usb: gadget: Gadget directory cleanup - group UDC drivers
authorAndrzej Pietrasiewicz <andrzej.p@samsung.com>
Tue, 15 Jul 2014 11:09:45 +0000 (13:09 +0200)
committerFelipe Balbi <balbi@ti.com>
Wed, 16 Jul 2014 17:15:28 +0000 (12:15 -0500)
The drivers/usb/gadget directory contains many files.
Files which are related can be distributed into separate directories.
This patch moves the UDC drivers into a separate directory.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
97 files changed:
drivers/usb/gadget/Kconfig
drivers/usb/gadget/Makefile
drivers/usb/gadget/amd5536udc.c [deleted file]
drivers/usb/gadget/amd5536udc.h [deleted file]
drivers/usb/gadget/at91_udc.c [deleted file]
drivers/usb/gadget/at91_udc.h [deleted file]
drivers/usb/gadget/atmel_usba_udc.c [deleted file]
drivers/usb/gadget/atmel_usba_udc.h [deleted file]
drivers/usb/gadget/bcm63xx_udc.c [deleted file]
drivers/usb/gadget/dummy_hcd.c [deleted file]
drivers/usb/gadget/fotg210-udc.c [deleted file]
drivers/usb/gadget/fotg210.h [deleted file]
drivers/usb/gadget/fsl_mxc_udc.c [deleted file]
drivers/usb/gadget/fsl_qe_udc.c [deleted file]
drivers/usb/gadget/fsl_qe_udc.h [deleted file]
drivers/usb/gadget/fsl_udc_core.c [deleted file]
drivers/usb/gadget/fsl_usb2_udc.h [deleted file]
drivers/usb/gadget/fusb300_udc.c [deleted file]
drivers/usb/gadget/fusb300_udc.h [deleted file]
drivers/usb/gadget/gadget_chips.h [deleted file]
drivers/usb/gadget/goku_udc.c [deleted file]
drivers/usb/gadget/goku_udc.h [deleted file]
drivers/usb/gadget/gr_udc.c [deleted file]
drivers/usb/gadget/gr_udc.h [deleted file]
drivers/usb/gadget/legacy/Makefile
drivers/usb/gadget/lpc32xx_udc.c [deleted file]
drivers/usb/gadget/m66592-udc.c [deleted file]
drivers/usb/gadget/m66592-udc.h [deleted file]
drivers/usb/gadget/mv_u3d.h [deleted file]
drivers/usb/gadget/mv_u3d_core.c [deleted file]
drivers/usb/gadget/mv_udc.h [deleted file]
drivers/usb/gadget/mv_udc_core.c [deleted file]
drivers/usb/gadget/net2272.c [deleted file]
drivers/usb/gadget/net2272.h [deleted file]
drivers/usb/gadget/net2280.c [deleted file]
drivers/usb/gadget/net2280.h [deleted file]
drivers/usb/gadget/omap_udc.c [deleted file]
drivers/usb/gadget/omap_udc.h [deleted file]
drivers/usb/gadget/pch_udc.c [deleted file]
drivers/usb/gadget/pxa25x_udc.c [deleted file]
drivers/usb/gadget/pxa25x_udc.h [deleted file]
drivers/usb/gadget/pxa27x_udc.c [deleted file]
drivers/usb/gadget/pxa27x_udc.h [deleted file]
drivers/usb/gadget/r8a66597-udc.c [deleted file]
drivers/usb/gadget/r8a66597-udc.h [deleted file]
drivers/usb/gadget/s3c-hsudc.c [deleted file]
drivers/usb/gadget/s3c2410_udc.c [deleted file]
drivers/usb/gadget/s3c2410_udc.h [deleted file]
drivers/usb/gadget/udc-core.c [deleted file]
drivers/usb/gadget/udc/Kconfig [new file with mode: 0644]
drivers/usb/gadget/udc/Makefile [new file with mode: 0644]
drivers/usb/gadget/udc/amd5536udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/amd5536udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/at91_udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/at91_udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/atmel_usba_udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/atmel_usba_udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/bcm63xx_udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/dummy_hcd.c [new file with mode: 0644]
drivers/usb/gadget/udc/fotg210-udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/fotg210.h [new file with mode: 0644]
drivers/usb/gadget/udc/fsl_mxc_udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/fsl_qe_udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/fsl_qe_udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/fsl_udc_core.c [new file with mode: 0644]
drivers/usb/gadget/udc/fsl_usb2_udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/fusb300_udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/fusb300_udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/gadget_chips.h [new file with mode: 0644]
drivers/usb/gadget/udc/goku_udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/goku_udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/gr_udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/gr_udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/lpc32xx_udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/m66592-udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/m66592-udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/mv_u3d.h [new file with mode: 0644]
drivers/usb/gadget/udc/mv_u3d_core.c [new file with mode: 0644]
drivers/usb/gadget/udc/mv_udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/mv_udc_core.c [new file with mode: 0644]
drivers/usb/gadget/udc/net2272.c [new file with mode: 0644]
drivers/usb/gadget/udc/net2272.h [new file with mode: 0644]
drivers/usb/gadget/udc/net2280.c [new file with mode: 0644]
drivers/usb/gadget/udc/net2280.h [new file with mode: 0644]
drivers/usb/gadget/udc/omap_udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/omap_udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/pch_udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/pxa25x_udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/pxa25x_udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/pxa27x_udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/pxa27x_udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/r8a66597-udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/r8a66597-udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/s3c-hsudc.c [new file with mode: 0644]
drivers/usb/gadget/udc/s3c2410_udc.c [new file with mode: 0644]
drivers/usb/gadget/udc/s3c2410_udc.h [new file with mode: 0644]
drivers/usb/gadget/udc/udc-core.c [new file with mode: 0644]

index 2986a4369df4a25800d4600e3d204e3ab66b1b4a..5c822afb6d70fc1ae2b8308678b1c0a400d70d23 100644 (file)
@@ -127,376 +127,7 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
           a module parameter as well.
           If unsure, say 2.
 
-#
-# USB Peripheral Controller Support
-#
-# The order here is alphabetical, except that integrated controllers go
-# before discrete ones so they will be the initial/default value:
-#   - integrated/SOC controllers first
-#   - licensed IP used in both SOC and discrete versions
-#   - discrete ones (including all PCI-only controllers)
-#   - debug/dummy gadget+hcd is last.
-#
-menu "USB Peripheral Controller"
-
-#
-# Integrated controllers
-#
-
-config USB_AT91
-       tristate "Atmel AT91 USB Device Port"
-       depends on ARCH_AT91
-       help
-          Many Atmel AT91 processors (such as the AT91RM2000) have a
-          full speed USB Device Port with support for five configurable
-          endpoints (plus endpoint zero).
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "at91_udc" and force all
-          gadget drivers to also be dynamically linked.
-
-config USB_LPC32XX
-       tristate "LPC32XX USB Peripheral Controller"
-       depends on ARCH_LPC32XX && I2C
-       select USB_ISP1301
-       help
-          This option selects the USB device controller in the LPC32xx SoC.
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "lpc32xx_udc" and force all
-          gadget drivers to also be dynamically linked.
-
-config USB_ATMEL_USBA
-       tristate "Atmel USBA"
-       depends on AVR32 || ARCH_AT91
-       help
-         USBA is the integrated high-speed USB Device controller on
-         the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
-
-config USB_BCM63XX_UDC
-       tristate "Broadcom BCM63xx Peripheral Controller"
-       depends on BCM63XX
-       help
-          Many Broadcom BCM63xx chipsets (such as the BCM6328) have a
-          high speed USB Device Port with support for four fixed endpoints
-          (plus endpoint zero).
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "bcm63xx_udc".
-
-config USB_FSL_USB2
-       tristate "Freescale Highspeed USB DR Peripheral Controller"
-       depends on FSL_SOC || ARCH_MXC
-       select USB_FSL_MPH_DR_OF if OF
-       help
-          Some of Freescale PowerPC and i.MX processors have a High Speed
-          Dual-Role(DR) USB controller, which supports device mode.
-
-          The number of programmable endpoints is different through
-          SOC revisions.
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "fsl_usb2_udc" and force
-          all gadget drivers to also be dynamically linked.
-
-config USB_FUSB300
-       tristate "Faraday FUSB300 USB Peripheral Controller"
-       depends on !PHYS_ADDR_T_64BIT && HAS_DMA
-       help
-          Faraday usb device controller FUSB300 driver
-
-config USB_FOTG210_UDC
-       depends on HAS_DMA
-       tristate "Faraday FOTG210 USB Peripheral Controller"
-       help
-          Faraday USB2.0 OTG controller which can be configured as
-          high speed or full speed USB device. This driver supppors
-          Bulk Transfer so far.
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "fotg210_udc".
-
-config USB_GR_UDC
-       tristate "Aeroflex Gaisler GRUSBDC USB Peripheral Controller Driver"
-       depends on HAS_DMA
-       help
-          Select this to support Aeroflex Gaisler GRUSBDC cores from the GRLIB
-         VHDL IP core library.
-
-config USB_OMAP
-       tristate "OMAP USB Device Controller"
-       depends on ARCH_OMAP1
-       depends on ISP1301_OMAP || !(MACH_OMAP_H2 || MACH_OMAP_H3)
-       help
-          Many Texas Instruments OMAP processors have flexible full
-          speed USB device controllers, with support for up to 30
-          endpoints (plus endpoint zero).  This driver supports the
-          controller in the OMAP 1611, and should work with controllers
-          in other OMAP processors too, given minor tweaks.
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "omap_udc" and force all
-          gadget drivers to also be dynamically linked.
-
-config USB_PXA25X
-       tristate "PXA 25x or IXP 4xx"
-       depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
-       help
-          Intel's PXA 25x series XScale ARM-5TE processors include
-          an integrated full speed USB 1.1 device controller.  The
-          controller in the IXP 4xx series is register-compatible.
-
-          It has fifteen fixed-function endpoints, as well as endpoint
-          zero (for control transfers).
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "pxa25x_udc" and force all
-          gadget drivers to also be dynamically linked.
-
-# if there's only one gadget driver, using only two bulk endpoints,
-# don't waste memory for the other endpoints
-config USB_PXA25X_SMALL
-       depends on USB_PXA25X
-       bool
-       default n if USB_ETH_RNDIS
-       default y if USB_ZERO
-       default y if USB_ETH
-       default y if USB_G_SERIAL
-
-config USB_R8A66597
-       tristate "Renesas R8A66597 USB Peripheral Controller"
-       depends on HAS_DMA
-       help
-          R8A66597 is a discrete USB host and peripheral controller chip that
-          supports both full and high speed USB 2.0 data transfers.
-          It has nine configurable endpoints, and endpoint zero.
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "r8a66597_udc" and force all
-          gadget drivers to also be dynamically linked.
-
-config USB_RENESAS_USBHS_UDC
-       tristate 'Renesas USBHS controller'
-       depends on USB_RENESAS_USBHS
-       help
-          Renesas USBHS is a discrete USB host and peripheral controller chip
-          that supports both full and high speed USB 2.0 data transfers.
-          It has nine or more configurable endpoints, and endpoint zero.
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "renesas_usbhs" and force all
-          gadget drivers to also be dynamically linked.
-
-config USB_PXA27X
-       tristate "PXA 27x"
-       help
-          Intel's PXA 27x series XScale ARM v5TE processors include
-          an integrated full speed USB 1.1 device controller.
-
-          It has up to 23 endpoints, as well as endpoint zero (for
-          control transfers).
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "pxa27x_udc" and force all
-          gadget drivers to also be dynamically linked.
-
-config USB_S3C2410
-       tristate "S3C2410 USB Device Controller"
-       depends on ARCH_S3C24XX
-       help
-         Samsung's S3C2410 is an ARM-4 processor with an integrated
-         full speed USB 1.1 device controller.  It has 4 configurable
-         endpoints, as well as endpoint zero (for control transfers).
-
-         This driver has been tested on the S3C2410, S3C2412, and
-         S3C2440 processors.
-
-config USB_S3C2410_DEBUG
-       boolean "S3C2410 udc debug messages"
-       depends on USB_S3C2410
-
-config USB_S3C_HSUDC
-       tristate "S3C2416, S3C2443 and S3C2450 USB Device Controller"
-       depends on ARCH_S3C24XX
-       help
-         Samsung's S3C2416, S3C2443 and S3C2450 is an ARM9 based SoC
-         integrated with dual speed USB 2.0 device controller. It has
-         8 endpoints, as well as endpoint zero.
-
-         This driver has been tested on S3C2416 and S3C2450 processors.
-
-config USB_MV_UDC
-       tristate "Marvell USB2.0 Device Controller"
-       depends on HAS_DMA
-       help
-         Marvell Socs (including PXA and MMP series) include a high speed
-         USB2.0 OTG controller, which can be configured as high speed or
-         full speed USB peripheral.
-
-config USB_MV_U3D
-       depends on HAS_DMA
-       tristate "MARVELL PXA2128 USB 3.0 controller"
-       help
-         MARVELL PXA2128 Processor series include a super speed USB3.0 device
-         controller, which support super speed USB peripheral.
-
-#
-# Controllers available in both integrated and discrete versions
-#
-
-config USB_M66592
-       tristate "Renesas M66592 USB Peripheral Controller"
-       help
-          M66592 is a discrete USB peripheral controller chip that
-          supports both full and high speed USB 2.0 data transfers.
-          It has seven configurable endpoints, and endpoint zero.
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "m66592_udc" and force all
-          gadget drivers to also be dynamically linked.
-
-#
-# Controllers available only in discrete form (and all PCI controllers)
-#
-
-config USB_AMD5536UDC
-       tristate "AMD5536 UDC"
-       depends on PCI
-       help
-          The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
-          It is a USB Highspeed DMA capable USB device controller. Beside ep0
-          it provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
-          The UDC port supports OTG operation, and may be used as a host port
-          if it's not being used to implement peripheral or OTG roles.
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "amd5536udc" and force all
-          gadget drivers to also be dynamically linked.
-
-config USB_FSL_QE
-       tristate "Freescale QE/CPM USB Device Controller"
-       depends on FSL_SOC && (QUICC_ENGINE || CPM)
-       help
-          Some of Freescale PowerPC processors have a Full Speed
-          QE/CPM2 USB controller, which support device mode with 4
-          programmable endpoints. This driver supports the
-          controller in the MPC8360 and MPC8272, and should work with
-          controllers having QE or CPM2, given minor tweaks.
-
-          Set CONFIG_USB_GADGET to "m" to build this driver as a
-          dynamically linked module called "fsl_qe_udc".
-
-config USB_NET2272
-       tristate "PLX NET2272"
-       help
-         PLX NET2272 is a USB peripheral controller which supports
-         both full and high speed USB 2.0 data transfers.
-
-         It has three configurable endpoints, as well as endpoint zero
-         (for control transfer).
-         Say "y" to link the driver statically, or "m" to build a
-         dynamically linked module called "net2272" and force all
-         gadget drivers to also be dynamically linked.
-
-config USB_NET2272_DMA
-       boolean "Support external DMA controller"
-       depends on USB_NET2272 && HAS_DMA
-       help
-         The NET2272 part can optionally support an external DMA
-         controller, but your board has to have support in the
-         driver itself.
-
-         If unsure, say "N" here.  The driver works fine in PIO mode.
-
-config USB_NET2280
-       tristate "NetChip 228x / PLX USB338x"
-       depends on PCI
-       help
-          NetChip 2280 / 2282 is a PCI based USB peripheral controller which
-          supports both full and high speed USB 2.0 data transfers.
-
-          It has six configurable endpoints, as well as endpoint zero
-          (for control transfers) and several endpoints with dedicated
-          functions.
-
-          PLX 3380 / 3382 is a PCIe based USB peripheral controller which
-          supports full, high speed USB 2.0 and super speed USB 3.0
-          data transfers.
-
-          It has eight configurable endpoints, as well as endpoint zero
-          (for control transfers) and several endpoints with dedicated
-          functions.
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "net2280" and force all
-          gadget drivers to also be dynamically linked.
-
-config USB_GOKU
-       tristate "Toshiba TC86C001 'Goku-S'"
-       depends on PCI
-       help
-          The Toshiba TC86C001 is a PCI device which includes controllers
-          for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI).
-
-          The device controller has three configurable (bulk or interrupt)
-          endpoints, plus endpoint zero (for control transfers).
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "goku_udc" and to force all
-          gadget drivers to also be dynamically linked.
-
-config USB_EG20T
-       tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
-       depends on PCI
-       help
-         This is a USB device driver for EG20T PCH.
-         EG20T PCH is the platform controller hub that is used in Intel's
-         general embedded platform. EG20T PCH has USB device interface.
-         Using this interface, it is able to access system devices connected
-         to USB device.
-         This driver enables USB device function.
-         USB device is a USB peripheral controller which
-         supports both full and high speed USB 2.0 data transfers.
-         This driver supports both control transfer and bulk transfer modes.
-         This driver dose not support interrupt transfer or isochronous
-         transfer modes.
-
-         This driver also can be used for LAPIS Semiconductor's ML7213 which is
-         for IVI(In-Vehicle Infotainment) use.
-         ML7831 is for general purpose use.
-         ML7213/ML7831 is companion chip for Intel Atom E6xx series.
-         ML7213/ML7831 is completely compatible for Intel EG20T PCH.
-
-#
-# LAST -- dummy/emulated controller
-#
-
-config USB_DUMMY_HCD
-       tristate "Dummy HCD (DEVELOPMENT)"
-       depends on USB=y || (USB=m && USB_GADGET=m)
-       help
-         This host controller driver emulates USB, looping all data transfer
-         requests back to a USB "gadget driver" in the same host.  The host
-         side is the master; the gadget side is the slave.  Gadget drivers
-         can be high, full, or low speed; and they have access to endpoints
-         like those from NET2280, PXA2xx, or SA1100 hardware.
-
-         This may help in some stages of creating a driver to embed in a
-         Linux device, since it lets you debug several parts of the gadget
-         driver without its hardware or drivers being involved.
-
-         Since such a gadget side driver needs to interoperate with a host
-         side Linux-USB device driver, this may help to debug both sides
-         of a USB protocol stack.
-
-         Say "y" to link the driver statically, or "m" to build a
-         dynamically linked module called "dummy_hcd" and force all
-         gadget drivers to also be dynamically linked.
-
-# NOTE:  Please keep dummy_hcd LAST so that "real hardware" appears
-# first and will be selected by default.
-
-endmenu
+source "drivers/usb/gadget/udc/Kconfig"
 
 #
 # USB Gadget Drivers
index 61d2503ef561f232984d94d86f8b073e7149d869..c144102ea793541c7e8dad1d42072bb62e71ed4f 100644 (file)
@@ -3,38 +3,11 @@
 #
 subdir-ccflags-$(CONFIG_USB_GADGET_DEBUG)      := -DDEBUG
 subdir-ccflags-$(CONFIG_USB_GADGET_VERBOSE)    += -DVERBOSE_DEBUG
+ccflags-y                              += -I$(PWD)/drivers/usb/gadget/udc
 
-obj-$(CONFIG_USB_GADGET)       += udc-core.o
 obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
 libcomposite-y                 := usbstring.o config.o epautoconf.o
 libcomposite-y                 += composite.o functions.o configfs.o u_f.o
-obj-$(CONFIG_USB_DUMMY_HCD)    += dummy_hcd.o
-obj-$(CONFIG_USB_NET2272)      += net2272.o
-obj-$(CONFIG_USB_NET2280)      += net2280.o
-obj-$(CONFIG_USB_AMD5536UDC)   += amd5536udc.o
-obj-$(CONFIG_USB_PXA25X)       += pxa25x_udc.o
-obj-$(CONFIG_USB_PXA27X)       += pxa27x_udc.o
-obj-$(CONFIG_USB_GOKU)         += goku_udc.o
-obj-$(CONFIG_USB_OMAP)         += omap_udc.o
-obj-$(CONFIG_USB_S3C2410)      += s3c2410_udc.o
-obj-$(CONFIG_USB_AT91)         += at91_udc.o
-obj-$(CONFIG_USB_ATMEL_USBA)   += atmel_usba_udc.o
-obj-$(CONFIG_USB_BCM63XX_UDC)  += bcm63xx_udc.o
-obj-$(CONFIG_USB_FSL_USB2)     += fsl_usb2_udc.o
-fsl_usb2_udc-y                 := fsl_udc_core.o
-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_S3C_HSUDC)    += s3c-hsudc.o
-obj-$(CONFIG_USB_LPC32XX)      += lpc32xx_udc.o
-obj-$(CONFIG_USB_EG20T)                += pch_udc.o
-obj-$(CONFIG_USB_MV_UDC)       += mv_udc.o
-mv_udc-y                       := mv_udc_core.o
-obj-$(CONFIG_USB_FUSB300)      += fusb300_udc.o
-obj-$(CONFIG_USB_FOTG210_UDC)  += fotg210-udc.o
-obj-$(CONFIG_USB_MV_U3D)       += mv_u3d_core.o
-obj-$(CONFIG_USB_GR_UDC)       += gr_udc.o
 
 # USB Functions
 usb_f_acm-y                    := f_acm.o
@@ -64,4 +37,4 @@ obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
 usb_f_fs-y                     := f_fs.o
 obj-$(CONFIG_USB_F_FS)         += usb_f_fs.o
 
-obj-$(CONFIG_USB_GADGET)       += legacy/
+obj-$(CONFIG_USB_GADGET)       += udc/ legacy/
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
deleted file mode 100644 (file)
index 41b062e..0000000
+++ /dev/null
@@ -1,3366 +0,0 @@
-/*
- * amd5536.c -- AMD 5536 UDC high/full speed USB device controller
- *
- * Copyright (C) 2005-2007 AMD (http://www.amd.com)
- * Author: Thomas Dahlmann
- *
- * 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.
- */
-
-/*
- * The AMD5536 UDC is part of the x86 southbridge AMD Geode CS5536.
- * It is a USB Highspeed DMA capable USB device controller. Beside ep0 it
- * provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
- *
- * Make sure that UDC is assigned to port 4 by BIOS settings (port can also
- * be used as host port) and UOC bits PAD_EN and APU are set (should be done
- * by BIOS init).
- *
- * UDC DMA requires 32-bit aligned buffers so DMA with gadget ether does not
- * work without updating NET_IP_ALIGN. Or PIO mode (module param "use_dma=0")
- * can be used with gadget ether.
- */
-
-/* debug control */
-/* #define UDC_VERBOSE */
-
-/* Driver strings */
-#define UDC_MOD_DESCRIPTION            "AMD 5536 UDC - USB Device Controller"
-#define UDC_DRIVER_VERSION_STRING      "01.00.0206"
-
-/* system */
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/ioctl.h>
-#include <linux/fs.h>
-#include <linux/dmapool.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/prefetch.h>
-
-#include <asm/byteorder.h>
-#include <asm/unaligned.h>
-
-/* gadget stack */
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-/* udc specific */
-#include "amd5536udc.h"
-
-
-static void udc_tasklet_disconnect(unsigned long);
-static void empty_req_queue(struct udc_ep *);
-static int udc_probe(struct udc *dev);
-static void udc_basic_init(struct udc *dev);
-static void udc_setup_endpoints(struct udc *dev);
-static void udc_soft_reset(struct udc *dev);
-static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep);
-static void udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq);
-static int udc_free_dma_chain(struct udc *dev, struct udc_request *req);
-static int udc_create_dma_chain(struct udc_ep *ep, struct udc_request *req,
-                               unsigned long buf_len, gfp_t gfp_flags);
-static int udc_remote_wakeup(struct udc *dev);
-static int udc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id);
-static void udc_pci_remove(struct pci_dev *pdev);
-
-/* description */
-static const char mod_desc[] = UDC_MOD_DESCRIPTION;
-static const char name[] = "amd5536udc";
-
-/* structure to hold endpoint function pointers */
-static const struct usb_ep_ops udc_ep_ops;
-
-/* received setup data */
-static union udc_setup_data setup_data;
-
-/* pointer to device object */
-static struct udc *udc;
-
-/* irq spin lock for soft reset */
-static DEFINE_SPINLOCK(udc_irq_spinlock);
-/* stall spin lock */
-static DEFINE_SPINLOCK(udc_stall_spinlock);
-
-/*
-* slave mode: pending bytes in rx fifo after nyet,
-* used if EPIN irq came but no req was available
-*/
-static unsigned int udc_rxfifo_pending;
-
-/* count soft resets after suspend to avoid loop */
-static int soft_reset_occured;
-static int soft_reset_after_usbreset_occured;
-
-/* timer */
-static struct timer_list udc_timer;
-static int stop_timer;
-
-/* set_rde -- Is used to control enabling of RX DMA. Problem is
- * that UDC has only one bit (RDE) to enable/disable RX DMA for
- * all OUT endpoints. So we have to handle race conditions like
- * when OUT data reaches the fifo but no request was queued yet.
- * This cannot be solved by letting the RX DMA disabled until a
- * request gets queued because there may be other OUT packets
- * in the FIFO (important for not blocking control traffic).
- * The value of set_rde controls the correspondig timer.
- *
- * set_rde -1 == not used, means it is alloed to be set to 0 or 1
- * set_rde  0 == do not touch RDE, do no start the RDE timer
- * set_rde  1 == timer function will look whether FIFO has data
- * set_rde  2 == set by timer function to enable RX DMA on next call
- */
-static int set_rde = -1;
-
-static DECLARE_COMPLETION(on_exit);
-static struct timer_list udc_pollstall_timer;
-static int stop_pollstall_timer;
-static DECLARE_COMPLETION(on_pollstall_exit);
-
-/* tasklet for usb disconnect */
-static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect,
-               (unsigned long) &udc);
-
-
-/* endpoint names used for print */
-static const char ep0_string[] = "ep0in";
-static const char *const ep_string[] = {
-       ep0_string,
-       "ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk",
-       "ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk",
-       "ep11in-bulk", "ep12in-bulk", "ep13in-bulk", "ep14in-bulk",
-       "ep15in-bulk", "ep0out", "ep1out-bulk", "ep2out-bulk", "ep3out-bulk",
-       "ep4out-bulk", "ep5out-bulk", "ep6out-bulk", "ep7out-bulk",
-       "ep8out-bulk", "ep9out-bulk", "ep10out-bulk", "ep11out-bulk",
-       "ep12out-bulk", "ep13out-bulk", "ep14out-bulk", "ep15out-bulk"
-};
-
-/* DMA usage flag */
-static bool use_dma = 1;
-/* packet per buffer dma */
-static bool use_dma_ppb = 1;
-/* with per descr. update */
-static bool use_dma_ppb_du;
-/* buffer fill mode */
-static int use_dma_bufferfill_mode;
-/* full speed only mode */
-static bool use_fullspeed;
-/* tx buffer size for high speed */
-static unsigned long hs_tx_buf = UDC_EPIN_BUFF_SIZE;
-
-/* module parameters */
-module_param(use_dma, bool, S_IRUGO);
-MODULE_PARM_DESC(use_dma, "true for DMA");
-module_param(use_dma_ppb, bool, S_IRUGO);
-MODULE_PARM_DESC(use_dma_ppb, "true for DMA in packet per buffer mode");
-module_param(use_dma_ppb_du, bool, S_IRUGO);
-MODULE_PARM_DESC(use_dma_ppb_du,
-       "true for DMA in packet per buffer mode with descriptor update");
-module_param(use_fullspeed, bool, S_IRUGO);
-MODULE_PARM_DESC(use_fullspeed, "true for fullspeed only");
-
-/*---------------------------------------------------------------------------*/
-/* Prints UDC device registers and endpoint irq registers */
-static void print_regs(struct udc *dev)
-{
-       DBG(dev, "------- Device registers -------\n");
-       DBG(dev, "dev config     = %08x\n", readl(&dev->regs->cfg));
-       DBG(dev, "dev control    = %08x\n", readl(&dev->regs->ctl));
-       DBG(dev, "dev status     = %08x\n", readl(&dev->regs->sts));
-       DBG(dev, "\n");
-       DBG(dev, "dev int's      = %08x\n", readl(&dev->regs->irqsts));
-       DBG(dev, "dev intmask    = %08x\n", readl(&dev->regs->irqmsk));
-       DBG(dev, "\n");
-       DBG(dev, "dev ep int's   = %08x\n", readl(&dev->regs->ep_irqsts));
-       DBG(dev, "dev ep intmask = %08x\n", readl(&dev->regs->ep_irqmsk));
-       DBG(dev, "\n");
-       DBG(dev, "USE DMA        = %d\n", use_dma);
-       if (use_dma && use_dma_ppb && !use_dma_ppb_du) {
-               DBG(dev, "DMA mode       = PPBNDU (packet per buffer "
-                       "WITHOUT desc. update)\n");
-               dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBNDU");
-       } else if (use_dma && use_dma_ppb && use_dma_ppb_du) {
-               DBG(dev, "DMA mode       = PPBDU (packet per buffer "
-                       "WITH desc. update)\n");
-               dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBDU");
-       }
-       if (use_dma && use_dma_bufferfill_mode) {
-               DBG(dev, "DMA mode       = BF (buffer fill mode)\n");
-               dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "BF");
-       }
-       if (!use_dma)
-               dev_info(&dev->pdev->dev, "FIFO mode\n");
-       DBG(dev, "-------------------------------------------------------\n");
-}
-
-/* Masks unused interrupts */
-static int udc_mask_unused_interrupts(struct udc *dev)
-{
-       u32 tmp;
-
-       /* mask all dev interrupts */
-       tmp =   AMD_BIT(UDC_DEVINT_SVC) |
-               AMD_BIT(UDC_DEVINT_ENUM) |
-               AMD_BIT(UDC_DEVINT_US) |
-               AMD_BIT(UDC_DEVINT_UR) |
-               AMD_BIT(UDC_DEVINT_ES) |
-               AMD_BIT(UDC_DEVINT_SI) |
-               AMD_BIT(UDC_DEVINT_SOF)|
-               AMD_BIT(UDC_DEVINT_SC);
-       writel(tmp, &dev->regs->irqmsk);
-
-       /* mask all ep interrupts */
-       writel(UDC_EPINT_MSK_DISABLE_ALL, &dev->regs->ep_irqmsk);
-
-       return 0;
-}
-
-/* Enables endpoint 0 interrupts */
-static int udc_enable_ep0_interrupts(struct udc *dev)
-{
-       u32 tmp;
-
-       DBG(dev, "udc_enable_ep0_interrupts()\n");
-
-       /* read irq mask */
-       tmp = readl(&dev->regs->ep_irqmsk);
-       /* enable ep0 irq's */
-       tmp &= AMD_UNMASK_BIT(UDC_EPINT_IN_EP0)
-               & AMD_UNMASK_BIT(UDC_EPINT_OUT_EP0);
-       writel(tmp, &dev->regs->ep_irqmsk);
-
-       return 0;
-}
-
-/* Enables device interrupts for SET_INTF and SET_CONFIG */
-static int udc_enable_dev_setup_interrupts(struct udc *dev)
-{
-       u32 tmp;
-
-       DBG(dev, "enable device interrupts for setup data\n");
-
-       /* read irq mask */
-       tmp = readl(&dev->regs->irqmsk);
-
-       /* enable SET_INTERFACE, SET_CONFIG and other needed irq's */
-       tmp &= AMD_UNMASK_BIT(UDC_DEVINT_SI)
-               & AMD_UNMASK_BIT(UDC_DEVINT_SC)
-               & AMD_UNMASK_BIT(UDC_DEVINT_UR)
-               & AMD_UNMASK_BIT(UDC_DEVINT_SVC)
-               & AMD_UNMASK_BIT(UDC_DEVINT_ENUM);
-       writel(tmp, &dev->regs->irqmsk);
-
-       return 0;
-}
-
-/* Calculates fifo start of endpoint based on preceding endpoints */
-static int udc_set_txfifo_addr(struct udc_ep *ep)
-{
-       struct udc      *dev;
-       u32 tmp;
-       int i;
-
-       if (!ep || !(ep->in))
-               return -EINVAL;
-
-       dev = ep->dev;
-       ep->txfifo = dev->txfifo;
-
-       /* traverse ep's */
-       for (i = 0; i < ep->num; i++) {
-               if (dev->ep[i].regs) {
-                       /* read fifo size */
-                       tmp = readl(&dev->ep[i].regs->bufin_framenum);
-                       tmp = AMD_GETBITS(tmp, UDC_EPIN_BUFF_SIZE);
-                       ep->txfifo += tmp;
-               }
-       }
-       return 0;
-}
-
-/* CNAK pending field: bit0 = ep0in, bit16 = ep0out */
-static u32 cnak_pending;
-
-static void UDC_QUEUE_CNAK(struct udc_ep *ep, unsigned num)
-{
-       if (readl(&ep->regs->ctl) & AMD_BIT(UDC_EPCTL_NAK)) {
-               DBG(ep->dev, "NAK could not be cleared for ep%d\n", num);
-               cnak_pending |= 1 << (num);
-               ep->naking = 1;
-       } else
-               cnak_pending = cnak_pending & (~(1 << (num)));
-}
-
-
-/* Enables endpoint, is called by gadget driver */
-static int
-udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc)
-{
-       struct udc_ep           *ep;
-       struct udc              *dev;
-       u32                     tmp;
-       unsigned long           iflags;
-       u8 udc_csr_epix;
-       unsigned                maxpacket;
-
-       if (!usbep
-                       || usbep->name == ep0_string
-                       || !desc
-                       || desc->bDescriptorType != USB_DT_ENDPOINT)
-               return -EINVAL;
-
-       ep = container_of(usbep, struct udc_ep, ep);
-       dev = ep->dev;
-
-       DBG(dev, "udc_ep_enable() ep %d\n", ep->num);
-
-       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       spin_lock_irqsave(&dev->lock, iflags);
-       ep->ep.desc = desc;
-
-       ep->halted = 0;
-
-       /* set traffic type */
-       tmp = readl(&dev->ep[ep->num].regs->ctl);
-       tmp = AMD_ADDBITS(tmp, desc->bmAttributes, UDC_EPCTL_ET);
-       writel(tmp, &dev->ep[ep->num].regs->ctl);
-
-       /* set max packet size */
-       maxpacket = usb_endpoint_maxp(desc);
-       tmp = readl(&dev->ep[ep->num].regs->bufout_maxpkt);
-       tmp = AMD_ADDBITS(tmp, maxpacket, UDC_EP_MAX_PKT_SIZE);
-       ep->ep.maxpacket = maxpacket;
-       writel(tmp, &dev->ep[ep->num].regs->bufout_maxpkt);
-
-       /* IN ep */
-       if (ep->in) {
-
-               /* ep ix in UDC CSR register space */
-               udc_csr_epix = ep->num;
-
-               /* set buffer size (tx fifo entries) */
-               tmp = readl(&dev->ep[ep->num].regs->bufin_framenum);
-               /* double buffering: fifo size = 2 x max packet size */
-               tmp = AMD_ADDBITS(
-                               tmp,
-                               maxpacket * UDC_EPIN_BUFF_SIZE_MULT
-                                         / UDC_DWORD_BYTES,
-                               UDC_EPIN_BUFF_SIZE);
-               writel(tmp, &dev->ep[ep->num].regs->bufin_framenum);
-
-               /* calc. tx fifo base addr */
-               udc_set_txfifo_addr(ep);
-
-               /* flush fifo */
-               tmp = readl(&ep->regs->ctl);
-               tmp |= AMD_BIT(UDC_EPCTL_F);
-               writel(tmp, &ep->regs->ctl);
-
-       /* OUT ep */
-       } else {
-               /* ep ix in UDC CSR register space */
-               udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS;
-
-               /* set max packet size UDC CSR  */
-               tmp = readl(&dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]);
-               tmp = AMD_ADDBITS(tmp, maxpacket,
-                                       UDC_CSR_NE_MAX_PKT);
-               writel(tmp, &dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]);
-
-               if (use_dma && !ep->in) {
-                       /* alloc and init BNA dummy request */
-                       ep->bna_dummy_req = udc_alloc_bna_dummy(ep);
-                       ep->bna_occurred = 0;
-               }
-
-               if (ep->num != UDC_EP0OUT_IX)
-                       dev->data_ep_enabled = 1;
-       }
-
-       /* set ep values */
-       tmp = readl(&dev->csr->ne[udc_csr_epix]);
-       /* max packet */
-       tmp = AMD_ADDBITS(tmp, maxpacket, UDC_CSR_NE_MAX_PKT);
-       /* ep number */
-       tmp = AMD_ADDBITS(tmp, desc->bEndpointAddress, UDC_CSR_NE_NUM);
-       /* ep direction */
-       tmp = AMD_ADDBITS(tmp, ep->in, UDC_CSR_NE_DIR);
-       /* ep type */
-       tmp = AMD_ADDBITS(tmp, desc->bmAttributes, UDC_CSR_NE_TYPE);
-       /* ep config */
-       tmp = AMD_ADDBITS(tmp, ep->dev->cur_config, UDC_CSR_NE_CFG);
-       /* ep interface */
-       tmp = AMD_ADDBITS(tmp, ep->dev->cur_intf, UDC_CSR_NE_INTF);
-       /* ep alt */
-       tmp = AMD_ADDBITS(tmp, ep->dev->cur_alt, UDC_CSR_NE_ALT);
-       /* write reg */
-       writel(tmp, &dev->csr->ne[udc_csr_epix]);
-
-       /* enable ep irq */
-       tmp = readl(&dev->regs->ep_irqmsk);
-       tmp &= AMD_UNMASK_BIT(ep->num);
-       writel(tmp, &dev->regs->ep_irqmsk);
-
-       /*
-        * clear NAK by writing CNAK
-        * avoid BNA for OUT DMA, don't clear NAK until DMA desc. written
-        */
-       if (!use_dma || ep->in) {
-               tmp = readl(&ep->regs->ctl);
-               tmp |= AMD_BIT(UDC_EPCTL_CNAK);
-               writel(tmp, &ep->regs->ctl);
-               ep->naking = 0;
-               UDC_QUEUE_CNAK(ep, ep->num);
-       }
-       tmp = desc->bEndpointAddress;
-       DBG(dev, "%s enabled\n", usbep->name);
-
-       spin_unlock_irqrestore(&dev->lock, iflags);
-       return 0;
-}
-
-/* Resets endpoint */
-static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep)
-{
-       u32             tmp;
-
-       VDBG(ep->dev, "ep-%d reset\n", ep->num);
-       ep->ep.desc = NULL;
-       ep->ep.ops = &udc_ep_ops;
-       INIT_LIST_HEAD(&ep->queue);
-
-       usb_ep_set_maxpacket_limit(&ep->ep,(u16) ~0);
-       /* set NAK */
-       tmp = readl(&ep->regs->ctl);
-       tmp |= AMD_BIT(UDC_EPCTL_SNAK);
-       writel(tmp, &ep->regs->ctl);
-       ep->naking = 1;
-
-       /* disable interrupt */
-       tmp = readl(&regs->ep_irqmsk);
-       tmp |= AMD_BIT(ep->num);
-       writel(tmp, &regs->ep_irqmsk);
-
-       if (ep->in) {
-               /* unset P and IN bit of potential former DMA */
-               tmp = readl(&ep->regs->ctl);
-               tmp &= AMD_UNMASK_BIT(UDC_EPCTL_P);
-               writel(tmp, &ep->regs->ctl);
-
-               tmp = readl(&ep->regs->sts);
-               tmp |= AMD_BIT(UDC_EPSTS_IN);
-               writel(tmp, &ep->regs->sts);
-
-               /* flush the fifo */
-               tmp = readl(&ep->regs->ctl);
-               tmp |= AMD_BIT(UDC_EPCTL_F);
-               writel(tmp, &ep->regs->ctl);
-
-       }
-       /* reset desc pointer */
-       writel(0, &ep->regs->desptr);
-}
-
-/* Disables endpoint, is called by gadget driver */
-static int udc_ep_disable(struct usb_ep *usbep)
-{
-       struct udc_ep   *ep = NULL;
-       unsigned long   iflags;
-
-       if (!usbep)
-               return -EINVAL;
-
-       ep = container_of(usbep, struct udc_ep, ep);
-       if (usbep->name == ep0_string || !ep->ep.desc)
-               return -EINVAL;
-
-       DBG(ep->dev, "Disable ep-%d\n", ep->num);
-
-       spin_lock_irqsave(&ep->dev->lock, iflags);
-       udc_free_request(&ep->ep, &ep->bna_dummy_req->req);
-       empty_req_queue(ep);
-       ep_init(ep->dev->regs, ep);
-       spin_unlock_irqrestore(&ep->dev->lock, iflags);
-
-       return 0;
-}
-
-/* Allocates request packet, called by gadget driver */
-static struct usb_request *
-udc_alloc_request(struct usb_ep *usbep, gfp_t gfp)
-{
-       struct udc_request      *req;
-       struct udc_data_dma     *dma_desc;
-       struct udc_ep   *ep;
-
-       if (!usbep)
-               return NULL;
-
-       ep = container_of(usbep, struct udc_ep, ep);
-
-       VDBG(ep->dev, "udc_alloc_req(): ep%d\n", ep->num);
-       req = kzalloc(sizeof(struct udc_request), gfp);
-       if (!req)
-               return NULL;
-
-       req->req.dma = DMA_DONT_USE;
-       INIT_LIST_HEAD(&req->queue);
-
-       if (ep->dma) {
-               /* ep0 in requests are allocated from data pool here */
-               dma_desc = pci_pool_alloc(ep->dev->data_requests, gfp,
-                                               &req->td_phys);
-               if (!dma_desc) {
-                       kfree(req);
-                       return NULL;
-               }
-
-               VDBG(ep->dev, "udc_alloc_req: req = %p dma_desc = %p, "
-                               "td_phys = %lx\n",
-                               req, dma_desc,
-                               (unsigned long)req->td_phys);
-               /* prevent from using desc. - set HOST BUSY */
-               dma_desc->status = AMD_ADDBITS(dma_desc->status,
-                                               UDC_DMA_STP_STS_BS_HOST_BUSY,
-                                               UDC_DMA_STP_STS_BS);
-               dma_desc->bufptr = cpu_to_le32(DMA_DONT_USE);
-               req->td_data = dma_desc;
-               req->td_data_last = NULL;
-               req->chain_len = 1;
-       }
-
-       return &req->req;
-}
-
-/* Frees request packet, called by gadget driver */
-static void
-udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq)
-{
-       struct udc_ep   *ep;
-       struct udc_request      *req;
-
-       if (!usbep || !usbreq)
-               return;
-
-       ep = container_of(usbep, struct udc_ep, ep);
-       req = container_of(usbreq, struct udc_request, req);
-       VDBG(ep->dev, "free_req req=%p\n", req);
-       BUG_ON(!list_empty(&req->queue));
-       if (req->td_data) {
-               VDBG(ep->dev, "req->td_data=%p\n", req->td_data);
-
-               /* free dma chain if created */
-               if (req->chain_len > 1)
-                       udc_free_dma_chain(ep->dev, req);
-
-               pci_pool_free(ep->dev->data_requests, req->td_data,
-                                                       req->td_phys);
-       }
-       kfree(req);
-}
-
-/* Init BNA dummy descriptor for HOST BUSY and pointing to itself */
-static void udc_init_bna_dummy(struct udc_request *req)
-{
-       if (req) {
-               /* set last bit */
-               req->td_data->status |= AMD_BIT(UDC_DMA_IN_STS_L);
-               /* set next pointer to itself */
-               req->td_data->next = req->td_phys;
-               /* set HOST BUSY */
-               req->td_data->status
-                       = AMD_ADDBITS(req->td_data->status,
-                                       UDC_DMA_STP_STS_BS_DMA_DONE,
-                                       UDC_DMA_STP_STS_BS);
-#ifdef UDC_VERBOSE
-               pr_debug("bna desc = %p, sts = %08x\n",
-                       req->td_data, req->td_data->status);
-#endif
-       }
-}
-
-/* Allocate BNA dummy descriptor */
-static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep)
-{
-       struct udc_request *req = NULL;
-       struct usb_request *_req = NULL;
-
-       /* alloc the dummy request */
-       _req = udc_alloc_request(&ep->ep, GFP_ATOMIC);
-       if (_req) {
-               req = container_of(_req, struct udc_request, req);
-               ep->bna_dummy_req = req;
-               udc_init_bna_dummy(req);
-       }
-       return req;
-}
-
-/* Write data to TX fifo for IN packets */
-static void
-udc_txfifo_write(struct udc_ep *ep, struct usb_request *req)
-{
-       u8                      *req_buf;
-       u32                     *buf;
-       int                     i, j;
-       unsigned                bytes = 0;
-       unsigned                remaining = 0;
-
-       if (!req || !ep)
-               return;
-
-       req_buf = req->buf + req->actual;
-       prefetch(req_buf);
-       remaining = req->length - req->actual;
-
-       buf = (u32 *) req_buf;
-
-       bytes = ep->ep.maxpacket;
-       if (bytes > remaining)
-               bytes = remaining;
-
-       /* dwords first */
-       for (i = 0; i < bytes / UDC_DWORD_BYTES; i++)
-               writel(*(buf + i), ep->txfifo);
-
-       /* remaining bytes must be written by byte access */
-       for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) {
-               writeb((u8)(*(buf + i) >> (j << UDC_BITS_PER_BYTE_SHIFT)),
-                                                       ep->txfifo);
-       }
-
-       /* dummy write confirm */
-       writel(0, &ep->regs->confirm);
-}
-
-/* Read dwords from RX fifo for OUT transfers */
-static int udc_rxfifo_read_dwords(struct udc *dev, u32 *buf, int dwords)
-{
-       int i;
-
-       VDBG(dev, "udc_read_dwords(): %d dwords\n", dwords);
-
-       for (i = 0; i < dwords; i++)
-               *(buf + i) = readl(dev->rxfifo);
-       return 0;
-}
-
-/* Read bytes from RX fifo for OUT transfers */
-static int udc_rxfifo_read_bytes(struct udc *dev, u8 *buf, int bytes)
-{
-       int i, j;
-       u32 tmp;
-
-       VDBG(dev, "udc_read_bytes(): %d bytes\n", bytes);
-
-       /* dwords first */
-       for (i = 0; i < bytes / UDC_DWORD_BYTES; i++)
-               *((u32 *)(buf + (i<<2))) = readl(dev->rxfifo);
-
-       /* remaining bytes must be read by byte access */
-       if (bytes % UDC_DWORD_BYTES) {
-               tmp = readl(dev->rxfifo);
-               for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) {
-                       *(buf + (i<<2) + j) = (u8)(tmp & UDC_BYTE_MASK);
-                       tmp = tmp >> UDC_BITS_PER_BYTE;
-               }
-       }
-
-       return 0;
-}
-
-/* Read data from RX fifo for OUT transfers */
-static int
-udc_rxfifo_read(struct udc_ep *ep, struct udc_request *req)
-{
-       u8 *buf;
-       unsigned buf_space;
-       unsigned bytes = 0;
-       unsigned finished = 0;
-
-       /* received number bytes */
-       bytes = readl(&ep->regs->sts);
-       bytes = AMD_GETBITS(bytes, UDC_EPSTS_RX_PKT_SIZE);
-
-       buf_space = req->req.length - req->req.actual;
-       buf = req->req.buf + req->req.actual;
-       if (bytes > buf_space) {
-               if ((buf_space % ep->ep.maxpacket) != 0) {
-                       DBG(ep->dev,
-                               "%s: rx %d bytes, rx-buf space = %d bytesn\n",
-                               ep->ep.name, bytes, buf_space);
-                       req->req.status = -EOVERFLOW;
-               }
-               bytes = buf_space;
-       }
-       req->req.actual += bytes;
-
-       /* last packet ? */
-       if (((bytes % ep->ep.maxpacket) != 0) || (!bytes)
-               || ((req->req.actual == req->req.length) && !req->req.zero))
-               finished = 1;
-
-       /* read rx fifo bytes */
-       VDBG(ep->dev, "ep %s: rxfifo read %d bytes\n", ep->ep.name, bytes);
-       udc_rxfifo_read_bytes(ep->dev, buf, bytes);
-
-       return finished;
-}
-
-/* create/re-init a DMA descriptor or a DMA descriptor chain */
-static int prep_dma(struct udc_ep *ep, struct udc_request *req, gfp_t gfp)
-{
-       int     retval = 0;
-       u32     tmp;
-
-       VDBG(ep->dev, "prep_dma\n");
-       VDBG(ep->dev, "prep_dma ep%d req->td_data=%p\n",
-                       ep->num, req->td_data);
-
-       /* set buffer pointer */
-       req->td_data->bufptr = req->req.dma;
-
-       /* set last bit */
-       req->td_data->status |= AMD_BIT(UDC_DMA_IN_STS_L);
-
-       /* build/re-init dma chain if maxpkt scatter mode, not for EP0 */
-       if (use_dma_ppb) {
-
-               retval = udc_create_dma_chain(ep, req, ep->ep.maxpacket, gfp);
-               if (retval != 0) {
-                       if (retval == -ENOMEM)
-                               DBG(ep->dev, "Out of DMA memory\n");
-                       return retval;
-               }
-               if (ep->in) {
-                       if (req->req.length == ep->ep.maxpacket) {
-                               /* write tx bytes */
-                               req->td_data->status =
-                                       AMD_ADDBITS(req->td_data->status,
-                                               ep->ep.maxpacket,
-                                               UDC_DMA_IN_STS_TXBYTES);
-
-                       }
-               }
-
-       }
-
-       if (ep->in) {
-               VDBG(ep->dev, "IN: use_dma_ppb=%d req->req.len=%d "
-                               "maxpacket=%d ep%d\n",
-                               use_dma_ppb, req->req.length,
-                               ep->ep.maxpacket, ep->num);
-               /*
-                * if bytes < max packet then tx bytes must
-                * be written in packet per buffer mode
-                */
-               if (!use_dma_ppb || req->req.length < ep->ep.maxpacket
-                               || ep->num == UDC_EP0OUT_IX
-                               || ep->num == UDC_EP0IN_IX) {
-                       /* write tx bytes */
-                       req->td_data->status =
-                               AMD_ADDBITS(req->td_data->status,
-                                               req->req.length,
-                                               UDC_DMA_IN_STS_TXBYTES);
-                       /* reset frame num */
-                       req->td_data->status =
-                               AMD_ADDBITS(req->td_data->status,
-                                               0,
-                                               UDC_DMA_IN_STS_FRAMENUM);
-               }
-               /* set HOST BUSY */
-               req->td_data->status =
-                       AMD_ADDBITS(req->td_data->status,
-                               UDC_DMA_STP_STS_BS_HOST_BUSY,
-                               UDC_DMA_STP_STS_BS);
-       } else {
-               VDBG(ep->dev, "OUT set host ready\n");
-               /* set HOST READY */
-               req->td_data->status =
-                       AMD_ADDBITS(req->td_data->status,
-                               UDC_DMA_STP_STS_BS_HOST_READY,
-                               UDC_DMA_STP_STS_BS);
-
-
-                       /* clear NAK by writing CNAK */
-                       if (ep->naking) {
-                               tmp = readl(&ep->regs->ctl);
-                               tmp |= AMD_BIT(UDC_EPCTL_CNAK);
-                               writel(tmp, &ep->regs->ctl);
-                               ep->naking = 0;
-                               UDC_QUEUE_CNAK(ep, ep->num);
-                       }
-
-       }
-
-       return retval;
-}
-
-/* Completes request packet ... caller MUST hold lock */
-static void
-complete_req(struct udc_ep *ep, struct udc_request *req, int sts)
-__releases(ep->dev->lock)
-__acquires(ep->dev->lock)
-{
-       struct udc              *dev;
-       unsigned                halted;
-
-       VDBG(ep->dev, "complete_req(): ep%d\n", ep->num);
-
-       dev = ep->dev;
-       /* unmap DMA */
-       if (ep->dma)
-               usb_gadget_unmap_request(&dev->gadget, &req->req, ep->in);
-
-       halted = ep->halted;
-       ep->halted = 1;
-
-       /* set new status if pending */
-       if (req->req.status == -EINPROGRESS)
-               req->req.status = sts;
-
-       /* remove from ep queue */
-       list_del_init(&req->queue);
-
-       VDBG(ep->dev, "req %p => complete %d bytes at %s with sts %d\n",
-               &req->req, req->req.length, ep->ep.name, sts);
-
-       spin_unlock(&dev->lock);
-       req->req.complete(&ep->ep, &req->req);
-       spin_lock(&dev->lock);
-       ep->halted = halted;
-}
-
-/* frees pci pool descriptors of a DMA chain */
-static int udc_free_dma_chain(struct udc *dev, struct udc_request *req)
-{
-
-       int ret_val = 0;
-       struct udc_data_dma     *td;
-       struct udc_data_dma     *td_last = NULL;
-       unsigned int i;
-
-       DBG(dev, "free chain req = %p\n", req);
-
-       /* do not free first desc., will be done by free for request */
-       td_last = req->td_data;
-       td = phys_to_virt(td_last->next);
-
-       for (i = 1; i < req->chain_len; i++) {
-
-               pci_pool_free(dev->data_requests, td,
-                               (dma_addr_t) td_last->next);
-               td_last = td;
-               td = phys_to_virt(td_last->next);
-       }
-
-       return ret_val;
-}
-
-/* Iterates to the end of a DMA chain and returns last descriptor */
-static struct udc_data_dma *udc_get_last_dma_desc(struct udc_request *req)
-{
-       struct udc_data_dma     *td;
-
-       td = req->td_data;
-       while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L)))
-               td = phys_to_virt(td->next);
-
-       return td;
-
-}
-
-/* Iterates to the end of a DMA chain and counts bytes received */
-static u32 udc_get_ppbdu_rxbytes(struct udc_request *req)
-{
-       struct udc_data_dma     *td;
-       u32 count;
-
-       td = req->td_data;
-       /* received number bytes */
-       count = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_RXBYTES);
-
-       while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) {
-               td = phys_to_virt(td->next);
-               /* received number bytes */
-               if (td) {
-                       count += AMD_GETBITS(td->status,
-                               UDC_DMA_OUT_STS_RXBYTES);
-               }
-       }
-
-       return count;
-
-}
-
-/* Creates or re-inits a DMA chain */
-static int udc_create_dma_chain(
-       struct udc_ep *ep,
-       struct udc_request *req,
-       unsigned long buf_len, gfp_t gfp_flags
-)
-{
-       unsigned long bytes = req->req.length;
-       unsigned int i;
-       dma_addr_t dma_addr;
-       struct udc_data_dma     *td = NULL;
-       struct udc_data_dma     *last = NULL;
-       unsigned long txbytes;
-       unsigned create_new_chain = 0;
-       unsigned len;
-
-       VDBG(ep->dev, "udc_create_dma_chain: bytes=%ld buf_len=%ld\n",
-                       bytes, buf_len);
-       dma_addr = DMA_DONT_USE;
-
-       /* unset L bit in first desc for OUT */
-       if (!ep->in)
-               req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
-
-       /* alloc only new desc's if not already available */
-       len = req->req.length / ep->ep.maxpacket;
-       if (req->req.length % ep->ep.maxpacket)
-               len++;
-
-       if (len > req->chain_len) {
-               /* shorter chain already allocated before */
-               if (req->chain_len > 1)
-                       udc_free_dma_chain(ep->dev, req);
-               req->chain_len = len;
-               create_new_chain = 1;
-       }
-
-       td = req->td_data;
-       /* gen. required number of descriptors and buffers */
-       for (i = buf_len; i < bytes; i += buf_len) {
-               /* create or determine next desc. */
-               if (create_new_chain) {
-
-                       td = pci_pool_alloc(ep->dev->data_requests,
-                                       gfp_flags, &dma_addr);
-                       if (!td)
-                               return -ENOMEM;
-
-                       td->status = 0;
-               } else if (i == buf_len) {
-                       /* first td */
-                       td = (struct udc_data_dma *) phys_to_virt(
-                                               req->td_data->next);
-                       td->status = 0;
-               } else {
-                       td = (struct udc_data_dma *) phys_to_virt(last->next);
-                       td->status = 0;
-               }
-
-
-               if (td)
-                       td->bufptr = req->req.dma + i; /* assign buffer */
-               else
-                       break;
-
-               /* short packet ? */
-               if ((bytes - i) >= buf_len) {
-                       txbytes = buf_len;
-               } else {
-                       /* short packet */
-                       txbytes = bytes - i;
-               }
-
-               /* link td and assign tx bytes */
-               if (i == buf_len) {
-                       if (create_new_chain)
-                               req->td_data->next = dma_addr;
-                       /*
-                       else
-                               req->td_data->next = virt_to_phys(td);
-                       */
-                       /* write tx bytes */
-                       if (ep->in) {
-                               /* first desc */
-                               req->td_data->status =
-                                       AMD_ADDBITS(req->td_data->status,
-                                                       ep->ep.maxpacket,
-                                                       UDC_DMA_IN_STS_TXBYTES);
-                               /* second desc */
-                               td->status = AMD_ADDBITS(td->status,
-                                                       txbytes,
-                                                       UDC_DMA_IN_STS_TXBYTES);
-                       }
-               } else {
-                       if (create_new_chain)
-                               last->next = dma_addr;
-                       /*
-                       else
-                               last->next = virt_to_phys(td);
-                       */
-                       if (ep->in) {
-                               /* write tx bytes */
-                               td->status = AMD_ADDBITS(td->status,
-                                                       txbytes,
-                                                       UDC_DMA_IN_STS_TXBYTES);
-                       }
-               }
-               last = td;
-       }
-       /* set last bit */
-       if (td) {
-               td->status |= AMD_BIT(UDC_DMA_IN_STS_L);
-               /* last desc. points to itself */
-               req->td_data_last = td;
-       }
-
-       return 0;
-}
-
-/* Enabling RX DMA */
-static void udc_set_rde(struct udc *dev)
-{
-       u32 tmp;
-
-       VDBG(dev, "udc_set_rde()\n");
-       /* stop RDE timer */
-       if (timer_pending(&udc_timer)) {
-               set_rde = 0;
-               mod_timer(&udc_timer, jiffies - 1);
-       }
-       /* set RDE */
-       tmp = readl(&dev->regs->ctl);
-       tmp |= AMD_BIT(UDC_DEVCTL_RDE);
-       writel(tmp, &dev->regs->ctl);
-}
-
-/* Queues a request packet, called by gadget driver */
-static int
-udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
-{
-       int                     retval = 0;
-       u8                      open_rxfifo = 0;
-       unsigned long           iflags;
-       struct udc_ep           *ep;
-       struct udc_request      *req;
-       struct udc              *dev;
-       u32                     tmp;
-
-       /* check the inputs */
-       req = container_of(usbreq, struct udc_request, req);
-
-       if (!usbep || !usbreq || !usbreq->complete || !usbreq->buf
-                       || !list_empty(&req->queue))
-               return -EINVAL;
-
-       ep = container_of(usbep, struct udc_ep, ep);
-       if (!ep->ep.desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
-               return -EINVAL;
-
-       VDBG(ep->dev, "udc_queue(): ep%d-in=%d\n", ep->num, ep->in);
-       dev = ep->dev;
-
-       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       /* map dma (usually done before) */
-       if (ep->dma) {
-               VDBG(dev, "DMA map req %p\n", req);
-               retval = usb_gadget_map_request(&udc->gadget, usbreq, ep->in);
-               if (retval)
-                       return retval;
-       }
-
-       VDBG(dev, "%s queue req %p, len %d req->td_data=%p buf %p\n",
-                       usbep->name, usbreq, usbreq->length,
-                       req->td_data, usbreq->buf);
-
-       spin_lock_irqsave(&dev->lock, iflags);
-       usbreq->actual = 0;
-       usbreq->status = -EINPROGRESS;
-       req->dma_done = 0;
-
-       /* on empty queue just do first transfer */
-       if (list_empty(&ep->queue)) {
-               /* zlp */
-               if (usbreq->length == 0) {
-                       /* IN zlp's are handled by hardware */
-                       complete_req(ep, req, 0);
-                       VDBG(dev, "%s: zlp\n", ep->ep.name);
-                       /*
-                        * if set_config or set_intf is waiting for ack by zlp
-                        * then set CSR_DONE
-                        */
-                       if (dev->set_cfg_not_acked) {
-                               tmp = readl(&dev->regs->ctl);
-                               tmp |= AMD_BIT(UDC_DEVCTL_CSR_DONE);
-                               writel(tmp, &dev->regs->ctl);
-                               dev->set_cfg_not_acked = 0;
-                       }
-                       /* setup command is ACK'ed now by zlp */
-                       if (dev->waiting_zlp_ack_ep0in) {
-                               /* clear NAK by writing CNAK in EP0_IN */
-                               tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
-                               tmp |= AMD_BIT(UDC_EPCTL_CNAK);
-                               writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
-                               dev->ep[UDC_EP0IN_IX].naking = 0;
-                               UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX],
-                                                       UDC_EP0IN_IX);
-                               dev->waiting_zlp_ack_ep0in = 0;
-                       }
-                       goto finished;
-               }
-               if (ep->dma) {
-                       retval = prep_dma(ep, req, GFP_ATOMIC);
-                       if (retval != 0)
-                               goto finished;
-                       /* write desc pointer to enable DMA */
-                       if (ep->in) {
-                               /* set HOST READY */
-                               req->td_data->status =
-                                       AMD_ADDBITS(req->td_data->status,
-                                               UDC_DMA_IN_STS_BS_HOST_READY,
-                                               UDC_DMA_IN_STS_BS);
-                       }
-
-                       /* disabled rx dma while descriptor update */
-                       if (!ep->in) {
-                               /* stop RDE timer */
-                               if (timer_pending(&udc_timer)) {
-                                       set_rde = 0;
-                                       mod_timer(&udc_timer, jiffies - 1);
-                               }
-                               /* clear RDE */
-                               tmp = readl(&dev->regs->ctl);
-                               tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_RDE);
-                               writel(tmp, &dev->regs->ctl);
-                               open_rxfifo = 1;
-
-                               /*
-                                * if BNA occurred then let BNA dummy desc.
-                                * point to current desc.
-                                */
-                               if (ep->bna_occurred) {
-                                       VDBG(dev, "copy to BNA dummy desc.\n");
-                                       memcpy(ep->bna_dummy_req->td_data,
-                                               req->td_data,
-                                               sizeof(struct udc_data_dma));
-                               }
-                       }
-                       /* write desc pointer */
-                       writel(req->td_phys, &ep->regs->desptr);
-
-                       /* clear NAK by writing CNAK */
-                       if (ep->naking) {
-                               tmp = readl(&ep->regs->ctl);
-                               tmp |= AMD_BIT(UDC_EPCTL_CNAK);
-                               writel(tmp, &ep->regs->ctl);
-                               ep->naking = 0;
-                               UDC_QUEUE_CNAK(ep, ep->num);
-                       }
-
-                       if (ep->in) {
-                               /* enable ep irq */
-                               tmp = readl(&dev->regs->ep_irqmsk);
-                               tmp &= AMD_UNMASK_BIT(ep->num);
-                               writel(tmp, &dev->regs->ep_irqmsk);
-                       }
-               } else if (ep->in) {
-                               /* enable ep irq */
-                               tmp = readl(&dev->regs->ep_irqmsk);
-                               tmp &= AMD_UNMASK_BIT(ep->num);
-                               writel(tmp, &dev->regs->ep_irqmsk);
-                       }
-
-       } else if (ep->dma) {
-
-               /*
-                * prep_dma not used for OUT ep's, this is not possible
-                * for PPB modes, because of chain creation reasons
-                */
-               if (ep->in) {
-                       retval = prep_dma(ep, req, GFP_ATOMIC);
-                       if (retval != 0)
-                               goto finished;
-               }
-       }
-       VDBG(dev, "list_add\n");
-       /* add request to ep queue */
-       if (req) {
-
-               list_add_tail(&req->queue, &ep->queue);
-
-               /* open rxfifo if out data queued */
-               if (open_rxfifo) {
-                       /* enable DMA */
-                       req->dma_going = 1;
-                       udc_set_rde(dev);
-                       if (ep->num != UDC_EP0OUT_IX)
-                               dev->data_ep_queued = 1;
-               }
-               /* stop OUT naking */
-               if (!ep->in) {
-                       if (!use_dma && udc_rxfifo_pending) {
-                               DBG(dev, "udc_queue(): pending bytes in "
-                                       "rxfifo after nyet\n");
-                               /*
-                                * read pending bytes afer nyet:
-                                * referring to isr
-                                */
-                               if (udc_rxfifo_read(ep, req)) {
-                                       /* finish */
-                                       complete_req(ep, req, 0);
-                               }
-                               udc_rxfifo_pending = 0;
-
-                       }
-               }
-       }
-
-finished:
-       spin_unlock_irqrestore(&dev->lock, iflags);
-       return retval;
-}
-
-/* Empty request queue of an endpoint; caller holds spinlock */
-static void empty_req_queue(struct udc_ep *ep)
-{
-       struct udc_request      *req;
-
-       ep->halted = 1;
-       while (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next,
-                       struct udc_request,
-                       queue);
-               complete_req(ep, req, -ESHUTDOWN);
-       }
-}
-
-/* Dequeues a request packet, called by gadget driver */
-static int udc_dequeue(struct usb_ep *usbep, struct usb_request *usbreq)
-{
-       struct udc_ep           *ep;
-       struct udc_request      *req;
-       unsigned                halted;
-       unsigned long           iflags;
-
-       ep = container_of(usbep, struct udc_ep, ep);
-       if (!usbep || !usbreq || (!ep->ep.desc && (ep->num != 0
-                               && ep->num != UDC_EP0OUT_IX)))
-               return -EINVAL;
-
-       req = container_of(usbreq, struct udc_request, req);
-
-       spin_lock_irqsave(&ep->dev->lock, iflags);
-       halted = ep->halted;
-       ep->halted = 1;
-       /* request in processing or next one */
-       if (ep->queue.next == &req->queue) {
-               if (ep->dma && req->dma_going) {
-                       if (ep->in)
-                               ep->cancel_transfer = 1;
-                       else {
-                               u32 tmp;
-                               u32 dma_sts;
-                               /* stop potential receive DMA */
-                               tmp = readl(&udc->regs->ctl);
-                               writel(tmp & AMD_UNMASK_BIT(UDC_DEVCTL_RDE),
-                                                       &udc->regs->ctl);
-                               /*
-                                * Cancel transfer later in ISR
-                                * if descriptor was touched.
-                                */
-                               dma_sts = AMD_GETBITS(req->td_data->status,
-                                                       UDC_DMA_OUT_STS_BS);
-                               if (dma_sts != UDC_DMA_OUT_STS_BS_HOST_READY)
-                                       ep->cancel_transfer = 1;
-                               else {
-                                       udc_init_bna_dummy(ep->req);
-                                       writel(ep->bna_dummy_req->td_phys,
-                                               &ep->regs->desptr);
-                               }
-                               writel(tmp, &udc->regs->ctl);
-                       }
-               }
-       }
-       complete_req(ep, req, -ECONNRESET);
-       ep->halted = halted;
-
-       spin_unlock_irqrestore(&ep->dev->lock, iflags);
-       return 0;
-}
-
-/* Halt or clear halt of endpoint */
-static int
-udc_set_halt(struct usb_ep *usbep, int halt)
-{
-       struct udc_ep   *ep;
-       u32 tmp;
-       unsigned long iflags;
-       int retval = 0;
-
-       if (!usbep)
-               return -EINVAL;
-
-       pr_debug("set_halt %s: halt=%d\n", usbep->name, halt);
-
-       ep = container_of(usbep, struct udc_ep, ep);
-       if (!ep->ep.desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
-               return -EINVAL;
-       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       spin_lock_irqsave(&udc_stall_spinlock, iflags);
-       /* halt or clear halt */
-       if (halt) {
-               if (ep->num == 0)
-                       ep->dev->stall_ep0in = 1;
-               else {
-                       /*
-                        * set STALL
-                        * rxfifo empty not taken into acount
-                        */
-                       tmp = readl(&ep->regs->ctl);
-                       tmp |= AMD_BIT(UDC_EPCTL_S);
-                       writel(tmp, &ep->regs->ctl);
-                       ep->halted = 1;
-
-                       /* setup poll timer */
-                       if (!timer_pending(&udc_pollstall_timer)) {
-                               udc_pollstall_timer.expires = jiffies +
-                                       HZ * UDC_POLLSTALL_TIMER_USECONDS
-                                       / (1000 * 1000);
-                               if (!stop_pollstall_timer) {
-                                       DBG(ep->dev, "start polltimer\n");
-                                       add_timer(&udc_pollstall_timer);
-                               }
-                       }
-               }
-       } else {
-               /* ep is halted by set_halt() before */
-               if (ep->halted) {
-                       tmp = readl(&ep->regs->ctl);
-                       /* clear stall bit */
-                       tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S);
-                       /* clear NAK by writing CNAK */
-                       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
-                       writel(tmp, &ep->regs->ctl);
-                       ep->halted = 0;
-                       UDC_QUEUE_CNAK(ep, ep->num);
-               }
-       }
-       spin_unlock_irqrestore(&udc_stall_spinlock, iflags);
-       return retval;
-}
-
-/* gadget interface */
-static const struct usb_ep_ops udc_ep_ops = {
-       .enable         = udc_ep_enable,
-       .disable        = udc_ep_disable,
-
-       .alloc_request  = udc_alloc_request,
-       .free_request   = udc_free_request,
-
-       .queue          = udc_queue,
-       .dequeue        = udc_dequeue,
-
-       .set_halt       = udc_set_halt,
-       /* fifo ops not implemented */
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* Get frame counter (not implemented) */
-static int udc_get_frame(struct usb_gadget *gadget)
-{
-       return -EOPNOTSUPP;
-}
-
-/* Remote wakeup gadget interface */
-static int udc_wakeup(struct usb_gadget *gadget)
-{
-       struct udc              *dev;
-
-       if (!gadget)
-               return -EINVAL;
-       dev = container_of(gadget, struct udc, gadget);
-       udc_remote_wakeup(dev);
-
-       return 0;
-}
-
-static int amd5536_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-static int amd5536_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-/* gadget operations */
-static const struct usb_gadget_ops udc_ops = {
-       .wakeup         = udc_wakeup,
-       .get_frame      = udc_get_frame,
-       .udc_start      = amd5536_udc_start,
-       .udc_stop       = amd5536_udc_stop,
-};
-
-/* Setups endpoint parameters, adds endpoints to linked list */
-static void make_ep_lists(struct udc *dev)
-{
-       /* make gadget ep lists */
-       INIT_LIST_HEAD(&dev->gadget.ep_list);
-       list_add_tail(&dev->ep[UDC_EPIN_STATUS_IX].ep.ep_list,
-                                               &dev->gadget.ep_list);
-       list_add_tail(&dev->ep[UDC_EPIN_IX].ep.ep_list,
-                                               &dev->gadget.ep_list);
-       list_add_tail(&dev->ep[UDC_EPOUT_IX].ep.ep_list,
-                                               &dev->gadget.ep_list);
-
-       /* fifo config */
-       dev->ep[UDC_EPIN_STATUS_IX].fifo_depth = UDC_EPIN_SMALLINT_BUFF_SIZE;
-       if (dev->gadget.speed == USB_SPEED_FULL)
-               dev->ep[UDC_EPIN_IX].fifo_depth = UDC_FS_EPIN_BUFF_SIZE;
-       else if (dev->gadget.speed == USB_SPEED_HIGH)
-               dev->ep[UDC_EPIN_IX].fifo_depth = hs_tx_buf;
-       dev->ep[UDC_EPOUT_IX].fifo_depth = UDC_RXFIFO_SIZE;
-}
-
-/* init registers at driver load time */
-static int startup_registers(struct udc *dev)
-{
-       u32 tmp;
-
-       /* init controller by soft reset */
-       udc_soft_reset(dev);
-
-       /* mask not needed interrupts */
-       udc_mask_unused_interrupts(dev);
-
-       /* put into initial config */
-       udc_basic_init(dev);
-       /* link up all endpoints */
-       udc_setup_endpoints(dev);
-
-       /* program speed */
-       tmp = readl(&dev->regs->cfg);
-       if (use_fullspeed)
-               tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
-       else
-               tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);
-       writel(tmp, &dev->regs->cfg);
-
-       return 0;
-}
-
-/* Inits UDC context */
-static void udc_basic_init(struct udc *dev)
-{
-       u32     tmp;
-
-       DBG(dev, "udc_basic_init()\n");
-
-       dev->gadget.speed = USB_SPEED_UNKNOWN;
-
-       /* stop RDE timer */
-       if (timer_pending(&udc_timer)) {
-               set_rde = 0;
-               mod_timer(&udc_timer, jiffies - 1);
-       }
-       /* stop poll stall timer */
-       if (timer_pending(&udc_pollstall_timer))
-               mod_timer(&udc_pollstall_timer, jiffies - 1);
-       /* disable DMA */
-       tmp = readl(&dev->regs->ctl);
-       tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_RDE);
-       tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_TDE);
-       writel(tmp, &dev->regs->ctl);
-
-       /* enable dynamic CSR programming */
-       tmp = readl(&dev->regs->cfg);
-       tmp |= AMD_BIT(UDC_DEVCFG_CSR_PRG);
-       /* set self powered */
-       tmp |= AMD_BIT(UDC_DEVCFG_SP);
-       /* set remote wakeupable */
-       tmp |= AMD_BIT(UDC_DEVCFG_RWKP);
-       writel(tmp, &dev->regs->cfg);
-
-       make_ep_lists(dev);
-
-       dev->data_ep_enabled = 0;
-       dev->data_ep_queued = 0;
-}
-
-/* Sets initial endpoint parameters */
-static void udc_setup_endpoints(struct udc *dev)
-{
-       struct udc_ep   *ep;
-       u32     tmp;
-       u32     reg;
-
-       DBG(dev, "udc_setup_endpoints()\n");
-
-       /* read enum speed */
-       tmp = readl(&dev->regs->sts);
-       tmp = AMD_GETBITS(tmp, UDC_DEVSTS_ENUM_SPEED);
-       if (tmp == UDC_DEVSTS_ENUM_SPEED_HIGH)
-               dev->gadget.speed = USB_SPEED_HIGH;
-       else if (tmp == UDC_DEVSTS_ENUM_SPEED_FULL)
-               dev->gadget.speed = USB_SPEED_FULL;
-
-       /* set basic ep parameters */
-       for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
-               ep = &dev->ep[tmp];
-               ep->dev = dev;
-               ep->ep.name = ep_string[tmp];
-               ep->num = tmp;
-               /* txfifo size is calculated at enable time */
-               ep->txfifo = dev->txfifo;
-
-               /* fifo size */
-               if (tmp < UDC_EPIN_NUM) {
-                       ep->fifo_depth = UDC_TXFIFO_SIZE;
-                       ep->in = 1;
-               } else {
-                       ep->fifo_depth = UDC_RXFIFO_SIZE;
-                       ep->in = 0;
-
-               }
-               ep->regs = &dev->ep_regs[tmp];
-               /*
-                * ep will be reset only if ep was not enabled before to avoid
-                * disabling ep interrupts when ENUM interrupt occurs but ep is
-                * not enabled by gadget driver
-                */
-               if (!ep->ep.desc)
-                       ep_init(dev->regs, ep);
-
-               if (use_dma) {
-                       /*
-                        * ep->dma is not really used, just to indicate that
-                        * DMA is active: remove this
-                        * dma regs = dev control regs
-                        */
-                       ep->dma = &dev->regs->ctl;
-
-                       /* nak OUT endpoints until enable - not for ep0 */
-                       if (tmp != UDC_EP0IN_IX && tmp != UDC_EP0OUT_IX
-                                               && tmp > UDC_EPIN_NUM) {
-                               /* set NAK */
-                               reg = readl(&dev->ep[tmp].regs->ctl);
-                               reg |= AMD_BIT(UDC_EPCTL_SNAK);
-                               writel(reg, &dev->ep[tmp].regs->ctl);
-                               dev->ep[tmp].naking = 1;
-
-                       }
-               }
-       }
-       /* EP0 max packet */
-       if (dev->gadget.speed == USB_SPEED_FULL) {
-               usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0IN_IX].ep,
-                                          UDC_FS_EP0IN_MAX_PKT_SIZE);
-               usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0OUT_IX].ep,
-                                          UDC_FS_EP0OUT_MAX_PKT_SIZE);
-       } else if (dev->gadget.speed == USB_SPEED_HIGH) {
-               usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0IN_IX].ep,
-                                          UDC_EP0IN_MAX_PKT_SIZE);
-               usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0OUT_IX].ep,
-                                          UDC_EP0OUT_MAX_PKT_SIZE);
-       }
-
-       /*
-        * with suspend bug workaround, ep0 params for gadget driver
-        * are set at gadget driver bind() call
-        */
-       dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IX].ep;
-       dev->ep[UDC_EP0IN_IX].halted = 0;
-       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
-
-       /* init cfg/alt/int */
-       dev->cur_config = 0;
-       dev->cur_intf = 0;
-       dev->cur_alt = 0;
-}
-
-/* Bringup after Connect event, initial bringup to be ready for ep0 events */
-static void usb_connect(struct udc *dev)
-{
-
-       dev_info(&dev->pdev->dev, "USB Connect\n");
-
-       dev->connected = 1;
-
-       /* put into initial config */
-       udc_basic_init(dev);
-
-       /* enable device setup interrupts */
-       udc_enable_dev_setup_interrupts(dev);
-}
-
-/*
- * Calls gadget with disconnect event and resets the UDC and makes
- * initial bringup to be ready for ep0 events
- */
-static void usb_disconnect(struct udc *dev)
-{
-
-       dev_info(&dev->pdev->dev, "USB Disconnect\n");
-
-       dev->connected = 0;
-
-       /* mask interrupts */
-       udc_mask_unused_interrupts(dev);
-
-       /* REVISIT there doesn't seem to be a point to having this
-        * talk to a tasklet ... do it directly, we already hold
-        * the spinlock needed to process the disconnect.
-        */
-
-       tasklet_schedule(&disconnect_tasklet);
-}
-
-/* Tasklet for disconnect to be outside of interrupt context */
-static void udc_tasklet_disconnect(unsigned long par)
-{
-       struct udc *dev = (struct udc *)(*((struct udc **) par));
-       u32 tmp;
-
-       DBG(dev, "Tasklet disconnect\n");
-       spin_lock_irq(&dev->lock);
-
-       if (dev->driver) {
-               spin_unlock(&dev->lock);
-               dev->driver->disconnect(&dev->gadget);
-               spin_lock(&dev->lock);
-
-               /* empty queues */
-               for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
-                       empty_req_queue(&dev->ep[tmp]);
-
-       }
-
-       /* disable ep0 */
-       ep_init(dev->regs,
-                       &dev->ep[UDC_EP0IN_IX]);
-
-
-       if (!soft_reset_occured) {
-               /* init controller by soft reset */
-               udc_soft_reset(dev);
-               soft_reset_occured++;
-       }
-
-       /* re-enable dev interrupts */
-       udc_enable_dev_setup_interrupts(dev);
-       /* back to full speed ? */
-       if (use_fullspeed) {
-               tmp = readl(&dev->regs->cfg);
-               tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
-               writel(tmp, &dev->regs->cfg);
-       }
-
-       spin_unlock_irq(&dev->lock);
-}
-
-/* Reset the UDC core */
-static void udc_soft_reset(struct udc *dev)
-{
-       unsigned long   flags;
-
-       DBG(dev, "Soft reset\n");
-       /*
-        * reset possible waiting interrupts, because int.
-        * status is lost after soft reset,
-        * ep int. status reset
-        */
-       writel(UDC_EPINT_MSK_DISABLE_ALL, &dev->regs->ep_irqsts);
-       /* device int. status reset */
-       writel(UDC_DEV_MSK_DISABLE, &dev->regs->irqsts);
-
-       spin_lock_irqsave(&udc_irq_spinlock, flags);
-       writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
-       readl(&dev->regs->cfg);
-       spin_unlock_irqrestore(&udc_irq_spinlock, flags);
-
-}
-
-/* RDE timer callback to set RDE bit */
-static void udc_timer_function(unsigned long v)
-{
-       u32 tmp;
-
-       spin_lock_irq(&udc_irq_spinlock);
-
-       if (set_rde > 0) {
-               /*
-                * open the fifo if fifo was filled on last timer call
-                * conditionally
-                */
-               if (set_rde > 1) {
-                       /* set RDE to receive setup data */
-                       tmp = readl(&udc->regs->ctl);
-                       tmp |= AMD_BIT(UDC_DEVCTL_RDE);
-                       writel(tmp, &udc->regs->ctl);
-                       set_rde = -1;
-               } else if (readl(&udc->regs->sts)
-                               & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {
-                       /*
-                        * if fifo empty setup polling, do not just
-                        * open the fifo
-                        */
-                       udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV;
-                       if (!stop_timer)
-                               add_timer(&udc_timer);
-               } else {
-                       /*
-                        * fifo contains data now, setup timer for opening
-                        * the fifo when timer expires to be able to receive
-                        * setup packets, when data packets gets queued by
-                        * gadget layer then timer will forced to expire with
-                        * set_rde=0 (RDE is set in udc_queue())
-                        */
-                       set_rde++;
-                       /* debug: lhadmot_timer_start = 221070 */
-                       udc_timer.expires = jiffies + HZ*UDC_RDE_TIMER_SECONDS;
-                       if (!stop_timer)
-                               add_timer(&udc_timer);
-               }
-
-       } else
-               set_rde = -1; /* RDE was set by udc_queue() */
-       spin_unlock_irq(&udc_irq_spinlock);
-       if (stop_timer)
-               complete(&on_exit);
-
-}
-
-/* Handle halt state, used in stall poll timer */
-static void udc_handle_halt_state(struct udc_ep *ep)
-{
-       u32 tmp;
-       /* set stall as long not halted */
-       if (ep->halted == 1) {
-               tmp = readl(&ep->regs->ctl);
-               /* STALL cleared ? */
-               if (!(tmp & AMD_BIT(UDC_EPCTL_S))) {
-                       /*
-                        * FIXME: MSC spec requires that stall remains
-                        * even on receivng of CLEAR_FEATURE HALT. So
-                        * we would set STALL again here to be compliant.
-                        * But with current mass storage drivers this does
-                        * not work (would produce endless host retries).
-                        * So we clear halt on CLEAR_FEATURE.
-                        *
-                       DBG(ep->dev, "ep %d: set STALL again\n", ep->num);
-                       tmp |= AMD_BIT(UDC_EPCTL_S);
-                       writel(tmp, &ep->regs->ctl);*/
-
-                       /* clear NAK by writing CNAK */
-                       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
-                       writel(tmp, &ep->regs->ctl);
-                       ep->halted = 0;
-                       UDC_QUEUE_CNAK(ep, ep->num);
-               }
-       }
-}
-
-/* Stall timer callback to poll S bit and set it again after */
-static void udc_pollstall_timer_function(unsigned long v)
-{
-       struct udc_ep *ep;
-       int halted = 0;
-
-       spin_lock_irq(&udc_stall_spinlock);
-       /*
-        * only one IN and OUT endpoints are handled
-        * IN poll stall
-        */
-       ep = &udc->ep[UDC_EPIN_IX];
-       udc_handle_halt_state(ep);
-       if (ep->halted)
-               halted = 1;
-       /* OUT poll stall */
-       ep = &udc->ep[UDC_EPOUT_IX];
-       udc_handle_halt_state(ep);
-       if (ep->halted)
-               halted = 1;
-
-       /* setup timer again when still halted */
-       if (!stop_pollstall_timer && halted) {
-               udc_pollstall_timer.expires = jiffies +
-                                       HZ * UDC_POLLSTALL_TIMER_USECONDS
-                                       / (1000 * 1000);
-               add_timer(&udc_pollstall_timer);
-       }
-       spin_unlock_irq(&udc_stall_spinlock);
-
-       if (stop_pollstall_timer)
-               complete(&on_pollstall_exit);
-}
-
-/* Inits endpoint 0 so that SETUP packets are processed */
-static void activate_control_endpoints(struct udc *dev)
-{
-       u32 tmp;
-
-       DBG(dev, "activate_control_endpoints\n");
-
-       /* flush fifo */
-       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
-       tmp |= AMD_BIT(UDC_EPCTL_F);
-       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
-
-       /* set ep0 directions */
-       dev->ep[UDC_EP0IN_IX].in = 1;
-       dev->ep[UDC_EP0OUT_IX].in = 0;
-
-       /* set buffer size (tx fifo entries) of EP0_IN */
-       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufin_framenum);
-       if (dev->gadget.speed == USB_SPEED_FULL)
-               tmp = AMD_ADDBITS(tmp, UDC_FS_EPIN0_BUFF_SIZE,
-                                       UDC_EPIN_BUFF_SIZE);
-       else if (dev->gadget.speed == USB_SPEED_HIGH)
-               tmp = AMD_ADDBITS(tmp, UDC_EPIN0_BUFF_SIZE,
-                                       UDC_EPIN_BUFF_SIZE);
-       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufin_framenum);
-
-       /* set max packet size of EP0_IN */
-       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt);
-       if (dev->gadget.speed == USB_SPEED_FULL)
-               tmp = AMD_ADDBITS(tmp, UDC_FS_EP0IN_MAX_PKT_SIZE,
-                                       UDC_EP_MAX_PKT_SIZE);
-       else if (dev->gadget.speed == USB_SPEED_HIGH)
-               tmp = AMD_ADDBITS(tmp, UDC_EP0IN_MAX_PKT_SIZE,
-                               UDC_EP_MAX_PKT_SIZE);
-       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt);
-
-       /* set max packet size of EP0_OUT */
-       tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt);
-       if (dev->gadget.speed == USB_SPEED_FULL)
-               tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE,
-                                       UDC_EP_MAX_PKT_SIZE);
-       else if (dev->gadget.speed == USB_SPEED_HIGH)
-               tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE,
-                                       UDC_EP_MAX_PKT_SIZE);
-       writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt);
-
-       /* set max packet size of EP0 in UDC CSR */
-       tmp = readl(&dev->csr->ne[0]);
-       if (dev->gadget.speed == USB_SPEED_FULL)
-               tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE,
-                                       UDC_CSR_NE_MAX_PKT);
-       else if (dev->gadget.speed == USB_SPEED_HIGH)
-               tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE,
-                                       UDC_CSR_NE_MAX_PKT);
-       writel(tmp, &dev->csr->ne[0]);
-
-       if (use_dma) {
-               dev->ep[UDC_EP0OUT_IX].td->status |=
-                       AMD_BIT(UDC_DMA_OUT_STS_L);
-               /* write dma desc address */
-               writel(dev->ep[UDC_EP0OUT_IX].td_stp_dma,
-                       &dev->ep[UDC_EP0OUT_IX].regs->subptr);
-               writel(dev->ep[UDC_EP0OUT_IX].td_phys,
-                       &dev->ep[UDC_EP0OUT_IX].regs->desptr);
-               /* stop RDE timer */
-               if (timer_pending(&udc_timer)) {
-                       set_rde = 0;
-                       mod_timer(&udc_timer, jiffies - 1);
-               }
-               /* stop pollstall timer */
-               if (timer_pending(&udc_pollstall_timer))
-                       mod_timer(&udc_pollstall_timer, jiffies - 1);
-               /* enable DMA */
-               tmp = readl(&dev->regs->ctl);
-               tmp |= AMD_BIT(UDC_DEVCTL_MODE)
-                               | AMD_BIT(UDC_DEVCTL_RDE)
-                               | AMD_BIT(UDC_DEVCTL_TDE);
-               if (use_dma_bufferfill_mode)
-                       tmp |= AMD_BIT(UDC_DEVCTL_BF);
-               else if (use_dma_ppb_du)
-                       tmp |= AMD_BIT(UDC_DEVCTL_DU);
-               writel(tmp, &dev->regs->ctl);
-       }
-
-       /* clear NAK by writing CNAK for EP0IN */
-       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
-       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
-       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
-       dev->ep[UDC_EP0IN_IX].naking = 0;
-       UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX);
-
-       /* clear NAK by writing CNAK for EP0OUT */
-       tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);
-       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
-       writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl);
-       dev->ep[UDC_EP0OUT_IX].naking = 0;
-       UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX);
-}
-
-/* Make endpoint 0 ready for control traffic */
-static int setup_ep0(struct udc *dev)
-{
-       activate_control_endpoints(dev);
-       /* enable ep0 interrupts */
-       udc_enable_ep0_interrupts(dev);
-       /* enable device setup interrupts */
-       udc_enable_dev_setup_interrupts(dev);
-
-       return 0;
-}
-
-/* Called by gadget driver to register itself */
-static int amd5536_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct udc *dev = to_amd5536_udc(g);
-       u32 tmp;
-
-       driver->driver.bus = NULL;
-       dev->driver = driver;
-
-       /* Some gadget drivers use both ep0 directions.
-        * NOTE: to gadget driver, ep0 is just one endpoint...
-        */
-       dev->ep[UDC_EP0OUT_IX].ep.driver_data =
-               dev->ep[UDC_EP0IN_IX].ep.driver_data;
-
-       /* get ready for ep0 traffic */
-       setup_ep0(dev);
-
-       /* clear SD */
-       tmp = readl(&dev->regs->ctl);
-       tmp = tmp & AMD_CLEAR_BIT(UDC_DEVCTL_SD);
-       writel(tmp, &dev->regs->ctl);
-
-       usb_connect(dev);
-
-       return 0;
-}
-
-/* shutdown requests and disconnect from gadget */
-static void
-shutdown(struct udc *dev, struct usb_gadget_driver *driver)
-__releases(dev->lock)
-__acquires(dev->lock)
-{
-       int tmp;
-
-       /* empty queues and init hardware */
-       udc_basic_init(dev);
-
-       for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
-               empty_req_queue(&dev->ep[tmp]);
-
-       udc_setup_endpoints(dev);
-}
-
-/* Called by gadget driver to unregister itself */
-static int amd5536_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct udc *dev = to_amd5536_udc(g);
-       unsigned long flags;
-       u32 tmp;
-
-       spin_lock_irqsave(&dev->lock, flags);
-       udc_mask_unused_interrupts(dev);
-       shutdown(dev, driver);
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       dev->driver = NULL;
-
-       /* set SD */
-       tmp = readl(&dev->regs->ctl);
-       tmp |= AMD_BIT(UDC_DEVCTL_SD);
-       writel(tmp, &dev->regs->ctl);
-
-       return 0;
-}
-
-/* Clear pending NAK bits */
-static void udc_process_cnak_queue(struct udc *dev)
-{
-       u32 tmp;
-       u32 reg;
-
-       /* check epin's */
-       DBG(dev, "CNAK pending queue processing\n");
-       for (tmp = 0; tmp < UDC_EPIN_NUM_USED; tmp++) {
-               if (cnak_pending & (1 << tmp)) {
-                       DBG(dev, "CNAK pending for ep%d\n", tmp);
-                       /* clear NAK by writing CNAK */
-                       reg = readl(&dev->ep[tmp].regs->ctl);
-                       reg |= AMD_BIT(UDC_EPCTL_CNAK);
-                       writel(reg, &dev->ep[tmp].regs->ctl);
-                       dev->ep[tmp].naking = 0;
-                       UDC_QUEUE_CNAK(&dev->ep[tmp], dev->ep[tmp].num);
-               }
-       }
-       /* ...  and ep0out */
-       if (cnak_pending & (1 << UDC_EP0OUT_IX)) {
-               DBG(dev, "CNAK pending for ep%d\n", UDC_EP0OUT_IX);
-               /* clear NAK by writing CNAK */
-               reg = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);
-               reg |= AMD_BIT(UDC_EPCTL_CNAK);
-               writel(reg, &dev->ep[UDC_EP0OUT_IX].regs->ctl);
-               dev->ep[UDC_EP0OUT_IX].naking = 0;
-               UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX],
-                               dev->ep[UDC_EP0OUT_IX].num);
-       }
-}
-
-/* Enabling RX DMA after setup packet */
-static void udc_ep0_set_rde(struct udc *dev)
-{
-       if (use_dma) {
-               /*
-                * only enable RXDMA when no data endpoint enabled
-                * or data is queued
-                */
-               if (!dev->data_ep_enabled || dev->data_ep_queued) {
-                       udc_set_rde(dev);
-               } else {
-                       /*
-                        * setup timer for enabling RDE (to not enable
-                        * RXFIFO DMA for data endpoints to early)
-                        */
-                       if (set_rde != 0 && !timer_pending(&udc_timer)) {
-                               udc_timer.expires =
-                                       jiffies + HZ/UDC_RDE_TIMER_DIV;
-                               set_rde = 1;
-                               if (!stop_timer)
-                                       add_timer(&udc_timer);
-                       }
-               }
-       }
-}
-
-
-/* Interrupt handler for data OUT traffic */
-static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
-{
-       irqreturn_t             ret_val = IRQ_NONE;
-       u32                     tmp;
-       struct udc_ep           *ep;
-       struct udc_request      *req;
-       unsigned int            count;
-       struct udc_data_dma     *td = NULL;
-       unsigned                dma_done;
-
-       VDBG(dev, "ep%d irq\n", ep_ix);
-       ep = &dev->ep[ep_ix];
-
-       tmp = readl(&ep->regs->sts);
-       if (use_dma) {
-               /* BNA event ? */
-               if (tmp & AMD_BIT(UDC_EPSTS_BNA)) {
-                       DBG(dev, "BNA ep%dout occurred - DESPTR = %x\n",
-                                       ep->num, readl(&ep->regs->desptr));
-                       /* clear BNA */
-                       writel(tmp | AMD_BIT(UDC_EPSTS_BNA), &ep->regs->sts);
-                       if (!ep->cancel_transfer)
-                               ep->bna_occurred = 1;
-                       else
-                               ep->cancel_transfer = 0;
-                       ret_val = IRQ_HANDLED;
-                       goto finished;
-               }
-       }
-       /* HE event ? */
-       if (tmp & AMD_BIT(UDC_EPSTS_HE)) {
-               dev_err(&dev->pdev->dev, "HE ep%dout occurred\n", ep->num);
-
-               /* clear HE */
-               writel(tmp | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts);
-               ret_val = IRQ_HANDLED;
-               goto finished;
-       }
-
-       if (!list_empty(&ep->queue)) {
-
-               /* next request */
-               req = list_entry(ep->queue.next,
-                       struct udc_request, queue);
-       } else {
-               req = NULL;
-               udc_rxfifo_pending = 1;
-       }
-       VDBG(dev, "req = %p\n", req);
-       /* fifo mode */
-       if (!use_dma) {
-
-               /* read fifo */
-               if (req && udc_rxfifo_read(ep, req)) {
-                       ret_val = IRQ_HANDLED;
-
-                       /* finish */
-                       complete_req(ep, req, 0);
-                       /* next request */
-                       if (!list_empty(&ep->queue) && !ep->halted) {
-                               req = list_entry(ep->queue.next,
-                                       struct udc_request, queue);
-                       } else
-                               req = NULL;
-               }
-
-       /* DMA */
-       } else if (!ep->cancel_transfer && req != NULL) {
-               ret_val = IRQ_HANDLED;
-
-               /* check for DMA done */
-               if (!use_dma_ppb) {
-                       dma_done = AMD_GETBITS(req->td_data->status,
-                                               UDC_DMA_OUT_STS_BS);
-               /* packet per buffer mode - rx bytes */
-               } else {
-                       /*
-                        * if BNA occurred then recover desc. from
-                        * BNA dummy desc.
-                        */
-                       if (ep->bna_occurred) {
-                               VDBG(dev, "Recover desc. from BNA dummy\n");
-                               memcpy(req->td_data, ep->bna_dummy_req->td_data,
-                                               sizeof(struct udc_data_dma));
-                               ep->bna_occurred = 0;
-                               udc_init_bna_dummy(ep->req);
-                       }
-                       td = udc_get_last_dma_desc(req);
-                       dma_done = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_BS);
-               }
-               if (dma_done == UDC_DMA_OUT_STS_BS_DMA_DONE) {
-                       /* buffer fill mode - rx bytes */
-                       if (!use_dma_ppb) {
-                               /* received number bytes */
-                               count = AMD_GETBITS(req->td_data->status,
-                                               UDC_DMA_OUT_STS_RXBYTES);
-                               VDBG(dev, "rx bytes=%u\n", count);
-                       /* packet per buffer mode - rx bytes */
-                       } else {
-                               VDBG(dev, "req->td_data=%p\n", req->td_data);
-                               VDBG(dev, "last desc = %p\n", td);
-                               /* received number bytes */
-                               if (use_dma_ppb_du) {
-                                       /* every desc. counts bytes */
-                                       count = udc_get_ppbdu_rxbytes(req);
-                               } else {
-                                       /* last desc. counts bytes */
-                                       count = AMD_GETBITS(td->status,
-                                               UDC_DMA_OUT_STS_RXBYTES);
-                                       if (!count && req->req.length
-                                               == UDC_DMA_MAXPACKET) {
-                                               /*
-                                                * on 64k packets the RXBYTES
-                                                * field is zero
-                                                */
-                                               count = UDC_DMA_MAXPACKET;
-                                       }
-                               }
-                               VDBG(dev, "last desc rx bytes=%u\n", count);
-                       }
-
-                       tmp = req->req.length - req->req.actual;
-                       if (count > tmp) {
-                               if ((tmp % ep->ep.maxpacket) != 0) {
-                                       DBG(dev, "%s: rx %db, space=%db\n",
-                                               ep->ep.name, count, tmp);
-                                       req->req.status = -EOVERFLOW;
-                               }
-                               count = tmp;
-                       }
-                       req->req.actual += count;
-                       req->dma_going = 0;
-                       /* complete request */
-                       complete_req(ep, req, 0);
-
-                       /* next request */
-                       if (!list_empty(&ep->queue) && !ep->halted) {
-                               req = list_entry(ep->queue.next,
-                                       struct udc_request,
-                                       queue);
-                               /*
-                                * DMA may be already started by udc_queue()
-                                * called by gadget drivers completion
-                                * routine. This happens when queue
-                                * holds one request only.
-                                */
-                               if (req->dma_going == 0) {
-                                       /* next dma */
-                                       if (prep_dma(ep, req, GFP_ATOMIC) != 0)
-                                               goto finished;
-                                       /* write desc pointer */
-                                       writel(req->td_phys,
-                                               &ep->regs->desptr);
-                                       req->dma_going = 1;
-                                       /* enable DMA */
-                                       udc_set_rde(dev);
-                               }
-                       } else {
-                               /*
-                                * implant BNA dummy descriptor to allow
-                                * RXFIFO opening by RDE
-                                */
-                               if (ep->bna_dummy_req) {
-                                       /* write desc pointer */
-                                       writel(ep->bna_dummy_req->td_phys,
-                                               &ep->regs->desptr);
-                                       ep->bna_occurred = 0;
-                               }
-
-                               /*
-                                * schedule timer for setting RDE if queue
-                                * remains empty to allow ep0 packets pass
-                                * through
-                                */
-                               if (set_rde != 0
-                                               && !timer_pending(&udc_timer)) {
-                                       udc_timer.expires =
-                                               jiffies
-                                               + HZ*UDC_RDE_TIMER_SECONDS;
-                                       set_rde = 1;
-                                       if (!stop_timer)
-                                               add_timer(&udc_timer);
-                               }
-                               if (ep->num != UDC_EP0OUT_IX)
-                                       dev->data_ep_queued = 0;
-                       }
-
-               } else {
-                       /*
-                       * RX DMA must be reenabled for each desc in PPBDU mode
-                       * and must be enabled for PPBNDU mode in case of BNA
-                       */
-                       udc_set_rde(dev);
-               }
-
-       } else if (ep->cancel_transfer) {
-               ret_val = IRQ_HANDLED;
-               ep->cancel_transfer = 0;
-       }
-
-       /* check pending CNAKS */
-       if (cnak_pending) {
-               /* CNAk processing when rxfifo empty only */
-               if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY))
-                       udc_process_cnak_queue(dev);
-       }
-
-       /* clear OUT bits in ep status */
-       writel(UDC_EPSTS_OUT_CLEAR, &ep->regs->sts);
-finished:
-       return ret_val;
-}
-
-/* Interrupt handler for data IN traffic */
-static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
-{
-       irqreturn_t ret_val = IRQ_NONE;
-       u32 tmp;
-       u32 epsts;
-       struct udc_ep *ep;
-       struct udc_request *req;
-       struct udc_data_dma *td;
-       unsigned dma_done;
-       unsigned len;
-
-       ep = &dev->ep[ep_ix];
-
-       epsts = readl(&ep->regs->sts);
-       if (use_dma) {
-               /* BNA ? */
-               if (epsts & AMD_BIT(UDC_EPSTS_BNA)) {
-                       dev_err(&dev->pdev->dev,
-                               "BNA ep%din occurred - DESPTR = %08lx\n",
-                               ep->num,
-                               (unsigned long) readl(&ep->regs->desptr));
-
-                       /* clear BNA */
-                       writel(epsts, &ep->regs->sts);
-                       ret_val = IRQ_HANDLED;
-                       goto finished;
-               }
-       }
-       /* HE event ? */
-       if (epsts & AMD_BIT(UDC_EPSTS_HE)) {
-               dev_err(&dev->pdev->dev,
-                       "HE ep%dn occurred - DESPTR = %08lx\n",
-                       ep->num, (unsigned long) readl(&ep->regs->desptr));
-
-               /* clear HE */
-               writel(epsts | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts);
-               ret_val = IRQ_HANDLED;
-               goto finished;
-       }
-
-       /* DMA completion */
-       if (epsts & AMD_BIT(UDC_EPSTS_TDC)) {
-               VDBG(dev, "TDC set- completion\n");
-               ret_val = IRQ_HANDLED;
-               if (!ep->cancel_transfer && !list_empty(&ep->queue)) {
-                       req = list_entry(ep->queue.next,
-                                       struct udc_request, queue);
-                       /*
-                        * length bytes transferred
-                        * check dma done of last desc. in PPBDU mode
-                        */
-                       if (use_dma_ppb_du) {
-                               td = udc_get_last_dma_desc(req);
-                               if (td) {
-                                       dma_done =
-                                               AMD_GETBITS(td->status,
-                                               UDC_DMA_IN_STS_BS);
-                                       /* don't care DMA done */
-                                       req->req.actual = req->req.length;
-                               }
-                       } else {
-                               /* assume all bytes transferred */
-                               req->req.actual = req->req.length;
-                       }
-
-                       if (req->req.actual == req->req.length) {
-                               /* complete req */
-                               complete_req(ep, req, 0);
-                               req->dma_going = 0;
-                               /* further request available ? */
-                               if (list_empty(&ep->queue)) {
-                                       /* disable interrupt */
-                                       tmp = readl(&dev->regs->ep_irqmsk);
-                                       tmp |= AMD_BIT(ep->num);
-                                       writel(tmp, &dev->regs->ep_irqmsk);
-                               }
-                       }
-               }
-               ep->cancel_transfer = 0;
-
-       }
-       /*
-        * status reg has IN bit set and TDC not set (if TDC was handled,
-        * IN must not be handled (UDC defect) ?
-        */
-       if ((epsts & AMD_BIT(UDC_EPSTS_IN))
-                       && !(epsts & AMD_BIT(UDC_EPSTS_TDC))) {
-               ret_val = IRQ_HANDLED;
-               if (!list_empty(&ep->queue)) {
-                       /* next request */
-                       req = list_entry(ep->queue.next,
-                                       struct udc_request, queue);
-                       /* FIFO mode */
-                       if (!use_dma) {
-                               /* write fifo */
-                               udc_txfifo_write(ep, &req->req);
-                               len = req->req.length - req->req.actual;
-                               if (len > ep->ep.maxpacket)
-                                       len = ep->ep.maxpacket;
-                               req->req.actual += len;
-                               if (req->req.actual == req->req.length
-                                       || (len != ep->ep.maxpacket)) {
-                                       /* complete req */
-                                       complete_req(ep, req, 0);
-                               }
-                       /* DMA */
-                       } else if (req && !req->dma_going) {
-                               VDBG(dev, "IN DMA : req=%p req->td_data=%p\n",
-                                       req, req->td_data);
-                               if (req->td_data) {
-
-                                       req->dma_going = 1;
-
-                                       /*
-                                        * unset L bit of first desc.
-                                        * for chain
-                                        */
-                                       if (use_dma_ppb && req->req.length >
-                                                       ep->ep.maxpacket) {
-                                               req->td_data->status &=
-                                                       AMD_CLEAR_BIT(
-                                                       UDC_DMA_IN_STS_L);
-                                       }
-
-                                       /* write desc pointer */
-                                       writel(req->td_phys, &ep->regs->desptr);
-
-                                       /* set HOST READY */
-                                       req->td_data->status =
-                                               AMD_ADDBITS(
-                                               req->td_data->status,
-                                               UDC_DMA_IN_STS_BS_HOST_READY,
-                                               UDC_DMA_IN_STS_BS);
-
-                                       /* set poll demand bit */
-                                       tmp = readl(&ep->regs->ctl);
-                                       tmp |= AMD_BIT(UDC_EPCTL_P);
-                                       writel(tmp, &ep->regs->ctl);
-                               }
-                       }
-
-               } else if (!use_dma && ep->in) {
-                       /* disable interrupt */
-                       tmp = readl(
-                               &dev->regs->ep_irqmsk);
-                       tmp |= AMD_BIT(ep->num);
-                       writel(tmp,
-                               &dev->regs->ep_irqmsk);
-               }
-       }
-       /* clear status bits */
-       writel(epsts, &ep->regs->sts);
-
-finished:
-       return ret_val;
-
-}
-
-/* Interrupt handler for Control OUT traffic */
-static irqreturn_t udc_control_out_isr(struct udc *dev)
-__releases(dev->lock)
-__acquires(dev->lock)
-{
-       irqreturn_t ret_val = IRQ_NONE;
-       u32 tmp;
-       int setup_supported;
-       u32 count;
-       int set = 0;
-       struct udc_ep   *ep;
-       struct udc_ep   *ep_tmp;
-
-       ep = &dev->ep[UDC_EP0OUT_IX];
-
-       /* clear irq */
-       writel(AMD_BIT(UDC_EPINT_OUT_EP0), &dev->regs->ep_irqsts);
-
-       tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->sts);
-       /* check BNA and clear if set */
-       if (tmp & AMD_BIT(UDC_EPSTS_BNA)) {
-               VDBG(dev, "ep0: BNA set\n");
-               writel(AMD_BIT(UDC_EPSTS_BNA),
-                       &dev->ep[UDC_EP0OUT_IX].regs->sts);
-               ep->bna_occurred = 1;
-               ret_val = IRQ_HANDLED;
-               goto finished;
-       }
-
-       /* type of data: SETUP or DATA 0 bytes */
-       tmp = AMD_GETBITS(tmp, UDC_EPSTS_OUT);
-       VDBG(dev, "data_typ = %x\n", tmp);
-
-       /* setup data */
-       if (tmp == UDC_EPSTS_OUT_SETUP) {
-               ret_val = IRQ_HANDLED;
-
-               ep->dev->stall_ep0in = 0;
-               dev->waiting_zlp_ack_ep0in = 0;
-
-               /* set NAK for EP0_IN */
-               tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
-               tmp |= AMD_BIT(UDC_EPCTL_SNAK);
-               writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
-               dev->ep[UDC_EP0IN_IX].naking = 1;
-               /* get setup data */
-               if (use_dma) {
-
-                       /* clear OUT bits in ep status */
-                       writel(UDC_EPSTS_OUT_CLEAR,
-                               &dev->ep[UDC_EP0OUT_IX].regs->sts);
-
-                       setup_data.data[0] =
-                               dev->ep[UDC_EP0OUT_IX].td_stp->data12;
-                       setup_data.data[1] =
-                               dev->ep[UDC_EP0OUT_IX].td_stp->data34;
-                       /* set HOST READY */
-                       dev->ep[UDC_EP0OUT_IX].td_stp->status =
-                                       UDC_DMA_STP_STS_BS_HOST_READY;
-               } else {
-                       /* read fifo */
-                       udc_rxfifo_read_dwords(dev, setup_data.data, 2);
-               }
-
-               /* determine direction of control data */
-               if ((setup_data.request.bRequestType & USB_DIR_IN) != 0) {
-                       dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IX].ep;
-                       /* enable RDE */
-                       udc_ep0_set_rde(dev);
-                       set = 0;
-               } else {
-                       dev->gadget.ep0 = &dev->ep[UDC_EP0OUT_IX].ep;
-                       /*
-                        * implant BNA dummy descriptor to allow RXFIFO opening
-                        * by RDE
-                        */
-                       if (ep->bna_dummy_req) {
-                               /* write desc pointer */
-                               writel(ep->bna_dummy_req->td_phys,
-                                       &dev->ep[UDC_EP0OUT_IX].regs->desptr);
-                               ep->bna_occurred = 0;
-                       }
-
-                       set = 1;
-                       dev->ep[UDC_EP0OUT_IX].naking = 1;
-                       /*
-                        * setup timer for enabling RDE (to not enable
-                        * RXFIFO DMA for data to early)
-                        */
-                       set_rde = 1;
-                       if (!timer_pending(&udc_timer)) {
-                               udc_timer.expires = jiffies +
-                                                       HZ/UDC_RDE_TIMER_DIV;
-                               if (!stop_timer)
-                                       add_timer(&udc_timer);
-                       }
-               }
-
-               /*
-                * mass storage reset must be processed here because
-                * next packet may be a CLEAR_FEATURE HALT which would not
-                * clear the stall bit when no STALL handshake was received
-                * before (autostall can cause this)
-                */
-               if (setup_data.data[0] == UDC_MSCRES_DWORD0
-                               && setup_data.data[1] == UDC_MSCRES_DWORD1) {
-                       DBG(dev, "MSC Reset\n");
-                       /*
-                        * clear stall bits
-                        * only one IN and OUT endpoints are handled
-                        */
-                       ep_tmp = &udc->ep[UDC_EPIN_IX];
-                       udc_set_halt(&ep_tmp->ep, 0);
-                       ep_tmp = &udc->ep[UDC_EPOUT_IX];
-                       udc_set_halt(&ep_tmp->ep, 0);
-               }
-
-               /* call gadget with setup data received */
-               spin_unlock(&dev->lock);
-               setup_supported = dev->driver->setup(&dev->gadget,
-                                               &setup_data.request);
-               spin_lock(&dev->lock);
-
-               tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
-               /* ep0 in returns data (not zlp) on IN phase */
-               if (setup_supported >= 0 && setup_supported <
-                               UDC_EP0IN_MAXPACKET) {
-                       /* clear NAK by writing CNAK in EP0_IN */
-                       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
-                       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
-                       dev->ep[UDC_EP0IN_IX].naking = 0;
-                       UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX);
-
-               /* if unsupported request then stall */
-               } else if (setup_supported < 0) {
-                       tmp |= AMD_BIT(UDC_EPCTL_S);
-                       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
-               } else
-                       dev->waiting_zlp_ack_ep0in = 1;
-
-
-               /* clear NAK by writing CNAK in EP0_OUT */
-               if (!set) {
-                       tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);
-                       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
-                       writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl);
-                       dev->ep[UDC_EP0OUT_IX].naking = 0;
-                       UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX);
-               }
-
-               if (!use_dma) {
-                       /* clear OUT bits in ep status */
-                       writel(UDC_EPSTS_OUT_CLEAR,
-                               &dev->ep[UDC_EP0OUT_IX].regs->sts);
-               }
-
-       /* data packet 0 bytes */
-       } else if (tmp == UDC_EPSTS_OUT_DATA) {
-               /* clear OUT bits in ep status */
-               writel(UDC_EPSTS_OUT_CLEAR, &dev->ep[UDC_EP0OUT_IX].regs->sts);
-
-               /* get setup data: only 0 packet */
-               if (use_dma) {
-                       /* no req if 0 packet, just reactivate */
-                       if (list_empty(&dev->ep[UDC_EP0OUT_IX].queue)) {
-                               VDBG(dev, "ZLP\n");
-
-                               /* set HOST READY */
-                               dev->ep[UDC_EP0OUT_IX].td->status =
-                                       AMD_ADDBITS(
-                                       dev->ep[UDC_EP0OUT_IX].td->status,
-                                       UDC_DMA_OUT_STS_BS_HOST_READY,
-                                       UDC_DMA_OUT_STS_BS);
-                               /* enable RDE */
-                               udc_ep0_set_rde(dev);
-                               ret_val = IRQ_HANDLED;
-
-                       } else {
-                               /* control write */
-                               ret_val |= udc_data_out_isr(dev, UDC_EP0OUT_IX);
-                               /* re-program desc. pointer for possible ZLPs */
-                               writel(dev->ep[UDC_EP0OUT_IX].td_phys,
-                                       &dev->ep[UDC_EP0OUT_IX].regs->desptr);
-                               /* enable RDE */
-                               udc_ep0_set_rde(dev);
-                       }
-               } else {
-
-                       /* received number bytes */
-                       count = readl(&dev->ep[UDC_EP0OUT_IX].regs->sts);
-                       count = AMD_GETBITS(count, UDC_EPSTS_RX_PKT_SIZE);
-                       /* out data for fifo mode not working */
-                       count = 0;
-
-                       /* 0 packet or real data ? */
-                       if (count != 0) {
-                               ret_val |= udc_data_out_isr(dev, UDC_EP0OUT_IX);
-                       } else {
-                               /* dummy read confirm */
-                               readl(&dev->ep[UDC_EP0OUT_IX].regs->confirm);
-                               ret_val = IRQ_HANDLED;
-                       }
-               }
-       }
-
-       /* check pending CNAKS */
-       if (cnak_pending) {
-               /* CNAk processing when rxfifo empty only */
-               if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY))
-                       udc_process_cnak_queue(dev);
-       }
-
-finished:
-       return ret_val;
-}
-
-/* Interrupt handler for Control IN traffic */
-static irqreturn_t udc_control_in_isr(struct udc *dev)
-{
-       irqreturn_t ret_val = IRQ_NONE;
-       u32 tmp;
-       struct udc_ep *ep;
-       struct udc_request *req;
-       unsigned len;
-
-       ep = &dev->ep[UDC_EP0IN_IX];
-
-       /* clear irq */
-       writel(AMD_BIT(UDC_EPINT_IN_EP0), &dev->regs->ep_irqsts);
-
-       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->sts);
-       /* DMA completion */
-       if (tmp & AMD_BIT(UDC_EPSTS_TDC)) {
-               VDBG(dev, "isr: TDC clear\n");
-               ret_val = IRQ_HANDLED;
-
-               /* clear TDC bit */
-               writel(AMD_BIT(UDC_EPSTS_TDC),
-                               &dev->ep[UDC_EP0IN_IX].regs->sts);
-
-       /* status reg has IN bit set ? */
-       } else if (tmp & AMD_BIT(UDC_EPSTS_IN)) {
-               ret_val = IRQ_HANDLED;
-
-               if (ep->dma) {
-                       /* clear IN bit */
-                       writel(AMD_BIT(UDC_EPSTS_IN),
-                               &dev->ep[UDC_EP0IN_IX].regs->sts);
-               }
-               if (dev->stall_ep0in) {
-                       DBG(dev, "stall ep0in\n");
-                       /* halt ep0in */
-                       tmp = readl(&ep->regs->ctl);
-                       tmp |= AMD_BIT(UDC_EPCTL_S);
-                       writel(tmp, &ep->regs->ctl);
-               } else {
-                       if (!list_empty(&ep->queue)) {
-                               /* next request */
-                               req = list_entry(ep->queue.next,
-                                               struct udc_request, queue);
-
-                               if (ep->dma) {
-                                       /* write desc pointer */
-                                       writel(req->td_phys, &ep->regs->desptr);
-                                       /* set HOST READY */
-                                       req->td_data->status =
-                                               AMD_ADDBITS(
-                                               req->td_data->status,
-                                               UDC_DMA_STP_STS_BS_HOST_READY,
-                                               UDC_DMA_STP_STS_BS);
-
-                                       /* set poll demand bit */
-                                       tmp =
-                                       readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
-                                       tmp |= AMD_BIT(UDC_EPCTL_P);
-                                       writel(tmp,
-                                       &dev->ep[UDC_EP0IN_IX].regs->ctl);
-
-                                       /* all bytes will be transferred */
-                                       req->req.actual = req->req.length;
-
-                                       /* complete req */
-                                       complete_req(ep, req, 0);
-
-                               } else {
-                                       /* write fifo */
-                                       udc_txfifo_write(ep, &req->req);
-
-                                       /* lengh bytes transferred */
-                                       len = req->req.length - req->req.actual;
-                                       if (len > ep->ep.maxpacket)
-                                               len = ep->ep.maxpacket;
-
-                                       req->req.actual += len;
-                                       if (req->req.actual == req->req.length
-                                               || (len != ep->ep.maxpacket)) {
-                                               /* complete req */
-                                               complete_req(ep, req, 0);
-                                       }
-                               }
-
-                       }
-               }
-               ep->halted = 0;
-               dev->stall_ep0in = 0;
-               if (!ep->dma) {
-                       /* clear IN bit */
-                       writel(AMD_BIT(UDC_EPSTS_IN),
-                               &dev->ep[UDC_EP0IN_IX].regs->sts);
-               }
-       }
-
-       return ret_val;
-}
-
-
-/* Interrupt handler for global device events */
-static irqreturn_t udc_dev_isr(struct udc *dev, u32 dev_irq)
-__releases(dev->lock)
-__acquires(dev->lock)
-{
-       irqreturn_t ret_val = IRQ_NONE;
-       u32 tmp;
-       u32 cfg;
-       struct udc_ep *ep;
-       u16 i;
-       u8 udc_csr_epix;
-
-       /* SET_CONFIG irq ? */
-       if (dev_irq & AMD_BIT(UDC_DEVINT_SC)) {
-               ret_val = IRQ_HANDLED;
-
-               /* read config value */
-               tmp = readl(&dev->regs->sts);
-               cfg = AMD_GETBITS(tmp, UDC_DEVSTS_CFG);
-               DBG(dev, "SET_CONFIG interrupt: config=%d\n", cfg);
-               dev->cur_config = cfg;
-               dev->set_cfg_not_acked = 1;
-
-               /* make usb request for gadget driver */
-               memset(&setup_data, 0 , sizeof(union udc_setup_data));
-               setup_data.request.bRequest = USB_REQ_SET_CONFIGURATION;
-               setup_data.request.wValue = cpu_to_le16(dev->cur_config);
-
-               /* programm the NE registers */
-               for (i = 0; i < UDC_EP_NUM; i++) {
-                       ep = &dev->ep[i];
-                       if (ep->in) {
-
-                               /* ep ix in UDC CSR register space */
-                               udc_csr_epix = ep->num;
-
-
-                       /* OUT ep */
-                       } else {
-                               /* ep ix in UDC CSR register space */
-                               udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS;
-                       }
-
-                       tmp = readl(&dev->csr->ne[udc_csr_epix]);
-                       /* ep cfg */
-                       tmp = AMD_ADDBITS(tmp, ep->dev->cur_config,
-                                               UDC_CSR_NE_CFG);
-                       /* write reg */
-                       writel(tmp, &dev->csr->ne[udc_csr_epix]);
-
-                       /* clear stall bits */
-                       ep->halted = 0;
-                       tmp = readl(&ep->regs->ctl);
-                       tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S);
-                       writel(tmp, &ep->regs->ctl);
-               }
-               /* call gadget zero with setup data received */
-               spin_unlock(&dev->lock);
-               tmp = dev->driver->setup(&dev->gadget, &setup_data.request);
-               spin_lock(&dev->lock);
-
-       } /* SET_INTERFACE ? */
-       if (dev_irq & AMD_BIT(UDC_DEVINT_SI)) {
-               ret_val = IRQ_HANDLED;
-
-               dev->set_cfg_not_acked = 1;
-               /* read interface and alt setting values */
-               tmp = readl(&dev->regs->sts);
-               dev->cur_alt = AMD_GETBITS(tmp, UDC_DEVSTS_ALT);
-               dev->cur_intf = AMD_GETBITS(tmp, UDC_DEVSTS_INTF);
-
-               /* make usb request for gadget driver */
-               memset(&setup_data, 0 , sizeof(union udc_setup_data));
-               setup_data.request.bRequest = USB_REQ_SET_INTERFACE;
-               setup_data.request.bRequestType = USB_RECIP_INTERFACE;
-               setup_data.request.wValue = cpu_to_le16(dev->cur_alt);
-               setup_data.request.wIndex = cpu_to_le16(dev->cur_intf);
-
-               DBG(dev, "SET_INTERFACE interrupt: alt=%d intf=%d\n",
-                               dev->cur_alt, dev->cur_intf);
-
-               /* programm the NE registers */
-               for (i = 0; i < UDC_EP_NUM; i++) {
-                       ep = &dev->ep[i];
-                       if (ep->in) {
-
-                               /* ep ix in UDC CSR register space */
-                               udc_csr_epix = ep->num;
-
-
-                       /* OUT ep */
-                       } else {
-                               /* ep ix in UDC CSR register space */
-                               udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS;
-                       }
-
-                       /* UDC CSR reg */
-                       /* set ep values */
-                       tmp = readl(&dev->csr->ne[udc_csr_epix]);
-                       /* ep interface */
-                       tmp = AMD_ADDBITS(tmp, ep->dev->cur_intf,
-                                               UDC_CSR_NE_INTF);
-                       /* tmp = AMD_ADDBITS(tmp, 2, UDC_CSR_NE_INTF); */
-                       /* ep alt */
-                       tmp = AMD_ADDBITS(tmp, ep->dev->cur_alt,
-                                               UDC_CSR_NE_ALT);
-                       /* write reg */
-                       writel(tmp, &dev->csr->ne[udc_csr_epix]);
-
-                       /* clear stall bits */
-                       ep->halted = 0;
-                       tmp = readl(&ep->regs->ctl);
-                       tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S);
-                       writel(tmp, &ep->regs->ctl);
-               }
-
-               /* call gadget zero with setup data received */
-               spin_unlock(&dev->lock);
-               tmp = dev->driver->setup(&dev->gadget, &setup_data.request);
-               spin_lock(&dev->lock);
-
-       } /* USB reset */
-       if (dev_irq & AMD_BIT(UDC_DEVINT_UR)) {
-               DBG(dev, "USB Reset interrupt\n");
-               ret_val = IRQ_HANDLED;
-
-               /* allow soft reset when suspend occurs */
-               soft_reset_occured = 0;
-
-               dev->waiting_zlp_ack_ep0in = 0;
-               dev->set_cfg_not_acked = 0;
-
-               /* mask not needed interrupts */
-               udc_mask_unused_interrupts(dev);
-
-               /* call gadget to resume and reset configs etc. */
-               spin_unlock(&dev->lock);
-               if (dev->sys_suspended && dev->driver->resume) {
-                       dev->driver->resume(&dev->gadget);
-                       dev->sys_suspended = 0;
-               }
-               dev->driver->disconnect(&dev->gadget);
-               spin_lock(&dev->lock);
-
-               /* disable ep0 to empty req queue */
-               empty_req_queue(&dev->ep[UDC_EP0IN_IX]);
-               ep_init(dev->regs, &dev->ep[UDC_EP0IN_IX]);
-
-               /* soft reset when rxfifo not empty */
-               tmp = readl(&dev->regs->sts);
-               if (!(tmp & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY))
-                               && !soft_reset_after_usbreset_occured) {
-                       udc_soft_reset(dev);
-                       soft_reset_after_usbreset_occured++;
-               }
-
-               /*
-                * DMA reset to kill potential old DMA hw hang,
-                * POLL bit is already reset by ep_init() through
-                * disconnect()
-                */
-               DBG(dev, "DMA machine reset\n");
-               tmp = readl(&dev->regs->cfg);
-               writel(tmp | AMD_BIT(UDC_DEVCFG_DMARST), &dev->regs->cfg);
-               writel(tmp, &dev->regs->cfg);
-
-               /* put into initial config */
-               udc_basic_init(dev);
-
-               /* enable device setup interrupts */
-               udc_enable_dev_setup_interrupts(dev);
-
-               /* enable suspend interrupt */
-               tmp = readl(&dev->regs->irqmsk);
-               tmp &= AMD_UNMASK_BIT(UDC_DEVINT_US);
-               writel(tmp, &dev->regs->irqmsk);
-
-       } /* USB suspend */
-       if (dev_irq & AMD_BIT(UDC_DEVINT_US)) {
-               DBG(dev, "USB Suspend interrupt\n");
-               ret_val = IRQ_HANDLED;
-               if (dev->driver->suspend) {
-                       spin_unlock(&dev->lock);
-                       dev->sys_suspended = 1;
-                       dev->driver->suspend(&dev->gadget);
-                       spin_lock(&dev->lock);
-               }
-       } /* new speed ? */
-       if (dev_irq & AMD_BIT(UDC_DEVINT_ENUM)) {
-               DBG(dev, "ENUM interrupt\n");
-               ret_val = IRQ_HANDLED;
-               soft_reset_after_usbreset_occured = 0;
-
-               /* disable ep0 to empty req queue */
-               empty_req_queue(&dev->ep[UDC_EP0IN_IX]);
-               ep_init(dev->regs, &dev->ep[UDC_EP0IN_IX]);
-
-               /* link up all endpoints */
-               udc_setup_endpoints(dev);
-               dev_info(&dev->pdev->dev, "Connect: %s\n",
-                        usb_speed_string(dev->gadget.speed));
-
-               /* init ep 0 */
-               activate_control_endpoints(dev);
-
-               /* enable ep0 interrupts */
-               udc_enable_ep0_interrupts(dev);
-       }
-       /* session valid change interrupt */
-       if (dev_irq & AMD_BIT(UDC_DEVINT_SVC)) {
-               DBG(dev, "USB SVC interrupt\n");
-               ret_val = IRQ_HANDLED;
-
-               /* check that session is not valid to detect disconnect */
-               tmp = readl(&dev->regs->sts);
-               if (!(tmp & AMD_BIT(UDC_DEVSTS_SESSVLD))) {
-                       /* disable suspend interrupt */
-                       tmp = readl(&dev->regs->irqmsk);
-                       tmp |= AMD_BIT(UDC_DEVINT_US);
-                       writel(tmp, &dev->regs->irqmsk);
-                       DBG(dev, "USB Disconnect (session valid low)\n");
-                       /* cleanup on disconnect */
-                       usb_disconnect(udc);
-               }
-
-       }
-
-       return ret_val;
-}
-
-/* Interrupt Service Routine, see Linux Kernel Doc for parameters */
-static irqreturn_t udc_irq(int irq, void *pdev)
-{
-       struct udc *dev = pdev;
-       u32 reg;
-       u16 i;
-       u32 ep_irq;
-       irqreturn_t ret_val = IRQ_NONE;
-
-       spin_lock(&dev->lock);
-
-       /* check for ep irq */
-       reg = readl(&dev->regs->ep_irqsts);
-       if (reg) {
-               if (reg & AMD_BIT(UDC_EPINT_OUT_EP0))
-                       ret_val |= udc_control_out_isr(dev);
-               if (reg & AMD_BIT(UDC_EPINT_IN_EP0))
-                       ret_val |= udc_control_in_isr(dev);
-
-               /*
-                * data endpoint
-                * iterate ep's
-                */
-               for (i = 1; i < UDC_EP_NUM; i++) {
-                       ep_irq = 1 << i;
-                       if (!(reg & ep_irq) || i == UDC_EPINT_OUT_EP0)
-                               continue;
-
-                       /* clear irq status */
-                       writel(ep_irq, &dev->regs->ep_irqsts);
-
-                       /* irq for out ep ? */
-                       if (i > UDC_EPIN_NUM)
-                               ret_val |= udc_data_out_isr(dev, i);
-                       else
-                               ret_val |= udc_data_in_isr(dev, i);
-               }
-
-       }
-
-
-       /* check for dev irq */
-       reg = readl(&dev->regs->irqsts);
-       if (reg) {
-               /* clear irq */
-               writel(reg, &dev->regs->irqsts);
-               ret_val |= udc_dev_isr(dev, reg);
-       }
-
-
-       spin_unlock(&dev->lock);
-       return ret_val;
-}
-
-/* Tears down device */
-static void gadget_release(struct device *pdev)
-{
-       struct amd5536udc *dev = dev_get_drvdata(pdev);
-       kfree(dev);
-}
-
-/* Cleanup on device remove */
-static void udc_remove(struct udc *dev)
-{
-       /* remove timer */
-       stop_timer++;
-       if (timer_pending(&udc_timer))
-               wait_for_completion(&on_exit);
-       if (udc_timer.data)
-               del_timer_sync(&udc_timer);
-       /* remove pollstall timer */
-       stop_pollstall_timer++;
-       if (timer_pending(&udc_pollstall_timer))
-               wait_for_completion(&on_pollstall_exit);
-       if (udc_pollstall_timer.data)
-               del_timer_sync(&udc_pollstall_timer);
-       udc = NULL;
-}
-
-/* Reset all pci context */
-static void udc_pci_remove(struct pci_dev *pdev)
-{
-       struct udc              *dev;
-
-       dev = pci_get_drvdata(pdev);
-
-       usb_del_gadget_udc(&udc->gadget);
-       /* gadget driver must not be registered */
-       BUG_ON(dev->driver != NULL);
-
-       /* dma pool cleanup */
-       if (dev->data_requests)
-               pci_pool_destroy(dev->data_requests);
-
-       if (dev->stp_requests) {
-               /* cleanup DMA desc's for ep0in */
-               pci_pool_free(dev->stp_requests,
-                       dev->ep[UDC_EP0OUT_IX].td_stp,
-                       dev->ep[UDC_EP0OUT_IX].td_stp_dma);
-               pci_pool_free(dev->stp_requests,
-                       dev->ep[UDC_EP0OUT_IX].td,
-                       dev->ep[UDC_EP0OUT_IX].td_phys);
-
-               pci_pool_destroy(dev->stp_requests);
-       }
-
-       /* reset controller */
-       writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
-       if (dev->irq_registered)
-               free_irq(pdev->irq, dev);
-       if (dev->regs)
-               iounmap(dev->regs);
-       if (dev->mem_region)
-               release_mem_region(pci_resource_start(pdev, 0),
-                               pci_resource_len(pdev, 0));
-       if (dev->active)
-               pci_disable_device(pdev);
-
-       udc_remove(dev);
-}
-
-/* create dma pools on init */
-static int init_dma_pools(struct udc *dev)
-{
-       struct udc_stp_dma      *td_stp;
-       struct udc_data_dma     *td_data;
-       int retval;
-
-       /* consistent DMA mode setting ? */
-       if (use_dma_ppb) {
-               use_dma_bufferfill_mode = 0;
-       } else {
-               use_dma_ppb_du = 0;
-               use_dma_bufferfill_mode = 1;
-       }
-
-       /* DMA setup */
-       dev->data_requests = dma_pool_create("data_requests", NULL,
-               sizeof(struct udc_data_dma), 0, 0);
-       if (!dev->data_requests) {
-               DBG(dev, "can't get request data pool\n");
-               retval = -ENOMEM;
-               goto finished;
-       }
-
-       /* EP0 in dma regs = dev control regs */
-       dev->ep[UDC_EP0IN_IX].dma = &dev->regs->ctl;
-
-       /* dma desc for setup data */
-       dev->stp_requests = dma_pool_create("setup requests", NULL,
-               sizeof(struct udc_stp_dma), 0, 0);
-       if (!dev->stp_requests) {
-               DBG(dev, "can't get stp request pool\n");
-               retval = -ENOMEM;
-               goto finished;
-       }
-       /* setup */
-       td_stp = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
-                               &dev->ep[UDC_EP0OUT_IX].td_stp_dma);
-       if (td_stp == NULL) {
-               retval = -ENOMEM;
-               goto finished;
-       }
-       dev->ep[UDC_EP0OUT_IX].td_stp = td_stp;
-
-       /* data: 0 packets !? */
-       td_data = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
-                               &dev->ep[UDC_EP0OUT_IX].td_phys);
-       if (td_data == NULL) {
-               retval = -ENOMEM;
-               goto finished;
-       }
-       dev->ep[UDC_EP0OUT_IX].td = td_data;
-       return 0;
-
-finished:
-       return retval;
-}
-
-/* Called by pci bus driver to init pci context */
-static int udc_pci_probe(
-       struct pci_dev *pdev,
-       const struct pci_device_id *id
-)
-{
-       struct udc              *dev;
-       unsigned long           resource;
-       unsigned long           len;
-       int                     retval = 0;
-
-       /* one udc only */
-       if (udc) {
-               dev_dbg(&pdev->dev, "already probed\n");
-               return -EBUSY;
-       }
-
-       /* init */
-       dev = kzalloc(sizeof(struct udc), GFP_KERNEL);
-       if (!dev) {
-               retval = -ENOMEM;
-               goto finished;
-       }
-
-       /* pci setup */
-       if (pci_enable_device(pdev) < 0) {
-               kfree(dev);
-               dev = NULL;
-               retval = -ENODEV;
-               goto finished;
-       }
-       dev->active = 1;
-
-       /* PCI resource allocation */
-       resource = pci_resource_start(pdev, 0);
-       len = pci_resource_len(pdev, 0);
-
-       if (!request_mem_region(resource, len, name)) {
-               dev_dbg(&pdev->dev, "pci device used already\n");
-               kfree(dev);
-               dev = NULL;
-               retval = -EBUSY;
-               goto finished;
-       }
-       dev->mem_region = 1;
-
-       dev->virt_addr = ioremap_nocache(resource, len);
-       if (dev->virt_addr == NULL) {
-               dev_dbg(&pdev->dev, "start address cannot be mapped\n");
-               kfree(dev);
-               dev = NULL;
-               retval = -EFAULT;
-               goto finished;
-       }
-
-       if (!pdev->irq) {
-               dev_err(&pdev->dev, "irq not set\n");
-               kfree(dev);
-               dev = NULL;
-               retval = -ENODEV;
-               goto finished;
-       }
-
-       spin_lock_init(&dev->lock);
-       /* udc csr registers base */
-       dev->csr = dev->virt_addr + UDC_CSR_ADDR;
-       /* dev registers base */
-       dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR;
-       /* ep registers base */
-       dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR;
-       /* fifo's base */
-       dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR);
-       dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR);
-
-       if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
-               dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq);
-               kfree(dev);
-               dev = NULL;
-               retval = -EBUSY;
-               goto finished;
-       }
-       dev->irq_registered = 1;
-
-       pci_set_drvdata(pdev, dev);
-
-       /* chip revision for Hs AMD5536 */
-       dev->chiprev = pdev->revision;
-
-       pci_set_master(pdev);
-       pci_try_set_mwi(pdev);
-
-       /* init dma pools */
-       if (use_dma) {
-               retval = init_dma_pools(dev);
-               if (retval != 0)
-                       goto finished;
-       }
-
-       dev->phys_addr = resource;
-       dev->irq = pdev->irq;
-       dev->pdev = pdev;
-
-       /* general probing */
-       if (udc_probe(dev) == 0)
-               return 0;
-
-finished:
-       if (dev)
-               udc_pci_remove(pdev);
-       return retval;
-}
-
-/* general probe */
-static int udc_probe(struct udc *dev)
-{
-       char            tmp[128];
-       u32             reg;
-       int             retval;
-
-       /* mark timer as not initialized */
-       udc_timer.data = 0;
-       udc_pollstall_timer.data = 0;
-
-       /* device struct setup */
-       dev->gadget.ops = &udc_ops;
-
-       dev_set_name(&dev->gadget.dev, "gadget");
-       dev->gadget.name = name;
-       dev->gadget.max_speed = USB_SPEED_HIGH;
-
-       /* init registers, interrupts, ... */
-       startup_registers(dev);
-
-       dev_info(&dev->pdev->dev, "%s\n", mod_desc);
-
-       snprintf(tmp, sizeof tmp, "%d", dev->irq);
-       dev_info(&dev->pdev->dev,
-               "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
-               tmp, dev->phys_addr, dev->chiprev,
-               (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1");
-       strcpy(tmp, UDC_DRIVER_VERSION_STRING);
-       if (dev->chiprev == UDC_HSA0_REV) {
-               dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
-               retval = -ENODEV;
-               goto finished;
-       }
-       dev_info(&dev->pdev->dev,
-               "driver version: %s(for Geode5536 B1)\n", tmp);
-       udc = dev;
-
-       retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
-                       gadget_release);
-       if (retval)
-               goto finished;
-
-       /* timer init */
-       init_timer(&udc_timer);
-       udc_timer.function = udc_timer_function;
-       udc_timer.data = 1;
-       /* timer pollstall init */
-       init_timer(&udc_pollstall_timer);
-       udc_pollstall_timer.function = udc_pollstall_timer_function;
-       udc_pollstall_timer.data = 1;
-
-       /* set SD */
-       reg = readl(&dev->regs->ctl);
-       reg |= AMD_BIT(UDC_DEVCTL_SD);
-       writel(reg, &dev->regs->ctl);
-
-       /* print dev register info */
-       print_regs(dev);
-
-       return 0;
-
-finished:
-       return retval;
-}
-
-/* Initiates a remote wakeup */
-static int udc_remote_wakeup(struct udc *dev)
-{
-       unsigned long flags;
-       u32 tmp;
-
-       DBG(dev, "UDC initiates remote wakeup\n");
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       tmp = readl(&dev->regs->ctl);
-       tmp |= AMD_BIT(UDC_DEVCTL_RES);
-       writel(tmp, &dev->regs->ctl);
-       tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES);
-       writel(tmp, &dev->regs->ctl);
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-       return 0;
-}
-
-/* PCI device parameters */
-static const struct pci_device_id pci_id[] = {
-       {
-               PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096),
-               .class =        (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
-               .class_mask =   0xffffffff,
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(pci, pci_id);
-
-/* PCI functions */
-static struct pci_driver udc_pci_driver = {
-       .name =         (char *) name,
-       .id_table =     pci_id,
-       .probe =        udc_pci_probe,
-       .remove =       udc_pci_remove,
-};
-
-module_pci_driver(udc_pci_driver);
-
-MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION);
-MODULE_AUTHOR("Thomas Dahlmann");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/amd5536udc.h
deleted file mode 100644 (file)
index 6744d3b..0000000
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- * amd5536.h -- header for AMD 5536 UDC high/full speed USB device controller
- *
- * Copyright (C) 2007 AMD (http://www.amd.com)
- * Author: Thomas Dahlmann
- *
- * 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.
- */
-
-#ifndef AMD5536UDC_H
-#define AMD5536UDC_H
-
-/* various constants */
-#define UDC_RDE_TIMER_SECONDS          1
-#define UDC_RDE_TIMER_DIV              10
-#define UDC_POLLSTALL_TIMER_USECONDS   500
-
-/* Hs AMD5536 chip rev. */
-#define UDC_HSA0_REV 1
-#define UDC_HSB1_REV 2
-
-/*
- * SETUP usb commands
- * needed, because some SETUP's are handled in hw, but must be passed to
- * gadget driver above
- * SET_CONFIG
- */
-#define UDC_SETCONFIG_DWORD0                   0x00000900
-#define UDC_SETCONFIG_DWORD0_VALUE_MASK                0xffff0000
-#define UDC_SETCONFIG_DWORD0_VALUE_OFS         16
-
-#define UDC_SETCONFIG_DWORD1                   0x00000000
-
-/* SET_INTERFACE */
-#define UDC_SETINTF_DWORD0                     0x00000b00
-#define UDC_SETINTF_DWORD0_ALT_MASK            0xffff0000
-#define UDC_SETINTF_DWORD0_ALT_OFS             16
-
-#define UDC_SETINTF_DWORD1                     0x00000000
-#define UDC_SETINTF_DWORD1_INTF_MASK           0x0000ffff
-#define UDC_SETINTF_DWORD1_INTF_OFS            0
-
-/* Mass storage reset */
-#define UDC_MSCRES_DWORD0                      0x0000ff21
-#define UDC_MSCRES_DWORD1                      0x00000000
-
-/* Global CSR's -------------------------------------------------------------*/
-#define UDC_CSR_ADDR                           0x500
-
-/* EP NE bits */
-/* EP number */
-#define UDC_CSR_NE_NUM_MASK                    0x0000000f
-#define UDC_CSR_NE_NUM_OFS                     0
-/* EP direction */
-#define UDC_CSR_NE_DIR_MASK                    0x00000010
-#define UDC_CSR_NE_DIR_OFS                     4
-/* EP type */
-#define UDC_CSR_NE_TYPE_MASK                   0x00000060
-#define UDC_CSR_NE_TYPE_OFS                    5
-/* EP config number */
-#define UDC_CSR_NE_CFG_MASK                    0x00000780
-#define UDC_CSR_NE_CFG_OFS                     7
-/* EP interface number */
-#define UDC_CSR_NE_INTF_MASK                   0x00007800
-#define UDC_CSR_NE_INTF_OFS                    11
-/* EP alt setting */
-#define UDC_CSR_NE_ALT_MASK                    0x00078000
-#define UDC_CSR_NE_ALT_OFS                     15
-
-/* max pkt */
-#define UDC_CSR_NE_MAX_PKT_MASK                        0x3ff80000
-#define UDC_CSR_NE_MAX_PKT_OFS                 19
-
-/* Device Config Register ---------------------------------------------------*/
-#define UDC_DEVCFG_ADDR                                0x400
-
-#define UDC_DEVCFG_SOFTRESET                   31
-#define UDC_DEVCFG_HNPSFEN                     30
-#define UDC_DEVCFG_DMARST                      29
-#define UDC_DEVCFG_SET_DESC                    18
-#define UDC_DEVCFG_CSR_PRG                     17
-#define UDC_DEVCFG_STATUS                      7
-#define UDC_DEVCFG_DIR                         6
-#define UDC_DEVCFG_PI                          5
-#define UDC_DEVCFG_SS                          4
-#define UDC_DEVCFG_SP                          3
-#define UDC_DEVCFG_RWKP                                2
-
-#define UDC_DEVCFG_SPD_MASK                    0x3
-#define UDC_DEVCFG_SPD_OFS                     0
-#define UDC_DEVCFG_SPD_HS                      0x0
-#define UDC_DEVCFG_SPD_FS                      0x1
-#define UDC_DEVCFG_SPD_LS                      0x2
-/*#define UDC_DEVCFG_SPD_FS                    0x3*/
-
-
-/* Device Control Register --------------------------------------------------*/
-#define UDC_DEVCTL_ADDR                                0x404
-
-#define UDC_DEVCTL_THLEN_MASK                  0xff000000
-#define UDC_DEVCTL_THLEN_OFS                   24
-
-#define UDC_DEVCTL_BRLEN_MASK                  0x00ff0000
-#define UDC_DEVCTL_BRLEN_OFS                   16
-
-#define UDC_DEVCTL_CSR_DONE                    13
-#define UDC_DEVCTL_DEVNAK                      12
-#define UDC_DEVCTL_SD                          10
-#define UDC_DEVCTL_MODE                                9
-#define UDC_DEVCTL_BREN                                8
-#define UDC_DEVCTL_THE                         7
-#define UDC_DEVCTL_BF                          6
-#define UDC_DEVCTL_BE                          5
-#define UDC_DEVCTL_DU                          4
-#define UDC_DEVCTL_TDE                         3
-#define UDC_DEVCTL_RDE                         2
-#define UDC_DEVCTL_RES                         0
-
-
-/* Device Status Register ---------------------------------------------------*/
-#define UDC_DEVSTS_ADDR                                0x408
-
-#define UDC_DEVSTS_TS_MASK                     0xfffc0000
-#define UDC_DEVSTS_TS_OFS                      18
-
-#define UDC_DEVSTS_SESSVLD                     17
-#define UDC_DEVSTS_PHY_ERROR                   16
-#define UDC_DEVSTS_RXFIFO_EMPTY                        15
-
-#define UDC_DEVSTS_ENUM_SPEED_MASK             0x00006000
-#define UDC_DEVSTS_ENUM_SPEED_OFS              13
-#define UDC_DEVSTS_ENUM_SPEED_FULL             1
-#define UDC_DEVSTS_ENUM_SPEED_HIGH             0
-
-#define UDC_DEVSTS_SUSP                                12
-
-#define UDC_DEVSTS_ALT_MASK                    0x00000f00
-#define UDC_DEVSTS_ALT_OFS                     8
-
-#define UDC_DEVSTS_INTF_MASK                   0x000000f0
-#define UDC_DEVSTS_INTF_OFS                    4
-
-#define UDC_DEVSTS_CFG_MASK                    0x0000000f
-#define UDC_DEVSTS_CFG_OFS                     0
-
-
-/* Device Interrupt Register ------------------------------------------------*/
-#define UDC_DEVINT_ADDR                                0x40c
-
-#define UDC_DEVINT_SVC                         7
-#define UDC_DEVINT_ENUM                                6
-#define UDC_DEVINT_SOF                         5
-#define UDC_DEVINT_US                          4
-#define UDC_DEVINT_UR                          3
-#define UDC_DEVINT_ES                          2
-#define UDC_DEVINT_SI                          1
-#define UDC_DEVINT_SC                          0
-
-/* Device Interrupt Mask Register -------------------------------------------*/
-#define UDC_DEVINT_MSK_ADDR                    0x410
-
-#define UDC_DEVINT_MSK                         0x7f
-
-/* Endpoint Interrupt Register ----------------------------------------------*/
-#define UDC_EPINT_ADDR                         0x414
-
-#define UDC_EPINT_OUT_MASK                     0xffff0000
-#define UDC_EPINT_OUT_OFS                      16
-#define UDC_EPINT_IN_MASK                      0x0000ffff
-#define UDC_EPINT_IN_OFS                       0
-
-#define UDC_EPINT_IN_EP0                       0
-#define UDC_EPINT_IN_EP1                       1
-#define UDC_EPINT_IN_EP2                       2
-#define UDC_EPINT_IN_EP3                       3
-#define UDC_EPINT_OUT_EP0                      16
-#define UDC_EPINT_OUT_EP1                      17
-#define UDC_EPINT_OUT_EP2                      18
-#define UDC_EPINT_OUT_EP3                      19
-
-#define UDC_EPINT_EP0_ENABLE_MSK               0x001e001e
-
-/* Endpoint Interrupt Mask Register -----------------------------------------*/
-#define UDC_EPINT_MSK_ADDR                     0x418
-
-#define UDC_EPINT_OUT_MSK_MASK                 0xffff0000
-#define UDC_EPINT_OUT_MSK_OFS                  16
-#define UDC_EPINT_IN_MSK_MASK                  0x0000ffff
-#define UDC_EPINT_IN_MSK_OFS                   0
-
-#define UDC_EPINT_MSK_DISABLE_ALL              0xffffffff
-/* mask non-EP0 endpoints */
-#define UDC_EPDATAINT_MSK_DISABLE              0xfffefffe
-/* mask all dev interrupts */
-#define UDC_DEV_MSK_DISABLE                    0x7f
-
-/* Endpoint-specific CSR's --------------------------------------------------*/
-#define UDC_EPREGS_ADDR                                0x0
-#define UDC_EPIN_REGS_ADDR                     0x0
-#define UDC_EPOUT_REGS_ADDR                    0x200
-
-#define UDC_EPCTL_ADDR                         0x0
-
-#define UDC_EPCTL_RRDY                         9
-#define UDC_EPCTL_CNAK                         8
-#define UDC_EPCTL_SNAK                         7
-#define UDC_EPCTL_NAK                          6
-
-#define UDC_EPCTL_ET_MASK                      0x00000030
-#define UDC_EPCTL_ET_OFS                       4
-#define UDC_EPCTL_ET_CONTROL                   0
-#define UDC_EPCTL_ET_ISO                       1
-#define UDC_EPCTL_ET_BULK                      2
-#define UDC_EPCTL_ET_INTERRUPT                 3
-
-#define UDC_EPCTL_P                            3
-#define UDC_EPCTL_SN                           2
-#define UDC_EPCTL_F                            1
-#define UDC_EPCTL_S                            0
-
-/* Endpoint Status Registers ------------------------------------------------*/
-#define UDC_EPSTS_ADDR                         0x4
-
-#define UDC_EPSTS_RX_PKT_SIZE_MASK             0x007ff800
-#define UDC_EPSTS_RX_PKT_SIZE_OFS              11
-
-#define UDC_EPSTS_TDC                          10
-#define UDC_EPSTS_HE                           9
-#define UDC_EPSTS_BNA                          7
-#define UDC_EPSTS_IN                           6
-
-#define UDC_EPSTS_OUT_MASK                     0x00000030
-#define UDC_EPSTS_OUT_OFS                      4
-#define UDC_EPSTS_OUT_DATA                     1
-#define UDC_EPSTS_OUT_DATA_CLEAR               0x10
-#define UDC_EPSTS_OUT_SETUP                    2
-#define UDC_EPSTS_OUT_SETUP_CLEAR              0x20
-#define UDC_EPSTS_OUT_CLEAR                    0x30
-
-/* Endpoint Buffer Size IN/ Receive Packet Frame Number OUT Registers ------*/
-#define UDC_EPIN_BUFF_SIZE_ADDR                        0x8
-#define UDC_EPOUT_FRAME_NUMBER_ADDR            0x8
-
-#define UDC_EPIN_BUFF_SIZE_MASK                        0x0000ffff
-#define UDC_EPIN_BUFF_SIZE_OFS                 0
-/* EP0in txfifo = 128 bytes*/
-#define UDC_EPIN0_BUFF_SIZE                    32
-/* EP0in fullspeed txfifo = 128 bytes*/
-#define UDC_FS_EPIN0_BUFF_SIZE                 32
-
-/* fifo size mult = fifo size / max packet */
-#define UDC_EPIN_BUFF_SIZE_MULT                        2
-
-/* EPin data fifo size = 1024 bytes DOUBLE BUFFERING */
-#define UDC_EPIN_BUFF_SIZE                     256
-/* EPin small INT data fifo size = 128 bytes */
-#define UDC_EPIN_SMALLINT_BUFF_SIZE            32
-
-/* EPin fullspeed data fifo size = 128 bytes DOUBLE BUFFERING */
-#define UDC_FS_EPIN_BUFF_SIZE                  32
-
-#define UDC_EPOUT_FRAME_NUMBER_MASK            0x0000ffff
-#define UDC_EPOUT_FRAME_NUMBER_OFS             0
-
-/* Endpoint Buffer Size OUT/Max Packet Size Registers -----------------------*/
-#define UDC_EPOUT_BUFF_SIZE_ADDR               0x0c
-#define UDC_EP_MAX_PKT_SIZE_ADDR               0x0c
-
-#define UDC_EPOUT_BUFF_SIZE_MASK               0xffff0000
-#define UDC_EPOUT_BUFF_SIZE_OFS                        16
-#define UDC_EP_MAX_PKT_SIZE_MASK               0x0000ffff
-#define UDC_EP_MAX_PKT_SIZE_OFS                        0
-/* EP0in max packet size = 64 bytes */
-#define UDC_EP0IN_MAX_PKT_SIZE                 64
-/* EP0out max packet size = 64 bytes */
-#define UDC_EP0OUT_MAX_PKT_SIZE                        64
-/* EP0in fullspeed max packet size = 64 bytes */
-#define UDC_FS_EP0IN_MAX_PKT_SIZE              64
-/* EP0out fullspeed max packet size = 64 bytes */
-#define UDC_FS_EP0OUT_MAX_PKT_SIZE             64
-
-/*
- * Endpoint dma descriptors ------------------------------------------------
- *
- * Setup data, Status dword
- */
-#define UDC_DMA_STP_STS_CFG_MASK               0x0fff0000
-#define UDC_DMA_STP_STS_CFG_OFS                        16
-#define UDC_DMA_STP_STS_CFG_ALT_MASK           0x000f0000
-#define UDC_DMA_STP_STS_CFG_ALT_OFS            16
-#define UDC_DMA_STP_STS_CFG_INTF_MASK          0x00f00000
-#define UDC_DMA_STP_STS_CFG_INTF_OFS           20
-#define UDC_DMA_STP_STS_CFG_NUM_MASK           0x0f000000
-#define UDC_DMA_STP_STS_CFG_NUM_OFS            24
-#define UDC_DMA_STP_STS_RX_MASK                        0x30000000
-#define UDC_DMA_STP_STS_RX_OFS                 28
-#define UDC_DMA_STP_STS_BS_MASK                        0xc0000000
-#define UDC_DMA_STP_STS_BS_OFS                 30
-#define UDC_DMA_STP_STS_BS_HOST_READY          0
-#define UDC_DMA_STP_STS_BS_DMA_BUSY            1
-#define UDC_DMA_STP_STS_BS_DMA_DONE            2
-#define UDC_DMA_STP_STS_BS_HOST_BUSY           3
-/* IN data, Status dword */
-#define UDC_DMA_IN_STS_TXBYTES_MASK            0x0000ffff
-#define UDC_DMA_IN_STS_TXBYTES_OFS             0
-#define        UDC_DMA_IN_STS_FRAMENUM_MASK            0x07ff0000
-#define UDC_DMA_IN_STS_FRAMENUM_OFS            0
-#define UDC_DMA_IN_STS_L                       27
-#define UDC_DMA_IN_STS_TX_MASK                 0x30000000
-#define UDC_DMA_IN_STS_TX_OFS                  28
-#define UDC_DMA_IN_STS_BS_MASK                 0xc0000000
-#define UDC_DMA_IN_STS_BS_OFS                  30
-#define UDC_DMA_IN_STS_BS_HOST_READY           0
-#define UDC_DMA_IN_STS_BS_DMA_BUSY             1
-#define UDC_DMA_IN_STS_BS_DMA_DONE             2
-#define UDC_DMA_IN_STS_BS_HOST_BUSY            3
-/* OUT data, Status dword */
-#define UDC_DMA_OUT_STS_RXBYTES_MASK           0x0000ffff
-#define UDC_DMA_OUT_STS_RXBYTES_OFS            0
-#define UDC_DMA_OUT_STS_FRAMENUM_MASK          0x07ff0000
-#define UDC_DMA_OUT_STS_FRAMENUM_OFS           0
-#define UDC_DMA_OUT_STS_L                      27
-#define UDC_DMA_OUT_STS_RX_MASK                        0x30000000
-#define UDC_DMA_OUT_STS_RX_OFS                 28
-#define UDC_DMA_OUT_STS_BS_MASK                        0xc0000000
-#define UDC_DMA_OUT_STS_BS_OFS                 30
-#define UDC_DMA_OUT_STS_BS_HOST_READY          0
-#define UDC_DMA_OUT_STS_BS_DMA_BUSY            1
-#define UDC_DMA_OUT_STS_BS_DMA_DONE            2
-#define UDC_DMA_OUT_STS_BS_HOST_BUSY           3
-/* max ep0in packet */
-#define UDC_EP0IN_MAXPACKET                    1000
-/* max dma packet */
-#define UDC_DMA_MAXPACKET                      65536
-
-/* un-usable DMA address */
-#define DMA_DONT_USE                           (~(dma_addr_t) 0 )
-
-/* other Endpoint register addresses and values-----------------------------*/
-#define UDC_EP_SUBPTR_ADDR                     0x10
-#define UDC_EP_DESPTR_ADDR                     0x14
-#define UDC_EP_WRITE_CONFIRM_ADDR              0x1c
-
-/* EP number as layouted in AHB space */
-#define UDC_EP_NUM                             32
-#define UDC_EPIN_NUM                           16
-#define UDC_EPIN_NUM_USED                      5
-#define UDC_EPOUT_NUM                          16
-/* EP number of EP's really used = EP0 + 8 data EP's */
-#define UDC_USED_EP_NUM                                9
-/* UDC CSR regs are aligned but AHB regs not - offset for OUT EP's */
-#define UDC_CSR_EP_OUT_IX_OFS                  12
-
-#define UDC_EP0OUT_IX                          16
-#define UDC_EP0IN_IX                           0
-
-/* Rx fifo address and size = 1k -------------------------------------------*/
-#define UDC_RXFIFO_ADDR                                0x800
-#define UDC_RXFIFO_SIZE                                0x400
-
-/* Tx fifo address and size = 1.5k -----------------------------------------*/
-#define UDC_TXFIFO_ADDR                                0xc00
-#define UDC_TXFIFO_SIZE                                0x600
-
-/* default data endpoints --------------------------------------------------*/
-#define UDC_EPIN_STATUS_IX                     1
-#define UDC_EPIN_IX                            2
-#define UDC_EPOUT_IX                           18
-
-/* general constants -------------------------------------------------------*/
-#define UDC_DWORD_BYTES                                4
-#define UDC_BITS_PER_BYTE_SHIFT                        3
-#define UDC_BYTE_MASK                          0xff
-#define UDC_BITS_PER_BYTE                      8
-
-/*---------------------------------------------------------------------------*/
-/* UDC CSR's */
-struct udc_csrs {
-
-       /* sca - setup command address */
-       u32 sca;
-
-       /* ep ne's */
-       u32 ne[UDC_USED_EP_NUM];
-} __attribute__ ((packed));
-
-/* AHB subsystem CSR registers */
-struct udc_regs {
-
-       /* device configuration */
-       u32 cfg;
-
-       /* device control */
-       u32 ctl;
-
-       /* device status */
-       u32 sts;
-
-       /* device interrupt */
-       u32 irqsts;
-
-       /* device interrupt mask */
-       u32 irqmsk;
-
-       /* endpoint interrupt */
-       u32 ep_irqsts;
-
-       /* endpoint interrupt mask */
-       u32 ep_irqmsk;
-} __attribute__ ((packed));
-
-/* endpoint specific registers */
-struct udc_ep_regs {
-
-       /* endpoint control */
-       u32 ctl;
-
-       /* endpoint status */
-       u32 sts;
-
-       /* endpoint buffer size in/ receive packet frame number out */
-       u32 bufin_framenum;
-
-       /* endpoint buffer size out/max packet size */
-       u32 bufout_maxpkt;
-
-       /* endpoint setup buffer pointer */
-       u32 subptr;
-
-       /* endpoint data descriptor pointer */
-       u32 desptr;
-
-       /* reserverd */
-       u32 reserved;
-
-       /* write/read confirmation */
-       u32 confirm;
-
-} __attribute__ ((packed));
-
-/* control data DMA desc */
-struct udc_stp_dma {
-       /* status quadlet */
-       u32     status;
-       /* reserved */
-       u32     _reserved;
-       /* first setup word */
-       u32     data12;
-       /* second setup word */
-       u32     data34;
-} __attribute__ ((aligned (16)));
-
-/* normal data DMA desc */
-struct udc_data_dma {
-       /* status quadlet */
-       u32     status;
-       /* reserved */
-       u32     _reserved;
-       /* buffer pointer */
-       u32     bufptr;
-       /* next descriptor pointer */
-       u32     next;
-} __attribute__ ((aligned (16)));
-
-/* request packet */
-struct udc_request {
-       /* embedded gadget ep */
-       struct usb_request              req;
-
-       /* flags */
-       unsigned                        dma_going : 1,
-                                       dma_done : 1;
-       /* phys. address */
-       dma_addr_t                      td_phys;
-       /* first dma desc. of chain */
-       struct udc_data_dma             *td_data;
-       /* last dma desc. of chain */
-       struct udc_data_dma             *td_data_last;
-       struct list_head                queue;
-
-       /* chain length */
-       unsigned                        chain_len;
-
-};
-
-/* UDC specific endpoint parameters */
-struct udc_ep {
-       struct usb_ep                   ep;
-       struct udc_ep_regs __iomem      *regs;
-       u32 __iomem                     *txfifo;
-       u32 __iomem                     *dma;
-       dma_addr_t                      td_phys;
-       dma_addr_t                      td_stp_dma;
-       struct udc_stp_dma              *td_stp;
-       struct udc_data_dma             *td;
-       /* temp request */
-       struct udc_request              *req;
-       unsigned                        req_used;
-       unsigned                        req_completed;
-       /* dummy DMA desc for BNA dummy */
-       struct udc_request              *bna_dummy_req;
-       unsigned                        bna_occurred;
-
-       /* NAK state */
-       unsigned                        naking;
-
-       struct udc                      *dev;
-
-       /* queue for requests */
-       struct list_head                queue;
-       unsigned                        halted;
-       unsigned                        cancel_transfer;
-       unsigned                        num : 5,
-                                       fifo_depth : 14,
-                                       in : 1;
-};
-
-/* device struct */
-struct udc {
-       struct usb_gadget               gadget;
-       spinlock_t                      lock;   /* protects all state */
-       /* all endpoints */
-       struct udc_ep                   ep[UDC_EP_NUM];
-       struct usb_gadget_driver        *driver;
-       /* operational flags */
-       unsigned                        active : 1,
-                                       stall_ep0in : 1,
-                                       waiting_zlp_ack_ep0in : 1,
-                                       set_cfg_not_acked : 1,
-                                       irq_registered : 1,
-                                       data_ep_enabled : 1,
-                                       data_ep_queued : 1,
-                                       mem_region : 1,
-                                       sys_suspended : 1,
-                                       connected;
-
-       u16                             chiprev;
-
-       /* registers */
-       struct pci_dev                  *pdev;
-       struct udc_csrs __iomem         *csr;
-       struct udc_regs __iomem         *regs;
-       struct udc_ep_regs __iomem      *ep_regs;
-       u32 __iomem                     *rxfifo;
-       u32 __iomem                     *txfifo;
-
-       /* DMA desc pools */
-       struct pci_pool                 *data_requests;
-       struct pci_pool                 *stp_requests;
-
-       /* device data */
-       unsigned long                   phys_addr;
-       void __iomem                    *virt_addr;
-       unsigned                        irq;
-
-       /* states */
-       u16                             cur_config;
-       u16                             cur_intf;
-       u16                             cur_alt;
-};
-
-#define to_amd5536_udc(g)      (container_of((g), struct udc, gadget))
-
-/* setup request data */
-union udc_setup_data {
-       u32                     data[2];
-       struct usb_ctrlrequest  request;
-};
-
-/*
- *---------------------------------------------------------------------------
- * SET and GET bitfields in u32 values
- * via constants for mask/offset:
- * <bit_field_stub_name> is the text between
- * UDC_ and _MASK|_OFS of appropriate
- * constant
- *
- * set bitfield value in u32 u32Val
- */
-#define AMD_ADDBITS(u32Val, bitfield_val, bitfield_stub_name)          \
-       (((u32Val) & (((u32) ~((u32) bitfield_stub_name##_MASK))))      \
-       | (((bitfield_val) << ((u32) bitfield_stub_name##_OFS))         \
-               & ((u32) bitfield_stub_name##_MASK)))
-
-/*
- * set bitfield value in zero-initialized u32 u32Val
- * => bitfield bits in u32Val are all zero
- */
-#define AMD_INIT_SETBITS(u32Val, bitfield_val, bitfield_stub_name)     \
-       ((u32Val)                                                       \
-       | (((bitfield_val) << ((u32) bitfield_stub_name##_OFS))         \
-               & ((u32) bitfield_stub_name##_MASK)))
-
-/* get bitfield value from u32 u32Val */
-#define AMD_GETBITS(u32Val, bitfield_stub_name)                                \
-       ((u32Val & ((u32) bitfield_stub_name##_MASK))                   \
-               >> ((u32) bitfield_stub_name##_OFS))
-
-/* SET and GET bits in u32 values ------------------------------------------*/
-#define AMD_BIT(bit_stub_name) (1 << bit_stub_name)
-#define AMD_UNMASK_BIT(bit_stub_name) (~AMD_BIT(bit_stub_name))
-#define AMD_CLEAR_BIT(bit_stub_name) (~AMD_BIT(bit_stub_name))
-
-/* debug macros ------------------------------------------------------------*/
-
-#define DBG(udc , args...)     dev_dbg(&(udc)->pdev->dev, args)
-
-#ifdef UDC_VERBOSE
-#define VDBG                   DBG
-#else
-#define VDBG(udc , args...)    do {} while (0)
-#endif
-
-#endif /* #ifdef AMD5536UDC_H */
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
deleted file mode 100644 (file)
index cfd18bc..0000000
+++ /dev/null
@@ -1,1985 +0,0 @@
-/*
- * at91_udc -- driver for at91-series USB peripheral controller
- *
- * Copyright (C) 2004 by Thomas Rathbone
- * Copyright (C) 2005 by HP Labs
- * Copyright (C) 2005 by David Brownell
- *
- * 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.
- */
-
-#undef VERBOSE_DEBUG
-#undef PACKET_TRACE
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/prefetch.h>
-#include <linux/clk.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/platform_data/atmel.h>
-
-#include <asm/byteorder.h>
-#include <mach/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/gpio.h>
-
-#include <mach/cpu.h>
-#include <mach/at91sam9261_matrix.h>
-#include <mach/at91_matrix.h>
-
-#include "at91_udc.h"
-
-
-/*
- * This controller is simple and PIO-only.  It's used in many AT91-series
- * full speed USB controllers, including the at91rm9200 (arm920T, with MMU),
- * at91sam926x (arm926ejs, with MMU), and several no-mmu versions.
- *
- * This driver expects the board has been wired with two GPIOs supporting
- * a VBUS sensing IRQ, and a D+ pullup.  (They may be omitted, but the
- * testing hasn't covered such cases.)
- *
- * The pullup is most important (so it's integrated on sam926x parts).  It
- * provides software control over whether the host enumerates the device.
- *
- * The VBUS sensing helps during enumeration, and allows both USB clocks
- * (and the transceiver) to stay gated off until they're necessary, saving
- * power.  During USB suspend, the 48 MHz clock is gated off in hardware;
- * it may also be gated off by software during some Linux sleep states.
- */
-
-#define        DRIVER_VERSION  "3 May 2006"
-
-static const char driver_name [] = "at91_udc";
-static const char ep0name[] = "ep0";
-
-#define VBUS_POLL_TIMEOUT      msecs_to_jiffies(1000)
-
-#define at91_udp_read(udc, reg) \
-       __raw_readl((udc)->udp_baseaddr + (reg))
-#define at91_udp_write(udc, reg, val) \
-       __raw_writel((val), (udc)->udp_baseaddr + (reg))
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-
-#include <linux/seq_file.h>
-
-static const char debug_filename[] = "driver/udc";
-
-#define FOURBITS "%s%s%s%s"
-#define EIGHTBITS FOURBITS FOURBITS
-
-static void proc_ep_show(struct seq_file *s, struct at91_ep *ep)
-{
-       static char             *types[] = {
-               "control", "out-iso", "out-bulk", "out-int",
-               "BOGUS",   "in-iso",  "in-bulk",  "in-int"};
-
-       u32                     csr;
-       struct at91_request     *req;
-       unsigned long   flags;
-       struct at91_udc *udc = ep->udc;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       csr = __raw_readl(ep->creg);
-
-       /* NOTE:  not collecting per-endpoint irq statistics... */
-
-       seq_printf(s, "\n");
-       seq_printf(s, "%s, maxpacket %d %s%s %s%s\n",
-                       ep->ep.name, ep->ep.maxpacket,
-                       ep->is_in ? "in" : "out",
-                       ep->is_iso ? " iso" : "",
-                       ep->is_pingpong
-                               ? (ep->fifo_bank ? "pong" : "ping")
-                               : "",
-                       ep->stopped ? " stopped" : "");
-       seq_printf(s, "csr %08x rxbytes=%d %s %s %s" EIGHTBITS "\n",
-               csr,
-               (csr & 0x07ff0000) >> 16,
-               (csr & (1 << 15)) ? "enabled" : "disabled",
-               (csr & (1 << 11)) ? "DATA1" : "DATA0",
-               types[(csr & 0x700) >> 8],
-
-               /* iff type is control then print current direction */
-               (!(csr & 0x700))
-                       ? ((csr & (1 << 7)) ? " IN" : " OUT")
-                       : "",
-               (csr & (1 << 6)) ? " rxdatabk1" : "",
-               (csr & (1 << 5)) ? " forcestall" : "",
-               (csr & (1 << 4)) ? " txpktrdy" : "",
-
-               (csr & (1 << 3)) ? " stallsent" : "",
-               (csr & (1 << 2)) ? " rxsetup" : "",
-               (csr & (1 << 1)) ? " rxdatabk0" : "",
-               (csr & (1 << 0)) ? " txcomp" : "");
-       if (list_empty (&ep->queue))
-               seq_printf(s, "\t(queue empty)\n");
-
-       else list_for_each_entry (req, &ep->queue, queue) {
-               unsigned        length = req->req.actual;
-
-               seq_printf(s, "\treq %p len %d/%d buf %p\n",
-                               &req->req, length,
-                               req->req.length, req->req.buf);
-       }
-       spin_unlock_irqrestore(&udc->lock, flags);
-}
-
-static void proc_irq_show(struct seq_file *s, const char *label, u32 mask)
-{
-       int i;
-
-       seq_printf(s, "%s %04x:%s%s" FOURBITS, label, mask,
-               (mask & (1 << 13)) ? " wakeup" : "",
-               (mask & (1 << 12)) ? " endbusres" : "",
-
-               (mask & (1 << 11)) ? " sofint" : "",
-               (mask & (1 << 10)) ? " extrsm" : "",
-               (mask & (1 << 9)) ? " rxrsm" : "",
-               (mask & (1 << 8)) ? " rxsusp" : "");
-       for (i = 0; i < 8; i++) {
-               if (mask & (1 << i))
-                       seq_printf(s, " ep%d", i);
-       }
-       seq_printf(s, "\n");
-}
-
-static int proc_udc_show(struct seq_file *s, void *unused)
-{
-       struct at91_udc *udc = s->private;
-       struct at91_ep  *ep;
-       u32             tmp;
-
-       seq_printf(s, "%s: version %s\n", driver_name, DRIVER_VERSION);
-
-       seq_printf(s, "vbus %s, pullup %s, %s powered%s, gadget %s\n\n",
-               udc->vbus ? "present" : "off",
-               udc->enabled
-                       ? (udc->vbus ? "active" : "enabled")
-                       : "disabled",
-               udc->selfpowered ? "self" : "VBUS",
-               udc->suspended ? ", suspended" : "",
-               udc->driver ? udc->driver->driver.name : "(none)");
-
-       /* don't access registers when interface isn't clocked */
-       if (!udc->clocked) {
-               seq_printf(s, "(not clocked)\n");
-               return 0;
-       }
-
-       tmp = at91_udp_read(udc, AT91_UDP_FRM_NUM);
-       seq_printf(s, "frame %05x:%s%s frame=%d\n", tmp,
-               (tmp & AT91_UDP_FRM_OK) ? " ok" : "",
-               (tmp & AT91_UDP_FRM_ERR) ? " err" : "",
-               (tmp & AT91_UDP_NUM));
-
-       tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
-       seq_printf(s, "glbstate %02x:%s" FOURBITS "\n", tmp,
-               (tmp & AT91_UDP_RMWUPE) ? " rmwupe" : "",
-               (tmp & AT91_UDP_RSMINPR) ? " rsminpr" : "",
-               (tmp & AT91_UDP_ESR) ? " esr" : "",
-               (tmp & AT91_UDP_CONFG) ? " confg" : "",
-               (tmp & AT91_UDP_FADDEN) ? " fadden" : "");
-
-       tmp = at91_udp_read(udc, AT91_UDP_FADDR);
-       seq_printf(s, "faddr   %03x:%s fadd=%d\n", tmp,
-               (tmp & AT91_UDP_FEN) ? " fen" : "",
-               (tmp & AT91_UDP_FADD));
-
-       proc_irq_show(s, "imr   ", at91_udp_read(udc, AT91_UDP_IMR));
-       proc_irq_show(s, "isr   ", at91_udp_read(udc, AT91_UDP_ISR));
-
-       if (udc->enabled && udc->vbus) {
-               proc_ep_show(s, &udc->ep[0]);
-               list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) {
-                       if (ep->ep.desc)
-                               proc_ep_show(s, ep);
-               }
-       }
-       return 0;
-}
-
-static int proc_udc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, proc_udc_show, PDE_DATA(inode));
-}
-
-static const struct file_operations proc_ops = {
-       .owner          = THIS_MODULE,
-       .open           = proc_udc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static void create_debug_file(struct at91_udc *udc)
-{
-       udc->pde = proc_create_data(debug_filename, 0, NULL, &proc_ops, udc);
-}
-
-static void remove_debug_file(struct at91_udc *udc)
-{
-       if (udc->pde)
-               remove_proc_entry(debug_filename, NULL);
-}
-
-#else
-
-static inline void create_debug_file(struct at91_udc *udc) {}
-static inline void remove_debug_file(struct at91_udc *udc) {}
-
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-static void done(struct at91_ep *ep, struct at91_request *req, int status)
-{
-       unsigned        stopped = ep->stopped;
-       struct at91_udc *udc = ep->udc;
-
-       list_del_init(&req->queue);
-       if (req->req.status == -EINPROGRESS)
-               req->req.status = status;
-       else
-               status = req->req.status;
-       if (status && status != -ESHUTDOWN)
-               VDBG("%s done %p, status %d\n", ep->ep.name, req, status);
-
-       ep->stopped = 1;
-       spin_unlock(&udc->lock);
-       req->req.complete(&ep->ep, &req->req);
-       spin_lock(&udc->lock);
-       ep->stopped = stopped;
-
-       /* ep0 is always ready; other endpoints need a non-empty queue */
-       if (list_empty(&ep->queue) && ep->int_mask != (1 << 0))
-               at91_udp_write(udc, AT91_UDP_IDR, ep->int_mask);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* bits indicating OUT fifo has data ready */
-#define        RX_DATA_READY   (AT91_UDP_RX_DATA_BK0 | AT91_UDP_RX_DATA_BK1)
-
-/*
- * Endpoint FIFO CSR bits have a mix of bits, making it unsafe to just write
- * back most of the value you just read (because of side effects, including
- * bits that may change after reading and before writing).
- *
- * Except when changing a specific bit, always write values which:
- *  - clear SET_FX bits (setting them could change something)
- *  - set CLR_FX bits (clearing them could change something)
- *
- * There are also state bits like FORCESTALL, EPEDS, DIR, and EPTYPE
- * that shouldn't normally be changed.
- *
- * NOTE at91sam9260 docs mention synch between UDPCK and MCK clock domains,
- * implying a need to wait for one write to complete (test relevant bits)
- * before starting the next write.  This shouldn't be an issue given how
- * infrequently we write, except maybe for write-then-read idioms.
- */
-#define        SET_FX  (AT91_UDP_TXPKTRDY)
-#define        CLR_FX  (RX_DATA_READY | AT91_UDP_RXSETUP \
-               | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)
-
-/* pull OUT packet data from the endpoint's fifo */
-static int read_fifo (struct at91_ep *ep, struct at91_request *req)
-{
-       u32 __iomem     *creg = ep->creg;
-       u8 __iomem      *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
-       u32             csr;
-       u8              *buf;
-       unsigned int    count, bufferspace, is_done;
-
-       buf = req->req.buf + req->req.actual;
-       bufferspace = req->req.length - req->req.actual;
-
-       /*
-        * there might be nothing to read if ep_queue() calls us,
-        * or if we already emptied both pingpong buffers
-        */
-rescan:
-       csr = __raw_readl(creg);
-       if ((csr & RX_DATA_READY) == 0)
-               return 0;
-
-       count = (csr & AT91_UDP_RXBYTECNT) >> 16;
-       if (count > ep->ep.maxpacket)
-               count = ep->ep.maxpacket;
-       if (count > bufferspace) {
-               DBG("%s buffer overflow\n", ep->ep.name);
-               req->req.status = -EOVERFLOW;
-               count = bufferspace;
-       }
-       __raw_readsb(dreg, buf, count);
-
-       /* release and swap pingpong mem bank */
-       csr |= CLR_FX;
-       if (ep->is_pingpong) {
-               if (ep->fifo_bank == 0) {
-                       csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0);
-                       ep->fifo_bank = 1;
-               } else {
-                       csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK1);
-                       ep->fifo_bank = 0;
-               }
-       } else
-               csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0);
-       __raw_writel(csr, creg);
-
-       req->req.actual += count;
-       is_done = (count < ep->ep.maxpacket);
-       if (count == bufferspace)
-               is_done = 1;
-
-       PACKET("%s %p out/%d%s\n", ep->ep.name, &req->req, count,
-                       is_done ? " (done)" : "");
-
-       /*
-        * avoid extra trips through IRQ logic for packets already in
-        * the fifo ... maybe preventing an extra (expensive) OUT-NAK
-        */
-       if (is_done)
-               done(ep, req, 0);
-       else if (ep->is_pingpong) {
-               /*
-                * One dummy read to delay the code because of a HW glitch:
-                * CSR returns bad RXCOUNT when read too soon after updating
-                * RX_DATA_BK flags.
-                */
-               csr = __raw_readl(creg);
-
-               bufferspace -= count;
-               buf += count;
-               goto rescan;
-       }
-
-       return is_done;
-}
-
-/* load fifo for an IN packet */
-static int write_fifo(struct at91_ep *ep, struct at91_request *req)
-{
-       u32 __iomem     *creg = ep->creg;
-       u32             csr = __raw_readl(creg);
-       u8 __iomem      *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
-       unsigned        total, count, is_last;
-       u8              *buf;
-
-       /*
-        * TODO: allow for writing two packets to the fifo ... that'll
-        * reduce the amount of IN-NAKing, but probably won't affect
-        * throughput much.  (Unlike preventing OUT-NAKing!)
-        */
-
-       /*
-        * If ep_queue() calls us, the queue is empty and possibly in
-        * odd states like TXCOMP not yet cleared (we do it, saving at
-        * least one IRQ) or the fifo not yet being free.  Those aren't
-        * issues normally (IRQ handler fast path).
-        */
-       if (unlikely(csr & (AT91_UDP_TXCOMP | AT91_UDP_TXPKTRDY))) {
-               if (csr & AT91_UDP_TXCOMP) {
-                       csr |= CLR_FX;
-                       csr &= ~(SET_FX | AT91_UDP_TXCOMP);
-                       __raw_writel(csr, creg);
-                       csr = __raw_readl(creg);
-               }
-               if (csr & AT91_UDP_TXPKTRDY)
-                       return 0;
-       }
-
-       buf = req->req.buf + req->req.actual;
-       prefetch(buf);
-       total = req->req.length - req->req.actual;
-       if (ep->ep.maxpacket < total) {
-               count = ep->ep.maxpacket;
-               is_last = 0;
-       } else {
-               count = total;
-               is_last = (count < ep->ep.maxpacket) || !req->req.zero;
-       }
-
-       /*
-        * Write the packet, maybe it's a ZLP.
-        *
-        * NOTE:  incrementing req->actual before we receive the ACK means
-        * gadget driver IN bytecounts can be wrong in fault cases.  That's
-        * fixable with PIO drivers like this one (save "count" here, and
-        * do the increment later on TX irq), but not for most DMA hardware.
-        *
-        * So all gadget drivers must accept that potential error.  Some
-        * hardware supports precise fifo status reporting, letting them
-        * recover when the actual bytecount matters (e.g. for USB Test
-        * and Measurement Class devices).
-        */
-       __raw_writesb(dreg, buf, count);
-       csr &= ~SET_FX;
-       csr |= CLR_FX | AT91_UDP_TXPKTRDY;
-       __raw_writel(csr, creg);
-       req->req.actual += count;
-
-       PACKET("%s %p in/%d%s\n", ep->ep.name, &req->req, count,
-                       is_last ? " (done)" : "");
-       if (is_last)
-               done(ep, req, 0);
-       return is_last;
-}
-
-static void nuke(struct at91_ep *ep, int status)
-{
-       struct at91_request *req;
-
-       /* terminate any request in the queue */
-       ep->stopped = 1;
-       if (list_empty(&ep->queue))
-               return;
-
-       VDBG("%s %s\n", __func__, ep->ep.name);
-       while (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next, struct at91_request, queue);
-               done(ep, req, status);
-       }
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int at91_ep_enable(struct usb_ep *_ep,
-                               const struct usb_endpoint_descriptor *desc)
-{
-       struct at91_ep  *ep = container_of(_ep, struct at91_ep, ep);
-       struct at91_udc *udc;
-       u16             maxpacket;
-       u32             tmp;
-       unsigned long   flags;
-
-       if (!_ep || !ep
-                       || !desc || _ep->name == ep0name
-                       || desc->bDescriptorType != USB_DT_ENDPOINT
-                       || (maxpacket = usb_endpoint_maxp(desc)) == 0
-                       || maxpacket > ep->maxpacket) {
-               DBG("bad ep or descriptor\n");
-               return -EINVAL;
-       }
-
-       udc = ep->udc;
-       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
-               DBG("bogus device state\n");
-               return -ESHUTDOWN;
-       }
-
-       tmp = usb_endpoint_type(desc);
-       switch (tmp) {
-       case USB_ENDPOINT_XFER_CONTROL:
-               DBG("only one control endpoint\n");
-               return -EINVAL;
-       case USB_ENDPOINT_XFER_INT:
-               if (maxpacket > 64)
-                       goto bogus_max;
-               break;
-       case USB_ENDPOINT_XFER_BULK:
-               switch (maxpacket) {
-               case 8:
-               case 16:
-               case 32:
-               case 64:
-                       goto ok;
-               }
-bogus_max:
-               DBG("bogus maxpacket %d\n", maxpacket);
-               return -EINVAL;
-       case USB_ENDPOINT_XFER_ISOC:
-               if (!ep->is_pingpong) {
-                       DBG("iso requires double buffering\n");
-                       return -EINVAL;
-               }
-               break;
-       }
-
-ok:
-       spin_lock_irqsave(&udc->lock, flags);
-
-       /* initialize endpoint to match this descriptor */
-       ep->is_in = usb_endpoint_dir_in(desc);
-       ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC);
-       ep->stopped = 0;
-       if (ep->is_in)
-               tmp |= 0x04;
-       tmp <<= 8;
-       tmp |= AT91_UDP_EPEDS;
-       __raw_writel(tmp, ep->creg);
-
-       ep->ep.maxpacket = maxpacket;
-
-       /*
-        * reset/init endpoint fifo.  NOTE:  leaves fifo_bank alone,
-        * since endpoint resets don't reset hw pingpong state.
-        */
-       at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
-       at91_udp_write(udc, AT91_UDP_RST_EP, 0);
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return 0;
-}
-
-static int at91_ep_disable (struct usb_ep * _ep)
-{
-       struct at91_ep  *ep = container_of(_ep, struct at91_ep, ep);
-       struct at91_udc *udc = ep->udc;
-       unsigned long   flags;
-
-       if (ep == &ep->udc->ep[0])
-               return -EINVAL;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       nuke(ep, -ESHUTDOWN);
-
-       /* restore the endpoint's pristine config */
-       ep->ep.desc = NULL;
-       ep->ep.maxpacket = ep->maxpacket;
-
-       /* reset fifos and endpoint */
-       if (ep->udc->clocked) {
-               at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
-               at91_udp_write(udc, AT91_UDP_RST_EP, 0);
-               __raw_writel(0, ep->creg);
-       }
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return 0;
-}
-
-/*
- * this is a PIO-only driver, so there's nothing
- * interesting for request or buffer allocation.
- */
-
-static struct usb_request *
-at91_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
-{
-       struct at91_request *req;
-
-       req = kzalloc(sizeof (struct at91_request), gfp_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD(&req->queue);
-       return &req->req;
-}
-
-static void at91_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct at91_request *req;
-
-       req = container_of(_req, struct at91_request, req);
-       BUG_ON(!list_empty(&req->queue));
-       kfree(req);
-}
-
-static int at91_ep_queue(struct usb_ep *_ep,
-                       struct usb_request *_req, gfp_t gfp_flags)
-{
-       struct at91_request     *req;
-       struct at91_ep          *ep;
-       struct at91_udc         *udc;
-       int                     status;
-       unsigned long           flags;
-
-       req = container_of(_req, struct at91_request, req);
-       ep = container_of(_ep, struct at91_ep, ep);
-
-       if (!_req || !_req->complete
-                       || !_req->buf || !list_empty(&req->queue)) {
-               DBG("invalid request\n");
-               return -EINVAL;
-       }
-
-       if (!_ep || (!ep->ep.desc && ep->ep.name != ep0name)) {
-               DBG("invalid ep\n");
-               return -EINVAL;
-       }
-
-       udc = ep->udc;
-
-       if (!udc || !udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
-               DBG("invalid device\n");
-               return -EINVAL;
-       }
-
-       _req->status = -EINPROGRESS;
-       _req->actual = 0;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       /* try to kickstart any empty and idle queue */
-       if (list_empty(&ep->queue) && !ep->stopped) {
-               int     is_ep0;
-
-               /*
-                * If this control request has a non-empty DATA stage, this
-                * will start that stage.  It works just like a non-control
-                * request (until the status stage starts, maybe early).
-                *
-                * If the data stage is empty, then this starts a successful
-                * IN/STATUS stage.  (Unsuccessful ones use set_halt.)
-                */
-               is_ep0 = (ep->ep.name == ep0name);
-               if (is_ep0) {
-                       u32     tmp;
-
-                       if (!udc->req_pending) {
-                               status = -EINVAL;
-                               goto done;
-                       }
-
-                       /*
-                        * defer changing CONFG until after the gadget driver
-                        * reconfigures the endpoints.
-                        */
-                       if (udc->wait_for_config_ack) {
-                               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
-                               tmp ^= AT91_UDP_CONFG;
-                               VDBG("toggle config\n");
-                               at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
-                       }
-                       if (req->req.length == 0) {
-ep0_in_status:
-                               PACKET("ep0 in/status\n");
-                               status = 0;
-                               tmp = __raw_readl(ep->creg);
-                               tmp &= ~SET_FX;
-                               tmp |= CLR_FX | AT91_UDP_TXPKTRDY;
-                               __raw_writel(tmp, ep->creg);
-                               udc->req_pending = 0;
-                               goto done;
-                       }
-               }
-
-               if (ep->is_in)
-                       status = write_fifo(ep, req);
-               else {
-                       status = read_fifo(ep, req);
-
-                       /* IN/STATUS stage is otherwise triggered by irq */
-                       if (status && is_ep0)
-                               goto ep0_in_status;
-               }
-       } else
-               status = 0;
-
-       if (req && !status) {
-               list_add_tail (&req->queue, &ep->queue);
-               at91_udp_write(udc, AT91_UDP_IER, ep->int_mask);
-       }
-done:
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return (status < 0) ? status : 0;
-}
-
-static int at91_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct at91_ep          *ep;
-       struct at91_request     *req;
-       unsigned long           flags;
-       struct at91_udc         *udc;
-
-       ep = container_of(_ep, struct at91_ep, ep);
-       if (!_ep || ep->ep.name == ep0name)
-               return -EINVAL;
-
-       udc = ep->udc;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       /* make sure it's actually queued on this endpoint */
-       list_for_each_entry (req, &ep->queue, queue) {
-               if (&req->req == _req)
-                       break;
-       }
-       if (&req->req != _req) {
-               spin_unlock_irqrestore(&udc->lock, flags);
-               return -EINVAL;
-       }
-
-       done(ep, req, -ECONNRESET);
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return 0;
-}
-
-static int at91_ep_set_halt(struct usb_ep *_ep, int value)
-{
-       struct at91_ep  *ep = container_of(_ep, struct at91_ep, ep);
-       struct at91_udc *udc = ep->udc;
-       u32 __iomem     *creg;
-       u32             csr;
-       unsigned long   flags;
-       int             status = 0;
-
-       if (!_ep || ep->is_iso || !ep->udc->clocked)
-               return -EINVAL;
-
-       creg = ep->creg;
-       spin_lock_irqsave(&udc->lock, flags);
-
-       csr = __raw_readl(creg);
-
-       /*
-        * fail with still-busy IN endpoints, ensuring correct sequencing
-        * of data tx then stall.  note that the fifo rx bytecount isn't
-        * completely accurate as a tx bytecount.
-        */
-       if (ep->is_in && (!list_empty(&ep->queue) || (csr >> 16) != 0))
-               status = -EAGAIN;
-       else {
-               csr |= CLR_FX;
-               csr &= ~SET_FX;
-               if (value) {
-                       csr |= AT91_UDP_FORCESTALL;
-                       VDBG("halt %s\n", ep->ep.name);
-               } else {
-                       at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
-                       at91_udp_write(udc, AT91_UDP_RST_EP, 0);
-                       csr &= ~AT91_UDP_FORCESTALL;
-               }
-               __raw_writel(csr, creg);
-       }
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return status;
-}
-
-static const struct usb_ep_ops at91_ep_ops = {
-       .enable         = at91_ep_enable,
-       .disable        = at91_ep_disable,
-       .alloc_request  = at91_ep_alloc_request,
-       .free_request   = at91_ep_free_request,
-       .queue          = at91_ep_queue,
-       .dequeue        = at91_ep_dequeue,
-       .set_halt       = at91_ep_set_halt,
-       /* there's only imprecise fifo status reporting */
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int at91_get_frame(struct usb_gadget *gadget)
-{
-       struct at91_udc *udc = to_udc(gadget);
-
-       if (!to_udc(gadget)->clocked)
-               return -EINVAL;
-       return at91_udp_read(udc, AT91_UDP_FRM_NUM) & AT91_UDP_NUM;
-}
-
-static int at91_wakeup(struct usb_gadget *gadget)
-{
-       struct at91_udc *udc = to_udc(gadget);
-       u32             glbstate;
-       int             status = -EINVAL;
-       unsigned long   flags;
-
-       DBG("%s\n", __func__ );
-       spin_lock_irqsave(&udc->lock, flags);
-
-       if (!udc->clocked || !udc->suspended)
-               goto done;
-
-       /* NOTE:  some "early versions" handle ESR differently ... */
-
-       glbstate = at91_udp_read(udc, AT91_UDP_GLB_STAT);
-       if (!(glbstate & AT91_UDP_ESR))
-               goto done;
-       glbstate |= AT91_UDP_ESR;
-       at91_udp_write(udc, AT91_UDP_GLB_STAT, glbstate);
-
-done:
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return status;
-}
-
-/* reinit == restore initial software state */
-static void udc_reinit(struct at91_udc *udc)
-{
-       u32 i;
-
-       INIT_LIST_HEAD(&udc->gadget.ep_list);
-       INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
-
-       for (i = 0; i < NUM_ENDPOINTS; i++) {
-               struct at91_ep *ep = &udc->ep[i];
-
-               if (i != 0)
-                       list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
-               ep->ep.desc = NULL;
-               ep->stopped = 0;
-               ep->fifo_bank = 0;
-               usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
-               ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i);
-               /* initialize one queue per endpoint */
-               INIT_LIST_HEAD(&ep->queue);
-       }
-}
-
-static void stop_activity(struct at91_udc *udc)
-{
-       struct usb_gadget_driver *driver = udc->driver;
-       int i;
-
-       if (udc->gadget.speed == USB_SPEED_UNKNOWN)
-               driver = NULL;
-       udc->gadget.speed = USB_SPEED_UNKNOWN;
-       udc->suspended = 0;
-
-       for (i = 0; i < NUM_ENDPOINTS; i++) {
-               struct at91_ep *ep = &udc->ep[i];
-               ep->stopped = 1;
-               nuke(ep, -ESHUTDOWN);
-       }
-       if (driver) {
-               spin_unlock(&udc->lock);
-               driver->disconnect(&udc->gadget);
-               spin_lock(&udc->lock);
-       }
-
-       udc_reinit(udc);
-}
-
-static void clk_on(struct at91_udc *udc)
-{
-       if (udc->clocked)
-               return;
-       udc->clocked = 1;
-
-       if (IS_ENABLED(CONFIG_COMMON_CLK)) {
-               clk_set_rate(udc->uclk, 48000000);
-               clk_prepare_enable(udc->uclk);
-       }
-       clk_prepare_enable(udc->iclk);
-       clk_prepare_enable(udc->fclk);
-}
-
-static void clk_off(struct at91_udc *udc)
-{
-       if (!udc->clocked)
-               return;
-       udc->clocked = 0;
-       udc->gadget.speed = USB_SPEED_UNKNOWN;
-       clk_disable_unprepare(udc->fclk);
-       clk_disable_unprepare(udc->iclk);
-       if (IS_ENABLED(CONFIG_COMMON_CLK))
-               clk_disable_unprepare(udc->uclk);
-}
-
-/*
- * activate/deactivate link with host; minimize power usage for
- * inactive links by cutting clocks and transceiver power.
- */
-static void pullup(struct at91_udc *udc, int is_on)
-{
-       int     active = !udc->board.pullup_active_low;
-
-       if (!udc->enabled || !udc->vbus)
-               is_on = 0;
-       DBG("%sactive\n", is_on ? "" : "in");
-
-       if (is_on) {
-               clk_on(udc);
-               at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
-               at91_udp_write(udc, AT91_UDP_TXVC, 0);
-               if (cpu_is_at91rm9200())
-                       gpio_set_value(udc->board.pullup_pin, active);
-               else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
-                       u32     txvc = at91_udp_read(udc, AT91_UDP_TXVC);
-
-                       txvc |= AT91_UDP_TXVC_PUON;
-                       at91_udp_write(udc, AT91_UDP_TXVC, txvc);
-               } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
-                       u32     usbpucr;
-
-                       usbpucr = at91_matrix_read(AT91_MATRIX_USBPUCR);
-                       usbpucr |= AT91_MATRIX_USBPUCR_PUON;
-                       at91_matrix_write(AT91_MATRIX_USBPUCR, usbpucr);
-               }
-       } else {
-               stop_activity(udc);
-               at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
-               at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
-               if (cpu_is_at91rm9200())
-                       gpio_set_value(udc->board.pullup_pin, !active);
-               else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
-                       u32     txvc = at91_udp_read(udc, AT91_UDP_TXVC);
-
-                       txvc &= ~AT91_UDP_TXVC_PUON;
-                       at91_udp_write(udc, AT91_UDP_TXVC, txvc);
-               } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
-                       u32     usbpucr;
-
-                       usbpucr = at91_matrix_read(AT91_MATRIX_USBPUCR);
-                       usbpucr &= ~AT91_MATRIX_USBPUCR_PUON;
-                       at91_matrix_write(AT91_MATRIX_USBPUCR, usbpucr);
-               }
-               clk_off(udc);
-       }
-}
-
-/* vbus is here!  turn everything on that's ready */
-static int at91_vbus_session(struct usb_gadget *gadget, int is_active)
-{
-       struct at91_udc *udc = to_udc(gadget);
-       unsigned long   flags;
-
-       /* VDBG("vbus %s\n", is_active ? "on" : "off"); */
-       spin_lock_irqsave(&udc->lock, flags);
-       udc->vbus = (is_active != 0);
-       if (udc->driver)
-               pullup(udc, is_active);
-       else
-               pullup(udc, 0);
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return 0;
-}
-
-static int at91_pullup(struct usb_gadget *gadget, int is_on)
-{
-       struct at91_udc *udc = to_udc(gadget);
-       unsigned long   flags;
-
-       spin_lock_irqsave(&udc->lock, flags);
-       udc->enabled = is_on = !!is_on;
-       pullup(udc, is_on);
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return 0;
-}
-
-static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on)
-{
-       struct at91_udc *udc = to_udc(gadget);
-       unsigned long   flags;
-
-       spin_lock_irqsave(&udc->lock, flags);
-       udc->selfpowered = (is_on != 0);
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return 0;
-}
-
-static int at91_start(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver);
-static int at91_stop(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver);
-static const struct usb_gadget_ops at91_udc_ops = {
-       .get_frame              = at91_get_frame,
-       .wakeup                 = at91_wakeup,
-       .set_selfpowered        = at91_set_selfpowered,
-       .vbus_session           = at91_vbus_session,
-       .pullup                 = at91_pullup,
-       .udc_start              = at91_start,
-       .udc_stop               = at91_stop,
-
-       /*
-        * VBUS-powered devices may also also want to support bigger
-        * power budgets after an appropriate SET_CONFIGURATION.
-        */
-       /* .vbus_power          = at91_vbus_power, */
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int handle_ep(struct at91_ep *ep)
-{
-       struct at91_request     *req;
-       u32 __iomem             *creg = ep->creg;
-       u32                     csr = __raw_readl(creg);
-
-       if (!list_empty(&ep->queue))
-               req = list_entry(ep->queue.next,
-                       struct at91_request, queue);
-       else
-               req = NULL;
-
-       if (ep->is_in) {
-               if (csr & (AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)) {
-                       csr |= CLR_FX;
-                       csr &= ~(SET_FX | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP);
-                       __raw_writel(csr, creg);
-               }
-               if (req)
-                       return write_fifo(ep, req);
-
-       } else {
-               if (csr & AT91_UDP_STALLSENT) {
-                       /* STALLSENT bit == ISOERR */
-                       if (ep->is_iso && req)
-                               req->req.status = -EILSEQ;
-                       csr |= CLR_FX;
-                       csr &= ~(SET_FX | AT91_UDP_STALLSENT);
-                       __raw_writel(csr, creg);
-                       csr = __raw_readl(creg);
-               }
-               if (req && (csr & RX_DATA_READY))
-                       return read_fifo(ep, req);
-       }
-       return 0;
-}
-
-union setup {
-       u8                      raw[8];
-       struct usb_ctrlrequest  r;
-};
-
-static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
-{
-       u32 __iomem     *creg = ep->creg;
-       u8 __iomem      *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
-       unsigned        rxcount, i = 0;
-       u32             tmp;
-       union setup     pkt;
-       int             status = 0;
-
-       /* read and ack SETUP; hard-fail for bogus packets */
-       rxcount = (csr & AT91_UDP_RXBYTECNT) >> 16;
-       if (likely(rxcount == 8)) {
-               while (rxcount--)
-                       pkt.raw[i++] = __raw_readb(dreg);
-               if (pkt.r.bRequestType & USB_DIR_IN) {
-                       csr |= AT91_UDP_DIR;
-                       ep->is_in = 1;
-               } else {
-                       csr &= ~AT91_UDP_DIR;
-                       ep->is_in = 0;
-               }
-       } else {
-               /* REVISIT this happens sometimes under load; why?? */
-               ERR("SETUP len %d, csr %08x\n", rxcount, csr);
-               status = -EINVAL;
-       }
-       csr |= CLR_FX;
-       csr &= ~(SET_FX | AT91_UDP_RXSETUP);
-       __raw_writel(csr, creg);
-       udc->wait_for_addr_ack = 0;
-       udc->wait_for_config_ack = 0;
-       ep->stopped = 0;
-       if (unlikely(status != 0))
-               goto stall;
-
-#define w_index                le16_to_cpu(pkt.r.wIndex)
-#define w_value                le16_to_cpu(pkt.r.wValue)
-#define w_length       le16_to_cpu(pkt.r.wLength)
-
-       VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n",
-                       pkt.r.bRequestType, pkt.r.bRequest,
-                       w_value, w_index, w_length);
-
-       /*
-        * A few standard requests get handled here, ones that touch
-        * hardware ... notably for device and endpoint features.
-        */
-       udc->req_pending = 1;
-       csr = __raw_readl(creg);
-       csr |= CLR_FX;
-       csr &= ~SET_FX;
-       switch ((pkt.r.bRequestType << 8) | pkt.r.bRequest) {
-
-       case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
-                       | USB_REQ_SET_ADDRESS:
-               __raw_writel(csr | AT91_UDP_TXPKTRDY, creg);
-               udc->addr = w_value;
-               udc->wait_for_addr_ack = 1;
-               udc->req_pending = 0;
-               /* FADDR is set later, when we ack host STATUS */
-               return;
-
-       case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
-                       | USB_REQ_SET_CONFIGURATION:
-               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_CONFG;
-               if (pkt.r.wValue)
-                       udc->wait_for_config_ack = (tmp == 0);
-               else
-                       udc->wait_for_config_ack = (tmp != 0);
-               if (udc->wait_for_config_ack)
-                       VDBG("wait for config\n");
-               /* CONFG is toggled later, if gadget driver succeeds */
-               break;
-
-       /*
-        * Hosts may set or clear remote wakeup status, and
-        * devices may report they're VBUS powered.
-        */
-       case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
-                       | USB_REQ_GET_STATUS:
-               tmp = (udc->selfpowered << USB_DEVICE_SELF_POWERED);
-               if (at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_ESR)
-                       tmp |= (1 << USB_DEVICE_REMOTE_WAKEUP);
-               PACKET("get device status\n");
-               __raw_writeb(tmp, dreg);
-               __raw_writeb(0, dreg);
-               goto write_in;
-               /* then STATUS starts later, automatically */
-       case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
-                       | USB_REQ_SET_FEATURE:
-               if (w_value != USB_DEVICE_REMOTE_WAKEUP)
-                       goto stall;
-               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
-               tmp |= AT91_UDP_ESR;
-               at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
-               goto succeed;
-       case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
-                       | USB_REQ_CLEAR_FEATURE:
-               if (w_value != USB_DEVICE_REMOTE_WAKEUP)
-                       goto stall;
-               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
-               tmp &= ~AT91_UDP_ESR;
-               at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
-               goto succeed;
-
-       /*
-        * Interfaces have no feature settings; this is pretty useless.
-        * we won't even insist the interface exists...
-        */
-       case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8)
-                       | USB_REQ_GET_STATUS:
-               PACKET("get interface status\n");
-               __raw_writeb(0, dreg);
-               __raw_writeb(0, dreg);
-               goto write_in;
-               /* then STATUS starts later, automatically */
-       case ((USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8)
-                       | USB_REQ_SET_FEATURE:
-       case ((USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8)
-                       | USB_REQ_CLEAR_FEATURE:
-               goto stall;
-
-       /*
-        * Hosts may clear bulk/intr endpoint halt after the gadget
-        * driver sets it (not widely used); or set it (for testing)
-        */
-       case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8)
-                       | USB_REQ_GET_STATUS:
-               tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
-               ep = &udc->ep[tmp];
-               if (tmp >= NUM_ENDPOINTS || (tmp && !ep->ep.desc))
-                       goto stall;
-
-               if (tmp) {
-                       if ((w_index & USB_DIR_IN)) {
-                               if (!ep->is_in)
-                                       goto stall;
-                       } else if (ep->is_in)
-                               goto stall;
-               }
-               PACKET("get %s status\n", ep->ep.name);
-               if (__raw_readl(ep->creg) & AT91_UDP_FORCESTALL)
-                       tmp = (1 << USB_ENDPOINT_HALT);
-               else
-                       tmp = 0;
-               __raw_writeb(tmp, dreg);
-               __raw_writeb(0, dreg);
-               goto write_in;
-               /* then STATUS starts later, automatically */
-       case ((USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8)
-                       | USB_REQ_SET_FEATURE:
-               tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
-               ep = &udc->ep[tmp];
-               if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
-                       goto stall;
-               if (!ep->ep.desc || ep->is_iso)
-                       goto stall;
-               if ((w_index & USB_DIR_IN)) {
-                       if (!ep->is_in)
-                               goto stall;
-               } else if (ep->is_in)
-                       goto stall;
-
-               tmp = __raw_readl(ep->creg);
-               tmp &= ~SET_FX;
-               tmp |= CLR_FX | AT91_UDP_FORCESTALL;
-               __raw_writel(tmp, ep->creg);
-               goto succeed;
-       case ((USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8)
-                       | USB_REQ_CLEAR_FEATURE:
-               tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
-               ep = &udc->ep[tmp];
-               if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
-                       goto stall;
-               if (tmp == 0)
-                       goto succeed;
-               if (!ep->ep.desc || ep->is_iso)
-                       goto stall;
-               if ((w_index & USB_DIR_IN)) {
-                       if (!ep->is_in)
-                               goto stall;
-               } else if (ep->is_in)
-                       goto stall;
-
-               at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
-               at91_udp_write(udc, AT91_UDP_RST_EP, 0);
-               tmp = __raw_readl(ep->creg);
-               tmp |= CLR_FX;
-               tmp &= ~(SET_FX | AT91_UDP_FORCESTALL);
-               __raw_writel(tmp, ep->creg);
-               if (!list_empty(&ep->queue))
-                       handle_ep(ep);
-               goto succeed;
-       }
-
-#undef w_value
-#undef w_index
-#undef w_length
-
-       /* pass request up to the gadget driver */
-       if (udc->driver) {
-               spin_unlock(&udc->lock);
-               status = udc->driver->setup(&udc->gadget, &pkt.r);
-               spin_lock(&udc->lock);
-       }
-       else
-               status = -ENODEV;
-       if (status < 0) {
-stall:
-               VDBG("req %02x.%02x protocol STALL; stat %d\n",
-                               pkt.r.bRequestType, pkt.r.bRequest, status);
-               csr |= AT91_UDP_FORCESTALL;
-               __raw_writel(csr, creg);
-               udc->req_pending = 0;
-       }
-       return;
-
-succeed:
-       /* immediate successful (IN) STATUS after zero length DATA */
-       PACKET("ep0 in/status\n");
-write_in:
-       csr |= AT91_UDP_TXPKTRDY;
-       __raw_writel(csr, creg);
-       udc->req_pending = 0;
-}
-
-static void handle_ep0(struct at91_udc *udc)
-{
-       struct at91_ep          *ep0 = &udc->ep[0];
-       u32 __iomem             *creg = ep0->creg;
-       u32                     csr = __raw_readl(creg);
-       struct at91_request     *req;
-
-       if (unlikely(csr & AT91_UDP_STALLSENT)) {
-               nuke(ep0, -EPROTO);
-               udc->req_pending = 0;
-               csr |= CLR_FX;
-               csr &= ~(SET_FX | AT91_UDP_STALLSENT | AT91_UDP_FORCESTALL);
-               __raw_writel(csr, creg);
-               VDBG("ep0 stalled\n");
-               csr = __raw_readl(creg);
-       }
-       if (csr & AT91_UDP_RXSETUP) {
-               nuke(ep0, 0);
-               udc->req_pending = 0;
-               handle_setup(udc, ep0, csr);
-               return;
-       }
-
-       if (list_empty(&ep0->queue))
-               req = NULL;
-       else
-               req = list_entry(ep0->queue.next, struct at91_request, queue);
-
-       /* host ACKed an IN packet that we sent */
-       if (csr & AT91_UDP_TXCOMP) {
-               csr |= CLR_FX;
-               csr &= ~(SET_FX | AT91_UDP_TXCOMP);
-
-               /* write more IN DATA? */
-               if (req && ep0->is_in) {
-                       if (handle_ep(ep0))
-                               udc->req_pending = 0;
-
-               /*
-                * Ack after:
-                *  - last IN DATA packet (including GET_STATUS)
-                *  - IN/STATUS for OUT DATA
-                *  - IN/STATUS for any zero-length DATA stage
-                * except for the IN DATA case, the host should send
-                * an OUT status later, which we'll ack.
-                */
-               } else {
-                       udc->req_pending = 0;
-                       __raw_writel(csr, creg);
-
-                       /*
-                        * SET_ADDRESS takes effect only after the STATUS
-                        * (to the original address) gets acked.
-                        */
-                       if (udc->wait_for_addr_ack) {
-                               u32     tmp;
-
-                               at91_udp_write(udc, AT91_UDP_FADDR,
-                                               AT91_UDP_FEN | udc->addr);
-                               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
-                               tmp &= ~AT91_UDP_FADDEN;
-                               if (udc->addr)
-                                       tmp |= AT91_UDP_FADDEN;
-                               at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
-
-                               udc->wait_for_addr_ack = 0;
-                               VDBG("address %d\n", udc->addr);
-                       }
-               }
-       }
-
-       /* OUT packet arrived ... */
-       else if (csr & AT91_UDP_RX_DATA_BK0) {
-               csr |= CLR_FX;
-               csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0);
-
-               /* OUT DATA stage */
-               if (!ep0->is_in) {
-                       if (req) {
-                               if (handle_ep(ep0)) {
-                                       /* send IN/STATUS */
-                                       PACKET("ep0 in/status\n");
-                                       csr = __raw_readl(creg);
-                                       csr &= ~SET_FX;
-                                       csr |= CLR_FX | AT91_UDP_TXPKTRDY;
-                                       __raw_writel(csr, creg);
-                                       udc->req_pending = 0;
-                               }
-                       } else if (udc->req_pending) {
-                               /*
-                                * AT91 hardware has a hard time with this
-                                * "deferred response" mode for control-OUT
-                                * transfers.  (For control-IN it's fine.)
-                                *
-                                * The normal solution leaves OUT data in the
-                                * fifo until the gadget driver is ready.
-                                * We couldn't do that here without disabling
-                                * the IRQ that tells about SETUP packets,
-                                * e.g. when the host gets impatient...
-                                *
-                                * Working around it by copying into a buffer
-                                * would almost be a non-deferred response,
-                                * except that it wouldn't permit reliable
-                                * stalling of the request.  Instead, demand
-                                * that gadget drivers not use this mode.
-                                */
-                               DBG("no control-OUT deferred responses!\n");
-                               __raw_writel(csr | AT91_UDP_FORCESTALL, creg);
-                               udc->req_pending = 0;
-                       }
-
-               /* STATUS stage for control-IN; ack.  */
-               } else {
-                       PACKET("ep0 out/status ACK\n");
-                       __raw_writel(csr, creg);
-
-                       /* "early" status stage */
-                       if (req)
-                               done(ep0, req, 0);
-               }
-       }
-}
-
-static irqreturn_t at91_udc_irq (int irq, void *_udc)
-{
-       struct at91_udc         *udc = _udc;
-       u32                     rescans = 5;
-       int                     disable_clock = 0;
-       unsigned long           flags;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       if (!udc->clocked) {
-               clk_on(udc);
-               disable_clock = 1;
-       }
-
-       while (rescans--) {
-               u32 status;
-
-               status = at91_udp_read(udc, AT91_UDP_ISR)
-                       & at91_udp_read(udc, AT91_UDP_IMR);
-               if (!status)
-                       break;
-
-               /* USB reset irq:  not maskable */
-               if (status & AT91_UDP_ENDBUSRES) {
-                       at91_udp_write(udc, AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS);
-                       at91_udp_write(udc, AT91_UDP_IER, MINIMUS_INTERRUPTUS);
-                       /* Atmel code clears this irq twice */
-                       at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
-                       at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
-                       VDBG("end bus reset\n");
-                       udc->addr = 0;
-                       stop_activity(udc);
-
-                       /* enable ep0 */
-                       at91_udp_write(udc, AT91_UDP_CSR(0),
-                                       AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL);
-                       udc->gadget.speed = USB_SPEED_FULL;
-                       udc->suspended = 0;
-                       at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_EP(0));
-
-                       /*
-                        * NOTE:  this driver keeps clocks off unless the
-                        * USB host is present.  That saves power, but for
-                        * boards that don't support VBUS detection, both
-                        * clocks need to be active most of the time.
-                        */
-
-               /* host initiated suspend (3+ms bus idle) */
-               } else if (status & AT91_UDP_RXSUSP) {
-                       at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXSUSP);
-                       at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXRSM);
-                       at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXSUSP);
-                       /* VDBG("bus suspend\n"); */
-                       if (udc->suspended)
-                               continue;
-                       udc->suspended = 1;
-
-                       /*
-                        * NOTE:  when suspending a VBUS-powered device, the
-                        * gadget driver should switch into slow clock mode
-                        * and then into standby to avoid drawing more than
-                        * 500uA power (2500uA for some high-power configs).
-                        */
-                       if (udc->driver && udc->driver->suspend) {
-                               spin_unlock(&udc->lock);
-                               udc->driver->suspend(&udc->gadget);
-                               spin_lock(&udc->lock);
-                       }
-
-               /* host initiated resume */
-               } else if (status & AT91_UDP_RXRSM) {
-                       at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
-                       at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXSUSP);
-                       at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
-                       /* VDBG("bus resume\n"); */
-                       if (!udc->suspended)
-                               continue;
-                       udc->suspended = 0;
-
-                       /*
-                        * NOTE:  for a VBUS-powered device, the gadget driver
-                        * would normally want to switch out of slow clock
-                        * mode into normal mode.
-                        */
-                       if (udc->driver && udc->driver->resume) {
-                               spin_unlock(&udc->lock);
-                               udc->driver->resume(&udc->gadget);
-                               spin_lock(&udc->lock);
-                       }
-
-               /* endpoint IRQs are cleared by handling them */
-               } else {
-                       int             i;
-                       unsigned        mask = 1;
-                       struct at91_ep  *ep = &udc->ep[1];
-
-                       if (status & mask)
-                               handle_ep0(udc);
-                       for (i = 1; i < NUM_ENDPOINTS; i++) {
-                               mask <<= 1;
-                               if (status & mask)
-                                       handle_ep(ep);
-                               ep++;
-                       }
-               }
-       }
-
-       if (disable_clock)
-               clk_off(udc);
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return IRQ_HANDLED;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void nop_release(struct device *dev)
-{
-       /* nothing to free */
-}
-
-static struct at91_udc controller = {
-       .gadget = {
-               .ops    = &at91_udc_ops,
-               .ep0    = &controller.ep[0].ep,
-               .name   = driver_name,
-               .dev    = {
-                       .init_name = "gadget",
-                       .release = nop_release,
-               }
-       },
-       .ep[0] = {
-               .ep = {
-                       .name   = ep0name,
-                       .ops    = &at91_ep_ops,
-               },
-               .udc            = &controller,
-               .maxpacket      = 8,
-               .int_mask       = 1 << 0,
-       },
-       .ep[1] = {
-               .ep = {
-                       .name   = "ep1",
-                       .ops    = &at91_ep_ops,
-               },
-               .udc            = &controller,
-               .is_pingpong    = 1,
-               .maxpacket      = 64,
-               .int_mask       = 1 << 1,
-       },
-       .ep[2] = {
-               .ep = {
-                       .name   = "ep2",
-                       .ops    = &at91_ep_ops,
-               },
-               .udc            = &controller,
-               .is_pingpong    = 1,
-               .maxpacket      = 64,
-               .int_mask       = 1 << 2,
-       },
-       .ep[3] = {
-               .ep = {
-                       /* could actually do bulk too */
-                       .name   = "ep3-int",
-                       .ops    = &at91_ep_ops,
-               },
-               .udc            = &controller,
-               .maxpacket      = 8,
-               .int_mask       = 1 << 3,
-       },
-       .ep[4] = {
-               .ep = {
-                       .name   = "ep4",
-                       .ops    = &at91_ep_ops,
-               },
-               .udc            = &controller,
-               .is_pingpong    = 1,
-               .maxpacket      = 256,
-               .int_mask       = 1 << 4,
-       },
-       .ep[5] = {
-               .ep = {
-                       .name   = "ep5",
-                       .ops    = &at91_ep_ops,
-               },
-               .udc            = &controller,
-               .is_pingpong    = 1,
-               .maxpacket      = 256,
-               .int_mask       = 1 << 5,
-       },
-       /* ep6 and ep7 are also reserved (custom silicon might use them) */
-};
-
-static void at91_vbus_update(struct at91_udc *udc, unsigned value)
-{
-       value ^= udc->board.vbus_active_low;
-       if (value != udc->vbus)
-               at91_vbus_session(&udc->gadget, value);
-}
-
-static irqreturn_t at91_vbus_irq(int irq, void *_udc)
-{
-       struct at91_udc *udc = _udc;
-
-       /* vbus needs at least brief debouncing */
-       udelay(10);
-       at91_vbus_update(udc, gpio_get_value(udc->board.vbus_pin));
-
-       return IRQ_HANDLED;
-}
-
-static void at91_vbus_timer_work(struct work_struct *work)
-{
-       struct at91_udc *udc = container_of(work, struct at91_udc,
-                                           vbus_timer_work);
-
-       at91_vbus_update(udc, gpio_get_value_cansleep(udc->board.vbus_pin));
-
-       if (!timer_pending(&udc->vbus_timer))
-               mod_timer(&udc->vbus_timer, jiffies + VBUS_POLL_TIMEOUT);
-}
-
-static void at91_vbus_timer(unsigned long data)
-{
-       struct at91_udc *udc = (struct at91_udc *)data;
-
-       /*
-        * If we are polling vbus it is likely that the gpio is on an
-        * bus such as i2c or spi which may sleep, so schedule some work
-        * to read the vbus gpio
-        */
-       schedule_work(&udc->vbus_timer_work);
-}
-
-static int at91_start(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct at91_udc *udc;
-
-       udc = container_of(gadget, struct at91_udc, gadget);
-       udc->driver = driver;
-       udc->gadget.dev.of_node = udc->pdev->dev.of_node;
-       udc->enabled = 1;
-       udc->selfpowered = 1;
-
-       DBG("bound to %s\n", driver->driver.name);
-       return 0;
-}
-
-static int at91_stop(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct at91_udc *udc;
-       unsigned long   flags;
-
-       udc = container_of(gadget, struct at91_udc, gadget);
-       spin_lock_irqsave(&udc->lock, flags);
-       udc->enabled = 0;
-       at91_udp_write(udc, AT91_UDP_IDR, ~0);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       udc->driver = NULL;
-
-       DBG("unbound from %s\n", driver->driver.name);
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void at91udc_shutdown(struct platform_device *dev)
-{
-       struct at91_udc *udc = platform_get_drvdata(dev);
-       unsigned long   flags;
-
-       /* force disconnect on reboot */
-       spin_lock_irqsave(&udc->lock, flags);
-       pullup(platform_get_drvdata(dev), 0);
-       spin_unlock_irqrestore(&udc->lock, flags);
-}
-
-static void at91udc_of_init(struct at91_udc *udc,
-                                    struct device_node *np)
-{
-       struct at91_udc_data *board = &udc->board;
-       u32 val;
-       enum of_gpio_flags flags;
-
-       if (of_property_read_u32(np, "atmel,vbus-polled", &val) == 0)
-               board->vbus_polled = 1;
-
-       board->vbus_pin = of_get_named_gpio_flags(np, "atmel,vbus-gpio", 0,
-                                                 &flags);
-       board->vbus_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
-
-       board->pullup_pin = of_get_named_gpio_flags(np, "atmel,pullup-gpio", 0,
-                                                 &flags);
-
-       board->pullup_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
-}
-
-static int at91udc_probe(struct platform_device *pdev)
-{
-       struct device   *dev = &pdev->dev;
-       struct at91_udc *udc;
-       int             retval;
-       struct resource *res;
-
-       if (!dev_get_platdata(dev) && !pdev->dev.of_node) {
-               /* small (so we copy it) but critical! */
-               DBG("missing platform_data\n");
-               return -ENODEV;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENXIO;
-
-       if (!request_mem_region(res->start, resource_size(res), driver_name)) {
-               DBG("someone's using UDC memory\n");
-               return -EBUSY;
-       }
-
-       /* init software state */
-       udc = &controller;
-       udc->gadget.dev.parent = dev;
-       if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
-               at91udc_of_init(udc, pdev->dev.of_node);
-       else
-               memcpy(&udc->board, dev_get_platdata(dev),
-                      sizeof(struct at91_udc_data));
-       udc->pdev = pdev;
-       udc->enabled = 0;
-       spin_lock_init(&udc->lock);
-
-       /* rm9200 needs manual D+ pullup; off by default */
-       if (cpu_is_at91rm9200()) {
-               if (!gpio_is_valid(udc->board.pullup_pin)) {
-                       DBG("no D+ pullup?\n");
-                       retval = -ENODEV;
-                       goto fail0;
-               }
-               retval = gpio_request(udc->board.pullup_pin, "udc_pullup");
-               if (retval) {
-                       DBG("D+ pullup is busy\n");
-                       goto fail0;
-               }
-               gpio_direction_output(udc->board.pullup_pin,
-                               udc->board.pullup_active_low);
-       }
-
-       /* newer chips have more FIFO memory than rm9200 */
-       if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) {
-               udc->ep[0].maxpacket = 64;
-               udc->ep[3].maxpacket = 64;
-               udc->ep[4].maxpacket = 512;
-               udc->ep[5].maxpacket = 512;
-       } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
-               udc->ep[3].maxpacket = 64;
-       } else if (cpu_is_at91sam9263()) {
-               udc->ep[0].maxpacket = 64;
-               udc->ep[3].maxpacket = 64;
-       }
-
-       udc->udp_baseaddr = ioremap(res->start, resource_size(res));
-       if (!udc->udp_baseaddr) {
-               retval = -ENOMEM;
-               goto fail0a;
-       }
-
-       udc_reinit(udc);
-
-       /* get interface and function clocks */
-       udc->iclk = clk_get(dev, "udc_clk");
-       udc->fclk = clk_get(dev, "udpck");
-       if (IS_ENABLED(CONFIG_COMMON_CLK))
-               udc->uclk = clk_get(dev, "usb_clk");
-       if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk) ||
-           (IS_ENABLED(CONFIG_COMMON_CLK) && IS_ERR(udc->uclk))) {
-               DBG("clocks missing\n");
-               retval = -ENODEV;
-               goto fail1;
-       }
-
-       /* don't do anything until we have both gadget driver and VBUS */
-       retval = clk_prepare_enable(udc->iclk);
-       if (retval)
-               goto fail1;
-       at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
-       at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
-       /* Clear all pending interrupts - UDP may be used by bootloader. */
-       at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff);
-       clk_disable_unprepare(udc->iclk);
-
-       /* request UDC and maybe VBUS irqs */
-       udc->udp_irq = platform_get_irq(pdev, 0);
-       retval = request_irq(udc->udp_irq, at91_udc_irq,
-                       0, driver_name, udc);
-       if (retval < 0) {
-               DBG("request irq %d failed\n", udc->udp_irq);
-               goto fail1;
-       }
-       if (gpio_is_valid(udc->board.vbus_pin)) {
-               retval = gpio_request(udc->board.vbus_pin, "udc_vbus");
-               if (retval < 0) {
-                       DBG("request vbus pin failed\n");
-                       goto fail2;
-               }
-               gpio_direction_input(udc->board.vbus_pin);
-
-               /*
-                * Get the initial state of VBUS - we cannot expect
-                * a pending interrupt.
-                */
-               udc->vbus = gpio_get_value_cansleep(udc->board.vbus_pin) ^
-                       udc->board.vbus_active_low;
-
-               if (udc->board.vbus_polled) {
-                       INIT_WORK(&udc->vbus_timer_work, at91_vbus_timer_work);
-                       setup_timer(&udc->vbus_timer, at91_vbus_timer,
-                                   (unsigned long)udc);
-                       mod_timer(&udc->vbus_timer,
-                                 jiffies + VBUS_POLL_TIMEOUT);
-               } else {
-                       if (request_irq(gpio_to_irq(udc->board.vbus_pin),
-                                       at91_vbus_irq, 0, driver_name, udc)) {
-                               DBG("request vbus irq %d failed\n",
-                                   udc->board.vbus_pin);
-                               retval = -EBUSY;
-                               goto fail3;
-                       }
-               }
-       } else {
-               DBG("no VBUS detection, assuming always-on\n");
-               udc->vbus = 1;
-       }
-       retval = usb_add_gadget_udc(dev, &udc->gadget);
-       if (retval)
-               goto fail4;
-       dev_set_drvdata(dev, udc);
-       device_init_wakeup(dev, 1);
-       create_debug_file(udc);
-
-       INFO("%s version %s\n", driver_name, DRIVER_VERSION);
-       return 0;
-fail4:
-       if (gpio_is_valid(udc->board.vbus_pin) && !udc->board.vbus_polled)
-               free_irq(gpio_to_irq(udc->board.vbus_pin), udc);
-fail3:
-       if (gpio_is_valid(udc->board.vbus_pin))
-               gpio_free(udc->board.vbus_pin);
-fail2:
-       free_irq(udc->udp_irq, udc);
-fail1:
-       if (IS_ENABLED(CONFIG_COMMON_CLK) && !IS_ERR(udc->uclk))
-               clk_put(udc->uclk);
-       if (!IS_ERR(udc->fclk))
-               clk_put(udc->fclk);
-       if (!IS_ERR(udc->iclk))
-               clk_put(udc->iclk);
-       iounmap(udc->udp_baseaddr);
-fail0a:
-       if (cpu_is_at91rm9200())
-               gpio_free(udc->board.pullup_pin);
-fail0:
-       release_mem_region(res->start, resource_size(res));
-       DBG("%s probe failed, %d\n", driver_name, retval);
-       return retval;
-}
-
-static int __exit at91udc_remove(struct platform_device *pdev)
-{
-       struct at91_udc *udc = platform_get_drvdata(pdev);
-       struct resource *res;
-       unsigned long   flags;
-
-       DBG("remove\n");
-
-       usb_del_gadget_udc(&udc->gadget);
-       if (udc->driver)
-               return -EBUSY;
-
-       spin_lock_irqsave(&udc->lock, flags);
-       pullup(udc, 0);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       device_init_wakeup(&pdev->dev, 0);
-       remove_debug_file(udc);
-       if (gpio_is_valid(udc->board.vbus_pin)) {
-               free_irq(gpio_to_irq(udc->board.vbus_pin), udc);
-               gpio_free(udc->board.vbus_pin);
-       }
-       free_irq(udc->udp_irq, udc);
-       iounmap(udc->udp_baseaddr);
-
-       if (cpu_is_at91rm9200())
-               gpio_free(udc->board.pullup_pin);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, resource_size(res));
-
-       clk_put(udc->iclk);
-       clk_put(udc->fclk);
-       if (IS_ENABLED(CONFIG_COMMON_CLK))
-               clk_put(udc->uclk);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-       struct at91_udc *udc = platform_get_drvdata(pdev);
-       int             wake = udc->driver && device_may_wakeup(&pdev->dev);
-       unsigned long   flags;
-
-       /* Unless we can act normally to the host (letting it wake us up
-        * whenever it has work for us) force disconnect.  Wakeup requires
-        * PLLB for USB events (signaling for reset, wakeup, or incoming
-        * tokens) and VBUS irqs (on systems which support them).
-        */
-       if ((!udc->suspended && udc->addr)
-                       || !wake
-                       || at91_suspend_entering_slow_clock()) {
-               spin_lock_irqsave(&udc->lock, flags);
-               pullup(udc, 0);
-               wake = 0;
-               spin_unlock_irqrestore(&udc->lock, flags);
-       } else
-               enable_irq_wake(udc->udp_irq);
-
-       udc->active_suspend = wake;
-       if (gpio_is_valid(udc->board.vbus_pin) && !udc->board.vbus_polled && wake)
-               enable_irq_wake(udc->board.vbus_pin);
-       return 0;
-}
-
-static int at91udc_resume(struct platform_device *pdev)
-{
-       struct at91_udc *udc = platform_get_drvdata(pdev);
-       unsigned long   flags;
-
-       if (gpio_is_valid(udc->board.vbus_pin) && !udc->board.vbus_polled &&
-           udc->active_suspend)
-               disable_irq_wake(udc->board.vbus_pin);
-
-       /* maybe reconnect to host; if so, clocks on */
-       if (udc->active_suspend)
-               disable_irq_wake(udc->udp_irq);
-       else {
-               spin_lock_irqsave(&udc->lock, flags);
-               pullup(udc, 1);
-               spin_unlock_irqrestore(&udc->lock, flags);
-       }
-       return 0;
-}
-#else
-#define        at91udc_suspend NULL
-#define        at91udc_resume  NULL
-#endif
-
-#if defined(CONFIG_OF)
-static const struct of_device_id at91_udc_dt_ids[] = {
-       { .compatible = "atmel,at91rm9200-udc" },
-       { /* sentinel */ }
-};
-
-MODULE_DEVICE_TABLE(of, at91_udc_dt_ids);
-#endif
-
-static struct platform_driver at91_udc_driver = {
-       .remove         = __exit_p(at91udc_remove),
-       .shutdown       = at91udc_shutdown,
-       .suspend        = at91udc_suspend,
-       .resume         = at91udc_resume,
-       .driver         = {
-               .name   = (char *) driver_name,
-               .owner  = THIS_MODULE,
-               .of_match_table = of_match_ptr(at91_udc_dt_ids),
-       },
-};
-
-module_platform_driver_probe(at91_udc_driver, at91udc_probe);
-
-MODULE_DESCRIPTION("AT91 udc driver");
-MODULE_AUTHOR("Thomas Rathbone, David Brownell");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:at91_udc");
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
deleted file mode 100644 (file)
index 0175246..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2004 by Thomas Rathbone, HP Labs
- * Copyright (C) 2005 by Ivan Kokshaysky
- * Copyright (C) 2006 by SAN People
- *
- * 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.
- */
-
-#ifndef AT91_UDC_H
-#define AT91_UDC_H
-
-/*
- * USB Device Port (UDP) registers.
- * Based on AT91RM9200 datasheet revision E.
- */
-
-#define AT91_UDP_FRM_NUM       0x00            /* Frame Number Register */
-#define     AT91_UDP_NUM       (0x7ff <<  0)   /* Frame Number */
-#define     AT91_UDP_FRM_ERR   (1     << 16)   /* Frame Error */
-#define     AT91_UDP_FRM_OK    (1     << 17)   /* Frame OK */
-
-#define AT91_UDP_GLB_STAT      0x04            /* Global State Register */
-#define     AT91_UDP_FADDEN    (1 <<  0)       /* Function Address Enable */
-#define     AT91_UDP_CONFG     (1 <<  1)       /* Configured */
-#define     AT91_UDP_ESR       (1 <<  2)       /* Enable Send Resume */
-#define     AT91_UDP_RSMINPR   (1 <<  3)       /* Resume has been sent */
-#define     AT91_UDP_RMWUPE    (1 <<  4)       /* Remote Wake Up Enable */
-
-#define AT91_UDP_FADDR         0x08            /* Function Address Register */
-#define     AT91_UDP_FADD      (0x7f << 0)     /* Function Address Value */
-#define     AT91_UDP_FEN       (1    << 8)     /* Function Enable */
-
-#define AT91_UDP_IER           0x10            /* Interrupt Enable Register */
-#define AT91_UDP_IDR           0x14            /* Interrupt Disable Register */
-#define AT91_UDP_IMR           0x18            /* Interrupt Mask Register */
-
-#define AT91_UDP_ISR           0x1c            /* Interrupt Status Register */
-#define     AT91_UDP_EP(n)     (1 << (n))      /* Endpoint Interrupt Status */
-#define     AT91_UDP_RXSUSP    (1 <<  8)       /* USB Suspend Interrupt Status */
-#define     AT91_UDP_RXRSM     (1 <<  9)       /* USB Resume Interrupt Status */
-#define     AT91_UDP_EXTRSM    (1 << 10)       /* External Resume Interrupt Status [AT91RM9200 only] */
-#define     AT91_UDP_SOFINT    (1 << 11)       /* Start of Frame Interrupt Status */
-#define     AT91_UDP_ENDBUSRES (1 << 12)       /* End of Bus Reset Interrupt Status */
-#define     AT91_UDP_WAKEUP    (1 << 13)       /* USB Wakeup Interrupt Status [AT91RM9200 only] */
-
-#define AT91_UDP_ICR           0x20            /* Interrupt Clear Register */
-#define AT91_UDP_RST_EP                0x28            /* Reset Endpoint Register */
-
-#define AT91_UDP_CSR(n)                (0x30+((n)*4))  /* Endpoint Control/Status Registers 0-7 */
-#define     AT91_UDP_TXCOMP    (1 <<  0)       /* Generates IN packet with data previously written in DPR */
-#define     AT91_UDP_RX_DATA_BK0 (1 <<  1)     /* Receive Data Bank 0 */
-#define     AT91_UDP_RXSETUP   (1 <<  2)       /* Send STALL to the host */
-#define     AT91_UDP_STALLSENT (1 <<  3)       /* Stall Sent / Isochronous error (Isochronous endpoints) */
-#define     AT91_UDP_TXPKTRDY  (1 <<  4)       /* Transmit Packet Ready */
-#define     AT91_UDP_FORCESTALL        (1 <<  5)       /* Force Stall */
-#define     AT91_UDP_RX_DATA_BK1 (1 <<  6)     /* Receive Data Bank 1 */
-#define     AT91_UDP_DIR       (1 <<  7)       /* Transfer Direction */
-#define     AT91_UDP_EPTYPE    (7 <<  8)       /* Endpoint Type */
-#define                AT91_UDP_EPTYPE_CTRL            (0 <<  8)
-#define                AT91_UDP_EPTYPE_ISO_OUT         (1 <<  8)
-#define                AT91_UDP_EPTYPE_BULK_OUT        (2 <<  8)
-#define                AT91_UDP_EPTYPE_INT_OUT         (3 <<  8)
-#define                AT91_UDP_EPTYPE_ISO_IN          (5 <<  8)
-#define                AT91_UDP_EPTYPE_BULK_IN         (6 <<  8)
-#define                AT91_UDP_EPTYPE_INT_IN          (7 <<  8)
-#define     AT91_UDP_DTGLE     (1 << 11)       /* Data Toggle */
-#define     AT91_UDP_EPEDS     (1 << 15)       /* Endpoint Enable/Disable */
-#define     AT91_UDP_RXBYTECNT (0x7ff << 16)   /* Number of bytes in FIFO */
-
-#define AT91_UDP_FDR(n)                (0x50+((n)*4))  /* Endpoint FIFO Data Registers 0-7 */
-
-#define AT91_UDP_TXVC          0x74            /* Transceiver Control Register */
-#define     AT91_UDP_TXVC_TXVDIS (1 << 8)      /* Transceiver Disable */
-#define     AT91_UDP_TXVC_PUON   (1 << 9)      /* PullUp On [AT91SAM9260 only] */
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * controller driver data structures
- */
-
-#define        NUM_ENDPOINTS   6
-
-/*
- * hardware won't disable bus reset, or resume while the controller
- * is suspended ... watching suspend helps keep the logic symmetric.
- */
-#define        MINIMUS_INTERRUPTUS \
-       (AT91_UDP_ENDBUSRES | AT91_UDP_RXRSM | AT91_UDP_RXSUSP)
-
-struct at91_ep {
-       struct usb_ep                   ep;
-       struct list_head                queue;
-       struct at91_udc                 *udc;
-       void __iomem                    *creg;
-
-       unsigned                        maxpacket:16;
-       u8                              int_mask;
-       unsigned                        is_pingpong:1;
-
-       unsigned                        stopped:1;
-       unsigned                        is_in:1;
-       unsigned                        is_iso:1;
-       unsigned                        fifo_bank:1;
-};
-
-/*
- * driver is non-SMP, and just blocks IRQs whenever it needs
- * access protection for chip registers or driver state
- */
-struct at91_udc {
-       struct usb_gadget               gadget;
-       struct at91_ep                  ep[NUM_ENDPOINTS];
-       struct usb_gadget_driver        *driver;
-       unsigned                        vbus:1;
-       unsigned                        enabled:1;
-       unsigned                        clocked:1;
-       unsigned                        suspended:1;
-       unsigned                        req_pending:1;
-       unsigned                        wait_for_addr_ack:1;
-       unsigned                        wait_for_config_ack:1;
-       unsigned                        selfpowered:1;
-       unsigned                        active_suspend:1;
-       u8                              addr;
-       struct at91_udc_data            board;
-       struct clk                      *iclk, *fclk, *uclk;
-       struct platform_device          *pdev;
-       struct proc_dir_entry           *pde;
-       void __iomem                    *udp_baseaddr;
-       int                             udp_irq;
-       spinlock_t                      lock;
-       struct timer_list               vbus_timer;
-       struct work_struct              vbus_timer_work;
-};
-
-static inline struct at91_udc *to_udc(struct usb_gadget *g)
-{
-       return container_of(g, struct at91_udc, gadget);
-}
-
-struct at91_request {
-       struct usb_request              req;
-       struct list_head                queue;
-};
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef VERBOSE_DEBUG
-#    define VDBG               DBG
-#else
-#    define VDBG(stuff...)     do{}while(0)
-#endif
-
-#ifdef PACKET_TRACE
-#    define PACKET             VDBG
-#else
-#    define PACKET(stuff...)   do{}while(0)
-#endif
-
-#define ERR(stuff...)          pr_err("udc: " stuff)
-#define WARNING(stuff...)      pr_warning("udc: " stuff)
-#define INFO(stuff...)         pr_info("udc: " stuff)
-#define DBG(stuff...)          pr_debug("udc: " stuff)
-
-#endif
-
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
deleted file mode 100644 (file)
index 906e65f..0000000
+++ /dev/null
@@ -1,2133 +0,0 @@
-/*
- * Driver for the Atmel USBA high speed USB device controller
- *
- * Copyright (C) 2005-2007 Atmel Corporation
- *
- * 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 <linux/clk.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/list.h>
-#include <linux/platform_device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/atmel_usba_udc.h>
-#include <linux/delay.h>
-#include <linux/platform_data/atmel.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-
-#include <asm/gpio.h>
-
-#include "atmel_usba_udc.h"
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FS
-#include <linux/debugfs.h>
-#include <linux/uaccess.h>
-
-static int queue_dbg_open(struct inode *inode, struct file *file)
-{
-       struct usba_ep *ep = inode->i_private;
-       struct usba_request *req, *req_copy;
-       struct list_head *queue_data;
-
-       queue_data = kmalloc(sizeof(*queue_data), GFP_KERNEL);
-       if (!queue_data)
-               return -ENOMEM;
-       INIT_LIST_HEAD(queue_data);
-
-       spin_lock_irq(&ep->udc->lock);
-       list_for_each_entry(req, &ep->queue, queue) {
-               req_copy = kmemdup(req, sizeof(*req_copy), GFP_ATOMIC);
-               if (!req_copy)
-                       goto fail;
-               list_add_tail(&req_copy->queue, queue_data);
-       }
-       spin_unlock_irq(&ep->udc->lock);
-
-       file->private_data = queue_data;
-       return 0;
-
-fail:
-       spin_unlock_irq(&ep->udc->lock);
-       list_for_each_entry_safe(req, req_copy, queue_data, queue) {
-               list_del(&req->queue);
-               kfree(req);
-       }
-       kfree(queue_data);
-       return -ENOMEM;
-}
-
-/*
- * bbbbbbbb llllllll IZS sssss nnnn FDL\n\0
- *
- * b: buffer address
- * l: buffer length
- * I/i: interrupt/no interrupt
- * Z/z: zero/no zero
- * S/s: short ok/short not ok
- * s: status
- * n: nr_packets
- * F/f: submitted/not submitted to FIFO
- * D/d: using/not using DMA
- * L/l: last transaction/not last transaction
- */
-static ssize_t queue_dbg_read(struct file *file, char __user *buf,
-               size_t nbytes, loff_t *ppos)
-{
-       struct list_head *queue = file->private_data;
-       struct usba_request *req, *tmp_req;
-       size_t len, remaining, actual = 0;
-       char tmpbuf[38];
-
-       if (!access_ok(VERIFY_WRITE, buf, nbytes))
-               return -EFAULT;
-
-       mutex_lock(&file_inode(file)->i_mutex);
-       list_for_each_entry_safe(req, tmp_req, queue, queue) {
-               len = snprintf(tmpbuf, sizeof(tmpbuf),
-                               "%8p %08x %c%c%c %5d %c%c%c\n",
-                               req->req.buf, req->req.length,
-                               req->req.no_interrupt ? 'i' : 'I',
-                               req->req.zero ? 'Z' : 'z',
-                               req->req.short_not_ok ? 's' : 'S',
-                               req->req.status,
-                               req->submitted ? 'F' : 'f',
-                               req->using_dma ? 'D' : 'd',
-                               req->last_transaction ? 'L' : 'l');
-               len = min(len, sizeof(tmpbuf));
-               if (len > nbytes)
-                       break;
-
-               list_del(&req->queue);
-               kfree(req);
-
-               remaining = __copy_to_user(buf, tmpbuf, len);
-               actual += len - remaining;
-               if (remaining)
-                       break;
-
-               nbytes -= len;
-               buf += len;
-       }
-       mutex_unlock(&file_inode(file)->i_mutex);
-
-       return actual;
-}
-
-static int queue_dbg_release(struct inode *inode, struct file *file)
-{
-       struct list_head *queue_data = file->private_data;
-       struct usba_request *req, *tmp_req;
-
-       list_for_each_entry_safe(req, tmp_req, queue_data, queue) {
-               list_del(&req->queue);
-               kfree(req);
-       }
-       kfree(queue_data);
-       return 0;
-}
-
-static int regs_dbg_open(struct inode *inode, struct file *file)
-{
-       struct usba_udc *udc;
-       unsigned int i;
-       u32 *data;
-       int ret = -ENOMEM;
-
-       mutex_lock(&inode->i_mutex);
-       udc = inode->i_private;
-       data = kmalloc(inode->i_size, GFP_KERNEL);
-       if (!data)
-               goto out;
-
-       spin_lock_irq(&udc->lock);
-       for (i = 0; i < inode->i_size / 4; i++)
-               data[i] = __raw_readl(udc->regs + i * 4);
-       spin_unlock_irq(&udc->lock);
-
-       file->private_data = data;
-       ret = 0;
-
-out:
-       mutex_unlock(&inode->i_mutex);
-
-       return ret;
-}
-
-static ssize_t regs_dbg_read(struct file *file, char __user *buf,
-               size_t nbytes, loff_t *ppos)
-{
-       struct inode *inode = file_inode(file);
-       int ret;
-
-       mutex_lock(&inode->i_mutex);
-       ret = simple_read_from_buffer(buf, nbytes, ppos,
-                       file->private_data,
-                       file_inode(file)->i_size);
-       mutex_unlock(&inode->i_mutex);
-
-       return ret;
-}
-
-static int regs_dbg_release(struct inode *inode, struct file *file)
-{
-       kfree(file->private_data);
-       return 0;
-}
-
-const struct file_operations queue_dbg_fops = {
-       .owner          = THIS_MODULE,
-       .open           = queue_dbg_open,
-       .llseek         = no_llseek,
-       .read           = queue_dbg_read,
-       .release        = queue_dbg_release,
-};
-
-const struct file_operations regs_dbg_fops = {
-       .owner          = THIS_MODULE,
-       .open           = regs_dbg_open,
-       .llseek         = generic_file_llseek,
-       .read           = regs_dbg_read,
-       .release        = regs_dbg_release,
-};
-
-static void usba_ep_init_debugfs(struct usba_udc *udc,
-               struct usba_ep *ep)
-{
-       struct dentry *ep_root;
-
-       ep_root = debugfs_create_dir(ep->ep.name, udc->debugfs_root);
-       if (!ep_root)
-               goto err_root;
-       ep->debugfs_dir = ep_root;
-
-       ep->debugfs_queue = debugfs_create_file("queue", 0400, ep_root,
-                                               ep, &queue_dbg_fops);
-       if (!ep->debugfs_queue)
-               goto err_queue;
-
-       if (ep->can_dma) {
-               ep->debugfs_dma_status
-                       = debugfs_create_u32("dma_status", 0400, ep_root,
-                                       &ep->last_dma_status);
-               if (!ep->debugfs_dma_status)
-                       goto err_dma_status;
-       }
-       if (ep_is_control(ep)) {
-               ep->debugfs_state
-                       = debugfs_create_u32("state", 0400, ep_root,
-                                       &ep->state);
-               if (!ep->debugfs_state)
-                       goto err_state;
-       }
-
-       return;
-
-err_state:
-       if (ep->can_dma)
-               debugfs_remove(ep->debugfs_dma_status);
-err_dma_status:
-       debugfs_remove(ep->debugfs_queue);
-err_queue:
-       debugfs_remove(ep_root);
-err_root:
-       dev_err(&ep->udc->pdev->dev,
-               "failed to create debugfs directory for %s\n", ep->ep.name);
-}
-
-static void usba_ep_cleanup_debugfs(struct usba_ep *ep)
-{
-       debugfs_remove(ep->debugfs_queue);
-       debugfs_remove(ep->debugfs_dma_status);
-       debugfs_remove(ep->debugfs_state);
-       debugfs_remove(ep->debugfs_dir);
-       ep->debugfs_dma_status = NULL;
-       ep->debugfs_dir = NULL;
-}
-
-static void usba_init_debugfs(struct usba_udc *udc)
-{
-       struct dentry *root, *regs;
-       struct resource *regs_resource;
-
-       root = debugfs_create_dir(udc->gadget.name, NULL);
-       if (IS_ERR(root) || !root)
-               goto err_root;
-       udc->debugfs_root = root;
-
-       regs = debugfs_create_file("regs", 0400, root, udc, &regs_dbg_fops);
-       if (!regs)
-               goto err_regs;
-
-       regs_resource = platform_get_resource(udc->pdev, IORESOURCE_MEM,
-                               CTRL_IOMEM_ID);
-       regs->d_inode->i_size = resource_size(regs_resource);
-       udc->debugfs_regs = regs;
-
-       usba_ep_init_debugfs(udc, to_usba_ep(udc->gadget.ep0));
-
-       return;
-
-err_regs:
-       debugfs_remove(root);
-err_root:
-       udc->debugfs_root = NULL;
-       dev_err(&udc->pdev->dev, "debugfs is not available\n");
-}
-
-static void usba_cleanup_debugfs(struct usba_udc *udc)
-{
-       usba_ep_cleanup_debugfs(to_usba_ep(udc->gadget.ep0));
-       debugfs_remove(udc->debugfs_regs);
-       debugfs_remove(udc->debugfs_root);
-       udc->debugfs_regs = NULL;
-       udc->debugfs_root = NULL;
-}
-#else
-static inline void usba_ep_init_debugfs(struct usba_udc *udc,
-                                        struct usba_ep *ep)
-{
-
-}
-
-static inline void usba_ep_cleanup_debugfs(struct usba_ep *ep)
-{
-
-}
-
-static inline void usba_init_debugfs(struct usba_udc *udc)
-{
-
-}
-
-static inline void usba_cleanup_debugfs(struct usba_udc *udc)
-{
-
-}
-#endif
-
-static int vbus_is_present(struct usba_udc *udc)
-{
-       if (gpio_is_valid(udc->vbus_pin))
-               return gpio_get_value(udc->vbus_pin) ^ udc->vbus_pin_inverted;
-
-       /* No Vbus detection: Assume always present */
-       return 1;
-}
-
-#if defined(CONFIG_ARCH_AT91SAM9RL)
-
-#include <linux/clk/at91_pmc.h>
-
-static void toggle_bias(int is_on)
-{
-       unsigned int uckr = at91_pmc_read(AT91_CKGR_UCKR);
-
-       if (is_on)
-               at91_pmc_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
-       else
-               at91_pmc_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN));
-}
-
-#else
-
-static void toggle_bias(int is_on)
-{
-}
-
-#endif /* CONFIG_ARCH_AT91SAM9RL */
-
-static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
-{
-       unsigned int transaction_len;
-
-       transaction_len = req->req.length - req->req.actual;
-       req->last_transaction = 1;
-       if (transaction_len > ep->ep.maxpacket) {
-               transaction_len = ep->ep.maxpacket;
-               req->last_transaction = 0;
-       } else if (transaction_len == ep->ep.maxpacket && req->req.zero)
-               req->last_transaction = 0;
-
-       DBG(DBG_QUEUE, "%s: submit_transaction, req %p (length %d)%s\n",
-               ep->ep.name, req, transaction_len,
-               req->last_transaction ? ", done" : "");
-
-       memcpy_toio(ep->fifo, req->req.buf + req->req.actual, transaction_len);
-       usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
-       req->req.actual += transaction_len;
-}
-
-static void submit_request(struct usba_ep *ep, struct usba_request *req)
-{
-       DBG(DBG_QUEUE, "%s: submit_request: req %p (length %d)\n",
-               ep->ep.name, req, req->req.length);
-
-       req->req.actual = 0;
-       req->submitted = 1;
-
-       if (req->using_dma) {
-               if (req->req.length == 0) {
-                       usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
-                       return;
-               }
-
-               if (req->req.zero)
-                       usba_ep_writel(ep, CTL_ENB, USBA_SHORT_PACKET);
-               else
-                       usba_ep_writel(ep, CTL_DIS, USBA_SHORT_PACKET);
-
-               usba_dma_writel(ep, ADDRESS, req->req.dma);
-               usba_dma_writel(ep, CONTROL, req->ctrl);
-       } else {
-               next_fifo_transaction(ep, req);
-               if (req->last_transaction) {
-                       usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
-                       usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
-               } else {
-                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
-                       usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
-               }
-       }
-}
-
-static void submit_next_request(struct usba_ep *ep)
-{
-       struct usba_request *req;
-
-       if (list_empty(&ep->queue)) {
-               usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY | USBA_RX_BK_RDY);
-               return;
-       }
-
-       req = list_entry(ep->queue.next, struct usba_request, queue);
-       if (!req->submitted)
-               submit_request(ep, req);
-}
-
-static void send_status(struct usba_udc *udc, struct usba_ep *ep)
-{
-       ep->state = STATUS_STAGE_IN;
-       usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
-       usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
-}
-
-static void receive_data(struct usba_ep *ep)
-{
-       struct usba_udc *udc = ep->udc;
-       struct usba_request *req;
-       unsigned long status;
-       unsigned int bytecount, nr_busy;
-       int is_complete = 0;
-
-       status = usba_ep_readl(ep, STA);
-       nr_busy = USBA_BFEXT(BUSY_BANKS, status);
-
-       DBG(DBG_QUEUE, "receive data: nr_busy=%u\n", nr_busy);
-
-       while (nr_busy > 0) {
-               if (list_empty(&ep->queue)) {
-                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
-                       break;
-               }
-               req = list_entry(ep->queue.next,
-                                struct usba_request, queue);
-
-               bytecount = USBA_BFEXT(BYTE_COUNT, status);
-
-               if (status & (1 << 31))
-                       is_complete = 1;
-               if (req->req.actual + bytecount >= req->req.length) {
-                       is_complete = 1;
-                       bytecount = req->req.length - req->req.actual;
-               }
-
-               memcpy_fromio(req->req.buf + req->req.actual,
-                               ep->fifo, bytecount);
-               req->req.actual += bytecount;
-
-               usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
-
-               if (is_complete) {
-                       DBG(DBG_QUEUE, "%s: request done\n", ep->ep.name);
-                       req->req.status = 0;
-                       list_del_init(&req->queue);
-                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
-                       spin_unlock(&udc->lock);
-                       req->req.complete(&ep->ep, &req->req);
-                       spin_lock(&udc->lock);
-               }
-
-               status = usba_ep_readl(ep, STA);
-               nr_busy = USBA_BFEXT(BUSY_BANKS, status);
-
-               if (is_complete && ep_is_control(ep)) {
-                       send_status(udc, ep);
-                       break;
-               }
-       }
-}
-
-static void
-request_complete(struct usba_ep *ep, struct usba_request *req, int status)
-{
-       struct usba_udc *udc = ep->udc;
-
-       WARN_ON(!list_empty(&req->queue));
-
-       if (req->req.status == -EINPROGRESS)
-               req->req.status = status;
-
-       if (req->using_dma)
-               usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
-
-       DBG(DBG_GADGET | DBG_REQ,
-               "%s: req %p complete: status %d, actual %u\n",
-               ep->ep.name, req, req->req.status, req->req.actual);
-
-       spin_unlock(&udc->lock);
-       req->req.complete(&ep->ep, &req->req);
-       spin_lock(&udc->lock);
-}
-
-static void
-request_complete_list(struct usba_ep *ep, struct list_head *list, int status)
-{
-       struct usba_request *req, *tmp_req;
-
-       list_for_each_entry_safe(req, tmp_req, list, queue) {
-               list_del_init(&req->queue);
-               request_complete(ep, req, status);
-       }
-}
-
-static int
-usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
-{
-       struct usba_ep *ep = to_usba_ep(_ep);
-       struct usba_udc *udc = ep->udc;
-       unsigned long flags, ept_cfg, maxpacket;
-       unsigned int nr_trans;
-
-       DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep->ep.name, desc);
-
-       maxpacket = usb_endpoint_maxp(desc) & 0x7ff;
-
-       if (((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) != ep->index)
-                       || ep->index == 0
-                       || desc->bDescriptorType != USB_DT_ENDPOINT
-                       || maxpacket == 0
-                       || maxpacket > ep->fifo_size) {
-               DBG(DBG_ERR, "ep_enable: Invalid argument");
-               return -EINVAL;
-       }
-
-       ep->is_isoc = 0;
-       ep->is_in = 0;
-
-       if (maxpacket <= 8)
-               ept_cfg = USBA_BF(EPT_SIZE, USBA_EPT_SIZE_8);
-       else
-               /* LSB is bit 1, not 0 */
-               ept_cfg = USBA_BF(EPT_SIZE, fls(maxpacket - 1) - 3);
-
-       DBG(DBG_HW, "%s: EPT_SIZE = %lu (maxpacket = %lu)\n",
-                       ep->ep.name, ept_cfg, maxpacket);
-
-       if (usb_endpoint_dir_in(desc)) {
-               ep->is_in = 1;
-               ept_cfg |= USBA_EPT_DIR_IN;
-       }
-
-       switch (usb_endpoint_type(desc)) {
-       case USB_ENDPOINT_XFER_CONTROL:
-               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL);
-               ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE);
-               break;
-       case USB_ENDPOINT_XFER_ISOC:
-               if (!ep->can_isoc) {
-                       DBG(DBG_ERR, "ep_enable: %s is not isoc capable\n",
-                                       ep->ep.name);
-                       return -EINVAL;
-               }
-
-               /*
-                * Bits 11:12 specify number of _additional_
-                * transactions per microframe.
-                */
-               nr_trans = ((usb_endpoint_maxp(desc) >> 11) & 3) + 1;
-               if (nr_trans > 3)
-                       return -EINVAL;
-
-               ep->is_isoc = 1;
-               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_ISO);
-
-               /*
-                * Do triple-buffering on high-bandwidth iso endpoints.
-                */
-               if (nr_trans > 1 && ep->nr_banks == 3)
-                       ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_TRIPLE);
-               else
-                       ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE);
-               ept_cfg |= USBA_BF(NB_TRANS, nr_trans);
-               break;
-       case USB_ENDPOINT_XFER_BULK:
-               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK);
-               ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE);
-               break;
-       case USB_ENDPOINT_XFER_INT:
-               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_INT);
-               ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE);
-               break;
-       }
-
-       spin_lock_irqsave(&ep->udc->lock, flags);
-
-       ep->ep.desc = desc;
-       ep->ep.maxpacket = maxpacket;
-
-       usba_ep_writel(ep, CFG, ept_cfg);
-       usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
-
-       if (ep->can_dma) {
-               u32 ctrl;
-
-               usba_writel(udc, INT_ENB,
-                               (usba_readl(udc, INT_ENB)
-                                       | USBA_BF(EPT_INT, 1 << ep->index)
-                                       | USBA_BF(DMA_INT, 1 << ep->index)));
-               ctrl = USBA_AUTO_VALID | USBA_INTDIS_DMA;
-               usba_ep_writel(ep, CTL_ENB, ctrl);
-       } else {
-               usba_writel(udc, INT_ENB,
-                               (usba_readl(udc, INT_ENB)
-                                       | USBA_BF(EPT_INT, 1 << ep->index)));
-       }
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       DBG(DBG_HW, "EPT_CFG%d after init: %#08lx\n", ep->index,
-                       (unsigned long)usba_ep_readl(ep, CFG));
-       DBG(DBG_HW, "INT_ENB after init: %#08lx\n",
-                       (unsigned long)usba_readl(udc, INT_ENB));
-
-       return 0;
-}
-
-static int usba_ep_disable(struct usb_ep *_ep)
-{
-       struct usba_ep *ep = to_usba_ep(_ep);
-       struct usba_udc *udc = ep->udc;
-       LIST_HEAD(req_list);
-       unsigned long flags;
-
-       DBG(DBG_GADGET, "ep_disable: %s\n", ep->ep.name);
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       if (!ep->ep.desc) {
-               spin_unlock_irqrestore(&udc->lock, flags);
-               /* REVISIT because this driver disables endpoints in
-                * reset_all_endpoints() before calling disconnect(),
-                * most gadget drivers would trigger this non-error ...
-                */
-               if (udc->gadget.speed != USB_SPEED_UNKNOWN)
-                       DBG(DBG_ERR, "ep_disable: %s not enabled\n",
-                                       ep->ep.name);
-               return -EINVAL;
-       }
-       ep->ep.desc = NULL;
-
-       list_splice_init(&ep->queue, &req_list);
-       if (ep->can_dma) {
-               usba_dma_writel(ep, CONTROL, 0);
-               usba_dma_writel(ep, ADDRESS, 0);
-               usba_dma_readl(ep, STATUS);
-       }
-       usba_ep_writel(ep, CTL_DIS, USBA_EPT_ENABLE);
-       usba_writel(udc, INT_ENB,
-                       usba_readl(udc, INT_ENB)
-                       & ~USBA_BF(EPT_INT, 1 << ep->index));
-
-       request_complete_list(ep, &req_list, -ESHUTDOWN);
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-static struct usb_request *
-usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
-{
-       struct usba_request *req;
-
-       DBG(DBG_GADGET, "ep_alloc_request: %p, 0x%x\n", _ep, gfp_flags);
-
-       req = kzalloc(sizeof(*req), gfp_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD(&req->queue);
-
-       return &req->req;
-}
-
-static void
-usba_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct usba_request *req = to_usba_req(_req);
-
-       DBG(DBG_GADGET, "ep_free_request: %p, %p\n", _ep, _req);
-
-       kfree(req);
-}
-
-static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
-               struct usba_request *req, gfp_t gfp_flags)
-{
-       unsigned long flags;
-       int ret;
-
-       DBG(DBG_DMA, "%s: req l/%u d/%08x %c%c%c\n",
-               ep->ep.name, req->req.length, req->req.dma,
-               req->req.zero ? 'Z' : 'z',
-               req->req.short_not_ok ? 'S' : 's',
-               req->req.no_interrupt ? 'I' : 'i');
-
-       if (req->req.length > 0x10000) {
-               /* Lengths from 0 to 65536 (inclusive) are supported */
-               DBG(DBG_ERR, "invalid request length %u\n", req->req.length);
-               return -EINVAL;
-       }
-
-       ret = usb_gadget_map_request(&udc->gadget, &req->req, ep->is_in);
-       if (ret)
-               return ret;
-
-       req->using_dma = 1;
-       req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length)
-                       | USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE
-                       | USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE;
-
-       if (ep->is_in)
-               req->ctrl |= USBA_DMA_END_BUF_EN;
-
-       /*
-        * Add this request to the queue and submit for DMA if
-        * possible. Check if we're still alive first -- we may have
-        * received a reset since last time we checked.
-        */
-       ret = -ESHUTDOWN;
-       spin_lock_irqsave(&udc->lock, flags);
-       if (ep->ep.desc) {
-               if (list_empty(&ep->queue))
-                       submit_request(ep, req);
-
-               list_add_tail(&req->queue, &ep->queue);
-               ret = 0;
-       }
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return ret;
-}
-
-static int
-usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
-{
-       struct usba_request *req = to_usba_req(_req);
-       struct usba_ep *ep = to_usba_ep(_ep);
-       struct usba_udc *udc = ep->udc;
-       unsigned long flags;
-       int ret;
-
-       DBG(DBG_GADGET | DBG_QUEUE | DBG_REQ, "%s: queue req %p, len %u\n",
-                       ep->ep.name, req, _req->length);
-
-       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN ||
-           !ep->ep.desc)
-               return -ESHUTDOWN;
-
-       req->submitted = 0;
-       req->using_dma = 0;
-       req->last_transaction = 0;
-
-       _req->status = -EINPROGRESS;
-       _req->actual = 0;
-
-       if (ep->can_dma)
-               return queue_dma(udc, ep, req, gfp_flags);
-
-       /* May have received a reset since last time we checked */
-       ret = -ESHUTDOWN;
-       spin_lock_irqsave(&udc->lock, flags);
-       if (ep->ep.desc) {
-               list_add_tail(&req->queue, &ep->queue);
-
-               if ((!ep_is_control(ep) && ep->is_in) ||
-                       (ep_is_control(ep)
-                               && (ep->state == DATA_STAGE_IN
-                                       || ep->state == STATUS_STAGE_IN)))
-                       usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
-               else
-                       usba_ep_writel(ep, CTL_ENB, USBA_RX_BK_RDY);
-               ret = 0;
-       }
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return ret;
-}
-
-static void
-usba_update_req(struct usba_ep *ep, struct usba_request *req, u32 status)
-{
-       req->req.actual = req->req.length - USBA_BFEXT(DMA_BUF_LEN, status);
-}
-
-static int stop_dma(struct usba_ep *ep, u32 *pstatus)
-{
-       unsigned int timeout;
-       u32 status;
-
-       /*
-        * Stop the DMA controller. When writing both CH_EN
-        * and LINK to 0, the other bits are not affected.
-        */
-       usba_dma_writel(ep, CONTROL, 0);
-
-       /* Wait for the FIFO to empty */
-       for (timeout = 40; timeout; --timeout) {
-               status = usba_dma_readl(ep, STATUS);
-               if (!(status & USBA_DMA_CH_EN))
-                       break;
-               udelay(1);
-       }
-
-       if (pstatus)
-               *pstatus = status;
-
-       if (timeout == 0) {
-               dev_err(&ep->udc->pdev->dev,
-                       "%s: timed out waiting for DMA FIFO to empty\n",
-                       ep->ep.name);
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct usba_ep *ep = to_usba_ep(_ep);
-       struct usba_udc *udc = ep->udc;
-       struct usba_request *req = to_usba_req(_req);
-       unsigned long flags;
-       u32 status;
-
-       DBG(DBG_GADGET | DBG_QUEUE, "ep_dequeue: %s, req %p\n",
-                       ep->ep.name, req);
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       if (req->using_dma) {
-               /*
-                * If this request is currently being transferred,
-                * stop the DMA controller and reset the FIFO.
-                */
-               if (ep->queue.next == &req->queue) {
-                       status = usba_dma_readl(ep, STATUS);
-                       if (status & USBA_DMA_CH_EN)
-                               stop_dma(ep, &status);
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FS
-                       ep->last_dma_status = status;
-#endif
-
-                       usba_writel(udc, EPT_RST, 1 << ep->index);
-
-                       usba_update_req(ep, req, status);
-               }
-       }
-
-       /*
-        * Errors should stop the queue from advancing until the
-        * completion function returns.
-        */
-       list_del_init(&req->queue);
-
-       request_complete(ep, req, -ECONNRESET);
-
-       /* Process the next request if any */
-       submit_next_request(ep);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-static int usba_ep_set_halt(struct usb_ep *_ep, int value)
-{
-       struct usba_ep *ep = to_usba_ep(_ep);
-       struct usba_udc *udc = ep->udc;
-       unsigned long flags;
-       int ret = 0;
-
-       DBG(DBG_GADGET, "endpoint %s: %s HALT\n", ep->ep.name,
-                       value ? "set" : "clear");
-
-       if (!ep->ep.desc) {
-               DBG(DBG_ERR, "Attempted to halt uninitialized ep %s\n",
-                               ep->ep.name);
-               return -ENODEV;
-       }
-       if (ep->is_isoc) {
-               DBG(DBG_ERR, "Attempted to halt isochronous ep %s\n",
-                               ep->ep.name);
-               return -ENOTTY;
-       }
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       /*
-        * We can't halt IN endpoints while there are still data to be
-        * transferred
-        */
-       if (!list_empty(&ep->queue)
-                       || ((value && ep->is_in && (usba_ep_readl(ep, STA)
-                                       & USBA_BF(BUSY_BANKS, -1L))))) {
-               ret = -EAGAIN;
-       } else {
-               if (value)
-                       usba_ep_writel(ep, SET_STA, USBA_FORCE_STALL);
-               else
-                       usba_ep_writel(ep, CLR_STA,
-                                       USBA_FORCE_STALL | USBA_TOGGLE_CLR);
-               usba_ep_readl(ep, STA);
-       }
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return ret;
-}
-
-static int usba_ep_fifo_status(struct usb_ep *_ep)
-{
-       struct usba_ep *ep = to_usba_ep(_ep);
-
-       return USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
-}
-
-static void usba_ep_fifo_flush(struct usb_ep *_ep)
-{
-       struct usba_ep *ep = to_usba_ep(_ep);
-       struct usba_udc *udc = ep->udc;
-
-       usba_writel(udc, EPT_RST, 1 << ep->index);
-}
-
-static const struct usb_ep_ops usba_ep_ops = {
-       .enable         = usba_ep_enable,
-       .disable        = usba_ep_disable,
-       .alloc_request  = usba_ep_alloc_request,
-       .free_request   = usba_ep_free_request,
-       .queue          = usba_ep_queue,
-       .dequeue        = usba_ep_dequeue,
-       .set_halt       = usba_ep_set_halt,
-       .fifo_status    = usba_ep_fifo_status,
-       .fifo_flush     = usba_ep_fifo_flush,
-};
-
-static int usba_udc_get_frame(struct usb_gadget *gadget)
-{
-       struct usba_udc *udc = to_usba_udc(gadget);
-
-       return USBA_BFEXT(FRAME_NUMBER, usba_readl(udc, FNUM));
-}
-
-static int usba_udc_wakeup(struct usb_gadget *gadget)
-{
-       struct usba_udc *udc = to_usba_udc(gadget);
-       unsigned long flags;
-       u32 ctrl;
-       int ret = -EINVAL;
-
-       spin_lock_irqsave(&udc->lock, flags);
-       if (udc->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
-               ctrl = usba_readl(udc, CTRL);
-               usba_writel(udc, CTRL, ctrl | USBA_REMOTE_WAKE_UP);
-               ret = 0;
-       }
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return ret;
-}
-
-static int
-usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
-{
-       struct usba_udc *udc = to_usba_udc(gadget);
-       unsigned long flags;
-
-       spin_lock_irqsave(&udc->lock, flags);
-       if (is_selfpowered)
-               udc->devstatus |= 1 << USB_DEVICE_SELF_POWERED;
-       else
-               udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-static int atmel_usba_start(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver);
-static int atmel_usba_stop(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver);
-static const struct usb_gadget_ops usba_udc_ops = {
-       .get_frame              = usba_udc_get_frame,
-       .wakeup                 = usba_udc_wakeup,
-       .set_selfpowered        = usba_udc_set_selfpowered,
-       .udc_start              = atmel_usba_start,
-       .udc_stop               = atmel_usba_stop,
-};
-
-static struct usb_endpoint_descriptor usba_ep0_desc = {
-       .bLength = USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType = USB_DT_ENDPOINT,
-       .bEndpointAddress = 0,
-       .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
-       .wMaxPacketSize = cpu_to_le16(64),
-       /* FIXME: I have no idea what to put here */
-       .bInterval = 1,
-};
-
-static void nop_release(struct device *dev)
-{
-
-}
-
-static struct usb_gadget usba_gadget_template = {
-       .ops            = &usba_udc_ops,
-       .max_speed      = USB_SPEED_HIGH,
-       .name           = "atmel_usba_udc",
-       .dev    = {
-               .init_name      = "gadget",
-               .release        = nop_release,
-       },
-};
-
-/*
- * Called with interrupts disabled and udc->lock held.
- */
-static void reset_all_endpoints(struct usba_udc *udc)
-{
-       struct usba_ep *ep;
-       struct usba_request *req, *tmp_req;
-
-       usba_writel(udc, EPT_RST, ~0UL);
-
-       ep = to_usba_ep(udc->gadget.ep0);
-       list_for_each_entry_safe(req, tmp_req, &ep->queue, queue) {
-               list_del_init(&req->queue);
-               request_complete(ep, req, -ECONNRESET);
-       }
-
-       /* NOTE:  normally, the next call to the gadget driver is in
-        * charge of disabling endpoints... usually disconnect().
-        * The exception would be entering a high speed test mode.
-        *
-        * FIXME remove this code ... and retest thoroughly.
-        */
-       list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
-               if (ep->ep.desc) {
-                       spin_unlock(&udc->lock);
-                       usba_ep_disable(&ep->ep);
-                       spin_lock(&udc->lock);
-               }
-       }
-}
-
-static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex)
-{
-       struct usba_ep *ep;
-
-       if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
-               return to_usba_ep(udc->gadget.ep0);
-
-       list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) {
-               u8 bEndpointAddress;
-
-               if (!ep->ep.desc)
-                       continue;
-               bEndpointAddress = ep->ep.desc->bEndpointAddress;
-               if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
-                       continue;
-               if ((bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)
-                               == (wIndex & USB_ENDPOINT_NUMBER_MASK))
-                       return ep;
-       }
-
-       return NULL;
-}
-
-/* Called with interrupts disabled and udc->lock held */
-static inline void set_protocol_stall(struct usba_udc *udc, struct usba_ep *ep)
-{
-       usba_ep_writel(ep, SET_STA, USBA_FORCE_STALL);
-       ep->state = WAIT_FOR_SETUP;
-}
-
-static inline int is_stalled(struct usba_udc *udc, struct usba_ep *ep)
-{
-       if (usba_ep_readl(ep, STA) & USBA_FORCE_STALL)
-               return 1;
-       return 0;
-}
-
-static inline void set_address(struct usba_udc *udc, unsigned int addr)
-{
-       u32 regval;
-
-       DBG(DBG_BUS, "setting address %u...\n", addr);
-       regval = usba_readl(udc, CTRL);
-       regval = USBA_BFINS(DEV_ADDR, addr, regval);
-       usba_writel(udc, CTRL, regval);
-}
-
-static int do_test_mode(struct usba_udc *udc)
-{
-       static const char test_packet_buffer[] = {
-               /* JKJKJKJK * 9 */
-               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-               /* JJKKJJKK * 8 */
-               0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
-               /* JJKKJJKK * 8 */
-               0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
-               /* JJJJJJJKKKKKKK * 8 */
-               0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-               /* JJJJJJJK * 8 */
-               0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD,
-               /* {JKKKKKKK * 10}, JK */
-               0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0x7E
-       };
-       struct usba_ep *ep;
-       struct device *dev = &udc->pdev->dev;
-       int test_mode;
-
-       test_mode = udc->test_mode;
-
-       /* Start from a clean slate */
-       reset_all_endpoints(udc);
-
-       switch (test_mode) {
-       case 0x0100:
-               /* Test_J */
-               usba_writel(udc, TST, USBA_TST_J_MODE);
-               dev_info(dev, "Entering Test_J mode...\n");
-               break;
-       case 0x0200:
-               /* Test_K */
-               usba_writel(udc, TST, USBA_TST_K_MODE);
-               dev_info(dev, "Entering Test_K mode...\n");
-               break;
-       case 0x0300:
-               /*
-                * Test_SE0_NAK: Force high-speed mode and set up ep0
-                * for Bulk IN transfers
-                */
-               ep = &udc->usba_ep[0];
-               usba_writel(udc, TST,
-                               USBA_BF(SPEED_CFG, USBA_SPEED_CFG_FORCE_HIGH));
-               usba_ep_writel(ep, CFG,
-                               USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64)
-                               | USBA_EPT_DIR_IN
-                               | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK)
-                               | USBA_BF(BK_NUMBER, 1));
-               if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) {
-                       set_protocol_stall(udc, ep);
-                       dev_err(dev, "Test_SE0_NAK: ep0 not mapped\n");
-               } else {
-                       usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
-                       dev_info(dev, "Entering Test_SE0_NAK mode...\n");
-               }
-               break;
-       case 0x0400:
-               /* Test_Packet */
-               ep = &udc->usba_ep[0];
-               usba_ep_writel(ep, CFG,
-                               USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64)
-                               | USBA_EPT_DIR_IN
-                               | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK)
-                               | USBA_BF(BK_NUMBER, 1));
-               if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) {
-                       set_protocol_stall(udc, ep);
-                       dev_err(dev, "Test_Packet: ep0 not mapped\n");
-               } else {
-                       usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
-                       usba_writel(udc, TST, USBA_TST_PKT_MODE);
-                       memcpy_toio(ep->fifo, test_packet_buffer,
-                                       sizeof(test_packet_buffer));
-                       usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
-                       dev_info(dev, "Entering Test_Packet mode...\n");
-               }
-               break;
-       default:
-               dev_err(dev, "Invalid test mode: 0x%04x\n", test_mode);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/* Avoid overly long expressions */
-static inline bool feature_is_dev_remote_wakeup(struct usb_ctrlrequest *crq)
-{
-       if (crq->wValue == cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP))
-               return true;
-       return false;
-}
-
-static inline bool feature_is_dev_test_mode(struct usb_ctrlrequest *crq)
-{
-       if (crq->wValue == cpu_to_le16(USB_DEVICE_TEST_MODE))
-               return true;
-       return false;
-}
-
-static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq)
-{
-       if (crq->wValue == cpu_to_le16(USB_ENDPOINT_HALT))
-               return true;
-       return false;
-}
-
-static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep,
-               struct usb_ctrlrequest *crq)
-{
-       int retval = 0;
-
-       switch (crq->bRequest) {
-       case USB_REQ_GET_STATUS: {
-               u16 status;
-
-               if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_DEVICE)) {
-                       status = cpu_to_le16(udc->devstatus);
-               } else if (crq->bRequestType
-                               == (USB_DIR_IN | USB_RECIP_INTERFACE)) {
-                       status = cpu_to_le16(0);
-               } else if (crq->bRequestType
-                               == (USB_DIR_IN | USB_RECIP_ENDPOINT)) {
-                       struct usba_ep *target;
-
-                       target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
-                       if (!target)
-                               goto stall;
-
-                       status = 0;
-                       if (is_stalled(udc, target))
-                               status |= cpu_to_le16(1);
-               } else
-                       goto delegate;
-
-               /* Write directly to the FIFO. No queueing is done. */
-               if (crq->wLength != cpu_to_le16(sizeof(status)))
-                       goto stall;
-               ep->state = DATA_STAGE_IN;
-               __raw_writew(status, ep->fifo);
-               usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
-               break;
-       }
-
-       case USB_REQ_CLEAR_FEATURE: {
-               if (crq->bRequestType == USB_RECIP_DEVICE) {
-                       if (feature_is_dev_remote_wakeup(crq))
-                               udc->devstatus
-                                       &= ~(1 << USB_DEVICE_REMOTE_WAKEUP);
-                       else
-                               /* Can't CLEAR_FEATURE TEST_MODE */
-                               goto stall;
-               } else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
-                       struct usba_ep *target;
-
-                       if (crq->wLength != cpu_to_le16(0)
-                                       || !feature_is_ep_halt(crq))
-                               goto stall;
-                       target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
-                       if (!target)
-                               goto stall;
-
-                       usba_ep_writel(target, CLR_STA, USBA_FORCE_STALL);
-                       if (target->index != 0)
-                               usba_ep_writel(target, CLR_STA,
-                                               USBA_TOGGLE_CLR);
-               } else {
-                       goto delegate;
-               }
-
-               send_status(udc, ep);
-               break;
-       }
-
-       case USB_REQ_SET_FEATURE: {
-               if (crq->bRequestType == USB_RECIP_DEVICE) {
-                       if (feature_is_dev_test_mode(crq)) {
-                               send_status(udc, ep);
-                               ep->state = STATUS_STAGE_TEST;
-                               udc->test_mode = le16_to_cpu(crq->wIndex);
-                               return 0;
-                       } else if (feature_is_dev_remote_wakeup(crq)) {
-                               udc->devstatus |= 1 << USB_DEVICE_REMOTE_WAKEUP;
-                       } else {
-                               goto stall;
-                       }
-               } else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
-                       struct usba_ep *target;
-
-                       if (crq->wLength != cpu_to_le16(0)
-                                       || !feature_is_ep_halt(crq))
-                               goto stall;
-
-                       target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
-                       if (!target)
-                               goto stall;
-
-                       usba_ep_writel(target, SET_STA, USBA_FORCE_STALL);
-               } else
-                       goto delegate;
-
-               send_status(udc, ep);
-               break;
-       }
-
-       case USB_REQ_SET_ADDRESS:
-               if (crq->bRequestType != (USB_DIR_OUT | USB_RECIP_DEVICE))
-                       goto delegate;
-
-               set_address(udc, le16_to_cpu(crq->wValue));
-               send_status(udc, ep);
-               ep->state = STATUS_STAGE_ADDR;
-               break;
-
-       default:
-delegate:
-               spin_unlock(&udc->lock);
-               retval = udc->driver->setup(&udc->gadget, crq);
-               spin_lock(&udc->lock);
-       }
-
-       return retval;
-
-stall:
-       pr_err("udc: %s: Invalid setup request: %02x.%02x v%04x i%04x l%d, "
-               "halting endpoint...\n",
-               ep->ep.name, crq->bRequestType, crq->bRequest,
-               le16_to_cpu(crq->wValue), le16_to_cpu(crq->wIndex),
-               le16_to_cpu(crq->wLength));
-       set_protocol_stall(udc, ep);
-       return -1;
-}
-
-static void usba_control_irq(struct usba_udc *udc, struct usba_ep *ep)
-{
-       struct usba_request *req;
-       u32 epstatus;
-       u32 epctrl;
-
-restart:
-       epstatus = usba_ep_readl(ep, STA);
-       epctrl = usba_ep_readl(ep, CTL);
-
-       DBG(DBG_INT, "%s [%d]: s/%08x c/%08x\n",
-                       ep->ep.name, ep->state, epstatus, epctrl);
-
-       req = NULL;
-       if (!list_empty(&ep->queue))
-               req = list_entry(ep->queue.next,
-                                struct usba_request, queue);
-
-       if ((epctrl & USBA_TX_PK_RDY) && !(epstatus & USBA_TX_PK_RDY)) {
-               if (req->submitted)
-                       next_fifo_transaction(ep, req);
-               else
-                       submit_request(ep, req);
-
-               if (req->last_transaction) {
-                       usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
-                       usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
-               }
-               goto restart;
-       }
-       if ((epstatus & epctrl) & USBA_TX_COMPLETE) {
-               usba_ep_writel(ep, CLR_STA, USBA_TX_COMPLETE);
-
-               switch (ep->state) {
-               case DATA_STAGE_IN:
-                       usba_ep_writel(ep, CTL_ENB, USBA_RX_BK_RDY);
-                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
-                       ep->state = STATUS_STAGE_OUT;
-                       break;
-               case STATUS_STAGE_ADDR:
-                       /* Activate our new address */
-                       usba_writel(udc, CTRL, (usba_readl(udc, CTRL)
-                                               | USBA_FADDR_EN));
-                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
-                       ep->state = WAIT_FOR_SETUP;
-                       break;
-               case STATUS_STAGE_IN:
-                       if (req) {
-                               list_del_init(&req->queue);
-                               request_complete(ep, req, 0);
-                               submit_next_request(ep);
-                       }
-                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
-                       ep->state = WAIT_FOR_SETUP;
-                       break;
-               case STATUS_STAGE_TEST:
-                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
-                       ep->state = WAIT_FOR_SETUP;
-                       if (do_test_mode(udc))
-                               set_protocol_stall(udc, ep);
-                       break;
-               default:
-                       pr_err("udc: %s: TXCOMP: Invalid endpoint state %d, "
-                               "halting endpoint...\n",
-                               ep->ep.name, ep->state);
-                       set_protocol_stall(udc, ep);
-                       break;
-               }
-
-               goto restart;
-       }
-       if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
-               switch (ep->state) {
-               case STATUS_STAGE_OUT:
-                       usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
-                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
-
-                       if (req) {
-                               list_del_init(&req->queue);
-                               request_complete(ep, req, 0);
-                       }
-                       ep->state = WAIT_FOR_SETUP;
-                       break;
-
-               case DATA_STAGE_OUT:
-                       receive_data(ep);
-                       break;
-
-               default:
-                       usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
-                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
-                       pr_err("udc: %s: RXRDY: Invalid endpoint state %d, "
-                               "halting endpoint...\n",
-                               ep->ep.name, ep->state);
-                       set_protocol_stall(udc, ep);
-                       break;
-               }
-
-               goto restart;
-       }
-       if (epstatus & USBA_RX_SETUP) {
-               union {
-                       struct usb_ctrlrequest crq;
-                       unsigned long data[2];
-               } crq;
-               unsigned int pkt_len;
-               int ret;
-
-               if (ep->state != WAIT_FOR_SETUP) {
-                       /*
-                        * Didn't expect a SETUP packet at this
-                        * point. Clean up any pending requests (which
-                        * may be successful).
-                        */
-                       int status = -EPROTO;
-
-                       /*
-                        * RXRDY and TXCOMP are dropped when SETUP
-                        * packets arrive.  Just pretend we received
-                        * the status packet.
-                        */
-                       if (ep->state == STATUS_STAGE_OUT
-                                       || ep->state == STATUS_STAGE_IN) {
-                               usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
-                               status = 0;
-                       }
-
-                       if (req) {
-                               list_del_init(&req->queue);
-                               request_complete(ep, req, status);
-                       }
-               }
-
-               pkt_len = USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
-               DBG(DBG_HW, "Packet length: %u\n", pkt_len);
-               if (pkt_len != sizeof(crq)) {
-                       pr_warning("udc: Invalid packet length %u "
-                               "(expected %zu)\n", pkt_len, sizeof(crq));
-                       set_protocol_stall(udc, ep);
-                       return;
-               }
-
-               DBG(DBG_FIFO, "Copying ctrl request from 0x%p:\n", ep->fifo);
-               memcpy_fromio(crq.data, ep->fifo, sizeof(crq));
-
-               /* Free up one bank in the FIFO so that we can
-                * generate or receive a reply right away. */
-               usba_ep_writel(ep, CLR_STA, USBA_RX_SETUP);
-
-               /* printk(KERN_DEBUG "setup: %d: %02x.%02x\n",
-                       ep->state, crq.crq.bRequestType,
-                       crq.crq.bRequest); */
-
-               if (crq.crq.bRequestType & USB_DIR_IN) {
-                       /*
-                        * The USB 2.0 spec states that "if wLength is
-                        * zero, there is no data transfer phase."
-                        * However, testusb #14 seems to actually
-                        * expect a data phase even if wLength = 0...
-                        */
-                       ep->state = DATA_STAGE_IN;
-               } else {
-                       if (crq.crq.wLength != cpu_to_le16(0))
-                               ep->state = DATA_STAGE_OUT;
-                       else
-                               ep->state = STATUS_STAGE_IN;
-               }
-
-               ret = -1;
-               if (ep->index == 0)
-                       ret = handle_ep0_setup(udc, ep, &crq.crq);
-               else {
-                       spin_unlock(&udc->lock);
-                       ret = udc->driver->setup(&udc->gadget, &crq.crq);
-                       spin_lock(&udc->lock);
-               }
-
-               DBG(DBG_BUS, "req %02x.%02x, length %d, state %d, ret %d\n",
-                       crq.crq.bRequestType, crq.crq.bRequest,
-                       le16_to_cpu(crq.crq.wLength), ep->state, ret);
-
-               if (ret < 0) {
-                       /* Let the host know that we failed */
-                       set_protocol_stall(udc, ep);
-               }
-       }
-}
-
-static void usba_ep_irq(struct usba_udc *udc, struct usba_ep *ep)
-{
-       struct usba_request *req;
-       u32 epstatus;
-       u32 epctrl;
-
-       epstatus = usba_ep_readl(ep, STA);
-       epctrl = usba_ep_readl(ep, CTL);
-
-       DBG(DBG_INT, "%s: interrupt, status: 0x%08x\n", ep->ep.name, epstatus);
-
-       while ((epctrl & USBA_TX_PK_RDY) && !(epstatus & USBA_TX_PK_RDY)) {
-               DBG(DBG_BUS, "%s: TX PK ready\n", ep->ep.name);
-
-               if (list_empty(&ep->queue)) {
-                       dev_warn(&udc->pdev->dev, "ep_irq: queue empty\n");
-                       usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
-                       return;
-               }
-
-               req = list_entry(ep->queue.next, struct usba_request, queue);
-
-               if (req->using_dma) {
-                       /* Send a zero-length packet */
-                       usba_ep_writel(ep, SET_STA,
-                                       USBA_TX_PK_RDY);
-                       usba_ep_writel(ep, CTL_DIS,
-                                       USBA_TX_PK_RDY);
-                       list_del_init(&req->queue);
-                       submit_next_request(ep);
-                       request_complete(ep, req, 0);
-               } else {
-                       if (req->submitted)
-                               next_fifo_transaction(ep, req);
-                       else
-                               submit_request(ep, req);
-
-                       if (req->last_transaction) {
-                               list_del_init(&req->queue);
-                               submit_next_request(ep);
-                               request_complete(ep, req, 0);
-                       }
-               }
-
-               epstatus = usba_ep_readl(ep, STA);
-               epctrl = usba_ep_readl(ep, CTL);
-       }
-       if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
-               DBG(DBG_BUS, "%s: RX data ready\n", ep->ep.name);
-               receive_data(ep);
-               usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
-       }
-}
-
-static void usba_dma_irq(struct usba_udc *udc, struct usba_ep *ep)
-{
-       struct usba_request *req;
-       u32 status, control, pending;
-
-       status = usba_dma_readl(ep, STATUS);
-       control = usba_dma_readl(ep, CONTROL);
-#ifdef CONFIG_USB_GADGET_DEBUG_FS
-       ep->last_dma_status = status;
-#endif
-       pending = status & control;
-       DBG(DBG_INT | DBG_DMA, "dma irq, s/%#08x, c/%#08x\n", status, control);
-
-       if (status & USBA_DMA_CH_EN) {
-               dev_err(&udc->pdev->dev,
-                       "DMA_CH_EN is set after transfer is finished!\n");
-               dev_err(&udc->pdev->dev,
-                       "status=%#08x, pending=%#08x, control=%#08x\n",
-                       status, pending, control);
-
-               /*
-                * try to pretend nothing happened. We might have to
-                * do something here...
-                */
-       }
-
-       if (list_empty(&ep->queue))
-               /* Might happen if a reset comes along at the right moment */
-               return;
-
-       if (pending & (USBA_DMA_END_TR_ST | USBA_DMA_END_BUF_ST)) {
-               req = list_entry(ep->queue.next, struct usba_request, queue);
-               usba_update_req(ep, req, status);
-
-               list_del_init(&req->queue);
-               submit_next_request(ep);
-               request_complete(ep, req, 0);
-       }
-}
-
-static irqreturn_t usba_udc_irq(int irq, void *devid)
-{
-       struct usba_udc *udc = devid;
-       u32 status;
-       u32 dma_status;
-       u32 ep_status;
-
-       spin_lock(&udc->lock);
-
-       status = usba_readl(udc, INT_STA);
-       DBG(DBG_INT, "irq, status=%#08x\n", status);
-
-       if (status & USBA_DET_SUSPEND) {
-               toggle_bias(0);
-               usba_writel(udc, INT_CLR, USBA_DET_SUSPEND);
-               DBG(DBG_BUS, "Suspend detected\n");
-               if (udc->gadget.speed != USB_SPEED_UNKNOWN
-                               && udc->driver && udc->driver->suspend) {
-                       spin_unlock(&udc->lock);
-                       udc->driver->suspend(&udc->gadget);
-                       spin_lock(&udc->lock);
-               }
-       }
-
-       if (status & USBA_WAKE_UP) {
-               toggle_bias(1);
-               usba_writel(udc, INT_CLR, USBA_WAKE_UP);
-               DBG(DBG_BUS, "Wake Up CPU detected\n");
-       }
-
-       if (status & USBA_END_OF_RESUME) {
-               usba_writel(udc, INT_CLR, USBA_END_OF_RESUME);
-               DBG(DBG_BUS, "Resume detected\n");
-               if (udc->gadget.speed != USB_SPEED_UNKNOWN
-                               && udc->driver && udc->driver->resume) {
-                       spin_unlock(&udc->lock);
-                       udc->driver->resume(&udc->gadget);
-                       spin_lock(&udc->lock);
-               }
-       }
-
-       dma_status = USBA_BFEXT(DMA_INT, status);
-       if (dma_status) {
-               int i;
-
-               for (i = 1; i < USBA_NR_DMAS; i++)
-                       if (dma_status & (1 << i))
-                               usba_dma_irq(udc, &udc->usba_ep[i]);
-       }
-
-       ep_status = USBA_BFEXT(EPT_INT, status);
-       if (ep_status) {
-               int i;
-
-               for (i = 0; i < udc->num_ep; i++)
-                       if (ep_status & (1 << i)) {
-                               if (ep_is_control(&udc->usba_ep[i]))
-                                       usba_control_irq(udc, &udc->usba_ep[i]);
-                               else
-                                       usba_ep_irq(udc, &udc->usba_ep[i]);
-                       }
-       }
-
-       if (status & USBA_END_OF_RESET) {
-               struct usba_ep *ep0;
-
-               usba_writel(udc, INT_CLR, USBA_END_OF_RESET);
-               reset_all_endpoints(udc);
-
-               if (udc->gadget.speed != USB_SPEED_UNKNOWN
-                               && udc->driver && udc->driver->disconnect) {
-                       udc->gadget.speed = USB_SPEED_UNKNOWN;
-                       spin_unlock(&udc->lock);
-                       udc->driver->disconnect(&udc->gadget);
-                       spin_lock(&udc->lock);
-               }
-
-               if (status & USBA_HIGH_SPEED)
-                       udc->gadget.speed = USB_SPEED_HIGH;
-               else
-                       udc->gadget.speed = USB_SPEED_FULL;
-               DBG(DBG_BUS, "%s bus reset detected\n",
-                   usb_speed_string(udc->gadget.speed));
-
-               ep0 = &udc->usba_ep[0];
-               ep0->ep.desc = &usba_ep0_desc;
-               ep0->state = WAIT_FOR_SETUP;
-               usba_ep_writel(ep0, CFG,
-                               (USBA_BF(EPT_SIZE, EP0_EPT_SIZE)
-                               | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL)
-                               | USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE)));
-               usba_ep_writel(ep0, CTL_ENB,
-                               USBA_EPT_ENABLE | USBA_RX_SETUP);
-               usba_writel(udc, INT_ENB,
-                               (usba_readl(udc, INT_ENB)
-                               | USBA_BF(EPT_INT, 1)
-                               | USBA_DET_SUSPEND
-                               | USBA_END_OF_RESUME));
-
-               /*
-                * Unclear why we hit this irregularly, e.g. in usbtest,
-                * but it's clearly harmless...
-                */
-               if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED))
-                       dev_dbg(&udc->pdev->dev,
-                                "ODD: EP0 configuration is invalid!\n");
-       }
-
-       spin_unlock(&udc->lock);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t usba_vbus_irq(int irq, void *devid)
-{
-       struct usba_udc *udc = devid;
-       int vbus;
-
-       /* debounce */
-       udelay(10);
-
-       spin_lock(&udc->lock);
-
-       /* May happen if Vbus pin toggles during probe() */
-       if (!udc->driver)
-               goto out;
-
-       vbus = vbus_is_present(udc);
-       if (vbus != udc->vbus_prev) {
-               if (vbus) {
-                       toggle_bias(1);
-                       usba_writel(udc, CTRL, USBA_ENABLE_MASK);
-                       usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
-               } else {
-                       udc->gadget.speed = USB_SPEED_UNKNOWN;
-                       reset_all_endpoints(udc);
-                       toggle_bias(0);
-                       usba_writel(udc, CTRL, USBA_DISABLE_MASK);
-                       if (udc->driver->disconnect) {
-                               spin_unlock(&udc->lock);
-                               udc->driver->disconnect(&udc->gadget);
-                               spin_lock(&udc->lock);
-                       }
-               }
-               udc->vbus_prev = vbus;
-       }
-
-out:
-       spin_unlock(&udc->lock);
-
-       return IRQ_HANDLED;
-}
-
-static int atmel_usba_start(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       int ret;
-       struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
-       unsigned long flags;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
-       udc->driver = driver;
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       ret = clk_prepare_enable(udc->pclk);
-       if (ret)
-               return ret;
-       ret = clk_prepare_enable(udc->hclk);
-       if (ret) {
-               clk_disable_unprepare(udc->pclk);
-               return ret;
-       }
-
-       DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name);
-
-       udc->vbus_prev = 0;
-       if (gpio_is_valid(udc->vbus_pin))
-               enable_irq(gpio_to_irq(udc->vbus_pin));
-
-       /* If Vbus is present, enable the controller and wait for reset */
-       spin_lock_irqsave(&udc->lock, flags);
-       if (vbus_is_present(udc) && udc->vbus_prev == 0) {
-               toggle_bias(1);
-               usba_writel(udc, CTRL, USBA_ENABLE_MASK);
-               usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
-       }
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-static int atmel_usba_stop(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
-       unsigned long flags;
-
-       if (gpio_is_valid(udc->vbus_pin))
-               disable_irq(gpio_to_irq(udc->vbus_pin));
-
-       spin_lock_irqsave(&udc->lock, flags);
-       udc->gadget.speed = USB_SPEED_UNKNOWN;
-       reset_all_endpoints(udc);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       /* This will also disable the DP pullup */
-       toggle_bias(0);
-       usba_writel(udc, CTRL, USBA_DISABLE_MASK);
-
-       clk_disable_unprepare(udc->hclk);
-       clk_disable_unprepare(udc->pclk);
-
-       DBG(DBG_GADGET, "unregistered driver `%s'\n", udc->driver->driver.name);
-
-       udc->driver = NULL;
-
-       return 0;
-}
-
-#ifdef CONFIG_OF
-static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
-                                                   struct usba_udc *udc)
-{
-       u32 val;
-       const char *name;
-       enum of_gpio_flags flags;
-       struct device_node *np = pdev->dev.of_node;
-       struct device_node *pp;
-       int i, ret;
-       struct usba_ep *eps, *ep;
-
-       udc->num_ep = 0;
-
-       udc->vbus_pin = of_get_named_gpio_flags(np, "atmel,vbus-gpio", 0,
-                                               &flags);
-       udc->vbus_pin_inverted = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
-
-       pp = NULL;
-       while ((pp = of_get_next_child(np, pp)))
-               udc->num_ep++;
-
-       eps = devm_kzalloc(&pdev->dev, sizeof(struct usba_ep) * udc->num_ep,
-                          GFP_KERNEL);
-       if (!eps)
-               return ERR_PTR(-ENOMEM);
-
-       udc->gadget.ep0 = &eps[0].ep;
-
-       INIT_LIST_HEAD(&eps[0].ep.ep_list);
-
-       pp = NULL;
-       i = 0;
-       while ((pp = of_get_next_child(np, pp))) {
-               ep = &eps[i];
-
-               ret = of_property_read_u32(pp, "reg", &val);
-               if (ret) {
-                       dev_err(&pdev->dev, "of_probe: reg error(%d)\n", ret);
-                       goto err;
-               }
-               ep->index = val;
-
-               ret = of_property_read_u32(pp, "atmel,fifo-size", &val);
-               if (ret) {
-                       dev_err(&pdev->dev, "of_probe: fifo-size error(%d)\n", ret);
-                       goto err;
-               }
-               ep->fifo_size = val;
-
-               ret = of_property_read_u32(pp, "atmel,nb-banks", &val);
-               if (ret) {
-                       dev_err(&pdev->dev, "of_probe: nb-banks error(%d)\n", ret);
-                       goto err;
-               }
-               ep->nr_banks = val;
-
-               ep->can_dma = of_property_read_bool(pp, "atmel,can-dma");
-               ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc");
-
-               ret = of_property_read_string(pp, "name", &name);
-               ep->ep.name = name;
-
-               ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
-               ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
-               ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
-               ep->ep.ops = &usba_ep_ops;
-               usb_ep_set_maxpacket_limit(&ep->ep, ep->fifo_size);
-               ep->udc = udc;
-               INIT_LIST_HEAD(&ep->queue);
-
-               if (i)
-                       list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
-
-               i++;
-       }
-
-       if (i == 0) {
-               dev_err(&pdev->dev, "of_probe: no endpoint specified\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       return eps;
-err:
-       return ERR_PTR(ret);
-}
-#else
-static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
-                                                   struct usba_udc *udc)
-{
-       return ERR_PTR(-ENOSYS);
-}
-#endif
-
-static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
-                                                struct usba_udc *udc)
-{
-       struct usba_platform_data *pdata = dev_get_platdata(&pdev->dev);
-       struct usba_ep *eps;
-       int i;
-
-       if (!pdata)
-               return ERR_PTR(-ENXIO);
-
-       eps = devm_kzalloc(&pdev->dev, sizeof(struct usba_ep) * pdata->num_ep,
-                          GFP_KERNEL);
-       if (!eps)
-               return ERR_PTR(-ENOMEM);
-
-       udc->gadget.ep0 = &eps[0].ep;
-
-       udc->vbus_pin = pdata->vbus_pin;
-       udc->vbus_pin_inverted = pdata->vbus_pin_inverted;
-       udc->num_ep = pdata->num_ep;
-
-       INIT_LIST_HEAD(&eps[0].ep.ep_list);
-
-       for (i = 0; i < pdata->num_ep; i++) {
-               struct usba_ep *ep = &eps[i];
-
-               ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
-               ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
-               ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
-               ep->ep.ops = &usba_ep_ops;
-               ep->ep.name = pdata->ep[i].name;
-               ep->fifo_size = pdata->ep[i].fifo_size;
-               usb_ep_set_maxpacket_limit(&ep->ep, ep->fifo_size);
-               ep->udc = udc;
-               INIT_LIST_HEAD(&ep->queue);
-               ep->nr_banks = pdata->ep[i].nr_banks;
-               ep->index = pdata->ep[i].index;
-               ep->can_dma = pdata->ep[i].can_dma;
-               ep->can_isoc = pdata->ep[i].can_isoc;
-
-               if (i)
-                       list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
-       }
-
-       return eps;
-}
-
-static int usba_udc_probe(struct platform_device *pdev)
-{
-       struct resource *regs, *fifo;
-       struct clk *pclk, *hclk;
-       struct usba_udc *udc;
-       int irq, ret, i;
-
-       udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL);
-       if (!udc)
-               return -ENOMEM;
-
-       udc->gadget = usba_gadget_template;
-       INIT_LIST_HEAD(&udc->gadget.ep_list);
-
-       regs = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID);
-       fifo = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID);
-       if (!regs || !fifo)
-               return -ENXIO;
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
-
-       pclk = devm_clk_get(&pdev->dev, "pclk");
-       if (IS_ERR(pclk))
-               return PTR_ERR(pclk);
-       hclk = devm_clk_get(&pdev->dev, "hclk");
-       if (IS_ERR(hclk))
-               return PTR_ERR(hclk);
-
-       spin_lock_init(&udc->lock);
-       udc->pdev = pdev;
-       udc->pclk = pclk;
-       udc->hclk = hclk;
-       udc->vbus_pin = -ENODEV;
-
-       ret = -ENOMEM;
-       udc->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
-       if (!udc->regs) {
-               dev_err(&pdev->dev, "Unable to map I/O memory, aborting.\n");
-               return ret;
-       }
-       dev_info(&pdev->dev, "MMIO registers at 0x%08lx mapped at %p\n",
-                (unsigned long)regs->start, udc->regs);
-       udc->fifo = devm_ioremap(&pdev->dev, fifo->start, resource_size(fifo));
-       if (!udc->fifo) {
-               dev_err(&pdev->dev, "Unable to map FIFO, aborting.\n");
-               return ret;
-       }
-       dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
-                (unsigned long)fifo->start, udc->fifo);
-
-       platform_set_drvdata(pdev, udc);
-
-       /* Make sure we start from a clean slate */
-       ret = clk_prepare_enable(pclk);
-       if (ret) {
-               dev_err(&pdev->dev, "Unable to enable pclk, aborting.\n");
-               return ret;
-       }
-       toggle_bias(0);
-       usba_writel(udc, CTRL, USBA_DISABLE_MASK);
-       clk_disable_unprepare(pclk);
-
-       if (pdev->dev.of_node)
-               udc->usba_ep = atmel_udc_of_init(pdev, udc);
-       else
-               udc->usba_ep = usba_udc_pdata(pdev, udc);
-
-       if (IS_ERR(udc->usba_ep))
-               return PTR_ERR(udc->usba_ep);
-
-       ret = devm_request_irq(&pdev->dev, irq, usba_udc_irq, 0,
-                               "atmel_usba_udc", udc);
-       if (ret) {
-               dev_err(&pdev->dev, "Cannot request irq %d (error %d)\n",
-                       irq, ret);
-               return ret;
-       }
-       udc->irq = irq;
-
-       if (gpio_is_valid(udc->vbus_pin)) {
-               if (!devm_gpio_request(&pdev->dev, udc->vbus_pin, "atmel_usba_udc")) {
-                       ret = devm_request_irq(&pdev->dev,
-                                       gpio_to_irq(udc->vbus_pin),
-                                       usba_vbus_irq, 0,
-                                       "atmel_usba_udc", udc);
-                       if (ret) {
-                               udc->vbus_pin = -ENODEV;
-                               dev_warn(&udc->pdev->dev,
-                                        "failed to request vbus irq; "
-                                        "assuming always on\n");
-                       } else {
-                               disable_irq(gpio_to_irq(udc->vbus_pin));
-                       }
-               } else {
-                       /* gpio_request fail so use -EINVAL for gpio_is_valid */
-                       udc->vbus_pin = -EINVAL;
-               }
-       }
-
-       ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
-       if (ret)
-               return ret;
-
-       usba_init_debugfs(udc);
-       for (i = 1; i < udc->num_ep; i++)
-               usba_ep_init_debugfs(udc, &udc->usba_ep[i]);
-
-       return 0;
-}
-
-static int __exit usba_udc_remove(struct platform_device *pdev)
-{
-       struct usba_udc *udc;
-       int i;
-
-       udc = platform_get_drvdata(pdev);
-
-       usb_del_gadget_udc(&udc->gadget);
-
-       for (i = 1; i < udc->num_ep; i++)
-               usba_ep_cleanup_debugfs(&udc->usba_ep[i]);
-       usba_cleanup_debugfs(udc);
-
-       return 0;
-}
-
-#if defined(CONFIG_OF)
-static const struct of_device_id atmel_udc_dt_ids[] = {
-       { .compatible = "atmel,at91sam9rl-udc" },
-       { /* sentinel */ }
-};
-
-MODULE_DEVICE_TABLE(of, atmel_udc_dt_ids);
-#endif
-
-static struct platform_driver udc_driver = {
-       .remove         = __exit_p(usba_udc_remove),
-       .driver         = {
-               .name           = "atmel_usba_udc",
-               .owner          = THIS_MODULE,
-               .of_match_table = of_match_ptr(atmel_udc_dt_ids),
-       },
-};
-
-module_platform_driver_probe(udc_driver, usba_udc_probe);
-
-MODULE_DESCRIPTION("Atmel USBA UDC driver");
-MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:atmel_usba_udc");
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
deleted file mode 100644 (file)
index a70706e..0000000
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Driver for the Atmel USBA high speed USB device controller
- *
- * Copyright (C) 2005-2007 Atmel Corporation
- *
- * 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.
- */
-#ifndef __LINUX_USB_GADGET_USBA_UDC_H__
-#define __LINUX_USB_GADGET_USBA_UDC_H__
-
-/* USB register offsets */
-#define USBA_CTRL                              0x0000
-#define USBA_FNUM                              0x0004
-#define USBA_INT_ENB                           0x0010
-#define USBA_INT_STA                           0x0014
-#define USBA_INT_CLR                           0x0018
-#define USBA_EPT_RST                           0x001c
-#define USBA_TST                               0x00e0
-
-/* USB endpoint register offsets */
-#define USBA_EPT_CFG                           0x0000
-#define USBA_EPT_CTL_ENB                       0x0004
-#define USBA_EPT_CTL_DIS                       0x0008
-#define USBA_EPT_CTL                           0x000c
-#define USBA_EPT_SET_STA                       0x0014
-#define USBA_EPT_CLR_STA                       0x0018
-#define USBA_EPT_STA                           0x001c
-
-/* USB DMA register offsets */
-#define USBA_DMA_NXT_DSC                       0x0000
-#define USBA_DMA_ADDRESS                       0x0004
-#define USBA_DMA_CONTROL                       0x0008
-#define USBA_DMA_STATUS                                0x000c
-
-/* Bitfields in CTRL */
-#define USBA_DEV_ADDR_OFFSET                   0
-#define USBA_DEV_ADDR_SIZE                     7
-#define USBA_FADDR_EN                          (1 <<  7)
-#define USBA_EN_USBA                           (1 <<  8)
-#define USBA_DETACH                            (1 <<  9)
-#define USBA_REMOTE_WAKE_UP                    (1 << 10)
-#define USBA_PULLD_DIS                         (1 << 11)
-
-#if defined(CONFIG_AVR32)
-#define USBA_ENABLE_MASK                       USBA_EN_USBA
-#define USBA_DISABLE_MASK                      0
-#elif defined(CONFIG_ARCH_AT91)
-#define USBA_ENABLE_MASK                       (USBA_EN_USBA | USBA_PULLD_DIS)
-#define USBA_DISABLE_MASK                      USBA_DETACH
-#endif /* CONFIG_ARCH_AT91 */
-
-/* Bitfields in FNUM */
-#define USBA_MICRO_FRAME_NUM_OFFSET            0
-#define USBA_MICRO_FRAME_NUM_SIZE              3
-#define USBA_FRAME_NUMBER_OFFSET               3
-#define USBA_FRAME_NUMBER_SIZE                 11
-#define USBA_FRAME_NUM_ERROR                   (1 << 31)
-
-/* Bitfields in INT_ENB/INT_STA/INT_CLR */
-#define USBA_HIGH_SPEED                                (1 <<  0)
-#define USBA_DET_SUSPEND                       (1 <<  1)
-#define USBA_MICRO_SOF                         (1 <<  2)
-#define USBA_SOF                               (1 <<  3)
-#define USBA_END_OF_RESET                      (1 <<  4)
-#define USBA_WAKE_UP                           (1 <<  5)
-#define USBA_END_OF_RESUME                     (1 <<  6)
-#define USBA_UPSTREAM_RESUME                   (1 <<  7)
-#define USBA_EPT_INT_OFFSET                    8
-#define USBA_EPT_INT_SIZE                      16
-#define USBA_DMA_INT_OFFSET                    24
-#define USBA_DMA_INT_SIZE                      8
-
-/* Bitfields in EPT_RST */
-#define USBA_RST_OFFSET                                0
-#define USBA_RST_SIZE                          16
-
-/* Bitfields in USBA_TST */
-#define USBA_SPEED_CFG_OFFSET                  0
-#define USBA_SPEED_CFG_SIZE                    2
-#define USBA_TST_J_MODE                                (1 <<  2)
-#define USBA_TST_K_MODE                                (1 <<  3)
-#define USBA_TST_PKT_MODE                      (1 <<  4)
-#define USBA_OPMODE2                           (1 <<  5)
-
-/* Bitfields in EPT_CFG */
-#define USBA_EPT_SIZE_OFFSET                   0
-#define USBA_EPT_SIZE_SIZE                     3
-#define USBA_EPT_DIR_IN                                (1 <<  3)
-#define USBA_EPT_TYPE_OFFSET                   4
-#define USBA_EPT_TYPE_SIZE                     2
-#define USBA_BK_NUMBER_OFFSET                  6
-#define USBA_BK_NUMBER_SIZE                    2
-#define USBA_NB_TRANS_OFFSET                   8
-#define USBA_NB_TRANS_SIZE                     2
-#define USBA_EPT_MAPPED                                (1 << 31)
-
-/* Bitfields in EPT_CTL/EPT_CTL_ENB/EPT_CTL_DIS */
-#define USBA_EPT_ENABLE                                (1 <<  0)
-#define USBA_AUTO_VALID                                (1 <<  1)
-#define USBA_INTDIS_DMA                                (1 <<  3)
-#define USBA_NYET_DIS                          (1 <<  4)
-#define USBA_DATAX_RX                          (1 <<  6)
-#define USBA_MDATA_RX                          (1 <<  7)
-/* Bits 8-15 and 31 enable interrupts for respective bits in EPT_STA */
-#define USBA_BUSY_BANK_IE                      (1 << 18)
-
-/* Bitfields in EPT_SET_STA/EPT_CLR_STA/EPT_STA */
-#define USBA_FORCE_STALL                       (1 <<  5)
-#define USBA_TOGGLE_CLR                                (1 <<  6)
-#define USBA_TOGGLE_SEQ_OFFSET                 6
-#define USBA_TOGGLE_SEQ_SIZE                   2
-#define USBA_ERR_OVFLW                         (1 <<  8)
-#define USBA_RX_BK_RDY                         (1 <<  9)
-#define USBA_KILL_BANK                         (1 <<  9)
-#define USBA_TX_COMPLETE                       (1 << 10)
-#define USBA_TX_PK_RDY                         (1 << 11)
-#define USBA_ISO_ERR_TRANS                     (1 << 11)
-#define USBA_RX_SETUP                          (1 << 12)
-#define USBA_ISO_ERR_FLOW                      (1 << 12)
-#define USBA_STALL_SENT                                (1 << 13)
-#define USBA_ISO_ERR_CRC                       (1 << 13)
-#define USBA_ISO_ERR_NBTRANS                   (1 << 13)
-#define USBA_NAK_IN                            (1 << 14)
-#define USBA_ISO_ERR_FLUSH                     (1 << 14)
-#define USBA_NAK_OUT                           (1 << 15)
-#define USBA_CURRENT_BANK_OFFSET               16
-#define USBA_CURRENT_BANK_SIZE                 2
-#define USBA_BUSY_BANKS_OFFSET                 18
-#define USBA_BUSY_BANKS_SIZE                   2
-#define USBA_BYTE_COUNT_OFFSET                 20
-#define USBA_BYTE_COUNT_SIZE                   11
-#define USBA_SHORT_PACKET                      (1 << 31)
-
-/* Bitfields in DMA_CONTROL */
-#define USBA_DMA_CH_EN                         (1 <<  0)
-#define USBA_DMA_LINK                          (1 <<  1)
-#define USBA_DMA_END_TR_EN                     (1 <<  2)
-#define USBA_DMA_END_BUF_EN                    (1 <<  3)
-#define USBA_DMA_END_TR_IE                     (1 <<  4)
-#define USBA_DMA_END_BUF_IE                    (1 <<  5)
-#define USBA_DMA_DESC_LOAD_IE                  (1 <<  6)
-#define USBA_DMA_BURST_LOCK                    (1 <<  7)
-#define USBA_DMA_BUF_LEN_OFFSET                        16
-#define USBA_DMA_BUF_LEN_SIZE                  16
-
-/* Bitfields in DMA_STATUS */
-#define USBA_DMA_CH_ACTIVE                     (1 <<  1)
-#define USBA_DMA_END_TR_ST                     (1 <<  4)
-#define USBA_DMA_END_BUF_ST                    (1 <<  5)
-#define USBA_DMA_DESC_LOAD_ST                  (1 <<  6)
-
-/* Constants for SPEED_CFG */
-#define USBA_SPEED_CFG_NORMAL                  0
-#define USBA_SPEED_CFG_FORCE_HIGH              2
-#define USBA_SPEED_CFG_FORCE_FULL              3
-
-/* Constants for EPT_SIZE */
-#define USBA_EPT_SIZE_8                                0
-#define USBA_EPT_SIZE_16                       1
-#define USBA_EPT_SIZE_32                       2
-#define USBA_EPT_SIZE_64                       3
-#define USBA_EPT_SIZE_128                      4
-#define USBA_EPT_SIZE_256                      5
-#define USBA_EPT_SIZE_512                      6
-#define USBA_EPT_SIZE_1024                     7
-
-/* Constants for EPT_TYPE */
-#define USBA_EPT_TYPE_CONTROL                  0
-#define USBA_EPT_TYPE_ISO                      1
-#define USBA_EPT_TYPE_BULK                     2
-#define USBA_EPT_TYPE_INT                      3
-
-/* Constants for BK_NUMBER */
-#define USBA_BK_NUMBER_ZERO                    0
-#define USBA_BK_NUMBER_ONE                     1
-#define USBA_BK_NUMBER_DOUBLE                  2
-#define USBA_BK_NUMBER_TRIPLE                  3
-
-/* Bit manipulation macros */
-#define USBA_BF(name, value)                                   \
-       (((value) & ((1 << USBA_##name##_SIZE) - 1))            \
-        << USBA_##name##_OFFSET)
-#define USBA_BFEXT(name, value)                                        \
-       (((value) >> USBA_##name##_OFFSET)                      \
-        & ((1 << USBA_##name##_SIZE) - 1))
-#define USBA_BFINS(name, value, old)                           \
-       (((old) & ~(((1 << USBA_##name##_SIZE) - 1)             \
-                   << USBA_##name##_OFFSET))                   \
-        | USBA_BF(name, value))
-
-/* Register access macros */
-#define usba_readl(udc, reg)                                   \
-       __raw_readl((udc)->regs + USBA_##reg)
-#define usba_writel(udc, reg, value)                           \
-       __raw_writel((value), (udc)->regs + USBA_##reg)
-#define usba_ep_readl(ep, reg)                                 \
-       __raw_readl((ep)->ep_regs + USBA_EPT_##reg)
-#define usba_ep_writel(ep, reg, value)                         \
-       __raw_writel((value), (ep)->ep_regs + USBA_EPT_##reg)
-#define usba_dma_readl(ep, reg)                                        \
-       __raw_readl((ep)->dma_regs + USBA_DMA_##reg)
-#define usba_dma_writel(ep, reg, value)                                \
-       __raw_writel((value), (ep)->dma_regs + USBA_DMA_##reg)
-
-/* Calculate base address for a given endpoint or DMA controller */
-#define USBA_EPT_BASE(x)       (0x100 + (x) * 0x20)
-#define USBA_DMA_BASE(x)       (0x300 + (x) * 0x10)
-#define USBA_FIFO_BASE(x)      ((x) << 16)
-
-/* Synth parameters */
-#define USBA_NR_DMAS           7
-
-#define EP0_FIFO_SIZE          64
-#define EP0_EPT_SIZE           USBA_EPT_SIZE_64
-#define EP0_NR_BANKS           1
-
-#define FIFO_IOMEM_ID  0
-#define CTRL_IOMEM_ID  1
-
-#define DBG_ERR                0x0001  /* report all error returns */
-#define DBG_HW         0x0002  /* debug hardware initialization */
-#define DBG_GADGET     0x0004  /* calls to/from gadget driver */
-#define DBG_INT                0x0008  /* interrupts */
-#define DBG_BUS                0x0010  /* report changes in bus state */
-#define DBG_QUEUE      0x0020  /* debug request queue processing */
-#define DBG_FIFO       0x0040  /* debug FIFO contents */
-#define DBG_DMA                0x0080  /* debug DMA handling */
-#define DBG_REQ                0x0100  /* print out queued request length */
-#define DBG_ALL                0xffff
-#define DBG_NONE       0x0000
-
-#define DEBUG_LEVEL    (DBG_ERR)
-
-#define DBG(level, fmt, ...)                                   \
-       do {                                                    \
-               if ((level) & DEBUG_LEVEL)                      \
-                       pr_debug("udc: " fmt, ## __VA_ARGS__);  \
-       } while (0)
-
-enum usba_ctrl_state {
-       WAIT_FOR_SETUP,
-       DATA_STAGE_IN,
-       DATA_STAGE_OUT,
-       STATUS_STAGE_IN,
-       STATUS_STAGE_OUT,
-       STATUS_STAGE_ADDR,
-       STATUS_STAGE_TEST,
-};
-/*
-  EP_STATE_IDLE,
-  EP_STATE_SETUP,
-  EP_STATE_IN_DATA,
-  EP_STATE_OUT_DATA,
-  EP_STATE_SET_ADDR_STATUS,
-  EP_STATE_RX_STATUS,
-  EP_STATE_TX_STATUS,
-  EP_STATE_HALT,
-*/
-
-struct usba_dma_desc {
-       dma_addr_t next;
-       dma_addr_t addr;
-       u32 ctrl;
-};
-
-struct usba_ep {
-       int                                     state;
-       void __iomem                            *ep_regs;
-       void __iomem                            *dma_regs;
-       void __iomem                            *fifo;
-       struct usb_ep                           ep;
-       struct usba_udc                         *udc;
-
-       struct list_head                        queue;
-
-       u16                                     fifo_size;
-       u8                                      nr_banks;
-       u8                                      index;
-       unsigned int                            can_dma:1;
-       unsigned int                            can_isoc:1;
-       unsigned int                            is_isoc:1;
-       unsigned int                            is_in:1;
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FS
-       u32                                     last_dma_status;
-       struct dentry                           *debugfs_dir;
-       struct dentry                           *debugfs_queue;
-       struct dentry                           *debugfs_dma_status;
-       struct dentry                           *debugfs_state;
-#endif
-};
-
-struct usba_request {
-       struct usb_request                      req;
-       struct list_head                        queue;
-
-       u32                                     ctrl;
-
-       unsigned int                            submitted:1;
-       unsigned int                            last_transaction:1;
-       unsigned int                            using_dma:1;
-       unsigned int                            mapped:1;
-};
-
-struct usba_udc {
-       /* Protect hw registers from concurrent modifications */
-       spinlock_t lock;
-
-       void __iomem *regs;
-       void __iomem *fifo;
-
-       struct usb_gadget gadget;
-       struct usb_gadget_driver *driver;
-       struct platform_device *pdev;
-       int irq;
-       int vbus_pin;
-       int vbus_pin_inverted;
-       int num_ep;
-       struct clk *pclk;
-       struct clk *hclk;
-       struct usba_ep *usba_ep;
-
-       u16 devstatus;
-
-       u16 test_mode;
-       int vbus_prev;
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FS
-       struct dentry *debugfs_root;
-       struct dentry *debugfs_regs;
-#endif
-};
-
-static inline struct usba_ep *to_usba_ep(struct usb_ep *ep)
-{
-       return container_of(ep, struct usba_ep, ep);
-}
-
-static inline struct usba_request *to_usba_req(struct usb_request *req)
-{
-       return container_of(req, struct usba_request, req);
-}
-
-static inline struct usba_udc *to_usba_udc(struct usb_gadget *gadget)
-{
-       return container_of(gadget, struct usba_udc, gadget);
-}
-
-#define ep_is_control(ep)      ((ep)->index == 0)
-#define ep_is_idle(ep)         ((ep)->state == EP_STATE_IDLE)
-
-#endif /* __LINUX_USB_GADGET_USBA_UDC_H */
diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c
deleted file mode 100644 (file)
index e969eb8..0000000
+++ /dev/null
@@ -1,2436 +0,0 @@
-/*
- * bcm63xx_udc.c -- BCM63xx UDC high/full speed USB device controller
- *
- * Copyright (C) 2012 Kevin Cernekee <cernekee@gmail.com>
- * Copyright (C) 2012 Broadcom 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.
- */
-
-#include <linux/bitops.h>
-#include <linux/bug.h>
-#include <linux/clk.h>
-#include <linux/compiler.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/kconfig.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/timer.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/workqueue.h>
-
-#include <bcm63xx_cpu.h>
-#include <bcm63xx_iudma.h>
-#include <bcm63xx_dev_usb_usbd.h>
-#include <bcm63xx_io.h>
-#include <bcm63xx_regs.h>
-
-#define DRV_MODULE_NAME                "bcm63xx_udc"
-
-static const char bcm63xx_ep0name[] = "ep0";
-static const char *const bcm63xx_ep_name[] = {
-       bcm63xx_ep0name,
-       "ep1in-bulk", "ep2out-bulk", "ep3in-int", "ep4out-int",
-};
-
-static bool use_fullspeed;
-module_param(use_fullspeed, bool, S_IRUGO);
-MODULE_PARM_DESC(use_fullspeed, "true for fullspeed only");
-
-/*
- * RX IRQ coalescing options:
- *
- * false (default) - one IRQ per DATAx packet.  Slow but reliable.  The
- * driver is able to pass the "testusb" suite and recover from conditions like:
- *
- *   1) Device queues up a 2048-byte RX IUDMA transaction on an OUT bulk ep
- *   2) Host sends 512 bytes of data
- *   3) Host decides to reconfigure the device and sends SET_INTERFACE
- *   4) Device shuts down the endpoint and cancels the RX transaction
- *
- * true - one IRQ per transfer, for transfers <= 2048B.  Generates
- * considerably fewer IRQs, but error recovery is less robust.  Does not
- * reliably pass "testusb".
- *
- * TX always uses coalescing, because we can cancel partially complete TX
- * transfers by repeatedly flushing the FIFO.  The hardware doesn't allow
- * this on RX.
- */
-static bool irq_coalesce;
-module_param(irq_coalesce, bool, S_IRUGO);
-MODULE_PARM_DESC(irq_coalesce, "take one IRQ per RX transfer");
-
-#define BCM63XX_NUM_EP                 5
-#define BCM63XX_NUM_IUDMA              6
-#define BCM63XX_NUM_FIFO_PAIRS         3
-
-#define IUDMA_RESET_TIMEOUT_US         10000
-
-#define IUDMA_EP0_RXCHAN               0
-#define IUDMA_EP0_TXCHAN               1
-
-#define IUDMA_MAX_FRAGMENT             2048
-#define BCM63XX_MAX_CTRL_PKT           64
-
-#define BCMEP_CTRL                     0x00
-#define BCMEP_ISOC                     0x01
-#define BCMEP_BULK                     0x02
-#define BCMEP_INTR                     0x03
-
-#define BCMEP_OUT                      0x00
-#define BCMEP_IN                       0x01
-
-#define BCM63XX_SPD_FULL               1
-#define BCM63XX_SPD_HIGH               0
-
-#define IUDMA_DMAC_OFFSET              0x200
-#define IUDMA_DMAS_OFFSET              0x400
-
-enum bcm63xx_ep0_state {
-       EP0_REQUEUE,
-       EP0_IDLE,
-       EP0_IN_DATA_PHASE_SETUP,
-       EP0_IN_DATA_PHASE_COMPLETE,
-       EP0_OUT_DATA_PHASE_SETUP,
-       EP0_OUT_DATA_PHASE_COMPLETE,
-       EP0_OUT_STATUS_PHASE,
-       EP0_IN_FAKE_STATUS_PHASE,
-       EP0_SHUTDOWN,
-};
-
-static const char __maybe_unused bcm63xx_ep0_state_names[][32] = {
-       "REQUEUE",
-       "IDLE",
-       "IN_DATA_PHASE_SETUP",
-       "IN_DATA_PHASE_COMPLETE",
-       "OUT_DATA_PHASE_SETUP",
-       "OUT_DATA_PHASE_COMPLETE",
-       "OUT_STATUS_PHASE",
-       "IN_FAKE_STATUS_PHASE",
-       "SHUTDOWN",
-};
-
-/**
- * struct iudma_ch_cfg - Static configuration for an IUDMA channel.
- * @ep_num: USB endpoint number.
- * @n_bds: Number of buffer descriptors in the ring.
- * @ep_type: Endpoint type (control, bulk, interrupt).
- * @dir: Direction (in, out).
- * @n_fifo_slots: Number of FIFO entries to allocate for this channel.
- * @max_pkt_hs: Maximum packet size in high speed mode.
- * @max_pkt_fs: Maximum packet size in full speed mode.
- */
-struct iudma_ch_cfg {
-       int                             ep_num;
-       int                             n_bds;
-       int                             ep_type;
-       int                             dir;
-       int                             n_fifo_slots;
-       int                             max_pkt_hs;
-       int                             max_pkt_fs;
-};
-
-static const struct iudma_ch_cfg iudma_defaults[] = {
-
-       /* This controller was designed to support a CDC/RNDIS application.
-          It may be possible to reconfigure some of the endpoints, but
-          the hardware limitations (FIFO sizing and number of DMA channels)
-          may significantly impact flexibility and/or stability.  Change
-          these values at your own risk.
-
-             ep_num       ep_type           n_fifo_slots    max_pkt_fs
-       idx      |  n_bds     |         dir       |  max_pkt_hs  |
-        |       |    |       |          |        |      |       |       */
-       [0] = { -1,   4, BCMEP_CTRL, BCMEP_OUT,  32,    64,     64 },
-       [1] = {  0,   4, BCMEP_CTRL, BCMEP_OUT,  32,    64,     64 },
-       [2] = {  2,  16, BCMEP_BULK, BCMEP_OUT, 128,   512,     64 },
-       [3] = {  1,  16, BCMEP_BULK, BCMEP_IN,  128,   512,     64 },
-       [4] = {  4,   4, BCMEP_INTR, BCMEP_OUT,  32,    64,     64 },
-       [5] = {  3,   4, BCMEP_INTR, BCMEP_IN,   32,    64,     64 },
-};
-
-struct bcm63xx_udc;
-
-/**
- * struct iudma_ch - Represents the current state of a single IUDMA channel.
- * @ch_idx: IUDMA channel index (0 to BCM63XX_NUM_IUDMA-1).
- * @ep_num: USB endpoint number.  -1 for ep0 RX.
- * @enabled: Whether bcm63xx_ep_enable() has been called.
- * @max_pkt: "Chunk size" on the USB interface.  Based on interface speed.
- * @is_tx: true for TX, false for RX.
- * @bep: Pointer to the associated endpoint.  NULL for ep0 RX.
- * @udc: Reference to the device controller.
- * @read_bd: Next buffer descriptor to reap from the hardware.
- * @write_bd: Next BD available for a new packet.
- * @end_bd: Points to the final BD in the ring.
- * @n_bds_used: Number of BD entries currently occupied.
- * @bd_ring: Base pointer to the BD ring.
- * @bd_ring_dma: Physical (DMA) address of bd_ring.
- * @n_bds: Total number of BDs in the ring.
- *
- * ep0 has two IUDMA channels (IUDMA_EP0_RXCHAN and IUDMA_EP0_TXCHAN), as it is
- * bidirectional.  The "struct usb_ep" associated with ep0 is for TX (IN)
- * only.
- *
- * Each bulk/intr endpoint has a single IUDMA channel and a single
- * struct usb_ep.
- */
-struct iudma_ch {
-       unsigned int                    ch_idx;
-       int                             ep_num;
-       bool                            enabled;
-       int                             max_pkt;
-       bool                            is_tx;
-       struct bcm63xx_ep               *bep;
-       struct bcm63xx_udc              *udc;
-
-       struct bcm_enet_desc            *read_bd;
-       struct bcm_enet_desc            *write_bd;
-       struct bcm_enet_desc            *end_bd;
-       int                             n_bds_used;
-
-       struct bcm_enet_desc            *bd_ring;
-       dma_addr_t                      bd_ring_dma;
-       unsigned int                    n_bds;
-};
-
-/**
- * struct bcm63xx_ep - Internal (driver) state of a single endpoint.
- * @ep_num: USB endpoint number.
- * @iudma: Pointer to IUDMA channel state.
- * @ep: USB gadget layer representation of the EP.
- * @udc: Reference to the device controller.
- * @queue: Linked list of outstanding requests for this EP.
- * @halted: 1 if the EP is stalled; 0 otherwise.
- */
-struct bcm63xx_ep {
-       unsigned int                    ep_num;
-       struct iudma_ch                 *iudma;
-       struct usb_ep                   ep;
-       struct bcm63xx_udc              *udc;
-       struct list_head                queue;
-       unsigned                        halted:1;
-};
-
-/**
- * struct bcm63xx_req - Internal (driver) state of a single request.
- * @queue: Links back to the EP's request list.
- * @req: USB gadget layer representation of the request.
- * @offset: Current byte offset into the data buffer (next byte to queue).
- * @bd_bytes: Number of data bytes in outstanding BD entries.
- * @iudma: IUDMA channel used for the request.
- */
-struct bcm63xx_req {
-       struct list_head                queue;          /* ep's requests */
-       struct usb_request              req;
-       unsigned int                    offset;
-       unsigned int                    bd_bytes;
-       struct iudma_ch                 *iudma;
-};
-
-/**
- * struct bcm63xx_udc - Driver/hardware private context.
- * @lock: Spinlock to mediate access to this struct, and (most) HW regs.
- * @dev: Generic Linux device structure.
- * @pd: Platform data (board/port info).
- * @usbd_clk: Clock descriptor for the USB device block.
- * @usbh_clk: Clock descriptor for the USB host block.
- * @gadget: USB slave device.
- * @driver: Driver for USB slave devices.
- * @usbd_regs: Base address of the USBD/USB20D block.
- * @iudma_regs: Base address of the USBD's associated IUDMA block.
- * @bep: Array of endpoints, including ep0.
- * @iudma: Array of all IUDMA channels used by this controller.
- * @cfg: USB configuration number, from SET_CONFIGURATION wValue.
- * @iface: USB interface number, from SET_INTERFACE wIndex.
- * @alt_iface: USB alt interface number, from SET_INTERFACE wValue.
- * @ep0_ctrl_req: Request object for bcm63xx_udc-initiated ep0 transactions.
- * @ep0_ctrl_buf: Data buffer for ep0_ctrl_req.
- * @ep0state: Current state of the ep0 state machine.
- * @ep0_wq: Workqueue struct used to wake up the ep0 state machine.
- * @wedgemap: Bitmap of wedged endpoints.
- * @ep0_req_reset: USB reset is pending.
- * @ep0_req_set_cfg: Need to spoof a SET_CONFIGURATION packet.
- * @ep0_req_set_iface: Need to spoof a SET_INTERFACE packet.
- * @ep0_req_shutdown: Driver is shutting down; requesting ep0 to halt activity.
- * @ep0_req_completed: ep0 request has completed; worker has not seen it yet.
- * @ep0_reply: Pending reply from gadget driver.
- * @ep0_request: Outstanding ep0 request.
- * @debugfs_root: debugfs directory: /sys/kernel/debug/<DRV_MODULE_NAME>.
- * @debugfs_usbd: debugfs file "usbd" for controller state.
- * @debugfs_iudma: debugfs file "usbd" for IUDMA state.
- */
-struct bcm63xx_udc {
-       spinlock_t                      lock;
-
-       struct device                   *dev;
-       struct bcm63xx_usbd_platform_data *pd;
-       struct clk                      *usbd_clk;
-       struct clk                      *usbh_clk;
-
-       struct usb_gadget               gadget;
-       struct usb_gadget_driver        *driver;
-
-       void __iomem                    *usbd_regs;
-       void __iomem                    *iudma_regs;
-
-       struct bcm63xx_ep               bep[BCM63XX_NUM_EP];
-       struct iudma_ch                 iudma[BCM63XX_NUM_IUDMA];
-
-       int                             cfg;
-       int                             iface;
-       int                             alt_iface;
-
-       struct bcm63xx_req              ep0_ctrl_req;
-       u8                              *ep0_ctrl_buf;
-
-       int                             ep0state;
-       struct work_struct              ep0_wq;
-
-       unsigned long                   wedgemap;
-
-       unsigned                        ep0_req_reset:1;
-       unsigned                        ep0_req_set_cfg:1;
-       unsigned                        ep0_req_set_iface:1;
-       unsigned                        ep0_req_shutdown:1;
-
-       unsigned                        ep0_req_completed:1;
-       struct usb_request              *ep0_reply;
-       struct usb_request              *ep0_request;
-
-       struct dentry                   *debugfs_root;
-       struct dentry                   *debugfs_usbd;
-       struct dentry                   *debugfs_iudma;
-};
-
-static const struct usb_ep_ops bcm63xx_udc_ep_ops;
-
-/***********************************************************************
- * Convenience functions
- ***********************************************************************/
-
-static inline struct bcm63xx_udc *gadget_to_udc(struct usb_gadget *g)
-{
-       return container_of(g, struct bcm63xx_udc, gadget);
-}
-
-static inline struct bcm63xx_ep *our_ep(struct usb_ep *ep)
-{
-       return container_of(ep, struct bcm63xx_ep, ep);
-}
-
-static inline struct bcm63xx_req *our_req(struct usb_request *req)
-{
-       return container_of(req, struct bcm63xx_req, req);
-}
-
-static inline u32 usbd_readl(struct bcm63xx_udc *udc, u32 off)
-{
-       return bcm_readl(udc->usbd_regs + off);
-}
-
-static inline void usbd_writel(struct bcm63xx_udc *udc, u32 val, u32 off)
-{
-       bcm_writel(val, udc->usbd_regs + off);
-}
-
-static inline u32 usb_dma_readl(struct bcm63xx_udc *udc, u32 off)
-{
-       return bcm_readl(udc->iudma_regs + off);
-}
-
-static inline void usb_dma_writel(struct bcm63xx_udc *udc, u32 val, u32 off)
-{
-       bcm_writel(val, udc->iudma_regs + off);
-}
-
-static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off, int chan)
-{
-       return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off +
-                       (ENETDMA_CHAN_WIDTH * chan));
-}
-
-static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off,
-                                       int chan)
-{
-       bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off +
-                       (ENETDMA_CHAN_WIDTH * chan));
-}
-
-static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off, int chan)
-{
-       return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off +
-                       (ENETDMA_CHAN_WIDTH * chan));
-}
-
-static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off,
-                                       int chan)
-{
-       bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off +
-                       (ENETDMA_CHAN_WIDTH * chan));
-}
-
-static inline void set_clocks(struct bcm63xx_udc *udc, bool is_enabled)
-{
-       if (is_enabled) {
-               clk_enable(udc->usbh_clk);
-               clk_enable(udc->usbd_clk);
-               udelay(10);
-       } else {
-               clk_disable(udc->usbd_clk);
-               clk_disable(udc->usbh_clk);
-       }
-}
-
-/***********************************************************************
- * Low-level IUDMA / FIFO operations
- ***********************************************************************/
-
-/**
- * bcm63xx_ep_dma_select - Helper function to set up the init_sel signal.
- * @udc: Reference to the device controller.
- * @idx: Desired init_sel value.
- *
- * The "init_sel" signal is used as a selection index for both endpoints
- * and IUDMA channels.  Since these do not map 1:1, the use of this signal
- * depends on the context.
- */
-static void bcm63xx_ep_dma_select(struct bcm63xx_udc *udc, int idx)
-{
-       u32 val = usbd_readl(udc, USBD_CONTROL_REG);
-
-       val &= ~USBD_CONTROL_INIT_SEL_MASK;
-       val |= idx << USBD_CONTROL_INIT_SEL_SHIFT;
-       usbd_writel(udc, val, USBD_CONTROL_REG);
-}
-
-/**
- * bcm63xx_set_stall - Enable/disable stall on one endpoint.
- * @udc: Reference to the device controller.
- * @bep: Endpoint on which to operate.
- * @is_stalled: true to enable stall, false to disable.
- *
- * See notes in bcm63xx_update_wedge() regarding automatic clearing of
- * halt/stall conditions.
- */
-static void bcm63xx_set_stall(struct bcm63xx_udc *udc, struct bcm63xx_ep *bep,
-       bool is_stalled)
-{
-       u32 val;
-
-       val = USBD_STALL_UPDATE_MASK |
-               (is_stalled ? USBD_STALL_ENABLE_MASK : 0) |
-               (bep->ep_num << USBD_STALL_EPNUM_SHIFT);
-       usbd_writel(udc, val, USBD_STALL_REG);
-}
-
-/**
- * bcm63xx_fifo_setup - (Re)initialize FIFO boundaries and settings.
- * @udc: Reference to the device controller.
- *
- * These parameters depend on the USB link speed.  Settings are
- * per-IUDMA-channel-pair.
- */
-static void bcm63xx_fifo_setup(struct bcm63xx_udc *udc)
-{
-       int is_hs = udc->gadget.speed == USB_SPEED_HIGH;
-       u32 i, val, rx_fifo_slot, tx_fifo_slot;
-
-       /* set up FIFO boundaries and packet sizes; this is done in pairs */
-       rx_fifo_slot = tx_fifo_slot = 0;
-       for (i = 0; i < BCM63XX_NUM_IUDMA; i += 2) {
-               const struct iudma_ch_cfg *rx_cfg = &iudma_defaults[i];
-               const struct iudma_ch_cfg *tx_cfg = &iudma_defaults[i + 1];
-
-               bcm63xx_ep_dma_select(udc, i >> 1);
-
-               val = (rx_fifo_slot << USBD_RXFIFO_CONFIG_START_SHIFT) |
-                       ((rx_fifo_slot + rx_cfg->n_fifo_slots - 1) <<
-                        USBD_RXFIFO_CONFIG_END_SHIFT);
-               rx_fifo_slot += rx_cfg->n_fifo_slots;
-               usbd_writel(udc, val, USBD_RXFIFO_CONFIG_REG);
-               usbd_writel(udc,
-                           is_hs ? rx_cfg->max_pkt_hs : rx_cfg->max_pkt_fs,
-                           USBD_RXFIFO_EPSIZE_REG);
-
-               val = (tx_fifo_slot << USBD_TXFIFO_CONFIG_START_SHIFT) |
-                       ((tx_fifo_slot + tx_cfg->n_fifo_slots - 1) <<
-                        USBD_TXFIFO_CONFIG_END_SHIFT);
-               tx_fifo_slot += tx_cfg->n_fifo_slots;
-               usbd_writel(udc, val, USBD_TXFIFO_CONFIG_REG);
-               usbd_writel(udc,
-                           is_hs ? tx_cfg->max_pkt_hs : tx_cfg->max_pkt_fs,
-                           USBD_TXFIFO_EPSIZE_REG);
-
-               usbd_readl(udc, USBD_TXFIFO_EPSIZE_REG);
-       }
-}
-
-/**
- * bcm63xx_fifo_reset_ep - Flush a single endpoint's FIFO.
- * @udc: Reference to the device controller.
- * @ep_num: Endpoint number.
- */
-static void bcm63xx_fifo_reset_ep(struct bcm63xx_udc *udc, int ep_num)
-{
-       u32 val;
-
-       bcm63xx_ep_dma_select(udc, ep_num);
-
-       val = usbd_readl(udc, USBD_CONTROL_REG);
-       val |= USBD_CONTROL_FIFO_RESET_MASK;
-       usbd_writel(udc, val, USBD_CONTROL_REG);
-       usbd_readl(udc, USBD_CONTROL_REG);
-}
-
-/**
- * bcm63xx_fifo_reset - Flush all hardware FIFOs.
- * @udc: Reference to the device controller.
- */
-static void bcm63xx_fifo_reset(struct bcm63xx_udc *udc)
-{
-       int i;
-
-       for (i = 0; i < BCM63XX_NUM_FIFO_PAIRS; i++)
-               bcm63xx_fifo_reset_ep(udc, i);
-}
-
-/**
- * bcm63xx_ep_init - Initial (one-time) endpoint initialization.
- * @udc: Reference to the device controller.
- */
-static void bcm63xx_ep_init(struct bcm63xx_udc *udc)
-{
-       u32 i, val;
-
-       for (i = 0; i < BCM63XX_NUM_IUDMA; i++) {
-               const struct iudma_ch_cfg *cfg = &iudma_defaults[i];
-
-               if (cfg->ep_num < 0)
-                       continue;
-
-               bcm63xx_ep_dma_select(udc, cfg->ep_num);
-               val = (cfg->ep_type << USBD_EPNUM_TYPEMAP_TYPE_SHIFT) |
-                       ((i >> 1) << USBD_EPNUM_TYPEMAP_DMA_CH_SHIFT);
-               usbd_writel(udc, val, USBD_EPNUM_TYPEMAP_REG);
-       }
-}
-
-/**
- * bcm63xx_ep_setup - Configure per-endpoint settings.
- * @udc: Reference to the device controller.
- *
- * This needs to be rerun if the speed/cfg/intf/altintf changes.
- */
-static void bcm63xx_ep_setup(struct bcm63xx_udc *udc)
-{
-       u32 val, i;
-
-       usbd_writel(udc, USBD_CSR_SETUPADDR_DEF, USBD_CSR_SETUPADDR_REG);
-
-       for (i = 0; i < BCM63XX_NUM_IUDMA; i++) {
-               const struct iudma_ch_cfg *cfg = &iudma_defaults[i];
-               int max_pkt = udc->gadget.speed == USB_SPEED_HIGH ?
-                             cfg->max_pkt_hs : cfg->max_pkt_fs;
-               int idx = cfg->ep_num;
-
-               udc->iudma[i].max_pkt = max_pkt;
-
-               if (idx < 0)
-                       continue;
-               usb_ep_set_maxpacket_limit(&udc->bep[idx].ep, max_pkt);
-
-               val = (idx << USBD_CSR_EP_LOG_SHIFT) |
-                     (cfg->dir << USBD_CSR_EP_DIR_SHIFT) |
-                     (cfg->ep_type << USBD_CSR_EP_TYPE_SHIFT) |
-                     (udc->cfg << USBD_CSR_EP_CFG_SHIFT) |
-                     (udc->iface << USBD_CSR_EP_IFACE_SHIFT) |
-                     (udc->alt_iface << USBD_CSR_EP_ALTIFACE_SHIFT) |
-                     (max_pkt << USBD_CSR_EP_MAXPKT_SHIFT);
-               usbd_writel(udc, val, USBD_CSR_EP_REG(idx));
-       }
-}
-
-/**
- * iudma_write - Queue a single IUDMA transaction.
- * @udc: Reference to the device controller.
- * @iudma: IUDMA channel to use.
- * @breq: Request containing the transaction data.
- *
- * For RX IUDMA, this will queue a single buffer descriptor, as RX IUDMA
- * does not honor SOP/EOP so the handling of multiple buffers is ambiguous.
- * So iudma_write() may be called several times to fulfill a single
- * usb_request.
- *
- * For TX IUDMA, this can queue multiple buffer descriptors if needed.
- */
-static void iudma_write(struct bcm63xx_udc *udc, struct iudma_ch *iudma,
-       struct bcm63xx_req *breq)
-{
-       int first_bd = 1, last_bd = 0, extra_zero_pkt = 0;
-       unsigned int bytes_left = breq->req.length - breq->offset;
-       const int max_bd_bytes = !irq_coalesce && !iudma->is_tx ?
-               iudma->max_pkt : IUDMA_MAX_FRAGMENT;
-
-       iudma->n_bds_used = 0;
-       breq->bd_bytes = 0;
-       breq->iudma = iudma;
-
-       if ((bytes_left % iudma->max_pkt == 0) && bytes_left && breq->req.zero)
-               extra_zero_pkt = 1;
-
-       do {
-               struct bcm_enet_desc *d = iudma->write_bd;
-               u32 dmaflags = 0;
-               unsigned int n_bytes;
-
-               if (d == iudma->end_bd) {
-                       dmaflags |= DMADESC_WRAP_MASK;
-                       iudma->write_bd = iudma->bd_ring;
-               } else {
-                       iudma->write_bd++;
-               }
-               iudma->n_bds_used++;
-
-               n_bytes = min_t(int, bytes_left, max_bd_bytes);
-               if (n_bytes)
-                       dmaflags |= n_bytes << DMADESC_LENGTH_SHIFT;
-               else
-                       dmaflags |= (1 << DMADESC_LENGTH_SHIFT) |
-                                   DMADESC_USB_ZERO_MASK;
-
-               dmaflags |= DMADESC_OWNER_MASK;
-               if (first_bd) {
-                       dmaflags |= DMADESC_SOP_MASK;
-                       first_bd = 0;
-               }
-
-               /*
-                * extra_zero_pkt forces one more iteration through the loop
-                * after all data is queued up, to send the zero packet
-                */
-               if (extra_zero_pkt && !bytes_left)
-                       extra_zero_pkt = 0;
-
-               if (!iudma->is_tx || iudma->n_bds_used == iudma->n_bds ||
-                   (n_bytes == bytes_left && !extra_zero_pkt)) {
-                       last_bd = 1;
-                       dmaflags |= DMADESC_EOP_MASK;
-               }
-
-               d->address = breq->req.dma + breq->offset;
-               mb();
-               d->len_stat = dmaflags;
-
-               breq->offset += n_bytes;
-               breq->bd_bytes += n_bytes;
-               bytes_left -= n_bytes;
-       } while (!last_bd);
-
-       usb_dmac_writel(udc, ENETDMAC_CHANCFG_EN_MASK,
-                       ENETDMAC_CHANCFG_REG, iudma->ch_idx);
-}
-
-/**
- * iudma_read - Check for IUDMA buffer completion.
- * @udc: Reference to the device controller.
- * @iudma: IUDMA channel to use.
- *
- * This checks to see if ALL of the outstanding BDs on the DMA channel
- * have been filled.  If so, it returns the actual transfer length;
- * otherwise it returns -EBUSY.
- */
-static int iudma_read(struct bcm63xx_udc *udc, struct iudma_ch *iudma)
-{
-       int i, actual_len = 0;
-       struct bcm_enet_desc *d = iudma->read_bd;
-
-       if (!iudma->n_bds_used)
-               return -EINVAL;
-
-       for (i = 0; i < iudma->n_bds_used; i++) {
-               u32 dmaflags;
-
-               dmaflags = d->len_stat;
-
-               if (dmaflags & DMADESC_OWNER_MASK)
-                       return -EBUSY;
-
-               actual_len += (dmaflags & DMADESC_LENGTH_MASK) >>
-                             DMADESC_LENGTH_SHIFT;
-               if (d == iudma->end_bd)
-                       d = iudma->bd_ring;
-               else
-                       d++;
-       }
-
-       iudma->read_bd = d;
-       iudma->n_bds_used = 0;
-       return actual_len;
-}
-
-/**
- * iudma_reset_channel - Stop DMA on a single channel.
- * @udc: Reference to the device controller.
- * @iudma: IUDMA channel to reset.
- */
-static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma)
-{
-       int timeout = IUDMA_RESET_TIMEOUT_US;
-       struct bcm_enet_desc *d;
-       int ch_idx = iudma->ch_idx;
-
-       if (!iudma->is_tx)
-               bcm63xx_fifo_reset_ep(udc, max(0, iudma->ep_num));
-
-       /* stop DMA, then wait for the hardware to wrap up */
-       usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG, ch_idx);
-
-       while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx) &
-                                  ENETDMAC_CHANCFG_EN_MASK) {
-               udelay(1);
-
-               /* repeatedly flush the FIFO data until the BD completes */
-               if (iudma->is_tx && iudma->ep_num >= 0)
-                       bcm63xx_fifo_reset_ep(udc, iudma->ep_num);
-
-               if (!timeout--) {
-                       dev_err(udc->dev, "can't reset IUDMA channel %d\n",
-                               ch_idx);
-                       break;
-               }
-               if (timeout == IUDMA_RESET_TIMEOUT_US / 2) {
-                       dev_warn(udc->dev, "forcibly halting IUDMA channel %d\n",
-                                ch_idx);
-                       usb_dmac_writel(udc, ENETDMAC_CHANCFG_BUFHALT_MASK,
-                                       ENETDMAC_CHANCFG_REG, ch_idx);
-               }
-       }
-       usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG, ch_idx);
-
-       /* don't leave "live" HW-owned entries for the next guy to step on */
-       for (d = iudma->bd_ring; d <= iudma->end_bd; d++)
-               d->len_stat = 0;
-       mb();
-
-       iudma->read_bd = iudma->write_bd = iudma->bd_ring;
-       iudma->n_bds_used = 0;
-
-       /* set up IRQs, UBUS burst size, and BD base for this channel */
-       usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK,
-                       ENETDMAC_IRMASK_REG, ch_idx);
-       usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG, ch_idx);
-
-       usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG, ch_idx);
-       usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG, ch_idx);
-}
-
-/**
- * iudma_init_channel - One-time IUDMA channel initialization.
- * @udc: Reference to the device controller.
- * @ch_idx: Channel to initialize.
- */
-static int iudma_init_channel(struct bcm63xx_udc *udc, unsigned int ch_idx)
-{
-       struct iudma_ch *iudma = &udc->iudma[ch_idx];
-       const struct iudma_ch_cfg *cfg = &iudma_defaults[ch_idx];
-       unsigned int n_bds = cfg->n_bds;
-       struct bcm63xx_ep *bep = NULL;
-
-       iudma->ep_num = cfg->ep_num;
-       iudma->ch_idx = ch_idx;
-       iudma->is_tx = !!(ch_idx & 0x01);
-       if (iudma->ep_num >= 0) {
-               bep = &udc->bep[iudma->ep_num];
-               bep->iudma = iudma;
-               INIT_LIST_HEAD(&bep->queue);
-       }
-
-       iudma->bep = bep;
-       iudma->udc = udc;
-
-       /* ep0 is always active; others are controlled by the gadget driver */
-       if (iudma->ep_num <= 0)
-               iudma->enabled = true;
-
-       iudma->n_bds = n_bds;
-       iudma->bd_ring = dmam_alloc_coherent(udc->dev,
-               n_bds * sizeof(struct bcm_enet_desc),
-               &iudma->bd_ring_dma, GFP_KERNEL);
-       if (!iudma->bd_ring)
-               return -ENOMEM;
-       iudma->end_bd = &iudma->bd_ring[n_bds - 1];
-
-       return 0;
-}
-
-/**
- * iudma_init - One-time initialization of all IUDMA channels.
- * @udc: Reference to the device controller.
- *
- * Enable DMA, flush channels, and enable global IUDMA IRQs.
- */
-static int iudma_init(struct bcm63xx_udc *udc)
-{
-       int i, rc;
-
-       usb_dma_writel(udc, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG);
-
-       for (i = 0; i < BCM63XX_NUM_IUDMA; i++) {
-               rc = iudma_init_channel(udc, i);
-               if (rc)
-                       return rc;
-               iudma_reset_channel(udc, &udc->iudma[i]);
-       }
-
-       usb_dma_writel(udc, BIT(BCM63XX_NUM_IUDMA)-1, ENETDMA_GLB_IRQMASK_REG);
-       return 0;
-}
-
-/**
- * iudma_uninit - Uninitialize IUDMA channels.
- * @udc: Reference to the device controller.
- *
- * Kill global IUDMA IRQs, flush channels, and kill DMA.
- */
-static void iudma_uninit(struct bcm63xx_udc *udc)
-{
-       int i;
-
-       usb_dma_writel(udc, 0, ENETDMA_GLB_IRQMASK_REG);
-
-       for (i = 0; i < BCM63XX_NUM_IUDMA; i++)
-               iudma_reset_channel(udc, &udc->iudma[i]);
-
-       usb_dma_writel(udc, 0, ENETDMA_CFG_REG);
-}
-
-/***********************************************************************
- * Other low-level USBD operations
- ***********************************************************************/
-
-/**
- * bcm63xx_set_ctrl_irqs - Mask/unmask control path interrupts.
- * @udc: Reference to the device controller.
- * @enable_irqs: true to enable, false to disable.
- */
-static void bcm63xx_set_ctrl_irqs(struct bcm63xx_udc *udc, bool enable_irqs)
-{
-       u32 val;
-
-       usbd_writel(udc, 0, USBD_STATUS_REG);
-
-       val = BIT(USBD_EVENT_IRQ_USB_RESET) |
-             BIT(USBD_EVENT_IRQ_SETUP) |
-             BIT(USBD_EVENT_IRQ_SETCFG) |
-             BIT(USBD_EVENT_IRQ_SETINTF) |
-             BIT(USBD_EVENT_IRQ_USB_LINK);
-       usbd_writel(udc, enable_irqs ? val : 0, USBD_EVENT_IRQ_MASK_REG);
-       usbd_writel(udc, val, USBD_EVENT_IRQ_STATUS_REG);
-}
-
-/**
- * bcm63xx_select_phy_mode - Select between USB device and host mode.
- * @udc: Reference to the device controller.
- * @is_device: true for device, false for host.
- *
- * This should probably be reworked to use the drivers/usb/otg
- * infrastructure.
- *
- * By default, the AFE/pullups are disabled in device mode, until
- * bcm63xx_select_pullup() is called.
- */
-static void bcm63xx_select_phy_mode(struct bcm63xx_udc *udc, bool is_device)
-{
-       u32 val, portmask = BIT(udc->pd->port_no);
-
-       if (BCMCPU_IS_6328()) {
-               /* configure pinmux to sense VBUS signal */
-               val = bcm_gpio_readl(GPIO_PINMUX_OTHR_REG);
-               val &= ~GPIO_PINMUX_OTHR_6328_USB_MASK;
-               val |= is_device ? GPIO_PINMUX_OTHR_6328_USB_DEV :
-                              GPIO_PINMUX_OTHR_6328_USB_HOST;
-               bcm_gpio_writel(val, GPIO_PINMUX_OTHR_REG);
-       }
-
-       val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
-       if (is_device) {
-               val |= (portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
-               val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
-       } else {
-               val &= ~(portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
-               val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
-       }
-       bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
-
-       val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
-       if (is_device)
-               val |= USBH_PRIV_SWAP_USBD_MASK;
-       else
-               val &= ~USBH_PRIV_SWAP_USBD_MASK;
-       bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG);
-}
-
-/**
- * bcm63xx_select_pullup - Enable/disable the pullup on D+
- * @udc: Reference to the device controller.
- * @is_on: true to enable the pullup, false to disable.
- *
- * If the pullup is active, the host will sense a FS/HS device connected to
- * the port.  If the pullup is inactive, the host will think the USB
- * device has been disconnected.
- */
-static void bcm63xx_select_pullup(struct bcm63xx_udc *udc, bool is_on)
-{
-       u32 val, portmask = BIT(udc->pd->port_no);
-
-       val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
-       if (is_on)
-               val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
-       else
-               val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
-       bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
-}
-
-/**
- * bcm63xx_uninit_udc_hw - Shut down the hardware prior to driver removal.
- * @udc: Reference to the device controller.
- *
- * This just masks the IUDMA IRQs and releases the clocks.  It is assumed
- * that bcm63xx_udc_stop() has already run, and the clocks are stopped.
- */
-static void bcm63xx_uninit_udc_hw(struct bcm63xx_udc *udc)
-{
-       set_clocks(udc, true);
-       iudma_uninit(udc);
-       set_clocks(udc, false);
-
-       clk_put(udc->usbd_clk);
-       clk_put(udc->usbh_clk);
-}
-
-/**
- * bcm63xx_init_udc_hw - Initialize the controller hardware and data structures.
- * @udc: Reference to the device controller.
- */
-static int bcm63xx_init_udc_hw(struct bcm63xx_udc *udc)
-{
-       int i, rc = 0;
-       u32 val;
-
-       udc->ep0_ctrl_buf = devm_kzalloc(udc->dev, BCM63XX_MAX_CTRL_PKT,
-                                        GFP_KERNEL);
-       if (!udc->ep0_ctrl_buf)
-               return -ENOMEM;
-
-       INIT_LIST_HEAD(&udc->gadget.ep_list);
-       for (i = 0; i < BCM63XX_NUM_EP; i++) {
-               struct bcm63xx_ep *bep = &udc->bep[i];
-
-               bep->ep.name = bcm63xx_ep_name[i];
-               bep->ep_num = i;
-               bep->ep.ops = &bcm63xx_udc_ep_ops;
-               list_add_tail(&bep->ep.ep_list, &udc->gadget.ep_list);
-               bep->halted = 0;
-               usb_ep_set_maxpacket_limit(&bep->ep, BCM63XX_MAX_CTRL_PKT);
-               bep->udc = udc;
-               bep->ep.desc = NULL;
-               INIT_LIST_HEAD(&bep->queue);
-       }
-
-       udc->gadget.ep0 = &udc->bep[0].ep;
-       list_del(&udc->bep[0].ep.ep_list);
-
-       udc->gadget.speed = USB_SPEED_UNKNOWN;
-       udc->ep0state = EP0_SHUTDOWN;
-
-       udc->usbh_clk = clk_get(udc->dev, "usbh");
-       if (IS_ERR(udc->usbh_clk))
-               return -EIO;
-
-       udc->usbd_clk = clk_get(udc->dev, "usbd");
-       if (IS_ERR(udc->usbd_clk)) {
-               clk_put(udc->usbh_clk);
-               return -EIO;
-       }
-
-       set_clocks(udc, true);
-
-       val = USBD_CONTROL_AUTO_CSRS_MASK |
-             USBD_CONTROL_DONE_CSRS_MASK |
-             (irq_coalesce ? USBD_CONTROL_RXZSCFG_MASK : 0);
-       usbd_writel(udc, val, USBD_CONTROL_REG);
-
-       val = USBD_STRAPS_APP_SELF_PWR_MASK |
-             USBD_STRAPS_APP_RAM_IF_MASK |
-             USBD_STRAPS_APP_CSRPRGSUP_MASK |
-             USBD_STRAPS_APP_8BITPHY_MASK |
-             USBD_STRAPS_APP_RMTWKUP_MASK;
-
-       if (udc->gadget.max_speed == USB_SPEED_HIGH)
-               val |= (BCM63XX_SPD_HIGH << USBD_STRAPS_SPEED_SHIFT);
-       else
-               val |= (BCM63XX_SPD_FULL << USBD_STRAPS_SPEED_SHIFT);
-       usbd_writel(udc, val, USBD_STRAPS_REG);
-
-       bcm63xx_set_ctrl_irqs(udc, false);
-
-       usbd_writel(udc, 0, USBD_EVENT_IRQ_CFG_LO_REG);
-
-       val = USBD_EVENT_IRQ_CFG_FALLING(USBD_EVENT_IRQ_ENUM_ON) |
-             USBD_EVENT_IRQ_CFG_FALLING(USBD_EVENT_IRQ_SET_CSRS);
-       usbd_writel(udc, val, USBD_EVENT_IRQ_CFG_HI_REG);
-
-       rc = iudma_init(udc);
-       set_clocks(udc, false);
-       if (rc)
-               bcm63xx_uninit_udc_hw(udc);
-
-       return 0;
-}
-
-/***********************************************************************
- * Standard EP gadget operations
- ***********************************************************************/
-
-/**
- * bcm63xx_ep_enable - Enable one endpoint.
- * @ep: Endpoint to enable.
- * @desc: Contains max packet, direction, etc.
- *
- * Most of the endpoint parameters are fixed in this controller, so there
- * isn't much for this function to do.
- */
-static int bcm63xx_ep_enable(struct usb_ep *ep,
-       const struct usb_endpoint_descriptor *desc)
-{
-       struct bcm63xx_ep *bep = our_ep(ep);
-       struct bcm63xx_udc *udc = bep->udc;
-       struct iudma_ch *iudma = bep->iudma;
-       unsigned long flags;
-
-       if (!ep || !desc || ep->name == bcm63xx_ep0name)
-               return -EINVAL;
-
-       if (!udc->driver)
-               return -ESHUTDOWN;
-
-       spin_lock_irqsave(&udc->lock, flags);
-       if (iudma->enabled) {
-               spin_unlock_irqrestore(&udc->lock, flags);
-               return -EINVAL;
-       }
-
-       iudma->enabled = true;
-       BUG_ON(!list_empty(&bep->queue));
-
-       iudma_reset_channel(udc, iudma);
-
-       bep->halted = 0;
-       bcm63xx_set_stall(udc, bep, false);
-       clear_bit(bep->ep_num, &udc->wedgemap);
-
-       ep->desc = desc;
-       ep->maxpacket = usb_endpoint_maxp(desc);
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return 0;
-}
-
-/**
- * bcm63xx_ep_disable - Disable one endpoint.
- * @ep: Endpoint to disable.
- */
-static int bcm63xx_ep_disable(struct usb_ep *ep)
-{
-       struct bcm63xx_ep *bep = our_ep(ep);
-       struct bcm63xx_udc *udc = bep->udc;
-       struct iudma_ch *iudma = bep->iudma;
-       struct list_head *pos, *n;
-       unsigned long flags;
-
-       if (!ep || !ep->desc)
-               return -EINVAL;
-
-       spin_lock_irqsave(&udc->lock, flags);
-       if (!iudma->enabled) {
-               spin_unlock_irqrestore(&udc->lock, flags);
-               return -EINVAL;
-       }
-       iudma->enabled = false;
-
-       iudma_reset_channel(udc, iudma);
-
-       if (!list_empty(&bep->queue)) {
-               list_for_each_safe(pos, n, &bep->queue) {
-                       struct bcm63xx_req *breq =
-                               list_entry(pos, struct bcm63xx_req, queue);
-
-                       usb_gadget_unmap_request(&udc->gadget, &breq->req,
-                                                iudma->is_tx);
-                       list_del(&breq->queue);
-                       breq->req.status = -ESHUTDOWN;
-
-                       spin_unlock_irqrestore(&udc->lock, flags);
-                       breq->req.complete(&iudma->bep->ep, &breq->req);
-                       spin_lock_irqsave(&udc->lock, flags);
-               }
-       }
-       ep->desc = NULL;
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return 0;
-}
-
-/**
- * bcm63xx_udc_alloc_request - Allocate a new request.
- * @ep: Endpoint associated with the request.
- * @mem_flags: Flags to pass to kzalloc().
- */
-static struct usb_request *bcm63xx_udc_alloc_request(struct usb_ep *ep,
-       gfp_t mem_flags)
-{
-       struct bcm63xx_req *breq;
-
-       breq = kzalloc(sizeof(*breq), mem_flags);
-       if (!breq)
-               return NULL;
-       return &breq->req;
-}
-
-/**
- * bcm63xx_udc_free_request - Free a request.
- * @ep: Endpoint associated with the request.
- * @req: Request to free.
- */
-static void bcm63xx_udc_free_request(struct usb_ep *ep,
-       struct usb_request *req)
-{
-       struct bcm63xx_req *breq = our_req(req);
-       kfree(breq);
-}
-
-/**
- * bcm63xx_udc_queue - Queue up a new request.
- * @ep: Endpoint associated with the request.
- * @req: Request to add.
- * @mem_flags: Unused.
- *
- * If the queue is empty, start this request immediately.  Otherwise, add
- * it to the list.
- *
- * ep0 replies are sent through this function from the gadget driver, but
- * they are treated differently because they need to be handled by the ep0
- * state machine.  (Sometimes they are replies to control requests that
- * were spoofed by this driver, and so they shouldn't be transmitted at all.)
- */
-static int bcm63xx_udc_queue(struct usb_ep *ep, struct usb_request *req,
-       gfp_t mem_flags)
-{
-       struct bcm63xx_ep *bep = our_ep(ep);
-       struct bcm63xx_udc *udc = bep->udc;
-       struct bcm63xx_req *breq = our_req(req);
-       unsigned long flags;
-       int rc = 0;
-
-       if (unlikely(!req || !req->complete || !req->buf || !ep))
-               return -EINVAL;
-
-       req->actual = 0;
-       req->status = 0;
-       breq->offset = 0;
-
-       if (bep == &udc->bep[0]) {
-               /* only one reply per request, please */
-               if (udc->ep0_reply)
-                       return -EINVAL;
-
-               udc->ep0_reply = req;
-               schedule_work(&udc->ep0_wq);
-               return 0;
-       }
-
-       spin_lock_irqsave(&udc->lock, flags);
-       if (!bep->iudma->enabled) {
-               rc = -ESHUTDOWN;
-               goto out;
-       }
-
-       rc = usb_gadget_map_request(&udc->gadget, req, bep->iudma->is_tx);
-       if (rc == 0) {
-               list_add_tail(&breq->queue, &bep->queue);
-               if (list_is_singular(&bep->queue))
-                       iudma_write(udc, bep->iudma, breq);
-       }
-
-out:
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return rc;
-}
-
-/**
- * bcm63xx_udc_dequeue - Remove a pending request from the queue.
- * @ep: Endpoint associated with the request.
- * @req: Request to remove.
- *
- * If the request is not at the head of the queue, this is easy - just nuke
- * it.  If the request is at the head of the queue, we'll need to stop the
- * DMA transaction and then queue up the successor.
- */
-static int bcm63xx_udc_dequeue(struct usb_ep *ep, struct usb_request *req)
-{
-       struct bcm63xx_ep *bep = our_ep(ep);
-       struct bcm63xx_udc *udc = bep->udc;
-       struct bcm63xx_req *breq = our_req(req), *cur;
-       unsigned long flags;
-       int rc = 0;
-
-       spin_lock_irqsave(&udc->lock, flags);
-       if (list_empty(&bep->queue)) {
-               rc = -EINVAL;
-               goto out;
-       }
-
-       cur = list_first_entry(&bep->queue, struct bcm63xx_req, queue);
-       usb_gadget_unmap_request(&udc->gadget, &breq->req, bep->iudma->is_tx);
-
-       if (breq == cur) {
-               iudma_reset_channel(udc, bep->iudma);
-               list_del(&breq->queue);
-
-               if (!list_empty(&bep->queue)) {
-                       struct bcm63xx_req *next;
-
-                       next = list_first_entry(&bep->queue,
-                               struct bcm63xx_req, queue);
-                       iudma_write(udc, bep->iudma, next);
-               }
-       } else {
-               list_del(&breq->queue);
-       }
-
-out:
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       req->status = -ESHUTDOWN;
-       req->complete(ep, req);
-
-       return rc;
-}
-
-/**
- * bcm63xx_udc_set_halt - Enable/disable STALL flag in the hardware.
- * @ep: Endpoint to halt.
- * @value: Zero to clear halt; nonzero to set halt.
- *
- * See comments in bcm63xx_update_wedge().
- */
-static int bcm63xx_udc_set_halt(struct usb_ep *ep, int value)
-{
-       struct bcm63xx_ep *bep = our_ep(ep);
-       struct bcm63xx_udc *udc = bep->udc;
-       unsigned long flags;
-
-       spin_lock_irqsave(&udc->lock, flags);
-       bcm63xx_set_stall(udc, bep, !!value);
-       bep->halted = value;
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-/**
- * bcm63xx_udc_set_wedge - Stall the endpoint until the next reset.
- * @ep: Endpoint to wedge.
- *
- * See comments in bcm63xx_update_wedge().
- */
-static int bcm63xx_udc_set_wedge(struct usb_ep *ep)
-{
-       struct bcm63xx_ep *bep = our_ep(ep);
-       struct bcm63xx_udc *udc = bep->udc;
-       unsigned long flags;
-
-       spin_lock_irqsave(&udc->lock, flags);
-       set_bit(bep->ep_num, &udc->wedgemap);
-       bcm63xx_set_stall(udc, bep, true);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-static const struct usb_ep_ops bcm63xx_udc_ep_ops = {
-       .enable         = bcm63xx_ep_enable,
-       .disable        = bcm63xx_ep_disable,
-
-       .alloc_request  = bcm63xx_udc_alloc_request,
-       .free_request   = bcm63xx_udc_free_request,
-
-       .queue          = bcm63xx_udc_queue,
-       .dequeue        = bcm63xx_udc_dequeue,
-
-       .set_halt       = bcm63xx_udc_set_halt,
-       .set_wedge      = bcm63xx_udc_set_wedge,
-};
-
-/***********************************************************************
- * EP0 handling
- ***********************************************************************/
-
-/**
- * bcm63xx_ep0_setup_callback - Drop spinlock to invoke ->setup callback.
- * @udc: Reference to the device controller.
- * @ctrl: 8-byte SETUP request.
- */
-static int bcm63xx_ep0_setup_callback(struct bcm63xx_udc *udc,
-       struct usb_ctrlrequest *ctrl)
-{
-       int rc;
-
-       spin_unlock_irq(&udc->lock);
-       rc = udc->driver->setup(&udc->gadget, ctrl);
-       spin_lock_irq(&udc->lock);
-       return rc;
-}
-
-/**
- * bcm63xx_ep0_spoof_set_cfg - Synthesize a SET_CONFIGURATION request.
- * @udc: Reference to the device controller.
- *
- * Many standard requests are handled automatically in the hardware, but
- * we still need to pass them to the gadget driver so that it can
- * reconfigure the interfaces/endpoints if necessary.
- *
- * Unfortunately we are not able to send a STALL response if the host
- * requests an invalid configuration.  If this happens, we'll have to be
- * content with printing a warning.
- */
-static int bcm63xx_ep0_spoof_set_cfg(struct bcm63xx_udc *udc)
-{
-       struct usb_ctrlrequest ctrl;
-       int rc;
-
-       ctrl.bRequestType = USB_DIR_OUT | USB_RECIP_DEVICE;
-       ctrl.bRequest = USB_REQ_SET_CONFIGURATION;
-       ctrl.wValue = cpu_to_le16(udc->cfg);
-       ctrl.wIndex = 0;
-       ctrl.wLength = 0;
-
-       rc = bcm63xx_ep0_setup_callback(udc, &ctrl);
-       if (rc < 0) {
-               dev_warn_ratelimited(udc->dev,
-                       "hardware auto-acked bad SET_CONFIGURATION(%d) request\n",
-                       udc->cfg);
-       }
-       return rc;
-}
-
-/**
- * bcm63xx_ep0_spoof_set_iface - Synthesize a SET_INTERFACE request.
- * @udc: Reference to the device controller.
- */
-static int bcm63xx_ep0_spoof_set_iface(struct bcm63xx_udc *udc)
-{
-       struct usb_ctrlrequest ctrl;
-       int rc;
-
-       ctrl.bRequestType = USB_DIR_OUT | USB_RECIP_INTERFACE;
-       ctrl.bRequest = USB_REQ_SET_INTERFACE;
-       ctrl.wValue = cpu_to_le16(udc->alt_iface);
-       ctrl.wIndex = cpu_to_le16(udc->iface);
-       ctrl.wLength = 0;
-
-       rc = bcm63xx_ep0_setup_callback(udc, &ctrl);
-       if (rc < 0) {
-               dev_warn_ratelimited(udc->dev,
-                       "hardware auto-acked bad SET_INTERFACE(%d,%d) request\n",
-                       udc->iface, udc->alt_iface);
-       }
-       return rc;
-}
-
-/**
- * bcm63xx_ep0_map_write - dma_map and iudma_write a single request.
- * @udc: Reference to the device controller.
- * @ch_idx: IUDMA channel number.
- * @req: USB gadget layer representation of the request.
- */
-static void bcm63xx_ep0_map_write(struct bcm63xx_udc *udc, int ch_idx,
-       struct usb_request *req)
-{
-       struct bcm63xx_req *breq = our_req(req);
-       struct iudma_ch *iudma = &udc->iudma[ch_idx];
-
-       BUG_ON(udc->ep0_request);
-       udc->ep0_request = req;
-
-       req->actual = 0;
-       breq->offset = 0;
-       usb_gadget_map_request(&udc->gadget, req, iudma->is_tx);
-       iudma_write(udc, iudma, breq);
-}
-
-/**
- * bcm63xx_ep0_complete - Set completion status and "stage" the callback.
- * @udc: Reference to the device controller.
- * @req: USB gadget layer representation of the request.
- * @status: Status to return to the gadget driver.
- */
-static void bcm63xx_ep0_complete(struct bcm63xx_udc *udc,
-       struct usb_request *req, int status)
-{
-       req->status = status;
-       if (status)
-               req->actual = 0;
-       if (req->complete) {
-               spin_unlock_irq(&udc->lock);
-               req->complete(&udc->bep[0].ep, req);
-               spin_lock_irq(&udc->lock);
-       }
-}
-
-/**
- * bcm63xx_ep0_nuke_reply - Abort request from the gadget driver due to
- *   reset/shutdown.
- * @udc: Reference to the device controller.
- * @is_tx: Nonzero for TX (IN), zero for RX (OUT).
- */
-static void bcm63xx_ep0_nuke_reply(struct bcm63xx_udc *udc, int is_tx)
-{
-       struct usb_request *req = udc->ep0_reply;
-
-       udc->ep0_reply = NULL;
-       usb_gadget_unmap_request(&udc->gadget, req, is_tx);
-       if (udc->ep0_request == req) {
-               udc->ep0_req_completed = 0;
-               udc->ep0_request = NULL;
-       }
-       bcm63xx_ep0_complete(udc, req, -ESHUTDOWN);
-}
-
-/**
- * bcm63xx_ep0_read_complete - Close out the pending ep0 request; return
- *   transfer len.
- * @udc: Reference to the device controller.
- */
-static int bcm63xx_ep0_read_complete(struct bcm63xx_udc *udc)
-{
-       struct usb_request *req = udc->ep0_request;
-
-       udc->ep0_req_completed = 0;
-       udc->ep0_request = NULL;
-
-       return req->actual;
-}
-
-/**
- * bcm63xx_ep0_internal_request - Helper function to submit an ep0 request.
- * @udc: Reference to the device controller.
- * @ch_idx: IUDMA channel number.
- * @length: Number of bytes to TX/RX.
- *
- * Used for simple transfers performed by the ep0 worker.  This will always
- * use ep0_ctrl_req / ep0_ctrl_buf.
- */
-static void bcm63xx_ep0_internal_request(struct bcm63xx_udc *udc, int ch_idx,
-       int length)
-{
-       struct usb_request *req = &udc->ep0_ctrl_req.req;
-
-       req->buf = udc->ep0_ctrl_buf;
-       req->length = length;
-       req->complete = NULL;
-
-       bcm63xx_ep0_map_write(udc, ch_idx, req);
-}
-
-/**
- * bcm63xx_ep0_do_setup - Parse new SETUP packet and decide how to handle it.
- * @udc: Reference to the device controller.
- *
- * EP0_IDLE probably shouldn't ever happen.  EP0_REQUEUE means we're ready
- * for the next packet.  Anything else means the transaction requires multiple
- * stages of handling.
- */
-static enum bcm63xx_ep0_state bcm63xx_ep0_do_setup(struct bcm63xx_udc *udc)
-{
-       int rc;
-       struct usb_ctrlrequest *ctrl = (void *)udc->ep0_ctrl_buf;
-
-       rc = bcm63xx_ep0_read_complete(udc);
-
-       if (rc < 0) {
-               dev_err(udc->dev, "missing SETUP packet\n");
-               return EP0_IDLE;
-       }
-
-       /*
-        * Handle 0-byte IN STATUS acknowledgement.  The hardware doesn't
-        * ALWAYS deliver these 100% of the time, so if we happen to see one,
-        * just throw it away.
-        */
-       if (rc == 0)
-               return EP0_REQUEUE;
-
-       /* Drop malformed SETUP packets */
-       if (rc != sizeof(*ctrl)) {
-               dev_warn_ratelimited(udc->dev,
-                       "malformed SETUP packet (%d bytes)\n", rc);
-               return EP0_REQUEUE;
-       }
-
-       /* Process new SETUP packet arriving on ep0 */
-       rc = bcm63xx_ep0_setup_callback(udc, ctrl);
-       if (rc < 0) {
-               bcm63xx_set_stall(udc, &udc->bep[0], true);
-               return EP0_REQUEUE;
-       }
-
-       if (!ctrl->wLength)
-               return EP0_REQUEUE;
-       else if (ctrl->bRequestType & USB_DIR_IN)
-               return EP0_IN_DATA_PHASE_SETUP;
-       else
-               return EP0_OUT_DATA_PHASE_SETUP;
-}
-
-/**
- * bcm63xx_ep0_do_idle - Check for outstanding requests if ep0 is idle.
- * @udc: Reference to the device controller.
- *
- * In state EP0_IDLE, the RX descriptor is either pending, or has been
- * filled with a SETUP packet from the host.  This function handles new
- * SETUP packets, control IRQ events (which can generate fake SETUP packets),
- * and reset/shutdown events.
- *
- * Returns 0 if work was done; -EAGAIN if nothing to do.
- */
-static int bcm63xx_ep0_do_idle(struct bcm63xx_udc *udc)
-{
-       if (udc->ep0_req_reset) {
-               udc->ep0_req_reset = 0;
-       } else if (udc->ep0_req_set_cfg) {
-               udc->ep0_req_set_cfg = 0;
-               if (bcm63xx_ep0_spoof_set_cfg(udc) >= 0)
-                       udc->ep0state = EP0_IN_FAKE_STATUS_PHASE;
-       } else if (udc->ep0_req_set_iface) {
-               udc->ep0_req_set_iface = 0;
-               if (bcm63xx_ep0_spoof_set_iface(udc) >= 0)
-                       udc->ep0state = EP0_IN_FAKE_STATUS_PHASE;
-       } else if (udc->ep0_req_completed) {
-               udc->ep0state = bcm63xx_ep0_do_setup(udc);
-               return udc->ep0state == EP0_IDLE ? -EAGAIN : 0;
-       } else if (udc->ep0_req_shutdown) {
-               udc->ep0_req_shutdown = 0;
-               udc->ep0_req_completed = 0;
-               udc->ep0_request = NULL;
-               iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_RXCHAN]);
-               usb_gadget_unmap_request(&udc->gadget,
-                       &udc->ep0_ctrl_req.req, 0);
-
-               /* bcm63xx_udc_pullup() is waiting for this */
-               mb();
-               udc->ep0state = EP0_SHUTDOWN;
-       } else if (udc->ep0_reply) {
-               /*
-                * This could happen if a USB RESET shows up during an ep0
-                * transaction (especially if a laggy driver like gadgetfs
-                * is in use).
-                */
-               dev_warn(udc->dev, "nuking unexpected reply\n");
-               bcm63xx_ep0_nuke_reply(udc, 0);
-       } else {
-               return -EAGAIN;
-       }
-
-       return 0;
-}
-
-/**
- * bcm63xx_ep0_one_round - Handle the current ep0 state.
- * @udc: Reference to the device controller.
- *
- * Returns 0 if work was done; -EAGAIN if nothing to do.
- */
-static int bcm63xx_ep0_one_round(struct bcm63xx_udc *udc)
-{
-       enum bcm63xx_ep0_state ep0state = udc->ep0state;
-       bool shutdown = udc->ep0_req_reset || udc->ep0_req_shutdown;
-
-       switch (udc->ep0state) {
-       case EP0_REQUEUE:
-               /* set up descriptor to receive SETUP packet */
-               bcm63xx_ep0_internal_request(udc, IUDMA_EP0_RXCHAN,
-                                            BCM63XX_MAX_CTRL_PKT);
-               ep0state = EP0_IDLE;
-               break;
-       case EP0_IDLE:
-               return bcm63xx_ep0_do_idle(udc);
-       case EP0_IN_DATA_PHASE_SETUP:
-               /*
-                * Normal case: TX request is in ep0_reply (queued by the
-                * callback), or will be queued shortly.  When it's here,
-                * send it to the HW and go to EP0_IN_DATA_PHASE_COMPLETE.
-                *
-                * Shutdown case: Stop waiting for the reply.  Just
-                * REQUEUE->IDLE.  The gadget driver is NOT expected to
-                * queue anything else now.
-                */
-               if (udc->ep0_reply) {
-                       bcm63xx_ep0_map_write(udc, IUDMA_EP0_TXCHAN,
-                                             udc->ep0_reply);
-                       ep0state = EP0_IN_DATA_PHASE_COMPLETE;
-               } else if (shutdown) {
-                       ep0state = EP0_REQUEUE;
-               }
-               break;
-       case EP0_IN_DATA_PHASE_COMPLETE: {
-               /*
-                * Normal case: TX packet (ep0_reply) is in flight; wait for
-                * it to finish, then go back to REQUEUE->IDLE.
-                *
-                * Shutdown case: Reset the TX channel, send -ESHUTDOWN
-                * completion to the gadget driver, then REQUEUE->IDLE.
-                */
-               if (udc->ep0_req_completed) {
-                       udc->ep0_reply = NULL;
-                       bcm63xx_ep0_read_complete(udc);
-                       /*
-                        * the "ack" sometimes gets eaten (see
-                        * bcm63xx_ep0_do_idle)
-                        */
-                       ep0state = EP0_REQUEUE;
-               } else if (shutdown) {
-                       iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_TXCHAN]);
-                       bcm63xx_ep0_nuke_reply(udc, 1);
-                       ep0state = EP0_REQUEUE;
-               }
-               break;
-       }
-       case EP0_OUT_DATA_PHASE_SETUP:
-               /* Similar behavior to EP0_IN_DATA_PHASE_SETUP */
-               if (udc->ep0_reply) {
-                       bcm63xx_ep0_map_write(udc, IUDMA_EP0_RXCHAN,
-                                             udc->ep0_reply);
-                       ep0state = EP0_OUT_DATA_PHASE_COMPLETE;
-               } else if (shutdown) {
-                       ep0state = EP0_REQUEUE;
-               }
-               break;
-       case EP0_OUT_DATA_PHASE_COMPLETE: {
-               /* Similar behavior to EP0_IN_DATA_PHASE_COMPLETE */
-               if (udc->ep0_req_completed) {
-                       udc->ep0_reply = NULL;
-                       bcm63xx_ep0_read_complete(udc);
-
-                       /* send 0-byte ack to host */
-                       bcm63xx_ep0_internal_request(udc, IUDMA_EP0_TXCHAN, 0);
-                       ep0state = EP0_OUT_STATUS_PHASE;
-               } else if (shutdown) {
-                       iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_RXCHAN]);
-                       bcm63xx_ep0_nuke_reply(udc, 0);
-                       ep0state = EP0_REQUEUE;
-               }
-               break;
-       }
-       case EP0_OUT_STATUS_PHASE:
-               /*
-                * Normal case: 0-byte OUT ack packet is in flight; wait
-                * for it to finish, then go back to REQUEUE->IDLE.
-                *
-                * Shutdown case: just cancel the transmission.  Don't bother
-                * calling the completion, because it originated from this
-                * function anyway.  Then go back to REQUEUE->IDLE.
-                */
-               if (udc->ep0_req_completed) {
-                       bcm63xx_ep0_read_complete(udc);
-                       ep0state = EP0_REQUEUE;
-               } else if (shutdown) {
-                       iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_TXCHAN]);
-                       udc->ep0_request = NULL;
-                       ep0state = EP0_REQUEUE;
-               }
-               break;
-       case EP0_IN_FAKE_STATUS_PHASE: {
-               /*
-                * Normal case: we spoofed a SETUP packet and are now
-                * waiting for the gadget driver to send a 0-byte reply.
-                * This doesn't actually get sent to the HW because the
-                * HW has already sent its own reply.  Once we get the
-                * response, return to IDLE.
-                *
-                * Shutdown case: return to IDLE immediately.
-                *
-                * Note that the ep0 RX descriptor has remained queued
-                * (and possibly unfilled) during this entire transaction.
-                * The HW datapath (IUDMA) never even sees SET_CONFIGURATION
-                * or SET_INTERFACE transactions.
-                */
-               struct usb_request *r = udc->ep0_reply;
-
-               if (!r) {
-                       if (shutdown)
-                               ep0state = EP0_IDLE;
-                       break;
-               }
-
-               bcm63xx_ep0_complete(udc, r, 0);
-               udc->ep0_reply = NULL;
-               ep0state = EP0_IDLE;
-               break;
-       }
-       case EP0_SHUTDOWN:
-               break;
-       }
-
-       if (udc->ep0state == ep0state)
-               return -EAGAIN;
-
-       udc->ep0state = ep0state;
-       return 0;
-}
-
-/**
- * bcm63xx_ep0_process - ep0 worker thread / state machine.
- * @w: Workqueue struct.
- *
- * bcm63xx_ep0_process is triggered any time an event occurs on ep0.  It
- * is used to synchronize ep0 events and ensure that both HW and SW events
- * occur in a well-defined order.  When the ep0 IUDMA queues are idle, it may
- * synthesize SET_CONFIGURATION / SET_INTERFACE requests that were consumed
- * by the USBD hardware.
- *
- * The worker function will continue iterating around the state machine
- * until there is nothing left to do.  Usually "nothing left to do" means
- * that we're waiting for a new event from the hardware.
- */
-static void bcm63xx_ep0_process(struct work_struct *w)
-{
-       struct bcm63xx_udc *udc = container_of(w, struct bcm63xx_udc, ep0_wq);
-       spin_lock_irq(&udc->lock);
-       while (bcm63xx_ep0_one_round(udc) == 0)
-               ;
-       spin_unlock_irq(&udc->lock);
-}
-
-/***********************************************************************
- * Standard UDC gadget operations
- ***********************************************************************/
-
-/**
- * bcm63xx_udc_get_frame - Read current SOF frame number from the HW.
- * @gadget: USB slave device.
- */
-static int bcm63xx_udc_get_frame(struct usb_gadget *gadget)
-{
-       struct bcm63xx_udc *udc = gadget_to_udc(gadget);
-
-       return (usbd_readl(udc, USBD_STATUS_REG) &
-               USBD_STATUS_SOF_MASK) >> USBD_STATUS_SOF_SHIFT;
-}
-
-/**
- * bcm63xx_udc_pullup - Enable/disable pullup on D+ line.
- * @gadget: USB slave device.
- * @is_on: 0 to disable pullup, 1 to enable.
- *
- * See notes in bcm63xx_select_pullup().
- */
-static int bcm63xx_udc_pullup(struct usb_gadget *gadget, int is_on)
-{
-       struct bcm63xx_udc *udc = gadget_to_udc(gadget);
-       unsigned long flags;
-       int i, rc = -EINVAL;
-
-       spin_lock_irqsave(&udc->lock, flags);
-       if (is_on && udc->ep0state == EP0_SHUTDOWN) {
-               udc->gadget.speed = USB_SPEED_UNKNOWN;
-               udc->ep0state = EP0_REQUEUE;
-               bcm63xx_fifo_setup(udc);
-               bcm63xx_fifo_reset(udc);
-               bcm63xx_ep_setup(udc);
-
-               bitmap_zero(&udc->wedgemap, BCM63XX_NUM_EP);
-               for (i = 0; i < BCM63XX_NUM_EP; i++)
-                       bcm63xx_set_stall(udc, &udc->bep[i], false);
-
-               bcm63xx_set_ctrl_irqs(udc, true);
-               bcm63xx_select_pullup(gadget_to_udc(gadget), true);
-               rc = 0;
-       } else if (!is_on && udc->ep0state != EP0_SHUTDOWN) {
-               bcm63xx_select_pullup(gadget_to_udc(gadget), false);
-
-               udc->ep0_req_shutdown = 1;
-               spin_unlock_irqrestore(&udc->lock, flags);
-
-               while (1) {
-                       schedule_work(&udc->ep0_wq);
-                       if (udc->ep0state == EP0_SHUTDOWN)
-                               break;
-                       msleep(50);
-               }
-               bcm63xx_set_ctrl_irqs(udc, false);
-               cancel_work_sync(&udc->ep0_wq);
-               return 0;
-       }
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return rc;
-}
-
-/**
- * bcm63xx_udc_start - Start the controller.
- * @gadget: USB slave device.
- * @driver: Driver for USB slave devices.
- */
-static int bcm63xx_udc_start(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct bcm63xx_udc *udc = gadget_to_udc(gadget);
-       unsigned long flags;
-
-       if (!driver || driver->max_speed < USB_SPEED_HIGH ||
-           !driver->setup)
-               return -EINVAL;
-       if (!udc)
-               return -ENODEV;
-       if (udc->driver)
-               return -EBUSY;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       set_clocks(udc, true);
-       bcm63xx_fifo_setup(udc);
-       bcm63xx_ep_init(udc);
-       bcm63xx_ep_setup(udc);
-       bcm63xx_fifo_reset(udc);
-       bcm63xx_select_phy_mode(udc, true);
-
-       udc->driver = driver;
-       driver->driver.bus = NULL;
-       udc->gadget.dev.of_node = udc->dev->of_node;
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-/**
- * bcm63xx_udc_stop - Shut down the controller.
- * @gadget: USB slave device.
- * @driver: Driver for USB slave devices.
- */
-static int bcm63xx_udc_stop(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct bcm63xx_udc *udc = gadget_to_udc(gadget);
-       unsigned long flags;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       udc->driver = NULL;
-
-       /*
-        * If we switch the PHY too abruptly after dropping D+, the host
-        * will often complain:
-        *
-        *     hub 1-0:1.0: port 1 disabled by hub (EMI?), re-enabling...
-        */
-       msleep(100);
-
-       bcm63xx_select_phy_mode(udc, false);
-       set_clocks(udc, false);
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-static const struct usb_gadget_ops bcm63xx_udc_ops = {
-       .get_frame      = bcm63xx_udc_get_frame,
-       .pullup         = bcm63xx_udc_pullup,
-       .udc_start      = bcm63xx_udc_start,
-       .udc_stop       = bcm63xx_udc_stop,
-};
-
-/***********************************************************************
- * IRQ handling
- ***********************************************************************/
-
-/**
- * bcm63xx_update_cfg_iface - Read current configuration/interface settings.
- * @udc: Reference to the device controller.
- *
- * This controller intercepts SET_CONFIGURATION and SET_INTERFACE messages.
- * The driver never sees the raw control packets coming in on the ep0
- * IUDMA channel, but at least we get an interrupt event to tell us that
- * new values are waiting in the USBD_STATUS register.
- */
-static void bcm63xx_update_cfg_iface(struct bcm63xx_udc *udc)
-{
-       u32 reg = usbd_readl(udc, USBD_STATUS_REG);
-
-       udc->cfg = (reg & USBD_STATUS_CFG_MASK) >> USBD_STATUS_CFG_SHIFT;
-       udc->iface = (reg & USBD_STATUS_INTF_MASK) >> USBD_STATUS_INTF_SHIFT;
-       udc->alt_iface = (reg & USBD_STATUS_ALTINTF_MASK) >>
-                        USBD_STATUS_ALTINTF_SHIFT;
-       bcm63xx_ep_setup(udc);
-}
-
-/**
- * bcm63xx_update_link_speed - Check to see if the link speed has changed.
- * @udc: Reference to the device controller.
- *
- * The link speed update coincides with a SETUP IRQ.  Returns 1 if the
- * speed has changed, so that the caller can update the endpoint settings.
- */
-static int bcm63xx_update_link_speed(struct bcm63xx_udc *udc)
-{
-       u32 reg = usbd_readl(udc, USBD_STATUS_REG);
-       enum usb_device_speed oldspeed = udc->gadget.speed;
-
-       switch ((reg & USBD_STATUS_SPD_MASK) >> USBD_STATUS_SPD_SHIFT) {
-       case BCM63XX_SPD_HIGH:
-               udc->gadget.speed = USB_SPEED_HIGH;
-               break;
-       case BCM63XX_SPD_FULL:
-               udc->gadget.speed = USB_SPEED_FULL;
-               break;
-       default:
-               /* this should never happen */
-               udc->gadget.speed = USB_SPEED_UNKNOWN;
-               dev_err(udc->dev,
-                       "received SETUP packet with invalid link speed\n");
-               return 0;
-       }
-
-       if (udc->gadget.speed != oldspeed) {
-               dev_info(udc->dev, "link up, %s-speed mode\n",
-                        udc->gadget.speed == USB_SPEED_HIGH ? "high" : "full");
-               return 1;
-       } else {
-               return 0;
-       }
-}
-
-/**
- * bcm63xx_update_wedge - Iterate through wedged endpoints.
- * @udc: Reference to the device controller.
- * @new_status: true to "refresh" wedge status; false to clear it.
- *
- * On a SETUP interrupt, we need to manually "refresh" the wedge status
- * because the controller hardware is designed to automatically clear
- * stalls in response to a CLEAR_FEATURE request from the host.
- *
- * On a RESET interrupt, we do want to restore all wedged endpoints.
- */
-static void bcm63xx_update_wedge(struct bcm63xx_udc *udc, bool new_status)
-{
-       int i;
-
-       for_each_set_bit(i, &udc->wedgemap, BCM63XX_NUM_EP) {
-               bcm63xx_set_stall(udc, &udc->bep[i], new_status);
-               if (!new_status)
-                       clear_bit(i, &udc->wedgemap);
-       }
-}
-
-/**
- * bcm63xx_udc_ctrl_isr - ISR for control path events (USBD).
- * @irq: IRQ number (unused).
- * @dev_id: Reference to the device controller.
- *
- * This is where we handle link (VBUS) down, USB reset, speed changes,
- * SET_CONFIGURATION, and SET_INTERFACE events.
- */
-static irqreturn_t bcm63xx_udc_ctrl_isr(int irq, void *dev_id)
-{
-       struct bcm63xx_udc *udc = dev_id;
-       u32 stat;
-       bool disconnected = false;
-
-       stat = usbd_readl(udc, USBD_EVENT_IRQ_STATUS_REG) &
-              usbd_readl(udc, USBD_EVENT_IRQ_MASK_REG);
-
-       usbd_writel(udc, stat, USBD_EVENT_IRQ_STATUS_REG);
-
-       spin_lock(&udc->lock);
-       if (stat & BIT(USBD_EVENT_IRQ_USB_LINK)) {
-               /* VBUS toggled */
-
-               if (!(usbd_readl(udc, USBD_EVENTS_REG) &
-                     USBD_EVENTS_USB_LINK_MASK) &&
-                     udc->gadget.speed != USB_SPEED_UNKNOWN)
-                       dev_info(udc->dev, "link down\n");
-
-               udc->gadget.speed = USB_SPEED_UNKNOWN;
-               disconnected = true;
-       }
-       if (stat & BIT(USBD_EVENT_IRQ_USB_RESET)) {
-               bcm63xx_fifo_setup(udc);
-               bcm63xx_fifo_reset(udc);
-               bcm63xx_ep_setup(udc);
-
-               bcm63xx_update_wedge(udc, false);
-
-               udc->ep0_req_reset = 1;
-               schedule_work(&udc->ep0_wq);
-               disconnected = true;
-       }
-       if (stat & BIT(USBD_EVENT_IRQ_SETUP)) {
-               if (bcm63xx_update_link_speed(udc)) {
-                       bcm63xx_fifo_setup(udc);
-                       bcm63xx_ep_setup(udc);
-               }
-               bcm63xx_update_wedge(udc, true);
-       }
-       if (stat & BIT(USBD_EVENT_IRQ_SETCFG)) {
-               bcm63xx_update_cfg_iface(udc);
-               udc->ep0_req_set_cfg = 1;
-               schedule_work(&udc->ep0_wq);
-       }
-       if (stat & BIT(USBD_EVENT_IRQ_SETINTF)) {
-               bcm63xx_update_cfg_iface(udc);
-               udc->ep0_req_set_iface = 1;
-               schedule_work(&udc->ep0_wq);
-       }
-       spin_unlock(&udc->lock);
-
-       if (disconnected && udc->driver)
-               udc->driver->disconnect(&udc->gadget);
-
-       return IRQ_HANDLED;
-}
-
-/**
- * bcm63xx_udc_data_isr - ISR for data path events (IUDMA).
- * @irq: IRQ number (unused).
- * @dev_id: Reference to the IUDMA channel that generated the interrupt.
- *
- * For the two ep0 channels, we have special handling that triggers the
- * ep0 worker thread.  For normal bulk/intr channels, either queue up
- * the next buffer descriptor for the transaction (incomplete transaction),
- * or invoke the completion callback (complete transactions).
- */
-static irqreturn_t bcm63xx_udc_data_isr(int irq, void *dev_id)
-{
-       struct iudma_ch *iudma = dev_id;
-       struct bcm63xx_udc *udc = iudma->udc;
-       struct bcm63xx_ep *bep;
-       struct usb_request *req = NULL;
-       struct bcm63xx_req *breq = NULL;
-       int rc;
-       bool is_done = false;
-
-       spin_lock(&udc->lock);
-
-       usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK,
-                       ENETDMAC_IR_REG, iudma->ch_idx);
-       bep = iudma->bep;
-       rc = iudma_read(udc, iudma);
-
-       /* special handling for EP0 RX (0) and TX (1) */
-       if (iudma->ch_idx == IUDMA_EP0_RXCHAN ||
-           iudma->ch_idx == IUDMA_EP0_TXCHAN) {
-               req = udc->ep0_request;
-               breq = our_req(req);
-
-               /* a single request could require multiple submissions */
-               if (rc >= 0) {
-                       req->actual += rc;
-
-                       if (req->actual >= req->length || breq->bd_bytes > rc) {
-                               udc->ep0_req_completed = 1;
-                               is_done = true;
-                               schedule_work(&udc->ep0_wq);
-
-                               /* "actual" on a ZLP is 1 byte */
-                               req->actual = min(req->actual, req->length);
-                       } else {
-                               /* queue up the next BD (same request) */
-                               iudma_write(udc, iudma, breq);
-                       }
-               }
-       } else if (!list_empty(&bep->queue)) {
-               breq = list_first_entry(&bep->queue, struct bcm63xx_req, queue);
-               req = &breq->req;
-
-               if (rc >= 0) {
-                       req->actual += rc;
-
-                       if (req->actual >= req->length || breq->bd_bytes > rc) {
-                               is_done = true;
-                               list_del(&breq->queue);
-
-                               req->actual = min(req->actual, req->length);
-
-                               if (!list_empty(&bep->queue)) {
-                                       struct bcm63xx_req *next;
-
-                                       next = list_first_entry(&bep->queue,
-                                               struct bcm63xx_req, queue);
-                                       iudma_write(udc, iudma, next);
-                               }
-                       } else {
-                               iudma_write(udc, iudma, breq);
-                       }
-               }
-       }
-       spin_unlock(&udc->lock);
-
-       if (is_done) {
-               usb_gadget_unmap_request(&udc->gadget, req, iudma->is_tx);
-               if (req->complete)
-                       req->complete(&bep->ep, req);
-       }
-
-       return IRQ_HANDLED;
-}
-
-/***********************************************************************
- * Debug filesystem
- ***********************************************************************/
-
-/*
- * bcm63xx_usbd_dbg_show - Show USBD controller state.
- * @s: seq_file to which the information will be written.
- * @p: Unused.
- *
- * This file nominally shows up as /sys/kernel/debug/bcm63xx_udc/usbd
- */
-static int bcm63xx_usbd_dbg_show(struct seq_file *s, void *p)
-{
-       struct bcm63xx_udc *udc = s->private;
-
-       if (!udc->driver)
-               return -ENODEV;
-
-       seq_printf(s, "ep0 state: %s\n",
-                  bcm63xx_ep0_state_names[udc->ep0state]);
-       seq_printf(s, "  pending requests: %s%s%s%s%s%s%s\n",
-                  udc->ep0_req_reset ? "reset " : "",
-                  udc->ep0_req_set_cfg ? "set_cfg " : "",
-                  udc->ep0_req_set_iface ? "set_iface " : "",
-                  udc->ep0_req_shutdown ? "shutdown " : "",
-                  udc->ep0_request ? "pending " : "",
-                  udc->ep0_req_completed ? "completed " : "",
-                  udc->ep0_reply ? "reply " : "");
-       seq_printf(s, "cfg: %d; iface: %d; alt_iface: %d\n",
-                  udc->cfg, udc->iface, udc->alt_iface);
-       seq_printf(s, "regs:\n");
-       seq_printf(s, "  control: %08x; straps: %08x; status: %08x\n",
-                  usbd_readl(udc, USBD_CONTROL_REG),
-                  usbd_readl(udc, USBD_STRAPS_REG),
-                  usbd_readl(udc, USBD_STATUS_REG));
-       seq_printf(s, "  events:  %08x; stall:  %08x\n",
-                  usbd_readl(udc, USBD_EVENTS_REG),
-                  usbd_readl(udc, USBD_STALL_REG));
-
-       return 0;
-}
-
-/*
- * bcm63xx_iudma_dbg_show - Show IUDMA status and descriptors.
- * @s: seq_file to which the information will be written.
- * @p: Unused.
- *
- * This file nominally shows up as /sys/kernel/debug/bcm63xx_udc/iudma
- */
-static int bcm63xx_iudma_dbg_show(struct seq_file *s, void *p)
-{
-       struct bcm63xx_udc *udc = s->private;
-       int ch_idx, i;
-       u32 sram2, sram3;
-
-       if (!udc->driver)
-               return -ENODEV;
-
-       for (ch_idx = 0; ch_idx < BCM63XX_NUM_IUDMA; ch_idx++) {
-               struct iudma_ch *iudma = &udc->iudma[ch_idx];
-               struct list_head *pos;
-
-               seq_printf(s, "IUDMA channel %d -- ", ch_idx);
-               switch (iudma_defaults[ch_idx].ep_type) {
-               case BCMEP_CTRL:
-                       seq_printf(s, "control");
-                       break;
-               case BCMEP_BULK:
-                       seq_printf(s, "bulk");
-                       break;
-               case BCMEP_INTR:
-                       seq_printf(s, "interrupt");
-                       break;
-               }
-               seq_printf(s, ch_idx & 0x01 ? " tx" : " rx");
-               seq_printf(s, " [ep%d]:\n",
-                          max_t(int, iudma_defaults[ch_idx].ep_num, 0));
-               seq_printf(s, "  cfg: %08x; irqstat: %08x; irqmask: %08x; maxburst: %08x\n",
-                          usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx),
-                          usb_dmac_readl(udc, ENETDMAC_IR_REG, ch_idx),
-                          usb_dmac_readl(udc, ENETDMAC_IRMASK_REG, ch_idx),
-                          usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG, ch_idx));
-
-               sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG, ch_idx);
-               sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG, ch_idx);
-               seq_printf(s, "  base: %08x; index: %04x_%04x; desc: %04x_%04x %08x\n",
-                          usb_dmas_readl(udc, ENETDMAS_RSTART_REG, ch_idx),
-                          sram2 >> 16, sram2 & 0xffff,
-                          sram3 >> 16, sram3 & 0xffff,
-                          usb_dmas_readl(udc, ENETDMAS_SRAM4_REG, ch_idx));
-               seq_printf(s, "  desc: %d/%d used", iudma->n_bds_used,
-                          iudma->n_bds);
-
-               if (iudma->bep) {
-                       i = 0;
-                       list_for_each(pos, &iudma->bep->queue)
-                               i++;
-                       seq_printf(s, "; %d queued\n", i);
-               } else {
-                       seq_printf(s, "\n");
-               }
-
-               for (i = 0; i < iudma->n_bds; i++) {
-                       struct bcm_enet_desc *d = &iudma->bd_ring[i];
-
-                       seq_printf(s, "  %03x (%02x): len_stat: %04x_%04x; pa %08x",
-                                  i * sizeof(*d), i,
-                                  d->len_stat >> 16, d->len_stat & 0xffff,
-                                  d->address);
-                       if (d == iudma->read_bd)
-                               seq_printf(s, "   <<RD");
-                       if (d == iudma->write_bd)
-                               seq_printf(s, "   <<WR");
-                       seq_printf(s, "\n");
-               }
-
-               seq_printf(s, "\n");
-       }
-
-       return 0;
-}
-
-static int bcm63xx_usbd_dbg_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, bcm63xx_usbd_dbg_show, inode->i_private);
-}
-
-static int bcm63xx_iudma_dbg_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, bcm63xx_iudma_dbg_show, inode->i_private);
-}
-
-static const struct file_operations usbd_dbg_fops = {
-       .owner          = THIS_MODULE,
-       .open           = bcm63xx_usbd_dbg_open,
-       .llseek         = seq_lseek,
-       .read           = seq_read,
-       .release        = single_release,
-};
-
-static const struct file_operations iudma_dbg_fops = {
-       .owner          = THIS_MODULE,
-       .open           = bcm63xx_iudma_dbg_open,
-       .llseek         = seq_lseek,
-       .read           = seq_read,
-       .release        = single_release,
-};
-
-
-/**
- * bcm63xx_udc_init_debugfs - Create debugfs entries.
- * @udc: Reference to the device controller.
- */
-static void bcm63xx_udc_init_debugfs(struct bcm63xx_udc *udc)
-{
-       struct dentry *root, *usbd, *iudma;
-
-       if (!IS_ENABLED(CONFIG_USB_GADGET_DEBUG_FS))
-               return;
-
-       root = debugfs_create_dir(udc->gadget.name, NULL);
-       if (IS_ERR(root) || !root)
-               goto err_root;
-
-       usbd = debugfs_create_file("usbd", 0400, root, udc,
-                       &usbd_dbg_fops);
-       if (!usbd)
-               goto err_usbd;
-       iudma = debugfs_create_file("iudma", 0400, root, udc,
-                       &iudma_dbg_fops);
-       if (!iudma)
-               goto err_iudma;
-
-       udc->debugfs_root = root;
-       udc->debugfs_usbd = usbd;
-       udc->debugfs_iudma = iudma;
-       return;
-err_iudma:
-       debugfs_remove(usbd);
-err_usbd:
-       debugfs_remove(root);
-err_root:
-       dev_err(udc->dev, "debugfs is not available\n");
-}
-
-/**
- * bcm63xx_udc_cleanup_debugfs - Remove debugfs entries.
- * @udc: Reference to the device controller.
- *
- * debugfs_remove() is safe to call with a NULL argument.
- */
-static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc)
-{
-       debugfs_remove(udc->debugfs_iudma);
-       debugfs_remove(udc->debugfs_usbd);
-       debugfs_remove(udc->debugfs_root);
-       udc->debugfs_iudma = NULL;
-       udc->debugfs_usbd = NULL;
-       udc->debugfs_root = NULL;
-}
-
-/***********************************************************************
- * Driver init/exit
- ***********************************************************************/
-
-/**
- * bcm63xx_udc_probe - Initialize a new instance of the UDC.
- * @pdev: Platform device struct from the bcm63xx BSP code.
- *
- * Note that platform data is required, because pd.port_no varies from chip
- * to chip and is used to switch the correct USB port to device mode.
- */
-static int bcm63xx_udc_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct bcm63xx_usbd_platform_data *pd = dev_get_platdata(dev);
-       struct bcm63xx_udc *udc;
-       struct resource *res;
-       int rc = -ENOMEM, i, irq;
-
-       udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL);
-       if (!udc) {
-               dev_err(dev, "cannot allocate memory\n");
-               return -ENOMEM;
-       }
-
-       platform_set_drvdata(pdev, udc);
-       udc->dev = dev;
-       udc->pd = pd;
-
-       if (!pd) {
-               dev_err(dev, "missing platform data\n");
-               return -EINVAL;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       udc->usbd_regs = devm_ioremap_resource(dev, res);
-       if (IS_ERR(udc->usbd_regs))
-               return PTR_ERR(udc->usbd_regs);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       udc->iudma_regs = devm_ioremap_resource(dev, res);
-       if (IS_ERR(udc->iudma_regs))
-               return PTR_ERR(udc->iudma_regs);
-
-       spin_lock_init(&udc->lock);
-       INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process);
-
-       udc->gadget.ops = &bcm63xx_udc_ops;
-       udc->gadget.name = dev_name(dev);
-
-       if (!pd->use_fullspeed && !use_fullspeed)
-               udc->gadget.max_speed = USB_SPEED_HIGH;
-       else
-               udc->gadget.max_speed = USB_SPEED_FULL;
-
-       /* request clocks, allocate buffers, and clear any pending IRQs */
-       rc = bcm63xx_init_udc_hw(udc);
-       if (rc)
-               return rc;
-
-       rc = -ENXIO;
-
-       /* IRQ resource #0: control interrupt (VBUS, speed, etc.) */
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(dev, "missing IRQ resource #0\n");
-               goto out_uninit;
-       }
-       if (devm_request_irq(dev, irq, &bcm63xx_udc_ctrl_isr, 0,
-                            dev_name(dev), udc) < 0) {
-               dev_err(dev, "error requesting IRQ #%d\n", irq);
-               goto out_uninit;
-       }
-
-       /* IRQ resources #1-6: data interrupts for IUDMA channels 0-5 */
-       for (i = 0; i < BCM63XX_NUM_IUDMA; i++) {
-               irq = platform_get_irq(pdev, i + 1);
-               if (irq < 0) {
-                       dev_err(dev, "missing IRQ resource #%d\n", i + 1);
-                       goto out_uninit;
-               }
-               if (devm_request_irq(dev, irq, &bcm63xx_udc_data_isr, 0,
-                                    dev_name(dev), &udc->iudma[i]) < 0) {
-                       dev_err(dev, "error requesting IRQ #%d\n", irq);
-                       goto out_uninit;
-               }
-       }
-
-       bcm63xx_udc_init_debugfs(udc);
-       rc = usb_add_gadget_udc(dev, &udc->gadget);
-       if (!rc)
-               return 0;
-
-       bcm63xx_udc_cleanup_debugfs(udc);
-out_uninit:
-       bcm63xx_uninit_udc_hw(udc);
-       return rc;
-}
-
-/**
- * bcm63xx_udc_remove - Remove the device from the system.
- * @pdev: Platform device struct from the bcm63xx BSP code.
- */
-static int bcm63xx_udc_remove(struct platform_device *pdev)
-{
-       struct bcm63xx_udc *udc = platform_get_drvdata(pdev);
-
-       bcm63xx_udc_cleanup_debugfs(udc);
-       usb_del_gadget_udc(&udc->gadget);
-       BUG_ON(udc->driver);
-
-       bcm63xx_uninit_udc_hw(udc);
-
-       return 0;
-}
-
-static struct platform_driver bcm63xx_udc_driver = {
-       .probe          = bcm63xx_udc_probe,
-       .remove         = bcm63xx_udc_remove,
-       .driver         = {
-               .name   = DRV_MODULE_NAME,
-               .owner  = THIS_MODULE,
-       },
-};
-module_platform_driver(bcm63xx_udc_driver);
-
-MODULE_DESCRIPTION("BCM63xx USB Peripheral Controller");
-MODULE_AUTHOR("Kevin Cernekee <cernekee@gmail.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_MODULE_NAME);
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
deleted file mode 100644 (file)
index 2b54955..0000000
+++ /dev/null
@@ -1,2764 +0,0 @@
-/*
- * dummy_hcd.c -- Dummy/Loopback USB host and device emulator driver.
- *
- * Maintainer: Alan Stern <stern@rowland.harvard.edu>
- *
- * Copyright (C) 2003 David Brownell
- * Copyright (C) 2003-2005 Alan Stern
- *
- * 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 exposes a device side "USB gadget" API, driven by requests to a
- * Linux-USB host controller driver.  USB traffic is simulated; there's
- * no need for USB hardware.  Use this with two other drivers:
- *
- *  - Gadget driver, responding to requests (slave);
- *  - Host-side device driver, as already familiar in Linux.
- *
- * Having this all in one kernel can help some stages of development,
- * bypassing some hardware (and driver) issues.  UML could help too.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/usb.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/hcd.h>
-#include <linux/scatterlist.h>
-
-#include <asm/byteorder.h>
-#include <linux/io.h>
-#include <asm/irq.h>
-#include <asm/unaligned.h>
-
-#define DRIVER_DESC    "USB Host+Gadget Emulator"
-#define DRIVER_VERSION "02 May 2005"
-
-#define POWER_BUDGET   500     /* in mA; use 8 for low-power port testing */
-
-static const char      driver_name[] = "dummy_hcd";
-static const char      driver_desc[] = "USB Host+Gadget Emulator";
-
-static const char      gadget_name[] = "dummy_udc";
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("David Brownell");
-MODULE_LICENSE("GPL");
-
-struct dummy_hcd_module_parameters {
-       bool is_super_speed;
-       bool is_high_speed;
-       unsigned int num;
-};
-
-static struct dummy_hcd_module_parameters mod_data = {
-       .is_super_speed = false,
-       .is_high_speed = true,
-       .num = 1,
-};
-module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO);
-MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection");
-module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO);
-MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection");
-module_param_named(num, mod_data.num, uint, S_IRUGO);
-MODULE_PARM_DESC(num, "number of emulated controllers");
-/*-------------------------------------------------------------------------*/
-
-/* gadget side driver data structres */
-struct dummy_ep {
-       struct list_head                queue;
-       unsigned long                   last_io;        /* jiffies timestamp */
-       struct usb_gadget               *gadget;
-       const struct usb_endpoint_descriptor *desc;
-       struct usb_ep                   ep;
-       unsigned                        halted:1;
-       unsigned                        wedged:1;
-       unsigned                        already_seen:1;
-       unsigned                        setup_stage:1;
-       unsigned                        stream_en:1;
-};
-
-struct dummy_request {
-       struct list_head                queue;          /* ep's requests */
-       struct usb_request              req;
-};
-
-static inline struct dummy_ep *usb_ep_to_dummy_ep(struct usb_ep *_ep)
-{
-       return container_of(_ep, struct dummy_ep, ep);
-}
-
-static inline struct dummy_request *usb_request_to_dummy_request
-               (struct usb_request *_req)
-{
-       return container_of(_req, struct dummy_request, req);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Every device has ep0 for control requests, plus up to 30 more endpoints,
- * in one of two types:
- *
- *   - Configurable:  direction (in/out), type (bulk, iso, etc), and endpoint
- *     number can be changed.  Names like "ep-a" are used for this type.
- *
- *   - Fixed Function:  in other cases.  some characteristics may be mutable;
- *     that'd be hardware-specific.  Names like "ep12out-bulk" are used.
- *
- * Gadget drivers are responsible for not setting up conflicting endpoint
- * configurations, illegal or unsupported packet lengths, and so on.
- */
-
-static const char ep0name[] = "ep0";
-
-static const char *const ep_name[] = {
-       ep0name,                                /* everyone has ep0 */
-
-       /* act like a pxa250: fifteen fixed function endpoints */
-       "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int",
-       "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int",
-       "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso",
-               "ep15in-int",
-
-       /* or like sa1100: two fixed function endpoints */
-       "ep1out-bulk", "ep2in-bulk",
-
-       /* and now some generic EPs so we have enough in multi config */
-       "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in",
-       "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out",
-};
-#define DUMMY_ENDPOINTS        ARRAY_SIZE(ep_name)
-
-/*-------------------------------------------------------------------------*/
-
-#define FIFO_SIZE              64
-
-struct urbp {
-       struct urb              *urb;
-       struct list_head        urbp_list;
-       struct sg_mapping_iter  miter;
-       u32                     miter_started;
-};
-
-
-enum dummy_rh_state {
-       DUMMY_RH_RESET,
-       DUMMY_RH_SUSPENDED,
-       DUMMY_RH_RUNNING
-};
-
-struct dummy_hcd {
-       struct dummy                    *dum;
-       enum dummy_rh_state             rh_state;
-       struct timer_list               timer;
-       u32                             port_status;
-       u32                             old_status;
-       unsigned long                   re_timeout;
-
-       struct usb_device               *udev;
-       struct list_head                urbp_list;
-       u32                             stream_en_ep;
-       u8                              num_stream[30 / 2];
-
-       unsigned                        active:1;
-       unsigned                        old_active:1;
-       unsigned                        resuming:1;
-};
-
-struct dummy {
-       spinlock_t                      lock;
-
-       /*
-        * SLAVE/GADGET side support
-        */
-       struct dummy_ep                 ep[DUMMY_ENDPOINTS];
-       int                             address;
-       struct usb_gadget               gadget;
-       struct usb_gadget_driver        *driver;
-       struct dummy_request            fifo_req;
-       u8                              fifo_buf[FIFO_SIZE];
-       u16                             devstatus;
-       unsigned                        udc_suspended:1;
-       unsigned                        pullup:1;
-
-       /*
-        * MASTER/HOST side support
-        */
-       struct dummy_hcd                *hs_hcd;
-       struct dummy_hcd                *ss_hcd;
-};
-
-static inline struct dummy_hcd *hcd_to_dummy_hcd(struct usb_hcd *hcd)
-{
-       return (struct dummy_hcd *) (hcd->hcd_priv);
-}
-
-static inline struct usb_hcd *dummy_hcd_to_hcd(struct dummy_hcd *dum)
-{
-       return container_of((void *) dum, struct usb_hcd, hcd_priv);
-}
-
-static inline struct device *dummy_dev(struct dummy_hcd *dum)
-{
-       return dummy_hcd_to_hcd(dum)->self.controller;
-}
-
-static inline struct device *udc_dev(struct dummy *dum)
-{
-       return dum->gadget.dev.parent;
-}
-
-static inline struct dummy *ep_to_dummy(struct dummy_ep *ep)
-{
-       return container_of(ep->gadget, struct dummy, gadget);
-}
-
-static inline struct dummy_hcd *gadget_to_dummy_hcd(struct usb_gadget *gadget)
-{
-       struct dummy *dum = container_of(gadget, struct dummy, gadget);
-       if (dum->gadget.speed == USB_SPEED_SUPER)
-               return dum->ss_hcd;
-       else
-               return dum->hs_hcd;
-}
-
-static inline struct dummy *gadget_dev_to_dummy(struct device *dev)
-{
-       return container_of(dev, struct dummy, gadget.dev);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* SLAVE/GADGET SIDE UTILITY ROUTINES */
-
-/* called with spinlock held */
-static void nuke(struct dummy *dum, struct dummy_ep *ep)
-{
-       while (!list_empty(&ep->queue)) {
-               struct dummy_request    *req;
-
-               req = list_entry(ep->queue.next, struct dummy_request, queue);
-               list_del_init(&req->queue);
-               req->req.status = -ESHUTDOWN;
-
-               spin_unlock(&dum->lock);
-               req->req.complete(&ep->ep, &req->req);
-               spin_lock(&dum->lock);
-       }
-}
-
-/* caller must hold lock */
-static void stop_activity(struct dummy *dum)
-{
-       struct dummy_ep *ep;
-
-       /* prevent any more requests */
-       dum->address = 0;
-
-       /* The timer is left running so that outstanding URBs can fail */
-
-       /* nuke any pending requests first, so driver i/o is quiesced */
-       list_for_each_entry(ep, &dum->gadget.ep_list, ep.ep_list)
-               nuke(dum, ep);
-
-       /* driver now does any non-usb quiescing necessary */
-}
-
-/**
- * set_link_state_by_speed() - Sets the current state of the link according to
- *     the hcd speed
- * @dum_hcd: pointer to the dummy_hcd structure to update the link state for
- *
- * This function updates the port_status according to the link state and the
- * speed of the hcd.
- */
-static void set_link_state_by_speed(struct dummy_hcd *dum_hcd)
-{
-       struct dummy *dum = dum_hcd->dum;
-
-       if (dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3) {
-               if ((dum_hcd->port_status & USB_SS_PORT_STAT_POWER) == 0) {
-                       dum_hcd->port_status = 0;
-               } else if (!dum->pullup || dum->udc_suspended) {
-                       /* UDC suspend must cause a disconnect */
-                       dum_hcd->port_status &= ~(USB_PORT_STAT_CONNECTION |
-                                               USB_PORT_STAT_ENABLE);
-                       if ((dum_hcd->old_status &
-                            USB_PORT_STAT_CONNECTION) != 0)
-                               dum_hcd->port_status |=
-                                       (USB_PORT_STAT_C_CONNECTION << 16);
-               } else {
-                       /* device is connected and not suspended */
-                       dum_hcd->port_status |= (USB_PORT_STAT_CONNECTION |
-                                                USB_PORT_STAT_SPEED_5GBPS) ;
-                       if ((dum_hcd->old_status &
-                            USB_PORT_STAT_CONNECTION) == 0)
-                               dum_hcd->port_status |=
-                                       (USB_PORT_STAT_C_CONNECTION << 16);
-                       if ((dum_hcd->port_status &
-                            USB_PORT_STAT_ENABLE) == 1 &&
-                               (dum_hcd->port_status &
-                                USB_SS_PORT_LS_U0) == 1 &&
-                               dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
-                               dum_hcd->active = 1;
-               }
-       } else {
-               if ((dum_hcd->port_status & USB_PORT_STAT_POWER) == 0) {
-                       dum_hcd->port_status = 0;
-               } else if (!dum->pullup || dum->udc_suspended) {
-                       /* UDC suspend must cause a disconnect */
-                       dum_hcd->port_status &= ~(USB_PORT_STAT_CONNECTION |
-                                               USB_PORT_STAT_ENABLE |
-                                               USB_PORT_STAT_LOW_SPEED |
-                                               USB_PORT_STAT_HIGH_SPEED |
-                                               USB_PORT_STAT_SUSPEND);
-                       if ((dum_hcd->old_status &
-                            USB_PORT_STAT_CONNECTION) != 0)
-                               dum_hcd->port_status |=
-                                       (USB_PORT_STAT_C_CONNECTION << 16);
-               } else {
-                       dum_hcd->port_status |= USB_PORT_STAT_CONNECTION;
-                       if ((dum_hcd->old_status &
-                            USB_PORT_STAT_CONNECTION) == 0)
-                               dum_hcd->port_status |=
-                                       (USB_PORT_STAT_C_CONNECTION << 16);
-                       if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0)
-                               dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND;
-                       else if ((dum_hcd->port_status &
-                                 USB_PORT_STAT_SUSPEND) == 0 &&
-                                       dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
-                               dum_hcd->active = 1;
-               }
-       }
-}
-
-/* caller must hold lock */
-static void set_link_state(struct dummy_hcd *dum_hcd)
-{
-       struct dummy *dum = dum_hcd->dum;
-
-       dum_hcd->active = 0;
-       if (dum->pullup)
-               if ((dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3 &&
-                    dum->gadget.speed != USB_SPEED_SUPER) ||
-                   (dummy_hcd_to_hcd(dum_hcd)->speed != HCD_USB3 &&
-                    dum->gadget.speed == USB_SPEED_SUPER))
-                       return;
-
-       set_link_state_by_speed(dum_hcd);
-
-       if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0 ||
-            dum_hcd->active)
-               dum_hcd->resuming = 0;
-
-       /* if !connected or reset */
-       if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0 ||
-                       (dum_hcd->port_status & USB_PORT_STAT_RESET) != 0) {
-               /*
-                * We're connected and not reset (reset occurred now),
-                * and driver attached - disconnect!
-                */
-               if ((dum_hcd->old_status & USB_PORT_STAT_CONNECTION) != 0 &&
-                   (dum_hcd->old_status & USB_PORT_STAT_RESET) == 0 &&
-                   dum->driver) {
-                       stop_activity(dum);
-                       spin_unlock(&dum->lock);
-                       dum->driver->disconnect(&dum->gadget);
-                       spin_lock(&dum->lock);
-               }
-       } else if (dum_hcd->active != dum_hcd->old_active) {
-               if (dum_hcd->old_active && dum->driver->suspend) {
-                       spin_unlock(&dum->lock);
-                       dum->driver->suspend(&dum->gadget);
-                       spin_lock(&dum->lock);
-               } else if (!dum_hcd->old_active &&  dum->driver->resume) {
-                       spin_unlock(&dum->lock);
-                       dum->driver->resume(&dum->gadget);
-                       spin_lock(&dum->lock);
-               }
-       }
-
-       dum_hcd->old_status = dum_hcd->port_status;
-       dum_hcd->old_active = dum_hcd->active;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* SLAVE/GADGET SIDE DRIVER
- *
- * This only tracks gadget state.  All the work is done when the host
- * side tries some (emulated) i/o operation.  Real device controller
- * drivers would do real i/o using dma, fifos, irqs, timers, etc.
- */
-
-#define is_enabled(dum) \
-       (dum->port_status & USB_PORT_STAT_ENABLE)
-
-static int dummy_enable(struct usb_ep *_ep,
-               const struct usb_endpoint_descriptor *desc)
-{
-       struct dummy            *dum;
-       struct dummy_hcd        *dum_hcd;
-       struct dummy_ep         *ep;
-       unsigned                max;
-       int                     retval;
-
-       ep = usb_ep_to_dummy_ep(_ep);
-       if (!_ep || !desc || ep->desc || _ep->name == ep0name
-                       || desc->bDescriptorType != USB_DT_ENDPOINT)
-               return -EINVAL;
-       dum = ep_to_dummy(ep);
-       if (!dum->driver)
-               return -ESHUTDOWN;
-
-       dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
-       if (!is_enabled(dum_hcd))
-               return -ESHUTDOWN;
-
-       /*
-        * For HS/FS devices only bits 0..10 of the wMaxPacketSize represent the
-        * maximum packet size.
-        * For SS devices the wMaxPacketSize is limited by 1024.
-        */
-       max = usb_endpoint_maxp(desc) & 0x7ff;
-
-       /* drivers must not request bad settings, since lower levels
-        * (hardware or its drivers) may not check.  some endpoints
-        * can't do iso, many have maxpacket limitations, etc.
-        *
-        * since this "hardware" driver is here to help debugging, we
-        * have some extra sanity checks.  (there could be more though,
-        * especially for "ep9out" style fixed function ones.)
-        */
-       retval = -EINVAL;
-       switch (usb_endpoint_type(desc)) {
-       case USB_ENDPOINT_XFER_BULK:
-               if (strstr(ep->ep.name, "-iso")
-                               || strstr(ep->ep.name, "-int")) {
-                       goto done;
-               }
-               switch (dum->gadget.speed) {
-               case USB_SPEED_SUPER:
-                       if (max == 1024)
-                               break;
-                       goto done;
-               case USB_SPEED_HIGH:
-                       if (max == 512)
-                               break;
-                       goto done;
-               case USB_SPEED_FULL:
-                       if (max == 8 || max == 16 || max == 32 || max == 64)
-                               /* we'll fake any legal size */
-                               break;
-                       /* save a return statement */
-               default:
-                       goto done;
-               }
-               break;
-       case USB_ENDPOINT_XFER_INT:
-               if (strstr(ep->ep.name, "-iso")) /* bulk is ok */
-                       goto done;
-               /* real hardware might not handle all packet sizes */
-               switch (dum->gadget.speed) {
-               case USB_SPEED_SUPER:
-               case USB_SPEED_HIGH:
-                       if (max <= 1024)
-                               break;
-                       /* save a return statement */
-               case USB_SPEED_FULL:
-                       if (max <= 64)
-                               break;
-                       /* save a return statement */
-               default:
-                       if (max <= 8)
-                               break;
-                       goto done;
-               }
-               break;
-       case USB_ENDPOINT_XFER_ISOC:
-               if (strstr(ep->ep.name, "-bulk")
-                               || strstr(ep->ep.name, "-int"))
-                       goto done;
-               /* real hardware might not handle all packet sizes */
-               switch (dum->gadget.speed) {
-               case USB_SPEED_SUPER:
-               case USB_SPEED_HIGH:
-                       if (max <= 1024)
-                               break;
-                       /* save a return statement */
-               case USB_SPEED_FULL:
-                       if (max <= 1023)
-                               break;
-                       /* save a return statement */
-               default:
-                       goto done;
-               }
-               break;
-       default:
-               /* few chips support control except on ep0 */
-               goto done;
-       }
-
-       _ep->maxpacket = max;
-       if (usb_ss_max_streams(_ep->comp_desc)) {
-               if (!usb_endpoint_xfer_bulk(desc)) {
-                       dev_err(udc_dev(dum), "Can't enable stream support on "
-                                       "non-bulk ep %s\n", _ep->name);
-                       return -EINVAL;
-               }
-               ep->stream_en = 1;
-       }
-       ep->desc = desc;
-
-       dev_dbg(udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d stream %s\n",
-               _ep->name,
-               desc->bEndpointAddress & 0x0f,
-               (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
-               ({ char *val;
-                switch (usb_endpoint_type(desc)) {
-                case USB_ENDPOINT_XFER_BULK:
-                        val = "bulk";
-                        break;
-                case USB_ENDPOINT_XFER_ISOC:
-                        val = "iso";
-                        break;
-                case USB_ENDPOINT_XFER_INT:
-                        val = "intr";
-                        break;
-                default:
-                        val = "ctrl";
-                        break;
-                } val; }),
-               max, ep->stream_en ? "enabled" : "disabled");
-
-       /* at this point real hardware should be NAKing transfers
-        * to that endpoint, until a buffer is queued to it.
-        */
-       ep->halted = ep->wedged = 0;
-       retval = 0;
-done:
-       return retval;
-}
-
-static int dummy_disable(struct usb_ep *_ep)
-{
-       struct dummy_ep         *ep;
-       struct dummy            *dum;
-       unsigned long           flags;
-
-       ep = usb_ep_to_dummy_ep(_ep);
-       if (!_ep || !ep->desc || _ep->name == ep0name)
-               return -EINVAL;
-       dum = ep_to_dummy(ep);
-
-       spin_lock_irqsave(&dum->lock, flags);
-       ep->desc = NULL;
-       ep->stream_en = 0;
-       nuke(dum, ep);
-       spin_unlock_irqrestore(&dum->lock, flags);
-
-       dev_dbg(udc_dev(dum), "disabled %s\n", _ep->name);
-       return 0;
-}
-
-static struct usb_request *dummy_alloc_request(struct usb_ep *_ep,
-               gfp_t mem_flags)
-{
-       struct dummy_ep         *ep;
-       struct dummy_request    *req;
-
-       if (!_ep)
-               return NULL;
-       ep = usb_ep_to_dummy_ep(_ep);
-
-       req = kzalloc(sizeof(*req), mem_flags);
-       if (!req)
-               return NULL;
-       INIT_LIST_HEAD(&req->queue);
-       return &req->req;
-}
-
-static void dummy_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct dummy_request    *req;
-
-       if (!_ep || !_req) {
-               WARN_ON(1);
-               return;
-       }
-
-       req = usb_request_to_dummy_request(_req);
-       WARN_ON(!list_empty(&req->queue));
-       kfree(req);
-}
-
-static void fifo_complete(struct usb_ep *ep, struct usb_request *req)
-{
-}
-
-static int dummy_queue(struct usb_ep *_ep, struct usb_request *_req,
-               gfp_t mem_flags)
-{
-       struct dummy_ep         *ep;
-       struct dummy_request    *req;
-       struct dummy            *dum;
-       struct dummy_hcd        *dum_hcd;
-       unsigned long           flags;
-
-       req = usb_request_to_dummy_request(_req);
-       if (!_req || !list_empty(&req->queue) || !_req->complete)
-               return -EINVAL;
-
-       ep = usb_ep_to_dummy_ep(_ep);
-       if (!_ep || (!ep->desc && _ep->name != ep0name))
-               return -EINVAL;
-
-       dum = ep_to_dummy(ep);
-       dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
-       if (!dum->driver || !is_enabled(dum_hcd))
-               return -ESHUTDOWN;
-
-#if 0
-       dev_dbg(udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n",
-                       ep, _req, _ep->name, _req->length, _req->buf);
-#endif
-       _req->status = -EINPROGRESS;
-       _req->actual = 0;
-       spin_lock_irqsave(&dum->lock, flags);
-
-       /* implement an emulated single-request FIFO */
-       if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
-                       list_empty(&dum->fifo_req.queue) &&
-                       list_empty(&ep->queue) &&
-                       _req->length <= FIFO_SIZE) {
-               req = &dum->fifo_req;
-               req->req = *_req;
-               req->req.buf = dum->fifo_buf;
-               memcpy(dum->fifo_buf, _req->buf, _req->length);
-               req->req.context = dum;
-               req->req.complete = fifo_complete;
-
-               list_add_tail(&req->queue, &ep->queue);
-               spin_unlock(&dum->lock);
-               _req->actual = _req->length;
-               _req->status = 0;
-               _req->complete(_ep, _req);
-               spin_lock(&dum->lock);
-       }  else
-               list_add_tail(&req->queue, &ep->queue);
-       spin_unlock_irqrestore(&dum->lock, flags);
-
-       /* real hardware would likely enable transfers here, in case
-        * it'd been left NAKing.
-        */
-       return 0;
-}
-
-static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct dummy_ep         *ep;
-       struct dummy            *dum;
-       int                     retval = -EINVAL;
-       unsigned long           flags;
-       struct dummy_request    *req = NULL;
-
-       if (!_ep || !_req)
-               return retval;
-       ep = usb_ep_to_dummy_ep(_ep);
-       dum = ep_to_dummy(ep);
-
-       if (!dum->driver)
-               return -ESHUTDOWN;
-
-       local_irq_save(flags);
-       spin_lock(&dum->lock);
-       list_for_each_entry(req, &ep->queue, queue) {
-               if (&req->req == _req) {
-                       list_del_init(&req->queue);
-                       _req->status = -ECONNRESET;
-                       retval = 0;
-                       break;
-               }
-       }
-       spin_unlock(&dum->lock);
-
-       if (retval == 0) {
-               dev_dbg(udc_dev(dum),
-                               "dequeued req %p from %s, len %d buf %p\n",
-                               req, _ep->name, _req->length, _req->buf);
-               _req->complete(_ep, _req);
-       }
-       local_irq_restore(flags);
-       return retval;
-}
-
-static int
-dummy_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
-{
-       struct dummy_ep         *ep;
-       struct dummy            *dum;
-
-       if (!_ep)
-               return -EINVAL;
-       ep = usb_ep_to_dummy_ep(_ep);
-       dum = ep_to_dummy(ep);
-       if (!dum->driver)
-               return -ESHUTDOWN;
-       if (!value)
-               ep->halted = ep->wedged = 0;
-       else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
-                       !list_empty(&ep->queue))
-               return -EAGAIN;
-       else {
-               ep->halted = 1;
-               if (wedged)
-                       ep->wedged = 1;
-       }
-       /* FIXME clear emulated data toggle too */
-       return 0;
-}
-
-static int
-dummy_set_halt(struct usb_ep *_ep, int value)
-{
-       return dummy_set_halt_and_wedge(_ep, value, 0);
-}
-
-static int dummy_set_wedge(struct usb_ep *_ep)
-{
-       if (!_ep || _ep->name == ep0name)
-               return -EINVAL;
-       return dummy_set_halt_and_wedge(_ep, 1, 1);
-}
-
-static const struct usb_ep_ops dummy_ep_ops = {
-       .enable         = dummy_enable,
-       .disable        = dummy_disable,
-
-       .alloc_request  = dummy_alloc_request,
-       .free_request   = dummy_free_request,
-
-       .queue          = dummy_queue,
-       .dequeue        = dummy_dequeue,
-
-       .set_halt       = dummy_set_halt,
-       .set_wedge      = dummy_set_wedge,
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* there are both host and device side versions of this call ... */
-static int dummy_g_get_frame(struct usb_gadget *_gadget)
-{
-       struct timeval  tv;
-
-       do_gettimeofday(&tv);
-       return tv.tv_usec / 1000;
-}
-
-static int dummy_wakeup(struct usb_gadget *_gadget)
-{
-       struct dummy_hcd *dum_hcd;
-
-       dum_hcd = gadget_to_dummy_hcd(_gadget);
-       if (!(dum_hcd->dum->devstatus & ((1 << USB_DEVICE_B_HNP_ENABLE)
-                               | (1 << USB_DEVICE_REMOTE_WAKEUP))))
-               return -EINVAL;
-       if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0)
-               return -ENOLINK;
-       if ((dum_hcd->port_status & USB_PORT_STAT_SUSPEND) == 0 &&
-                        dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
-               return -EIO;
-
-       /* FIXME: What if the root hub is suspended but the port isn't? */
-
-       /* hub notices our request, issues downstream resume, etc */
-       dum_hcd->resuming = 1;
-       dum_hcd->re_timeout = jiffies + msecs_to_jiffies(20);
-       mod_timer(&dummy_hcd_to_hcd(dum_hcd)->rh_timer, dum_hcd->re_timeout);
-       return 0;
-}
-
-static int dummy_set_selfpowered(struct usb_gadget *_gadget, int value)
-{
-       struct dummy    *dum;
-
-       dum = gadget_to_dummy_hcd(_gadget)->dum;
-       if (value)
-               dum->devstatus |= (1 << USB_DEVICE_SELF_POWERED);
-       else
-               dum->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
-       return 0;
-}
-
-static void dummy_udc_update_ep0(struct dummy *dum)
-{
-       if (dum->gadget.speed == USB_SPEED_SUPER)
-               dum->ep[0].ep.maxpacket = 9;
-       else
-               dum->ep[0].ep.maxpacket = 64;
-}
-
-static int dummy_pullup(struct usb_gadget *_gadget, int value)
-{
-       struct dummy_hcd *dum_hcd;
-       struct dummy    *dum;
-       unsigned long   flags;
-
-       dum = gadget_dev_to_dummy(&_gadget->dev);
-
-       if (value && dum->driver) {
-               if (mod_data.is_super_speed)
-                       dum->gadget.speed = dum->driver->max_speed;
-               else if (mod_data.is_high_speed)
-                       dum->gadget.speed = min_t(u8, USB_SPEED_HIGH,
-                                       dum->driver->max_speed);
-               else
-                       dum->gadget.speed = USB_SPEED_FULL;
-               dummy_udc_update_ep0(dum);
-
-               if (dum->gadget.speed < dum->driver->max_speed)
-                       dev_dbg(udc_dev(dum), "This device can perform faster"
-                               " if you connect it to a %s port...\n",
-                               usb_speed_string(dum->driver->max_speed));
-       }
-       dum_hcd = gadget_to_dummy_hcd(_gadget);
-
-       spin_lock_irqsave(&dum->lock, flags);
-       dum->pullup = (value != 0);
-       set_link_state(dum_hcd);
-       spin_unlock_irqrestore(&dum->lock, flags);
-
-       usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
-       return 0;
-}
-
-static int dummy_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-static int dummy_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-
-static const struct usb_gadget_ops dummy_ops = {
-       .get_frame      = dummy_g_get_frame,
-       .wakeup         = dummy_wakeup,
-       .set_selfpowered = dummy_set_selfpowered,
-       .pullup         = dummy_pullup,
-       .udc_start      = dummy_udc_start,
-       .udc_stop       = dummy_udc_stop,
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* "function" sysfs attribute */
-static ssize_t function_show(struct device *dev, struct device_attribute *attr,
-               char *buf)
-{
-       struct dummy    *dum = gadget_dev_to_dummy(dev);
-
-       if (!dum->driver || !dum->driver->function)
-               return 0;
-       return scnprintf(buf, PAGE_SIZE, "%s\n", dum->driver->function);
-}
-static DEVICE_ATTR_RO(function);
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Driver registration/unregistration.
- *
- * This is basically hardware-specific; there's usually only one real USB
- * device (not host) controller since that's how USB devices are intended
- * to work.  So most implementations of these api calls will rely on the
- * fact that only one driver will ever bind to the hardware.  But curious
- * hardware can be built with discrete components, so the gadget API doesn't
- * require that assumption.
- *
- * For this emulator, it might be convenient to create a usb slave device
- * for each driver that registers:  just add to a big root hub.
- */
-
-static int dummy_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct dummy_hcd        *dum_hcd = gadget_to_dummy_hcd(g);
-       struct dummy            *dum = dum_hcd->dum;
-
-       if (driver->max_speed == USB_SPEED_UNKNOWN)
-               return -EINVAL;
-
-       /*
-        * SLAVE side init ... the layer above hardware, which
-        * can't enumerate without help from the driver we're binding.
-        */
-
-       dum->devstatus = 0;
-
-       dum->driver = driver;
-       dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
-                       driver->driver.name);
-       return 0;
-}
-
-static int dummy_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct dummy_hcd        *dum_hcd = gadget_to_dummy_hcd(g);
-       struct dummy            *dum = dum_hcd->dum;
-
-       if (driver)
-               dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
-                               driver->driver.name);
-
-       dum->driver = NULL;
-
-       return 0;
-}
-
-#undef is_enabled
-
-/* The gadget structure is stored inside the hcd structure and will be
- * released along with it. */
-static void init_dummy_udc_hw(struct dummy *dum)
-{
-       int i;
-
-       INIT_LIST_HEAD(&dum->gadget.ep_list);
-       for (i = 0; i < DUMMY_ENDPOINTS; i++) {
-               struct dummy_ep *ep = &dum->ep[i];
-
-               if (!ep_name[i])
-                       break;
-               ep->ep.name = ep_name[i];
-               ep->ep.ops = &dummy_ep_ops;
-               list_add_tail(&ep->ep.ep_list, &dum->gadget.ep_list);
-               ep->halted = ep->wedged = ep->already_seen =
-                               ep->setup_stage = 0;
-               usb_ep_set_maxpacket_limit(&ep->ep, ~0);
-               ep->ep.max_streams = 16;
-               ep->last_io = jiffies;
-               ep->gadget = &dum->gadget;
-               ep->desc = NULL;
-               INIT_LIST_HEAD(&ep->queue);
-       }
-
-       dum->gadget.ep0 = &dum->ep[0].ep;
-       list_del_init(&dum->ep[0].ep.ep_list);
-       INIT_LIST_HEAD(&dum->fifo_req.queue);
-
-#ifdef CONFIG_USB_OTG
-       dum->gadget.is_otg = 1;
-#endif
-}
-
-static int dummy_udc_probe(struct platform_device *pdev)
-{
-       struct dummy    *dum;
-       int             rc;
-
-       dum = *((void **)dev_get_platdata(&pdev->dev));
-       dum->gadget.name = gadget_name;
-       dum->gadget.ops = &dummy_ops;
-       dum->gadget.max_speed = USB_SPEED_SUPER;
-
-       dum->gadget.dev.parent = &pdev->dev;
-       init_dummy_udc_hw(dum);
-
-       rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget);
-       if (rc < 0)
-               goto err_udc;
-
-       rc = device_create_file(&dum->gadget.dev, &dev_attr_function);
-       if (rc < 0)
-               goto err_dev;
-       platform_set_drvdata(pdev, dum);
-       return rc;
-
-err_dev:
-       usb_del_gadget_udc(&dum->gadget);
-err_udc:
-       return rc;
-}
-
-static int dummy_udc_remove(struct platform_device *pdev)
-{
-       struct dummy    *dum = platform_get_drvdata(pdev);
-
-       device_remove_file(&dum->gadget.dev, &dev_attr_function);
-       usb_del_gadget_udc(&dum->gadget);
-       return 0;
-}
-
-static void dummy_udc_pm(struct dummy *dum, struct dummy_hcd *dum_hcd,
-               int suspend)
-{
-       spin_lock_irq(&dum->lock);
-       dum->udc_suspended = suspend;
-       set_link_state(dum_hcd);
-       spin_unlock_irq(&dum->lock);
-}
-
-static int dummy_udc_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       struct dummy            *dum = platform_get_drvdata(pdev);
-       struct dummy_hcd        *dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
-
-       dev_dbg(&pdev->dev, "%s\n", __func__);
-       dummy_udc_pm(dum, dum_hcd, 1);
-       usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
-       return 0;
-}
-
-static int dummy_udc_resume(struct platform_device *pdev)
-{
-       struct dummy            *dum = platform_get_drvdata(pdev);
-       struct dummy_hcd        *dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
-
-       dev_dbg(&pdev->dev, "%s\n", __func__);
-       dummy_udc_pm(dum, dum_hcd, 0);
-       usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
-       return 0;
-}
-
-static struct platform_driver dummy_udc_driver = {
-       .probe          = dummy_udc_probe,
-       .remove         = dummy_udc_remove,
-       .suspend        = dummy_udc_suspend,
-       .resume         = dummy_udc_resume,
-       .driver         = {
-               .name   = (char *) gadget_name,
-               .owner  = THIS_MODULE,
-       },
-};
-
-/*-------------------------------------------------------------------------*/
-
-static unsigned int dummy_get_ep_idx(const struct usb_endpoint_descriptor *desc)
-{
-       unsigned int index;
-
-       index = usb_endpoint_num(desc) << 1;
-       if (usb_endpoint_dir_in(desc))
-               index |= 1;
-       return index;
-}
-
-/* MASTER/HOST SIDE DRIVER
- *
- * this uses the hcd framework to hook up to host side drivers.
- * its root hub will only have one device, otherwise it acts like
- * a normal host controller.
- *
- * when urbs are queued, they're just stuck on a list that we
- * scan in a timer callback.  that callback connects writes from
- * the host with reads from the device, and so on, based on the
- * usb 2.0 rules.
- */
-
-static int dummy_ep_stream_en(struct dummy_hcd *dum_hcd, struct urb *urb)
-{
-       const struct usb_endpoint_descriptor *desc = &urb->ep->desc;
-       u32 index;
-
-       if (!usb_endpoint_xfer_bulk(desc))
-               return 0;
-
-       index = dummy_get_ep_idx(desc);
-       return (1 << index) & dum_hcd->stream_en_ep;
-}
-
-/*
- * The max stream number is saved as a nibble so for the 30 possible endpoints
- * we only 15 bytes of memory. Therefore we are limited to max 16 streams (0
- * means we use only 1 stream). The maximum according to the spec is 16bit so
- * if the 16 stream limit is about to go, the array size should be incremented
- * to 30 elements of type u16.
- */
-static int get_max_streams_for_pipe(struct dummy_hcd *dum_hcd,
-               unsigned int pipe)
-{
-       int max_streams;
-
-       max_streams = dum_hcd->num_stream[usb_pipeendpoint(pipe)];
-       if (usb_pipeout(pipe))
-               max_streams >>= 4;
-       else
-               max_streams &= 0xf;
-       max_streams++;
-       return max_streams;
-}
-
-static void set_max_streams_for_pipe(struct dummy_hcd *dum_hcd,
-               unsigned int pipe, unsigned int streams)
-{
-       int max_streams;
-
-       streams--;
-       max_streams = dum_hcd->num_stream[usb_pipeendpoint(pipe)];
-       if (usb_pipeout(pipe)) {
-               streams <<= 4;
-               max_streams &= 0xf;
-       } else {
-               max_streams &= 0xf0;
-       }
-       max_streams |= streams;
-       dum_hcd->num_stream[usb_pipeendpoint(pipe)] = max_streams;
-}
-
-static int dummy_validate_stream(struct dummy_hcd *dum_hcd, struct urb *urb)
-{
-       unsigned int max_streams;
-       int enabled;
-
-       enabled = dummy_ep_stream_en(dum_hcd, urb);
-       if (!urb->stream_id) {
-               if (enabled)
-                       return -EINVAL;
-               return 0;
-       }
-       if (!enabled)
-               return -EINVAL;
-
-       max_streams = get_max_streams_for_pipe(dum_hcd,
-                       usb_pipeendpoint(urb->pipe));
-       if (urb->stream_id > max_streams) {
-               dev_err(dummy_dev(dum_hcd), "Stream id %d is out of range.\n",
-                               urb->stream_id);
-               BUG();
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int dummy_urb_enqueue(
-       struct usb_hcd                  *hcd,
-       struct urb                      *urb,
-       gfp_t                           mem_flags
-) {
-       struct dummy_hcd *dum_hcd;
-       struct urbp     *urbp;
-       unsigned long   flags;
-       int             rc;
-
-       urbp = kmalloc(sizeof *urbp, mem_flags);
-       if (!urbp)
-               return -ENOMEM;
-       urbp->urb = urb;
-       urbp->miter_started = 0;
-
-       dum_hcd = hcd_to_dummy_hcd(hcd);
-       spin_lock_irqsave(&dum_hcd->dum->lock, flags);
-
-       rc = dummy_validate_stream(dum_hcd, urb);
-       if (rc) {
-               kfree(urbp);
-               goto done;
-       }
-
-       rc = usb_hcd_link_urb_to_ep(hcd, urb);
-       if (rc) {
-               kfree(urbp);
-               goto done;
-       }
-
-       if (!dum_hcd->udev) {
-               dum_hcd->udev = urb->dev;
-               usb_get_dev(dum_hcd->udev);
-       } else if (unlikely(dum_hcd->udev != urb->dev))
-               dev_err(dummy_dev(dum_hcd), "usb_device address has changed!\n");
-
-       list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list);
-       urb->hcpriv = urbp;
-       if (usb_pipetype(urb->pipe) == PIPE_CONTROL)
-               urb->error_count = 1;           /* mark as a new urb */
-
-       /* kick the scheduler, it'll do the rest */
-       if (!timer_pending(&dum_hcd->timer))
-               mod_timer(&dum_hcd->timer, jiffies + 1);
-
- done:
-       spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
-       return rc;
-}
-
-static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
-{
-       struct dummy_hcd *dum_hcd;
-       unsigned long   flags;
-       int             rc;
-
-       /* giveback happens automatically in timer callback,
-        * so make sure the callback happens */
-       dum_hcd = hcd_to_dummy_hcd(hcd);
-       spin_lock_irqsave(&dum_hcd->dum->lock, flags);
-
-       rc = usb_hcd_check_unlink_urb(hcd, urb, status);
-       if (!rc && dum_hcd->rh_state != DUMMY_RH_RUNNING &&
-                       !list_empty(&dum_hcd->urbp_list))
-               mod_timer(&dum_hcd->timer, jiffies);
-
-       spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
-       return rc;
-}
-
-static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req,
-               u32 len)
-{
-       void *ubuf, *rbuf;
-       struct urbp *urbp = urb->hcpriv;
-       int to_host;
-       struct sg_mapping_iter *miter = &urbp->miter;
-       u32 trans = 0;
-       u32 this_sg;
-       bool next_sg;
-
-       to_host = usb_pipein(urb->pipe);
-       rbuf = req->req.buf + req->req.actual;
-
-       if (!urb->num_sgs) {
-               ubuf = urb->transfer_buffer + urb->actual_length;
-               if (to_host)
-                       memcpy(ubuf, rbuf, len);
-               else
-                       memcpy(rbuf, ubuf, len);
-               return len;
-       }
-
-       if (!urbp->miter_started) {
-               u32 flags = SG_MITER_ATOMIC;
-
-               if (to_host)
-                       flags |= SG_MITER_TO_SG;
-               else
-                       flags |= SG_MITER_FROM_SG;
-
-               sg_miter_start(miter, urb->sg, urb->num_sgs, flags);
-               urbp->miter_started = 1;
-       }
-       next_sg = sg_miter_next(miter);
-       if (next_sg == false) {
-               WARN_ON_ONCE(1);
-               return -EINVAL;
-       }
-       do {
-               ubuf = miter->addr;
-               this_sg = min_t(u32, len, miter->length);
-               miter->consumed = this_sg;
-               trans += this_sg;
-
-               if (to_host)
-                       memcpy(ubuf, rbuf, this_sg);
-               else
-                       memcpy(rbuf, ubuf, this_sg);
-               len -= this_sg;
-
-               if (!len)
-                       break;
-               next_sg = sg_miter_next(miter);
-               if (next_sg == false) {
-                       WARN_ON_ONCE(1);
-                       return -EINVAL;
-               }
-
-               rbuf += this_sg;
-       } while (1);
-
-       sg_miter_stop(miter);
-       return trans;
-}
-
-/* transfer up to a frame's worth; caller must own lock */
-static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
-               struct dummy_ep *ep, int limit, int *status)
-{
-       struct dummy            *dum = dum_hcd->dum;
-       struct dummy_request    *req;
-
-top:
-       /* if there's no request queued, the device is NAKing; return */
-       list_for_each_entry(req, &ep->queue, queue) {
-               unsigned        host_len, dev_len, len;
-               int             is_short, to_host;
-               int             rescan = 0;
-
-               if (dummy_ep_stream_en(dum_hcd, urb)) {
-                       if ((urb->stream_id != req->req.stream_id))
-                               continue;
-               }
-
-               /* 1..N packets of ep->ep.maxpacket each ... the last one
-                * may be short (including zero length).
-                *
-                * writer can send a zlp explicitly (length 0) or implicitly
-                * (length mod maxpacket zero, and 'zero' flag); they always
-                * terminate reads.
-                */
-               host_len = urb->transfer_buffer_length - urb->actual_length;
-               dev_len = req->req.length - req->req.actual;
-               len = min(host_len, dev_len);
-
-               /* FIXME update emulated data toggle too */
-
-               to_host = usb_pipein(urb->pipe);
-               if (unlikely(len == 0))
-                       is_short = 1;
-               else {
-                       /* not enough bandwidth left? */
-                       if (limit < ep->ep.maxpacket && limit < len)
-                               break;
-                       len = min_t(unsigned, len, limit);
-                       if (len == 0)
-                               break;
-
-                       /* use an extra pass for the final short packet */
-                       if (len > ep->ep.maxpacket) {
-                               rescan = 1;
-                               len -= (len % ep->ep.maxpacket);
-                       }
-                       is_short = (len % ep->ep.maxpacket) != 0;
-
-                       len = dummy_perform_transfer(urb, req, len);
-
-                       ep->last_io = jiffies;
-                       if ((int)len < 0) {
-                               req->req.status = len;
-                       } else {
-                               limit -= len;
-                               urb->actual_length += len;
-                               req->req.actual += len;
-                       }
-               }
-
-               /* short packets terminate, maybe with overflow/underflow.
-                * it's only really an error to write too much.
-                *
-                * partially filling a buffer optionally blocks queue advances
-                * (so completion handlers can clean up the queue) but we don't
-                * need to emulate such data-in-flight.
-                */
-               if (is_short) {
-                       if (host_len == dev_len) {
-                               req->req.status = 0;
-                               *status = 0;
-                       } else if (to_host) {
-                               req->req.status = 0;
-                               if (dev_len > host_len)
-                                       *status = -EOVERFLOW;
-                               else
-                                       *status = 0;
-                       } else if (!to_host) {
-                               *status = 0;
-                               if (host_len > dev_len)
-                                       req->req.status = -EOVERFLOW;
-                               else
-                                       req->req.status = 0;
-                       }
-
-               /* many requests terminate without a short packet */
-               } else {
-                       if (req->req.length == req->req.actual
-                                       && !req->req.zero)
-                               req->req.status = 0;
-                       if (urb->transfer_buffer_length == urb->actual_length
-                                       && !(urb->transfer_flags
-                                               & URB_ZERO_PACKET))
-                               *status = 0;
-               }
-
-               /* device side completion --> continuable */
-               if (req->req.status != -EINPROGRESS) {
-                       list_del_init(&req->queue);
-
-                       spin_unlock(&dum->lock);
-                       req->req.complete(&ep->ep, &req->req);
-                       spin_lock(&dum->lock);
-
-                       /* requests might have been unlinked... */
-                       rescan = 1;
-               }
-
-               /* host side completion --> terminate */
-               if (*status != -EINPROGRESS)
-                       break;
-
-               /* rescan to continue with any other queued i/o */
-               if (rescan)
-                       goto top;
-       }
-       return limit;
-}
-
-static int periodic_bytes(struct dummy *dum, struct dummy_ep *ep)
-{
-       int     limit = ep->ep.maxpacket;
-
-       if (dum->gadget.speed == USB_SPEED_HIGH) {
-               int     tmp;
-
-               /* high bandwidth mode */
-               tmp = usb_endpoint_maxp(ep->desc);
-               tmp = (tmp >> 11) & 0x03;
-               tmp *= 8 /* applies to entire frame */;
-               limit += limit * tmp;
-       }
-       if (dum->gadget.speed == USB_SPEED_SUPER) {
-               switch (usb_endpoint_type(ep->desc)) {
-               case USB_ENDPOINT_XFER_ISOC:
-                       /* Sec. 4.4.8.2 USB3.0 Spec */
-                       limit = 3 * 16 * 1024 * 8;
-                       break;
-               case USB_ENDPOINT_XFER_INT:
-                       /* Sec. 4.4.7.2 USB3.0 Spec */
-                       limit = 3 * 1024 * 8;
-                       break;
-               case USB_ENDPOINT_XFER_BULK:
-               default:
-                       break;
-               }
-       }
-       return limit;
-}
-
-#define is_active(dum_hcd)     ((dum_hcd->port_status & \
-               (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE | \
-                       USB_PORT_STAT_SUSPEND)) \
-               == (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE))
-
-static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address)
-{
-       int             i;
-
-       if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ?
-                       dum->ss_hcd : dum->hs_hcd)))
-               return NULL;
-       if ((address & ~USB_DIR_IN) == 0)
-               return &dum->ep[0];
-       for (i = 1; i < DUMMY_ENDPOINTS; i++) {
-               struct dummy_ep *ep = &dum->ep[i];
-
-               if (!ep->desc)
-                       continue;
-               if (ep->desc->bEndpointAddress == address)
-                       return ep;
-       }
-       return NULL;
-}
-
-#undef is_active
-
-#define Dev_Request    (USB_TYPE_STANDARD | USB_RECIP_DEVICE)
-#define Dev_InRequest  (Dev_Request | USB_DIR_IN)
-#define Intf_Request   (USB_TYPE_STANDARD | USB_RECIP_INTERFACE)
-#define Intf_InRequest (Intf_Request | USB_DIR_IN)
-#define Ep_Request     (USB_TYPE_STANDARD | USB_RECIP_ENDPOINT)
-#define Ep_InRequest   (Ep_Request | USB_DIR_IN)
-
-
-/**
- * handle_control_request() - handles all control transfers
- * @dum: pointer to dummy (the_controller)
- * @urb: the urb request to handle
- * @setup: pointer to the setup data for a USB device control
- *      request
- * @status: pointer to request handling status
- *
- * Return 0 - if the request was handled
- *       1 - if the request wasn't handles
- *       error code on error
- */
-static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,
-                                 struct usb_ctrlrequest *setup,
-                                 int *status)
-{
-       struct dummy_ep         *ep2;
-       struct dummy            *dum = dum_hcd->dum;
-       int                     ret_val = 1;
-       unsigned        w_index;
-       unsigned        w_value;
-
-       w_index = le16_to_cpu(setup->wIndex);
-       w_value = le16_to_cpu(setup->wValue);
-       switch (setup->bRequest) {
-       case USB_REQ_SET_ADDRESS:
-               if (setup->bRequestType != Dev_Request)
-                       break;
-               dum->address = w_value;
-               *status = 0;
-               dev_dbg(udc_dev(dum), "set_address = %d\n",
-                               w_value);
-               ret_val = 0;
-               break;
-       case USB_REQ_SET_FEATURE:
-               if (setup->bRequestType == Dev_Request) {
-                       ret_val = 0;
-                       switch (w_value) {
-                       case USB_DEVICE_REMOTE_WAKEUP:
-                               break;
-                       case USB_DEVICE_B_HNP_ENABLE:
-                               dum->gadget.b_hnp_enable = 1;
-                               break;
-                       case USB_DEVICE_A_HNP_SUPPORT:
-                               dum->gadget.a_hnp_support = 1;
-                               break;
-                       case USB_DEVICE_A_ALT_HNP_SUPPORT:
-                               dum->gadget.a_alt_hnp_support = 1;
-                               break;
-                       case USB_DEVICE_U1_ENABLE:
-                               if (dummy_hcd_to_hcd(dum_hcd)->speed ==
-                                   HCD_USB3)
-                                       w_value = USB_DEV_STAT_U1_ENABLED;
-                               else
-                                       ret_val = -EOPNOTSUPP;
-                               break;
-                       case USB_DEVICE_U2_ENABLE:
-                               if (dummy_hcd_to_hcd(dum_hcd)->speed ==
-                                   HCD_USB3)
-                                       w_value = USB_DEV_STAT_U2_ENABLED;
-                               else
-                                       ret_val = -EOPNOTSUPP;
-                               break;
-                       case USB_DEVICE_LTM_ENABLE:
-                               if (dummy_hcd_to_hcd(dum_hcd)->speed ==
-                                   HCD_USB3)
-                                       w_value = USB_DEV_STAT_LTM_ENABLED;
-                               else
-                                       ret_val = -EOPNOTSUPP;
-                               break;
-                       default:
-                               ret_val = -EOPNOTSUPP;
-                       }
-                       if (ret_val == 0) {
-                               dum->devstatus |= (1 << w_value);
-                               *status = 0;
-                       }
-               } else if (setup->bRequestType == Ep_Request) {
-                       /* endpoint halt */
-                       ep2 = find_endpoint(dum, w_index);
-                       if (!ep2 || ep2->ep.name == ep0name) {
-                               ret_val = -EOPNOTSUPP;
-                               break;
-                       }
-                       ep2->halted = 1;
-                       ret_val = 0;
-                       *status = 0;
-               }
-               break;
-       case USB_REQ_CLEAR_FEATURE:
-               if (setup->bRequestType == Dev_Request) {
-                       ret_val = 0;
-                       switch (w_value) {
-                       case USB_DEVICE_REMOTE_WAKEUP:
-                               w_value = USB_DEVICE_REMOTE_WAKEUP;
-                               break;
-                       case USB_DEVICE_U1_ENABLE:
-                               if (dummy_hcd_to_hcd(dum_hcd)->speed ==
-                                   HCD_USB3)
-                                       w_value = USB_DEV_STAT_U1_ENABLED;
-                               else
-                                       ret_val = -EOPNOTSUPP;
-                               break;
-                       case USB_DEVICE_U2_ENABLE:
-                               if (dummy_hcd_to_hcd(dum_hcd)->speed ==
-                                   HCD_USB3)
-                                       w_value = USB_DEV_STAT_U2_ENABLED;
-                               else
-                                       ret_val = -EOPNOTSUPP;
-                               break;
-                       case USB_DEVICE_LTM_ENABLE:
-                               if (dummy_hcd_to_hcd(dum_hcd)->speed ==
-                                   HCD_USB3)
-                                       w_value = USB_DEV_STAT_LTM_ENABLED;
-                               else
-                                       ret_val = -EOPNOTSUPP;
-                               break;
-                       default:
-                               ret_val = -EOPNOTSUPP;
-                               break;
-                       }
-                       if (ret_val == 0) {
-                               dum->devstatus &= ~(1 << w_value);
-                               *status = 0;
-                       }
-               } else if (setup->bRequestType == Ep_Request) {
-                       /* endpoint halt */
-                       ep2 = find_endpoint(dum, w_index);
-                       if (!ep2) {
-                               ret_val = -EOPNOTSUPP;
-                               break;
-                       }
-                       if (!ep2->wedged)
-                               ep2->halted = 0;
-                       ret_val = 0;
-                       *status = 0;
-               }
-               break;
-       case USB_REQ_GET_STATUS:
-               if (setup->bRequestType == Dev_InRequest
-                               || setup->bRequestType == Intf_InRequest
-                               || setup->bRequestType == Ep_InRequest) {
-                       char *buf;
-                       /*
-                        * device: remote wakeup, selfpowered
-                        * interface: nothing
-                        * endpoint: halt
-                        */
-                       buf = (char *)urb->transfer_buffer;
-                       if (urb->transfer_buffer_length > 0) {
-                               if (setup->bRequestType == Ep_InRequest) {
-                                       ep2 = find_endpoint(dum, w_index);
-                                       if (!ep2) {
-                                               ret_val = -EOPNOTSUPP;
-                                               break;
-                                       }
-                                       buf[0] = ep2->halted;
-                               } else if (setup->bRequestType ==
-                                          Dev_InRequest) {
-                                       buf[0] = (u8)dum->devstatus;
-                               } else
-                                       buf[0] = 0;
-                       }
-                       if (urb->transfer_buffer_length > 1)
-                               buf[1] = 0;
-                       urb->actual_length = min_t(u32, 2,
-                               urb->transfer_buffer_length);
-                       ret_val = 0;
-                       *status = 0;
-               }
-               break;
-       }
-       return ret_val;
-}
-
-/* drive both sides of the transfers; looks like irq handlers to
- * both drivers except the callbacks aren't in_irq().
- */
-static void dummy_timer(unsigned long _dum_hcd)
-{
-       struct dummy_hcd        *dum_hcd = (struct dummy_hcd *) _dum_hcd;
-       struct dummy            *dum = dum_hcd->dum;
-       struct urbp             *urbp, *tmp;
-       unsigned long           flags;
-       int                     limit, total;
-       int                     i;
-
-       /* simplistic model for one frame's bandwidth */
-       switch (dum->gadget.speed) {
-       case USB_SPEED_LOW:
-               total = 8/*bytes*/ * 12/*packets*/;
-               break;
-       case USB_SPEED_FULL:
-               total = 64/*bytes*/ * 19/*packets*/;
-               break;
-       case USB_SPEED_HIGH:
-               total = 512/*bytes*/ * 13/*packets*/ * 8/*uframes*/;
-               break;
-       case USB_SPEED_SUPER:
-               /* Bus speed is 500000 bytes/ms, so use a little less */
-               total = 490000;
-               break;
-       default:
-               dev_err(dummy_dev(dum_hcd), "bogus device speed\n");
-               return;
-       }
-
-       /* FIXME if HZ != 1000 this will probably misbehave ... */
-
-       /* look at each urb queued by the host side driver */
-       spin_lock_irqsave(&dum->lock, flags);
-
-       if (!dum_hcd->udev) {
-               dev_err(dummy_dev(dum_hcd),
-                               "timer fired with no URBs pending?\n");
-               spin_unlock_irqrestore(&dum->lock, flags);
-               return;
-       }
-
-       for (i = 0; i < DUMMY_ENDPOINTS; i++) {
-               if (!ep_name[i])
-                       break;
-               dum->ep[i].already_seen = 0;
-       }
-
-restart:
-       list_for_each_entry_safe(urbp, tmp, &dum_hcd->urbp_list, urbp_list) {
-               struct urb              *urb;
-               struct dummy_request    *req;
-               u8                      address;
-               struct dummy_ep         *ep = NULL;
-               int                     type;
-               int                     status = -EINPROGRESS;
-
-               urb = urbp->urb;
-               if (urb->unlinked)
-                       goto return_urb;
-               else if (dum_hcd->rh_state != DUMMY_RH_RUNNING)
-                       continue;
-               type = usb_pipetype(urb->pipe);
-
-               /* used up this frame's non-periodic bandwidth?
-                * FIXME there's infinite bandwidth for control and
-                * periodic transfers ... unrealistic.
-                */
-               if (total <= 0 && type == PIPE_BULK)
-                       continue;
-
-               /* find the gadget's ep for this request (if configured) */
-               address = usb_pipeendpoint (urb->pipe);
-               if (usb_pipein(urb->pipe))
-                       address |= USB_DIR_IN;
-               ep = find_endpoint(dum, address);
-               if (!ep) {
-                       /* set_configuration() disagreement */
-                       dev_dbg(dummy_dev(dum_hcd),
-                               "no ep configured for urb %p\n",
-                               urb);
-                       status = -EPROTO;
-                       goto return_urb;
-               }
-
-               if (ep->already_seen)
-                       continue;
-               ep->already_seen = 1;
-               if (ep == &dum->ep[0] && urb->error_count) {
-                       ep->setup_stage = 1;    /* a new urb */
-                       urb->error_count = 0;
-               }
-               if (ep->halted && !ep->setup_stage) {
-                       /* NOTE: must not be iso! */
-                       dev_dbg(dummy_dev(dum_hcd), "ep %s halted, urb %p\n",
-                                       ep->ep.name, urb);
-                       status = -EPIPE;
-                       goto return_urb;
-               }
-               /* FIXME make sure both ends agree on maxpacket */
-
-               /* handle control requests */
-               if (ep == &dum->ep[0] && ep->setup_stage) {
-                       struct usb_ctrlrequest          setup;
-                       int                             value = 1;
-
-                       setup = *(struct usb_ctrlrequest *) urb->setup_packet;
-                       /* paranoia, in case of stale queued data */
-                       list_for_each_entry(req, &ep->queue, queue) {
-                               list_del_init(&req->queue);
-                               req->req.status = -EOVERFLOW;
-                               dev_dbg(udc_dev(dum), "stale req = %p\n",
-                                               req);
-
-                               spin_unlock(&dum->lock);
-                               req->req.complete(&ep->ep, &req->req);
-                               spin_lock(&dum->lock);
-                               ep->already_seen = 0;
-                               goto restart;
-                       }
-
-                       /* gadget driver never sees set_address or operations
-                        * on standard feature flags.  some hardware doesn't
-                        * even expose them.
-                        */
-                       ep->last_io = jiffies;
-                       ep->setup_stage = 0;
-                       ep->halted = 0;
-
-                       value = handle_control_request(dum_hcd, urb, &setup,
-                                                      &status);
-
-                       /* gadget driver handles all other requests.  block
-                        * until setup() returns; no reentrancy issues etc.
-                        */
-                       if (value > 0) {
-                               spin_unlock(&dum->lock);
-                               value = dum->driver->setup(&dum->gadget,
-                                               &setup);
-                               spin_lock(&dum->lock);
-
-                               if (value >= 0) {
-                                       /* no delays (max 64KB data stage) */
-                                       limit = 64*1024;
-                                       goto treat_control_like_bulk;
-                               }
-                               /* error, see below */
-                       }
-
-                       if (value < 0) {
-                               if (value != -EOPNOTSUPP)
-                                       dev_dbg(udc_dev(dum),
-                                               "setup --> %d\n",
-                                               value);
-                               status = -EPIPE;
-                               urb->actual_length = 0;
-                       }
-
-                       goto return_urb;
-               }
-
-               /* non-control requests */
-               limit = total;
-               switch (usb_pipetype(urb->pipe)) {
-               case PIPE_ISOCHRONOUS:
-                       /* FIXME is it urb->interval since the last xfer?
-                        * use urb->iso_frame_desc[i].
-                        * complete whether or not ep has requests queued.
-                        * report random errors, to debug drivers.
-                        */
-                       limit = max(limit, periodic_bytes(dum, ep));
-                       status = -ENOSYS;
-                       break;
-
-               case PIPE_INTERRUPT:
-                       /* FIXME is it urb->interval since the last xfer?
-                        * this almost certainly polls too fast.
-                        */
-                       limit = max(limit, periodic_bytes(dum, ep));
-                       /* FALLTHROUGH */
-
-               default:
-treat_control_like_bulk:
-                       ep->last_io = jiffies;
-                       total = transfer(dum_hcd, urb, ep, limit, &status);
-                       break;
-               }
-
-               /* incomplete transfer? */
-               if (status == -EINPROGRESS)
-                       continue;
-
-return_urb:
-               list_del(&urbp->urbp_list);
-               kfree(urbp);
-               if (ep)
-                       ep->already_seen = ep->setup_stage = 0;
-
-               usb_hcd_unlink_urb_from_ep(dummy_hcd_to_hcd(dum_hcd), urb);
-               spin_unlock(&dum->lock);
-               usb_hcd_giveback_urb(dummy_hcd_to_hcd(dum_hcd), urb, status);
-               spin_lock(&dum->lock);
-
-               goto restart;
-       }
-
-       if (list_empty(&dum_hcd->urbp_list)) {
-               usb_put_dev(dum_hcd->udev);
-               dum_hcd->udev = NULL;
-       } else if (dum_hcd->rh_state == DUMMY_RH_RUNNING) {
-               /* want a 1 msec delay here */
-               mod_timer(&dum_hcd->timer, jiffies + msecs_to_jiffies(1));
-       }
-
-       spin_unlock_irqrestore(&dum->lock, flags);
-}
-
-/*-------------------------------------------------------------------------*/
-
-#define PORT_C_MASK \
-       ((USB_PORT_STAT_C_CONNECTION \
-       | USB_PORT_STAT_C_ENABLE \
-       | USB_PORT_STAT_C_SUSPEND \
-       | USB_PORT_STAT_C_OVERCURRENT \
-       | USB_PORT_STAT_C_RESET) << 16)
-
-static int dummy_hub_status(struct usb_hcd *hcd, char *buf)
-{
-       struct dummy_hcd        *dum_hcd;
-       unsigned long           flags;
-       int                     retval = 0;
-
-       dum_hcd = hcd_to_dummy_hcd(hcd);
-
-       spin_lock_irqsave(&dum_hcd->dum->lock, flags);
-       if (!HCD_HW_ACCESSIBLE(hcd))
-               goto done;
-
-       if (dum_hcd->resuming && time_after_eq(jiffies, dum_hcd->re_timeout)) {
-               dum_hcd->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
-               dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND;
-               set_link_state(dum_hcd);
-       }
-
-       if ((dum_hcd->port_status & PORT_C_MASK) != 0) {
-               *buf = (1 << 1);
-               dev_dbg(dummy_dev(dum_hcd), "port status 0x%08x has changes\n",
-                               dum_hcd->port_status);
-               retval = 1;
-               if (dum_hcd->rh_state == DUMMY_RH_SUSPENDED)
-                       usb_hcd_resume_root_hub(hcd);
-       }
-done:
-       spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
-       return retval;
-}
-
-/* usb 3.0 root hub device descriptor */
-static struct {
-       struct usb_bos_descriptor bos;
-       struct usb_ss_cap_descriptor ss_cap;
-} __packed usb3_bos_desc = {
-
-       .bos = {
-               .bLength                = USB_DT_BOS_SIZE,
-               .bDescriptorType        = USB_DT_BOS,
-               .wTotalLength           = cpu_to_le16(sizeof(usb3_bos_desc)),
-               .bNumDeviceCaps         = 1,
-       },
-       .ss_cap = {
-               .bLength                = USB_DT_USB_SS_CAP_SIZE,
-               .bDescriptorType        = USB_DT_DEVICE_CAPABILITY,
-               .bDevCapabilityType     = USB_SS_CAP_TYPE,
-               .wSpeedSupported        = cpu_to_le16(USB_5GBPS_OPERATION),
-               .bFunctionalitySupport  = ilog2(USB_5GBPS_OPERATION),
-       },
-};
-
-static inline void
-ss_hub_descriptor(struct usb_hub_descriptor *desc)
-{
-       memset(desc, 0, sizeof *desc);
-       desc->bDescriptorType = 0x2a;
-       desc->bDescLength = 12;
-       desc->wHubCharacteristics = cpu_to_le16(0x0001);
-       desc->bNbrPorts = 1;
-       desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/
-       desc->u.ss.DeviceRemovable = 0xffff;
-}
-
-static inline void hub_descriptor(struct usb_hub_descriptor *desc)
-{
-       memset(desc, 0, sizeof *desc);
-       desc->bDescriptorType = 0x29;
-       desc->bDescLength = 9;
-       desc->wHubCharacteristics = cpu_to_le16(0x0001);
-       desc->bNbrPorts = 1;
-       desc->u.hs.DeviceRemovable[0] = 0xff;
-       desc->u.hs.DeviceRemovable[1] = 0xff;
-}
-
-static int dummy_hub_control(
-       struct usb_hcd  *hcd,
-       u16             typeReq,
-       u16             wValue,
-       u16             wIndex,
-       char            *buf,
-       u16             wLength
-) {
-       struct dummy_hcd *dum_hcd;
-       int             retval = 0;
-       unsigned long   flags;
-
-       if (!HCD_HW_ACCESSIBLE(hcd))
-               return -ETIMEDOUT;
-
-       dum_hcd = hcd_to_dummy_hcd(hcd);
-
-       spin_lock_irqsave(&dum_hcd->dum->lock, flags);
-       switch (typeReq) {
-       case ClearHubFeature:
-               break;
-       case ClearPortFeature:
-               switch (wValue) {
-               case USB_PORT_FEAT_SUSPEND:
-                       if (hcd->speed == HCD_USB3) {
-                               dev_dbg(dummy_dev(dum_hcd),
-                                        "USB_PORT_FEAT_SUSPEND req not "
-                                        "supported for USB 3.0 roothub\n");
-                               goto error;
-                       }
-                       if (dum_hcd->port_status & USB_PORT_STAT_SUSPEND) {
-                               /* 20msec resume signaling */
-                               dum_hcd->resuming = 1;
-                               dum_hcd->re_timeout = jiffies +
-                                               msecs_to_jiffies(20);
-                       }
-                       break;
-               case USB_PORT_FEAT_POWER:
-                       if (hcd->speed == HCD_USB3) {
-                               if (dum_hcd->port_status & USB_PORT_STAT_POWER)
-                                       dev_dbg(dummy_dev(dum_hcd),
-                                               "power-off\n");
-                       } else
-                               if (dum_hcd->port_status &
-                                                       USB_SS_PORT_STAT_POWER)
-                                       dev_dbg(dummy_dev(dum_hcd),
-                                               "power-off\n");
-                       /* FALLS THROUGH */
-               default:
-                       dum_hcd->port_status &= ~(1 << wValue);
-                       set_link_state(dum_hcd);
-               }
-               break;
-       case GetHubDescriptor:
-               if (hcd->speed == HCD_USB3 &&
-                               (wLength < USB_DT_SS_HUB_SIZE ||
-                                wValue != (USB_DT_SS_HUB << 8))) {
-                       dev_dbg(dummy_dev(dum_hcd),
-                               "Wrong hub descriptor type for "
-                               "USB 3.0 roothub.\n");
-                       goto error;
-               }
-               if (hcd->speed == HCD_USB3)
-                       ss_hub_descriptor((struct usb_hub_descriptor *) buf);
-               else
-                       hub_descriptor((struct usb_hub_descriptor *) buf);
-               break;
-
-       case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
-               if (hcd->speed != HCD_USB3)
-                       goto error;
-
-               if ((wValue >> 8) != USB_DT_BOS)
-                       goto error;
-
-               memcpy(buf, &usb3_bos_desc, sizeof(usb3_bos_desc));
-               retval = sizeof(usb3_bos_desc);
-               break;
-
-       case GetHubStatus:
-               *(__le32 *) buf = cpu_to_le32(0);
-               break;
-       case GetPortStatus:
-               if (wIndex != 1)
-                       retval = -EPIPE;
-
-               /* whoever resets or resumes must GetPortStatus to
-                * complete it!!
-                */
-               if (dum_hcd->resuming &&
-                               time_after_eq(jiffies, dum_hcd->re_timeout)) {
-                       dum_hcd->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
-                       dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND;
-               }
-               if ((dum_hcd->port_status & USB_PORT_STAT_RESET) != 0 &&
-                               time_after_eq(jiffies, dum_hcd->re_timeout)) {
-                       dum_hcd->port_status |= (USB_PORT_STAT_C_RESET << 16);
-                       dum_hcd->port_status &= ~USB_PORT_STAT_RESET;
-                       if (dum_hcd->dum->pullup) {
-                               dum_hcd->port_status |= USB_PORT_STAT_ENABLE;
-
-                               if (hcd->speed < HCD_USB3) {
-                                       switch (dum_hcd->dum->gadget.speed) {
-                                       case USB_SPEED_HIGH:
-                                               dum_hcd->port_status |=
-                                                     USB_PORT_STAT_HIGH_SPEED;
-                                               break;
-                                       case USB_SPEED_LOW:
-                                               dum_hcd->dum->gadget.ep0->
-                                                       maxpacket = 8;
-                                               dum_hcd->port_status |=
-                                                       USB_PORT_STAT_LOW_SPEED;
-                                               break;
-                                       default:
-                                               dum_hcd->dum->gadget.speed =
-                                                       USB_SPEED_FULL;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-               set_link_state(dum_hcd);
-               ((__le16 *) buf)[0] = cpu_to_le16(dum_hcd->port_status);
-               ((__le16 *) buf)[1] = cpu_to_le16(dum_hcd->port_status >> 16);
-               break;
-       case SetHubFeature:
-               retval = -EPIPE;
-               break;
-       case SetPortFeature:
-               switch (wValue) {
-               case USB_PORT_FEAT_LINK_STATE:
-                       if (hcd->speed != HCD_USB3) {
-                               dev_dbg(dummy_dev(dum_hcd),
-                                        "USB_PORT_FEAT_LINK_STATE req not "
-                                        "supported for USB 2.0 roothub\n");
-                               goto error;
-                       }
-                       /*
-                        * Since this is dummy we don't have an actual link so
-                        * there is nothing to do for the SET_LINK_STATE cmd
-                        */
-                       break;
-               case USB_PORT_FEAT_U1_TIMEOUT:
-               case USB_PORT_FEAT_U2_TIMEOUT:
-                       /* TODO: add suspend/resume support! */
-                       if (hcd->speed != HCD_USB3) {
-                               dev_dbg(dummy_dev(dum_hcd),
-                                        "USB_PORT_FEAT_U1/2_TIMEOUT req not "
-                                        "supported for USB 2.0 roothub\n");
-                               goto error;
-                       }
-                       break;
-               case USB_PORT_FEAT_SUSPEND:
-                       /* Applicable only for USB2.0 hub */
-                       if (hcd->speed == HCD_USB3) {
-                               dev_dbg(dummy_dev(dum_hcd),
-                                        "USB_PORT_FEAT_SUSPEND req not "
-                                        "supported for USB 3.0 roothub\n");
-                               goto error;
-                       }
-                       if (dum_hcd->active) {
-                               dum_hcd->port_status |= USB_PORT_STAT_SUSPEND;
-
-                               /* HNP would happen here; for now we
-                                * assume b_bus_req is always true.
-                                */
-                               set_link_state(dum_hcd);
-                               if (((1 << USB_DEVICE_B_HNP_ENABLE)
-                                               & dum_hcd->dum->devstatus) != 0)
-                                       dev_dbg(dummy_dev(dum_hcd),
-                                                       "no HNP yet!\n");
-                       }
-                       break;
-               case USB_PORT_FEAT_POWER:
-                       if (hcd->speed == HCD_USB3)
-                               dum_hcd->port_status |= USB_SS_PORT_STAT_POWER;
-                       else
-                               dum_hcd->port_status |= USB_PORT_STAT_POWER;
-                       set_link_state(dum_hcd);
-                       break;
-               case USB_PORT_FEAT_BH_PORT_RESET:
-                       /* Applicable only for USB3.0 hub */
-                       if (hcd->speed != HCD_USB3) {
-                               dev_dbg(dummy_dev(dum_hcd),
-                                        "USB_PORT_FEAT_BH_PORT_RESET req not "
-                                        "supported for USB 2.0 roothub\n");
-                               goto error;
-                       }
-                       /* FALLS THROUGH */
-               case USB_PORT_FEAT_RESET:
-                       /* if it's already enabled, disable */
-                       if (hcd->speed == HCD_USB3) {
-                               dum_hcd->port_status = 0;
-                               dum_hcd->port_status =
-                                       (USB_SS_PORT_STAT_POWER |
-                                        USB_PORT_STAT_CONNECTION |
-                                        USB_PORT_STAT_RESET);
-                       } else
-                               dum_hcd->port_status &= ~(USB_PORT_STAT_ENABLE
-                                       | USB_PORT_STAT_LOW_SPEED
-                                       | USB_PORT_STAT_HIGH_SPEED);
-                       /*
-                        * We want to reset device status. All but the
-                        * Self powered feature
-                        */
-                       dum_hcd->dum->devstatus &=
-                               (1 << USB_DEVICE_SELF_POWERED);
-                       /*
-                        * FIXME USB3.0: what is the correct reset signaling
-                        * interval? Is it still 50msec as for HS?
-                        */
-                       dum_hcd->re_timeout = jiffies + msecs_to_jiffies(50);
-                       /* FALLS THROUGH */
-               default:
-                       if (hcd->speed == HCD_USB3) {
-                               if ((dum_hcd->port_status &
-                                    USB_SS_PORT_STAT_POWER) != 0) {
-                                       dum_hcd->port_status |= (1 << wValue);
-                                       set_link_state(dum_hcd);
-                               }
-                       } else
-                               if ((dum_hcd->port_status &
-                                    USB_PORT_STAT_POWER) != 0) {
-                                       dum_hcd->port_status |= (1 << wValue);
-                                       set_link_state(dum_hcd);
-                               }
-               }
-               break;
-       case GetPortErrorCount:
-               if (hcd->speed != HCD_USB3) {
-                       dev_dbg(dummy_dev(dum_hcd),
-                                "GetPortErrorCount req not "
-                                "supported for USB 2.0 roothub\n");
-                       goto error;
-               }
-               /* We'll always return 0 since this is a dummy hub */
-               *(__le32 *) buf = cpu_to_le32(0);
-               break;
-       case SetHubDepth:
-               if (hcd->speed != HCD_USB3) {
-                       dev_dbg(dummy_dev(dum_hcd),
-                                "SetHubDepth req not supported for "
-                                "USB 2.0 roothub\n");
-                       goto error;
-               }
-               break;
-       default:
-               dev_dbg(dummy_dev(dum_hcd),
-                       "hub control req%04x v%04x i%04x l%d\n",
-                       typeReq, wValue, wIndex, wLength);
-error:
-               /* "protocol stall" on error */
-               retval = -EPIPE;
-       }
-       spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
-
-       if ((dum_hcd->port_status & PORT_C_MASK) != 0)
-               usb_hcd_poll_rh_status(hcd);
-       return retval;
-}
-
-static int dummy_bus_suspend(struct usb_hcd *hcd)
-{
-       struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
-
-       dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
-
-       spin_lock_irq(&dum_hcd->dum->lock);
-       dum_hcd->rh_state = DUMMY_RH_SUSPENDED;
-       set_link_state(dum_hcd);
-       hcd->state = HC_STATE_SUSPENDED;
-       spin_unlock_irq(&dum_hcd->dum->lock);
-       return 0;
-}
-
-static int dummy_bus_resume(struct usb_hcd *hcd)
-{
-       struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
-       int rc = 0;
-
-       dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
-
-       spin_lock_irq(&dum_hcd->dum->lock);
-       if (!HCD_HW_ACCESSIBLE(hcd)) {
-               rc = -ESHUTDOWN;
-       } else {
-               dum_hcd->rh_state = DUMMY_RH_RUNNING;
-               set_link_state(dum_hcd);
-               if (!list_empty(&dum_hcd->urbp_list))
-                       mod_timer(&dum_hcd->timer, jiffies);
-               hcd->state = HC_STATE_RUNNING;
-       }
-       spin_unlock_irq(&dum_hcd->dum->lock);
-       return rc;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline ssize_t show_urb(char *buf, size_t size, struct urb *urb)
-{
-       int ep = usb_pipeendpoint(urb->pipe);
-
-       return snprintf(buf, size,
-               "urb/%p %s ep%d%s%s len %d/%d\n",
-               urb,
-               ({ char *s;
-               switch (urb->dev->speed) {
-               case USB_SPEED_LOW:
-                       s = "ls";
-                       break;
-               case USB_SPEED_FULL:
-                       s = "fs";
-                       break;
-               case USB_SPEED_HIGH:
-                       s = "hs";
-                       break;
-               case USB_SPEED_SUPER:
-                       s = "ss";
-                       break;
-               default:
-                       s = "?";
-                       break;
-                } s; }),
-               ep, ep ? (usb_pipein(urb->pipe) ? "in" : "out") : "",
-               ({ char *s; \
-               switch (usb_pipetype(urb->pipe)) { \
-               case PIPE_CONTROL: \
-                       s = ""; \
-                       break; \
-               case PIPE_BULK: \
-                       s = "-bulk"; \
-                       break; \
-               case PIPE_INTERRUPT: \
-                       s = "-int"; \
-                       break; \
-               default: \
-                       s = "-iso"; \
-                       break; \
-               } s; }),
-               urb->actual_length, urb->transfer_buffer_length);
-}
-
-static ssize_t urbs_show(struct device *dev, struct device_attribute *attr,
-               char *buf)
-{
-       struct usb_hcd          *hcd = dev_get_drvdata(dev);
-       struct dummy_hcd        *dum_hcd = hcd_to_dummy_hcd(hcd);
-       struct urbp             *urbp;
-       size_t                  size = 0;
-       unsigned long           flags;
-
-       spin_lock_irqsave(&dum_hcd->dum->lock, flags);
-       list_for_each_entry(urbp, &dum_hcd->urbp_list, urbp_list) {
-               size_t          temp;
-
-               temp = show_urb(buf, PAGE_SIZE - size, urbp->urb);
-               buf += temp;
-               size += temp;
-       }
-       spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
-
-       return size;
-}
-static DEVICE_ATTR_RO(urbs);
-
-static int dummy_start_ss(struct dummy_hcd *dum_hcd)
-{
-       init_timer(&dum_hcd->timer);
-       dum_hcd->timer.function = dummy_timer;
-       dum_hcd->timer.data = (unsigned long)dum_hcd;
-       dum_hcd->rh_state = DUMMY_RH_RUNNING;
-       dum_hcd->stream_en_ep = 0;
-       INIT_LIST_HEAD(&dum_hcd->urbp_list);
-       dummy_hcd_to_hcd(dum_hcd)->power_budget = POWER_BUDGET;
-       dummy_hcd_to_hcd(dum_hcd)->state = HC_STATE_RUNNING;
-       dummy_hcd_to_hcd(dum_hcd)->uses_new_polling = 1;
-#ifdef CONFIG_USB_OTG
-       dummy_hcd_to_hcd(dum_hcd)->self.otg_port = 1;
-#endif
-       return 0;
-
-       /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
-       return device_create_file(dummy_dev(dum_hcd), &dev_attr_urbs);
-}
-
-static int dummy_start(struct usb_hcd *hcd)
-{
-       struct dummy_hcd        *dum_hcd = hcd_to_dummy_hcd(hcd);
-
-       /*
-        * MASTER side init ... we emulate a root hub that'll only ever
-        * talk to one device (the slave side).  Also appears in sysfs,
-        * just like more familiar pci-based HCDs.
-        */
-       if (!usb_hcd_is_primary_hcd(hcd))
-               return dummy_start_ss(dum_hcd);
-
-       spin_lock_init(&dum_hcd->dum->lock);
-       init_timer(&dum_hcd->timer);
-       dum_hcd->timer.function = dummy_timer;
-       dum_hcd->timer.data = (unsigned long)dum_hcd;
-       dum_hcd->rh_state = DUMMY_RH_RUNNING;
-
-       INIT_LIST_HEAD(&dum_hcd->urbp_list);
-
-       hcd->power_budget = POWER_BUDGET;
-       hcd->state = HC_STATE_RUNNING;
-       hcd->uses_new_polling = 1;
-
-#ifdef CONFIG_USB_OTG
-       hcd->self.otg_port = 1;
-#endif
-
-       /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
-       return device_create_file(dummy_dev(dum_hcd), &dev_attr_urbs);
-}
-
-static void dummy_stop(struct usb_hcd *hcd)
-{
-       struct dummy            *dum;
-
-       dum = hcd_to_dummy_hcd(hcd)->dum;
-       device_remove_file(dummy_dev(hcd_to_dummy_hcd(hcd)), &dev_attr_urbs);
-       usb_gadget_unregister_driver(dum->driver);
-       dev_info(dummy_dev(hcd_to_dummy_hcd(hcd)), "stopped\n");
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int dummy_h_get_frame(struct usb_hcd *hcd)
-{
-       return dummy_g_get_frame(NULL);
-}
-
-static int dummy_setup(struct usb_hcd *hcd)
-{
-       struct dummy *dum;
-
-       dum = *((void **)dev_get_platdata(hcd->self.controller));
-       hcd->self.sg_tablesize = ~0;
-       if (usb_hcd_is_primary_hcd(hcd)) {
-               dum->hs_hcd = hcd_to_dummy_hcd(hcd);
-               dum->hs_hcd->dum = dum;
-               /*
-                * Mark the first roothub as being USB 2.0.
-                * The USB 3.0 roothub will be registered later by
-                * dummy_hcd_probe()
-                */
-               hcd->speed = HCD_USB2;
-               hcd->self.root_hub->speed = USB_SPEED_HIGH;
-       } else {
-               dum->ss_hcd = hcd_to_dummy_hcd(hcd);
-               dum->ss_hcd->dum = dum;
-               hcd->speed = HCD_USB3;
-               hcd->self.root_hub->speed = USB_SPEED_SUPER;
-       }
-       return 0;
-}
-
-/* Change a group of bulk endpoints to support multiple stream IDs */
-static int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
-       struct usb_host_endpoint **eps, unsigned int num_eps,
-       unsigned int num_streams, gfp_t mem_flags)
-{
-       struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
-       unsigned long flags;
-       int max_stream;
-       int ret_streams = num_streams;
-       unsigned int index;
-       unsigned int i;
-
-       if (!num_eps)
-               return -EINVAL;
-
-       spin_lock_irqsave(&dum_hcd->dum->lock, flags);
-       for (i = 0; i < num_eps; i++) {
-               index = dummy_get_ep_idx(&eps[i]->desc);
-               if ((1 << index) & dum_hcd->stream_en_ep) {
-                       ret_streams = -EINVAL;
-                       goto out;
-               }
-               max_stream = usb_ss_max_streams(&eps[i]->ss_ep_comp);
-               if (!max_stream) {
-                       ret_streams = -EINVAL;
-                       goto out;
-               }
-               if (max_stream < ret_streams) {
-                       dev_dbg(dummy_dev(dum_hcd), "Ep 0x%x only supports %u "
-                                       "stream IDs.\n",
-                                       eps[i]->desc.bEndpointAddress,
-                                       max_stream);
-                       ret_streams = max_stream;
-               }
-       }
-
-       for (i = 0; i < num_eps; i++) {
-               index = dummy_get_ep_idx(&eps[i]->desc);
-               dum_hcd->stream_en_ep |= 1 << index;
-               set_max_streams_for_pipe(dum_hcd,
-                               usb_endpoint_num(&eps[i]->desc), ret_streams);
-       }
-out:
-       spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
-       return ret_streams;
-}
-
-/* Reverts a group of bulk endpoints back to not using stream IDs. */
-static int dummy_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
-       struct usb_host_endpoint **eps, unsigned int num_eps,
-       gfp_t mem_flags)
-{
-       struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
-       unsigned long flags;
-       int ret;
-       unsigned int index;
-       unsigned int i;
-
-       spin_lock_irqsave(&dum_hcd->dum->lock, flags);
-       for (i = 0; i < num_eps; i++) {
-               index = dummy_get_ep_idx(&eps[i]->desc);
-               if (!((1 << index) & dum_hcd->stream_en_ep)) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-       }
-
-       for (i = 0; i < num_eps; i++) {
-               index = dummy_get_ep_idx(&eps[i]->desc);
-               dum_hcd->stream_en_ep &= ~(1 << index);
-               set_max_streams_for_pipe(dum_hcd,
-                               usb_endpoint_num(&eps[i]->desc), 0);
-       }
-       ret = 0;
-out:
-       spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
-       return ret;
-}
-
-static struct hc_driver dummy_hcd = {
-       .description =          (char *) driver_name,
-       .product_desc =         "Dummy host controller",
-       .hcd_priv_size =        sizeof(struct dummy_hcd),
-
-       .flags =                HCD_USB3 | HCD_SHARED,
-
-       .reset =                dummy_setup,
-       .start =                dummy_start,
-       .stop =                 dummy_stop,
-
-       .urb_enqueue =          dummy_urb_enqueue,
-       .urb_dequeue =          dummy_urb_dequeue,
-
-       .get_frame_number =     dummy_h_get_frame,
-
-       .hub_status_data =      dummy_hub_status,
-       .hub_control =          dummy_hub_control,
-       .bus_suspend =          dummy_bus_suspend,
-       .bus_resume =           dummy_bus_resume,
-
-       .alloc_streams =        dummy_alloc_streams,
-       .free_streams =         dummy_free_streams,
-};
-
-static int dummy_hcd_probe(struct platform_device *pdev)
-{
-       struct dummy            *dum;
-       struct usb_hcd          *hs_hcd;
-       struct usb_hcd          *ss_hcd;
-       int                     retval;
-
-       dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
-       dum = *((void **)dev_get_platdata(&pdev->dev));
-
-       if (!mod_data.is_super_speed)
-               dummy_hcd.flags = HCD_USB2;
-       hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev));
-       if (!hs_hcd)
-               return -ENOMEM;
-       hs_hcd->has_tt = 1;
-
-       retval = usb_add_hcd(hs_hcd, 0, 0);
-       if (retval)
-               goto put_usb2_hcd;
-
-       if (mod_data.is_super_speed) {
-               ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev,
-                                       dev_name(&pdev->dev), hs_hcd);
-               if (!ss_hcd) {
-                       retval = -ENOMEM;
-                       goto dealloc_usb2_hcd;
-               }
-
-               retval = usb_add_hcd(ss_hcd, 0, 0);
-               if (retval)
-                       goto put_usb3_hcd;
-       }
-       return 0;
-
-put_usb3_hcd:
-       usb_put_hcd(ss_hcd);
-dealloc_usb2_hcd:
-       usb_remove_hcd(hs_hcd);
-put_usb2_hcd:
-       usb_put_hcd(hs_hcd);
-       dum->hs_hcd = dum->ss_hcd = NULL;
-       return retval;
-}
-
-static int dummy_hcd_remove(struct platform_device *pdev)
-{
-       struct dummy            *dum;
-
-       dum = hcd_to_dummy_hcd(platform_get_drvdata(pdev))->dum;
-
-       if (dum->ss_hcd) {
-               usb_remove_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
-               usb_put_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
-       }
-
-       usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
-       usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
-
-       dum->hs_hcd = NULL;
-       dum->ss_hcd = NULL;
-
-       return 0;
-}
-
-static int dummy_hcd_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       struct usb_hcd          *hcd;
-       struct dummy_hcd        *dum_hcd;
-       int                     rc = 0;
-
-       dev_dbg(&pdev->dev, "%s\n", __func__);
-
-       hcd = platform_get_drvdata(pdev);
-       dum_hcd = hcd_to_dummy_hcd(hcd);
-       if (dum_hcd->rh_state == DUMMY_RH_RUNNING) {
-               dev_warn(&pdev->dev, "Root hub isn't suspended!\n");
-               rc = -EBUSY;
-       } else
-               clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       return rc;
-}
-
-static int dummy_hcd_resume(struct platform_device *pdev)
-{
-       struct usb_hcd          *hcd;
-
-       dev_dbg(&pdev->dev, "%s\n", __func__);
-
-       hcd = platform_get_drvdata(pdev);
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       usb_hcd_poll_rh_status(hcd);
-       return 0;
-}
-
-static struct platform_driver dummy_hcd_driver = {
-       .probe          = dummy_hcd_probe,
-       .remove         = dummy_hcd_remove,
-       .suspend        = dummy_hcd_suspend,
-       .resume         = dummy_hcd_resume,
-       .driver         = {
-               .name   = (char *) driver_name,
-               .owner  = THIS_MODULE,
-       },
-};
-
-/*-------------------------------------------------------------------------*/
-#define MAX_NUM_UDC    2
-static struct platform_device *the_udc_pdev[MAX_NUM_UDC];
-static struct platform_device *the_hcd_pdev[MAX_NUM_UDC];
-
-static int __init init(void)
-{
-       int     retval = -ENOMEM;
-       int     i;
-       struct  dummy *dum[MAX_NUM_UDC];
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       if (!mod_data.is_high_speed && mod_data.is_super_speed)
-               return -EINVAL;
-
-       if (mod_data.num < 1 || mod_data.num > MAX_NUM_UDC) {
-               pr_err("Number of emulated UDC must be in range of 1…%d\n",
-                               MAX_NUM_UDC);
-               return -EINVAL;
-       }
-
-       for (i = 0; i < mod_data.num; i++) {
-               the_hcd_pdev[i] = platform_device_alloc(driver_name, i);
-               if (!the_hcd_pdev[i]) {
-                       i--;
-                       while (i >= 0)
-                               platform_device_put(the_hcd_pdev[i--]);
-                       return retval;
-               }
-       }
-       for (i = 0; i < mod_data.num; i++) {
-               the_udc_pdev[i] = platform_device_alloc(gadget_name, i);
-               if (!the_udc_pdev[i]) {
-                       i--;
-                       while (i >= 0)
-                               platform_device_put(the_udc_pdev[i--]);
-                       goto err_alloc_udc;
-               }
-       }
-       for (i = 0; i < mod_data.num; i++) {
-               dum[i] = kzalloc(sizeof(struct dummy), GFP_KERNEL);
-               if (!dum[i]) {
-                       retval = -ENOMEM;
-                       goto err_add_pdata;
-               }
-               retval = platform_device_add_data(the_hcd_pdev[i], &dum[i],
-                               sizeof(void *));
-               if (retval)
-                       goto err_add_pdata;
-               retval = platform_device_add_data(the_udc_pdev[i], &dum[i],
-                               sizeof(void *));
-               if (retval)
-                       goto err_add_pdata;
-       }
-
-       retval = platform_driver_register(&dummy_hcd_driver);
-       if (retval < 0)
-               goto err_add_pdata;
-       retval = platform_driver_register(&dummy_udc_driver);
-       if (retval < 0)
-               goto err_register_udc_driver;
-
-       for (i = 0; i < mod_data.num; i++) {
-               retval = platform_device_add(the_hcd_pdev[i]);
-               if (retval < 0) {
-                       i--;
-                       while (i >= 0)
-                               platform_device_del(the_hcd_pdev[i--]);
-                       goto err_add_hcd;
-               }
-       }
-       for (i = 0; i < mod_data.num; i++) {
-               if (!dum[i]->hs_hcd ||
-                               (!dum[i]->ss_hcd && mod_data.is_super_speed)) {
-                       /*
-                        * The hcd was added successfully but its probe
-                        * function failed for some reason.
-                        */
-                       retval = -EINVAL;
-                       goto err_add_udc;
-               }
-       }
-
-       for (i = 0; i < mod_data.num; i++) {
-               retval = platform_device_add(the_udc_pdev[i]);
-               if (retval < 0) {
-                       i--;
-                       while (i >= 0)
-                               platform_device_del(the_udc_pdev[i]);
-                       goto err_add_udc;
-               }
-       }
-
-       for (i = 0; i < mod_data.num; i++) {
-               if (!platform_get_drvdata(the_udc_pdev[i])) {
-                       /*
-                        * The udc was added successfully but its probe
-                        * function failed for some reason.
-                        */
-                       retval = -EINVAL;
-                       goto err_probe_udc;
-               }
-       }
-       return retval;
-
-err_probe_udc:
-       for (i = 0; i < mod_data.num; i++)
-               platform_device_del(the_udc_pdev[i]);
-err_add_udc:
-       for (i = 0; i < mod_data.num; i++)
-               platform_device_del(the_hcd_pdev[i]);
-err_add_hcd:
-       platform_driver_unregister(&dummy_udc_driver);
-err_register_udc_driver:
-       platform_driver_unregister(&dummy_hcd_driver);
-err_add_pdata:
-       for (i = 0; i < mod_data.num; i++)
-               kfree(dum[i]);
-       for (i = 0; i < mod_data.num; i++)
-               platform_device_put(the_udc_pdev[i]);
-err_alloc_udc:
-       for (i = 0; i < mod_data.num; i++)
-               platform_device_put(the_hcd_pdev[i]);
-       return retval;
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-       int i;
-
-       for (i = 0; i < mod_data.num; i++) {
-               struct dummy *dum;
-
-               dum = *((void **)dev_get_platdata(&the_udc_pdev[i]->dev));
-
-               platform_device_unregister(the_udc_pdev[i]);
-               platform_device_unregister(the_hcd_pdev[i]);
-               kfree(dum);
-       }
-       platform_driver_unregister(&dummy_udc_driver);
-       platform_driver_unregister(&dummy_hcd_driver);
-}
-module_exit(cleanup);
diff --git a/drivers/usb/gadget/fotg210-udc.c b/drivers/usb/gadget/fotg210-udc.c
deleted file mode 100644 (file)
index e143d69..0000000
+++ /dev/null
@@ -1,1216 +0,0 @@
-/*
- * FOTG210 UDC Driver supports Bulk transfer so far
- *
- * Copyright (C) 2013 Faraday Technology Corporation
- *
- * Author : Yuan-Hsin Chen <yhchen@faraday-tech.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include "fotg210.h"
-
-#define        DRIVER_DESC     "FOTG210 USB Device Controller Driver"
-#define        DRIVER_VERSION  "30-April-2013"
-
-static const char udc_name[] = "fotg210_udc";
-static const char * const fotg210_ep_name[] = {
-       "ep0", "ep1", "ep2", "ep3", "ep4"};
-
-static void fotg210_disable_fifo_int(struct fotg210_ep *ep)
-{
-       u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR1);
-
-       if (ep->dir_in)
-               value |= DMISGR1_MF_IN_INT(ep->epnum - 1);
-       else
-               value |= DMISGR1_MF_OUTSPK_INT(ep->epnum - 1);
-       iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR1);
-}
-
-static void fotg210_enable_fifo_int(struct fotg210_ep *ep)
-{
-       u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR1);
-
-       if (ep->dir_in)
-               value &= ~DMISGR1_MF_IN_INT(ep->epnum - 1);
-       else
-               value &= ~DMISGR1_MF_OUTSPK_INT(ep->epnum - 1);
-       iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR1);
-}
-
-static void fotg210_set_cxdone(struct fotg210_udc *fotg210)
-{
-       u32 value = ioread32(fotg210->reg + FOTG210_DCFESR);
-
-       value |= DCFESR_CX_DONE;
-       iowrite32(value, fotg210->reg + FOTG210_DCFESR);
-}
-
-static void fotg210_done(struct fotg210_ep *ep, struct fotg210_request *req,
-                       int status)
-{
-       list_del_init(&req->queue);
-
-       /* don't modify queue heads during completion callback */
-       if (ep->fotg210->gadget.speed == USB_SPEED_UNKNOWN)
-               req->req.status = -ESHUTDOWN;
-       else
-               req->req.status = status;
-
-       spin_unlock(&ep->fotg210->lock);
-       req->req.complete(&ep->ep, &req->req);
-       spin_lock(&ep->fotg210->lock);
-
-       if (ep->epnum) {
-               if (list_empty(&ep->queue))
-                       fotg210_disable_fifo_int(ep);
-       } else {
-               fotg210_set_cxdone(ep->fotg210);
-       }
-}
-
-static void fotg210_fifo_ep_mapping(struct fotg210_ep *ep, u32 epnum,
-                               u32 dir_in)
-{
-       struct fotg210_udc *fotg210 = ep->fotg210;
-       u32 val;
-
-       /* Driver should map an ep to a fifo and then map the fifo
-        * to the ep. What a brain-damaged design!
-        */
-
-       /* map a fifo to an ep */
-       val = ioread32(fotg210->reg + FOTG210_EPMAP);
-       val &= ~EPMAP_FIFONOMSK(epnum, dir_in);
-       val |= EPMAP_FIFONO(epnum, dir_in);
-       iowrite32(val, fotg210->reg + FOTG210_EPMAP);
-
-       /* map the ep to the fifo */
-       val = ioread32(fotg210->reg + FOTG210_FIFOMAP);
-       val &= ~FIFOMAP_EPNOMSK(epnum);
-       val |= FIFOMAP_EPNO(epnum);
-       iowrite32(val, fotg210->reg + FOTG210_FIFOMAP);
-
-       /* enable fifo */
-       val = ioread32(fotg210->reg + FOTG210_FIFOCF);
-       val |= FIFOCF_FIFO_EN(epnum - 1);
-       iowrite32(val, fotg210->reg + FOTG210_FIFOCF);
-}
-
-static void fotg210_set_fifo_dir(struct fotg210_ep *ep, u32 epnum, u32 dir_in)
-{
-       struct fotg210_udc *fotg210 = ep->fotg210;
-       u32 val;
-
-       val = ioread32(fotg210->reg + FOTG210_FIFOMAP);
-       val |= (dir_in ? FIFOMAP_DIRIN(epnum - 1) : FIFOMAP_DIROUT(epnum - 1));
-       iowrite32(val, fotg210->reg + FOTG210_FIFOMAP);
-}
-
-static void fotg210_set_tfrtype(struct fotg210_ep *ep, u32 epnum, u32 type)
-{
-       struct fotg210_udc *fotg210 = ep->fotg210;
-       u32 val;
-
-       val = ioread32(fotg210->reg + FOTG210_FIFOCF);
-       val |= FIFOCF_TYPE(type, epnum - 1);
-       iowrite32(val, fotg210->reg + FOTG210_FIFOCF);
-}
-
-static void fotg210_set_mps(struct fotg210_ep *ep, u32 epnum, u32 mps,
-                               u32 dir_in)
-{
-       struct fotg210_udc *fotg210 = ep->fotg210;
-       u32 val;
-       u32 offset = dir_in ? FOTG210_INEPMPSR(epnum) :
-                               FOTG210_OUTEPMPSR(epnum);
-
-       val = ioread32(fotg210->reg + offset);
-       val |= INOUTEPMPSR_MPS(mps);
-       iowrite32(val, fotg210->reg + offset);
-}
-
-static int fotg210_config_ep(struct fotg210_ep *ep,
-                    const struct usb_endpoint_descriptor *desc)
-{
-       struct fotg210_udc *fotg210 = ep->fotg210;
-
-       fotg210_set_fifo_dir(ep, ep->epnum, ep->dir_in);
-       fotg210_set_tfrtype(ep, ep->epnum, ep->type);
-       fotg210_set_mps(ep, ep->epnum, ep->ep.maxpacket, ep->dir_in);
-       fotg210_fifo_ep_mapping(ep, ep->epnum, ep->dir_in);
-
-       fotg210->ep[ep->epnum] = ep;
-
-       return 0;
-}
-
-static int fotg210_ep_enable(struct usb_ep *_ep,
-                         const struct usb_endpoint_descriptor *desc)
-{
-       struct fotg210_ep *ep;
-
-       ep = container_of(_ep, struct fotg210_ep, ep);
-
-       ep->desc = desc;
-       ep->epnum = usb_endpoint_num(desc);
-       ep->type = usb_endpoint_type(desc);
-       ep->dir_in = usb_endpoint_dir_in(desc);
-       ep->ep.maxpacket = usb_endpoint_maxp(desc);
-
-       return fotg210_config_ep(ep, desc);
-}
-
-static void fotg210_reset_tseq(struct fotg210_udc *fotg210, u8 epnum)
-{
-       struct fotg210_ep *ep = fotg210->ep[epnum];
-       u32 value;
-       void __iomem *reg;
-
-       reg = (ep->dir_in) ?
-               fotg210->reg + FOTG210_INEPMPSR(epnum) :
-               fotg210->reg + FOTG210_OUTEPMPSR(epnum);
-
-       /* Note: Driver needs to set and clear INOUTEPMPSR_RESET_TSEQ
-        *       bit. Controller wouldn't clear this bit. WTF!!!
-        */
-
-       value = ioread32(reg);
-       value |= INOUTEPMPSR_RESET_TSEQ;
-       iowrite32(value, reg);
-
-       value = ioread32(reg);
-       value &= ~INOUTEPMPSR_RESET_TSEQ;
-       iowrite32(value, reg);
-}
-
-static int fotg210_ep_release(struct fotg210_ep *ep)
-{
-       if (!ep->epnum)
-               return 0;
-       ep->epnum = 0;
-       ep->stall = 0;
-       ep->wedged = 0;
-
-       fotg210_reset_tseq(ep->fotg210, ep->epnum);
-
-       return 0;
-}
-
-static int fotg210_ep_disable(struct usb_ep *_ep)
-{
-       struct fotg210_ep *ep;
-       struct fotg210_request *req;
-       unsigned long flags;
-
-       BUG_ON(!_ep);
-
-       ep = container_of(_ep, struct fotg210_ep, ep);
-
-       while (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next,
-                       struct fotg210_request, queue);
-               spin_lock_irqsave(&ep->fotg210->lock, flags);
-               fotg210_done(ep, req, -ECONNRESET);
-               spin_unlock_irqrestore(&ep->fotg210->lock, flags);
-       }
-
-       return fotg210_ep_release(ep);
-}
-
-static struct usb_request *fotg210_ep_alloc_request(struct usb_ep *_ep,
-                                               gfp_t gfp_flags)
-{
-       struct fotg210_request *req;
-
-       req = kzalloc(sizeof(struct fotg210_request), gfp_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD(&req->queue);
-
-       return &req->req;
-}
-
-static void fotg210_ep_free_request(struct usb_ep *_ep,
-                                       struct usb_request *_req)
-{
-       struct fotg210_request *req;
-
-       req = container_of(_req, struct fotg210_request, req);
-       kfree(req);
-}
-
-static void fotg210_enable_dma(struct fotg210_ep *ep,
-                             dma_addr_t d, u32 len)
-{
-       u32 value;
-       struct fotg210_udc *fotg210 = ep->fotg210;
-
-       /* set transfer length and direction */
-       value = ioread32(fotg210->reg + FOTG210_DMACPSR1);
-       value &= ~(DMACPSR1_DMA_LEN(0xFFFF) | DMACPSR1_DMA_TYPE(1));
-       value |= DMACPSR1_DMA_LEN(len) | DMACPSR1_DMA_TYPE(ep->dir_in);
-       iowrite32(value, fotg210->reg + FOTG210_DMACPSR1);
-
-       /* set device DMA target FIFO number */
-       value = ioread32(fotg210->reg + FOTG210_DMATFNR);
-       if (ep->epnum)
-               value |= DMATFNR_ACC_FN(ep->epnum - 1);
-       else
-               value |= DMATFNR_ACC_CXF;
-       iowrite32(value, fotg210->reg + FOTG210_DMATFNR);
-
-       /* set DMA memory address */
-       iowrite32(d, fotg210->reg + FOTG210_DMACPSR2);
-
-       /* enable MDMA_EROR and MDMA_CMPLT interrupt */
-       value = ioread32(fotg210->reg + FOTG210_DMISGR2);
-       value &= ~(DMISGR2_MDMA_CMPLT | DMISGR2_MDMA_ERROR);
-       iowrite32(value, fotg210->reg + FOTG210_DMISGR2);
-
-       /* start DMA */
-       value = ioread32(fotg210->reg + FOTG210_DMACPSR1);
-       value |= DMACPSR1_DMA_START;
-       iowrite32(value, fotg210->reg + FOTG210_DMACPSR1);
-}
-
-static void fotg210_disable_dma(struct fotg210_ep *ep)
-{
-       iowrite32(DMATFNR_DISDMA, ep->fotg210->reg + FOTG210_DMATFNR);
-}
-
-static void fotg210_wait_dma_done(struct fotg210_ep *ep)
-{
-       u32 value;
-
-       do {
-               value = ioread32(ep->fotg210->reg + FOTG210_DISGR2);
-               if ((value & DISGR2_USBRST_INT) ||
-                   (value & DISGR2_DMA_ERROR))
-                       goto dma_reset;
-       } while (!(value & DISGR2_DMA_CMPLT));
-
-       value &= ~DISGR2_DMA_CMPLT;
-       iowrite32(value, ep->fotg210->reg + FOTG210_DISGR2);
-       return;
-
-dma_reset:
-       value = ioread32(ep->fotg210->reg + FOTG210_DMACPSR1);
-       value |= DMACPSR1_DMA_ABORT;
-       iowrite32(value, ep->fotg210->reg + FOTG210_DMACPSR1);
-
-       /* reset fifo */
-       if (ep->epnum) {
-               value = ioread32(ep->fotg210->reg +
-                               FOTG210_FIBCR(ep->epnum - 1));
-               value |= FIBCR_FFRST;
-               iowrite32(value, ep->fotg210->reg +
-                               FOTG210_FIBCR(ep->epnum - 1));
-       } else {
-               value = ioread32(ep->fotg210->reg + FOTG210_DCFESR);
-               value |= DCFESR_CX_CLR;
-               iowrite32(value, ep->fotg210->reg + FOTG210_DCFESR);
-       }
-}
-
-static void fotg210_start_dma(struct fotg210_ep *ep,
-                       struct fotg210_request *req)
-{
-       dma_addr_t d;
-       u8 *buffer;
-       u32 length;
-
-       if (ep->epnum) {
-               if (ep->dir_in) {
-                       buffer = req->req.buf;
-                       length = req->req.length;
-               } else {
-                       buffer = req->req.buf + req->req.actual;
-                       length = ioread32(ep->fotg210->reg +
-                                       FOTG210_FIBCR(ep->epnum - 1));
-                       length &= FIBCR_BCFX;
-               }
-       } else {
-               buffer = req->req.buf + req->req.actual;
-               if (req->req.length - req->req.actual > ep->ep.maxpacket)
-                       length = ep->ep.maxpacket;
-               else
-                       length = req->req.length;
-       }
-
-       d = dma_map_single(NULL, buffer, length,
-                       ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-
-       if (dma_mapping_error(NULL, d)) {
-               pr_err("dma_mapping_error\n");
-               return;
-       }
-
-       dma_sync_single_for_device(NULL, d, length,
-                                  ep->dir_in ? DMA_TO_DEVICE :
-                                       DMA_FROM_DEVICE);
-
-       fotg210_enable_dma(ep, d, length);
-
-       /* check if dma is done */
-       fotg210_wait_dma_done(ep);
-
-       fotg210_disable_dma(ep);
-
-       /* update actual transfer length */
-       req->req.actual += length;
-
-       dma_unmap_single(NULL, d, length, DMA_TO_DEVICE);
-}
-
-static void fotg210_ep0_queue(struct fotg210_ep *ep,
-                               struct fotg210_request *req)
-{
-       if (!req->req.length) {
-               fotg210_done(ep, req, 0);
-               return;
-       }
-       if (ep->dir_in) { /* if IN */
-               if (req->req.length) {
-                       fotg210_start_dma(ep, req);
-               } else {
-                       pr_err("%s : req->req.length = 0x%x\n",
-                              __func__, req->req.length);
-               }
-               if ((req->req.length == req->req.actual) ||
-                   (req->req.actual < ep->ep.maxpacket))
-                       fotg210_done(ep, req, 0);
-       } else { /* OUT */
-               if (!req->req.length) {
-                       fotg210_done(ep, req, 0);
-               } else {
-                       u32 value = ioread32(ep->fotg210->reg +
-                                               FOTG210_DMISGR0);
-
-                       value &= ~DMISGR0_MCX_OUT_INT;
-                       iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0);
-               }
-       }
-}
-
-static int fotg210_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
-                               gfp_t gfp_flags)
-{
-       struct fotg210_ep *ep;
-       struct fotg210_request *req;
-       unsigned long flags;
-       int request = 0;
-
-       ep = container_of(_ep, struct fotg210_ep, ep);
-       req = container_of(_req, struct fotg210_request, req);
-
-       if (ep->fotg210->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       spin_lock_irqsave(&ep->fotg210->lock, flags);
-
-       if (list_empty(&ep->queue))
-               request = 1;
-
-       list_add_tail(&req->queue, &ep->queue);
-
-       req->req.actual = 0;
-       req->req.status = -EINPROGRESS;
-
-       if (!ep->epnum) /* ep0 */
-               fotg210_ep0_queue(ep, req);
-       else if (request && !ep->stall)
-               fotg210_enable_fifo_int(ep);
-
-       spin_unlock_irqrestore(&ep->fotg210->lock, flags);
-
-       return 0;
-}
-
-static int fotg210_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct fotg210_ep *ep;
-       struct fotg210_request *req;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct fotg210_ep, ep);
-       req = container_of(_req, struct fotg210_request, req);
-
-       spin_lock_irqsave(&ep->fotg210->lock, flags);
-       if (!list_empty(&ep->queue))
-               fotg210_done(ep, req, -ECONNRESET);
-       spin_unlock_irqrestore(&ep->fotg210->lock, flags);
-
-       return 0;
-}
-
-static void fotg210_set_epnstall(struct fotg210_ep *ep)
-{
-       struct fotg210_udc *fotg210 = ep->fotg210;
-       u32 value;
-       void __iomem *reg;
-
-       /* check if IN FIFO is empty before stall */
-       if (ep->dir_in) {
-               do {
-                       value = ioread32(fotg210->reg + FOTG210_DCFESR);
-               } while (!(value & DCFESR_FIFO_EMPTY(ep->epnum - 1)));
-       }
-
-       reg = (ep->dir_in) ?
-               fotg210->reg + FOTG210_INEPMPSR(ep->epnum) :
-               fotg210->reg + FOTG210_OUTEPMPSR(ep->epnum);
-       value = ioread32(reg);
-       value |= INOUTEPMPSR_STL_EP;
-       iowrite32(value, reg);
-}
-
-static void fotg210_clear_epnstall(struct fotg210_ep *ep)
-{
-       struct fotg210_udc *fotg210 = ep->fotg210;
-       u32 value;
-       void __iomem *reg;
-
-       reg = (ep->dir_in) ?
-               fotg210->reg + FOTG210_INEPMPSR(ep->epnum) :
-               fotg210->reg + FOTG210_OUTEPMPSR(ep->epnum);
-       value = ioread32(reg);
-       value &= ~INOUTEPMPSR_STL_EP;
-       iowrite32(value, reg);
-}
-
-static int fotg210_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedge)
-{
-       struct fotg210_ep *ep;
-       struct fotg210_udc *fotg210;
-       unsigned long flags;
-       int ret = 0;
-
-       ep = container_of(_ep, struct fotg210_ep, ep);
-
-       fotg210 = ep->fotg210;
-
-       spin_lock_irqsave(&ep->fotg210->lock, flags);
-
-       if (value) {
-               fotg210_set_epnstall(ep);
-               ep->stall = 1;
-               if (wedge)
-                       ep->wedged = 1;
-       } else {
-               fotg210_reset_tseq(fotg210, ep->epnum);
-               fotg210_clear_epnstall(ep);
-               ep->stall = 0;
-               ep->wedged = 0;
-               if (!list_empty(&ep->queue))
-                       fotg210_enable_fifo_int(ep);
-       }
-
-       spin_unlock_irqrestore(&ep->fotg210->lock, flags);
-       return ret;
-}
-
-static int fotg210_ep_set_halt(struct usb_ep *_ep, int value)
-{
-       return fotg210_set_halt_and_wedge(_ep, value, 0);
-}
-
-static int fotg210_ep_set_wedge(struct usb_ep *_ep)
-{
-       return fotg210_set_halt_and_wedge(_ep, 1, 1);
-}
-
-static void fotg210_ep_fifo_flush(struct usb_ep *_ep)
-{
-}
-
-static struct usb_ep_ops fotg210_ep_ops = {
-       .enable         = fotg210_ep_enable,
-       .disable        = fotg210_ep_disable,
-
-       .alloc_request  = fotg210_ep_alloc_request,
-       .free_request   = fotg210_ep_free_request,
-
-       .queue          = fotg210_ep_queue,
-       .dequeue        = fotg210_ep_dequeue,
-
-       .set_halt       = fotg210_ep_set_halt,
-       .fifo_flush     = fotg210_ep_fifo_flush,
-       .set_wedge      = fotg210_ep_set_wedge,
-};
-
-static void fotg210_clear_tx0byte(struct fotg210_udc *fotg210)
-{
-       u32 value = ioread32(fotg210->reg + FOTG210_TX0BYTE);
-
-       value &= ~(TX0BYTE_EP1 | TX0BYTE_EP2 | TX0BYTE_EP3
-                  | TX0BYTE_EP4);
-       iowrite32(value, fotg210->reg + FOTG210_TX0BYTE);
-}
-
-static void fotg210_clear_rx0byte(struct fotg210_udc *fotg210)
-{
-       u32 value = ioread32(fotg210->reg + FOTG210_RX0BYTE);
-
-       value &= ~(RX0BYTE_EP1 | RX0BYTE_EP2 | RX0BYTE_EP3
-                  | RX0BYTE_EP4);
-       iowrite32(value, fotg210->reg + FOTG210_RX0BYTE);
-}
-
-/* read 8-byte setup packet only */
-static void fotg210_rdsetupp(struct fotg210_udc *fotg210,
-                  u8 *buffer)
-{
-       int i = 0;
-       u8 *tmp = buffer;
-       u32 data;
-       u32 length = 8;
-
-       iowrite32(DMATFNR_ACC_CXF, fotg210->reg + FOTG210_DMATFNR);
-
-       for (i = (length >> 2); i > 0; i--) {
-               data = ioread32(fotg210->reg + FOTG210_CXPORT);
-               *tmp = data & 0xFF;
-               *(tmp + 1) = (data >> 8) & 0xFF;
-               *(tmp + 2) = (data >> 16) & 0xFF;
-               *(tmp + 3) = (data >> 24) & 0xFF;
-               tmp = tmp + 4;
-       }
-
-       switch (length % 4) {
-       case 1:
-               data = ioread32(fotg210->reg + FOTG210_CXPORT);
-               *tmp = data & 0xFF;
-               break;
-       case 2:
-               data = ioread32(fotg210->reg + FOTG210_CXPORT);
-               *tmp = data & 0xFF;
-               *(tmp + 1) = (data >> 8) & 0xFF;
-               break;
-       case 3:
-               data = ioread32(fotg210->reg + FOTG210_CXPORT);
-               *tmp = data & 0xFF;
-               *(tmp + 1) = (data >> 8) & 0xFF;
-               *(tmp + 2) = (data >> 16) & 0xFF;
-               break;
-       default:
-               break;
-       }
-
-       iowrite32(DMATFNR_DISDMA, fotg210->reg + FOTG210_DMATFNR);
-}
-
-static void fotg210_set_configuration(struct fotg210_udc *fotg210)
-{
-       u32 value = ioread32(fotg210->reg + FOTG210_DAR);
-
-       value |= DAR_AFT_CONF;
-       iowrite32(value, fotg210->reg + FOTG210_DAR);
-}
-
-static void fotg210_set_dev_addr(struct fotg210_udc *fotg210, u32 addr)
-{
-       u32 value = ioread32(fotg210->reg + FOTG210_DAR);
-
-       value |= (addr & 0x7F);
-       iowrite32(value, fotg210->reg + FOTG210_DAR);
-}
-
-static void fotg210_set_cxstall(struct fotg210_udc *fotg210)
-{
-       u32 value = ioread32(fotg210->reg + FOTG210_DCFESR);
-
-       value |= DCFESR_CX_STL;
-       iowrite32(value, fotg210->reg + FOTG210_DCFESR);
-}
-
-static void fotg210_request_error(struct fotg210_udc *fotg210)
-{
-       fotg210_set_cxstall(fotg210);
-       pr_err("request error!!\n");
-}
-
-static void fotg210_set_address(struct fotg210_udc *fotg210,
-                               struct usb_ctrlrequest *ctrl)
-{
-       if (ctrl->wValue >= 0x0100) {
-               fotg210_request_error(fotg210);
-       } else {
-               fotg210_set_dev_addr(fotg210, ctrl->wValue);
-               fotg210_set_cxdone(fotg210);
-       }
-}
-
-static void fotg210_set_feature(struct fotg210_udc *fotg210,
-                               struct usb_ctrlrequest *ctrl)
-{
-       switch (ctrl->bRequestType & USB_RECIP_MASK) {
-       case USB_RECIP_DEVICE:
-               fotg210_set_cxdone(fotg210);
-               break;
-       case USB_RECIP_INTERFACE:
-               fotg210_set_cxdone(fotg210);
-               break;
-       case USB_RECIP_ENDPOINT: {
-               u8 epnum;
-               epnum = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
-               if (epnum)
-                       fotg210_set_epnstall(fotg210->ep[epnum]);
-               else
-                       fotg210_set_cxstall(fotg210);
-               fotg210_set_cxdone(fotg210);
-               }
-               break;
-       default:
-               fotg210_request_error(fotg210);
-               break;
-       }
-}
-
-static void fotg210_clear_feature(struct fotg210_udc *fotg210,
-                               struct usb_ctrlrequest *ctrl)
-{
-       struct fotg210_ep *ep =
-               fotg210->ep[ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK];
-
-       switch (ctrl->bRequestType & USB_RECIP_MASK) {
-       case USB_RECIP_DEVICE:
-               fotg210_set_cxdone(fotg210);
-               break;
-       case USB_RECIP_INTERFACE:
-               fotg210_set_cxdone(fotg210);
-               break;
-       case USB_RECIP_ENDPOINT:
-               if (ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK) {
-                       if (ep->wedged) {
-                               fotg210_set_cxdone(fotg210);
-                               break;
-                       }
-                       if (ep->stall)
-                               fotg210_set_halt_and_wedge(&ep->ep, 0, 0);
-               }
-               fotg210_set_cxdone(fotg210);
-               break;
-       default:
-               fotg210_request_error(fotg210);
-               break;
-       }
-}
-
-static int fotg210_is_epnstall(struct fotg210_ep *ep)
-{
-       struct fotg210_udc *fotg210 = ep->fotg210;
-       u32 value;
-       void __iomem *reg;
-
-       reg = (ep->dir_in) ?
-               fotg210->reg + FOTG210_INEPMPSR(ep->epnum) :
-               fotg210->reg + FOTG210_OUTEPMPSR(ep->epnum);
-       value = ioread32(reg);
-       return value & INOUTEPMPSR_STL_EP ? 1 : 0;
-}
-
-static void fotg210_get_status(struct fotg210_udc *fotg210,
-                               struct usb_ctrlrequest *ctrl)
-{
-       u8 epnum;
-
-       switch (ctrl->bRequestType & USB_RECIP_MASK) {
-       case USB_RECIP_DEVICE:
-               fotg210->ep0_data = 1 << USB_DEVICE_SELF_POWERED;
-               break;
-       case USB_RECIP_INTERFACE:
-               fotg210->ep0_data = 0;
-               break;
-       case USB_RECIP_ENDPOINT:
-               epnum = ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK;
-               if (epnum)
-                       fotg210->ep0_data =
-                               fotg210_is_epnstall(fotg210->ep[epnum])
-                               << USB_ENDPOINT_HALT;
-               else
-                       fotg210_request_error(fotg210);
-               break;
-
-       default:
-               fotg210_request_error(fotg210);
-               return;         /* exit */
-       }
-
-       fotg210->ep0_req->buf = &fotg210->ep0_data;
-       fotg210->ep0_req->length = 2;
-
-       spin_unlock(&fotg210->lock);
-       fotg210_ep_queue(fotg210->gadget.ep0, fotg210->ep0_req, GFP_KERNEL);
-       spin_lock(&fotg210->lock);
-}
-
-static int fotg210_setup_packet(struct fotg210_udc *fotg210,
-                               struct usb_ctrlrequest *ctrl)
-{
-       u8 *p = (u8 *)ctrl;
-       u8 ret = 0;
-
-       fotg210_rdsetupp(fotg210, p);
-
-       fotg210->ep[0]->dir_in = ctrl->bRequestType & USB_DIR_IN;
-
-       if (fotg210->gadget.speed == USB_SPEED_UNKNOWN) {
-               u32 value = ioread32(fotg210->reg + FOTG210_DMCR);
-               fotg210->gadget.speed = value & DMCR_HS_EN ?
-                               USB_SPEED_HIGH : USB_SPEED_FULL;
-       }
-
-       /* check request */
-       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
-               switch (ctrl->bRequest) {
-               case USB_REQ_GET_STATUS:
-                       fotg210_get_status(fotg210, ctrl);
-                       break;
-               case USB_REQ_CLEAR_FEATURE:
-                       fotg210_clear_feature(fotg210, ctrl);
-                       break;
-               case USB_REQ_SET_FEATURE:
-                       fotg210_set_feature(fotg210, ctrl);
-                       break;
-               case USB_REQ_SET_ADDRESS:
-                       fotg210_set_address(fotg210, ctrl);
-                       break;
-               case USB_REQ_SET_CONFIGURATION:
-                       fotg210_set_configuration(fotg210);
-                       ret = 1;
-                       break;
-               default:
-                       ret = 1;
-                       break;
-               }
-       } else {
-               ret = 1;
-       }
-
-       return ret;
-}
-
-static void fotg210_ep0out(struct fotg210_udc *fotg210)
-{
-       struct fotg210_ep *ep = fotg210->ep[0];
-
-       if (!list_empty(&ep->queue) && !ep->dir_in) {
-               struct fotg210_request *req;
-
-               req = list_first_entry(&ep->queue,
-                       struct fotg210_request, queue);
-
-               if (req->req.length)
-                       fotg210_start_dma(ep, req);
-
-               if ((req->req.length - req->req.actual) < ep->ep.maxpacket)
-                       fotg210_done(ep, req, 0);
-       } else {
-               pr_err("%s : empty queue\n", __func__);
-       }
-}
-
-static void fotg210_ep0in(struct fotg210_udc *fotg210)
-{
-       struct fotg210_ep *ep = fotg210->ep[0];
-
-       if ((!list_empty(&ep->queue)) && (ep->dir_in)) {
-               struct fotg210_request *req;
-
-               req = list_entry(ep->queue.next,
-                               struct fotg210_request, queue);
-
-               if (req->req.length)
-                       fotg210_start_dma(ep, req);
-
-               if ((req->req.length - req->req.actual) < ep->ep.maxpacket)
-                       fotg210_done(ep, req, 0);
-       } else {
-               fotg210_set_cxdone(fotg210);
-       }
-}
-
-static void fotg210_clear_comabt_int(struct fotg210_udc *fotg210)
-{
-       u32 value = ioread32(fotg210->reg + FOTG210_DISGR0);
-
-       value &= ~DISGR0_CX_COMABT_INT;
-       iowrite32(value, fotg210->reg + FOTG210_DISGR0);
-}
-
-static void fotg210_in_fifo_handler(struct fotg210_ep *ep)
-{
-       struct fotg210_request *req = list_entry(ep->queue.next,
-                                       struct fotg210_request, queue);
-
-       if (req->req.length)
-               fotg210_start_dma(ep, req);
-       fotg210_done(ep, req, 0);
-}
-
-static void fotg210_out_fifo_handler(struct fotg210_ep *ep)
-{
-       struct fotg210_request *req = list_entry(ep->queue.next,
-                                                struct fotg210_request, queue);
-
-       fotg210_start_dma(ep, req);
-
-       /* finish out transfer */
-       if (req->req.length == req->req.actual ||
-           req->req.actual < ep->ep.maxpacket)
-               fotg210_done(ep, req, 0);
-}
-
-static irqreturn_t fotg210_irq(int irq, void *_fotg210)
-{
-       struct fotg210_udc *fotg210 = _fotg210;
-       u32 int_grp = ioread32(fotg210->reg + FOTG210_DIGR);
-       u32 int_msk = ioread32(fotg210->reg + FOTG210_DMIGR);
-
-       int_grp &= ~int_msk;
-
-       spin_lock(&fotg210->lock);
-
-       if (int_grp & DIGR_INT_G2) {
-               void __iomem *reg = fotg210->reg + FOTG210_DISGR2;
-               u32 int_grp2 = ioread32(reg);
-               u32 int_msk2 = ioread32(fotg210->reg + FOTG210_DMISGR2);
-               u32 value;
-
-               int_grp2 &= ~int_msk2;
-
-               if (int_grp2 & DISGR2_USBRST_INT) {
-                       value = ioread32(reg);
-                       value &= ~DISGR2_USBRST_INT;
-                       iowrite32(value, reg);
-                       pr_info("fotg210 udc reset\n");
-               }
-               if (int_grp2 & DISGR2_SUSP_INT) {
-                       value = ioread32(reg);
-                       value &= ~DISGR2_SUSP_INT;
-                       iowrite32(value, reg);
-                       pr_info("fotg210 udc suspend\n");
-               }
-               if (int_grp2 & DISGR2_RESM_INT) {
-                       value = ioread32(reg);
-                       value &= ~DISGR2_RESM_INT;
-                       iowrite32(value, reg);
-                       pr_info("fotg210 udc resume\n");
-               }
-               if (int_grp2 & DISGR2_ISO_SEQ_ERR_INT) {
-                       value = ioread32(reg);
-                       value &= ~DISGR2_ISO_SEQ_ERR_INT;
-                       iowrite32(value, reg);
-                       pr_info("fotg210 iso sequence error\n");
-               }
-               if (int_grp2 & DISGR2_ISO_SEQ_ABORT_INT) {
-                       value = ioread32(reg);
-                       value &= ~DISGR2_ISO_SEQ_ABORT_INT;
-                       iowrite32(value, reg);
-                       pr_info("fotg210 iso sequence abort\n");
-               }
-               if (int_grp2 & DISGR2_TX0BYTE_INT) {
-                       fotg210_clear_tx0byte(fotg210);
-                       value = ioread32(reg);
-                       value &= ~DISGR2_TX0BYTE_INT;
-                       iowrite32(value, reg);
-                       pr_info("fotg210 transferred 0 byte\n");
-               }
-               if (int_grp2 & DISGR2_RX0BYTE_INT) {
-                       fotg210_clear_rx0byte(fotg210);
-                       value = ioread32(reg);
-                       value &= ~DISGR2_RX0BYTE_INT;
-                       iowrite32(value, reg);
-                       pr_info("fotg210 received 0 byte\n");
-               }
-               if (int_grp2 & DISGR2_DMA_ERROR) {
-                       value = ioread32(reg);
-                       value &= ~DISGR2_DMA_ERROR;
-                       iowrite32(value, reg);
-               }
-       }
-
-       if (int_grp & DIGR_INT_G0) {
-               void __iomem *reg = fotg210->reg + FOTG210_DISGR0;
-               u32 int_grp0 = ioread32(reg);
-               u32 int_msk0 = ioread32(fotg210->reg + FOTG210_DMISGR0);
-               struct usb_ctrlrequest ctrl;
-
-               int_grp0 &= ~int_msk0;
-
-               /* the highest priority in this source register */
-               if (int_grp0 & DISGR0_CX_COMABT_INT) {
-                       fotg210_clear_comabt_int(fotg210);
-                       pr_info("fotg210 CX command abort\n");
-               }
-
-               if (int_grp0 & DISGR0_CX_SETUP_INT) {
-                       if (fotg210_setup_packet(fotg210, &ctrl)) {
-                               spin_unlock(&fotg210->lock);
-                               if (fotg210->driver->setup(&fotg210->gadget,
-                                                          &ctrl) < 0)
-                                       fotg210_set_cxstall(fotg210);
-                               spin_lock(&fotg210->lock);
-                       }
-               }
-               if (int_grp0 & DISGR0_CX_COMEND_INT)
-                       pr_info("fotg210 cmd end\n");
-
-               if (int_grp0 & DISGR0_CX_IN_INT)
-                       fotg210_ep0in(fotg210);
-
-               if (int_grp0 & DISGR0_CX_OUT_INT)
-                       fotg210_ep0out(fotg210);
-
-               if (int_grp0 & DISGR0_CX_COMFAIL_INT) {
-                       fotg210_set_cxstall(fotg210);
-                       pr_info("fotg210 ep0 fail\n");
-               }
-       }
-
-       if (int_grp & DIGR_INT_G1) {
-               void __iomem *reg = fotg210->reg + FOTG210_DISGR1;
-               u32 int_grp1 = ioread32(reg);
-               u32 int_msk1 = ioread32(fotg210->reg + FOTG210_DMISGR1);
-               int fifo;
-
-               int_grp1 &= ~int_msk1;
-
-               for (fifo = 0; fifo < FOTG210_MAX_FIFO_NUM; fifo++) {
-                       if (int_grp1 & DISGR1_IN_INT(fifo))
-                               fotg210_in_fifo_handler(fotg210->ep[fifo + 1]);
-
-                       if ((int_grp1 & DISGR1_OUT_INT(fifo)) ||
-                           (int_grp1 & DISGR1_SPK_INT(fifo)))
-                               fotg210_out_fifo_handler(fotg210->ep[fifo + 1]);
-               }
-       }
-
-       spin_unlock(&fotg210->lock);
-
-       return IRQ_HANDLED;
-}
-
-static void fotg210_disable_unplug(struct fotg210_udc *fotg210)
-{
-       u32 reg = ioread32(fotg210->reg + FOTG210_PHYTMSR);
-
-       reg &= ~PHYTMSR_UNPLUG;
-       iowrite32(reg, fotg210->reg + FOTG210_PHYTMSR);
-}
-
-static int fotg210_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct fotg210_udc *fotg210 = gadget_to_fotg210(g);
-       u32 value;
-
-       /* hook up the driver */
-       driver->driver.bus = NULL;
-       fotg210->driver = driver;
-
-       /* enable device global interrupt */
-       value = ioread32(fotg210->reg + FOTG210_DMCR);
-       value |= DMCR_GLINT_EN;
-       iowrite32(value, fotg210->reg + FOTG210_DMCR);
-
-       return 0;
-}
-
-static void fotg210_init(struct fotg210_udc *fotg210)
-{
-       u32 value;
-
-       /* disable global interrupt and set int polarity to active high */
-       iowrite32(GMIR_MHC_INT | GMIR_MOTG_INT | GMIR_INT_POLARITY,
-                 fotg210->reg + FOTG210_GMIR);
-
-       /* disable device global interrupt */
-       value = ioread32(fotg210->reg + FOTG210_DMCR);
-       value &= ~DMCR_GLINT_EN;
-       iowrite32(value, fotg210->reg + FOTG210_DMCR);
-
-       /* disable all fifo interrupt */
-       iowrite32(~(u32)0, fotg210->reg + FOTG210_DMISGR1);
-
-       /* disable cmd end */
-       value = ioread32(fotg210->reg + FOTG210_DMISGR0);
-       value |= DMISGR0_MCX_COMEND;
-       iowrite32(value, fotg210->reg + FOTG210_DMISGR0);
-}
-
-static int fotg210_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct fotg210_udc *fotg210 = gadget_to_fotg210(g);
-       unsigned long   flags;
-
-       spin_lock_irqsave(&fotg210->lock, flags);
-
-       fotg210_init(fotg210);
-       fotg210->driver = NULL;
-
-       spin_unlock_irqrestore(&fotg210->lock, flags);
-
-       return 0;
-}
-
-static struct usb_gadget_ops fotg210_gadget_ops = {
-       .udc_start              = fotg210_udc_start,
-       .udc_stop               = fotg210_udc_stop,
-};
-
-static int fotg210_udc_remove(struct platform_device *pdev)
-{
-       struct fotg210_udc *fotg210 = platform_get_drvdata(pdev);
-
-       usb_del_gadget_udc(&fotg210->gadget);
-       iounmap(fotg210->reg);
-       free_irq(platform_get_irq(pdev, 0), fotg210);
-
-       fotg210_ep_free_request(&fotg210->ep[0]->ep, fotg210->ep0_req);
-       kfree(fotg210);
-
-       return 0;
-}
-
-static int fotg210_udc_probe(struct platform_device *pdev)
-{
-       struct resource *res, *ires;
-       struct fotg210_udc *fotg210 = NULL;
-       struct fotg210_ep *_ep[FOTG210_MAX_NUM_EP];
-       int ret = 0;
-       int i;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               pr_err("platform_get_resource error.\n");
-               return -ENODEV;
-       }
-
-       ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!ires) {
-               pr_err("platform_get_resource IORESOURCE_IRQ error.\n");
-               return -ENODEV;
-       }
-
-       ret = -ENOMEM;
-
-       /* initialize udc */
-       fotg210 = kzalloc(sizeof(struct fotg210_udc), GFP_KERNEL);
-       if (fotg210 == NULL)
-               goto err_alloc;
-
-       for (i = 0; i < FOTG210_MAX_NUM_EP; i++) {
-               _ep[i] = kzalloc(sizeof(struct fotg210_ep), GFP_KERNEL);
-               if (_ep[i] == NULL)
-                       goto err_alloc;
-               fotg210->ep[i] = _ep[i];
-       }
-
-       fotg210->reg = ioremap(res->start, resource_size(res));
-       if (fotg210->reg == NULL) {
-               pr_err("ioremap error.\n");
-               goto err_map;
-       }
-
-       spin_lock_init(&fotg210->lock);
-
-       platform_set_drvdata(pdev, fotg210);
-
-       fotg210->gadget.ops = &fotg210_gadget_ops;
-
-       fotg210->gadget.max_speed = USB_SPEED_HIGH;
-       fotg210->gadget.dev.parent = &pdev->dev;
-       fotg210->gadget.dev.dma_mask = pdev->dev.dma_mask;
-       fotg210->gadget.name = udc_name;
-
-       INIT_LIST_HEAD(&fotg210->gadget.ep_list);
-
-       for (i = 0; i < FOTG210_MAX_NUM_EP; i++) {
-               struct fotg210_ep *ep = fotg210->ep[i];
-
-               if (i) {
-                       INIT_LIST_HEAD(&fotg210->ep[i]->ep.ep_list);
-                       list_add_tail(&fotg210->ep[i]->ep.ep_list,
-                                     &fotg210->gadget.ep_list);
-               }
-               ep->fotg210 = fotg210;
-               INIT_LIST_HEAD(&ep->queue);
-               ep->ep.name = fotg210_ep_name[i];
-               ep->ep.ops = &fotg210_ep_ops;
-               usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
-       }
-       usb_ep_set_maxpacket_limit(&fotg210->ep[0]->ep, 0x40);
-       fotg210->gadget.ep0 = &fotg210->ep[0]->ep;
-       INIT_LIST_HEAD(&fotg210->gadget.ep0->ep_list);
-
-       fotg210->ep0_req = fotg210_ep_alloc_request(&fotg210->ep[0]->ep,
-                               GFP_KERNEL);
-       if (fotg210->ep0_req == NULL)
-               goto err_req;
-
-       fotg210_init(fotg210);
-
-       fotg210_disable_unplug(fotg210);
-
-       ret = request_irq(ires->start, fotg210_irq, IRQF_SHARED,
-                         udc_name, fotg210);
-       if (ret < 0) {
-               pr_err("request_irq error (%d)\n", ret);
-               goto err_irq;
-       }
-
-       ret = usb_add_gadget_udc(&pdev->dev, &fotg210->gadget);
-       if (ret)
-               goto err_add_udc;
-
-       dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
-
-       return 0;
-
-err_add_udc:
-err_irq:
-       free_irq(ires->start, fotg210);
-
-err_req:
-       fotg210_ep_free_request(&fotg210->ep[0]->ep, fotg210->ep0_req);
-
-err_map:
-       if (fotg210->reg)
-               iounmap(fotg210->reg);
-
-err_alloc:
-       kfree(fotg210);
-
-       return ret;
-}
-
-static struct platform_driver fotg210_driver = {
-       .driver         = {
-               .name = (char *)udc_name,
-               .owner  = THIS_MODULE,
-       },
-       .probe          = fotg210_udc_probe,
-       .remove         = fotg210_udc_remove,
-};
-
-module_platform_driver(fotg210_driver);
-
-MODULE_AUTHOR("Yuan-Hsin Chen, Feng-Hsin Chiang <john453@faraday-tech.com>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/gadget/fotg210.h b/drivers/usb/gadget/fotg210.h
deleted file mode 100644 (file)
index bbf991b..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Faraday FOTG210 USB OTG controller
- *
- * Copyright (C) 2013 Faraday Technology Corporation
- * Author: Yuan-Hsin Chen <yhchen@faraday-tech.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-
-#define FOTG210_MAX_NUM_EP     5 /* ep0...ep4 */
-#define FOTG210_MAX_FIFO_NUM   4 /* fifo0...fifo4 */
-
-/* Global Mask of HC/OTG/DEV interrupt Register(0xC4) */
-#define FOTG210_GMIR           0xC4
-#define GMIR_INT_POLARITY      0x8 /*Active High*/
-#define GMIR_MHC_INT           0x4
-#define GMIR_MOTG_INT          0x2
-#define GMIR_MDEV_INT          0x1
-
-/*  Device Main Control Register(0x100) */
-#define FOTG210_DMCR           0x100
-#define DMCR_HS_EN             (1 << 6)
-#define DMCR_CHIP_EN           (1 << 5)
-#define DMCR_SFRST             (1 << 4)
-#define DMCR_GOSUSP            (1 << 3)
-#define DMCR_GLINT_EN          (1 << 2)
-#define DMCR_HALF_SPEED                (1 << 1)
-#define DMCR_CAP_RMWAKUP       (1 << 0)
-
-/* Device Address Register(0x104) */
-#define FOTG210_DAR            0x104
-#define DAR_AFT_CONF           (1 << 7)
-
-/* Device Test Register(0x108) */
-#define FOTG210_DTR            0x108
-#define DTR_TST_CLRFF          (1 << 0)
-
-/* PHY Test Mode Selector register(0x114) */
-#define FOTG210_PHYTMSR                0x114
-#define PHYTMSR_TST_PKT                (1 << 4)
-#define PHYTMSR_TST_SE0NAK     (1 << 3)
-#define PHYTMSR_TST_KSTA       (1 << 2)
-#define PHYTMSR_TST_JSTA       (1 << 1)
-#define PHYTMSR_UNPLUG         (1 << 0)
-
-/* Cx configuration and FIFO Empty Status register(0x120) */
-#define FOTG210_DCFESR         0x120
-#define DCFESR_FIFO_EMPTY(fifo)        (1 << 8 << (fifo))
-#define DCFESR_CX_EMP          (1 << 5)
-#define DCFESR_CX_CLR          (1 << 3)
-#define DCFESR_CX_STL          (1 << 2)
-#define DCFESR_TST_PKDONE      (1 << 1)
-#define DCFESR_CX_DONE         (1 << 0)
-
-/* Device IDLE Counter Register(0x124) */
-#define FOTG210_DICR           0x124
-
-/* Device Mask of Interrupt Group Register (0x130) */
-#define FOTG210_DMIGR          0x130
-#define DMIGR_MINT_G0          (1 << 0)
-
-/* Device Mask of Interrupt Source Group 0(0x134) */
-#define FOTG210_DMISGR0                0x134
-#define DMISGR0_MCX_COMEND     (1 << 3)
-#define DMISGR0_MCX_OUT_INT    (1 << 2)
-#define DMISGR0_MCX_IN_INT     (1 << 1)
-#define DMISGR0_MCX_SETUP_INT  (1 << 0)
-
-/* Device Mask of Interrupt Source Group 1 Register(0x138)*/
-#define FOTG210_DMISGR1                0x138
-#define DMISGR1_MF3_IN_INT     (1 << 19)
-#define DMISGR1_MF2_IN_INT     (1 << 18)
-#define DMISGR1_MF1_IN_INT     (1 << 17)
-#define DMISGR1_MF0_IN_INT     (1 << 16)
-#define DMISGR1_MF_IN_INT(fifo)        (1 << (16 + (fifo)))
-#define DMISGR1_MF3_SPK_INT    (1 << 7)
-#define DMISGR1_MF3_OUT_INT    (1 << 6)
-#define DMISGR1_MF2_SPK_INT    (1 << 5)
-#define DMISGR1_MF2_OUT_INT    (1 << 4)
-#define DMISGR1_MF1_SPK_INT    (1 << 3)
-#define DMISGR1_MF1_OUT_INT    (1 << 2)
-#define DMISGR1_MF0_SPK_INT    (1 << 1)
-#define DMISGR1_MF0_OUT_INT    (1 << 0)
-#define DMISGR1_MF_OUTSPK_INT(fifo)    (0x3 << (fifo) * 2)
-
-/* Device Mask of Interrupt Source Group 2 Register (0x13C) */
-#define FOTG210_DMISGR2                0x13C
-#define DMISGR2_MDMA_ERROR     (1 << 8)
-#define DMISGR2_MDMA_CMPLT     (1 << 7)
-
-/* Device Interrupt group Register (0x140) */
-#define FOTG210_DIGR           0x140
-#define DIGR_INT_G2            (1 << 2)
-#define DIGR_INT_G1            (1 << 1)
-#define DIGR_INT_G0            (1 << 0)
-
-/* Device Interrupt Source Group 0 Register (0x144) */
-#define FOTG210_DISGR0         0x144
-#define DISGR0_CX_COMABT_INT   (1 << 5)
-#define DISGR0_CX_COMFAIL_INT  (1 << 4)
-#define DISGR0_CX_COMEND_INT   (1 << 3)
-#define DISGR0_CX_OUT_INT      (1 << 2)
-#define DISGR0_CX_IN_INT       (1 << 1)
-#define DISGR0_CX_SETUP_INT    (1 << 0)
-
-/* Device Interrupt Source Group 1 Register (0x148) */
-#define FOTG210_DISGR1         0x148
-#define DISGR1_OUT_INT(fifo)   (1 << ((fifo) * 2))
-#define DISGR1_SPK_INT(fifo)   (1 << 1 << ((fifo) * 2))
-#define DISGR1_IN_INT(fifo)    (1 << 16 << (fifo))
-
-/* Device Interrupt Source Group 2 Register (0x14C) */
-#define FOTG210_DISGR2         0x14C
-#define DISGR2_DMA_ERROR       (1 << 8)
-#define DISGR2_DMA_CMPLT       (1 << 7)
-#define DISGR2_RX0BYTE_INT     (1 << 6)
-#define DISGR2_TX0BYTE_INT     (1 << 5)
-#define DISGR2_ISO_SEQ_ABORT_INT       (1 << 4)
-#define DISGR2_ISO_SEQ_ERR_INT (1 << 3)
-#define DISGR2_RESM_INT                (1 << 2)
-#define DISGR2_SUSP_INT                (1 << 1)
-#define DISGR2_USBRST_INT      (1 << 0)
-
-/* Device Receive Zero-Length Data Packet Register (0x150)*/
-#define FOTG210_RX0BYTE                0x150
-#define RX0BYTE_EP8            (1 << 7)
-#define RX0BYTE_EP7            (1 << 6)
-#define RX0BYTE_EP6            (1 << 5)
-#define RX0BYTE_EP5            (1 << 4)
-#define RX0BYTE_EP4            (1 << 3)
-#define RX0BYTE_EP3            (1 << 2)
-#define RX0BYTE_EP2            (1 << 1)
-#define RX0BYTE_EP1            (1 << 0)
-
-/* Device Transfer Zero-Length Data Packet Register (0x154)*/
-#define FOTG210_TX0BYTE                0x154
-#define TX0BYTE_EP8            (1 << 7)
-#define TX0BYTE_EP7            (1 << 6)
-#define TX0BYTE_EP6            (1 << 5)
-#define TX0BYTE_EP5            (1 << 4)
-#define TX0BYTE_EP4            (1 << 3)
-#define TX0BYTE_EP3            (1 << 2)
-#define TX0BYTE_EP2            (1 << 1)
-#define TX0BYTE_EP1            (1 << 0)
-
-/* Device IN Endpoint x MaxPacketSize Register(0x160+4*(x-1)) */
-#define FOTG210_INEPMPSR(ep)   (0x160 + 4 * ((ep) - 1))
-#define INOUTEPMPSR_MPS(mps)   ((mps) & 0x2FF)
-#define INOUTEPMPSR_STL_EP     (1 << 11)
-#define INOUTEPMPSR_RESET_TSEQ (1 << 12)
-
-/* Device OUT Endpoint x MaxPacketSize Register(0x180+4*(x-1)) */
-#define FOTG210_OUTEPMPSR(ep)  (0x180 + 4 * ((ep) - 1))
-
-/* Device Endpoint 1~4 Map Register (0x1A0) */
-#define FOTG210_EPMAP          0x1A0
-#define EPMAP_FIFONO(ep, dir)          \
-       ((((ep) - 1) << ((ep) - 1) * 8) << ((dir) ? 0 : 4))
-#define EPMAP_FIFONOMSK(ep, dir)       \
-       ((3 << ((ep) - 1) * 8) << ((dir) ? 0 : 4))
-
-/* Device FIFO Map Register (0x1A8) */
-#define FOTG210_FIFOMAP                0x1A8
-#define FIFOMAP_DIROUT(fifo)   (0x0 << 4 << (fifo) * 8)
-#define FIFOMAP_DIRIN(fifo)    (0x1 << 4 << (fifo) * 8)
-#define FIFOMAP_BIDIR(fifo)    (0x2 << 4 << (fifo) * 8)
-#define FIFOMAP_NA(fifo)       (0x3 << 4 << (fifo) * 8)
-#define FIFOMAP_EPNO(ep)       ((ep) << ((ep) - 1) * 8)
-#define FIFOMAP_EPNOMSK(ep)    (0xF << ((ep) - 1) * 8)
-
-/* Device FIFO Confuguration Register (0x1AC) */
-#define FOTG210_FIFOCF         0x1AC
-#define FIFOCF_TYPE(type, fifo)        ((type) << (fifo) * 8)
-#define FIFOCF_BLK_SIN(fifo)   (0x0 << (fifo) * 8 << 2)
-#define FIFOCF_BLK_DUB(fifo)   (0x1 << (fifo) * 8 << 2)
-#define FIFOCF_BLK_TRI(fifo)   (0x2 << (fifo) * 8 << 2)
-#define FIFOCF_BLKSZ_512(fifo) (0x0 << (fifo) * 8 << 4)
-#define FIFOCF_BLKSZ_1024(fifo)        (0x1 << (fifo) * 8 << 4)
-#define FIFOCF_FIFO_EN(fifo)   (0x1 << (fifo) * 8 << 5)
-
-/* Device FIFO n Instruction and Byte Count Register (0x1B0+4*n) */
-#define FOTG210_FIBCR(fifo)    (0x1B0 + (fifo) * 4)
-#define FIBCR_BCFX             0x7FF
-#define FIBCR_FFRST            (1 << 12)
-
-/* Device DMA Target FIFO Number Register (0x1C0) */
-#define FOTG210_DMATFNR                0x1C0
-#define DMATFNR_ACC_CXF                (1 << 4)
-#define DMATFNR_ACC_F3         (1 << 3)
-#define DMATFNR_ACC_F2         (1 << 2)
-#define DMATFNR_ACC_F1         (1 << 1)
-#define DMATFNR_ACC_F0         (1 << 0)
-#define DMATFNR_ACC_FN(fifo)   (1 << (fifo))
-#define DMATFNR_DISDMA         0
-
-/* Device DMA Controller Parameter setting 1 Register (0x1C8) */
-#define FOTG210_DMACPSR1       0x1C8
-#define DMACPSR1_DMA_LEN(len)  (((len) & 0xFFFF) << 8)
-#define DMACPSR1_DMA_ABORT     (1 << 3)
-#define DMACPSR1_DMA_TYPE(dir_in)      (((dir_in) ? 1 : 0) << 1)
-#define DMACPSR1_DMA_START     (1 << 0)
-
-/* Device DMA Controller Parameter setting 2 Register (0x1CC) */
-#define FOTG210_DMACPSR2       0x1CC
-
-/* Device DMA Controller Parameter setting 3 Register (0x1CC) */
-#define FOTG210_CXPORT         0x1D0
-
-struct fotg210_request {
-       struct usb_request      req;
-       struct list_head        queue;
-};
-
-struct fotg210_ep {
-       struct usb_ep           ep;
-       struct fotg210_udc      *fotg210;
-
-       struct list_head        queue;
-       unsigned                stall:1;
-       unsigned                wedged:1;
-       unsigned                use_dma:1;
-
-       unsigned char           epnum;
-       unsigned char           type;
-       unsigned char           dir_in;
-       unsigned int            maxp;
-       const struct usb_endpoint_descriptor    *desc;
-};
-
-struct fotg210_udc {
-       spinlock_t              lock; /* protect the struct */
-       void __iomem            *reg;
-
-       unsigned long           irq_trigger;
-
-       struct usb_gadget               gadget;
-       struct usb_gadget_driver        *driver;
-
-       struct fotg210_ep       *ep[FOTG210_MAX_NUM_EP];
-
-       struct usb_request      *ep0_req;       /* for internal request */
-       __le16                  ep0_data;
-       u8                      ep0_dir;        /* 0/0x80  out/in */
-
-       u8                      reenum;         /* if re-enumeration */
-};
-
-#define gadget_to_fotg210(g)   container_of((g), struct fotg210_udc, gadget)
diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c
deleted file mode 100644 (file)
index 9b140fc..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2009
- * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
- *
- * Description:
- * Helper routines for i.MX3x SoCs from Freescale, needed by the fsl_usb2_udc.c
- * driver to function correctly on these systems.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/fsl_devices.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-static struct clk *mxc_ahb_clk;
-static struct clk *mxc_per_clk;
-static struct clk *mxc_ipg_clk;
-
-/* workaround ENGcm09152 for i.MX35 */
-#define MX35_USBPHYCTRL_OFFSET         0x600
-#define USBPHYCTRL_OTGBASE_OFFSET      0x8
-#define USBPHYCTRL_EVDO                        (1 << 23)
-
-int fsl_udc_clk_init(struct platform_device *pdev)
-{
-       struct fsl_usb2_platform_data *pdata;
-       unsigned long freq;
-       int ret;
-
-       pdata = dev_get_platdata(&pdev->dev);
-
-       mxc_ipg_clk = devm_clk_get(&pdev->dev, "ipg");
-       if (IS_ERR(mxc_ipg_clk)) {
-               dev_err(&pdev->dev, "clk_get(\"ipg\") failed\n");
-               return PTR_ERR(mxc_ipg_clk);
-       }
-
-       mxc_ahb_clk = devm_clk_get(&pdev->dev, "ahb");
-       if (IS_ERR(mxc_ahb_clk)) {
-               dev_err(&pdev->dev, "clk_get(\"ahb\") failed\n");
-               return PTR_ERR(mxc_ahb_clk);
-       }
-
-       mxc_per_clk = devm_clk_get(&pdev->dev, "per");
-       if (IS_ERR(mxc_per_clk)) {
-               dev_err(&pdev->dev, "clk_get(\"per\") failed\n");
-               return PTR_ERR(mxc_per_clk);
-       }
-
-       clk_prepare_enable(mxc_ipg_clk);
-       clk_prepare_enable(mxc_ahb_clk);
-       clk_prepare_enable(mxc_per_clk);
-
-       /* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */
-       if (!strcmp(pdev->id_entry->name, "imx-udc-mx27")) {
-               freq = clk_get_rate(mxc_per_clk);
-               if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
-                   (freq < 59999000 || freq > 60001000)) {
-                       dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq);
-                       ret = -EINVAL;
-                       goto eclkrate;
-               }
-       }
-
-       return 0;
-
-eclkrate:
-       clk_disable_unprepare(mxc_ipg_clk);
-       clk_disable_unprepare(mxc_ahb_clk);
-       clk_disable_unprepare(mxc_per_clk);
-       mxc_per_clk = NULL;
-       return ret;
-}
-
-int fsl_udc_clk_finalize(struct platform_device *pdev)
-{
-       struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
-       int ret = 0;
-
-       /* workaround ENGcm09152 for i.MX35 */
-       if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
-               unsigned int v;
-               struct resource *res = platform_get_resource
-                       (pdev, IORESOURCE_MEM, 0);
-               void __iomem *phy_regs = ioremap(res->start +
-                                               MX35_USBPHYCTRL_OFFSET, 512);
-               if (!phy_regs) {
-                       dev_err(&pdev->dev, "ioremap for phy address fails\n");
-                       ret = -EINVAL;
-                       goto ioremap_err;
-               }
-
-               v = readl(phy_regs + USBPHYCTRL_OTGBASE_OFFSET);
-               writel(v | USBPHYCTRL_EVDO,
-                       phy_regs + USBPHYCTRL_OTGBASE_OFFSET);
-
-               iounmap(phy_regs);
-       }
-
-
-ioremap_err:
-       /* ULPI transceivers don't need usbpll */
-       if (pdata->phy_mode == FSL_USB2_PHY_ULPI) {
-               clk_disable_unprepare(mxc_per_clk);
-               mxc_per_clk = NULL;
-       }
-
-       return ret;
-}
-
-void fsl_udc_clk_release(void)
-{
-       if (mxc_per_clk)
-               clk_disable_unprepare(mxc_per_clk);
-       clk_disable_unprepare(mxc_ahb_clk);
-       clk_disable_unprepare(mxc_ipg_clk);
-}
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
deleted file mode 100644 (file)
index 7324308..0000000
+++ /dev/null
@@ -1,2731 +0,0 @@
-/*
- * driver/usb/gadget/fsl_qe_udc.c
- *
- * Copyright (c) 2006-2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- *     Xie Xiaobo <X.Xie@freescale.com>
- *     Li Yang <leoli@freescale.com>
- *     Based on bareboard code from Shlomi Gridish.
- *
- * Description:
- * Freescle QE/CPM USB Pheripheral Controller Driver
- * The controller can be found on MPC8360, MPC8272, and etc.
- * MPC8360 Rev 1.1 may need QE mircocode update
- *
- * 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.
- */
-
-#undef USB_TRACE
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/moduleparam.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/dma-mapping.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/otg.h>
-#include <asm/qe.h>
-#include <asm/cpm.h>
-#include <asm/dma.h>
-#include <asm/reg.h>
-#include "fsl_qe_udc.h"
-
-#define DRIVER_DESC     "Freescale QE/CPM USB Device Controller driver"
-#define DRIVER_AUTHOR   "Xie XiaoBo"
-#define DRIVER_VERSION  "1.0"
-
-#define DMA_ADDR_INVALID        (~(dma_addr_t)0)
-
-static const char driver_name[] = "fsl_qe_udc";
-static const char driver_desc[] = DRIVER_DESC;
-
-/*ep name is important in gadget, it should obey the convention of ep_match()*/
-static const char *const ep_name[] = {
-       "ep0-control", /* everyone has ep0 */
-       /* 3 configurable endpoints */
-       "ep1",
-       "ep2",
-       "ep3",
-};
-
-static struct usb_endpoint_descriptor qe_ep0_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-
-       .bEndpointAddress =     0,
-       .bmAttributes =         USB_ENDPOINT_XFER_CONTROL,
-       .wMaxPacketSize =       USB_MAX_CTRL_PAYLOAD,
-};
-
-/********************************************************************
- *      Internal Used Function Start
-********************************************************************/
-/*-----------------------------------------------------------------
- * done() - retire a request; caller blocked irqs
- *--------------------------------------------------------------*/
-static void done(struct qe_ep *ep, struct qe_req *req, int status)
-{
-       struct qe_udc *udc = ep->udc;
-       unsigned char stopped = ep->stopped;
-
-       /* the req->queue pointer is used by ep_queue() func, in which
-        * the request will be added into a udc_ep->queue 'd tail
-        * so here the req will be dropped from the ep->queue
-        */
-       list_del_init(&req->queue);
-
-       /* req.status should be set as -EINPROGRESS in ep_queue() */
-       if (req->req.status == -EINPROGRESS)
-               req->req.status = status;
-       else
-               status = req->req.status;
-
-       if (req->mapped) {
-               dma_unmap_single(udc->gadget.dev.parent,
-                       req->req.dma, req->req.length,
-                       ep_is_in(ep)
-                               ? DMA_TO_DEVICE
-                               : DMA_FROM_DEVICE);
-               req->req.dma = DMA_ADDR_INVALID;
-               req->mapped = 0;
-       } else
-               dma_sync_single_for_cpu(udc->gadget.dev.parent,
-                       req->req.dma, req->req.length,
-                       ep_is_in(ep)
-                               ? DMA_TO_DEVICE
-                               : DMA_FROM_DEVICE);
-
-       if (status && (status != -ESHUTDOWN))
-               dev_vdbg(udc->dev, "complete %s req %p stat %d len %u/%u\n",
-                       ep->ep.name, &req->req, status,
-                       req->req.actual, req->req.length);
-
-       /* don't modify queue heads during completion callback */
-       ep->stopped = 1;
-       spin_unlock(&udc->lock);
-
-       /* this complete() should a func implemented by gadget layer,
-        * eg fsg->bulk_in_complete() */
-       if (req->req.complete)
-               req->req.complete(&ep->ep, &req->req);
-
-       spin_lock(&udc->lock);
-
-       ep->stopped = stopped;
-}
-
-/*-----------------------------------------------------------------
- * nuke(): delete all requests related to this ep
- *--------------------------------------------------------------*/
-static void nuke(struct qe_ep *ep, int status)
-{
-       /* Whether this eq has request linked */
-       while (!list_empty(&ep->queue)) {
-               struct qe_req *req = NULL;
-               req = list_entry(ep->queue.next, struct qe_req, queue);
-
-               done(ep, req, status);
-       }
-}
-
-/*---------------------------------------------------------------------------*
- * USB and Endpoint manipulate process, include parameter and register       *
- *---------------------------------------------------------------------------*/
-/* @value: 1--set stall 0--clean stall */
-static int qe_eprx_stall_change(struct qe_ep *ep, int value)
-{
-       u16 tem_usep;
-       u8 epnum = ep->epnum;
-       struct qe_udc *udc = ep->udc;
-
-       tem_usep = in_be16(&udc->usb_regs->usb_usep[epnum]);
-       tem_usep = tem_usep & ~USB_RHS_MASK;
-       if (value == 1)
-               tem_usep |= USB_RHS_STALL;
-       else if (ep->dir == USB_DIR_IN)
-               tem_usep |= USB_RHS_IGNORE_OUT;
-
-       out_be16(&udc->usb_regs->usb_usep[epnum], tem_usep);
-       return 0;
-}
-
-static int qe_eptx_stall_change(struct qe_ep *ep, int value)
-{
-       u16 tem_usep;
-       u8 epnum = ep->epnum;
-       struct qe_udc *udc = ep->udc;
-
-       tem_usep = in_be16(&udc->usb_regs->usb_usep[epnum]);
-       tem_usep = tem_usep & ~USB_THS_MASK;
-       if (value == 1)
-               tem_usep |= USB_THS_STALL;
-       else if (ep->dir == USB_DIR_OUT)
-               tem_usep |= USB_THS_IGNORE_IN;
-
-       out_be16(&udc->usb_regs->usb_usep[epnum], tem_usep);
-
-       return 0;
-}
-
-static int qe_ep0_stall(struct qe_udc *udc)
-{
-       qe_eptx_stall_change(&udc->eps[0], 1);
-       qe_eprx_stall_change(&udc->eps[0], 1);
-       udc->ep0_state = WAIT_FOR_SETUP;
-       udc->ep0_dir = 0;
-       return 0;
-}
-
-static int qe_eprx_nack(struct qe_ep *ep)
-{
-       u8 epnum = ep->epnum;
-       struct qe_udc *udc = ep->udc;
-
-       if (ep->state == EP_STATE_IDLE) {
-               /* Set the ep's nack */
-               clrsetbits_be16(&udc->usb_regs->usb_usep[epnum],
-                               USB_RHS_MASK, USB_RHS_NACK);
-
-               /* Mask Rx and Busy interrupts */
-               clrbits16(&udc->usb_regs->usb_usbmr,
-                               (USB_E_RXB_MASK | USB_E_BSY_MASK));
-
-               ep->state = EP_STATE_NACK;
-       }
-       return 0;
-}
-
-static int qe_eprx_normal(struct qe_ep *ep)
-{
-       struct qe_udc *udc = ep->udc;
-
-       if (ep->state == EP_STATE_NACK) {
-               clrsetbits_be16(&udc->usb_regs->usb_usep[ep->epnum],
-                               USB_RTHS_MASK, USB_THS_IGNORE_IN);
-
-               /* Unmask RX interrupts */
-               out_be16(&udc->usb_regs->usb_usber,
-                               USB_E_BSY_MASK | USB_E_RXB_MASK);
-               setbits16(&udc->usb_regs->usb_usbmr,
-                               (USB_E_RXB_MASK | USB_E_BSY_MASK));
-
-               ep->state = EP_STATE_IDLE;
-               ep->has_data = 0;
-       }
-
-       return 0;
-}
-
-static int qe_ep_cmd_stoptx(struct qe_ep *ep)
-{
-       if (ep->udc->soc_type == PORT_CPM)
-               cpm_command(CPM_USB_STOP_TX | (ep->epnum << CPM_USB_EP_SHIFT),
-                               CPM_USB_STOP_TX_OPCODE);
-       else
-               qe_issue_cmd(QE_USB_STOP_TX, QE_CR_SUBBLOCK_USB,
-                               ep->epnum, 0);
-
-       return 0;
-}
-
-static int qe_ep_cmd_restarttx(struct qe_ep *ep)
-{
-       if (ep->udc->soc_type == PORT_CPM)
-               cpm_command(CPM_USB_RESTART_TX | (ep->epnum <<
-                               CPM_USB_EP_SHIFT), CPM_USB_RESTART_TX_OPCODE);
-       else
-               qe_issue_cmd(QE_USB_RESTART_TX, QE_CR_SUBBLOCK_USB,
-                               ep->epnum, 0);
-
-       return 0;
-}
-
-static int qe_ep_flushtxfifo(struct qe_ep *ep)
-{
-       struct qe_udc *udc = ep->udc;
-       int i;
-
-       i = (int)ep->epnum;
-
-       qe_ep_cmd_stoptx(ep);
-       out_8(&udc->usb_regs->usb_uscom,
-               USB_CMD_FLUSH_FIFO | (USB_CMD_EP_MASK & (ep->epnum)));
-       out_be16(&udc->ep_param[i]->tbptr, in_be16(&udc->ep_param[i]->tbase));
-       out_be32(&udc->ep_param[i]->tstate, 0);
-       out_be16(&udc->ep_param[i]->tbcnt, 0);
-
-       ep->c_txbd = ep->txbase;
-       ep->n_txbd = ep->txbase;
-       qe_ep_cmd_restarttx(ep);
-       return 0;
-}
-
-static int qe_ep_filltxfifo(struct qe_ep *ep)
-{
-       struct qe_udc *udc = ep->udc;
-
-       out_8(&udc->usb_regs->usb_uscom,
-                       USB_CMD_STR_FIFO | (USB_CMD_EP_MASK & (ep->epnum)));
-       return 0;
-}
-
-static int qe_epbds_reset(struct qe_udc *udc, int pipe_num)
-{
-       struct qe_ep *ep;
-       u32 bdring_len;
-       struct qe_bd __iomem *bd;
-       int i;
-
-       ep = &udc->eps[pipe_num];
-
-       if (ep->dir == USB_DIR_OUT)
-               bdring_len = USB_BDRING_LEN_RX;
-       else
-               bdring_len = USB_BDRING_LEN;
-
-       bd = ep->rxbase;
-       for (i = 0; i < (bdring_len - 1); i++) {
-               out_be32((u32 __iomem *)bd, R_E | R_I);
-               bd++;
-       }
-       out_be32((u32 __iomem *)bd, R_E | R_I | R_W);
-
-       bd = ep->txbase;
-       for (i = 0; i < USB_BDRING_LEN_TX - 1; i++) {
-               out_be32(&bd->buf, 0);
-               out_be32((u32 __iomem *)bd, 0);
-               bd++;
-       }
-       out_be32((u32 __iomem *)bd, T_W);
-
-       return 0;
-}
-
-static int qe_ep_reset(struct qe_udc *udc, int pipe_num)
-{
-       struct qe_ep *ep;
-       u16 tmpusep;
-
-       ep = &udc->eps[pipe_num];
-       tmpusep = in_be16(&udc->usb_regs->usb_usep[pipe_num]);
-       tmpusep &= ~USB_RTHS_MASK;
-
-       switch (ep->dir) {
-       case USB_DIR_BOTH:
-               qe_ep_flushtxfifo(ep);
-               break;
-       case USB_DIR_OUT:
-               tmpusep |= USB_THS_IGNORE_IN;
-               break;
-       case USB_DIR_IN:
-               qe_ep_flushtxfifo(ep);
-               tmpusep |= USB_RHS_IGNORE_OUT;
-               break;
-       default:
-               break;
-       }
-       out_be16(&udc->usb_regs->usb_usep[pipe_num], tmpusep);
-
-       qe_epbds_reset(udc, pipe_num);
-
-       return 0;
-}
-
-static int qe_ep_toggledata01(struct qe_ep *ep)
-{
-       ep->data01 ^= 0x1;
-       return 0;
-}
-
-static int qe_ep_bd_init(struct qe_udc *udc, unsigned char pipe_num)
-{
-       struct qe_ep *ep = &udc->eps[pipe_num];
-       unsigned long tmp_addr = 0;
-       struct usb_ep_para __iomem *epparam;
-       int i;
-       struct qe_bd __iomem *bd;
-       int bdring_len;
-
-       if (ep->dir == USB_DIR_OUT)
-               bdring_len = USB_BDRING_LEN_RX;
-       else
-               bdring_len = USB_BDRING_LEN;
-
-       epparam = udc->ep_param[pipe_num];
-       /* alloc multi-ram for BD rings and set the ep parameters */
-       tmp_addr = cpm_muram_alloc(sizeof(struct qe_bd) * (bdring_len +
-                               USB_BDRING_LEN_TX), QE_ALIGNMENT_OF_BD);
-       if (IS_ERR_VALUE(tmp_addr))
-               return -ENOMEM;
-
-       out_be16(&epparam->rbase, (u16)tmp_addr);
-       out_be16(&epparam->tbase, (u16)(tmp_addr +
-                               (sizeof(struct qe_bd) * bdring_len)));
-
-       out_be16(&epparam->rbptr, in_be16(&epparam->rbase));
-       out_be16(&epparam->tbptr, in_be16(&epparam->tbase));
-
-       ep->rxbase = cpm_muram_addr(tmp_addr);
-       ep->txbase = cpm_muram_addr(tmp_addr + (sizeof(struct qe_bd)
-                               * bdring_len));
-       ep->n_rxbd = ep->rxbase;
-       ep->e_rxbd = ep->rxbase;
-       ep->n_txbd = ep->txbase;
-       ep->c_txbd = ep->txbase;
-       ep->data01 = 0; /* data0 */
-
-       /* Init TX and RX bds */
-       bd = ep->rxbase;
-       for (i = 0; i < bdring_len - 1; i++) {
-               out_be32(&bd->buf, 0);
-               out_be32((u32 __iomem *)bd, 0);
-               bd++;
-       }
-       out_be32(&bd->buf, 0);
-       out_be32((u32 __iomem *)bd, R_W);
-
-       bd = ep->txbase;
-       for (i = 0; i < USB_BDRING_LEN_TX - 1; i++) {
-               out_be32(&bd->buf, 0);
-               out_be32((u32 __iomem *)bd, 0);
-               bd++;
-       }
-       out_be32(&bd->buf, 0);
-       out_be32((u32 __iomem *)bd, T_W);
-
-       return 0;
-}
-
-static int qe_ep_rxbd_update(struct qe_ep *ep)
-{
-       unsigned int size;
-       int i;
-       unsigned int tmp;
-       struct qe_bd __iomem *bd;
-       unsigned int bdring_len;
-
-       if (ep->rxbase == NULL)
-               return -EINVAL;
-
-       bd = ep->rxbase;
-
-       ep->rxframe = kmalloc(sizeof(*ep->rxframe), GFP_ATOMIC);
-       if (ep->rxframe == NULL) {
-               dev_err(ep->udc->dev, "malloc rxframe failed\n");
-               return -ENOMEM;
-       }
-
-       qe_frame_init(ep->rxframe);
-
-       if (ep->dir == USB_DIR_OUT)
-               bdring_len = USB_BDRING_LEN_RX;
-       else
-               bdring_len = USB_BDRING_LEN;
-
-       size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * (bdring_len + 1);
-       ep->rxbuffer = kzalloc(size, GFP_ATOMIC);
-       if (ep->rxbuffer == NULL) {
-               dev_err(ep->udc->dev, "malloc rxbuffer failed,size=%d\n",
-                               size);
-               kfree(ep->rxframe);
-               return -ENOMEM;
-       }
-
-       ep->rxbuf_d = virt_to_phys((void *)ep->rxbuffer);
-       if (ep->rxbuf_d == DMA_ADDR_INVALID) {
-               ep->rxbuf_d = dma_map_single(ep->udc->gadget.dev.parent,
-                                       ep->rxbuffer,
-                                       size,
-                                       DMA_FROM_DEVICE);
-               ep->rxbufmap = 1;
-       } else {
-               dma_sync_single_for_device(ep->udc->gadget.dev.parent,
-                                       ep->rxbuf_d, size,
-                                       DMA_FROM_DEVICE);
-               ep->rxbufmap = 0;
-       }
-
-       size = ep->ep.maxpacket + USB_CRC_SIZE + 2;
-       tmp = ep->rxbuf_d;
-       tmp = (u32)(((tmp >> 2) << 2) + 4);
-
-       for (i = 0; i < bdring_len - 1; i++) {
-               out_be32(&bd->buf, tmp);
-               out_be32((u32 __iomem *)bd, (R_E | R_I));
-               tmp = tmp + size;
-               bd++;
-       }
-       out_be32(&bd->buf, tmp);
-       out_be32((u32 __iomem *)bd, (R_E | R_I | R_W));
-
-       return 0;
-}
-
-static int qe_ep_register_init(struct qe_udc *udc, unsigned char pipe_num)
-{
-       struct qe_ep *ep = &udc->eps[pipe_num];
-       struct usb_ep_para __iomem *epparam;
-       u16 usep, logepnum;
-       u16 tmp;
-       u8 rtfcr = 0;
-
-       epparam = udc->ep_param[pipe_num];
-
-       usep = 0;
-       logepnum = (ep->ep.desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-       usep |= (logepnum << USB_EPNUM_SHIFT);
-
-       switch (ep->ep.desc->bmAttributes & 0x03) {
-       case USB_ENDPOINT_XFER_BULK:
-               usep |= USB_TRANS_BULK;
-               break;
-       case USB_ENDPOINT_XFER_ISOC:
-               usep |=  USB_TRANS_ISO;
-               break;
-       case USB_ENDPOINT_XFER_INT:
-               usep |= USB_TRANS_INT;
-               break;
-       default:
-               usep |= USB_TRANS_CTR;
-               break;
-       }
-
-       switch (ep->dir) {
-       case USB_DIR_OUT:
-               usep |= USB_THS_IGNORE_IN;
-               break;
-       case USB_DIR_IN:
-               usep |= USB_RHS_IGNORE_OUT;
-               break;
-       default:
-               break;
-       }
-       out_be16(&udc->usb_regs->usb_usep[pipe_num], usep);
-
-       rtfcr = 0x30;
-       out_8(&epparam->rbmr, rtfcr);
-       out_8(&epparam->tbmr, rtfcr);
-
-       tmp = (u16)(ep->ep.maxpacket + USB_CRC_SIZE);
-       /* MRBLR must be divisble by 4 */
-       tmp = (u16)(((tmp >> 2) << 2) + 4);
-       out_be16(&epparam->mrblr, tmp);
-
-       return 0;
-}
-
-static int qe_ep_init(struct qe_udc *udc,
-                     unsigned char pipe_num,
-                     const struct usb_endpoint_descriptor *desc)
-{
-       struct qe_ep *ep = &udc->eps[pipe_num];
-       unsigned long flags;
-       int reval = 0;
-       u16 max = 0;
-
-       max = usb_endpoint_maxp(desc);
-
-       /* check the max package size validate for this endpoint */
-       /* Refer to USB2.0 spec table 9-13,
-       */
-       if (pipe_num != 0) {
-               switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
-               case USB_ENDPOINT_XFER_BULK:
-                       if (strstr(ep->ep.name, "-iso")
-                                       || strstr(ep->ep.name, "-int"))
-                               goto en_done;
-                       switch (udc->gadget.speed) {
-                       case USB_SPEED_HIGH:
-                       if ((max == 128) || (max == 256) || (max == 512))
-                               break;
-                       default:
-                               switch (max) {
-                               case 4:
-                               case 8:
-                               case 16:
-                               case 32:
-                               case 64:
-                                       break;
-                               default:
-                               case USB_SPEED_LOW:
-                                       goto en_done;
-                               }
-                       }
-                       break;
-               case USB_ENDPOINT_XFER_INT:
-                       if (strstr(ep->ep.name, "-iso"))        /* bulk is ok */
-                               goto en_done;
-                       switch (udc->gadget.speed) {
-                       case USB_SPEED_HIGH:
-                               if (max <= 1024)
-                                       break;
-                       case USB_SPEED_FULL:
-                               if (max <= 64)
-                                       break;
-                       default:
-                               if (max <= 8)
-                                       break;
-                               goto en_done;
-                       }
-                       break;
-               case USB_ENDPOINT_XFER_ISOC:
-                       if (strstr(ep->ep.name, "-bulk")
-                               || strstr(ep->ep.name, "-int"))
-                               goto en_done;
-                       switch (udc->gadget.speed) {
-                       case USB_SPEED_HIGH:
-                               if (max <= 1024)
-                                       break;
-                       case USB_SPEED_FULL:
-                               if (max <= 1023)
-                                       break;
-                       default:
-                               goto en_done;
-                       }
-                       break;
-               case USB_ENDPOINT_XFER_CONTROL:
-                       if (strstr(ep->ep.name, "-iso")
-                               || strstr(ep->ep.name, "-int"))
-                               goto en_done;
-                       switch (udc->gadget.speed) {
-                       case USB_SPEED_HIGH:
-                       case USB_SPEED_FULL:
-                               switch (max) {
-                               case 1:
-                               case 2:
-                               case 4:
-                               case 8:
-                               case 16:
-                               case 32:
-                               case 64:
-                                       break;
-                               default:
-                                       goto en_done;
-                               }
-                       case USB_SPEED_LOW:
-                               switch (max) {
-                               case 1:
-                               case 2:
-                               case 4:
-                               case 8:
-                                       break;
-                               default:
-                                       goto en_done;
-                               }
-                       default:
-                               goto en_done;
-                       }
-                       break;
-
-               default:
-                       goto en_done;
-               }
-       } /* if ep0*/
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       /* initialize ep structure */
-       ep->ep.maxpacket = max;
-       ep->tm = (u8)(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
-       ep->ep.desc = desc;
-       ep->stopped = 0;
-       ep->init = 1;
-
-       if (pipe_num == 0) {
-               ep->dir = USB_DIR_BOTH;
-               udc->ep0_dir = USB_DIR_OUT;
-               udc->ep0_state = WAIT_FOR_SETUP;
-       } else  {
-               switch (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
-               case USB_DIR_OUT:
-                       ep->dir = USB_DIR_OUT;
-                       break;
-               case USB_DIR_IN:
-                       ep->dir = USB_DIR_IN;
-               default:
-                       break;
-               }
-       }
-
-       /* hardware special operation */
-       qe_ep_bd_init(udc, pipe_num);
-       if ((ep->tm == USBP_TM_CTL) || (ep->dir == USB_DIR_OUT)) {
-               reval = qe_ep_rxbd_update(ep);
-               if (reval)
-                       goto en_done1;
-       }
-
-       if ((ep->tm == USBP_TM_CTL) || (ep->dir == USB_DIR_IN)) {
-               ep->txframe = kmalloc(sizeof(*ep->txframe), GFP_ATOMIC);
-               if (ep->txframe == NULL) {
-                       dev_err(udc->dev, "malloc txframe failed\n");
-                       goto en_done2;
-               }
-               qe_frame_init(ep->txframe);
-       }
-
-       qe_ep_register_init(udc, pipe_num);
-
-       /* Now HW will be NAKing transfers to that EP,
-        * until a buffer is queued to it. */
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-en_done2:
-       kfree(ep->rxbuffer);
-       kfree(ep->rxframe);
-en_done1:
-       spin_unlock_irqrestore(&udc->lock, flags);
-en_done:
-       dev_err(udc->dev, "failed to initialize %s\n", ep->ep.name);
-       return -ENODEV;
-}
-
-static inline void qe_usb_enable(struct qe_udc *udc)
-{
-       setbits8(&udc->usb_regs->usb_usmod, USB_MODE_EN);
-}
-
-static inline void qe_usb_disable(struct qe_udc *udc)
-{
-       clrbits8(&udc->usb_regs->usb_usmod, USB_MODE_EN);
-}
-
-/*----------------------------------------------------------------------------*
- *             USB and EP basic manipulate function end                      *
- *----------------------------------------------------------------------------*/
-
-
-/******************************************************************************
-               UDC transmit and receive process
- ******************************************************************************/
-static void recycle_one_rxbd(struct qe_ep *ep)
-{
-       u32 bdstatus;
-
-       bdstatus = in_be32((u32 __iomem *)ep->e_rxbd);
-       bdstatus = R_I | R_E | (bdstatus & R_W);
-       out_be32((u32 __iomem *)ep->e_rxbd, bdstatus);
-
-       if (bdstatus & R_W)
-               ep->e_rxbd = ep->rxbase;
-       else
-               ep->e_rxbd++;
-}
-
-static void recycle_rxbds(struct qe_ep *ep, unsigned char stopatnext)
-{
-       u32 bdstatus;
-       struct qe_bd __iomem *bd, *nextbd;
-       unsigned char stop = 0;
-
-       nextbd = ep->n_rxbd;
-       bd = ep->e_rxbd;
-       bdstatus = in_be32((u32 __iomem *)bd);
-
-       while (!(bdstatus & R_E) && !(bdstatus & BD_LENGTH_MASK) && !stop) {
-               bdstatus = R_E | R_I | (bdstatus & R_W);
-               out_be32((u32 __iomem *)bd, bdstatus);
-
-               if (bdstatus & R_W)
-                       bd = ep->rxbase;
-               else
-                       bd++;
-
-               bdstatus = in_be32((u32 __iomem *)bd);
-               if (stopatnext && (bd == nextbd))
-                       stop = 1;
-       }
-
-       ep->e_rxbd = bd;
-}
-
-static void ep_recycle_rxbds(struct qe_ep *ep)
-{
-       struct qe_bd __iomem *bd = ep->n_rxbd;
-       u32 bdstatus;
-       u8 epnum = ep->epnum;
-       struct qe_udc *udc = ep->udc;
-
-       bdstatus = in_be32((u32 __iomem *)bd);
-       if (!(bdstatus & R_E) && !(bdstatus & BD_LENGTH_MASK)) {
-               bd = ep->rxbase +
-                               ((in_be16(&udc->ep_param[epnum]->rbptr) -
-                                 in_be16(&udc->ep_param[epnum]->rbase))
-                                >> 3);
-               bdstatus = in_be32((u32 __iomem *)bd);
-
-               if (bdstatus & R_W)
-                       bd = ep->rxbase;
-               else
-                       bd++;
-
-               ep->e_rxbd = bd;
-               recycle_rxbds(ep, 0);
-               ep->e_rxbd = ep->n_rxbd;
-       } else
-               recycle_rxbds(ep, 1);
-
-       if (in_be16(&udc->usb_regs->usb_usber) & USB_E_BSY_MASK)
-               out_be16(&udc->usb_regs->usb_usber, USB_E_BSY_MASK);
-
-       if (ep->has_data <= 0 && (!list_empty(&ep->queue)))
-               qe_eprx_normal(ep);
-
-       ep->localnack = 0;
-}
-
-static void setup_received_handle(struct qe_udc *udc,
-                                       struct usb_ctrlrequest *setup);
-static int qe_ep_rxframe_handle(struct qe_ep *ep);
-static void ep0_req_complete(struct qe_udc *udc, struct qe_req *req);
-/* when BD PID is setup, handle the packet */
-static int ep0_setup_handle(struct qe_udc *udc)
-{
-       struct qe_ep *ep = &udc->eps[0];
-       struct qe_frame *pframe;
-       unsigned int fsize;
-       u8 *cp;
-
-       pframe = ep->rxframe;
-       if ((frame_get_info(pframe) & PID_SETUP)
-                       && (udc->ep0_state == WAIT_FOR_SETUP)) {
-               fsize = frame_get_length(pframe);
-               if (unlikely(fsize != 8))
-                       return -EINVAL;
-               cp = (u8 *)&udc->local_setup_buff;
-               memcpy(cp, pframe->data, fsize);
-               ep->data01 = 1;
-
-               /* handle the usb command base on the usb_ctrlrequest */
-               setup_received_handle(udc, &udc->local_setup_buff);
-               return 0;
-       }
-       return -EINVAL;
-}
-
-static int qe_ep0_rx(struct qe_udc *udc)
-{
-       struct qe_ep *ep = &udc->eps[0];
-       struct qe_frame *pframe;
-       struct qe_bd __iomem *bd;
-       u32 bdstatus, length;
-       u32 vaddr;
-
-       pframe = ep->rxframe;
-
-       if (ep->dir == USB_DIR_IN) {
-               dev_err(udc->dev, "ep0 not a control endpoint\n");
-               return -EINVAL;
-       }
-
-       bd = ep->n_rxbd;
-       bdstatus = in_be32((u32 __iomem *)bd);
-       length = bdstatus & BD_LENGTH_MASK;
-
-       while (!(bdstatus & R_E) && length) {
-               if ((bdstatus & R_F) && (bdstatus & R_L)
-                       && !(bdstatus & R_ERROR)) {
-                       if (length == USB_CRC_SIZE) {
-                               udc->ep0_state = WAIT_FOR_SETUP;
-                               dev_vdbg(udc->dev,
-                                       "receive a ZLP in status phase\n");
-                       } else {
-                               qe_frame_clean(pframe);
-                               vaddr = (u32)phys_to_virt(in_be32(&bd->buf));
-                               frame_set_data(pframe, (u8 *)vaddr);
-                               frame_set_length(pframe,
-                                               (length - USB_CRC_SIZE));
-                               frame_set_status(pframe, FRAME_OK);
-                               switch (bdstatus & R_PID) {
-                               case R_PID_SETUP:
-                                       frame_set_info(pframe, PID_SETUP);
-                                       break;
-                               case R_PID_DATA1:
-                                       frame_set_info(pframe, PID_DATA1);
-                                       break;
-                               default:
-                                       frame_set_info(pframe, PID_DATA0);
-                                       break;
-                               }
-
-                               if ((bdstatus & R_PID) == R_PID_SETUP)
-                                       ep0_setup_handle(udc);
-                               else
-                                       qe_ep_rxframe_handle(ep);
-                       }
-               } else {
-                       dev_err(udc->dev, "The receive frame with error!\n");
-               }
-
-               /* note: don't clear the rxbd's buffer address */
-               recycle_one_rxbd(ep);
-
-               /* Get next BD */
-               if (bdstatus & R_W)
-                       bd = ep->rxbase;
-               else
-                       bd++;
-
-               bdstatus = in_be32((u32 __iomem *)bd);
-               length = bdstatus & BD_LENGTH_MASK;
-
-       }
-
-       ep->n_rxbd = bd;
-
-       return 0;
-}
-
-static int qe_ep_rxframe_handle(struct qe_ep *ep)
-{
-       struct qe_frame *pframe;
-       u8 framepid = 0;
-       unsigned int fsize;
-       u8 *cp;
-       struct qe_req *req;
-
-       pframe = ep->rxframe;
-
-       if (frame_get_info(pframe) & PID_DATA1)
-               framepid = 0x1;
-
-       if (framepid != ep->data01) {
-               dev_err(ep->udc->dev, "the data01 error!\n");
-               return -EIO;
-       }
-
-       fsize = frame_get_length(pframe);
-       if (list_empty(&ep->queue)) {
-               dev_err(ep->udc->dev, "the %s have no requeue!\n", ep->name);
-       } else {
-               req = list_entry(ep->queue.next, struct qe_req, queue);
-
-               cp = (u8 *)(req->req.buf) + req->req.actual;
-               if (cp) {
-                       memcpy(cp, pframe->data, fsize);
-                       req->req.actual += fsize;
-                       if ((fsize < ep->ep.maxpacket) ||
-                                       (req->req.actual >= req->req.length)) {
-                               if (ep->epnum == 0)
-                                       ep0_req_complete(ep->udc, req);
-                               else
-                                       done(ep, req, 0);
-                               if (list_empty(&ep->queue) && ep->epnum != 0)
-                                       qe_eprx_nack(ep);
-                       }
-               }
-       }
-
-       qe_ep_toggledata01(ep);
-
-       return 0;
-}
-
-static void ep_rx_tasklet(unsigned long data)
-{
-       struct qe_udc *udc = (struct qe_udc *)data;
-       struct qe_ep *ep;
-       struct qe_frame *pframe;
-       struct qe_bd __iomem *bd;
-       unsigned long flags;
-       u32 bdstatus, length;
-       u32 vaddr, i;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       for (i = 1; i < USB_MAX_ENDPOINTS; i++) {
-               ep = &udc->eps[i];
-
-               if (ep->dir == USB_DIR_IN || ep->enable_tasklet == 0) {
-                       dev_dbg(udc->dev,
-                               "This is a transmit ep or disable tasklet!\n");
-                       continue;
-               }
-
-               pframe = ep->rxframe;
-               bd = ep->n_rxbd;
-               bdstatus = in_be32((u32 __iomem *)bd);
-               length = bdstatus & BD_LENGTH_MASK;
-
-               while (!(bdstatus & R_E) && length) {
-                       if (list_empty(&ep->queue)) {
-                               qe_eprx_nack(ep);
-                               dev_dbg(udc->dev,
-                                       "The rxep have noreq %d\n",
-                                       ep->has_data);
-                               break;
-                       }
-
-                       if ((bdstatus & R_F) && (bdstatus & R_L)
-                               && !(bdstatus & R_ERROR)) {
-                               qe_frame_clean(pframe);
-                               vaddr = (u32)phys_to_virt(in_be32(&bd->buf));
-                               frame_set_data(pframe, (u8 *)vaddr);
-                               frame_set_length(pframe,
-                                               (length - USB_CRC_SIZE));
-                               frame_set_status(pframe, FRAME_OK);
-                               switch (bdstatus & R_PID) {
-                               case R_PID_DATA1:
-                                       frame_set_info(pframe, PID_DATA1);
-                                       break;
-                               case R_PID_SETUP:
-                                       frame_set_info(pframe, PID_SETUP);
-                                       break;
-                               default:
-                                       frame_set_info(pframe, PID_DATA0);
-                                       break;
-                               }
-                               /* handle the rx frame */
-                               qe_ep_rxframe_handle(ep);
-                       } else {
-                               dev_err(udc->dev,
-                                       "error in received frame\n");
-                       }
-                       /* note: don't clear the rxbd's buffer address */
-                       /*clear the length */
-                       out_be32((u32 __iomem *)bd, bdstatus & BD_STATUS_MASK);
-                       ep->has_data--;
-                       if (!(ep->localnack))
-                               recycle_one_rxbd(ep);
-
-                       /* Get next BD */
-                       if (bdstatus & R_W)
-                               bd = ep->rxbase;
-                       else
-                               bd++;
-
-                       bdstatus = in_be32((u32 __iomem *)bd);
-                       length = bdstatus & BD_LENGTH_MASK;
-               }
-
-               ep->n_rxbd = bd;
-
-               if (ep->localnack)
-                       ep_recycle_rxbds(ep);
-
-               ep->enable_tasklet = 0;
-       } /* for i=1 */
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-}
-
-static int qe_ep_rx(struct qe_ep *ep)
-{
-       struct qe_udc *udc;
-       struct qe_frame *pframe;
-       struct qe_bd __iomem *bd;
-       u16 swoffs, ucoffs, emptybds;
-
-       udc = ep->udc;
-       pframe = ep->rxframe;
-
-       if (ep->dir == USB_DIR_IN) {
-               dev_err(udc->dev, "transmit ep in rx function\n");
-               return -EINVAL;
-       }
-
-       bd = ep->n_rxbd;
-
-       swoffs = (u16)(bd - ep->rxbase);
-       ucoffs = (u16)((in_be16(&udc->ep_param[ep->epnum]->rbptr) -
-                       in_be16(&udc->ep_param[ep->epnum]->rbase)) >> 3);
-       if (swoffs < ucoffs)
-               emptybds = USB_BDRING_LEN_RX - ucoffs + swoffs;
-       else
-               emptybds = swoffs - ucoffs;
-
-       if (emptybds < MIN_EMPTY_BDS) {
-               qe_eprx_nack(ep);
-               ep->localnack = 1;
-               dev_vdbg(udc->dev, "%d empty bds, send NACK\n", emptybds);
-       }
-       ep->has_data = USB_BDRING_LEN_RX - emptybds;
-
-       if (list_empty(&ep->queue)) {
-               qe_eprx_nack(ep);
-               dev_vdbg(udc->dev, "The rxep have no req queued with %d BDs\n",
-                               ep->has_data);
-               return 0;
-       }
-
-       tasklet_schedule(&udc->rx_tasklet);
-       ep->enable_tasklet = 1;
-
-       return 0;
-}
-
-/* send data from a frame, no matter what tx_req */
-static int qe_ep_tx(struct qe_ep *ep, struct qe_frame *frame)
-{
-       struct qe_udc *udc = ep->udc;
-       struct qe_bd __iomem *bd;
-       u16 saveusbmr;
-       u32 bdstatus, pidmask;
-       u32 paddr;
-
-       if (ep->dir == USB_DIR_OUT) {
-               dev_err(udc->dev, "receive ep passed to tx function\n");
-               return -EINVAL;
-       }
-
-       /* Disable the Tx interrupt */
-       saveusbmr = in_be16(&udc->usb_regs->usb_usbmr);
-       out_be16(&udc->usb_regs->usb_usbmr,
-                       saveusbmr & ~(USB_E_TXB_MASK | USB_E_TXE_MASK));
-
-       bd = ep->n_txbd;
-       bdstatus = in_be32((u32 __iomem *)bd);
-
-       if (!(bdstatus & (T_R | BD_LENGTH_MASK))) {
-               if (frame_get_length(frame) == 0) {
-                       frame_set_data(frame, udc->nullbuf);
-                       frame_set_length(frame, 2);
-                       frame->info |= (ZLP | NO_CRC);
-                       dev_vdbg(udc->dev, "the frame size = 0\n");
-               }
-               paddr = virt_to_phys((void *)frame->data);
-               out_be32(&bd->buf, paddr);
-               bdstatus = (bdstatus&T_W);
-               if (!(frame_get_info(frame) & NO_CRC))
-                       bdstatus |= T_R | T_I | T_L | T_TC
-                                       | frame_get_length(frame);
-               else
-                       bdstatus |= T_R | T_I | T_L | frame_get_length(frame);
-
-               /* if the packet is a ZLP in status phase */
-               if ((ep->epnum == 0) && (udc->ep0_state == DATA_STATE_NEED_ZLP))
-                       ep->data01 = 0x1;
-
-               if (ep->data01) {
-                       pidmask = T_PID_DATA1;
-                       frame->info |= PID_DATA1;
-               } else {
-                       pidmask = T_PID_DATA0;
-                       frame->info |= PID_DATA0;
-               }
-               bdstatus |= T_CNF;
-               bdstatus |= pidmask;
-               out_be32((u32 __iomem *)bd, bdstatus);
-               qe_ep_filltxfifo(ep);
-
-               /* enable the TX interrupt */
-               out_be16(&udc->usb_regs->usb_usbmr, saveusbmr);
-
-               qe_ep_toggledata01(ep);
-               if (bdstatus & T_W)
-                       ep->n_txbd = ep->txbase;
-               else
-                       ep->n_txbd++;
-
-               return 0;
-       } else {
-               out_be16(&udc->usb_regs->usb_usbmr, saveusbmr);
-               dev_vdbg(udc->dev, "The tx bd is not ready!\n");
-               return -EBUSY;
-       }
-}
-
-/* when a bd was transmitted, the function can
- * handle the tx_req, not include ep0           */
-static int txcomplete(struct qe_ep *ep, unsigned char restart)
-{
-       if (ep->tx_req != NULL) {
-               struct qe_req *req = ep->tx_req;
-               unsigned zlp = 0, last_len = 0;
-
-               last_len = min_t(unsigned, req->req.length - ep->sent,
-                               ep->ep.maxpacket);
-
-               if (!restart) {
-                       int asent = ep->last;
-                       ep->sent += asent;
-                       ep->last -= asent;
-               } else {
-                       ep->last = 0;
-               }
-
-               /* zlp needed when req->re.zero is set */
-               if (req->req.zero) {
-                       if (last_len == 0 ||
-                               (req->req.length % ep->ep.maxpacket) != 0)
-                               zlp = 0;
-                       else
-                               zlp = 1;
-               } else
-                       zlp = 0;
-
-               /* a request already were transmitted completely */
-               if (((ep->tx_req->req.length - ep->sent) <= 0) && !zlp) {
-                       done(ep, ep->tx_req, 0);
-                       ep->tx_req = NULL;
-                       ep->last = 0;
-                       ep->sent = 0;
-               }
-       }
-
-       /* we should gain a new tx_req fot this endpoint */
-       if (ep->tx_req == NULL) {
-               if (!list_empty(&ep->queue)) {
-                       ep->tx_req = list_entry(ep->queue.next, struct qe_req,
-                                                       queue);
-                       ep->last = 0;
-                       ep->sent = 0;
-               }
-       }
-
-       return 0;
-}
-
-/* give a frame and a tx_req, send some data */
-static int qe_usb_senddata(struct qe_ep *ep, struct qe_frame *frame)
-{
-       unsigned int size;
-       u8 *buf;
-
-       qe_frame_clean(frame);
-       size = min_t(u32, (ep->tx_req->req.length - ep->sent),
-                               ep->ep.maxpacket);
-       buf = (u8 *)ep->tx_req->req.buf + ep->sent;
-       if (buf && size) {
-               ep->last = size;
-               ep->tx_req->req.actual += size;
-               frame_set_data(frame, buf);
-               frame_set_length(frame, size);
-               frame_set_status(frame, FRAME_OK);
-               frame_set_info(frame, 0);
-               return qe_ep_tx(ep, frame);
-       }
-       return -EIO;
-}
-
-/* give a frame struct,send a ZLP */
-static int sendnulldata(struct qe_ep *ep, struct qe_frame *frame, uint infor)
-{
-       struct qe_udc *udc = ep->udc;
-
-       if (frame == NULL)
-               return -ENODEV;
-
-       qe_frame_clean(frame);
-       frame_set_data(frame, (u8 *)udc->nullbuf);
-       frame_set_length(frame, 2);
-       frame_set_status(frame, FRAME_OK);
-       frame_set_info(frame, (ZLP | NO_CRC | infor));
-
-       return qe_ep_tx(ep, frame);
-}
-
-static int frame_create_tx(struct qe_ep *ep, struct qe_frame *frame)
-{
-       struct qe_req *req = ep->tx_req;
-       int reval;
-
-       if (req == NULL)
-               return -ENODEV;
-
-       if ((req->req.length - ep->sent) > 0)
-               reval = qe_usb_senddata(ep, frame);
-       else
-               reval = sendnulldata(ep, frame, 0);
-
-       return reval;
-}
-
-/* if direction is DIR_IN, the status is Device->Host
- * if direction is DIR_OUT, the status transaction is Device<-Host
- * in status phase, udc create a request and gain status */
-static int ep0_prime_status(struct qe_udc *udc, int direction)
-{
-
-       struct qe_ep *ep = &udc->eps[0];
-
-       if (direction == USB_DIR_IN) {
-               udc->ep0_state = DATA_STATE_NEED_ZLP;
-               udc->ep0_dir = USB_DIR_IN;
-               sendnulldata(ep, ep->txframe, SETUP_STATUS | NO_REQ);
-       } else {
-               udc->ep0_dir = USB_DIR_OUT;
-               udc->ep0_state = WAIT_FOR_OUT_STATUS;
-       }
-
-       return 0;
-}
-
-/* a request complete in ep0, whether gadget request or udc request */
-static void ep0_req_complete(struct qe_udc *udc, struct qe_req *req)
-{
-       struct qe_ep *ep = &udc->eps[0];
-       /* because usb and ep's status already been set in ch9setaddress() */
-
-       switch (udc->ep0_state) {
-       case DATA_STATE_XMIT:
-               done(ep, req, 0);
-               /* receive status phase */
-               if (ep0_prime_status(udc, USB_DIR_OUT))
-                       qe_ep0_stall(udc);
-               break;
-
-       case DATA_STATE_NEED_ZLP:
-               done(ep, req, 0);
-               udc->ep0_state = WAIT_FOR_SETUP;
-               break;
-
-       case DATA_STATE_RECV:
-               done(ep, req, 0);
-               /* send status phase */
-               if (ep0_prime_status(udc, USB_DIR_IN))
-                       qe_ep0_stall(udc);
-               break;
-
-       case WAIT_FOR_OUT_STATUS:
-               done(ep, req, 0);
-               udc->ep0_state = WAIT_FOR_SETUP;
-               break;
-
-       case WAIT_FOR_SETUP:
-               dev_vdbg(udc->dev, "Unexpected interrupt\n");
-               break;
-
-       default:
-               qe_ep0_stall(udc);
-               break;
-       }
-}
-
-static int ep0_txcomplete(struct qe_ep *ep, unsigned char restart)
-{
-       struct qe_req *tx_req = NULL;
-       struct qe_frame *frame = ep->txframe;
-
-       if ((frame_get_info(frame) & (ZLP | NO_REQ)) == (ZLP | NO_REQ)) {
-               if (!restart)
-                       ep->udc->ep0_state = WAIT_FOR_SETUP;
-               else
-                       sendnulldata(ep, ep->txframe, SETUP_STATUS | NO_REQ);
-               return 0;
-       }
-
-       tx_req = ep->tx_req;
-       if (tx_req != NULL) {
-               if (!restart) {
-                       int asent = ep->last;
-                       ep->sent += asent;
-                       ep->last -= asent;
-               } else {
-                       ep->last = 0;
-               }
-
-               /* a request already were transmitted completely */
-               if ((ep->tx_req->req.length - ep->sent) <= 0) {
-                       ep->tx_req->req.actual = (unsigned int)ep->sent;
-                       ep0_req_complete(ep->udc, ep->tx_req);
-                       ep->tx_req = NULL;
-                       ep->last = 0;
-                       ep->sent = 0;
-               }
-       } else {
-               dev_vdbg(ep->udc->dev, "the ep0_controller have no req\n");
-       }
-
-       return 0;
-}
-
-static int ep0_txframe_handle(struct qe_ep *ep)
-{
-       /* if have error, transmit again */
-       if (frame_get_status(ep->txframe) & FRAME_ERROR) {
-               qe_ep_flushtxfifo(ep);
-               dev_vdbg(ep->udc->dev, "The EP0 transmit data have error!\n");
-               if (frame_get_info(ep->txframe) & PID_DATA0)
-                       ep->data01 = 0;
-               else
-                       ep->data01 = 1;
-
-               ep0_txcomplete(ep, 1);
-       } else
-               ep0_txcomplete(ep, 0);
-
-       frame_create_tx(ep, ep->txframe);
-       return 0;
-}
-
-static int qe_ep0_txconf(struct qe_ep *ep)
-{
-       struct qe_bd __iomem *bd;
-       struct qe_frame *pframe;
-       u32 bdstatus;
-
-       bd = ep->c_txbd;
-       bdstatus = in_be32((u32 __iomem *)bd);
-       while (!(bdstatus & T_R) && (bdstatus & ~T_W)) {
-               pframe = ep->txframe;
-
-               /* clear and recycle the BD */
-               out_be32((u32 __iomem *)bd, bdstatus & T_W);
-               out_be32(&bd->buf, 0);
-               if (bdstatus & T_W)
-                       ep->c_txbd = ep->txbase;
-               else
-                       ep->c_txbd++;
-
-               if (ep->c_txbd == ep->n_txbd) {
-                       if (bdstatus & DEVICE_T_ERROR) {
-                               frame_set_status(pframe, FRAME_ERROR);
-                               if (bdstatus & T_TO)
-                                       pframe->status |= TX_ER_TIMEOUT;
-                               if (bdstatus & T_UN)
-                                       pframe->status |= TX_ER_UNDERUN;
-                       }
-                       ep0_txframe_handle(ep);
-               }
-
-               bd = ep->c_txbd;
-               bdstatus = in_be32((u32 __iomem *)bd);
-       }
-
-       return 0;
-}
-
-static int ep_txframe_handle(struct qe_ep *ep)
-{
-       if (frame_get_status(ep->txframe) & FRAME_ERROR) {
-               qe_ep_flushtxfifo(ep);
-               dev_vdbg(ep->udc->dev, "The EP0 transmit data have error!\n");
-               if (frame_get_info(ep->txframe) & PID_DATA0)
-                       ep->data01 = 0;
-               else
-                       ep->data01 = 1;
-
-               txcomplete(ep, 1);
-       } else
-               txcomplete(ep, 0);
-
-       frame_create_tx(ep, ep->txframe); /* send the data */
-       return 0;
-}
-
-/* confirm the already trainsmited bd */
-static int qe_ep_txconf(struct qe_ep *ep)
-{
-       struct qe_bd __iomem *bd;
-       struct qe_frame *pframe = NULL;
-       u32 bdstatus;
-       unsigned char breakonrxinterrupt = 0;
-
-       bd = ep->c_txbd;
-       bdstatus = in_be32((u32 __iomem *)bd);
-       while (!(bdstatus & T_R) && (bdstatus & ~T_W)) {
-               pframe = ep->txframe;
-               if (bdstatus & DEVICE_T_ERROR) {
-                       frame_set_status(pframe, FRAME_ERROR);
-                       if (bdstatus & T_TO)
-                               pframe->status |= TX_ER_TIMEOUT;
-                       if (bdstatus & T_UN)
-                               pframe->status |= TX_ER_UNDERUN;
-               }
-
-               /* clear and recycle the BD */
-               out_be32((u32 __iomem *)bd, bdstatus & T_W);
-               out_be32(&bd->buf, 0);
-               if (bdstatus & T_W)
-                       ep->c_txbd = ep->txbase;
-               else
-                       ep->c_txbd++;
-
-               /* handle the tx frame */
-               ep_txframe_handle(ep);
-               bd = ep->c_txbd;
-               bdstatus = in_be32((u32 __iomem *)bd);
-       }
-       if (breakonrxinterrupt)
-               return -EIO;
-       else
-               return 0;
-}
-
-/* Add a request in queue, and try to transmit a packet */
-static int ep_req_send(struct qe_ep *ep, struct qe_req *req)
-{
-       int reval = 0;
-
-       if (ep->tx_req == NULL) {
-               ep->sent = 0;
-               ep->last = 0;
-               txcomplete(ep, 0); /* can gain a new tx_req */
-               reval = frame_create_tx(ep, ep->txframe);
-       }
-       return reval;
-}
-
-/* Maybe this is a good ideal */
-static int ep_req_rx(struct qe_ep *ep, struct qe_req *req)
-{
-       struct qe_udc *udc = ep->udc;
-       struct qe_frame *pframe = NULL;
-       struct qe_bd __iomem *bd;
-       u32 bdstatus, length;
-       u32 vaddr, fsize;
-       u8 *cp;
-       u8 finish_req = 0;
-       u8 framepid;
-
-       if (list_empty(&ep->queue)) {
-               dev_vdbg(udc->dev, "the req already finish!\n");
-               return 0;
-       }
-       pframe = ep->rxframe;
-
-       bd = ep->n_rxbd;
-       bdstatus = in_be32((u32 __iomem *)bd);
-       length = bdstatus & BD_LENGTH_MASK;
-
-       while (!(bdstatus & R_E) && length) {
-               if (finish_req)
-                       break;
-               if ((bdstatus & R_F) && (bdstatus & R_L)
-                                       && !(bdstatus & R_ERROR)) {
-                       qe_frame_clean(pframe);
-                       vaddr = (u32)phys_to_virt(in_be32(&bd->buf));
-                       frame_set_data(pframe, (u8 *)vaddr);
-                       frame_set_length(pframe, (length - USB_CRC_SIZE));
-                       frame_set_status(pframe, FRAME_OK);
-                       switch (bdstatus & R_PID) {
-                       case R_PID_DATA1:
-                               frame_set_info(pframe, PID_DATA1); break;
-                       default:
-                               frame_set_info(pframe, PID_DATA0); break;
-                       }
-                       /* handle the rx frame */
-
-                       if (frame_get_info(pframe) & PID_DATA1)
-                               framepid = 0x1;
-                       else
-                               framepid = 0;
-
-                       if (framepid != ep->data01) {
-                               dev_vdbg(udc->dev, "the data01 error!\n");
-                       } else {
-                               fsize = frame_get_length(pframe);
-
-                               cp = (u8 *)(req->req.buf) + req->req.actual;
-                               if (cp) {
-                                       memcpy(cp, pframe->data, fsize);
-                                       req->req.actual += fsize;
-                                       if ((fsize < ep->ep.maxpacket)
-                                               || (req->req.actual >=
-                                                       req->req.length)) {
-                                               finish_req = 1;
-                                               done(ep, req, 0);
-                                               if (list_empty(&ep->queue))
-                                                       qe_eprx_nack(ep);
-                                       }
-                               }
-                               qe_ep_toggledata01(ep);
-                       }
-               } else {
-                       dev_err(udc->dev, "The receive frame with error!\n");
-               }
-
-               /* note: don't clear the rxbd's buffer address *
-                * only Clear the length */
-               out_be32((u32 __iomem *)bd, (bdstatus & BD_STATUS_MASK));
-               ep->has_data--;
-
-               /* Get next BD */
-               if (bdstatus & R_W)
-                       bd = ep->rxbase;
-               else
-                       bd++;
-
-               bdstatus = in_be32((u32 __iomem *)bd);
-               length = bdstatus & BD_LENGTH_MASK;
-       }
-
-       ep->n_rxbd = bd;
-       ep_recycle_rxbds(ep);
-
-       return 0;
-}
-
-/* only add the request in queue */
-static int ep_req_receive(struct qe_ep *ep, struct qe_req *req)
-{
-       if (ep->state == EP_STATE_NACK) {
-               if (ep->has_data <= 0) {
-                       /* Enable rx and unmask rx interrupt */
-                       qe_eprx_normal(ep);
-               } else {
-                       /* Copy the exist BD data */
-                       ep_req_rx(ep, req);
-               }
-       }
-
-       return 0;
-}
-
-/********************************************************************
-       Internal Used Function End
-********************************************************************/
-
-/*-----------------------------------------------------------------------
-       Endpoint Management Functions For Gadget
- -----------------------------------------------------------------------*/
-static int qe_ep_enable(struct usb_ep *_ep,
-                        const struct usb_endpoint_descriptor *desc)
-{
-       struct qe_udc *udc;
-       struct qe_ep *ep;
-       int retval = 0;
-       unsigned char epnum;
-
-       ep = container_of(_ep, struct qe_ep, ep);
-
-       /* catch various bogus parameters */
-       if (!_ep || !desc || _ep->name == ep_name[0] ||
-                       (desc->bDescriptorType != USB_DT_ENDPOINT))
-               return -EINVAL;
-
-       udc = ep->udc;
-       if (!udc->driver || (udc->gadget.speed == USB_SPEED_UNKNOWN))
-               return -ESHUTDOWN;
-
-       epnum = (u8)desc->bEndpointAddress & 0xF;
-
-       retval = qe_ep_init(udc, epnum, desc);
-       if (retval != 0) {
-               cpm_muram_free(cpm_muram_offset(ep->rxbase));
-               dev_dbg(udc->dev, "enable ep%d failed\n", ep->epnum);
-               return -EINVAL;
-       }
-       dev_dbg(udc->dev, "enable ep%d successful\n", ep->epnum);
-       return 0;
-}
-
-static int qe_ep_disable(struct usb_ep *_ep)
-{
-       struct qe_udc *udc;
-       struct qe_ep *ep;
-       unsigned long flags;
-       unsigned int size;
-
-       ep = container_of(_ep, struct qe_ep, ep);
-       udc = ep->udc;
-
-       if (!_ep || !ep->ep.desc) {
-               dev_dbg(udc->dev, "%s not enabled\n", _ep ? ep->ep.name : NULL);
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&udc->lock, flags);
-       /* Nuke all pending requests (does flush) */
-       nuke(ep, -ESHUTDOWN);
-       ep->ep.desc = NULL;
-       ep->stopped = 1;
-       ep->tx_req = NULL;
-       qe_ep_reset(udc, ep->epnum);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       cpm_muram_free(cpm_muram_offset(ep->rxbase));
-
-       if (ep->dir == USB_DIR_OUT)
-               size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) *
-                               (USB_BDRING_LEN_RX + 1);
-       else
-               size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) *
-                               (USB_BDRING_LEN + 1);
-
-       if (ep->dir != USB_DIR_IN) {
-               kfree(ep->rxframe);
-               if (ep->rxbufmap) {
-                       dma_unmap_single(udc->gadget.dev.parent,
-                                       ep->rxbuf_d, size,
-                                       DMA_FROM_DEVICE);
-                       ep->rxbuf_d = DMA_ADDR_INVALID;
-               } else {
-                       dma_sync_single_for_cpu(
-                                       udc->gadget.dev.parent,
-                                       ep->rxbuf_d, size,
-                                       DMA_FROM_DEVICE);
-               }
-               kfree(ep->rxbuffer);
-       }
-
-       if (ep->dir != USB_DIR_OUT)
-               kfree(ep->txframe);
-
-       dev_dbg(udc->dev, "disabled %s OK\n", _ep->name);
-       return 0;
-}
-
-static struct usb_request *qe_alloc_request(struct usb_ep *_ep,        gfp_t gfp_flags)
-{
-       struct qe_req *req;
-
-       req = kzalloc(sizeof(*req), gfp_flags);
-       if (!req)
-               return NULL;
-
-       req->req.dma = DMA_ADDR_INVALID;
-
-       INIT_LIST_HEAD(&req->queue);
-
-       return &req->req;
-}
-
-static void qe_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct qe_req *req;
-
-       req = container_of(_req, struct qe_req, req);
-
-       if (_req)
-               kfree(req);
-}
-
-static int __qe_ep_queue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct qe_ep *ep = container_of(_ep, struct qe_ep, ep);
-       struct qe_req *req = container_of(_req, struct qe_req, req);
-       struct qe_udc *udc;
-       int reval;
-
-       udc = ep->udc;
-       /* catch various bogus parameters */
-       if (!_req || !req->req.complete || !req->req.buf
-                       || !list_empty(&req->queue)) {
-               dev_dbg(udc->dev, "bad params\n");
-               return -EINVAL;
-       }
-       if (!_ep || (!ep->ep.desc && ep_index(ep))) {
-               dev_dbg(udc->dev, "bad ep\n");
-               return -EINVAL;
-       }
-
-       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       req->ep = ep;
-
-       /* map virtual address to hardware */
-       if (req->req.dma == DMA_ADDR_INVALID) {
-               req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
-                                       req->req.buf,
-                                       req->req.length,
-                                       ep_is_in(ep)
-                                       ? DMA_TO_DEVICE :
-                                       DMA_FROM_DEVICE);
-               req->mapped = 1;
-       } else {
-               dma_sync_single_for_device(ep->udc->gadget.dev.parent,
-                                       req->req.dma, req->req.length,
-                                       ep_is_in(ep)
-                                       ? DMA_TO_DEVICE :
-                                       DMA_FROM_DEVICE);
-               req->mapped = 0;
-       }
-
-       req->req.status = -EINPROGRESS;
-       req->req.actual = 0;
-
-       list_add_tail(&req->queue, &ep->queue);
-       dev_vdbg(udc->dev, "gadget have request in %s! %d\n",
-                       ep->name, req->req.length);
-
-       /* push the request to device */
-       if (ep_is_in(ep))
-               reval = ep_req_send(ep, req);
-
-       /* EP0 */
-       if (ep_index(ep) == 0 && req->req.length > 0) {
-               if (ep_is_in(ep))
-                       udc->ep0_state = DATA_STATE_XMIT;
-               else
-                       udc->ep0_state = DATA_STATE_RECV;
-       }
-
-       if (ep->dir == USB_DIR_OUT)
-               reval = ep_req_receive(ep, req);
-
-       return 0;
-}
-
-/* queues (submits) an I/O request to an endpoint */
-static int qe_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
-                      gfp_t gfp_flags)
-{
-       struct qe_ep *ep = container_of(_ep, struct qe_ep, ep);
-       struct qe_udc *udc = ep->udc;
-       unsigned long flags;
-       int ret;
-
-       spin_lock_irqsave(&udc->lock, flags);
-       ret = __qe_ep_queue(_ep, _req);
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return ret;
-}
-
-/* dequeues (cancels, unlinks) an I/O request from an endpoint */
-static int qe_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct qe_ep *ep = container_of(_ep, struct qe_ep, ep);
-       struct qe_req *req;
-       unsigned long flags;
-
-       if (!_ep || !_req)
-               return -EINVAL;
-
-       spin_lock_irqsave(&ep->udc->lock, flags);
-
-       /* make sure it's actually queued on this endpoint */
-       list_for_each_entry(req, &ep->queue, queue) {
-               if (&req->req == _req)
-                       break;
-       }
-
-       if (&req->req != _req) {
-               spin_unlock_irqrestore(&ep->udc->lock, flags);
-               return -EINVAL;
-       }
-
-       done(ep, req, -ECONNRESET);
-
-       spin_unlock_irqrestore(&ep->udc->lock, flags);
-       return 0;
-}
-
-/*-----------------------------------------------------------------
- * modify the endpoint halt feature
- * @ep: the non-isochronous endpoint being stalled
- * @value: 1--set halt  0--clear halt
- * Returns zero, or a negative error code.
-*----------------------------------------------------------------*/
-static int qe_ep_set_halt(struct usb_ep *_ep, int value)
-{
-       struct qe_ep *ep;
-       unsigned long flags;
-       int status = -EOPNOTSUPP;
-       struct qe_udc *udc;
-
-       ep = container_of(_ep, struct qe_ep, ep);
-       if (!_ep || !ep->ep.desc) {
-               status = -EINVAL;
-               goto out;
-       }
-
-       udc = ep->udc;
-       /* Attempt to halt IN ep will fail if any transfer requests
-        * are still queue */
-       if (value && ep_is_in(ep) && !list_empty(&ep->queue)) {
-               status = -EAGAIN;
-               goto out;
-       }
-
-       status = 0;
-       spin_lock_irqsave(&ep->udc->lock, flags);
-       qe_eptx_stall_change(ep, value);
-       qe_eprx_stall_change(ep, value);
-       spin_unlock_irqrestore(&ep->udc->lock, flags);
-
-       if (ep->epnum == 0) {
-               udc->ep0_state = WAIT_FOR_SETUP;
-               udc->ep0_dir = 0;
-       }
-
-       /* set data toggle to DATA0 on clear halt */
-       if (value == 0)
-               ep->data01 = 0;
-out:
-       dev_vdbg(udc->dev, "%s %s halt stat %d\n", ep->ep.name,
-                       value ?  "set" : "clear", status);
-
-       return status;
-}
-
-static struct usb_ep_ops qe_ep_ops = {
-       .enable = qe_ep_enable,
-       .disable = qe_ep_disable,
-
-       .alloc_request = qe_alloc_request,
-       .free_request = qe_free_request,
-
-       .queue = qe_ep_queue,
-       .dequeue = qe_ep_dequeue,
-
-       .set_halt = qe_ep_set_halt,
-};
-
-/*------------------------------------------------------------------------
-       Gadget Driver Layer Operations
- ------------------------------------------------------------------------*/
-
-/* Get the current frame number */
-static int qe_get_frame(struct usb_gadget *gadget)
-{
-       struct qe_udc *udc = container_of(gadget, struct qe_udc, gadget);
-       u16 tmp;
-
-       tmp = in_be16(&udc->usb_param->frame_n);
-       if (tmp & 0x8000)
-               tmp = tmp & 0x07ff;
-       else
-               tmp = -EINVAL;
-
-       return (int)tmp;
-}
-
-static int fsl_qe_start(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver);
-static int fsl_qe_stop(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver);
-
-/* defined in usb_gadget.h */
-static const struct usb_gadget_ops qe_gadget_ops = {
-       .get_frame = qe_get_frame,
-       .udc_start = fsl_qe_start,
-       .udc_stop = fsl_qe_stop,
-};
-
-/*-------------------------------------------------------------------------
-       USB ep0 Setup process in BUS Enumeration
- -------------------------------------------------------------------------*/
-static int udc_reset_ep_queue(struct qe_udc *udc, u8 pipe)
-{
-       struct qe_ep *ep = &udc->eps[pipe];
-
-       nuke(ep, -ECONNRESET);
-       ep->tx_req = NULL;
-       return 0;
-}
-
-static int reset_queues(struct qe_udc *udc)
-{
-       u8 pipe;
-
-       for (pipe = 0; pipe < USB_MAX_ENDPOINTS; pipe++)
-               udc_reset_ep_queue(udc, pipe);
-
-       /* report disconnect; the driver is already quiesced */
-       spin_unlock(&udc->lock);
-       udc->driver->disconnect(&udc->gadget);
-       spin_lock(&udc->lock);
-
-       return 0;
-}
-
-static void ch9setaddress(struct qe_udc *udc, u16 value, u16 index,
-                       u16 length)
-{
-       /* Save the new address to device struct */
-       udc->device_address = (u8) value;
-       /* Update usb state */
-       udc->usb_state = USB_STATE_ADDRESS;
-
-       /* Status phase , send a ZLP */
-       if (ep0_prime_status(udc, USB_DIR_IN))
-               qe_ep0_stall(udc);
-}
-
-static void ownercomplete(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct qe_req *req = container_of(_req, struct qe_req, req);
-
-       req->req.buf = NULL;
-       kfree(req);
-}
-
-static void ch9getstatus(struct qe_udc *udc, u8 request_type, u16 value,
-                       u16 index, u16 length)
-{
-       u16 usb_status = 0;
-       struct qe_req *req;
-       struct qe_ep *ep;
-       int status = 0;
-
-       ep = &udc->eps[0];
-       if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
-               /* Get device status */
-               usb_status = 1 << USB_DEVICE_SELF_POWERED;
-       } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) {
-               /* Get interface status */
-               /* We don't have interface information in udc driver */
-               usb_status = 0;
-       } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_ENDPOINT) {
-               /* Get endpoint status */
-               int pipe = index & USB_ENDPOINT_NUMBER_MASK;
-               struct qe_ep *target_ep = &udc->eps[pipe];
-               u16 usep;
-
-               /* stall if endpoint doesn't exist */
-               if (!target_ep->ep.desc)
-                       goto stall;
-
-               usep = in_be16(&udc->usb_regs->usb_usep[pipe]);
-               if (index & USB_DIR_IN) {
-                       if (target_ep->dir != USB_DIR_IN)
-                               goto stall;
-                       if ((usep & USB_THS_MASK) == USB_THS_STALL)
-                               usb_status = 1 << USB_ENDPOINT_HALT;
-               } else {
-                       if (target_ep->dir != USB_DIR_OUT)
-                               goto stall;
-                       if ((usep & USB_RHS_MASK) == USB_RHS_STALL)
-                               usb_status = 1 << USB_ENDPOINT_HALT;
-               }
-       }
-
-       req = container_of(qe_alloc_request(&ep->ep, GFP_KERNEL),
-                                       struct qe_req, req);
-       req->req.length = 2;
-       req->req.buf = udc->statusbuf;
-       *(u16 *)req->req.buf = cpu_to_le16(usb_status);
-       req->req.status = -EINPROGRESS;
-       req->req.actual = 0;
-       req->req.complete = ownercomplete;
-
-       udc->ep0_dir = USB_DIR_IN;
-
-       /* data phase */
-       status = __qe_ep_queue(&ep->ep, &req->req);
-
-       if (status == 0)
-               return;
-stall:
-       dev_err(udc->dev, "Can't respond to getstatus request \n");
-       qe_ep0_stall(udc);
-}
-
-/* only handle the setup request, suppose the device in normal status */
-static void setup_received_handle(struct qe_udc *udc,
-                               struct usb_ctrlrequest *setup)
-{
-       /* Fix Endian (udc->local_setup_buff is cpu Endian now)*/
-       u16 wValue = le16_to_cpu(setup->wValue);
-       u16 wIndex = le16_to_cpu(setup->wIndex);
-       u16 wLength = le16_to_cpu(setup->wLength);
-
-       /* clear the previous request in the ep0 */
-       udc_reset_ep_queue(udc, 0);
-
-       if (setup->bRequestType & USB_DIR_IN)
-               udc->ep0_dir = USB_DIR_IN;
-       else
-               udc->ep0_dir = USB_DIR_OUT;
-
-       switch (setup->bRequest) {
-       case USB_REQ_GET_STATUS:
-               /* Data+Status phase form udc */
-               if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
-                                       != (USB_DIR_IN | USB_TYPE_STANDARD))
-                       break;
-               ch9getstatus(udc, setup->bRequestType, wValue, wIndex,
-                                       wLength);
-               return;
-
-       case USB_REQ_SET_ADDRESS:
-               /* Status phase from udc */
-               if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
-                                               USB_RECIP_DEVICE))
-                       break;
-               ch9setaddress(udc, wValue, wIndex, wLength);
-               return;
-
-       case USB_REQ_CLEAR_FEATURE:
-       case USB_REQ_SET_FEATURE:
-               /* Requests with no data phase, status phase from udc */
-               if ((setup->bRequestType & USB_TYPE_MASK)
-                                       != USB_TYPE_STANDARD)
-                       break;
-
-               if ((setup->bRequestType & USB_RECIP_MASK)
-                               == USB_RECIP_ENDPOINT) {
-                       int pipe = wIndex & USB_ENDPOINT_NUMBER_MASK;
-                       struct qe_ep *ep;
-
-                       if (wValue != 0 || wLength != 0
-                               || pipe > USB_MAX_ENDPOINTS)
-                               break;
-                       ep = &udc->eps[pipe];
-
-                       spin_unlock(&udc->lock);
-                       qe_ep_set_halt(&ep->ep,
-                                       (setup->bRequest == USB_REQ_SET_FEATURE)
-                                               ? 1 : 0);
-                       spin_lock(&udc->lock);
-               }
-
-               ep0_prime_status(udc, USB_DIR_IN);
-
-               return;
-
-       default:
-               break;
-       }
-
-       if (wLength) {
-               /* Data phase from gadget, status phase from udc */
-               if (setup->bRequestType & USB_DIR_IN) {
-                       udc->ep0_state = DATA_STATE_XMIT;
-                       udc->ep0_dir = USB_DIR_IN;
-               } else {
-                       udc->ep0_state = DATA_STATE_RECV;
-                       udc->ep0_dir = USB_DIR_OUT;
-               }
-               spin_unlock(&udc->lock);
-               if (udc->driver->setup(&udc->gadget,
-                                       &udc->local_setup_buff) < 0)
-                       qe_ep0_stall(udc);
-               spin_lock(&udc->lock);
-       } else {
-               /* No data phase, IN status from gadget */
-               udc->ep0_dir = USB_DIR_IN;
-               spin_unlock(&udc->lock);
-               if (udc->driver->setup(&udc->gadget,
-                                       &udc->local_setup_buff) < 0)
-                       qe_ep0_stall(udc);
-               spin_lock(&udc->lock);
-               udc->ep0_state = DATA_STATE_NEED_ZLP;
-       }
-}
-
-/*-------------------------------------------------------------------------
-       USB Interrupt handlers
- -------------------------------------------------------------------------*/
-static void suspend_irq(struct qe_udc *udc)
-{
-       udc->resume_state = udc->usb_state;
-       udc->usb_state = USB_STATE_SUSPENDED;
-
-       /* report suspend to the driver ,serial.c not support this*/
-       if (udc->driver->suspend)
-               udc->driver->suspend(&udc->gadget);
-}
-
-static void resume_irq(struct qe_udc *udc)
-{
-       udc->usb_state = udc->resume_state;
-       udc->resume_state = 0;
-
-       /* report resume to the driver , serial.c not support this*/
-       if (udc->driver->resume)
-               udc->driver->resume(&udc->gadget);
-}
-
-static void idle_irq(struct qe_udc *udc)
-{
-       u8 usbs;
-
-       usbs = in_8(&udc->usb_regs->usb_usbs);
-       if (usbs & USB_IDLE_STATUS_MASK) {
-               if ((udc->usb_state) != USB_STATE_SUSPENDED)
-                       suspend_irq(udc);
-       } else {
-               if (udc->usb_state == USB_STATE_SUSPENDED)
-                       resume_irq(udc);
-       }
-}
-
-static int reset_irq(struct qe_udc *udc)
-{
-       unsigned char i;
-
-       if (udc->usb_state == USB_STATE_DEFAULT)
-               return 0;
-
-       qe_usb_disable(udc);
-       out_8(&udc->usb_regs->usb_usadr, 0);
-
-       for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
-               if (udc->eps[i].init)
-                       qe_ep_reset(udc, i);
-       }
-
-       reset_queues(udc);
-       udc->usb_state = USB_STATE_DEFAULT;
-       udc->ep0_state = WAIT_FOR_SETUP;
-       udc->ep0_dir = USB_DIR_OUT;
-       qe_usb_enable(udc);
-       return 0;
-}
-
-static int bsy_irq(struct qe_udc *udc)
-{
-       return 0;
-}
-
-static int txe_irq(struct qe_udc *udc)
-{
-       return 0;
-}
-
-/* ep0 tx interrupt also in here */
-static int tx_irq(struct qe_udc *udc)
-{
-       struct qe_ep *ep;
-       struct qe_bd __iomem *bd;
-       int i, res = 0;
-
-       if ((udc->usb_state == USB_STATE_ADDRESS)
-               && (in_8(&udc->usb_regs->usb_usadr) == 0))
-               out_8(&udc->usb_regs->usb_usadr, udc->device_address);
-
-       for (i = (USB_MAX_ENDPOINTS-1); ((i >= 0) && (res == 0)); i--) {
-               ep = &udc->eps[i];
-               if (ep && ep->init && (ep->dir != USB_DIR_OUT)) {
-                       bd = ep->c_txbd;
-                       if (!(in_be32((u32 __iomem *)bd) & T_R)
-                                               && (in_be32(&bd->buf))) {
-                               /* confirm the transmitted bd */
-                               if (ep->epnum == 0)
-                                       res = qe_ep0_txconf(ep);
-                               else
-                                       res = qe_ep_txconf(ep);
-                       }
-               }
-       }
-       return res;
-}
-
-
-/* setup packect's rx is handle in the function too */
-static void rx_irq(struct qe_udc *udc)
-{
-       struct qe_ep *ep;
-       struct qe_bd __iomem *bd;
-       int i;
-
-       for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
-               ep = &udc->eps[i];
-               if (ep && ep->init && (ep->dir != USB_DIR_IN)) {
-                       bd = ep->n_rxbd;
-                       if (!(in_be32((u32 __iomem *)bd) & R_E)
-                                               && (in_be32(&bd->buf))) {
-                               if (ep->epnum == 0) {
-                                       qe_ep0_rx(udc);
-                               } else {
-                                       /*non-setup package receive*/
-                                       qe_ep_rx(ep);
-                               }
-                       }
-               }
-       }
-}
-
-static irqreturn_t qe_udc_irq(int irq, void *_udc)
-{
-       struct qe_udc *udc = (struct qe_udc *)_udc;
-       u16 irq_src;
-       irqreturn_t status = IRQ_NONE;
-       unsigned long flags;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       irq_src = in_be16(&udc->usb_regs->usb_usber) &
-               in_be16(&udc->usb_regs->usb_usbmr);
-       /* Clear notification bits */
-       out_be16(&udc->usb_regs->usb_usber, irq_src);
-       /* USB Interrupt */
-       if (irq_src & USB_E_IDLE_MASK) {
-               idle_irq(udc);
-               irq_src &= ~USB_E_IDLE_MASK;
-               status = IRQ_HANDLED;
-       }
-
-       if (irq_src & USB_E_TXB_MASK) {
-               tx_irq(udc);
-               irq_src &= ~USB_E_TXB_MASK;
-               status = IRQ_HANDLED;
-       }
-
-       if (irq_src & USB_E_RXB_MASK) {
-               rx_irq(udc);
-               irq_src &= ~USB_E_RXB_MASK;
-               status = IRQ_HANDLED;
-       }
-
-       if (irq_src & USB_E_RESET_MASK) {
-               reset_irq(udc);
-               irq_src &= ~USB_E_RESET_MASK;
-               status = IRQ_HANDLED;
-       }
-
-       if (irq_src & USB_E_BSY_MASK) {
-               bsy_irq(udc);
-               irq_src &= ~USB_E_BSY_MASK;
-               status = IRQ_HANDLED;
-       }
-
-       if (irq_src & USB_E_TXE_MASK) {
-               txe_irq(udc);
-               irq_src &= ~USB_E_TXE_MASK;
-               status = IRQ_HANDLED;
-       }
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return status;
-}
-
-/*-------------------------------------------------------------------------
-       Gadget driver probe and unregister.
- --------------------------------------------------------------------------*/
-static int fsl_qe_start(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct qe_udc *udc;
-       unsigned long flags;
-
-       udc = container_of(gadget, struct qe_udc, gadget);
-       /* lock is needed but whether should use this lock or another */
-       spin_lock_irqsave(&udc->lock, flags);
-
-       driver->driver.bus = NULL;
-       /* hook up the driver */
-       udc->driver = driver;
-       udc->gadget.speed = driver->max_speed;
-
-       /* Enable IRQ reg and Set usbcmd reg EN bit */
-       qe_usb_enable(udc);
-
-       out_be16(&udc->usb_regs->usb_usber, 0xffff);
-       out_be16(&udc->usb_regs->usb_usbmr, USB_E_DEFAULT_DEVICE);
-       udc->usb_state = USB_STATE_ATTACHED;
-       udc->ep0_state = WAIT_FOR_SETUP;
-       udc->ep0_dir = USB_DIR_OUT;
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       dev_info(udc->dev, "%s bind to driver %s\n", udc->gadget.name,
-                       driver->driver.name);
-       return 0;
-}
-
-static int fsl_qe_stop(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct qe_udc *udc;
-       struct qe_ep *loop_ep;
-       unsigned long flags;
-
-       udc = container_of(gadget, struct qe_udc, gadget);
-       /* stop usb controller, disable intr */
-       qe_usb_disable(udc);
-
-       /* in fact, no needed */
-       udc->usb_state = USB_STATE_ATTACHED;
-       udc->ep0_state = WAIT_FOR_SETUP;
-       udc->ep0_dir = 0;
-
-       /* stand operation */
-       spin_lock_irqsave(&udc->lock, flags);
-       udc->gadget.speed = USB_SPEED_UNKNOWN;
-       nuke(&udc->eps[0], -ESHUTDOWN);
-       list_for_each_entry(loop_ep, &udc->gadget.ep_list, ep.ep_list)
-               nuke(loop_ep, -ESHUTDOWN);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       udc->driver = NULL;
-
-       dev_info(udc->dev, "unregistered gadget driver '%s'\r\n",
-                       driver->driver.name);
-       return 0;
-}
-
-/* udc structure's alloc and setup, include ep-param alloc */
-static struct qe_udc *qe_udc_config(struct platform_device *ofdev)
-{
-       struct qe_udc *udc;
-       struct device_node *np = ofdev->dev.of_node;
-       unsigned int tmp_addr = 0;
-       struct usb_device_para __iomem *usbpram;
-       unsigned int i;
-       u64 size;
-       u32 offset;
-
-       udc = kzalloc(sizeof(*udc), GFP_KERNEL);
-       if (udc == NULL) {
-               dev_err(&ofdev->dev, "malloc udc failed\n");
-               goto cleanup;
-       }
-
-       udc->dev = &ofdev->dev;
-
-       /* get default address of usb parameter in MURAM from device tree */
-       offset = *of_get_address(np, 1, &size, NULL);
-       udc->usb_param = cpm_muram_addr(offset);
-       memset_io(udc->usb_param, 0, size);
-
-       usbpram = udc->usb_param;
-       out_be16(&usbpram->frame_n, 0);
-       out_be32(&usbpram->rstate, 0);
-
-       tmp_addr = cpm_muram_alloc((USB_MAX_ENDPOINTS *
-                                       sizeof(struct usb_ep_para)),
-                                          USB_EP_PARA_ALIGNMENT);
-       if (IS_ERR_VALUE(tmp_addr))
-               goto cleanup;
-
-       for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
-               out_be16(&usbpram->epptr[i], (u16)tmp_addr);
-               udc->ep_param[i] = cpm_muram_addr(tmp_addr);
-               tmp_addr += 32;
-       }
-
-       memset_io(udc->ep_param[0], 0,
-                       USB_MAX_ENDPOINTS * sizeof(struct usb_ep_para));
-
-       udc->resume_state = USB_STATE_NOTATTACHED;
-       udc->usb_state = USB_STATE_POWERED;
-       udc->ep0_dir = 0;
-
-       spin_lock_init(&udc->lock);
-       return udc;
-
-cleanup:
-       kfree(udc);
-       return NULL;
-}
-
-/* USB Controller register init */
-static int qe_udc_reg_init(struct qe_udc *udc)
-{
-       struct usb_ctlr __iomem *qe_usbregs;
-       qe_usbregs = udc->usb_regs;
-
-       /* Spec says that we must enable the USB controller to change mode. */
-       out_8(&qe_usbregs->usb_usmod, 0x01);
-       /* Mode changed, now disable it, since muram isn't initialized yet. */
-       out_8(&qe_usbregs->usb_usmod, 0x00);
-
-       /* Initialize the rest. */
-       out_be16(&qe_usbregs->usb_usbmr, 0);
-       out_8(&qe_usbregs->usb_uscom, 0);
-       out_be16(&qe_usbregs->usb_usber, USBER_ALL_CLEAR);
-
-       return 0;
-}
-
-static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
-{
-       struct qe_ep *ep = &udc->eps[pipe_num];
-
-       ep->udc = udc;
-       strcpy(ep->name, ep_name[pipe_num]);
-       ep->ep.name = ep_name[pipe_num];
-
-       ep->ep.ops = &qe_ep_ops;
-       ep->stopped = 1;
-       usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
-       ep->ep.desc = NULL;
-       ep->dir = 0xff;
-       ep->epnum = (u8)pipe_num;
-       ep->sent = 0;
-       ep->last = 0;
-       ep->init = 0;
-       ep->rxframe = NULL;
-       ep->txframe = NULL;
-       ep->tx_req = NULL;
-       ep->state = EP_STATE_IDLE;
-       ep->has_data = 0;
-
-       /* the queue lists any req for this ep */
-       INIT_LIST_HEAD(&ep->queue);
-
-       /* gagdet.ep_list used for ep_autoconfig so no ep0*/
-       if (pipe_num != 0)
-               list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
-
-       ep->gadget = &udc->gadget;
-
-       return 0;
-}
-
-/*-----------------------------------------------------------------------
- *     UDC device Driver operation functions                           *
- *----------------------------------------------------------------------*/
-static void qe_udc_release(struct device *dev)
-{
-       struct qe_udc *udc = container_of(dev, struct qe_udc, gadget.dev);
-       int i;
-
-       complete(udc->done);
-       cpm_muram_free(cpm_muram_offset(udc->ep_param[0]));
-       for (i = 0; i < USB_MAX_ENDPOINTS; i++)
-               udc->ep_param[i] = NULL;
-
-       kfree(udc);
-}
-
-/* Driver probe functions */
-static const struct of_device_id qe_udc_match[];
-static int qe_udc_probe(struct platform_device *ofdev)
-{
-       struct qe_udc *udc;
-       const struct of_device_id *match;
-       struct device_node *np = ofdev->dev.of_node;
-       struct qe_ep *ep;
-       unsigned int ret = 0;
-       unsigned int i;
-       const void *prop;
-
-       match = of_match_device(qe_udc_match, &ofdev->dev);
-       if (!match)
-               return -EINVAL;
-
-       prop = of_get_property(np, "mode", NULL);
-       if (!prop || strcmp(prop, "peripheral"))
-               return -ENODEV;
-
-       /* Initialize the udc structure including QH member and other member */
-       udc = qe_udc_config(ofdev);
-       if (!udc) {
-               dev_err(&ofdev->dev, "failed to initialize\n");
-               return -ENOMEM;
-       }
-
-       udc->soc_type = (unsigned long)match->data;
-       udc->usb_regs = of_iomap(np, 0);
-       if (!udc->usb_regs) {
-               ret = -ENOMEM;
-               goto err1;
-       }
-
-       /* initialize usb hw reg except for regs for EP,
-        * leave usbintr reg untouched*/
-       qe_udc_reg_init(udc);
-
-       /* here comes the stand operations for probe
-        * set the qe_udc->gadget.xxx */
-       udc->gadget.ops = &qe_gadget_ops;
-
-       /* gadget.ep0 is a pointer */
-       udc->gadget.ep0 = &udc->eps[0].ep;
-
-       INIT_LIST_HEAD(&udc->gadget.ep_list);
-
-       /* modify in register gadget process */
-       udc->gadget.speed = USB_SPEED_UNKNOWN;
-
-       /* name: Identifies the controller hardware type. */
-       udc->gadget.name = driver_name;
-       udc->gadget.dev.parent = &ofdev->dev;
-
-       /* initialize qe_ep struct */
-       for (i = 0; i < USB_MAX_ENDPOINTS ; i++) {
-               /* because the ep type isn't decide here so
-                * qe_ep_init() should be called in ep_enable() */
-
-               /* setup the qe_ep struct and link ep.ep.list
-                * into gadget.ep_list */
-               qe_ep_config(udc, (unsigned char)i);
-       }
-
-       /* ep0 initialization in here */
-       ret = qe_ep_init(udc, 0, &qe_ep0_desc);
-       if (ret)
-               goto err2;
-
-       /* create a buf for ZLP send, need to remain zeroed */
-       udc->nullbuf = devm_kzalloc(&ofdev->dev, 256, GFP_KERNEL);
-       if (udc->nullbuf == NULL) {
-               dev_err(udc->dev, "cannot alloc nullbuf\n");
-               ret = -ENOMEM;
-               goto err3;
-       }
-
-       /* buffer for data of get_status request */
-       udc->statusbuf = devm_kzalloc(&ofdev->dev, 2, GFP_KERNEL);
-       if (udc->statusbuf == NULL) {
-               ret = -ENOMEM;
-               goto err3;
-       }
-
-       udc->nullp = virt_to_phys((void *)udc->nullbuf);
-       if (udc->nullp == DMA_ADDR_INVALID) {
-               udc->nullp = dma_map_single(
-                                       udc->gadget.dev.parent,
-                                       udc->nullbuf,
-                                       256,
-                                       DMA_TO_DEVICE);
-               udc->nullmap = 1;
-       } else {
-               dma_sync_single_for_device(udc->gadget.dev.parent,
-                                       udc->nullp, 256,
-                                       DMA_TO_DEVICE);
-       }
-
-       tasklet_init(&udc->rx_tasklet, ep_rx_tasklet,
-                       (unsigned long)udc);
-       /* request irq and disable DR  */
-       udc->usb_irq = irq_of_parse_and_map(np, 0);
-       if (!udc->usb_irq) {
-               ret = -EINVAL;
-               goto err_noirq;
-       }
-
-       ret = request_irq(udc->usb_irq, qe_udc_irq, 0,
-                               driver_name, udc);
-       if (ret) {
-               dev_err(udc->dev, "cannot request irq %d err %d\n",
-                               udc->usb_irq, ret);
-               goto err4;
-       }
-
-       ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
-                       qe_udc_release);
-       if (ret)
-               goto err5;
-
-       platform_set_drvdata(ofdev, udc);
-       dev_info(udc->dev,
-                       "%s USB controller initialized as device\n",
-                       (udc->soc_type == PORT_QE) ? "QE" : "CPM");
-       return 0;
-
-err5:
-       free_irq(udc->usb_irq, udc);
-err4:
-       irq_dispose_mapping(udc->usb_irq);
-err_noirq:
-       if (udc->nullmap) {
-               dma_unmap_single(udc->gadget.dev.parent,
-                       udc->nullp, 256,
-                               DMA_TO_DEVICE);
-                       udc->nullp = DMA_ADDR_INVALID;
-       } else {
-               dma_sync_single_for_cpu(udc->gadget.dev.parent,
-                       udc->nullp, 256,
-                               DMA_TO_DEVICE);
-       }
-err3:
-       ep = &udc->eps[0];
-       cpm_muram_free(cpm_muram_offset(ep->rxbase));
-       kfree(ep->rxframe);
-       kfree(ep->rxbuffer);
-       kfree(ep->txframe);
-err2:
-       iounmap(udc->usb_regs);
-err1:
-       kfree(udc);
-       return ret;
-}
-
-#ifdef CONFIG_PM
-static int qe_udc_suspend(struct platform_device *dev, pm_message_t state)
-{
-       return -ENOTSUPP;
-}
-
-static int qe_udc_resume(struct platform_device *dev)
-{
-       return -ENOTSUPP;
-}
-#endif
-
-static int qe_udc_remove(struct platform_device *ofdev)
-{
-       struct qe_udc *udc = platform_get_drvdata(ofdev);
-       struct qe_ep *ep;
-       unsigned int size;
-       DECLARE_COMPLETION(done);
-
-       usb_del_gadget_udc(&udc->gadget);
-
-       udc->done = &done;
-       tasklet_disable(&udc->rx_tasklet);
-
-       if (udc->nullmap) {
-               dma_unmap_single(udc->gadget.dev.parent,
-                       udc->nullp, 256,
-                               DMA_TO_DEVICE);
-                       udc->nullp = DMA_ADDR_INVALID;
-       } else {
-               dma_sync_single_for_cpu(udc->gadget.dev.parent,
-                       udc->nullp, 256,
-                               DMA_TO_DEVICE);
-       }
-
-       ep = &udc->eps[0];
-       cpm_muram_free(cpm_muram_offset(ep->rxbase));
-       size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * (USB_BDRING_LEN + 1);
-
-       kfree(ep->rxframe);
-       if (ep->rxbufmap) {
-               dma_unmap_single(udc->gadget.dev.parent,
-                               ep->rxbuf_d, size,
-                               DMA_FROM_DEVICE);
-               ep->rxbuf_d = DMA_ADDR_INVALID;
-       } else {
-               dma_sync_single_for_cpu(udc->gadget.dev.parent,
-                               ep->rxbuf_d, size,
-                               DMA_FROM_DEVICE);
-       }
-
-       kfree(ep->rxbuffer);
-       kfree(ep->txframe);
-
-       free_irq(udc->usb_irq, udc);
-       irq_dispose_mapping(udc->usb_irq);
-
-       tasklet_kill(&udc->rx_tasklet);
-
-       iounmap(udc->usb_regs);
-
-       /* wait for release() of gadget.dev to free udc */
-       wait_for_completion(&done);
-
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-static const struct of_device_id qe_udc_match[] = {
-       {
-               .compatible = "fsl,mpc8323-qe-usb",
-               .data = (void *)PORT_QE,
-       },
-       {
-               .compatible = "fsl,mpc8360-qe-usb",
-               .data = (void *)PORT_QE,
-       },
-       {
-               .compatible = "fsl,mpc8272-cpm-usb",
-               .data = (void *)PORT_CPM,
-       },
-       {},
-};
-
-MODULE_DEVICE_TABLE(of, qe_udc_match);
-
-static struct platform_driver udc_driver = {
-       .driver = {
-               .name = driver_name,
-               .owner = THIS_MODULE,
-               .of_match_table = qe_udc_match,
-       },
-       .probe          = qe_udc_probe,
-       .remove         = qe_udc_remove,
-#ifdef CONFIG_PM
-       .suspend        = qe_udc_suspend,
-       .resume         = qe_udc_resume,
-#endif
-};
-
-module_platform_driver(udc_driver);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/fsl_qe_udc.h
deleted file mode 100644 (file)
index 7026919..0000000
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * drivers/usb/gadget/qe_udc.h
- *
- * Copyright (C) 2006-2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- *     Xiaobo Xie <X.Xie@freescale.com>
- *     Li Yang <leoli@freescale.com>
- *
- * Description:
- * Freescale USB device/endpoint management registers
- *
- * 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.
- */
-
-#ifndef __FSL_QE_UDC_H
-#define __FSL_QE_UDC_H
-
-/* SoC type */
-#define PORT_CPM       0
-#define PORT_QE                1
-
-#define USB_MAX_ENDPOINTS               4
-#define USB_MAX_PIPES                   USB_MAX_ENDPOINTS
-#define USB_EP0_MAX_SIZE               64
-#define USB_MAX_CTRL_PAYLOAD            0x4000
-#define USB_BDRING_LEN                 16
-#define USB_BDRING_LEN_RX              256
-#define USB_BDRING_LEN_TX              16
-#define MIN_EMPTY_BDS                  128
-#define MAX_DATA_BDS                   8
-#define USB_CRC_SIZE                   2
-#define USB_DIR_BOTH                   0x88
-#define R_BUF_MAXSIZE                  0x800
-#define USB_EP_PARA_ALIGNMENT          32
-
-/* USB Mode Register bit define */
-#define USB_MODE_EN            0x01
-#define USB_MODE_HOST          0x02
-#define USB_MODE_TEST          0x04
-#define USB_MODE_SFTE          0x08
-#define USB_MODE_RESUME                0x40
-#define USB_MODE_LSS           0x80
-
-/* USB Slave Address Register Mask */
-#define USB_SLVADDR_MASK       0x7F
-
-/* USB Endpoint register define */
-#define USB_EPNUM_MASK         0xF000
-#define USB_EPNUM_SHIFT                12
-
-#define USB_TRANS_MODE_SHIFT   8
-#define USB_TRANS_CTR          0x0000
-#define USB_TRANS_INT          0x0100
-#define USB_TRANS_BULK         0x0200
-#define USB_TRANS_ISO          0x0300
-
-#define USB_EP_MF              0x0020
-#define USB_EP_RTE             0x0010
-
-#define USB_THS_SHIFT          2
-#define USB_THS_MASK           0x000c
-#define USB_THS_NORMAL         0x0
-#define USB_THS_IGNORE_IN      0x0004
-#define USB_THS_NACK           0x0008
-#define USB_THS_STALL          0x000c
-
-#define USB_RHS_SHIFT          0
-#define USB_RHS_MASK           0x0003
-#define USB_RHS_NORMAL         0x0
-#define USB_RHS_IGNORE_OUT     0x0001
-#define USB_RHS_NACK           0x0002
-#define USB_RHS_STALL          0x0003
-
-#define USB_RTHS_MASK          0x000f
-
-/* USB Command Register define */
-#define USB_CMD_STR_FIFO       0x80
-#define USB_CMD_FLUSH_FIFO     0x40
-#define USB_CMD_ISFT           0x20
-#define USB_CMD_DSFT           0x10
-#define USB_CMD_EP_MASK                0x03
-
-/* USB Event and Mask Register define */
-#define USB_E_MSF_MASK         0x0800
-#define USB_E_SFT_MASK         0x0400
-#define USB_E_RESET_MASK       0x0200
-#define USB_E_IDLE_MASK                0x0100
-#define USB_E_TXE4_MASK                0x0080
-#define USB_E_TXE3_MASK                0x0040
-#define USB_E_TXE2_MASK                0x0020
-#define USB_E_TXE1_MASK                0x0010
-#define USB_E_SOF_MASK         0x0008
-#define USB_E_BSY_MASK         0x0004
-#define USB_E_TXB_MASK         0x0002
-#define USB_E_RXB_MASK         0x0001
-#define USBER_ALL_CLEAR        0x0fff
-
-#define USB_E_DEFAULT_DEVICE   (USB_E_RESET_MASK | USB_E_TXE4_MASK | \
-                               USB_E_TXE3_MASK | USB_E_TXE2_MASK | \
-                               USB_E_TXE1_MASK | USB_E_BSY_MASK | \
-                               USB_E_TXB_MASK | USB_E_RXB_MASK)
-
-#define USB_E_TXE_MASK         (USB_E_TXE4_MASK | USB_E_TXE3_MASK|\
-                                USB_E_TXE2_MASK | USB_E_TXE1_MASK)
-/* USB Status Register define */
-#define USB_IDLE_STATUS_MASK   0x01
-
-/* USB Start of Frame Timer */
-#define USB_USSFT_MASK         0x3FFF
-
-/* USB Frame Number Register */
-#define USB_USFRN_MASK         0xFFFF
-
-struct usb_device_para{
-       u16     epptr[4];
-       u32     rstate;
-       u32     rptr;
-       u16     frame_n;
-       u16     rbcnt;
-       u32     rtemp;
-       u32     rxusb_data;
-       u16     rxuptr;
-       u8      reso[2];
-       u32     softbl;
-       u8      sofucrctemp;
-};
-
-struct usb_ep_para{
-       u16     rbase;
-       u16     tbase;
-       u8      rbmr;
-       u8      tbmr;
-       u16     mrblr;
-       u16     rbptr;
-       u16     tbptr;
-       u32     tstate;
-       u32     tptr;
-       u16     tcrc;
-       u16     tbcnt;
-       u32     ttemp;
-       u16     txusbu_ptr;
-       u8      reserve[2];
-};
-
-#define USB_BUSMODE_GBL                0x20
-#define USB_BUSMODE_BO_MASK    0x18
-#define USB_BUSMODE_BO_SHIFT   0x3
-#define USB_BUSMODE_BE         0x2
-#define USB_BUSMODE_CETM       0x04
-#define USB_BUSMODE_DTB                0x02
-
-/* Endpoint basic handle */
-#define ep_index(EP)           ((EP)->ep.desc->bEndpointAddress & 0xF)
-#define ep_maxpacket(EP)       ((EP)->ep.maxpacket)
-#define ep_is_in(EP)   ((ep_index(EP) == 0) ? (EP->udc->ep0_dir == \
-                       USB_DIR_IN) : ((EP)->ep.desc->bEndpointAddress \
-                       & USB_DIR_IN) == USB_DIR_IN)
-
-/* ep0 transfer state */
-#define WAIT_FOR_SETUP          0
-#define DATA_STATE_XMIT         1
-#define DATA_STATE_NEED_ZLP     2
-#define WAIT_FOR_OUT_STATUS     3
-#define DATA_STATE_RECV         4
-
-/* ep tramsfer mode */
-#define USBP_TM_CTL    0
-#define USBP_TM_ISO    1
-#define USBP_TM_BULK   2
-#define USBP_TM_INT    3
-
-/*-----------------------------------------------------------------------------
-       USB RX And TX DATA Frame
- -----------------------------------------------------------------------------*/
-struct qe_frame{
-       u8 *data;
-       u32 len;
-       u32 status;
-       u32 info;
-
-       void *privdata;
-       struct list_head node;
-};
-
-/* Frame structure, info field. */
-#define PID_DATA0              0x80000000 /* Data toggle zero */
-#define PID_DATA1              0x40000000 /* Data toggle one  */
-#define PID_SETUP              0x20000000 /* setup bit */
-#define SETUP_STATUS           0x10000000 /* setup status bit */
-#define SETADDR_STATUS         0x08000000 /* setupup address status bit */
-#define NO_REQ                 0x04000000 /* Frame without request */
-#define HOST_DATA              0x02000000 /* Host data frame */
-#define FIRST_PACKET_IN_FRAME  0x01000000 /* first packet in the frame */
-#define TOKEN_FRAME            0x00800000 /* Host token frame */
-#define ZLP                    0x00400000 /* Zero length packet */
-#define IN_TOKEN_FRAME         0x00200000 /* In token package */
-#define OUT_TOKEN_FRAME        0x00100000 /* Out token package */
-#define SETUP_TOKEN_FRAME      0x00080000 /* Setup token package */
-#define STALL_FRAME            0x00040000 /* Stall handshake */
-#define NACK_FRAME             0x00020000 /* Nack handshake */
-#define NO_PID                 0x00010000 /* No send PID */
-#define NO_CRC                 0x00008000 /* No send CRC */
-#define HOST_COMMAND           0x00004000 /* Host command frame   */
-
-/* Frame status field */
-/* Receive side */
-#define FRAME_OK               0x00000000 /* Frame transmitted or received OK */
-#define FRAME_ERROR            0x80000000 /* Error occurred on frame */
-#define START_FRAME_LOST       0x40000000 /* START_FRAME_LOST */
-#define END_FRAME_LOST         0x20000000 /* END_FRAME_LOST */
-#define RX_ER_NONOCT           0x10000000 /* Rx Non Octet Aligned Packet */
-#define RX_ER_BITSTUFF         0x08000000 /* Frame Aborted --Received packet
-                                            with bit stuff error */
-#define RX_ER_CRC              0x04000000 /* Received packet with CRC error */
-#define RX_ER_OVERUN           0x02000000 /* Over-run occurred on reception */
-#define RX_ER_PID              0x01000000 /* Wrong PID received */
-/* Tranmit side */
-#define TX_ER_NAK              0x00800000 /* Received NAK handshake */
-#define TX_ER_STALL            0x00400000 /* Received STALL handshake */
-#define TX_ER_TIMEOUT          0x00200000 /* Transmit time out */
-#define TX_ER_UNDERUN          0x00100000 /* Transmit underrun */
-#define FRAME_INPROGRESS       0x00080000 /* Frame is being transmitted */
-#define ER_DATA_UNDERUN        0x00040000 /* Frame is shorter then expected */
-#define ER_DATA_OVERUN         0x00020000 /* Frame is longer then expected */
-
-/* QE USB frame operation functions */
-#define frame_get_length(frm) (frm->len)
-#define frame_set_length(frm, leng) (frm->len = leng)
-#define frame_get_data(frm) (frm->data)
-#define frame_set_data(frm, dat) (frm->data = dat)
-#define frame_get_info(frm) (frm->info)
-#define frame_set_info(frm, inf) (frm->info = inf)
-#define frame_get_status(frm) (frm->status)
-#define frame_set_status(frm, stat) (frm->status = stat)
-#define frame_get_privdata(frm) (frm->privdata)
-#define frame_set_privdata(frm, dat) (frm->privdata = dat)
-
-static inline void qe_frame_clean(struct qe_frame *frm)
-{
-       frame_set_data(frm, NULL);
-       frame_set_length(frm, 0);
-       frame_set_status(frm, FRAME_OK);
-       frame_set_info(frm, 0);
-       frame_set_privdata(frm, NULL);
-}
-
-static inline void qe_frame_init(struct qe_frame *frm)
-{
-       qe_frame_clean(frm);
-       INIT_LIST_HEAD(&(frm->node));
-}
-
-struct qe_req {
-       struct usb_request req;
-       struct list_head queue;
-       /* ep_queue() func will add
-        a request->queue into a udc_ep->queue 'd tail */
-       struct qe_ep *ep;
-       unsigned mapped:1;
-};
-
-struct qe_ep {
-       struct usb_ep ep;
-       struct list_head queue;
-       struct qe_udc *udc;
-       struct usb_gadget *gadget;
-
-       u8 state;
-
-       struct qe_bd __iomem *rxbase;
-       struct qe_bd __iomem *n_rxbd;
-       struct qe_bd __iomem *e_rxbd;
-
-       struct qe_bd __iomem *txbase;
-       struct qe_bd __iomem *n_txbd;
-       struct qe_bd __iomem *c_txbd;
-
-       struct qe_frame *rxframe;
-       u8 *rxbuffer;
-       dma_addr_t rxbuf_d;
-       u8 rxbufmap;
-       unsigned char localnack;
-       int has_data;
-
-       struct qe_frame *txframe;
-       struct qe_req *tx_req;
-       int sent;  /*data already sent */
-       int last;  /*data sent in the last time*/
-
-       u8 dir;
-       u8 epnum;
-       u8 tm; /* transfer mode */
-       u8 data01;
-       u8 init;
-
-       u8 already_seen;
-       u8 enable_tasklet;
-       u8 setup_stage;
-       u32 last_io;            /* timestamp */
-
-       char name[14];
-
-       unsigned double_buf:1;
-       unsigned stopped:1;
-       unsigned fnf:1;
-       unsigned has_dma:1;
-
-       u8 ackwait;
-       u8 dma_channel;
-       u16 dma_counter;
-       int lch;
-
-       struct timer_list timer;
-};
-
-struct qe_udc {
-       struct usb_gadget gadget;
-       struct usb_gadget_driver *driver;
-       struct device *dev;
-       struct qe_ep eps[USB_MAX_ENDPOINTS];
-       struct usb_ctrlrequest local_setup_buff;
-       spinlock_t lock;        /* lock for set/config qe_udc */
-       unsigned long soc_type;         /* QE or CPM soc */
-
-       struct qe_req *status_req;      /* ep0 status request */
-
-       /* USB and EP Parameter Block pointer */
-       struct usb_device_para __iomem *usb_param;
-       struct usb_ep_para __iomem *ep_param[4];
-
-       u32 max_pipes;          /* Device max pipes */
-       u32 max_use_endpts;     /* Max endpointes to be used */
-       u32 bus_reset;          /* Device is bus reseting */
-       u32 resume_state;       /* USB state to resume*/
-       u32 usb_state;          /* USB current state */
-       u32 usb_next_state;     /* USB next state */
-       u32 ep0_state;          /* Enpoint zero state */
-       u32 ep0_dir;            /* Enpoint zero direction: can be
-                               USB_DIR_IN or USB_DIR_OUT*/
-       u32 usb_sof_count;      /* SOF count */
-       u32 errors;             /* USB ERRORs count */
-
-       u8 *tmpbuf;
-       u32 c_start;
-       u32 c_end;
-
-       u8 *nullbuf;
-       u8 *statusbuf;
-       dma_addr_t nullp;
-       u8 nullmap;
-       u8 device_address;      /* Device USB address */
-
-       unsigned int usb_clock;
-       unsigned int usb_irq;
-       struct usb_ctlr __iomem *usb_regs;
-
-       struct tasklet_struct rx_tasklet;
-
-       struct completion *done;        /* to make sure release() is done */
-};
-
-#define EP_STATE_IDLE  0
-#define EP_STATE_NACK  1
-#define EP_STATE_STALL 2
-
-/*
- * transmit BD's status
- */
-#define T_R           0x80000000         /* ready bit */
-#define T_W           0x20000000         /* wrap bit */
-#define T_I           0x10000000         /* interrupt on completion */
-#define T_L           0x08000000         /* last */
-#define T_TC          0x04000000         /* transmit CRC */
-#define T_CNF         0x02000000         /* wait for  transmit confirm */
-#define T_LSP         0x01000000         /* Low-speed transaction */
-#define T_PID         0x00c00000         /* packet id */
-#define T_NAK         0x00100000         /* No ack. */
-#define T_STAL        0x00080000         /* Stall received */
-#define T_TO          0x00040000         /* time out */
-#define T_UN          0x00020000         /* underrun */
-
-#define DEVICE_T_ERROR    (T_UN | T_TO)
-#define HOST_T_ERROR      (T_UN | T_TO | T_NAK | T_STAL)
-#define DEVICE_T_BD_MASK  DEVICE_T_ERROR
-#define HOST_T_BD_MASK    HOST_T_ERROR
-
-#define T_PID_SHIFT   6
-#define T_PID_DATA0   0x00800000         /* Data 0 toggle */
-#define T_PID_DATA1   0x00c00000         /* Data 1 toggle */
-
-/*
- * receive BD's status
- */
-#define R_E           0x80000000         /* buffer empty */
-#define R_W           0x20000000         /* wrap bit */
-#define R_I           0x10000000         /* interrupt on reception */
-#define R_L           0x08000000         /* last */
-#define R_F           0x04000000         /* first */
-#define R_PID         0x00c00000         /* packet id */
-#define R_NO          0x00100000         /* Rx Non Octet Aligned Packet */
-#define R_AB          0x00080000         /* Frame Aborted */
-#define R_CR          0x00040000         /* CRC Error */
-#define R_OV          0x00020000         /* Overrun */
-
-#define R_ERROR       (R_NO | R_AB | R_CR | R_OV)
-#define R_BD_MASK     R_ERROR
-
-#define R_PID_DATA0   0x00000000
-#define R_PID_DATA1   0x00400000
-#define R_PID_SETUP   0x00800000
-
-#define CPM_USB_STOP_TX 0x2e600000
-#define CPM_USB_RESTART_TX 0x2e600000
-#define CPM_USB_STOP_TX_OPCODE 0x0a
-#define CPM_USB_RESTART_TX_OPCODE 0x0b
-#define CPM_USB_EP_SHIFT 5
-
-#endif  /* __FSL_QE_UDC_H */
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
deleted file mode 100644 (file)
index 57944ee..0000000
+++ /dev/null
@@ -1,2682 +0,0 @@
-/*
- * Copyright (C) 2004-2007,2011-2012 Freescale Semiconductor, Inc.
- * All rights reserved.
- *
- * Author: Li Yang <leoli@freescale.com>
- *         Jiang Bo <tanya.jiang@freescale.com>
- *
- * Description:
- * Freescale high-speed USB SOC DR module device controller driver.
- * This can be found on MPC8349E/MPC8313E/MPC5121E cpus.
- * The driver is previously named as mpc_udc.  Based on bare board
- * code from Dave Liu and Shlomi Gridish.
- *
- * 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.
- */
-
-#undef VERBOSE
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/mm.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/otg.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/fsl_devices.h>
-#include <linux/dmapool.h>
-#include <linux/delay.h>
-#include <linux/of_device.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/unaligned.h>
-#include <asm/dma.h>
-
-#include "fsl_usb2_udc.h"
-
-#define        DRIVER_DESC     "Freescale High-Speed USB SOC Device Controller driver"
-#define        DRIVER_AUTHOR   "Li Yang/Jiang Bo"
-#define        DRIVER_VERSION  "Apr 20, 2007"
-
-#define        DMA_ADDR_INVALID        (~(dma_addr_t)0)
-
-static const char driver_name[] = "fsl-usb2-udc";
-static const char driver_desc[] = DRIVER_DESC;
-
-static struct usb_dr_device *dr_regs;
-
-static struct usb_sys_interface *usb_sys_regs;
-
-/* it is initialized in probe()  */
-static struct fsl_udc *udc_controller = NULL;
-
-static const struct usb_endpoint_descriptor
-fsl_ep0_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-       .bEndpointAddress =     0,
-       .bmAttributes =         USB_ENDPOINT_XFER_CONTROL,
-       .wMaxPacketSize =       USB_MAX_CTRL_PAYLOAD,
-};
-
-static void fsl_ep_fifo_flush(struct usb_ep *_ep);
-
-#ifdef CONFIG_PPC32
-/*
- * On some SoCs, the USB controller registers can be big or little endian,
- * depending on the version of the chip. In order to be able to run the
- * same kernel binary on 2 different versions of an SoC, the BE/LE decision
- * must be made at run time. _fsl_readl and fsl_writel are pointers to the
- * BE or LE readl() and writel() functions, and fsl_readl() and fsl_writel()
- * call through those pointers. Platform code for SoCs that have BE USB
- * registers should set pdata->big_endian_mmio flag.
- *
- * This also applies to controller-to-cpu accessors for the USB descriptors,
- * since their endianness is also SoC dependant. Platform code for SoCs that
- * have BE USB descriptors should set pdata->big_endian_desc flag.
- */
-static u32 _fsl_readl_be(const unsigned __iomem *p)
-{
-       return in_be32(p);
-}
-
-static u32 _fsl_readl_le(const unsigned __iomem *p)
-{
-       return in_le32(p);
-}
-
-static void _fsl_writel_be(u32 v, unsigned __iomem *p)
-{
-       out_be32(p, v);
-}
-
-static void _fsl_writel_le(u32 v, unsigned __iomem *p)
-{
-       out_le32(p, v);
-}
-
-static u32 (*_fsl_readl)(const unsigned __iomem *p);
-static void (*_fsl_writel)(u32 v, unsigned __iomem *p);
-
-#define fsl_readl(p)           (*_fsl_readl)((p))
-#define fsl_writel(v, p)       (*_fsl_writel)((v), (p))
-
-static inline void fsl_set_accessors(struct fsl_usb2_platform_data *pdata)
-{
-       if (pdata->big_endian_mmio) {
-               _fsl_readl = _fsl_readl_be;
-               _fsl_writel = _fsl_writel_be;
-       } else {
-               _fsl_readl = _fsl_readl_le;
-               _fsl_writel = _fsl_writel_le;
-       }
-}
-
-static inline u32 cpu_to_hc32(const u32 x)
-{
-       return udc_controller->pdata->big_endian_desc
-               ? (__force u32)cpu_to_be32(x)
-               : (__force u32)cpu_to_le32(x);
-}
-
-static inline u32 hc32_to_cpu(const u32 x)
-{
-       return udc_controller->pdata->big_endian_desc
-               ? be32_to_cpu((__force __be32)x)
-               : le32_to_cpu((__force __le32)x);
-}
-#else /* !CONFIG_PPC32 */
-static inline void fsl_set_accessors(struct fsl_usb2_platform_data *pdata) {}
-
-#define fsl_readl(addr)                readl(addr)
-#define fsl_writel(val32, addr) writel(val32, addr)
-#define cpu_to_hc32(x)         cpu_to_le32(x)
-#define hc32_to_cpu(x)         le32_to_cpu(x)
-#endif /* CONFIG_PPC32 */
-
-/********************************************************************
- *     Internal Used Function
-********************************************************************/
-/*-----------------------------------------------------------------
- * done() - retire a request; caller blocked irqs
- * @status : request status to be set, only works when
- *     request is still in progress.
- *--------------------------------------------------------------*/
-static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
-{
-       struct fsl_udc *udc = NULL;
-       unsigned char stopped = ep->stopped;
-       struct ep_td_struct *curr_td, *next_td;
-       int j;
-
-       udc = (struct fsl_udc *)ep->udc;
-       /* Removed the req from fsl_ep->queue */
-       list_del_init(&req->queue);
-
-       /* req.status should be set as -EINPROGRESS in ep_queue() */
-       if (req->req.status == -EINPROGRESS)
-               req->req.status = status;
-       else
-               status = req->req.status;
-
-       /* Free dtd for the request */
-       next_td = req->head;
-       for (j = 0; j < req->dtd_count; j++) {
-               curr_td = next_td;
-               if (j != req->dtd_count - 1) {
-                       next_td = curr_td->next_td_virt;
-               }
-               dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
-       }
-
-       usb_gadget_unmap_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
-
-       if (status && (status != -ESHUTDOWN))
-               VDBG("complete %s req %p stat %d len %u/%u",
-                       ep->ep.name, &req->req, status,
-                       req->req.actual, req->req.length);
-
-       ep->stopped = 1;
-
-       spin_unlock(&ep->udc->lock);
-       /* complete() is from gadget layer,
-        * eg fsg->bulk_in_complete() */
-       if (req->req.complete)
-               req->req.complete(&ep->ep, &req->req);
-
-       spin_lock(&ep->udc->lock);
-       ep->stopped = stopped;
-}
-
-/*-----------------------------------------------------------------
- * nuke(): delete all requests related to this ep
- * called with spinlock held
- *--------------------------------------------------------------*/
-static void nuke(struct fsl_ep *ep, int status)
-{
-       ep->stopped = 1;
-
-       /* Flush fifo */
-       fsl_ep_fifo_flush(&ep->ep);
-
-       /* Whether this eq has request linked */
-       while (!list_empty(&ep->queue)) {
-               struct fsl_req *req = NULL;
-
-               req = list_entry(ep->queue.next, struct fsl_req, queue);
-               done(ep, req, status);
-       }
-}
-
-/*------------------------------------------------------------------
-       Internal Hardware related function
- ------------------------------------------------------------------*/
-
-static int dr_controller_setup(struct fsl_udc *udc)
-{
-       unsigned int tmp, portctrl, ep_num;
-       unsigned int max_no_of_ep;
-       unsigned int ctrl;
-       unsigned long timeout;
-
-#define FSL_UDC_RESET_TIMEOUT 1000
-
-       /* Config PHY interface */
-       portctrl = fsl_readl(&dr_regs->portsc1);
-       portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH);
-       switch (udc->phy_mode) {
-       case FSL_USB2_PHY_ULPI:
-               if (udc->pdata->have_sysif_regs) {
-                       if (udc->pdata->controller_ver) {
-                               /* controller version 1.6 or above */
-                               ctrl = __raw_readl(&usb_sys_regs->control);
-                               ctrl &= ~USB_CTRL_UTMI_PHY_EN;
-                               ctrl |= USB_CTRL_USB_EN;
-                               __raw_writel(ctrl, &usb_sys_regs->control);
-                       }
-               }
-               portctrl |= PORTSCX_PTS_ULPI;
-               break;
-       case FSL_USB2_PHY_UTMI_WIDE:
-               portctrl |= PORTSCX_PTW_16BIT;
-               /* fall through */
-       case FSL_USB2_PHY_UTMI:
-               if (udc->pdata->have_sysif_regs) {
-                       if (udc->pdata->controller_ver) {
-                               /* controller version 1.6 or above */
-                               ctrl = __raw_readl(&usb_sys_regs->control);
-                               ctrl |= (USB_CTRL_UTMI_PHY_EN |
-                                       USB_CTRL_USB_EN);
-                               __raw_writel(ctrl, &usb_sys_regs->control);
-                               mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI
-                                       PHY CLK to become stable - 10ms*/
-                       }
-               }
-               portctrl |= PORTSCX_PTS_UTMI;
-               break;
-       case FSL_USB2_PHY_SERIAL:
-               portctrl |= PORTSCX_PTS_FSLS;
-               break;
-       default:
-               return -EINVAL;
-       }
-       fsl_writel(portctrl, &dr_regs->portsc1);
-
-       /* Stop and reset the usb controller */
-       tmp = fsl_readl(&dr_regs->usbcmd);
-       tmp &= ~USB_CMD_RUN_STOP;
-       fsl_writel(tmp, &dr_regs->usbcmd);
-
-       tmp = fsl_readl(&dr_regs->usbcmd);
-       tmp |= USB_CMD_CTRL_RESET;
-       fsl_writel(tmp, &dr_regs->usbcmd);
-
-       /* Wait for reset to complete */
-       timeout = jiffies + FSL_UDC_RESET_TIMEOUT;
-       while (fsl_readl(&dr_regs->usbcmd) & USB_CMD_CTRL_RESET) {
-               if (time_after(jiffies, timeout)) {
-                       ERR("udc reset timeout!\n");
-                       return -ETIMEDOUT;
-               }
-               cpu_relax();
-       }
-
-       /* Set the controller as device mode */
-       tmp = fsl_readl(&dr_regs->usbmode);
-       tmp &= ~USB_MODE_CTRL_MODE_MASK;        /* clear mode bits */
-       tmp |= USB_MODE_CTRL_MODE_DEVICE;
-       /* Disable Setup Lockout */
-       tmp |= USB_MODE_SETUP_LOCK_OFF;
-       if (udc->pdata->es)
-               tmp |= USB_MODE_ES;
-       fsl_writel(tmp, &dr_regs->usbmode);
-
-       /* Clear the setup status */
-       fsl_writel(0, &dr_regs->usbsts);
-
-       tmp = udc->ep_qh_dma;
-       tmp &= USB_EP_LIST_ADDRESS_MASK;
-       fsl_writel(tmp, &dr_regs->endpointlistaddr);
-
-       VDBG("vir[qh_base] is %p phy[qh_base] is 0x%8x reg is 0x%8x",
-               udc->ep_qh, (int)tmp,
-               fsl_readl(&dr_regs->endpointlistaddr));
-
-       max_no_of_ep = (0x0000001F & fsl_readl(&dr_regs->dccparams));
-       for (ep_num = 1; ep_num < max_no_of_ep; ep_num++) {
-               tmp = fsl_readl(&dr_regs->endptctrl[ep_num]);
-               tmp &= ~(EPCTRL_TX_TYPE | EPCTRL_RX_TYPE);
-               tmp |= (EPCTRL_EP_TYPE_BULK << EPCTRL_TX_EP_TYPE_SHIFT)
-               | (EPCTRL_EP_TYPE_BULK << EPCTRL_RX_EP_TYPE_SHIFT);
-               fsl_writel(tmp, &dr_regs->endptctrl[ep_num]);
-       }
-       /* Config control enable i/o output, cpu endian register */
-#ifndef CONFIG_ARCH_MXC
-       if (udc->pdata->have_sysif_regs) {
-               ctrl = __raw_readl(&usb_sys_regs->control);
-               ctrl |= USB_CTRL_IOENB;
-               __raw_writel(ctrl, &usb_sys_regs->control);
-       }
-#endif
-
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
-       /* Turn on cache snooping hardware, since some PowerPC platforms
-        * wholly rely on hardware to deal with cache coherent. */
-
-       if (udc->pdata->have_sysif_regs) {
-               /* Setup Snooping for all the 4GB space */
-               tmp = SNOOP_SIZE_2GB;   /* starts from 0x0, size 2G */
-               __raw_writel(tmp, &usb_sys_regs->snoop1);
-               tmp |= 0x80000000;      /* starts from 0x8000000, size 2G */
-               __raw_writel(tmp, &usb_sys_regs->snoop2);
-       }
-#endif
-
-       return 0;
-}
-
-/* Enable DR irq and set controller to run state */
-static void dr_controller_run(struct fsl_udc *udc)
-{
-       u32 temp;
-
-       /* Enable DR irq reg */
-       temp = USB_INTR_INT_EN | USB_INTR_ERR_INT_EN
-               | USB_INTR_PTC_DETECT_EN | USB_INTR_RESET_EN
-               | USB_INTR_DEVICE_SUSPEND | USB_INTR_SYS_ERR_EN;
-
-       fsl_writel(temp, &dr_regs->usbintr);
-
-       /* Clear stopped bit */
-       udc->stopped = 0;
-
-       /* Set the controller as device mode */
-       temp = fsl_readl(&dr_regs->usbmode);
-       temp |= USB_MODE_CTRL_MODE_DEVICE;
-       fsl_writel(temp, &dr_regs->usbmode);
-
-       /* Set controller to Run */
-       temp = fsl_readl(&dr_regs->usbcmd);
-       temp |= USB_CMD_RUN_STOP;
-       fsl_writel(temp, &dr_regs->usbcmd);
-}
-
-static void dr_controller_stop(struct fsl_udc *udc)
-{
-       unsigned int tmp;
-
-       pr_debug("%s\n", __func__);
-
-       /* if we're in OTG mode, and the Host is currently using the port,
-        * stop now and don't rip the controller out from under the
-        * ehci driver
-        */
-       if (udc->gadget.is_otg) {
-               if (!(fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID)) {
-                       pr_debug("udc: Leaving early\n");
-                       return;
-               }
-       }
-
-       /* disable all INTR */
-       fsl_writel(0, &dr_regs->usbintr);
-
-       /* Set stopped bit for isr */
-       udc->stopped = 1;
-
-       /* disable IO output */
-/*     usb_sys_regs->control = 0; */
-
-       /* set controller to Stop */
-       tmp = fsl_readl(&dr_regs->usbcmd);
-       tmp &= ~USB_CMD_RUN_STOP;
-       fsl_writel(tmp, &dr_regs->usbcmd);
-}
-
-static void dr_ep_setup(unsigned char ep_num, unsigned char dir,
-                       unsigned char ep_type)
-{
-       unsigned int tmp_epctrl = 0;
-
-       tmp_epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
-       if (dir) {
-               if (ep_num)
-                       tmp_epctrl |= EPCTRL_TX_DATA_TOGGLE_RST;
-               tmp_epctrl |= EPCTRL_TX_ENABLE;
-               tmp_epctrl &= ~EPCTRL_TX_TYPE;
-               tmp_epctrl |= ((unsigned int)(ep_type)
-                               << EPCTRL_TX_EP_TYPE_SHIFT);
-       } else {
-               if (ep_num)
-                       tmp_epctrl |= EPCTRL_RX_DATA_TOGGLE_RST;
-               tmp_epctrl |= EPCTRL_RX_ENABLE;
-               tmp_epctrl &= ~EPCTRL_RX_TYPE;
-               tmp_epctrl |= ((unsigned int)(ep_type)
-                               << EPCTRL_RX_EP_TYPE_SHIFT);
-       }
-
-       fsl_writel(tmp_epctrl, &dr_regs->endptctrl[ep_num]);
-}
-
-static void
-dr_ep_change_stall(unsigned char ep_num, unsigned char dir, int value)
-{
-       u32 tmp_epctrl = 0;
-
-       tmp_epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
-
-       if (value) {
-               /* set the stall bit */
-               if (dir)
-                       tmp_epctrl |= EPCTRL_TX_EP_STALL;
-               else
-                       tmp_epctrl |= EPCTRL_RX_EP_STALL;
-       } else {
-               /* clear the stall bit and reset data toggle */
-               if (dir) {
-                       tmp_epctrl &= ~EPCTRL_TX_EP_STALL;
-                       tmp_epctrl |= EPCTRL_TX_DATA_TOGGLE_RST;
-               } else {
-                       tmp_epctrl &= ~EPCTRL_RX_EP_STALL;
-                       tmp_epctrl |= EPCTRL_RX_DATA_TOGGLE_RST;
-               }
-       }
-       fsl_writel(tmp_epctrl, &dr_regs->endptctrl[ep_num]);
-}
-
-/* Get stall status of a specific ep
-   Return: 0: not stalled; 1:stalled */
-static int dr_ep_get_stall(unsigned char ep_num, unsigned char dir)
-{
-       u32 epctrl;
-
-       epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
-       if (dir)
-               return (epctrl & EPCTRL_TX_EP_STALL) ? 1 : 0;
-       else
-               return (epctrl & EPCTRL_RX_EP_STALL) ? 1 : 0;
-}
-
-/********************************************************************
-       Internal Structure Build up functions
-********************************************************************/
-
-/*------------------------------------------------------------------
-* struct_ep_qh_setup(): set the Endpoint Capabilites field of QH
- * @zlt: Zero Length Termination Select (1: disable; 0: enable)
- * @mult: Mult field
- ------------------------------------------------------------------*/
-static void struct_ep_qh_setup(struct fsl_udc *udc, unsigned char ep_num,
-               unsigned char dir, unsigned char ep_type,
-               unsigned int max_pkt_len,
-               unsigned int zlt, unsigned char mult)
-{
-       struct ep_queue_head *p_QH = &udc->ep_qh[2 * ep_num + dir];
-       unsigned int tmp = 0;
-
-       /* set the Endpoint Capabilites in QH */
-       switch (ep_type) {
-       case USB_ENDPOINT_XFER_CONTROL:
-               /* Interrupt On Setup (IOS). for control ep  */
-               tmp = (max_pkt_len << EP_QUEUE_HEAD_MAX_PKT_LEN_POS)
-                       | EP_QUEUE_HEAD_IOS;
-               break;
-       case USB_ENDPOINT_XFER_ISOC:
-               tmp = (max_pkt_len << EP_QUEUE_HEAD_MAX_PKT_LEN_POS)
-                       | (mult << EP_QUEUE_HEAD_MULT_POS);
-               break;
-       case USB_ENDPOINT_XFER_BULK:
-       case USB_ENDPOINT_XFER_INT:
-               tmp = max_pkt_len << EP_QUEUE_HEAD_MAX_PKT_LEN_POS;
-               break;
-       default:
-               VDBG("error ep type is %d", ep_type);
-               return;
-       }
-       if (zlt)
-               tmp |= EP_QUEUE_HEAD_ZLT_SEL;
-
-       p_QH->max_pkt_length = cpu_to_hc32(tmp);
-       p_QH->next_dtd_ptr = 1;
-       p_QH->size_ioc_int_sts = 0;
-}
-
-/* Setup qh structure and ep register for ep0. */
-static void ep0_setup(struct fsl_udc *udc)
-{
-       /* the intialization of an ep includes: fields in QH, Regs,
-        * fsl_ep struct */
-       struct_ep_qh_setup(udc, 0, USB_RECV, USB_ENDPOINT_XFER_CONTROL,
-                       USB_MAX_CTRL_PAYLOAD, 0, 0);
-       struct_ep_qh_setup(udc, 0, USB_SEND, USB_ENDPOINT_XFER_CONTROL,
-                       USB_MAX_CTRL_PAYLOAD, 0, 0);
-       dr_ep_setup(0, USB_RECV, USB_ENDPOINT_XFER_CONTROL);
-       dr_ep_setup(0, USB_SEND, USB_ENDPOINT_XFER_CONTROL);
-
-       return;
-
-}
-
-/***********************************************************************
-               Endpoint Management Functions
-***********************************************************************/
-
-/*-------------------------------------------------------------------------
- * when configurations are set, or when interface settings change
- * for example the do_set_interface() in gadget layer,
- * the driver will enable or disable the relevant endpoints
- * ep0 doesn't use this routine. It is always enabled.
--------------------------------------------------------------------------*/
-static int fsl_ep_enable(struct usb_ep *_ep,
-               const struct usb_endpoint_descriptor *desc)
-{
-       struct fsl_udc *udc = NULL;
-       struct fsl_ep *ep = NULL;
-       unsigned short max = 0;
-       unsigned char mult = 0, zlt;
-       int retval = -EINVAL;
-       unsigned long flags = 0;
-
-       ep = container_of(_ep, struct fsl_ep, ep);
-
-       /* catch various bogus parameters */
-       if (!_ep || !desc
-                       || (desc->bDescriptorType != USB_DT_ENDPOINT))
-               return -EINVAL;
-
-       udc = ep->udc;
-
-       if (!udc->driver || (udc->gadget.speed == USB_SPEED_UNKNOWN))
-               return -ESHUTDOWN;
-
-       max = usb_endpoint_maxp(desc);
-
-       /* Disable automatic zlp generation.  Driver is responsible to indicate
-        * explicitly through req->req.zero.  This is needed to enable multi-td
-        * request. */
-       zlt = 1;
-
-       /* Assume the max packet size from gadget is always correct */
-       switch (desc->bmAttributes & 0x03) {
-       case USB_ENDPOINT_XFER_CONTROL:
-       case USB_ENDPOINT_XFER_BULK:
-       case USB_ENDPOINT_XFER_INT:
-               /* mult = 0.  Execute N Transactions as demonstrated by
-                * the USB variable length packet protocol where N is
-                * computed using the Maximum Packet Length (dQH) and
-                * the Total Bytes field (dTD) */
-               mult = 0;
-               break;
-       case USB_ENDPOINT_XFER_ISOC:
-               /* Calculate transactions needed for high bandwidth iso */
-               mult = (unsigned char)(1 + ((max >> 11) & 0x03));
-               max = max & 0x7ff;      /* bit 0~10 */
-               /* 3 transactions at most */
-               if (mult > 3)
-                       goto en_done;
-               break;
-       default:
-               goto en_done;
-       }
-
-       spin_lock_irqsave(&udc->lock, flags);
-       ep->ep.maxpacket = max;
-       ep->ep.desc = desc;
-       ep->stopped = 0;
-
-       /* Controller related setup */
-       /* Init EPx Queue Head (Ep Capabilites field in QH
-        * according to max, zlt, mult) */
-       struct_ep_qh_setup(udc, (unsigned char) ep_index(ep),
-                       (unsigned char) ((desc->bEndpointAddress & USB_DIR_IN)
-                                       ?  USB_SEND : USB_RECV),
-                       (unsigned char) (desc->bmAttributes
-                                       & USB_ENDPOINT_XFERTYPE_MASK),
-                       max, zlt, mult);
-
-       /* Init endpoint ctrl register */
-       dr_ep_setup((unsigned char) ep_index(ep),
-                       (unsigned char) ((desc->bEndpointAddress & USB_DIR_IN)
-                                       ? USB_SEND : USB_RECV),
-                       (unsigned char) (desc->bmAttributes
-                                       & USB_ENDPOINT_XFERTYPE_MASK));
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-       retval = 0;
-
-       VDBG("enabled %s (ep%d%s) maxpacket %d",ep->ep.name,
-                       ep->ep.desc->bEndpointAddress & 0x0f,
-                       (desc->bEndpointAddress & USB_DIR_IN)
-                               ? "in" : "out", max);
-en_done:
-       return retval;
-}
-
-/*---------------------------------------------------------------------
- * @ep : the ep being unconfigured. May not be ep0
- * Any pending and uncomplete req will complete with status (-ESHUTDOWN)
-*---------------------------------------------------------------------*/
-static int fsl_ep_disable(struct usb_ep *_ep)
-{
-       struct fsl_udc *udc = NULL;
-       struct fsl_ep *ep = NULL;
-       unsigned long flags = 0;
-       u32 epctrl;
-       int ep_num;
-
-       ep = container_of(_ep, struct fsl_ep, ep);
-       if (!_ep || !ep->ep.desc) {
-               VDBG("%s not enabled", _ep ? ep->ep.name : NULL);
-               return -EINVAL;
-       }
-
-       /* disable ep on controller */
-       ep_num = ep_index(ep);
-       epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
-       if (ep_is_in(ep)) {
-               epctrl &= ~(EPCTRL_TX_ENABLE | EPCTRL_TX_TYPE);
-               epctrl |= EPCTRL_EP_TYPE_BULK << EPCTRL_TX_EP_TYPE_SHIFT;
-       } else {
-               epctrl &= ~(EPCTRL_RX_ENABLE | EPCTRL_TX_TYPE);
-               epctrl |= EPCTRL_EP_TYPE_BULK << EPCTRL_RX_EP_TYPE_SHIFT;
-       }
-       fsl_writel(epctrl, &dr_regs->endptctrl[ep_num]);
-
-       udc = (struct fsl_udc *)ep->udc;
-       spin_lock_irqsave(&udc->lock, flags);
-
-       /* nuke all pending requests (does flush) */
-       nuke(ep, -ESHUTDOWN);
-
-       ep->ep.desc = NULL;
-       ep->stopped = 1;
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       VDBG("disabled %s OK", _ep->name);
-       return 0;
-}
-
-/*---------------------------------------------------------------------
- * allocate a request object used by this endpoint
- * the main operation is to insert the req->queue to the eq->queue
- * Returns the request, or null if one could not be allocated
-*---------------------------------------------------------------------*/
-static struct usb_request *
-fsl_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
-{
-       struct fsl_req *req = NULL;
-
-       req = kzalloc(sizeof *req, gfp_flags);
-       if (!req)
-               return NULL;
-
-       req->req.dma = DMA_ADDR_INVALID;
-       INIT_LIST_HEAD(&req->queue);
-
-       return &req->req;
-}
-
-static void fsl_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct fsl_req *req = NULL;
-
-       req = container_of(_req, struct fsl_req, req);
-
-       if (_req)
-               kfree(req);
-}
-
-/* Actually add a dTD chain to an empty dQH and let go */
-static void fsl_prime_ep(struct fsl_ep *ep, struct ep_td_struct *td)
-{
-       struct ep_queue_head *qh = get_qh_by_ep(ep);
-
-       /* Write dQH next pointer and terminate bit to 0 */
-       qh->next_dtd_ptr = cpu_to_hc32(td->td_dma
-                       & EP_QUEUE_HEAD_NEXT_POINTER_MASK);
-
-       /* Clear active and halt bit */
-       qh->size_ioc_int_sts &= cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE
-                                       | EP_QUEUE_HEAD_STATUS_HALT));
-
-       /* Ensure that updates to the QH will occur before priming. */
-       wmb();
-
-       /* Prime endpoint by writing correct bit to ENDPTPRIME */
-       fsl_writel(ep_is_in(ep) ? (1 << (ep_index(ep) + 16))
-                       : (1 << (ep_index(ep))), &dr_regs->endpointprime);
-}
-
-/* Add dTD chain to the dQH of an EP */
-static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
-{
-       u32 temp, bitmask, tmp_stat;
-
-       /* VDBG("QH addr Register 0x%8x", dr_regs->endpointlistaddr);
-       VDBG("ep_qh[%d] addr is 0x%8x", i, (u32)&(ep->udc->ep_qh[i])); */
-
-       bitmask = ep_is_in(ep)
-               ? (1 << (ep_index(ep) + 16))
-               : (1 << (ep_index(ep)));
-
-       /* check if the pipe is empty */
-       if (!(list_empty(&ep->queue)) && !(ep_index(ep) == 0)) {
-               /* Add td to the end */
-               struct fsl_req *lastreq;
-               lastreq = list_entry(ep->queue.prev, struct fsl_req, queue);
-               lastreq->tail->next_td_ptr =
-                       cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK);
-               /* Ensure dTD's next dtd pointer to be updated */
-               wmb();
-               /* Read prime bit, if 1 goto done */
-               if (fsl_readl(&dr_regs->endpointprime) & bitmask)
-                       return;
-
-               do {
-                       /* Set ATDTW bit in USBCMD */
-                       temp = fsl_readl(&dr_regs->usbcmd);
-                       fsl_writel(temp | USB_CMD_ATDTW, &dr_regs->usbcmd);
-
-                       /* Read correct status bit */
-                       tmp_stat = fsl_readl(&dr_regs->endptstatus) & bitmask;
-
-               } while (!(fsl_readl(&dr_regs->usbcmd) & USB_CMD_ATDTW));
-
-               /* Write ATDTW bit to 0 */
-               temp = fsl_readl(&dr_regs->usbcmd);
-               fsl_writel(temp & ~USB_CMD_ATDTW, &dr_regs->usbcmd);
-
-               if (tmp_stat)
-                       return;
-       }
-
-       fsl_prime_ep(ep, req->head);
-}
-
-/* Fill in the dTD structure
- * @req: request that the transfer belongs to
- * @length: return actually data length of the dTD
- * @dma: return dma address of the dTD
- * @is_last: return flag if it is the last dTD of the request
- * return: pointer to the built dTD */
-static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
-               dma_addr_t *dma, int *is_last, gfp_t gfp_flags)
-{
-       u32 swap_temp;
-       struct ep_td_struct *dtd;
-
-       /* how big will this transfer be? */
-       *length = min(req->req.length - req->req.actual,
-                       (unsigned)EP_MAX_LENGTH_TRANSFER);
-
-       dtd = dma_pool_alloc(udc_controller->td_pool, gfp_flags, dma);
-       if (dtd == NULL)
-               return dtd;
-
-       dtd->td_dma = *dma;
-       /* Clear reserved field */
-       swap_temp = hc32_to_cpu(dtd->size_ioc_sts);
-       swap_temp &= ~DTD_RESERVED_FIELDS;
-       dtd->size_ioc_sts = cpu_to_hc32(swap_temp);
-
-       /* Init all of buffer page pointers */
-       swap_temp = (u32) (req->req.dma + req->req.actual);
-       dtd->buff_ptr0 = cpu_to_hc32(swap_temp);
-       dtd->buff_ptr1 = cpu_to_hc32(swap_temp + 0x1000);
-       dtd->buff_ptr2 = cpu_to_hc32(swap_temp + 0x2000);
-       dtd->buff_ptr3 = cpu_to_hc32(swap_temp + 0x3000);
-       dtd->buff_ptr4 = cpu_to_hc32(swap_temp + 0x4000);
-
-       req->req.actual += *length;
-
-       /* zlp is needed if req->req.zero is set */
-       if (req->req.zero) {
-               if (*length == 0 || (*length % req->ep->ep.maxpacket) != 0)
-                       *is_last = 1;
-               else
-                       *is_last = 0;
-       } else if (req->req.length == req->req.actual)
-               *is_last = 1;
-       else
-               *is_last = 0;
-
-       if ((*is_last) == 0)
-               VDBG("multi-dtd request!");
-       /* Fill in the transfer size; set active bit */
-       swap_temp = ((*length << DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE);
-
-       /* Enable interrupt for the last dtd of a request */
-       if (*is_last && !req->req.no_interrupt)
-               swap_temp |= DTD_IOC;
-
-       dtd->size_ioc_sts = cpu_to_hc32(swap_temp);
-
-       mb();
-
-       VDBG("length = %d address= 0x%x", *length, (int)*dma);
-
-       return dtd;
-}
-
-/* Generate dtd chain for a request */
-static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags)
-{
-       unsigned        count;
-       int             is_last;
-       int             is_first =1;
-       struct ep_td_struct     *last_dtd = NULL, *dtd;
-       dma_addr_t dma;
-
-       do {
-               dtd = fsl_build_dtd(req, &count, &dma, &is_last, gfp_flags);
-               if (dtd == NULL)
-                       return -ENOMEM;
-
-               if (is_first) {
-                       is_first = 0;
-                       req->head = dtd;
-               } else {
-                       last_dtd->next_td_ptr = cpu_to_hc32(dma);
-                       last_dtd->next_td_virt = dtd;
-               }
-               last_dtd = dtd;
-
-               req->dtd_count++;
-       } while (!is_last);
-
-       dtd->next_td_ptr = cpu_to_hc32(DTD_NEXT_TERMINATE);
-
-       req->tail = dtd;
-
-       return 0;
-}
-
-/* queues (submits) an I/O request to an endpoint */
-static int
-fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
-{
-       struct fsl_ep *ep = container_of(_ep, struct fsl_ep, ep);
-       struct fsl_req *req = container_of(_req, struct fsl_req, req);
-       struct fsl_udc *udc;
-       unsigned long flags;
-       int ret;
-
-       /* catch various bogus parameters */
-       if (!_req || !req->req.complete || !req->req.buf
-                       || !list_empty(&req->queue)) {
-               VDBG("%s, bad params", __func__);
-               return -EINVAL;
-       }
-       if (unlikely(!_ep || !ep->ep.desc)) {
-               VDBG("%s, bad ep", __func__);
-               return -EINVAL;
-       }
-       if (usb_endpoint_xfer_isoc(ep->ep.desc)) {
-               if (req->req.length > ep->ep.maxpacket)
-                       return -EMSGSIZE;
-       }
-
-       udc = ep->udc;
-       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       req->ep = ep;
-
-       ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
-       if (ret)
-               return ret;
-
-       req->req.status = -EINPROGRESS;
-       req->req.actual = 0;
-       req->dtd_count = 0;
-
-       /* build dtds and push them to device queue */
-       if (!fsl_req_to_dtd(req, gfp_flags)) {
-               spin_lock_irqsave(&udc->lock, flags);
-               fsl_queue_td(ep, req);
-       } else {
-               return -ENOMEM;
-       }
-
-       /* irq handler advances the queue */
-       if (req != NULL)
-               list_add_tail(&req->queue, &ep->queue);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-/* dequeues (cancels, unlinks) an I/O request from an endpoint */
-static int fsl_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct fsl_ep *ep = container_of(_ep, struct fsl_ep, ep);
-       struct fsl_req *req;
-       unsigned long flags;
-       int ep_num, stopped, ret = 0;
-       u32 epctrl;
-
-       if (!_ep || !_req)
-               return -EINVAL;
-
-       spin_lock_irqsave(&ep->udc->lock, flags);
-       stopped = ep->stopped;
-
-       /* Stop the ep before we deal with the queue */
-       ep->stopped = 1;
-       ep_num = ep_index(ep);
-       epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
-       if (ep_is_in(ep))
-               epctrl &= ~EPCTRL_TX_ENABLE;
-       else
-               epctrl &= ~EPCTRL_RX_ENABLE;
-       fsl_writel(epctrl, &dr_regs->endptctrl[ep_num]);
-
-       /* make sure it's actually queued on this endpoint */
-       list_for_each_entry(req, &ep->queue, queue) {
-               if (&req->req == _req)
-                       break;
-       }
-       if (&req->req != _req) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       /* The request is in progress, or completed but not dequeued */
-       if (ep->queue.next == &req->queue) {
-               _req->status = -ECONNRESET;
-               fsl_ep_fifo_flush(_ep); /* flush current transfer */
-
-               /* The request isn't the last request in this ep queue */
-               if (req->queue.next != &ep->queue) {
-                       struct fsl_req *next_req;
-
-                       next_req = list_entry(req->queue.next, struct fsl_req,
-                                       queue);
-
-                       /* prime with dTD of next request */
-                       fsl_prime_ep(ep, next_req->head);
-               }
-       /* The request hasn't been processed, patch up the TD chain */
-       } else {
-               struct fsl_req *prev_req;
-
-               prev_req = list_entry(req->queue.prev, struct fsl_req, queue);
-               prev_req->tail->next_td_ptr = req->tail->next_td_ptr;
-       }
-
-       done(ep, req, -ECONNRESET);
-
-       /* Enable EP */
-out:   epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
-       if (ep_is_in(ep))
-               epctrl |= EPCTRL_TX_ENABLE;
-       else
-               epctrl |= EPCTRL_RX_ENABLE;
-       fsl_writel(epctrl, &dr_regs->endptctrl[ep_num]);
-       ep->stopped = stopped;
-
-       spin_unlock_irqrestore(&ep->udc->lock, flags);
-       return ret;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*-----------------------------------------------------------------
- * modify the endpoint halt feature
- * @ep: the non-isochronous endpoint being stalled
- * @value: 1--set halt  0--clear halt
- * Returns zero, or a negative error code.
-*----------------------------------------------------------------*/
-static int fsl_ep_set_halt(struct usb_ep *_ep, int value)
-{
-       struct fsl_ep *ep = NULL;
-       unsigned long flags = 0;
-       int status = -EOPNOTSUPP;       /* operation not supported */
-       unsigned char ep_dir = 0, ep_num = 0;
-       struct fsl_udc *udc = NULL;
-
-       ep = container_of(_ep, struct fsl_ep, ep);
-       udc = ep->udc;
-       if (!_ep || !ep->ep.desc) {
-               status = -EINVAL;
-               goto out;
-       }
-
-       if (usb_endpoint_xfer_isoc(ep->ep.desc)) {
-               status = -EOPNOTSUPP;
-               goto out;
-       }
-
-       /* Attempt to halt IN ep will fail if any transfer requests
-        * are still queue */
-       if (value && ep_is_in(ep) && !list_empty(&ep->queue)) {
-               status = -EAGAIN;
-               goto out;
-       }
-
-       status = 0;
-       ep_dir = ep_is_in(ep) ? USB_SEND : USB_RECV;
-       ep_num = (unsigned char)(ep_index(ep));
-       spin_lock_irqsave(&ep->udc->lock, flags);
-       dr_ep_change_stall(ep_num, ep_dir, value);
-       spin_unlock_irqrestore(&ep->udc->lock, flags);
-
-       if (ep_index(ep) == 0) {
-               udc->ep0_state = WAIT_FOR_SETUP;
-               udc->ep0_dir = 0;
-       }
-out:
-       VDBG(" %s %s halt stat %d", ep->ep.name,
-                       value ?  "set" : "clear", status);
-
-       return status;
-}
-
-static int fsl_ep_fifo_status(struct usb_ep *_ep)
-{
-       struct fsl_ep *ep;
-       struct fsl_udc *udc;
-       int size = 0;
-       u32 bitmask;
-       struct ep_queue_head *qh;
-
-       ep = container_of(_ep, struct fsl_ep, ep);
-       if (!_ep || (!ep->ep.desc && ep_index(ep) != 0))
-               return -ENODEV;
-
-       udc = (struct fsl_udc *)ep->udc;
-
-       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       qh = get_qh_by_ep(ep);
-
-       bitmask = (ep_is_in(ep)) ? (1 << (ep_index(ep) + 16)) :
-           (1 << (ep_index(ep)));
-
-       if (fsl_readl(&dr_regs->endptstatus) & bitmask)
-               size = (qh->size_ioc_int_sts & DTD_PACKET_SIZE)
-                   >> DTD_LENGTH_BIT_POS;
-
-       pr_debug("%s %u\n", __func__, size);
-       return size;
-}
-
-static void fsl_ep_fifo_flush(struct usb_ep *_ep)
-{
-       struct fsl_ep *ep;
-       int ep_num, ep_dir;
-       u32 bits;
-       unsigned long timeout;
-#define FSL_UDC_FLUSH_TIMEOUT 1000
-
-       if (!_ep) {
-               return;
-       } else {
-               ep = container_of(_ep, struct fsl_ep, ep);
-               if (!ep->ep.desc)
-                       return;
-       }
-       ep_num = ep_index(ep);
-       ep_dir = ep_is_in(ep) ? USB_SEND : USB_RECV;
-
-       if (ep_num == 0)
-               bits = (1 << 16) | 1;
-       else if (ep_dir == USB_SEND)
-               bits = 1 << (16 + ep_num);
-       else
-               bits = 1 << ep_num;
-
-       timeout = jiffies + FSL_UDC_FLUSH_TIMEOUT;
-       do {
-               fsl_writel(bits, &dr_regs->endptflush);
-
-               /* Wait until flush complete */
-               while (fsl_readl(&dr_regs->endptflush)) {
-                       if (time_after(jiffies, timeout)) {
-                               ERR("ep flush timeout\n");
-                               return;
-                       }
-                       cpu_relax();
-               }
-               /* See if we need to flush again */
-       } while (fsl_readl(&dr_regs->endptstatus) & bits);
-}
-
-static struct usb_ep_ops fsl_ep_ops = {
-       .enable = fsl_ep_enable,
-       .disable = fsl_ep_disable,
-
-       .alloc_request = fsl_alloc_request,
-       .free_request = fsl_free_request,
-
-       .queue = fsl_ep_queue,
-       .dequeue = fsl_ep_dequeue,
-
-       .set_halt = fsl_ep_set_halt,
-       .fifo_status = fsl_ep_fifo_status,
-       .fifo_flush = fsl_ep_fifo_flush,        /* flush fifo */
-};
-
-/*-------------------------------------------------------------------------
-               Gadget Driver Layer Operations
--------------------------------------------------------------------------*/
-
-/*----------------------------------------------------------------------
- * Get the current frame number (from DR frame_index Reg )
- *----------------------------------------------------------------------*/
-static int fsl_get_frame(struct usb_gadget *gadget)
-{
-       return (int)(fsl_readl(&dr_regs->frindex) & USB_FRINDEX_MASKS);
-}
-
-/*-----------------------------------------------------------------------
- * Tries to wake up the host connected to this gadget
- -----------------------------------------------------------------------*/
-static int fsl_wakeup(struct usb_gadget *gadget)
-{
-       struct fsl_udc *udc = container_of(gadget, struct fsl_udc, gadget);
-       u32 portsc;
-
-       /* Remote wakeup feature not enabled by host */
-       if (!udc->remote_wakeup)
-               return -ENOTSUPP;
-
-       portsc = fsl_readl(&dr_regs->portsc1);
-       /* not suspended? */
-       if (!(portsc & PORTSCX_PORT_SUSPEND))
-               return 0;
-       /* trigger force resume */
-       portsc |= PORTSCX_PORT_FORCE_RESUME;
-       fsl_writel(portsc, &dr_regs->portsc1);
-       return 0;
-}
-
-static int can_pullup(struct fsl_udc *udc)
-{
-       return udc->driver && udc->softconnect && udc->vbus_active;
-}
-
-/* Notify controller that VBUS is powered, Called by whatever
-   detects VBUS sessions */
-static int fsl_vbus_session(struct usb_gadget *gadget, int is_active)
-{
-       struct fsl_udc  *udc;
-       unsigned long   flags;
-
-       udc = container_of(gadget, struct fsl_udc, gadget);
-       spin_lock_irqsave(&udc->lock, flags);
-       VDBG("VBUS %s", is_active ? "on" : "off");
-       udc->vbus_active = (is_active != 0);
-       if (can_pullup(udc))
-               fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
-                               &dr_regs->usbcmd);
-       else
-               fsl_writel((fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP),
-                               &dr_regs->usbcmd);
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return 0;
-}
-
-/* constrain controller's VBUS power usage
- * This call is used by gadget drivers during SET_CONFIGURATION calls,
- * reporting how much power the device may consume.  For example, this
- * could affect how quickly batteries are recharged.
- *
- * Returns zero on success, else negative errno.
- */
-static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA)
-{
-       struct fsl_udc *udc;
-
-       udc = container_of(gadget, struct fsl_udc, gadget);
-       if (!IS_ERR_OR_NULL(udc->transceiver))
-               return usb_phy_set_power(udc->transceiver, mA);
-       return -ENOTSUPP;
-}
-
-/* Change Data+ pullup status
- * this func is used by usb_gadget_connect/disconnet
- */
-static int fsl_pullup(struct usb_gadget *gadget, int is_on)
-{
-       struct fsl_udc *udc;
-
-       udc = container_of(gadget, struct fsl_udc, gadget);
-
-       if (!udc->vbus_active)
-               return -EOPNOTSUPP;
-
-       udc->softconnect = (is_on != 0);
-       if (can_pullup(udc))
-               fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
-                               &dr_regs->usbcmd);
-       else
-               fsl_writel((fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP),
-                               &dr_regs->usbcmd);
-
-       return 0;
-}
-
-static int fsl_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-static int fsl_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-/* defined in gadget.h */
-static const struct usb_gadget_ops fsl_gadget_ops = {
-       .get_frame = fsl_get_frame,
-       .wakeup = fsl_wakeup,
-/*     .set_selfpowered = fsl_set_selfpowered, */ /* Always selfpowered */
-       .vbus_session = fsl_vbus_session,
-       .vbus_draw = fsl_vbus_draw,
-       .pullup = fsl_pullup,
-       .udc_start = fsl_udc_start,
-       .udc_stop = fsl_udc_stop,
-};
-
-/* Set protocol stall on ep0, protocol stall will automatically be cleared
-   on new transaction */
-static void ep0stall(struct fsl_udc *udc)
-{
-       u32 tmp;
-
-       /* must set tx and rx to stall at the same time */
-       tmp = fsl_readl(&dr_regs->endptctrl[0]);
-       tmp |= EPCTRL_TX_EP_STALL | EPCTRL_RX_EP_STALL;
-       fsl_writel(tmp, &dr_regs->endptctrl[0]);
-       udc->ep0_state = WAIT_FOR_SETUP;
-       udc->ep0_dir = 0;
-}
-
-/* Prime a status phase for ep0 */
-static int ep0_prime_status(struct fsl_udc *udc, int direction)
-{
-       struct fsl_req *req = udc->status_req;
-       struct fsl_ep *ep;
-       int ret;
-
-       if (direction == EP_DIR_IN)
-               udc->ep0_dir = USB_DIR_IN;
-       else
-               udc->ep0_dir = USB_DIR_OUT;
-
-       ep = &udc->eps[0];
-       if (udc->ep0_state != DATA_STATE_XMIT)
-               udc->ep0_state = WAIT_FOR_OUT_STATUS;
-
-       req->ep = ep;
-       req->req.length = 0;
-       req->req.status = -EINPROGRESS;
-       req->req.actual = 0;
-       req->req.complete = NULL;
-       req->dtd_count = 0;
-
-       ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
-       if (ret)
-               return ret;
-
-       if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
-               fsl_queue_td(ep, req);
-       else
-               return -ENOMEM;
-
-       list_add_tail(&req->queue, &ep->queue);
-
-       return 0;
-}
-
-static void udc_reset_ep_queue(struct fsl_udc *udc, u8 pipe)
-{
-       struct fsl_ep *ep = get_ep_by_pipe(udc, pipe);
-
-       if (ep->name)
-               nuke(ep, -ESHUTDOWN);
-}
-
-/*
- * ch9 Set address
- */
-static void ch9setaddress(struct fsl_udc *udc, u16 value, u16 index, u16 length)
-{
-       /* Save the new address to device struct */
-       udc->device_address = (u8) value;
-       /* Update usb state */
-       udc->usb_state = USB_STATE_ADDRESS;
-       /* Status phase */
-       if (ep0_prime_status(udc, EP_DIR_IN))
-               ep0stall(udc);
-}
-
-/*
- * ch9 Get status
- */
-static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
-               u16 index, u16 length)
-{
-       u16 tmp = 0;            /* Status, cpu endian */
-       struct fsl_req *req;
-       struct fsl_ep *ep;
-       int ret;
-
-       ep = &udc->eps[0];
-
-       if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
-               /* Get device status */
-               tmp = 1 << USB_DEVICE_SELF_POWERED;
-               tmp |= udc->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP;
-       } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) {
-               /* Get interface status */
-               /* We don't have interface information in udc driver */
-               tmp = 0;
-       } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_ENDPOINT) {
-               /* Get endpoint status */
-               struct fsl_ep *target_ep;
-
-               target_ep = get_ep_by_pipe(udc, get_pipe_by_windex(index));
-
-               /* stall if endpoint doesn't exist */
-               if (!target_ep->ep.desc)
-                       goto stall;
-               tmp = dr_ep_get_stall(ep_index(target_ep), ep_is_in(target_ep))
-                               << USB_ENDPOINT_HALT;
-       }
-
-       udc->ep0_dir = USB_DIR_IN;
-       /* Borrow the per device status_req */
-       req = udc->status_req;
-       /* Fill in the reqest structure */
-       *((u16 *) req->req.buf) = cpu_to_le16(tmp);
-
-       req->ep = ep;
-       req->req.length = 2;
-       req->req.status = -EINPROGRESS;
-       req->req.actual = 0;
-       req->req.complete = NULL;
-       req->dtd_count = 0;
-
-       ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
-       if (ret)
-               goto stall;
-
-       /* prime the data phase */
-       if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
-               fsl_queue_td(ep, req);
-       else                    /* no mem */
-               goto stall;
-
-       list_add_tail(&req->queue, &ep->queue);
-       udc->ep0_state = DATA_STATE_XMIT;
-       if (ep0_prime_status(udc, EP_DIR_OUT))
-               ep0stall(udc);
-
-       return;
-stall:
-       ep0stall(udc);
-}
-
-static void setup_received_irq(struct fsl_udc *udc,
-               struct usb_ctrlrequest *setup)
-{
-       u16 wValue = le16_to_cpu(setup->wValue);
-       u16 wIndex = le16_to_cpu(setup->wIndex);
-       u16 wLength = le16_to_cpu(setup->wLength);
-
-       udc_reset_ep_queue(udc, 0);
-
-       /* We process some stardard setup requests here */
-       switch (setup->bRequest) {
-       case USB_REQ_GET_STATUS:
-               /* Data+Status phase from udc */
-               if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
-                                       != (USB_DIR_IN | USB_TYPE_STANDARD))
-                       break;
-               ch9getstatus(udc, setup->bRequestType, wValue, wIndex, wLength);
-               return;
-
-       case USB_REQ_SET_ADDRESS:
-               /* Status phase from udc */
-               if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD
-                                               | USB_RECIP_DEVICE))
-                       break;
-               ch9setaddress(udc, wValue, wIndex, wLength);
-               return;
-
-       case USB_REQ_CLEAR_FEATURE:
-       case USB_REQ_SET_FEATURE:
-               /* Status phase from udc */
-       {
-               int rc = -EOPNOTSUPP;
-               u16 ptc = 0;
-
-               if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK))
-                               == (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) {
-                       int pipe = get_pipe_by_windex(wIndex);
-                       struct fsl_ep *ep;
-
-                       if (wValue != 0 || wLength != 0 || pipe >= udc->max_ep)
-                               break;
-                       ep = get_ep_by_pipe(udc, pipe);
-
-                       spin_unlock(&udc->lock);
-                       rc = fsl_ep_set_halt(&ep->ep,
-                                       (setup->bRequest == USB_REQ_SET_FEATURE)
-                                               ? 1 : 0);
-                       spin_lock(&udc->lock);
-
-               } else if ((setup->bRequestType & (USB_RECIP_MASK
-                               | USB_TYPE_MASK)) == (USB_RECIP_DEVICE
-                               | USB_TYPE_STANDARD)) {
-                       /* Note: The driver has not include OTG support yet.
-                        * This will be set when OTG support is added */
-                       if (wValue == USB_DEVICE_TEST_MODE)
-                               ptc = wIndex >> 8;
-                       else if (gadget_is_otg(&udc->gadget)) {
-                               if (setup->bRequest ==
-                                   USB_DEVICE_B_HNP_ENABLE)
-                                       udc->gadget.b_hnp_enable = 1;
-                               else if (setup->bRequest ==
-                                        USB_DEVICE_A_HNP_SUPPORT)
-                                       udc->gadget.a_hnp_support = 1;
-                               else if (setup->bRequest ==
-                                        USB_DEVICE_A_ALT_HNP_SUPPORT)
-                                       udc->gadget.a_alt_hnp_support = 1;
-                       }
-                       rc = 0;
-               } else
-                       break;
-
-               if (rc == 0) {
-                       if (ep0_prime_status(udc, EP_DIR_IN))
-                               ep0stall(udc);
-               }
-               if (ptc) {
-                       u32 tmp;
-
-                       mdelay(10);
-                       tmp = fsl_readl(&dr_regs->portsc1) | (ptc << 16);
-                       fsl_writel(tmp, &dr_regs->portsc1);
-                       printk(KERN_INFO "udc: switch to test mode %d.\n", ptc);
-               }
-
-               return;
-       }
-
-       default:
-               break;
-       }
-
-       /* Requests handled by gadget */
-       if (wLength) {
-               /* Data phase from gadget, status phase from udc */
-               udc->ep0_dir = (setup->bRequestType & USB_DIR_IN)
-                               ?  USB_DIR_IN : USB_DIR_OUT;
-               spin_unlock(&udc->lock);
-               if (udc->driver->setup(&udc->gadget,
-                               &udc->local_setup_buff) < 0)
-                       ep0stall(udc);
-               spin_lock(&udc->lock);
-               udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
-                               ?  DATA_STATE_XMIT : DATA_STATE_RECV;
-               /*
-                * If the data stage is IN, send status prime immediately.
-                * See 2.0 Spec chapter 8.5.3.3 for detail.
-                */
-               if (udc->ep0_state == DATA_STATE_XMIT)
-                       if (ep0_prime_status(udc, EP_DIR_OUT))
-                               ep0stall(udc);
-
-       } else {
-               /* No data phase, IN status from gadget */
-               udc->ep0_dir = USB_DIR_IN;
-               spin_unlock(&udc->lock);
-               if (udc->driver->setup(&udc->gadget,
-                               &udc->local_setup_buff) < 0)
-                       ep0stall(udc);
-               spin_lock(&udc->lock);
-               udc->ep0_state = WAIT_FOR_OUT_STATUS;
-       }
-}
-
-/* Process request for Data or Status phase of ep0
- * prime status phase if needed */
-static void ep0_req_complete(struct fsl_udc *udc, struct fsl_ep *ep0,
-               struct fsl_req *req)
-{
-       if (udc->usb_state == USB_STATE_ADDRESS) {
-               /* Set the new address */
-               u32 new_address = (u32) udc->device_address;
-               fsl_writel(new_address << USB_DEVICE_ADDRESS_BIT_POS,
-                               &dr_regs->deviceaddr);
-       }
-
-       done(ep0, req, 0);
-
-       switch (udc->ep0_state) {
-       case DATA_STATE_XMIT:
-               /* already primed at setup_received_irq */
-               udc->ep0_state = WAIT_FOR_OUT_STATUS;
-               break;
-       case DATA_STATE_RECV:
-               /* send status phase */
-               if (ep0_prime_status(udc, EP_DIR_IN))
-                       ep0stall(udc);
-               break;
-       case WAIT_FOR_OUT_STATUS:
-               udc->ep0_state = WAIT_FOR_SETUP;
-               break;
-       case WAIT_FOR_SETUP:
-               ERR("Unexpect ep0 packets\n");
-               break;
-       default:
-               ep0stall(udc);
-               break;
-       }
-}
-
-/* Tripwire mechanism to ensure a setup packet payload is extracted without
- * being corrupted by another incoming setup packet */
-static void tripwire_handler(struct fsl_udc *udc, u8 ep_num, u8 *buffer_ptr)
-{
-       u32 temp;
-       struct ep_queue_head *qh;
-       struct fsl_usb2_platform_data *pdata = udc->pdata;
-
-       qh = &udc->ep_qh[ep_num * 2 + EP_DIR_OUT];
-
-       /* Clear bit in ENDPTSETUPSTAT */
-       temp = fsl_readl(&dr_regs->endptsetupstat);
-       fsl_writel(temp | (1 << ep_num), &dr_regs->endptsetupstat);
-
-       /* while a hazard exists when setup package arrives */
-       do {
-               /* Set Setup Tripwire */
-               temp = fsl_readl(&dr_regs->usbcmd);
-               fsl_writel(temp | USB_CMD_SUTW, &dr_regs->usbcmd);
-
-               /* Copy the setup packet to local buffer */
-               if (pdata->le_setup_buf) {
-                       u32 *p = (u32 *)buffer_ptr;
-                       u32 *s = (u32 *)qh->setup_buffer;
-
-                       /* Convert little endian setup buffer to CPU endian */
-                       *p++ = le32_to_cpu(*s++);
-                       *p = le32_to_cpu(*s);
-               } else {
-                       memcpy(buffer_ptr, (u8 *) qh->setup_buffer, 8);
-               }
-       } while (!(fsl_readl(&dr_regs->usbcmd) & USB_CMD_SUTW));
-
-       /* Clear Setup Tripwire */
-       temp = fsl_readl(&dr_regs->usbcmd);
-       fsl_writel(temp & ~USB_CMD_SUTW, &dr_regs->usbcmd);
-}
-
-/* process-ep_req(): free the completed Tds for this req */
-static int process_ep_req(struct fsl_udc *udc, int pipe,
-               struct fsl_req *curr_req)
-{
-       struct ep_td_struct *curr_td;
-       int     td_complete, actual, remaining_length, j, tmp;
-       int     status = 0;
-       int     errors = 0;
-       struct  ep_queue_head *curr_qh = &udc->ep_qh[pipe];
-       int direction = pipe % 2;
-
-       curr_td = curr_req->head;
-       td_complete = 0;
-       actual = curr_req->req.length;
-
-       for (j = 0; j < curr_req->dtd_count; j++) {
-               remaining_length = (hc32_to_cpu(curr_td->size_ioc_sts)
-                                       & DTD_PACKET_SIZE)
-                               >> DTD_LENGTH_BIT_POS;
-               actual -= remaining_length;
-
-               errors = hc32_to_cpu(curr_td->size_ioc_sts);
-               if (errors & DTD_ERROR_MASK) {
-                       if (errors & DTD_STATUS_HALTED) {
-                               ERR("dTD error %08x QH=%d\n", errors, pipe);
-                               /* Clear the errors and Halt condition */
-                               tmp = hc32_to_cpu(curr_qh->size_ioc_int_sts);
-                               tmp &= ~errors;
-                               curr_qh->size_ioc_int_sts = cpu_to_hc32(tmp);
-                               status = -EPIPE;
-                               /* FIXME: continue with next queued TD? */
-
-                               break;
-                       }
-                       if (errors & DTD_STATUS_DATA_BUFF_ERR) {
-                               VDBG("Transfer overflow");
-                               status = -EPROTO;
-                               break;
-                       } else if (errors & DTD_STATUS_TRANSACTION_ERR) {
-                               VDBG("ISO error");
-                               status = -EILSEQ;
-                               break;
-                       } else
-                               ERR("Unknown error has occurred (0x%x)!\n",
-                                       errors);
-
-               } else if (hc32_to_cpu(curr_td->size_ioc_sts)
-                               & DTD_STATUS_ACTIVE) {
-                       VDBG("Request not complete");
-                       status = REQ_UNCOMPLETE;
-                       return status;
-               } else if (remaining_length) {
-                       if (direction) {
-                               VDBG("Transmit dTD remaining length not zero");
-                               status = -EPROTO;
-                               break;
-                       } else {
-                               td_complete++;
-                               break;
-                       }
-               } else {
-                       td_complete++;
-                       VDBG("dTD transmitted successful");
-               }
-
-               if (j != curr_req->dtd_count - 1)
-                       curr_td = (struct ep_td_struct *)curr_td->next_td_virt;
-       }
-
-       if (status)
-               return status;
-
-       curr_req->req.actual = actual;
-
-       return 0;
-}
-
-/* Process a DTD completion interrupt */
-static void dtd_complete_irq(struct fsl_udc *udc)
-{
-       u32 bit_pos;
-       int i, ep_num, direction, bit_mask, status;
-       struct fsl_ep *curr_ep;
-       struct fsl_req *curr_req, *temp_req;
-
-       /* Clear the bits in the register */
-       bit_pos = fsl_readl(&dr_regs->endptcomplete);
-       fsl_writel(bit_pos, &dr_regs->endptcomplete);
-
-       if (!bit_pos)
-               return;
-
-       for (i = 0; i < udc->max_ep; i++) {
-               ep_num = i >> 1;
-               direction = i % 2;
-
-               bit_mask = 1 << (ep_num + 16 * direction);
-
-               if (!(bit_pos & bit_mask))
-                       continue;
-
-               curr_ep = get_ep_by_pipe(udc, i);
-
-               /* If the ep is configured */
-               if (curr_ep->name == NULL) {
-                       WARNING("Invalid EP?");
-                       continue;
-               }
-
-               /* process the req queue until an uncomplete request */
-               list_for_each_entry_safe(curr_req, temp_req, &curr_ep->queue,
-                               queue) {
-                       status = process_ep_req(udc, i, curr_req);
-
-                       VDBG("status of process_ep_req= %d, ep = %d",
-                                       status, ep_num);
-                       if (status == REQ_UNCOMPLETE)
-                               break;
-                       /* write back status to req */
-                       curr_req->req.status = status;
-
-                       if (ep_num == 0) {
-                               ep0_req_complete(udc, curr_ep, curr_req);
-                               break;
-                       } else
-                               done(curr_ep, curr_req, status);
-               }
-       }
-}
-
-static inline enum usb_device_speed portscx_device_speed(u32 reg)
-{
-       switch (reg & PORTSCX_PORT_SPEED_MASK) {
-       case PORTSCX_PORT_SPEED_HIGH:
-               return USB_SPEED_HIGH;
-       case PORTSCX_PORT_SPEED_FULL:
-               return USB_SPEED_FULL;
-       case PORTSCX_PORT_SPEED_LOW:
-               return USB_SPEED_LOW;
-       default:
-               return USB_SPEED_UNKNOWN;
-       }
-}
-
-/* Process a port change interrupt */
-static void port_change_irq(struct fsl_udc *udc)
-{
-       if (udc->bus_reset)
-               udc->bus_reset = 0;
-
-       /* Bus resetting is finished */
-       if (!(fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET))
-               /* Get the speed */
-               udc->gadget.speed =
-                       portscx_device_speed(fsl_readl(&dr_regs->portsc1));
-
-       /* Update USB state */
-       if (!udc->resume_state)
-               udc->usb_state = USB_STATE_DEFAULT;
-}
-
-/* Process suspend interrupt */
-static void suspend_irq(struct fsl_udc *udc)
-{
-       udc->resume_state = udc->usb_state;
-       udc->usb_state = USB_STATE_SUSPENDED;
-
-       /* report suspend to the driver, serial.c does not support this */
-       if (udc->driver->suspend)
-               udc->driver->suspend(&udc->gadget);
-}
-
-static void bus_resume(struct fsl_udc *udc)
-{
-       udc->usb_state = udc->resume_state;
-       udc->resume_state = 0;
-
-       /* report resume to the driver, serial.c does not support this */
-       if (udc->driver->resume)
-               udc->driver->resume(&udc->gadget);
-}
-
-/* Clear up all ep queues */
-static int reset_queues(struct fsl_udc *udc)
-{
-       u8 pipe;
-
-       for (pipe = 0; pipe < udc->max_pipes; pipe++)
-               udc_reset_ep_queue(udc, pipe);
-
-       /* report disconnect; the driver is already quiesced */
-       spin_unlock(&udc->lock);
-       udc->driver->disconnect(&udc->gadget);
-       spin_lock(&udc->lock);
-
-       return 0;
-}
-
-/* Process reset interrupt */
-static void reset_irq(struct fsl_udc *udc)
-{
-       u32 temp;
-       unsigned long timeout;
-
-       /* Clear the device address */
-       temp = fsl_readl(&dr_regs->deviceaddr);
-       fsl_writel(temp & ~USB_DEVICE_ADDRESS_MASK, &dr_regs->deviceaddr);
-
-       udc->device_address = 0;
-
-       /* Clear usb state */
-       udc->resume_state = 0;
-       udc->ep0_dir = 0;
-       udc->ep0_state = WAIT_FOR_SETUP;
-       udc->remote_wakeup = 0; /* default to 0 on reset */
-       udc->gadget.b_hnp_enable = 0;
-       udc->gadget.a_hnp_support = 0;
-       udc->gadget.a_alt_hnp_support = 0;
-
-       /* Clear all the setup token semaphores */
-       temp = fsl_readl(&dr_regs->endptsetupstat);
-       fsl_writel(temp, &dr_regs->endptsetupstat);
-
-       /* Clear all the endpoint complete status bits */
-       temp = fsl_readl(&dr_regs->endptcomplete);
-       fsl_writel(temp, &dr_regs->endptcomplete);
-
-       timeout = jiffies + 100;
-       while (fsl_readl(&dr_regs->endpointprime)) {
-               /* Wait until all endptprime bits cleared */
-               if (time_after(jiffies, timeout)) {
-                       ERR("Timeout for reset\n");
-                       break;
-               }
-               cpu_relax();
-       }
-
-       /* Write 1s to the flush register */
-       fsl_writel(0xffffffff, &dr_regs->endptflush);
-
-       if (fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET) {
-               VDBG("Bus reset");
-               /* Bus is reseting */
-               udc->bus_reset = 1;
-               /* Reset all the queues, include XD, dTD, EP queue
-                * head and TR Queue */
-               reset_queues(udc);
-               udc->usb_state = USB_STATE_DEFAULT;
-       } else {
-               VDBG("Controller reset");
-               /* initialize usb hw reg except for regs for EP, not
-                * touch usbintr reg */
-               dr_controller_setup(udc);
-
-               /* Reset all internal used Queues */
-               reset_queues(udc);
-
-               ep0_setup(udc);
-
-               /* Enable DR IRQ reg, Set Run bit, change udc state */
-               dr_controller_run(udc);
-               udc->usb_state = USB_STATE_ATTACHED;
-       }
-}
-
-/*
- * USB device controller interrupt handler
- */
-static irqreturn_t fsl_udc_irq(int irq, void *_udc)
-{
-       struct fsl_udc *udc = _udc;
-       u32 irq_src;
-       irqreturn_t status = IRQ_NONE;
-       unsigned long flags;
-
-       /* Disable ISR for OTG host mode */
-       if (udc->stopped)
-               return IRQ_NONE;
-       spin_lock_irqsave(&udc->lock, flags);
-       irq_src = fsl_readl(&dr_regs->usbsts) & fsl_readl(&dr_regs->usbintr);
-       /* Clear notification bits */
-       fsl_writel(irq_src, &dr_regs->usbsts);
-
-       /* VDBG("irq_src [0x%8x]", irq_src); */
-
-       /* Need to resume? */
-       if (udc->usb_state == USB_STATE_SUSPENDED)
-               if ((fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_SUSPEND) == 0)
-                       bus_resume(udc);
-
-       /* USB Interrupt */
-       if (irq_src & USB_STS_INT) {
-               VDBG("Packet int");
-               /* Setup package, we only support ep0 as control ep */
-               if (fsl_readl(&dr_regs->endptsetupstat) & EP_SETUP_STATUS_EP0) {
-                       tripwire_handler(udc, 0,
-                                       (u8 *) (&udc->local_setup_buff));
-                       setup_received_irq(udc, &udc->local_setup_buff);
-                       status = IRQ_HANDLED;
-               }
-
-               /* completion of dtd */
-               if (fsl_readl(&dr_regs->endptcomplete)) {
-                       dtd_complete_irq(udc);
-                       status = IRQ_HANDLED;
-               }
-       }
-
-       /* SOF (for ISO transfer) */
-       if (irq_src & USB_STS_SOF) {
-               status = IRQ_HANDLED;
-       }
-
-       /* Port Change */
-       if (irq_src & USB_STS_PORT_CHANGE) {
-               port_change_irq(udc);
-               status = IRQ_HANDLED;
-       }
-
-       /* Reset Received */
-       if (irq_src & USB_STS_RESET) {
-               VDBG("reset int");
-               reset_irq(udc);
-               status = IRQ_HANDLED;
-       }
-
-       /* Sleep Enable (Suspend) */
-       if (irq_src & USB_STS_SUSPEND) {
-               suspend_irq(udc);
-               status = IRQ_HANDLED;
-       }
-
-       if (irq_src & (USB_STS_ERR | USB_STS_SYS_ERR)) {
-               VDBG("Error IRQ %x", irq_src);
-       }
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return status;
-}
-
-/*----------------------------------------------------------------*
- * Hook to gadget drivers
- * Called by initialization code of gadget drivers
-*----------------------------------------------------------------*/
-static int fsl_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       int retval = 0;
-       unsigned long flags = 0;
-
-       /* lock is needed but whether should use this lock or another */
-       spin_lock_irqsave(&udc_controller->lock, flags);
-
-       driver->driver.bus = NULL;
-       /* hook up the driver */
-       udc_controller->driver = driver;
-       spin_unlock_irqrestore(&udc_controller->lock, flags);
-
-       if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
-               /* Suspend the controller until OTG enable it */
-               udc_controller->stopped = 1;
-               printk(KERN_INFO "Suspend udc for OTG auto detect\n");
-
-               /* connect to bus through transceiver */
-               if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
-                       retval = otg_set_peripheral(
-                                       udc_controller->transceiver->otg,
-                                                   &udc_controller->gadget);
-                       if (retval < 0) {
-                               ERR("can't bind to transceiver\n");
-                               udc_controller->driver = 0;
-                               return retval;
-                       }
-               }
-       } else {
-               /* Enable DR IRQ reg and set USBCMD reg Run bit */
-               dr_controller_run(udc_controller);
-               udc_controller->usb_state = USB_STATE_ATTACHED;
-               udc_controller->ep0_state = WAIT_FOR_SETUP;
-               udc_controller->ep0_dir = 0;
-       }
-
-       return retval;
-}
-
-/* Disconnect from gadget driver */
-static int fsl_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct fsl_ep *loop_ep;
-       unsigned long flags;
-
-       if (!IS_ERR_OR_NULL(udc_controller->transceiver))
-               otg_set_peripheral(udc_controller->transceiver->otg, NULL);
-
-       /* stop DR, disable intr */
-       dr_controller_stop(udc_controller);
-
-       /* in fact, no needed */
-       udc_controller->usb_state = USB_STATE_ATTACHED;
-       udc_controller->ep0_state = WAIT_FOR_SETUP;
-       udc_controller->ep0_dir = 0;
-
-       /* stand operation */
-       spin_lock_irqsave(&udc_controller->lock, flags);
-       udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
-       nuke(&udc_controller->eps[0], -ESHUTDOWN);
-       list_for_each_entry(loop_ep, &udc_controller->gadget.ep_list,
-                       ep.ep_list)
-               nuke(loop_ep, -ESHUTDOWN);
-       spin_unlock_irqrestore(&udc_controller->lock, flags);
-
-       udc_controller->driver = NULL;
-
-       return 0;
-}
-
-/*-------------------------------------------------------------------------
-               PROC File System Support
--------------------------------------------------------------------------*/
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-
-#include <linux/seq_file.h>
-
-static const char proc_filename[] = "driver/fsl_usb2_udc";
-
-static int fsl_proc_read(struct seq_file *m, void *v)
-{
-       unsigned long flags;
-       int i;
-       u32 tmp_reg;
-       struct fsl_ep *ep = NULL;
-       struct fsl_req *req;
-
-       struct fsl_udc *udc = udc_controller;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       /* ------basic driver information ---- */
-       seq_printf(m,
-                       DRIVER_DESC "\n"
-                       "%s version: %s\n"
-                       "Gadget driver: %s\n\n",
-                       driver_name, DRIVER_VERSION,
-                       udc->driver ? udc->driver->driver.name : "(none)");
-
-       /* ------ DR Registers ----- */
-       tmp_reg = fsl_readl(&dr_regs->usbcmd);
-       seq_printf(m,
-                       "USBCMD reg:\n"
-                       "SetupTW: %d\n"
-                       "Run/Stop: %s\n\n",
-                       (tmp_reg & USB_CMD_SUTW) ? 1 : 0,
-                       (tmp_reg & USB_CMD_RUN_STOP) ? "Run" : "Stop");
-
-       tmp_reg = fsl_readl(&dr_regs->usbsts);
-       seq_printf(m,
-                       "USB Status Reg:\n"
-                       "Dr Suspend: %d Reset Received: %d System Error: %s "
-                       "USB Error Interrupt: %s\n\n",
-                       (tmp_reg & USB_STS_SUSPEND) ? 1 : 0,
-                       (tmp_reg & USB_STS_RESET) ? 1 : 0,
-                       (tmp_reg & USB_STS_SYS_ERR) ? "Err" : "Normal",
-                       (tmp_reg & USB_STS_ERR) ? "Err detected" : "No err");
-
-       tmp_reg = fsl_readl(&dr_regs->usbintr);
-       seq_printf(m,
-                       "USB Interrupt Enable Reg:\n"
-                       "Sleep Enable: %d SOF Received Enable: %d "
-                       "Reset Enable: %d\n"
-                       "System Error Enable: %d "
-                       "Port Change Dectected Enable: %d\n"
-                       "USB Error Intr Enable: %d USB Intr Enable: %d\n\n",
-                       (tmp_reg & USB_INTR_DEVICE_SUSPEND) ? 1 : 0,
-                       (tmp_reg & USB_INTR_SOF_EN) ? 1 : 0,
-                       (tmp_reg & USB_INTR_RESET_EN) ? 1 : 0,
-                       (tmp_reg & USB_INTR_SYS_ERR_EN) ? 1 : 0,
-                       (tmp_reg & USB_INTR_PTC_DETECT_EN) ? 1 : 0,
-                       (tmp_reg & USB_INTR_ERR_INT_EN) ? 1 : 0,
-                       (tmp_reg & USB_INTR_INT_EN) ? 1 : 0);
-
-       tmp_reg = fsl_readl(&dr_regs->frindex);
-       seq_printf(m,
-                       "USB Frame Index Reg: Frame Number is 0x%x\n\n",
-                       (tmp_reg & USB_FRINDEX_MASKS));
-
-       tmp_reg = fsl_readl(&dr_regs->deviceaddr);
-       seq_printf(m,
-                       "USB Device Address Reg: Device Addr is 0x%x\n\n",
-                       (tmp_reg & USB_DEVICE_ADDRESS_MASK));
-
-       tmp_reg = fsl_readl(&dr_regs->endpointlistaddr);
-       seq_printf(m,
-                       "USB Endpoint List Address Reg: "
-                       "Device Addr is 0x%x\n\n",
-                       (tmp_reg & USB_EP_LIST_ADDRESS_MASK));
-
-       tmp_reg = fsl_readl(&dr_regs->portsc1);
-       seq_printf(m,
-               "USB Port Status&Control Reg:\n"
-               "Port Transceiver Type : %s Port Speed: %s\n"
-               "PHY Low Power Suspend: %s Port Reset: %s "
-               "Port Suspend Mode: %s\n"
-               "Over-current Change: %s "
-               "Port Enable/Disable Change: %s\n"
-               "Port Enabled/Disabled: %s "
-               "Current Connect Status: %s\n\n", ( {
-                       const char *s;
-                       switch (tmp_reg & PORTSCX_PTS_FSLS) {
-                       case PORTSCX_PTS_UTMI:
-                               s = "UTMI"; break;
-                       case PORTSCX_PTS_ULPI:
-                               s = "ULPI "; break;
-                       case PORTSCX_PTS_FSLS:
-                               s = "FS/LS Serial"; break;
-                       default:
-                               s = "None"; break;
-                       }
-                       s;} ),
-               usb_speed_string(portscx_device_speed(tmp_reg)),
-               (tmp_reg & PORTSCX_PHY_LOW_POWER_SPD) ?
-               "Normal PHY mode" : "Low power mode",
-               (tmp_reg & PORTSCX_PORT_RESET) ? "In Reset" :
-               "Not in Reset",
-               (tmp_reg & PORTSCX_PORT_SUSPEND) ? "In " : "Not in",
-               (tmp_reg & PORTSCX_OVER_CURRENT_CHG) ? "Dected" :
-               "No",
-               (tmp_reg & PORTSCX_PORT_EN_DIS_CHANGE) ? "Disable" :
-               "Not change",
-               (tmp_reg & PORTSCX_PORT_ENABLE) ? "Enable" :
-               "Not correct",
-               (tmp_reg & PORTSCX_CURRENT_CONNECT_STATUS) ?
-               "Attached" : "Not-Att");
-
-       tmp_reg = fsl_readl(&dr_regs->usbmode);
-       seq_printf(m,
-                       "USB Mode Reg: Controller Mode is: %s\n\n", ( {
-                               const char *s;
-                               switch (tmp_reg & USB_MODE_CTRL_MODE_HOST) {
-                               case USB_MODE_CTRL_MODE_IDLE:
-                                       s = "Idle"; break;
-                               case USB_MODE_CTRL_MODE_DEVICE:
-                                       s = "Device Controller"; break;
-                               case USB_MODE_CTRL_MODE_HOST:
-                                       s = "Host Controller"; break;
-                               default:
-                                       s = "None"; break;
-                               }
-                               s;
-                       } ));
-
-       tmp_reg = fsl_readl(&dr_regs->endptsetupstat);
-       seq_printf(m,
-                       "Endpoint Setup Status Reg: SETUP on ep 0x%x\n\n",
-                       (tmp_reg & EP_SETUP_STATUS_MASK));
-
-       for (i = 0; i < udc->max_ep / 2; i++) {
-               tmp_reg = fsl_readl(&dr_regs->endptctrl[i]);
-               seq_printf(m, "EP Ctrl Reg [0x%x]: = [0x%x]\n", i, tmp_reg);
-       }
-       tmp_reg = fsl_readl(&dr_regs->endpointprime);
-       seq_printf(m, "EP Prime Reg = [0x%x]\n\n", tmp_reg);
-
-#ifndef CONFIG_ARCH_MXC
-       if (udc->pdata->have_sysif_regs) {
-               tmp_reg = usb_sys_regs->snoop1;
-               seq_printf(m, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg);
-
-               tmp_reg = usb_sys_regs->control;
-               seq_printf(m, "General Control Reg : = [0x%x]\n\n", tmp_reg);
-       }
-#endif
-
-       /* ------fsl_udc, fsl_ep, fsl_request structure information ----- */
-       ep = &udc->eps[0];
-       seq_printf(m, "For %s Maxpkt is 0x%x index is 0x%x\n",
-                       ep->ep.name, ep_maxpacket(ep), ep_index(ep));
-
-       if (list_empty(&ep->queue)) {
-               seq_puts(m, "its req queue is empty\n\n");
-       } else {
-               list_for_each_entry(req, &ep->queue, queue) {
-                       seq_printf(m,
-                               "req %p actual 0x%x length 0x%x buf %p\n",
-                               &req->req, req->req.actual,
-                               req->req.length, req->req.buf);
-               }
-       }
-       /* other gadget->eplist ep */
-       list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
-               if (ep->ep.desc) {
-                       seq_printf(m,
-                                       "\nFor %s Maxpkt is 0x%x "
-                                       "index is 0x%x\n",
-                                       ep->ep.name, ep_maxpacket(ep),
-                                       ep_index(ep));
-
-                       if (list_empty(&ep->queue)) {
-                               seq_puts(m, "its req queue is empty\n\n");
-                       } else {
-                               list_for_each_entry(req, &ep->queue, queue) {
-                                       seq_printf(m,
-                                               "req %p actual 0x%x length "
-                                               "0x%x  buf %p\n",
-                                               &req->req, req->req.actual,
-                                               req->req.length, req->req.buf);
-                               }       /* end for each_entry of ep req */
-                       }       /* end for else */
-               }       /* end for if(ep->queue) */
-       }       /* end (ep->desc) */
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return 0;
-}
-
-/*
- * seq_file wrappers for procfile show routines.
- */
-static int fsl_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, fsl_proc_read, NULL);
-}
-
-static const struct file_operations fsl_proc_fops = {
-       .open           = fsl_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-#define create_proc_file()     proc_create(proc_filename, 0, NULL, &fsl_proc_fops)
-#define remove_proc_file()     remove_proc_entry(proc_filename, NULL)
-
-#else                          /* !CONFIG_USB_GADGET_DEBUG_FILES */
-
-#define create_proc_file()     do {} while (0)
-#define remove_proc_file()     do {} while (0)
-
-#endif                         /* CONFIG_USB_GADGET_DEBUG_FILES */
-
-/*-------------------------------------------------------------------------*/
-
-/* Release udc structures */
-static void fsl_udc_release(struct device *dev)
-{
-       complete(udc_controller->done);
-       dma_free_coherent(dev->parent, udc_controller->ep_qh_size,
-                       udc_controller->ep_qh, udc_controller->ep_qh_dma);
-       kfree(udc_controller);
-}
-
-/******************************************************************
-       Internal structure setup functions
-*******************************************************************/
-/*------------------------------------------------------------------
- * init resource for globle controller
- * Return the udc handle on success or NULL on failure
- ------------------------------------------------------------------*/
-static int struct_udc_setup(struct fsl_udc *udc,
-               struct platform_device *pdev)
-{
-       struct fsl_usb2_platform_data *pdata;
-       size_t size;
-
-       pdata = dev_get_platdata(&pdev->dev);
-       udc->phy_mode = pdata->phy_mode;
-
-       udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);
-       if (!udc->eps)
-               return -1;
-
-       /* initialized QHs, take care of alignment */
-       size = udc->max_ep * sizeof(struct ep_queue_head);
-       if (size < QH_ALIGNMENT)
-               size = QH_ALIGNMENT;
-       else if ((size % QH_ALIGNMENT) != 0) {
-               size += QH_ALIGNMENT + 1;
-               size &= ~(QH_ALIGNMENT - 1);
-       }
-       udc->ep_qh = dma_alloc_coherent(&pdev->dev, size,
-                                       &udc->ep_qh_dma, GFP_KERNEL);
-       if (!udc->ep_qh) {
-               ERR("malloc QHs for udc failed\n");
-               kfree(udc->eps);
-               return -1;
-       }
-
-       udc->ep_qh_size = size;
-
-       /* Initialize ep0 status request structure */
-       /* FIXME: fsl_alloc_request() ignores ep argument */
-       udc->status_req = container_of(fsl_alloc_request(NULL, GFP_KERNEL),
-                       struct fsl_req, req);
-       /* allocate a small amount of memory to get valid address */
-       udc->status_req->req.buf = kmalloc(8, GFP_KERNEL);
-
-       udc->resume_state = USB_STATE_NOTATTACHED;
-       udc->usb_state = USB_STATE_POWERED;
-       udc->ep0_dir = 0;
-       udc->remote_wakeup = 0; /* default to 0 on reset */
-
-       return 0;
-}
-
-/*----------------------------------------------------------------
- * Setup the fsl_ep struct for eps
- * Link fsl_ep->ep to gadget->ep_list
- * ep0out is not used so do nothing here
- * ep0in should be taken care
- *--------------------------------------------------------------*/
-static int struct_ep_setup(struct fsl_udc *udc, unsigned char index,
-               char *name, int link)
-{
-       struct fsl_ep *ep = &udc->eps[index];
-
-       ep->udc = udc;
-       strcpy(ep->name, name);
-       ep->ep.name = ep->name;
-
-       ep->ep.ops = &fsl_ep_ops;
-       ep->stopped = 0;
-
-       /* for ep0: maxP defined in desc
-        * for other eps, maxP is set by epautoconfig() called by gadget layer
-        */
-       usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
-
-       /* the queue lists any req for this ep */
-       INIT_LIST_HEAD(&ep->queue);
-
-       /* gagdet.ep_list used for ep_autoconfig so no ep0 */
-       if (link)
-               list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
-       ep->gadget = &udc->gadget;
-       ep->qh = &udc->ep_qh[index];
-
-       return 0;
-}
-
-/* Driver probe function
- * all intialization operations implemented here except enabling usb_intr reg
- * board setup should have been done in the platform code
- */
-static int fsl_udc_probe(struct platform_device *pdev)
-{
-       struct fsl_usb2_platform_data *pdata;
-       struct resource *res;
-       int ret = -ENODEV;
-       unsigned int i;
-       u32 dccparams;
-
-       udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
-       if (udc_controller == NULL)
-               return -ENOMEM;
-
-       pdata = dev_get_platdata(&pdev->dev);
-       udc_controller->pdata = pdata;
-       spin_lock_init(&udc_controller->lock);
-       udc_controller->stopped = 1;
-
-#ifdef CONFIG_USB_OTG
-       if (pdata->operating_mode == FSL_USB2_DR_OTG) {
-               udc_controller->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
-               if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
-                       ERR("Can't find OTG driver!\n");
-                       ret = -ENODEV;
-                       goto err_kfree;
-               }
-       }
-#endif
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENXIO;
-               goto err_kfree;
-       }
-
-       if (pdata->operating_mode == FSL_USB2_DR_DEVICE) {
-               if (!request_mem_region(res->start, resource_size(res),
-                                       driver_name)) {
-                       ERR("request mem region for %s failed\n", pdev->name);
-                       ret = -EBUSY;
-                       goto err_kfree;
-               }
-       }
-
-       dr_regs = ioremap(res->start, resource_size(res));
-       if (!dr_regs) {
-               ret = -ENOMEM;
-               goto err_release_mem_region;
-       }
-
-       pdata->regs = (void *)dr_regs;
-
-       /*
-        * do platform specific init: check the clock, grab/config pins, etc.
-        */
-       if (pdata->init && pdata->init(pdev)) {
-               ret = -ENODEV;
-               goto err_iounmap_noclk;
-       }
-
-       /* Set accessors only after pdata->init() ! */
-       fsl_set_accessors(pdata);
-
-#ifndef CONFIG_ARCH_MXC
-       if (pdata->have_sysif_regs)
-               usb_sys_regs = (void *)dr_regs + USB_DR_SYS_OFFSET;
-#endif
-
-       /* Initialize USB clocks */
-       ret = fsl_udc_clk_init(pdev);
-       if (ret < 0)
-               goto err_iounmap_noclk;
-
-       /* Read Device Controller Capability Parameters register */
-       dccparams = fsl_readl(&dr_regs->dccparams);
-       if (!(dccparams & DCCPARAMS_DC)) {
-               ERR("This SOC doesn't support device role\n");
-               ret = -ENODEV;
-               goto err_iounmap;
-       }
-       /* Get max device endpoints */
-       /* DEN is bidirectional ep number, max_ep doubles the number */
-       udc_controller->max_ep = (dccparams & DCCPARAMS_DEN_MASK) * 2;
-
-       udc_controller->irq = platform_get_irq(pdev, 0);
-       if (!udc_controller->irq) {
-               ret = -ENODEV;
-               goto err_iounmap;
-       }
-
-       ret = request_irq(udc_controller->irq, fsl_udc_irq, IRQF_SHARED,
-                       driver_name, udc_controller);
-       if (ret != 0) {
-               ERR("cannot request irq %d err %d\n",
-                               udc_controller->irq, ret);
-               goto err_iounmap;
-       }
-
-       /* Initialize the udc structure including QH member and other member */
-       if (struct_udc_setup(udc_controller, pdev)) {
-               ERR("Can't initialize udc data structure\n");
-               ret = -ENOMEM;
-               goto err_free_irq;
-       }
-
-       if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
-               /* initialize usb hw reg except for regs for EP,
-                * leave usbintr reg untouched */
-               dr_controller_setup(udc_controller);
-       }
-
-       ret = fsl_udc_clk_finalize(pdev);
-       if (ret)
-               goto err_free_irq;
-
-       /* Setup gadget structure */
-       udc_controller->gadget.ops = &fsl_gadget_ops;
-       udc_controller->gadget.max_speed = USB_SPEED_HIGH;
-       udc_controller->gadget.ep0 = &udc_controller->eps[0].ep;
-       INIT_LIST_HEAD(&udc_controller->gadget.ep_list);
-       udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
-       udc_controller->gadget.name = driver_name;
-
-       /* Setup gadget.dev and register with kernel */
-       dev_set_name(&udc_controller->gadget.dev, "gadget");
-       udc_controller->gadget.dev.of_node = pdev->dev.of_node;
-
-       if (!IS_ERR_OR_NULL(udc_controller->transceiver))
-               udc_controller->gadget.is_otg = 1;
-
-       /* setup QH and epctrl for ep0 */
-       ep0_setup(udc_controller);
-
-       /* setup udc->eps[] for ep0 */
-       struct_ep_setup(udc_controller, 0, "ep0", 0);
-       /* for ep0: the desc defined here;
-        * for other eps, gadget layer called ep_enable with defined desc
-        */
-       udc_controller->eps[0].ep.desc = &fsl_ep0_desc;
-       usb_ep_set_maxpacket_limit(&udc_controller->eps[0].ep,
-                                  USB_MAX_CTRL_PAYLOAD);
-
-       /* setup the udc->eps[] for non-control endpoints and link
-        * to gadget.ep_list */
-       for (i = 1; i < (int)(udc_controller->max_ep / 2); i++) {
-               char name[14];
-
-               sprintf(name, "ep%dout", i);
-               struct_ep_setup(udc_controller, i * 2, name, 1);
-               sprintf(name, "ep%din", i);
-               struct_ep_setup(udc_controller, i * 2 + 1, name, 1);
-       }
-
-       /* use dma_pool for TD management */
-       udc_controller->td_pool = dma_pool_create("udc_td", &pdev->dev,
-                       sizeof(struct ep_td_struct),
-                       DTD_ALIGNMENT, UDC_DMA_BOUNDARY);
-       if (udc_controller->td_pool == NULL) {
-               ret = -ENOMEM;
-               goto err_free_irq;
-       }
-
-       ret = usb_add_gadget_udc_release(&pdev->dev, &udc_controller->gadget,
-                       fsl_udc_release);
-       if (ret)
-               goto err_del_udc;
-
-       create_proc_file();
-       return 0;
-
-err_del_udc:
-       dma_pool_destroy(udc_controller->td_pool);
-err_free_irq:
-       free_irq(udc_controller->irq, udc_controller);
-err_iounmap:
-       if (pdata->exit)
-               pdata->exit(pdev);
-       fsl_udc_clk_release();
-err_iounmap_noclk:
-       iounmap(dr_regs);
-err_release_mem_region:
-       if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
-               release_mem_region(res->start, resource_size(res));
-err_kfree:
-       kfree(udc_controller);
-       udc_controller = NULL;
-       return ret;
-}
-
-/* Driver removal function
- * Free resources and finish pending transactions
- */
-static int __exit fsl_udc_remove(struct platform_device *pdev)
-{
-       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
-
-       DECLARE_COMPLETION(done);
-
-       if (!udc_controller)
-               return -ENODEV;
-
-       udc_controller->done = &done;
-       usb_del_gadget_udc(&udc_controller->gadget);
-
-       fsl_udc_clk_release();
-
-       /* DR has been stopped in usb_gadget_unregister_driver() */
-       remove_proc_file();
-
-       /* Free allocated memory */
-       kfree(udc_controller->status_req->req.buf);
-       kfree(udc_controller->status_req);
-       kfree(udc_controller->eps);
-
-       dma_pool_destroy(udc_controller->td_pool);
-       free_irq(udc_controller->irq, udc_controller);
-       iounmap(dr_regs);
-       if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
-               release_mem_region(res->start, resource_size(res));
-
-       /* free udc --wait for the release() finished */
-       wait_for_completion(&done);
-
-       /*
-        * do platform specific un-initialization:
-        * release iomux pins, etc.
-        */
-       if (pdata->exit)
-               pdata->exit(pdev);
-
-       return 0;
-}
-
-/*-----------------------------------------------------------------
- * Modify Power management attributes
- * Used by OTG statemachine to disable gadget temporarily
- -----------------------------------------------------------------*/
-static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       dr_controller_stop(udc_controller);
-       return 0;
-}
-
-/*-----------------------------------------------------------------
- * Invoked on USB resume. May be called in_interrupt.
- * Here we start the DR controller and enable the irq
- *-----------------------------------------------------------------*/
-static int fsl_udc_resume(struct platform_device *pdev)
-{
-       /* Enable DR irq reg and set controller Run */
-       if (udc_controller->stopped) {
-               dr_controller_setup(udc_controller);
-               dr_controller_run(udc_controller);
-       }
-       udc_controller->usb_state = USB_STATE_ATTACHED;
-       udc_controller->ep0_state = WAIT_FOR_SETUP;
-       udc_controller->ep0_dir = 0;
-       return 0;
-}
-
-static int fsl_udc_otg_suspend(struct device *dev, pm_message_t state)
-{
-       struct fsl_udc *udc = udc_controller;
-       u32 mode, usbcmd;
-
-       mode = fsl_readl(&dr_regs->usbmode) & USB_MODE_CTRL_MODE_MASK;
-
-       pr_debug("%s(): mode 0x%x stopped %d\n", __func__, mode, udc->stopped);
-
-       /*
-        * If the controller is already stopped, then this must be a
-        * PM suspend.  Remember this fact, so that we will leave the
-        * controller stopped at PM resume time.
-        */
-       if (udc->stopped) {
-               pr_debug("gadget already stopped, leaving early\n");
-               udc->already_stopped = 1;
-               return 0;
-       }
-
-       if (mode != USB_MODE_CTRL_MODE_DEVICE) {
-               pr_debug("gadget not in device mode, leaving early\n");
-               return 0;
-       }
-
-       /* stop the controller */
-       usbcmd = fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP;
-       fsl_writel(usbcmd, &dr_regs->usbcmd);
-
-       udc->stopped = 1;
-
-       pr_info("USB Gadget suspended\n");
-
-       return 0;
-}
-
-static int fsl_udc_otg_resume(struct device *dev)
-{
-       pr_debug("%s(): stopped %d  already_stopped %d\n", __func__,
-                udc_controller->stopped, udc_controller->already_stopped);
-
-       /*
-        * If the controller was stopped at suspend time, then
-        * don't resume it now.
-        */
-       if (udc_controller->already_stopped) {
-               udc_controller->already_stopped = 0;
-               pr_debug("gadget was already stopped, leaving early\n");
-               return 0;
-       }
-
-       pr_info("USB Gadget resume\n");
-
-       return fsl_udc_resume(NULL);
-}
-/*-------------------------------------------------------------------------
-       Register entry point for the peripheral controller driver
---------------------------------------------------------------------------*/
-static const struct platform_device_id fsl_udc_devtype[] = {
-       {
-               .name = "imx-udc-mx27",
-       }, {
-               .name = "imx-udc-mx51",
-       }, {
-               /* sentinel */
-       }
-};
-MODULE_DEVICE_TABLE(platform, fsl_udc_devtype);
-static struct platform_driver udc_driver = {
-       .remove         = __exit_p(fsl_udc_remove),
-       /* Just for FSL i.mx SoC currently */
-       .id_table       = fsl_udc_devtype,
-       /* these suspend and resume are not usb suspend and resume */
-       .suspend        = fsl_udc_suspend,
-       .resume         = fsl_udc_resume,
-       .driver         = {
-                       .name = driver_name,
-                       .owner = THIS_MODULE,
-                       /* udc suspend/resume called from OTG driver */
-                       .suspend = fsl_udc_otg_suspend,
-                       .resume  = fsl_udc_otg_resume,
-       },
-};
-
-module_platform_driver_probe(udc_driver, fsl_udc_probe);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:fsl-usb2-udc");
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
deleted file mode 100644 (file)
index c6703bb..0000000
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- * Copyright (C) 2004,2012 Freescale Semiconductor, Inc
- * 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 as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Freescale USB device/endpoint management registers
- */
-#ifndef __FSL_USB2_UDC_H
-#define __FSL_USB2_UDC_H
-
-/* ### define USB registers here
- */
-#define USB_MAX_CTRL_PAYLOAD           64
-#define USB_DR_SYS_OFFSET              0x400
-
- /* USB DR device mode registers (Little Endian) */
-struct usb_dr_device {
-       /* Capability register */
-       u8 res1[256];
-       u16 caplength;          /* Capability Register Length */
-       u16 hciversion;         /* Host Controller Interface Version */
-       u32 hcsparams;          /* Host Controller Structural Parameters */
-       u32 hccparams;          /* Host Controller Capability Parameters */
-       u8 res2[20];
-       u32 dciversion;         /* Device Controller Interface Version */
-       u32 dccparams;          /* Device Controller Capability Parameters */
-       u8 res3[24];
-       /* Operation register */
-       u32 usbcmd;             /* USB Command Register */
-       u32 usbsts;             /* USB Status Register */
-       u32 usbintr;            /* USB Interrupt Enable Register */
-       u32 frindex;            /* Frame Index Register */
-       u8 res4[4];
-       u32 deviceaddr;         /* Device Address */
-       u32 endpointlistaddr;   /* Endpoint List Address Register */
-       u8 res5[4];
-       u32 burstsize;          /* Master Interface Data Burst Size Register */
-       u32 txttfilltuning;     /* Transmit FIFO Tuning Controls Register */
-       u8 res6[24];
-       u32 configflag;         /* Configure Flag Register */
-       u32 portsc1;            /* Port 1 Status and Control Register */
-       u8 res7[28];
-       u32 otgsc;              /* On-The-Go Status and Control */
-       u32 usbmode;            /* USB Mode Register */
-       u32 endptsetupstat;     /* Endpoint Setup Status Register */
-       u32 endpointprime;      /* Endpoint Initialization Register */
-       u32 endptflush;         /* Endpoint Flush Register */
-       u32 endptstatus;        /* Endpoint Status Register */
-       u32 endptcomplete;      /* Endpoint Complete Register */
-       u32 endptctrl[6];       /* Endpoint Control Registers */
-};
-
- /* USB DR host mode registers (Little Endian) */
-struct usb_dr_host {
-       /* Capability register */
-       u8 res1[256];
-       u16 caplength;          /* Capability Register Length */
-       u16 hciversion;         /* Host Controller Interface Version */
-       u32 hcsparams;          /* Host Controller Structural Parameters */
-       u32 hccparams;          /* Host Controller Capability Parameters */
-       u8 res2[20];
-       u32 dciversion;         /* Device Controller Interface Version */
-       u32 dccparams;          /* Device Controller Capability Parameters */
-       u8 res3[24];
-       /* Operation register */
-       u32 usbcmd;             /* USB Command Register */
-       u32 usbsts;             /* USB Status Register */
-       u32 usbintr;            /* USB Interrupt Enable Register */
-       u32 frindex;            /* Frame Index Register */
-       u8 res4[4];
-       u32 periodiclistbase;   /* Periodic Frame List Base Address Register */
-       u32 asynclistaddr;      /* Current Asynchronous List Address Register */
-       u8 res5[4];
-       u32 burstsize;          /* Master Interface Data Burst Size Register */
-       u32 txttfilltuning;     /* Transmit FIFO Tuning Controls Register */
-       u8 res6[24];
-       u32 configflag;         /* Configure Flag Register */
-       u32 portsc1;            /* Port 1 Status and Control Register */
-       u8 res7[28];
-       u32 otgsc;              /* On-The-Go Status and Control */
-       u32 usbmode;            /* USB Mode Register */
-       u32 endptsetupstat;     /* Endpoint Setup Status Register */
-       u32 endpointprime;      /* Endpoint Initialization Register */
-       u32 endptflush;         /* Endpoint Flush Register */
-       u32 endptstatus;        /* Endpoint Status Register */
-       u32 endptcomplete;      /* Endpoint Complete Register */
-       u32 endptctrl[6];       /* Endpoint Control Registers */
-};
-
- /* non-EHCI USB system interface registers (Big Endian) */
-struct usb_sys_interface {
-       u32 snoop1;
-       u32 snoop2;
-       u32 age_cnt_thresh;     /* Age Count Threshold Register */
-       u32 pri_ctrl;           /* Priority Control Register */
-       u32 si_ctrl;            /* System Interface Control Register */
-       u8 res[236];
-       u32 control;            /* General Purpose Control Register */
-};
-
-/* ep0 transfer state */
-#define WAIT_FOR_SETUP          0
-#define DATA_STATE_XMIT         1
-#define DATA_STATE_NEED_ZLP     2
-#define WAIT_FOR_OUT_STATUS     3
-#define DATA_STATE_RECV         4
-
-/* Device Controller Capability Parameter register */
-#define DCCPARAMS_DC                           0x00000080
-#define DCCPARAMS_DEN_MASK                     0x0000001f
-
-/* Frame Index Register Bit Masks */
-#define        USB_FRINDEX_MASKS                       0x3fff
-/* USB CMD  Register Bit Masks */
-#define  USB_CMD_RUN_STOP                     0x00000001
-#define  USB_CMD_CTRL_RESET                   0x00000002
-#define  USB_CMD_PERIODIC_SCHEDULE_EN         0x00000010
-#define  USB_CMD_ASYNC_SCHEDULE_EN            0x00000020
-#define  USB_CMD_INT_AA_DOORBELL              0x00000040
-#define  USB_CMD_ASP                          0x00000300
-#define  USB_CMD_ASYNC_SCH_PARK_EN            0x00000800
-#define  USB_CMD_SUTW                         0x00002000
-#define  USB_CMD_ATDTW                        0x00004000
-#define  USB_CMD_ITC                          0x00FF0000
-
-/* bit 15,3,2 are frame list size */
-#define  USB_CMD_FRAME_SIZE_1024              0x00000000
-#define  USB_CMD_FRAME_SIZE_512               0x00000004
-#define  USB_CMD_FRAME_SIZE_256               0x00000008
-#define  USB_CMD_FRAME_SIZE_128               0x0000000C
-#define  USB_CMD_FRAME_SIZE_64                0x00008000
-#define  USB_CMD_FRAME_SIZE_32                0x00008004
-#define  USB_CMD_FRAME_SIZE_16                0x00008008
-#define  USB_CMD_FRAME_SIZE_8                 0x0000800C
-
-/* bit 9-8 are async schedule park mode count */
-#define  USB_CMD_ASP_00                       0x00000000
-#define  USB_CMD_ASP_01                       0x00000100
-#define  USB_CMD_ASP_10                       0x00000200
-#define  USB_CMD_ASP_11                       0x00000300
-#define  USB_CMD_ASP_BIT_POS                  8
-
-/* bit 23-16 are interrupt threshold control */
-#define  USB_CMD_ITC_NO_THRESHOLD             0x00000000
-#define  USB_CMD_ITC_1_MICRO_FRM              0x00010000
-#define  USB_CMD_ITC_2_MICRO_FRM              0x00020000
-#define  USB_CMD_ITC_4_MICRO_FRM              0x00040000
-#define  USB_CMD_ITC_8_MICRO_FRM              0x00080000
-#define  USB_CMD_ITC_16_MICRO_FRM             0x00100000
-#define  USB_CMD_ITC_32_MICRO_FRM             0x00200000
-#define  USB_CMD_ITC_64_MICRO_FRM             0x00400000
-#define  USB_CMD_ITC_BIT_POS                  16
-
-/* USB STS Register Bit Masks */
-#define  USB_STS_INT                          0x00000001
-#define  USB_STS_ERR                          0x00000002
-#define  USB_STS_PORT_CHANGE                  0x00000004
-#define  USB_STS_FRM_LST_ROLL                 0x00000008
-#define  USB_STS_SYS_ERR                      0x00000010
-#define  USB_STS_IAA                          0x00000020
-#define  USB_STS_RESET                        0x00000040
-#define  USB_STS_SOF                          0x00000080
-#define  USB_STS_SUSPEND                      0x00000100
-#define  USB_STS_HC_HALTED                    0x00001000
-#define  USB_STS_RCL                          0x00002000
-#define  USB_STS_PERIODIC_SCHEDULE            0x00004000
-#define  USB_STS_ASYNC_SCHEDULE               0x00008000
-
-/* USB INTR Register Bit Masks */
-#define  USB_INTR_INT_EN                      0x00000001
-#define  USB_INTR_ERR_INT_EN                  0x00000002
-#define  USB_INTR_PTC_DETECT_EN               0x00000004
-#define  USB_INTR_FRM_LST_ROLL_EN             0x00000008
-#define  USB_INTR_SYS_ERR_EN                  0x00000010
-#define  USB_INTR_ASYN_ADV_EN                 0x00000020
-#define  USB_INTR_RESET_EN                    0x00000040
-#define  USB_INTR_SOF_EN                      0x00000080
-#define  USB_INTR_DEVICE_SUSPEND              0x00000100
-
-/* Device Address bit masks */
-#define  USB_DEVICE_ADDRESS_MASK              0xFE000000
-#define  USB_DEVICE_ADDRESS_BIT_POS           25
-
-/* endpoint list address bit masks */
-#define USB_EP_LIST_ADDRESS_MASK              0xfffff800
-
-/* PORTSCX  Register Bit Masks */
-#define  PORTSCX_CURRENT_CONNECT_STATUS       0x00000001
-#define  PORTSCX_CONNECT_STATUS_CHANGE        0x00000002
-#define  PORTSCX_PORT_ENABLE                  0x00000004
-#define  PORTSCX_PORT_EN_DIS_CHANGE           0x00000008
-#define  PORTSCX_OVER_CURRENT_ACT             0x00000010
-#define  PORTSCX_OVER_CURRENT_CHG             0x00000020
-#define  PORTSCX_PORT_FORCE_RESUME            0x00000040
-#define  PORTSCX_PORT_SUSPEND                 0x00000080
-#define  PORTSCX_PORT_RESET                   0x00000100
-#define  PORTSCX_LINE_STATUS_BITS             0x00000C00
-#define  PORTSCX_PORT_POWER                   0x00001000
-#define  PORTSCX_PORT_INDICTOR_CTRL           0x0000C000
-#define  PORTSCX_PORT_TEST_CTRL               0x000F0000
-#define  PORTSCX_WAKE_ON_CONNECT_EN           0x00100000
-#define  PORTSCX_WAKE_ON_CONNECT_DIS          0x00200000
-#define  PORTSCX_WAKE_ON_OVER_CURRENT         0x00400000
-#define  PORTSCX_PHY_LOW_POWER_SPD            0x00800000
-#define  PORTSCX_PORT_FORCE_FULL_SPEED        0x01000000
-#define  PORTSCX_PORT_SPEED_MASK              0x0C000000
-#define  PORTSCX_PORT_WIDTH                   0x10000000
-#define  PORTSCX_PHY_TYPE_SEL                 0xC0000000
-
-/* bit 11-10 are line status */
-#define  PORTSCX_LINE_STATUS_SE0              0x00000000
-#define  PORTSCX_LINE_STATUS_JSTATE           0x00000400
-#define  PORTSCX_LINE_STATUS_KSTATE           0x00000800
-#define  PORTSCX_LINE_STATUS_UNDEF            0x00000C00
-#define  PORTSCX_LINE_STATUS_BIT_POS          10
-
-/* bit 15-14 are port indicator control */
-#define  PORTSCX_PIC_OFF                      0x00000000
-#define  PORTSCX_PIC_AMBER                    0x00004000
-#define  PORTSCX_PIC_GREEN                    0x00008000
-#define  PORTSCX_PIC_UNDEF                    0x0000C000
-#define  PORTSCX_PIC_BIT_POS                  14
-
-/* bit 19-16 are port test control */
-#define  PORTSCX_PTC_DISABLE                  0x00000000
-#define  PORTSCX_PTC_JSTATE                   0x00010000
-#define  PORTSCX_PTC_KSTATE                   0x00020000
-#define  PORTSCX_PTC_SEQNAK                   0x00030000
-#define  PORTSCX_PTC_PACKET                   0x00040000
-#define  PORTSCX_PTC_FORCE_EN                 0x00050000
-#define  PORTSCX_PTC_BIT_POS                  16
-
-/* bit 27-26 are port speed */
-#define  PORTSCX_PORT_SPEED_FULL              0x00000000
-#define  PORTSCX_PORT_SPEED_LOW               0x04000000
-#define  PORTSCX_PORT_SPEED_HIGH              0x08000000
-#define  PORTSCX_PORT_SPEED_UNDEF             0x0C000000
-#define  PORTSCX_SPEED_BIT_POS                26
-
-/* bit 28 is parallel transceiver width for UTMI interface */
-#define  PORTSCX_PTW                          0x10000000
-#define  PORTSCX_PTW_8BIT                     0x00000000
-#define  PORTSCX_PTW_16BIT                    0x10000000
-
-/* bit 31-30 are port transceiver select */
-#define  PORTSCX_PTS_UTMI                     0x00000000
-#define  PORTSCX_PTS_ULPI                     0x80000000
-#define  PORTSCX_PTS_FSLS                     0xC0000000
-#define  PORTSCX_PTS_BIT_POS                  30
-
-/* otgsc Register Bit Masks */
-#define  OTGSC_CTRL_VUSB_DISCHARGE            0x00000001
-#define  OTGSC_CTRL_VUSB_CHARGE               0x00000002
-#define  OTGSC_CTRL_OTG_TERM                  0x00000008
-#define  OTGSC_CTRL_DATA_PULSING              0x00000010
-#define  OTGSC_STS_USB_ID                     0x00000100
-#define  OTGSC_STS_A_VBUS_VALID               0x00000200
-#define  OTGSC_STS_A_SESSION_VALID            0x00000400
-#define  OTGSC_STS_B_SESSION_VALID            0x00000800
-#define  OTGSC_STS_B_SESSION_END              0x00001000
-#define  OTGSC_STS_1MS_TOGGLE                 0x00002000
-#define  OTGSC_STS_DATA_PULSING               0x00004000
-#define  OTGSC_INTSTS_USB_ID                  0x00010000
-#define  OTGSC_INTSTS_A_VBUS_VALID            0x00020000
-#define  OTGSC_INTSTS_A_SESSION_VALID         0x00040000
-#define  OTGSC_INTSTS_B_SESSION_VALID         0x00080000
-#define  OTGSC_INTSTS_B_SESSION_END           0x00100000
-#define  OTGSC_INTSTS_1MS                     0x00200000
-#define  OTGSC_INTSTS_DATA_PULSING            0x00400000
-#define  OTGSC_INTR_USB_ID                    0x01000000
-#define  OTGSC_INTR_A_VBUS_VALID              0x02000000
-#define  OTGSC_INTR_A_SESSION_VALID           0x04000000
-#define  OTGSC_INTR_B_SESSION_VALID           0x08000000
-#define  OTGSC_INTR_B_SESSION_END             0x10000000
-#define  OTGSC_INTR_1MS_TIMER                 0x20000000
-#define  OTGSC_INTR_DATA_PULSING              0x40000000
-
-/* USB MODE Register Bit Masks */
-#define  USB_MODE_CTRL_MODE_IDLE              0x00000000
-#define  USB_MODE_CTRL_MODE_DEVICE            0x00000002
-#define  USB_MODE_CTRL_MODE_HOST              0x00000003
-#define  USB_MODE_CTRL_MODE_MASK              0x00000003
-#define  USB_MODE_CTRL_MODE_RSV               0x00000001
-#define  USB_MODE_ES                          0x00000004 /* Endian Select */
-#define  USB_MODE_SETUP_LOCK_OFF              0x00000008
-#define  USB_MODE_STREAM_DISABLE              0x00000010
-/* Endpoint Flush Register */
-#define EPFLUSH_TX_OFFSET                    0x00010000
-#define EPFLUSH_RX_OFFSET                    0x00000000
-
-/* Endpoint Setup Status bit masks */
-#define  EP_SETUP_STATUS_MASK                 0x0000003F
-#define  EP_SETUP_STATUS_EP0                 0x00000001
-
-/* ENDPOINTCTRLx  Register Bit Masks */
-#define  EPCTRL_TX_ENABLE                     0x00800000
-#define  EPCTRL_TX_DATA_TOGGLE_RST            0x00400000       /* Not EP0 */
-#define  EPCTRL_TX_DATA_TOGGLE_INH            0x00200000       /* Not EP0 */
-#define  EPCTRL_TX_TYPE                       0x000C0000
-#define  EPCTRL_TX_DATA_SOURCE                0x00020000       /* Not EP0 */
-#define  EPCTRL_TX_EP_STALL                   0x00010000
-#define  EPCTRL_RX_ENABLE                     0x00000080
-#define  EPCTRL_RX_DATA_TOGGLE_RST            0x00000040       /* Not EP0 */
-#define  EPCTRL_RX_DATA_TOGGLE_INH            0x00000020       /* Not EP0 */
-#define  EPCTRL_RX_TYPE                       0x0000000C
-#define  EPCTRL_RX_DATA_SINK                  0x00000002       /* Not EP0 */
-#define  EPCTRL_RX_EP_STALL                   0x00000001
-
-/* bit 19-18 and 3-2 are endpoint type */
-#define  EPCTRL_EP_TYPE_CONTROL               0
-#define  EPCTRL_EP_TYPE_ISO                   1
-#define  EPCTRL_EP_TYPE_BULK                  2
-#define  EPCTRL_EP_TYPE_INTERRUPT             3
-#define  EPCTRL_TX_EP_TYPE_SHIFT              18
-#define  EPCTRL_RX_EP_TYPE_SHIFT              2
-
-/* SNOOPn Register Bit Masks */
-#define  SNOOP_ADDRESS_MASK                   0xFFFFF000
-#define  SNOOP_SIZE_ZERO                      0x00     /* snooping disable */
-#define  SNOOP_SIZE_4KB                       0x0B     /* 4KB snoop size */
-#define  SNOOP_SIZE_8KB                       0x0C
-#define  SNOOP_SIZE_16KB                      0x0D
-#define  SNOOP_SIZE_32KB                      0x0E
-#define  SNOOP_SIZE_64KB                      0x0F
-#define  SNOOP_SIZE_128KB                     0x10
-#define  SNOOP_SIZE_256KB                     0x11
-#define  SNOOP_SIZE_512KB                     0x12
-#define  SNOOP_SIZE_1MB                       0x13
-#define  SNOOP_SIZE_2MB                       0x14
-#define  SNOOP_SIZE_4MB                       0x15
-#define  SNOOP_SIZE_8MB                       0x16
-#define  SNOOP_SIZE_16MB                      0x17
-#define  SNOOP_SIZE_32MB                      0x18
-#define  SNOOP_SIZE_64MB                      0x19
-#define  SNOOP_SIZE_128MB                     0x1A
-#define  SNOOP_SIZE_256MB                     0x1B
-#define  SNOOP_SIZE_512MB                     0x1C
-#define  SNOOP_SIZE_1GB                       0x1D
-#define  SNOOP_SIZE_2GB                       0x1E     /* 2GB snoop size */
-
-/* pri_ctrl Register Bit Masks */
-#define  PRI_CTRL_PRI_LVL1                    0x0000000C
-#define  PRI_CTRL_PRI_LVL0                    0x00000003
-
-/* si_ctrl Register Bit Masks */
-#define  SI_CTRL_ERR_DISABLE                  0x00000010
-#define  SI_CTRL_IDRC_DISABLE                 0x00000008
-#define  SI_CTRL_RD_SAFE_EN                   0x00000004
-#define  SI_CTRL_RD_PREFETCH_DISABLE          0x00000002
-#define  SI_CTRL_RD_PREFEFETCH_VAL            0x00000001
-
-/* control Register Bit Masks */
-#define  USB_CTRL_IOENB                       0x00000004
-#define  USB_CTRL_ULPI_INT0EN                 0x00000001
-#define USB_CTRL_UTMI_PHY_EN                 0x00000200
-#define USB_CTRL_USB_EN                              0x00000004
-#define USB_CTRL_ULPI_PHY_CLK_SEL            0x00000400
-
-/* Endpoint Queue Head data struct
- * Rem: all the variables of qh are LittleEndian Mode
- * and NEXT_POINTER_MASK should operate on a LittleEndian, Phy Addr
- */
-struct ep_queue_head {
-       u32 max_pkt_length;     /* Mult(31-30) , Zlt(29) , Max Pkt len
-                                  and IOS(15) */
-       u32 curr_dtd_ptr;       /* Current dTD Pointer(31-5) */
-       u32 next_dtd_ptr;       /* Next dTD Pointer(31-5), T(0) */
-       u32 size_ioc_int_sts;   /* Total bytes (30-16), IOC (15),
-                                  MultO(11-10), STS (7-0)  */
-       u32 buff_ptr0;          /* Buffer pointer Page 0 (31-12) */
-       u32 buff_ptr1;          /* Buffer pointer Page 1 (31-12) */
-       u32 buff_ptr2;          /* Buffer pointer Page 2 (31-12) */
-       u32 buff_ptr3;          /* Buffer pointer Page 3 (31-12) */
-       u32 buff_ptr4;          /* Buffer pointer Page 4 (31-12) */
-       u32 res1;
-       u8 setup_buffer[8];     /* Setup data 8 bytes */
-       u32 res2[4];
-};
-
-/* Endpoint Queue Head Bit Masks */
-#define  EP_QUEUE_HEAD_MULT_POS               30
-#define  EP_QUEUE_HEAD_ZLT_SEL                0x20000000
-#define  EP_QUEUE_HEAD_MAX_PKT_LEN_POS        16
-#define  EP_QUEUE_HEAD_MAX_PKT_LEN(ep_info)   (((ep_info)>>16)&0x07ff)
-#define  EP_QUEUE_HEAD_IOS                    0x00008000
-#define  EP_QUEUE_HEAD_NEXT_TERMINATE         0x00000001
-#define  EP_QUEUE_HEAD_IOC                    0x00008000
-#define  EP_QUEUE_HEAD_MULTO                  0x00000C00
-#define  EP_QUEUE_HEAD_STATUS_HALT           0x00000040
-#define  EP_QUEUE_HEAD_STATUS_ACTIVE          0x00000080
-#define  EP_QUEUE_CURRENT_OFFSET_MASK         0x00000FFF
-#define  EP_QUEUE_HEAD_NEXT_POINTER_MASK      0xFFFFFFE0
-#define  EP_QUEUE_FRINDEX_MASK                0x000007FF
-#define  EP_MAX_LENGTH_TRANSFER               0x4000
-
-/* Endpoint Transfer Descriptor data struct */
-/* Rem: all the variables of td are LittleEndian Mode */
-struct ep_td_struct {
-       u32 next_td_ptr;        /* Next TD pointer(31-5), T(0) set
-                                  indicate invalid */
-       u32 size_ioc_sts;       /* Total bytes (30-16), IOC (15),
-                                  MultO(11-10), STS (7-0)  */
-       u32 buff_ptr0;          /* Buffer pointer Page 0 */
-       u32 buff_ptr1;          /* Buffer pointer Page 1 */
-       u32 buff_ptr2;          /* Buffer pointer Page 2 */
-       u32 buff_ptr3;          /* Buffer pointer Page 3 */
-       u32 buff_ptr4;          /* Buffer pointer Page 4 */
-       u32 res;
-       /* 32 bytes */
-       dma_addr_t td_dma;      /* dma address for this td */
-       /* virtual address of next td specified in next_td_ptr */
-       struct ep_td_struct *next_td_virt;
-};
-
-/* Endpoint Transfer Descriptor bit Masks */
-#define  DTD_NEXT_TERMINATE                   0x00000001
-#define  DTD_IOC                              0x00008000
-#define  DTD_STATUS_ACTIVE                    0x00000080
-#define  DTD_STATUS_HALTED                    0x00000040
-#define  DTD_STATUS_DATA_BUFF_ERR             0x00000020
-#define  DTD_STATUS_TRANSACTION_ERR           0x00000008
-#define  DTD_RESERVED_FIELDS                  0x80007300
-#define  DTD_ADDR_MASK                        0xFFFFFFE0
-#define  DTD_PACKET_SIZE                      0x7FFF0000
-#define  DTD_LENGTH_BIT_POS                   16
-#define  DTD_ERROR_MASK                       (DTD_STATUS_HALTED | \
-                                               DTD_STATUS_DATA_BUFF_ERR | \
-                                               DTD_STATUS_TRANSACTION_ERR)
-/* Alignment requirements; must be a power of two */
-#define DTD_ALIGNMENT                          0x20
-#define QH_ALIGNMENT                           2048
-
-/* Controller dma boundary */
-#define UDC_DMA_BOUNDARY                       0x1000
-
-/*-------------------------------------------------------------------------*/
-
-/* ### driver private data
- */
-struct fsl_req {
-       struct usb_request req;
-       struct list_head queue;
-       /* ep_queue() func will add
-          a request->queue into a udc_ep->queue 'd tail */
-       struct fsl_ep *ep;
-       unsigned mapped:1;
-
-       struct ep_td_struct *head, *tail;       /* For dTD List
-                                                  cpu endian Virtual addr */
-       unsigned int dtd_count;
-};
-
-#define REQ_UNCOMPLETE                 1
-
-struct fsl_ep {
-       struct usb_ep ep;
-       struct list_head queue;
-       struct fsl_udc *udc;
-       struct ep_queue_head *qh;
-       struct usb_gadget *gadget;
-
-       char name[14];
-       unsigned stopped:1;
-};
-
-#define EP_DIR_IN      1
-#define EP_DIR_OUT     0
-
-struct fsl_udc {
-       struct usb_gadget gadget;
-       struct usb_gadget_driver *driver;
-       struct fsl_usb2_platform_data *pdata;
-       struct completion *done;        /* to make sure release() is done */
-       struct fsl_ep *eps;
-       unsigned int max_ep;
-       unsigned int irq;
-
-       struct usb_ctrlrequest local_setup_buff;
-       spinlock_t lock;
-       struct usb_phy *transceiver;
-       unsigned softconnect:1;
-       unsigned vbus_active:1;
-       unsigned stopped:1;
-       unsigned remote_wakeup:1;
-       unsigned already_stopped:1;
-       unsigned big_endian_desc:1;
-
-       struct ep_queue_head *ep_qh;    /* Endpoints Queue-Head */
-       struct fsl_req *status_req;     /* ep0 status request */
-       struct dma_pool *td_pool;       /* dma pool for DTD */
-       enum fsl_usb2_phy_modes phy_mode;
-
-       size_t ep_qh_size;              /* size after alignment adjustment*/
-       dma_addr_t ep_qh_dma;           /* dma address of QH */
-
-       u32 max_pipes;          /* Device max pipes */
-       u32 bus_reset;          /* Device is bus resetting */
-       u32 resume_state;       /* USB state to resume */
-       u32 usb_state;          /* USB current state */
-       u32 ep0_state;          /* Endpoint zero state */
-       u32 ep0_dir;            /* Endpoint zero direction: can be
-                                  USB_DIR_IN or USB_DIR_OUT */
-       u8 device_address;      /* Device USB address */
-};
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef DEBUG
-#define DBG(fmt, args...)      printk(KERN_DEBUG "[%s]  " fmt "\n", \
-                               __func__, ## args)
-#else
-#define DBG(fmt, args...)      do{}while(0)
-#endif
-
-#if 0
-static void dump_msg(const char *label, const u8 * buf, unsigned int length)
-{
-       unsigned int start, num, i;
-       char line[52], *p;
-
-       if (length >= 512)
-               return;
-       DBG("%s, length %u:\n", label, length);
-       start = 0;
-       while (length > 0) {
-               num = min(length, 16u);
-               p = line;
-               for (i = 0; i < num; ++i) {
-                       if (i == 8)
-                               *p++ = ' ';
-                       sprintf(p, " %02x", buf[i]);
-                       p += 3;
-               }
-               *p = 0;
-               printk(KERN_DEBUG "%6x: %s\n", start, line);
-               buf += num;
-               start += num;
-               length -= num;
-       }
-}
-#endif
-
-#ifdef VERBOSE
-#define VDBG           DBG
-#else
-#define VDBG(stuff...) do{}while(0)
-#endif
-
-#define ERR(stuff...)          pr_err("udc: " stuff)
-#define WARNING(stuff...)              pr_warning("udc: " stuff)
-#define INFO(stuff...)         pr_info("udc: " stuff)
-
-/*-------------------------------------------------------------------------*/
-
-/* ### Add board specific defines here
- */
-
-/*
- * ### pipe direction macro from device view
- */
-#define USB_RECV       0       /* OUT EP */
-#define USB_SEND       1       /* IN EP */
-
-/*
- * ### internal used help routines.
- */
-#define ep_index(EP)           ((EP)->ep.desc->bEndpointAddress&0xF)
-#define ep_maxpacket(EP)       ((EP)->ep.maxpacket)
-#define ep_is_in(EP)   ( (ep_index(EP) == 0) ? (EP->udc->ep0_dir == \
-                       USB_DIR_IN) : ((EP)->ep.desc->bEndpointAddress \
-                       & USB_DIR_IN)==USB_DIR_IN)
-#define get_ep_by_pipe(udc, pipe)      ((pipe == 1)? &udc->eps[0]: \
-                                       &udc->eps[pipe])
-#define get_pipe_by_windex(windex)     ((windex & USB_ENDPOINT_NUMBER_MASK) \
-                                       * 2 + ((windex & USB_DIR_IN) ? 1 : 0))
-#define get_pipe_by_ep(EP)     (ep_index(EP) * 2 + ep_is_in(EP))
-
-static inline struct ep_queue_head *get_qh_by_ep(struct fsl_ep *ep)
-{
-       /* we only have one ep0 structure but two queue heads */
-       if (ep_index(ep) != 0)
-               return ep->qh;
-       else
-               return &ep->udc->ep_qh[(ep->udc->ep0_dir ==
-                               USB_DIR_IN) ? 1 : 0];
-}
-
-struct platform_device;
-#ifdef CONFIG_ARCH_MXC
-int fsl_udc_clk_init(struct platform_device *pdev);
-int fsl_udc_clk_finalize(struct platform_device *pdev);
-void fsl_udc_clk_release(void);
-#else
-static inline int fsl_udc_clk_init(struct platform_device *pdev)
-{
-       return 0;
-}
-static inline int fsl_udc_clk_finalize(struct platform_device *pdev)
-{
-       return 0;
-}
-static inline void fsl_udc_clk_release(void)
-{
-}
-#endif
-
-#endif
diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c
deleted file mode 100644 (file)
index d40255f..0000000
+++ /dev/null
@@ -1,1499 +0,0 @@
-/*
- * Fusb300 UDC (USB gadget)
- *
- * Copyright (C) 2010 Faraday Technology Corp.
- *
- * Author : Yuan-hsin Chen <yhchen@faraday-tech.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- */
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include "fusb300_udc.h"
-
-MODULE_DESCRIPTION("FUSB300  USB gadget driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Yuan-Hsin Chen, Feng-Hsin Chiang <john453@faraday-tech.com>");
-MODULE_ALIAS("platform:fusb300_udc");
-
-#define DRIVER_VERSION "20 October 2010"
-
-static const char udc_name[] = "fusb300_udc";
-static const char * const fusb300_ep_name[] = {
-       "ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7", "ep8", "ep9",
-       "ep10", "ep11", "ep12", "ep13", "ep14", "ep15"
-};
-
-static void done(struct fusb300_ep *ep, struct fusb300_request *req,
-                int status);
-
-static void fusb300_enable_bit(struct fusb300 *fusb300, u32 offset,
-                              u32 value)
-{
-       u32 reg = ioread32(fusb300->reg + offset);
-
-       reg |= value;
-       iowrite32(reg, fusb300->reg + offset);
-}
-
-static void fusb300_disable_bit(struct fusb300 *fusb300, u32 offset,
-                               u32 value)
-{
-       u32 reg = ioread32(fusb300->reg + offset);
-
-       reg &= ~value;
-       iowrite32(reg, fusb300->reg + offset);
-}
-
-
-static void fusb300_ep_setting(struct fusb300_ep *ep,
-                              struct fusb300_ep_info info)
-{
-       ep->epnum = info.epnum;
-       ep->type = info.type;
-}
-
-static int fusb300_ep_release(struct fusb300_ep *ep)
-{
-       if (!ep->epnum)
-               return 0;
-       ep->epnum = 0;
-       ep->stall = 0;
-       ep->wedged = 0;
-       return 0;
-}
-
-static void fusb300_set_fifo_entry(struct fusb300 *fusb300,
-                                  u32 ep)
-{
-       u32 val = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
-
-       val &= ~FUSB300_EPSET1_FIFOENTRY_MSK;
-       val |= FUSB300_EPSET1_FIFOENTRY(FUSB300_FIFO_ENTRY_NUM);
-       iowrite32(val, fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
-}
-
-static void fusb300_set_start_entry(struct fusb300 *fusb300,
-                                   u8 ep)
-{
-       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
-       u32 start_entry = fusb300->fifo_entry_num * FUSB300_FIFO_ENTRY_NUM;
-
-       reg &= ~FUSB300_EPSET1_START_ENTRY_MSK  ;
-       reg |= FUSB300_EPSET1_START_ENTRY(start_entry);
-       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
-       if (fusb300->fifo_entry_num == FUSB300_MAX_FIFO_ENTRY) {
-               fusb300->fifo_entry_num = 0;
-               fusb300->addrofs = 0;
-               pr_err("fifo entry is over the maximum number!\n");
-       } else
-               fusb300->fifo_entry_num++;
-}
-
-/* set fusb300_set_start_entry first before fusb300_set_epaddrofs */
-static void fusb300_set_epaddrofs(struct fusb300 *fusb300,
-                                 struct fusb300_ep_info info)
-{
-       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET2(info.epnum));
-
-       reg &= ~FUSB300_EPSET2_ADDROFS_MSK;
-       reg |= FUSB300_EPSET2_ADDROFS(fusb300->addrofs);
-       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET2(info.epnum));
-       fusb300->addrofs += (info.maxpacket + 7) / 8 * FUSB300_FIFO_ENTRY_NUM;
-}
-
-static void ep_fifo_setting(struct fusb300 *fusb300,
-                           struct fusb300_ep_info info)
-{
-       fusb300_set_fifo_entry(fusb300, info.epnum);
-       fusb300_set_start_entry(fusb300, info.epnum);
-       fusb300_set_epaddrofs(fusb300, info);
-}
-
-static void fusb300_set_eptype(struct fusb300 *fusb300,
-                              struct fusb300_ep_info info)
-{
-       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
-
-       reg &= ~FUSB300_EPSET1_TYPE_MSK;
-       reg |= FUSB300_EPSET1_TYPE(info.type);
-       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
-}
-
-static void fusb300_set_epdir(struct fusb300 *fusb300,
-                             struct fusb300_ep_info info)
-{
-       u32 reg;
-
-       if (!info.dir_in)
-               return;
-       reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
-       reg &= ~FUSB300_EPSET1_DIR_MSK;
-       reg |= FUSB300_EPSET1_DIRIN;
-       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
-}
-
-static void fusb300_set_ep_active(struct fusb300 *fusb300,
-                         u8 ep)
-{
-       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
-
-       reg |= FUSB300_EPSET1_ACTEN;
-       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
-}
-
-static void fusb300_set_epmps(struct fusb300 *fusb300,
-                             struct fusb300_ep_info info)
-{
-       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET2(info.epnum));
-
-       reg &= ~FUSB300_EPSET2_MPS_MSK;
-       reg |= FUSB300_EPSET2_MPS(info.maxpacket);
-       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET2(info.epnum));
-}
-
-static void fusb300_set_interval(struct fusb300 *fusb300,
-                                struct fusb300_ep_info info)
-{
-       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
-
-       reg &= ~FUSB300_EPSET1_INTERVAL(0x7);
-       reg |= FUSB300_EPSET1_INTERVAL(info.interval);
-       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
-}
-
-static void fusb300_set_bwnum(struct fusb300 *fusb300,
-                             struct fusb300_ep_info info)
-{
-       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
-
-       reg &= ~FUSB300_EPSET1_BWNUM(0x3);
-       reg |= FUSB300_EPSET1_BWNUM(info.bw_num);
-       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
-}
-
-static void set_ep_reg(struct fusb300 *fusb300,
-                     struct fusb300_ep_info info)
-{
-       fusb300_set_eptype(fusb300, info);
-       fusb300_set_epdir(fusb300, info);
-       fusb300_set_epmps(fusb300, info);
-
-       if (info.interval)
-               fusb300_set_interval(fusb300, info);
-
-       if (info.bw_num)
-               fusb300_set_bwnum(fusb300, info);
-
-       fusb300_set_ep_active(fusb300, info.epnum);
-}
-
-static int config_ep(struct fusb300_ep *ep,
-                    const struct usb_endpoint_descriptor *desc)
-{
-       struct fusb300 *fusb300 = ep->fusb300;
-       struct fusb300_ep_info info;
-
-       ep->ep.desc = desc;
-
-       info.interval = 0;
-       info.addrofs = 0;
-       info.bw_num = 0;
-
-       info.type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-       info.dir_in = (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? 1 : 0;
-       info.maxpacket = usb_endpoint_maxp(desc);
-       info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-
-       if ((info.type == USB_ENDPOINT_XFER_INT) ||
-          (info.type == USB_ENDPOINT_XFER_ISOC)) {
-               info.interval = desc->bInterval;
-               if (info.type == USB_ENDPOINT_XFER_ISOC)
-                       info.bw_num = ((desc->wMaxPacketSize & 0x1800) >> 11);
-       }
-
-       ep_fifo_setting(fusb300, info);
-
-       set_ep_reg(fusb300, info);
-
-       fusb300_ep_setting(ep, info);
-
-       fusb300->ep[info.epnum] = ep;
-
-       return 0;
-}
-
-static int fusb300_enable(struct usb_ep *_ep,
-                         const struct usb_endpoint_descriptor *desc)
-{
-       struct fusb300_ep *ep;
-
-       ep = container_of(_ep, struct fusb300_ep, ep);
-
-       if (ep->fusb300->reenum) {
-               ep->fusb300->fifo_entry_num = 0;
-               ep->fusb300->addrofs = 0;
-               ep->fusb300->reenum = 0;
-       }
-
-       return config_ep(ep, desc);
-}
-
-static int fusb300_disable(struct usb_ep *_ep)
-{
-       struct fusb300_ep *ep;
-       struct fusb300_request *req;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct fusb300_ep, ep);
-
-       BUG_ON(!ep);
-
-       while (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next, struct fusb300_request, queue);
-               spin_lock_irqsave(&ep->fusb300->lock, flags);
-               done(ep, req, -ECONNRESET);
-               spin_unlock_irqrestore(&ep->fusb300->lock, flags);
-       }
-
-       return fusb300_ep_release(ep);
-}
-
-static struct usb_request *fusb300_alloc_request(struct usb_ep *_ep,
-                                               gfp_t gfp_flags)
-{
-       struct fusb300_request *req;
-
-       req = kzalloc(sizeof(struct fusb300_request), gfp_flags);
-       if (!req)
-               return NULL;
-       INIT_LIST_HEAD(&req->queue);
-
-       return &req->req;
-}
-
-static void fusb300_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct fusb300_request *req;
-
-       req = container_of(_req, struct fusb300_request, req);
-       kfree(req);
-}
-
-static int enable_fifo_int(struct fusb300_ep *ep)
-{
-       struct fusb300 *fusb300 = ep->fusb300;
-
-       if (ep->epnum) {
-               fusb300_enable_bit(fusb300, FUSB300_OFFSET_IGER0,
-                       FUSB300_IGER0_EEPn_FIFO_INT(ep->epnum));
-       } else {
-               pr_err("can't enable_fifo_int ep0\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int disable_fifo_int(struct fusb300_ep *ep)
-{
-       struct fusb300 *fusb300 = ep->fusb300;
-
-       if (ep->epnum) {
-               fusb300_disable_bit(fusb300, FUSB300_OFFSET_IGER0,
-                       FUSB300_IGER0_EEPn_FIFO_INT(ep->epnum));
-       } else {
-               pr_err("can't disable_fifo_int ep0\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static void fusb300_set_cxlen(struct fusb300 *fusb300, u32 length)
-{
-       u32 reg;
-
-       reg = ioread32(fusb300->reg + FUSB300_OFFSET_CSR);
-       reg &= ~FUSB300_CSR_LEN_MSK;
-       reg |= FUSB300_CSR_LEN(length);
-       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_CSR);
-}
-
-/* write data to cx fifo */
-static void fusb300_wrcxf(struct fusb300_ep *ep,
-                  struct fusb300_request *req)
-{
-       int i = 0;
-       u8 *tmp;
-       u32 data;
-       struct fusb300 *fusb300 = ep->fusb300;
-       u32 length = req->req.length - req->req.actual;
-
-       tmp = req->req.buf + req->req.actual;
-
-       if (length > SS_CTL_MAX_PACKET_SIZE) {
-               fusb300_set_cxlen(fusb300, SS_CTL_MAX_PACKET_SIZE);
-               for (i = (SS_CTL_MAX_PACKET_SIZE >> 2); i > 0; i--) {
-                       data = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16 |
-                               *(tmp + 3) << 24;
-                       iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
-                       tmp += 4;
-               }
-               req->req.actual += SS_CTL_MAX_PACKET_SIZE;
-       } else { /* length is less than max packet size */
-               fusb300_set_cxlen(fusb300, length);
-               for (i = length >> 2; i > 0; i--) {
-                       data = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16 |
-                               *(tmp + 3) << 24;
-                       printk(KERN_DEBUG "    0x%x\n", data);
-                       iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
-                       tmp = tmp + 4;
-               }
-               switch (length % 4) {
-               case 1:
-                       data = *tmp;
-                       printk(KERN_DEBUG "    0x%x\n", data);
-                       iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
-                       break;
-               case 2:
-                       data = *tmp | *(tmp + 1) << 8;
-                       printk(KERN_DEBUG "    0x%x\n", data);
-                       iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
-                       break;
-               case 3:
-                       data = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16;
-                       printk(KERN_DEBUG "    0x%x\n", data);
-                       iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
-                       break;
-               default:
-                       break;
-               }
-               req->req.actual += length;
-       }
-}
-
-static void fusb300_set_epnstall(struct fusb300 *fusb300, u8 ep)
-{
-       fusb300_enable_bit(fusb300, FUSB300_OFFSET_EPSET0(ep),
-               FUSB300_EPSET0_STL);
-}
-
-static void fusb300_clear_epnstall(struct fusb300 *fusb300, u8 ep)
-{
-       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
-
-       if (reg & FUSB300_EPSET0_STL) {
-               printk(KERN_DEBUG "EP%d stall... Clear!!\n", ep);
-               reg |= FUSB300_EPSET0_STL_CLR;
-               iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
-       }
-}
-
-static void ep0_queue(struct fusb300_ep *ep, struct fusb300_request *req)
-{
-       if (ep->fusb300->ep0_dir) { /* if IN */
-               if (req->req.length) {
-                       fusb300_wrcxf(ep, req);
-               } else
-                       printk(KERN_DEBUG "%s : req->req.length = 0x%x\n",
-                               __func__, req->req.length);
-               if ((req->req.length == req->req.actual) ||
-                   (req->req.actual < ep->ep.maxpacket))
-                       done(ep, req, 0);
-       } else { /* OUT */
-               if (!req->req.length)
-                       done(ep, req, 0);
-               else
-                       fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER1,
-                               FUSB300_IGER1_CX_OUT_INT);
-       }
-}
-
-static int fusb300_queue(struct usb_ep *_ep, struct usb_request *_req,
-                        gfp_t gfp_flags)
-{
-       struct fusb300_ep *ep;
-       struct fusb300_request *req;
-       unsigned long flags;
-       int request  = 0;
-
-       ep = container_of(_ep, struct fusb300_ep, ep);
-       req = container_of(_req, struct fusb300_request, req);
-
-       if (ep->fusb300->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       spin_lock_irqsave(&ep->fusb300->lock, flags);
-
-       if (list_empty(&ep->queue))
-               request = 1;
-
-       list_add_tail(&req->queue, &ep->queue);
-
-       req->req.actual = 0;
-       req->req.status = -EINPROGRESS;
-
-       if (ep->ep.desc == NULL) /* ep0 */
-               ep0_queue(ep, req);
-       else if (request && !ep->stall)
-               enable_fifo_int(ep);
-
-       spin_unlock_irqrestore(&ep->fusb300->lock, flags);
-
-       return 0;
-}
-
-static int fusb300_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct fusb300_ep *ep;
-       struct fusb300_request *req;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct fusb300_ep, ep);
-       req = container_of(_req, struct fusb300_request, req);
-
-       spin_lock_irqsave(&ep->fusb300->lock, flags);
-       if (!list_empty(&ep->queue))
-               done(ep, req, -ECONNRESET);
-       spin_unlock_irqrestore(&ep->fusb300->lock, flags);
-
-       return 0;
-}
-
-static int fusb300_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedge)
-{
-       struct fusb300_ep *ep;
-       struct fusb300 *fusb300;
-       unsigned long flags;
-       int ret = 0;
-
-       ep = container_of(_ep, struct fusb300_ep, ep);
-
-       fusb300 = ep->fusb300;
-
-       spin_lock_irqsave(&ep->fusb300->lock, flags);
-
-       if (!list_empty(&ep->queue)) {
-               ret = -EAGAIN;
-               goto out;
-       }
-
-       if (value) {
-               fusb300_set_epnstall(fusb300, ep->epnum);
-               ep->stall = 1;
-               if (wedge)
-                       ep->wedged = 1;
-       } else {
-               fusb300_clear_epnstall(fusb300, ep->epnum);
-               ep->stall = 0;
-               ep->wedged = 0;
-       }
-
-out:
-       spin_unlock_irqrestore(&ep->fusb300->lock, flags);
-       return ret;
-}
-
-static int fusb300_set_halt(struct usb_ep *_ep, int value)
-{
-       return fusb300_set_halt_and_wedge(_ep, value, 0);
-}
-
-static int fusb300_set_wedge(struct usb_ep *_ep)
-{
-       return fusb300_set_halt_and_wedge(_ep, 1, 1);
-}
-
-static void fusb300_fifo_flush(struct usb_ep *_ep)
-{
-}
-
-static struct usb_ep_ops fusb300_ep_ops = {
-       .enable         = fusb300_enable,
-       .disable        = fusb300_disable,
-
-       .alloc_request  = fusb300_alloc_request,
-       .free_request   = fusb300_free_request,
-
-       .queue          = fusb300_queue,
-       .dequeue        = fusb300_dequeue,
-
-       .set_halt       = fusb300_set_halt,
-       .fifo_flush     = fusb300_fifo_flush,
-       .set_wedge      = fusb300_set_wedge,
-};
-
-/*****************************************************************************/
-static void fusb300_clear_int(struct fusb300 *fusb300, u32 offset,
-                      u32 value)
-{
-       iowrite32(value, fusb300->reg + offset);
-}
-
-static void fusb300_reset(void)
-{
-}
-
-static void fusb300_set_cxstall(struct fusb300 *fusb300)
-{
-       fusb300_enable_bit(fusb300, FUSB300_OFFSET_CSR,
-                          FUSB300_CSR_STL);
-}
-
-static void fusb300_set_cxdone(struct fusb300 *fusb300)
-{
-       fusb300_enable_bit(fusb300, FUSB300_OFFSET_CSR,
-                          FUSB300_CSR_DONE);
-}
-
-/* read data from cx fifo */
-static void fusb300_rdcxf(struct fusb300 *fusb300,
-                  u8 *buffer, u32 length)
-{
-       int i = 0;
-       u8 *tmp;
-       u32 data;
-
-       tmp = buffer;
-
-       for (i = (length >> 2); i > 0; i--) {
-               data = ioread32(fusb300->reg + FUSB300_OFFSET_CXPORT);
-               printk(KERN_DEBUG "    0x%x\n", data);
-               *tmp = data & 0xFF;
-               *(tmp + 1) = (data >> 8) & 0xFF;
-               *(tmp + 2) = (data >> 16) & 0xFF;
-               *(tmp + 3) = (data >> 24) & 0xFF;
-               tmp = tmp + 4;
-       }
-
-       switch (length % 4) {
-       case 1:
-               data = ioread32(fusb300->reg + FUSB300_OFFSET_CXPORT);
-               printk(KERN_DEBUG "    0x%x\n", data);
-               *tmp = data & 0xFF;
-               break;
-       case 2:
-               data = ioread32(fusb300->reg + FUSB300_OFFSET_CXPORT);
-               printk(KERN_DEBUG "    0x%x\n", data);
-               *tmp = data & 0xFF;
-               *(tmp + 1) = (data >> 8) & 0xFF;
-               break;
-       case 3:
-               data = ioread32(fusb300->reg + FUSB300_OFFSET_CXPORT);
-               printk(KERN_DEBUG "    0x%x\n", data);
-               *tmp = data & 0xFF;
-               *(tmp + 1) = (data >> 8) & 0xFF;
-               *(tmp + 2) = (data >> 16) & 0xFF;
-               break;
-       default:
-               break;
-       }
-}
-
-static void fusb300_rdfifo(struct fusb300_ep *ep,
-                         struct fusb300_request *req,
-                         u32 length)
-{
-       int i = 0;
-       u8 *tmp;
-       u32 data, reg;
-       struct fusb300 *fusb300 = ep->fusb300;
-
-       tmp = req->req.buf + req->req.actual;
-       req->req.actual += length;
-
-       if (req->req.actual > req->req.length)
-               printk(KERN_DEBUG "req->req.actual > req->req.length\n");
-
-       for (i = (length >> 2); i > 0; i--) {
-               data = ioread32(fusb300->reg +
-                       FUSB300_OFFSET_EPPORT(ep->epnum));
-               *tmp = data & 0xFF;
-               *(tmp + 1) = (data >> 8) & 0xFF;
-               *(tmp + 2) = (data >> 16) & 0xFF;
-               *(tmp + 3) = (data >> 24) & 0xFF;
-               tmp = tmp + 4;
-       }
-
-       switch (length % 4) {
-       case 1:
-               data = ioread32(fusb300->reg +
-                       FUSB300_OFFSET_EPPORT(ep->epnum));
-               *tmp = data & 0xFF;
-               break;
-       case 2:
-               data = ioread32(fusb300->reg +
-                       FUSB300_OFFSET_EPPORT(ep->epnum));
-               *tmp = data & 0xFF;
-               *(tmp + 1) = (data >> 8) & 0xFF;
-               break;
-       case 3:
-               data = ioread32(fusb300->reg +
-                       FUSB300_OFFSET_EPPORT(ep->epnum));
-               *tmp = data & 0xFF;
-               *(tmp + 1) = (data >> 8) & 0xFF;
-               *(tmp + 2) = (data >> 16) & 0xFF;
-               break;
-       default:
-               break;
-       }
-
-       do {
-               reg = ioread32(fusb300->reg + FUSB300_OFFSET_IGR1);
-               reg &= FUSB300_IGR1_SYNF0_EMPTY_INT;
-               if (i)
-                       printk(KERN_INFO "sync fifo is not empty!\n");
-               i++;
-       } while (!reg);
-}
-
-static u8 fusb300_get_epnstall(struct fusb300 *fusb300, u8 ep)
-{
-       u8 value;
-       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
-
-       value = reg & FUSB300_EPSET0_STL;
-
-       return value;
-}
-
-static u8 fusb300_get_cxstall(struct fusb300 *fusb300)
-{
-       u8 value;
-       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_CSR);
-
-       value = (reg & FUSB300_CSR_STL) >> 1;
-
-       return value;
-}
-
-static void request_error(struct fusb300 *fusb300)
-{
-       fusb300_set_cxstall(fusb300);
-       printk(KERN_DEBUG "request error!!\n");
-}
-
-static void get_status(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
-__releases(fusb300->lock)
-__acquires(fusb300->lock)
-{
-       u8 ep;
-       u16 status = 0;
-       u16 w_index = ctrl->wIndex;
-
-       switch (ctrl->bRequestType & USB_RECIP_MASK) {
-       case USB_RECIP_DEVICE:
-               status = 1 << USB_DEVICE_SELF_POWERED;
-               break;
-       case USB_RECIP_INTERFACE:
-               status = 0;
-               break;
-       case USB_RECIP_ENDPOINT:
-               ep = w_index & USB_ENDPOINT_NUMBER_MASK;
-               if (ep) {
-                       if (fusb300_get_epnstall(fusb300, ep))
-                               status = 1 << USB_ENDPOINT_HALT;
-               } else {
-                       if (fusb300_get_cxstall(fusb300))
-                               status = 0;
-               }
-               break;
-
-       default:
-               request_error(fusb300);
-               return;         /* exit */
-       }
-
-       fusb300->ep0_data = cpu_to_le16(status);
-       fusb300->ep0_req->buf = &fusb300->ep0_data;
-       fusb300->ep0_req->length = 2;
-
-       spin_unlock(&fusb300->lock);
-       fusb300_queue(fusb300->gadget.ep0, fusb300->ep0_req, GFP_KERNEL);
-       spin_lock(&fusb300->lock);
-}
-
-static void set_feature(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
-{
-       u8 ep;
-
-       switch (ctrl->bRequestType & USB_RECIP_MASK) {
-       case USB_RECIP_DEVICE:
-               fusb300_set_cxdone(fusb300);
-               break;
-       case USB_RECIP_INTERFACE:
-               fusb300_set_cxdone(fusb300);
-               break;
-       case USB_RECIP_ENDPOINT: {
-               u16 w_index = le16_to_cpu(ctrl->wIndex);
-
-               ep = w_index & USB_ENDPOINT_NUMBER_MASK;
-               if (ep)
-                       fusb300_set_epnstall(fusb300, ep);
-               else
-                       fusb300_set_cxstall(fusb300);
-               fusb300_set_cxdone(fusb300);
-               }
-               break;
-       default:
-               request_error(fusb300);
-               break;
-       }
-}
-
-static void fusb300_clear_seqnum(struct fusb300 *fusb300, u8 ep)
-{
-       fusb300_enable_bit(fusb300, FUSB300_OFFSET_EPSET0(ep),
-                           FUSB300_EPSET0_CLRSEQNUM);
-}
-
-static void clear_feature(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
-{
-       struct fusb300_ep *ep =
-               fusb300->ep[ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK];
-
-       switch (ctrl->bRequestType & USB_RECIP_MASK) {
-       case USB_RECIP_DEVICE:
-               fusb300_set_cxdone(fusb300);
-               break;
-       case USB_RECIP_INTERFACE:
-               fusb300_set_cxdone(fusb300);
-               break;
-       case USB_RECIP_ENDPOINT:
-               if (ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK) {
-                       if (ep->wedged) {
-                               fusb300_set_cxdone(fusb300);
-                               break;
-                       }
-                       if (ep->stall) {
-                               ep->stall = 0;
-                               fusb300_clear_seqnum(fusb300, ep->epnum);
-                               fusb300_clear_epnstall(fusb300, ep->epnum);
-                               if (!list_empty(&ep->queue))
-                                       enable_fifo_int(ep);
-                       }
-               }
-               fusb300_set_cxdone(fusb300);
-               break;
-       default:
-               request_error(fusb300);
-               break;
-       }
-}
-
-static void fusb300_set_dev_addr(struct fusb300 *fusb300, u16 addr)
-{
-       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_DAR);
-
-       reg &= ~FUSB300_DAR_DRVADDR_MSK;
-       reg |= FUSB300_DAR_DRVADDR(addr);
-
-       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_DAR);
-}
-
-static void set_address(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
-{
-       if (ctrl->wValue >= 0x0100)
-               request_error(fusb300);
-       else {
-               fusb300_set_dev_addr(fusb300, ctrl->wValue);
-               fusb300_set_cxdone(fusb300);
-       }
-}
-
-#define UVC_COPY_DESCRIPTORS(mem, src) \
-       do { \
-               const struct usb_descriptor_header * const *__src; \
-               for (__src = src; *__src; ++__src) { \
-                       memcpy(mem, *__src, (*__src)->bLength); \
-                       mem += (*__src)->bLength; \
-               } \
-       } while (0)
-
-static int setup_packet(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
-{
-       u8 *p = (u8 *)ctrl;
-       u8 ret = 0;
-       u8 i = 0;
-
-       fusb300_rdcxf(fusb300, p, 8);
-       fusb300->ep0_dir = ctrl->bRequestType & USB_DIR_IN;
-       fusb300->ep0_length = ctrl->wLength;
-
-       /* check request */
-       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
-               switch (ctrl->bRequest) {
-               case USB_REQ_GET_STATUS:
-                       get_status(fusb300, ctrl);
-                       break;
-               case USB_REQ_CLEAR_FEATURE:
-                       clear_feature(fusb300, ctrl);
-                       break;
-               case USB_REQ_SET_FEATURE:
-                       set_feature(fusb300, ctrl);
-                       break;
-               case USB_REQ_SET_ADDRESS:
-                       set_address(fusb300, ctrl);
-                       break;
-               case USB_REQ_SET_CONFIGURATION:
-                       fusb300_enable_bit(fusb300, FUSB300_OFFSET_DAR,
-                                          FUSB300_DAR_SETCONFG);
-                       /* clear sequence number */
-                       for (i = 1; i <= FUSB300_MAX_NUM_EP; i++)
-                               fusb300_clear_seqnum(fusb300, i);
-                       fusb300->reenum = 1;
-                       ret = 1;
-                       break;
-               default:
-                       ret = 1;
-                       break;
-               }
-       } else
-               ret = 1;
-
-       return ret;
-}
-
-static void done(struct fusb300_ep *ep, struct fusb300_request *req,
-                int status)
-{
-       list_del_init(&req->queue);
-
-       /* don't modify queue heads during completion callback */
-       if (ep->fusb300->gadget.speed == USB_SPEED_UNKNOWN)
-               req->req.status = -ESHUTDOWN;
-       else
-               req->req.status = status;
-
-       spin_unlock(&ep->fusb300->lock);
-       req->req.complete(&ep->ep, &req->req);
-       spin_lock(&ep->fusb300->lock);
-
-       if (ep->epnum) {
-               disable_fifo_int(ep);
-               if (!list_empty(&ep->queue))
-                       enable_fifo_int(ep);
-       } else
-               fusb300_set_cxdone(ep->fusb300);
-}
-
-static void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep, dma_addr_t d,
-               u32 len)
-{
-       u32 value;
-       u32 reg;
-
-       /* wait SW owner */
-       do {
-               reg = ioread32(ep->fusb300->reg +
-                       FUSB300_OFFSET_EPPRD_W0(ep->epnum));
-               reg &= FUSB300_EPPRD0_H;
-       } while (reg);
-
-       iowrite32(d, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W1(ep->epnum));
-
-       value = FUSB300_EPPRD0_BTC(len) | FUSB300_EPPRD0_H |
-               FUSB300_EPPRD0_F | FUSB300_EPPRD0_L | FUSB300_EPPRD0_I;
-       iowrite32(value, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W0(ep->epnum));
-
-       iowrite32(0x0, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W2(ep->epnum));
-
-       fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_EPPRDRDY,
-               FUSB300_EPPRDR_EP_PRD_RDY(ep->epnum));
-}
-
-static void fusb300_wait_idma_finished(struct fusb300_ep *ep)
-{
-       u32 reg;
-
-       do {
-               reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGR1);
-               if ((reg & FUSB300_IGR1_VBUS_CHG_INT) ||
-                   (reg & FUSB300_IGR1_WARM_RST_INT) ||
-                   (reg & FUSB300_IGR1_HOT_RST_INT) ||
-                   (reg & FUSB300_IGR1_USBRST_INT)
-               )
-                       goto IDMA_RESET;
-               reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGR0);
-               reg &= FUSB300_IGR0_EPn_PRD_INT(ep->epnum);
-       } while (!reg);
-
-       fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0,
-               FUSB300_IGR0_EPn_PRD_INT(ep->epnum));
-       return;
-
-IDMA_RESET:
-       reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGER0);
-       reg &= ~FUSB300_IGER0_EEPn_PRD_INT(ep->epnum);
-       iowrite32(reg, ep->fusb300->reg + FUSB300_OFFSET_IGER0);
-}
-
-static void fusb300_set_idma(struct fusb300_ep *ep,
-                       struct fusb300_request *req)
-{
-       int ret;
-
-       ret = usb_gadget_map_request(&ep->fusb300->gadget,
-                       &req->req, DMA_TO_DEVICE);
-       if (ret)
-               return;
-
-       fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,
-               FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
-
-       fusb300_fill_idma_prdtbl(ep, req->req.dma, req->req.length);
-       /* check idma is done */
-       fusb300_wait_idma_finished(ep);
-
-       usb_gadget_unmap_request(&ep->fusb300->gadget,
-                       &req->req, DMA_TO_DEVICE);
-}
-
-static void in_ep_fifo_handler(struct fusb300_ep *ep)
-{
-       struct fusb300_request *req = list_entry(ep->queue.next,
-                                       struct fusb300_request, queue);
-
-       if (req->req.length)
-               fusb300_set_idma(ep, req);
-       done(ep, req, 0);
-}
-
-static void out_ep_fifo_handler(struct fusb300_ep *ep)
-{
-       struct fusb300 *fusb300 = ep->fusb300;
-       struct fusb300_request *req = list_entry(ep->queue.next,
-                                                struct fusb300_request, queue);
-       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPFFR(ep->epnum));
-       u32 length = reg & FUSB300_FFR_BYCNT;
-
-       fusb300_rdfifo(ep, req, length);
-
-       /* finish out transfer */
-       if ((req->req.length == req->req.actual) || (length < ep->ep.maxpacket))
-               done(ep, req, 0);
-}
-
-static void check_device_mode(struct fusb300 *fusb300)
-{
-       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_GCR);
-
-       switch (reg & FUSB300_GCR_DEVEN_MSK) {
-       case FUSB300_GCR_DEVEN_SS:
-               fusb300->gadget.speed = USB_SPEED_SUPER;
-               break;
-       case FUSB300_GCR_DEVEN_HS:
-               fusb300->gadget.speed = USB_SPEED_HIGH;
-               break;
-       case FUSB300_GCR_DEVEN_FS:
-               fusb300->gadget.speed = USB_SPEED_FULL;
-               break;
-       default:
-               fusb300->gadget.speed = USB_SPEED_UNKNOWN;
-               break;
-       }
-       printk(KERN_INFO "dev_mode = %d\n", (reg & FUSB300_GCR_DEVEN_MSK));
-}
-
-
-static void fusb300_ep0out(struct fusb300 *fusb300)
-{
-       struct fusb300_ep *ep = fusb300->ep[0];
-       u32 reg;
-
-       if (!list_empty(&ep->queue)) {
-               struct fusb300_request *req;
-
-               req = list_first_entry(&ep->queue,
-                       struct fusb300_request, queue);
-               if (req->req.length)
-                       fusb300_rdcxf(ep->fusb300, req->req.buf,
-                               req->req.length);
-               done(ep, req, 0);
-               reg = ioread32(fusb300->reg + FUSB300_OFFSET_IGER1);
-               reg &= ~FUSB300_IGER1_CX_OUT_INT;
-               iowrite32(reg, fusb300->reg + FUSB300_OFFSET_IGER1);
-       } else
-               pr_err("%s : empty queue\n", __func__);
-}
-
-static void fusb300_ep0in(struct fusb300 *fusb300)
-{
-       struct fusb300_request *req;
-       struct fusb300_ep *ep = fusb300->ep[0];
-
-       if ((!list_empty(&ep->queue)) && (fusb300->ep0_dir)) {
-               req = list_entry(ep->queue.next,
-                               struct fusb300_request, queue);
-               if (req->req.length)
-                       fusb300_wrcxf(ep, req);
-               if ((req->req.length - req->req.actual) < ep->ep.maxpacket)
-                       done(ep, req, 0);
-       } else
-               fusb300_set_cxdone(fusb300);
-}
-
-static void fusb300_grp2_handler(void)
-{
-}
-
-static void fusb300_grp3_handler(void)
-{
-}
-
-static void fusb300_grp4_handler(void)
-{
-}
-
-static void fusb300_grp5_handler(void)
-{
-}
-
-static irqreturn_t fusb300_irq(int irq, void *_fusb300)
-{
-       struct fusb300 *fusb300 = _fusb300;
-       u32 int_grp1 = ioread32(fusb300->reg + FUSB300_OFFSET_IGR1);
-       u32 int_grp1_en = ioread32(fusb300->reg + FUSB300_OFFSET_IGER1);
-       u32 int_grp0 = ioread32(fusb300->reg + FUSB300_OFFSET_IGR0);
-       u32 int_grp0_en = ioread32(fusb300->reg + FUSB300_OFFSET_IGER0);
-       struct usb_ctrlrequest ctrl;
-       u8 in;
-       u32 reg;
-       int i;
-
-       spin_lock(&fusb300->lock);
-
-       int_grp1 &= int_grp1_en;
-       int_grp0 &= int_grp0_en;
-
-       if (int_grp1 & FUSB300_IGR1_WARM_RST_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_WARM_RST_INT);
-               printk(KERN_INFO"fusb300_warmreset\n");
-               fusb300_reset();
-       }
-
-       if (int_grp1 & FUSB300_IGR1_HOT_RST_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_HOT_RST_INT);
-               printk(KERN_INFO"fusb300_hotreset\n");
-               fusb300_reset();
-       }
-
-       if (int_grp1 & FUSB300_IGR1_USBRST_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_USBRST_INT);
-               fusb300_reset();
-       }
-       /* COMABT_INT has a highest priority */
-
-       if (int_grp1 & FUSB300_IGR1_CX_COMABT_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_CX_COMABT_INT);
-               printk(KERN_INFO"fusb300_ep0abt\n");
-       }
-
-       if (int_grp1 & FUSB300_IGR1_VBUS_CHG_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_VBUS_CHG_INT);
-               printk(KERN_INFO"fusb300_vbus_change\n");
-       }
-
-       if (int_grp1 & FUSB300_IGR1_U3_EXIT_FAIL_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_U3_EXIT_FAIL_INT);
-       }
-
-       if (int_grp1 & FUSB300_IGR1_U2_EXIT_FAIL_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_U2_EXIT_FAIL_INT);
-       }
-
-       if (int_grp1 & FUSB300_IGR1_U1_EXIT_FAIL_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_U1_EXIT_FAIL_INT);
-       }
-
-       if (int_grp1 & FUSB300_IGR1_U2_ENTRY_FAIL_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_U2_ENTRY_FAIL_INT);
-       }
-
-       if (int_grp1 & FUSB300_IGR1_U1_ENTRY_FAIL_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_U1_ENTRY_FAIL_INT);
-       }
-
-       if (int_grp1 & FUSB300_IGR1_U3_EXIT_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_U3_EXIT_INT);
-               printk(KERN_INFO "FUSB300_IGR1_U3_EXIT_INT\n");
-       }
-
-       if (int_grp1 & FUSB300_IGR1_U2_EXIT_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_U2_EXIT_INT);
-               printk(KERN_INFO "FUSB300_IGR1_U2_EXIT_INT\n");
-       }
-
-       if (int_grp1 & FUSB300_IGR1_U1_EXIT_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_U1_EXIT_INT);
-               printk(KERN_INFO "FUSB300_IGR1_U1_EXIT_INT\n");
-       }
-
-       if (int_grp1 & FUSB300_IGR1_U3_ENTRY_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_U3_ENTRY_INT);
-               printk(KERN_INFO "FUSB300_IGR1_U3_ENTRY_INT\n");
-               fusb300_enable_bit(fusb300, FUSB300_OFFSET_SSCR1,
-                                  FUSB300_SSCR1_GO_U3_DONE);
-       }
-
-       if (int_grp1 & FUSB300_IGR1_U2_ENTRY_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_U2_ENTRY_INT);
-               printk(KERN_INFO "FUSB300_IGR1_U2_ENTRY_INT\n");
-       }
-
-       if (int_grp1 & FUSB300_IGR1_U1_ENTRY_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_U1_ENTRY_INT);
-               printk(KERN_INFO "FUSB300_IGR1_U1_ENTRY_INT\n");
-       }
-
-       if (int_grp1 & FUSB300_IGR1_RESM_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_RESM_INT);
-               printk(KERN_INFO "fusb300_resume\n");
-       }
-
-       if (int_grp1 & FUSB300_IGR1_SUSP_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_SUSP_INT);
-               printk(KERN_INFO "fusb300_suspend\n");
-       }
-
-       if (int_grp1 & FUSB300_IGR1_HS_LPM_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_HS_LPM_INT);
-               printk(KERN_INFO "fusb300_HS_LPM_INT\n");
-       }
-
-       if (int_grp1 & FUSB300_IGR1_DEV_MODE_CHG_INT) {
-               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
-                                 FUSB300_IGR1_DEV_MODE_CHG_INT);
-               check_device_mode(fusb300);
-       }
-
-       if (int_grp1 & FUSB300_IGR1_CX_COMFAIL_INT) {
-               fusb300_set_cxstall(fusb300);
-               printk(KERN_INFO "fusb300_ep0fail\n");
-       }
-
-       if (int_grp1 & FUSB300_IGR1_CX_SETUP_INT) {
-               printk(KERN_INFO "fusb300_ep0setup\n");
-               if (setup_packet(fusb300, &ctrl)) {
-                       spin_unlock(&fusb300->lock);
-                       if (fusb300->driver->setup(&fusb300->gadget, &ctrl) < 0)
-                               fusb300_set_cxstall(fusb300);
-                       spin_lock(&fusb300->lock);
-               }
-       }
-
-       if (int_grp1 & FUSB300_IGR1_CX_CMDEND_INT)
-               printk(KERN_INFO "fusb300_cmdend\n");
-
-
-       if (int_grp1 & FUSB300_IGR1_CX_OUT_INT) {
-               printk(KERN_INFO "fusb300_cxout\n");
-               fusb300_ep0out(fusb300);
-       }
-
-       if (int_grp1 & FUSB300_IGR1_CX_IN_INT) {
-               printk(KERN_INFO "fusb300_cxin\n");
-               fusb300_ep0in(fusb300);
-       }
-
-       if (int_grp1 & FUSB300_IGR1_INTGRP5)
-               fusb300_grp5_handler();
-
-       if (int_grp1 & FUSB300_IGR1_INTGRP4)
-               fusb300_grp4_handler();
-
-       if (int_grp1 & FUSB300_IGR1_INTGRP3)
-               fusb300_grp3_handler();
-
-       if (int_grp1 & FUSB300_IGR1_INTGRP2)
-               fusb300_grp2_handler();
-
-       if (int_grp0) {
-               for (i = 1; i < FUSB300_MAX_NUM_EP; i++) {
-                       if (int_grp0 & FUSB300_IGR0_EPn_FIFO_INT(i)) {
-                               reg = ioread32(fusb300->reg +
-                                       FUSB300_OFFSET_EPSET1(i));
-                               in = (reg & FUSB300_EPSET1_DIRIN) ? 1 : 0;
-                               if (in)
-                                       in_ep_fifo_handler(fusb300->ep[i]);
-                               else
-                                       out_ep_fifo_handler(fusb300->ep[i]);
-                       }
-               }
-       }
-
-       spin_unlock(&fusb300->lock);
-
-       return IRQ_HANDLED;
-}
-
-static void fusb300_set_u2_timeout(struct fusb300 *fusb300,
-                                  u32 time)
-{
-       u32 reg;
-
-       reg = ioread32(fusb300->reg + FUSB300_OFFSET_TT);
-       reg &= ~0xff;
-       reg |= FUSB300_SSCR2_U2TIMEOUT(time);
-
-       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_TT);
-}
-
-static void fusb300_set_u1_timeout(struct fusb300 *fusb300,
-                                  u32 time)
-{
-       u32 reg;
-
-       reg = ioread32(fusb300->reg + FUSB300_OFFSET_TT);
-       reg &= ~(0xff << 8);
-       reg |= FUSB300_SSCR2_U1TIMEOUT(time);
-
-       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_TT);
-}
-
-static void init_controller(struct fusb300 *fusb300)
-{
-       u32 reg;
-       u32 mask = 0;
-       u32 val = 0;
-
-       /* split on */
-       mask = val = FUSB300_AHBBCR_S0_SPLIT_ON | FUSB300_AHBBCR_S1_SPLIT_ON;
-       reg = ioread32(fusb300->reg + FUSB300_OFFSET_AHBCR);
-       reg &= ~mask;
-       reg |= val;
-       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_AHBCR);
-
-       /* enable high-speed LPM */
-       mask = val = FUSB300_HSCR_HS_LPM_PERMIT;
-       reg = ioread32(fusb300->reg + FUSB300_OFFSET_HSCR);
-       reg &= ~mask;
-       reg |= val;
-       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_HSCR);
-
-       /*set u1 u2 timmer*/
-       fusb300_set_u2_timeout(fusb300, 0xff);
-       fusb300_set_u1_timeout(fusb300, 0xff);
-
-       /* enable all grp1 interrupt */
-       iowrite32(0xcfffff9f, fusb300->reg + FUSB300_OFFSET_IGER1);
-}
-/*------------------------------------------------------------------------*/
-static int fusb300_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct fusb300 *fusb300 = to_fusb300(g);
-
-       /* hook up the driver */
-       driver->driver.bus = NULL;
-       fusb300->driver = driver;
-
-       return 0;
-}
-
-static int fusb300_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct fusb300 *fusb300 = to_fusb300(g);
-
-       init_controller(fusb300);
-       fusb300->driver = NULL;
-
-       return 0;
-}
-/*--------------------------------------------------------------------------*/
-
-static int fusb300_udc_pullup(struct usb_gadget *_gadget, int is_active)
-{
-       return 0;
-}
-
-static const struct usb_gadget_ops fusb300_gadget_ops = {
-       .pullup         = fusb300_udc_pullup,
-       .udc_start      = fusb300_udc_start,
-       .udc_stop       = fusb300_udc_stop,
-};
-
-static int __exit fusb300_remove(struct platform_device *pdev)
-{
-       struct fusb300 *fusb300 = platform_get_drvdata(pdev);
-
-       usb_del_gadget_udc(&fusb300->gadget);
-       iounmap(fusb300->reg);
-       free_irq(platform_get_irq(pdev, 0), fusb300);
-
-       fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
-       kfree(fusb300);
-
-       return 0;
-}
-
-static int fusb300_probe(struct platform_device *pdev)
-{
-       struct resource *res, *ires, *ires1;
-       void __iomem *reg = NULL;
-       struct fusb300 *fusb300 = NULL;
-       struct fusb300_ep *_ep[FUSB300_MAX_NUM_EP];
-       int ret = 0;
-       int i;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENODEV;
-               pr_err("platform_get_resource error.\n");
-               goto clean_up;
-       }
-
-       ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!ires) {
-               ret = -ENODEV;
-               dev_err(&pdev->dev,
-                       "platform_get_resource IORESOURCE_IRQ error.\n");
-               goto clean_up;
-       }
-
-       ires1 = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
-       if (!ires1) {
-               ret = -ENODEV;
-               dev_err(&pdev->dev,
-                       "platform_get_resource IORESOURCE_IRQ 1 error.\n");
-               goto clean_up;
-       }
-
-       reg = ioremap(res->start, resource_size(res));
-       if (reg == NULL) {
-               ret = -ENOMEM;
-               pr_err("ioremap error.\n");
-               goto clean_up;
-       }
-
-       /* initialize udc */
-       fusb300 = kzalloc(sizeof(struct fusb300), GFP_KERNEL);
-       if (fusb300 == NULL)
-               goto clean_up;
-
-       for (i = 0; i < FUSB300_MAX_NUM_EP; i++) {
-               _ep[i] = kzalloc(sizeof(struct fusb300_ep), GFP_KERNEL);
-               if (_ep[i] == NULL)
-                       goto clean_up;
-               fusb300->ep[i] = _ep[i];
-       }
-
-       spin_lock_init(&fusb300->lock);
-
-       platform_set_drvdata(pdev, fusb300);
-
-       fusb300->gadget.ops = &fusb300_gadget_ops;
-
-       fusb300->gadget.max_speed = USB_SPEED_HIGH;
-       fusb300->gadget.name = udc_name;
-       fusb300->reg = reg;
-
-       ret = request_irq(ires->start, fusb300_irq, IRQF_SHARED,
-                         udc_name, fusb300);
-       if (ret < 0) {
-               pr_err("request_irq error (%d)\n", ret);
-               goto clean_up;
-       }
-
-       ret = request_irq(ires1->start, fusb300_irq,
-                       IRQF_SHARED, udc_name, fusb300);
-       if (ret < 0) {
-               pr_err("request_irq1 error (%d)\n", ret);
-               goto clean_up;
-       }
-
-       INIT_LIST_HEAD(&fusb300->gadget.ep_list);
-
-       for (i = 0; i < FUSB300_MAX_NUM_EP ; i++) {
-               struct fusb300_ep *ep = fusb300->ep[i];
-
-               if (i != 0) {
-                       INIT_LIST_HEAD(&fusb300->ep[i]->ep.ep_list);
-                       list_add_tail(&fusb300->ep[i]->ep.ep_list,
-                                    &fusb300->gadget.ep_list);
-               }
-               ep->fusb300 = fusb300;
-               INIT_LIST_HEAD(&ep->queue);
-               ep->ep.name = fusb300_ep_name[i];
-               ep->ep.ops = &fusb300_ep_ops;
-               usb_ep_set_maxpacket_limit(&ep->ep, HS_BULK_MAX_PACKET_SIZE);
-       }
-       usb_ep_set_maxpacket_limit(&fusb300->ep[0]->ep, HS_CTL_MAX_PACKET_SIZE);
-       fusb300->ep[0]->epnum = 0;
-       fusb300->gadget.ep0 = &fusb300->ep[0]->ep;
-       INIT_LIST_HEAD(&fusb300->gadget.ep0->ep_list);
-
-       fusb300->ep0_req = fusb300_alloc_request(&fusb300->ep[0]->ep,
-                               GFP_KERNEL);
-       if (fusb300->ep0_req == NULL) {
-               ret = -ENOMEM;
-               goto clean_up3;
-       }
-
-       init_controller(fusb300);
-       ret = usb_add_gadget_udc(&pdev->dev, &fusb300->gadget);
-       if (ret)
-               goto err_add_udc;
-
-       dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
-
-       return 0;
-
-err_add_udc:
-       fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
-
-clean_up3:
-       free_irq(ires->start, fusb300);
-
-clean_up:
-       if (fusb300) {
-               if (fusb300->ep0_req)
-                       fusb300_free_request(&fusb300->ep[0]->ep,
-                               fusb300->ep0_req);
-               kfree(fusb300);
-       }
-       if (reg)
-               iounmap(reg);
-
-       return ret;
-}
-
-static struct platform_driver fusb300_driver = {
-       .remove =       __exit_p(fusb300_remove),
-       .driver         = {
-               .name = (char *) udc_name,
-               .owner  = THIS_MODULE,
-       },
-};
-
-module_platform_driver_probe(fusb300_driver, fusb300_probe);
diff --git a/drivers/usb/gadget/fusb300_udc.h b/drivers/usb/gadget/fusb300_udc.h
deleted file mode 100644 (file)
index ae811d8..0000000
+++ /dev/null
@@ -1,678 +0,0 @@
-/*
- * Fusb300 UDC (USB gadget)
- *
- * Copyright (C) 2010 Faraday Technology Corp.
- *
- * Author : Yuan-hsin Chen <yhchen@faraday-tech.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- */
-
-
-#ifndef __FUSB300_UDC_H__
-#define __FUSB300_UDC_H_
-
-#include <linux/kernel.h>
-
-#define FUSB300_OFFSET_GCR             0x00
-#define FUSB300_OFFSET_GTM             0x04
-#define FUSB300_OFFSET_DAR             0x08
-#define FUSB300_OFFSET_CSR             0x0C
-#define FUSB300_OFFSET_CXPORT          0x10
-#define FUSB300_OFFSET_EPSET0(n)       (0x20 + (n - 1) * 0x30)
-#define FUSB300_OFFSET_EPSET1(n)       (0x24 + (n - 1) * 0x30)
-#define FUSB300_OFFSET_EPSET2(n)       (0x28 + (n - 1) * 0x30)
-#define FUSB300_OFFSET_EPFFR(n)                (0x2c + (n - 1) * 0x30)
-#define FUSB300_OFFSET_EPSTRID(n)      (0x40 + (n - 1) * 0x30)
-#define FUSB300_OFFSET_HSPTM           0x300
-#define FUSB300_OFFSET_HSCR            0x304
-#define FUSB300_OFFSET_SSCR0           0x308
-#define FUSB300_OFFSET_SSCR1           0x30C
-#define FUSB300_OFFSET_TT              0x310
-#define FUSB300_OFFSET_DEVNOTF         0x314
-#define FUSB300_OFFSET_DNC1            0x318
-#define FUSB300_OFFSET_CS              0x31C
-#define FUSB300_OFFSET_SOF             0x324
-#define FUSB300_OFFSET_EFCS            0x328
-#define FUSB300_OFFSET_IGR0            0x400
-#define FUSB300_OFFSET_IGR1            0x404
-#define FUSB300_OFFSET_IGR2            0x408
-#define FUSB300_OFFSET_IGR3            0x40C
-#define FUSB300_OFFSET_IGR4            0x410
-#define FUSB300_OFFSET_IGR5            0x414
-#define FUSB300_OFFSET_IGER0           0x420
-#define FUSB300_OFFSET_IGER1           0x424
-#define FUSB300_OFFSET_IGER2           0x428
-#define FUSB300_OFFSET_IGER3           0x42C
-#define FUSB300_OFFSET_IGER4           0x430
-#define FUSB300_OFFSET_IGER5           0x434
-#define FUSB300_OFFSET_DMAHMER         0x500
-#define FUSB300_OFFSET_EPPRDRDY                0x504
-#define FUSB300_OFFSET_DMAEPMR         0x508
-#define FUSB300_OFFSET_DMAENR          0x50C
-#define FUSB300_OFFSET_DMAAPR          0x510
-#define FUSB300_OFFSET_AHBCR           0x514
-#define FUSB300_OFFSET_EPPRD_W0(n)     (0x520 + (n - 1) * 0x10)
-#define FUSB300_OFFSET_EPPRD_W1(n)     (0x524 + (n - 1) * 0x10)
-#define FUSB300_OFFSET_EPPRD_W2(n)     (0x528 + (n - 1) * 0x10)
-#define FUSB300_OFFSET_EPRD_PTR(n)     (0x52C + (n - 1) * 0x10)
-#define FUSB300_OFFSET_BUFDBG_START    0x800
-#define FUSB300_OFFSET_BUFDBG_END      0xBFC
-#define FUSB300_OFFSET_EPPORT(n)       (0x1010 + (n - 1) * 0x10)
-
-/*
- * *   Global Control Register (offset = 000H)
- * */
-#define FUSB300_GCR_SF_RST             (1 << 8)
-#define FUSB300_GCR_VBUS_STATUS                (1 << 7)
-#define FUSB300_GCR_FORCE_HS_SUSP      (1 << 6)
-#define FUSB300_GCR_SYNC_FIFO1_CLR     (1 << 5)
-#define FUSB300_GCR_SYNC_FIFO0_CLR     (1 << 4)
-#define FUSB300_GCR_FIFOCLR            (1 << 3)
-#define FUSB300_GCR_GLINTEN            (1 << 2)
-#define FUSB300_GCR_DEVEN_FS           0x3
-#define FUSB300_GCR_DEVEN_HS           0x2
-#define FUSB300_GCR_DEVEN_SS           0x1
-#define FUSB300_GCR_DEVDIS             0x0
-#define FUSB300_GCR_DEVEN_MSK          0x3
-
-
-/*
- * *Global Test Mode (offset = 004H)
- * */
-#define FUSB300_GTM_TST_DIS_SOFGEN     (1 << 16)
-#define FUSB300_GTM_TST_CUR_EP_ENTRY(n)        ((n & 0xF) << 12)
-#define FUSB300_GTM_TST_EP_ENTRY(n)    ((n & 0xF) << 8)
-#define FUSB300_GTM_TST_EP_NUM(n)      ((n & 0xF) << 4)
-#define FUSB300_GTM_TST_FIFO_DEG       (1 << 1)
-#define FUSB300_GTM_TSTMODE            (1 << 0)
-
-/*
- * * Device Address Register (offset = 008H)
- * */
-#define FUSB300_DAR_SETCONFG   (1 << 7)
-#define FUSB300_DAR_DRVADDR(x) (x & 0x7F)
-#define FUSB300_DAR_DRVADDR_MSK        0x7F
-
-/*
- * *Control Transfer Configuration and Status Register
- * (CX_Config_Status, offset = 00CH)
- * */
-#define FUSB300_CSR_LEN(x)     ((x & 0xFFFF) << 8)
-#define FUSB300_CSR_LEN_MSK    (0xFFFF << 8)
-#define FUSB300_CSR_EMP                (1 << 4)
-#define FUSB300_CSR_FUL                (1 << 3)
-#define FUSB300_CSR_CLR                (1 << 2)
-#define FUSB300_CSR_STL                (1 << 1)
-#define FUSB300_CSR_DONE       (1 << 0)
-
-/*
- * * EPn Setting 0 (EPn_SET0, offset = 020H+(n-1)*30H, n=1~15 )
- * */
-#define FUSB300_EPSET0_STL_CLR         (1 << 3)
-#define FUSB300_EPSET0_CLRSEQNUM       (1 << 2)
-#define FUSB300_EPSET0_STL             (1 << 0)
-
-/*
- * * EPn Setting 1 (EPn_SET1, offset = 024H+(n-1)*30H, n=1~15)
- * */
-#define FUSB300_EPSET1_START_ENTRY(x)  ((x & 0xFF) << 24)
-#define FUSB300_EPSET1_START_ENTRY_MSK (0xFF << 24)
-#define FUSB300_EPSET1_FIFOENTRY(x)    ((x & 0x1F) << 12)
-#define FUSB300_EPSET1_FIFOENTRY_MSK   (0x1f << 12)
-#define FUSB300_EPSET1_INTERVAL(x)     ((x & 0x7) << 6)
-#define FUSB300_EPSET1_BWNUM(x)                ((x & 0x3) << 4)
-#define FUSB300_EPSET1_TYPEISO         (1 << 2)
-#define FUSB300_EPSET1_TYPEBLK         (2 << 2)
-#define FUSB300_EPSET1_TYPEINT         (3 << 2)
-#define FUSB300_EPSET1_TYPE(x)         ((x & 0x3) << 2)
-#define FUSB300_EPSET1_TYPE_MSK                (0x3 << 2)
-#define FUSB300_EPSET1_DIROUT          (0 << 1)
-#define FUSB300_EPSET1_DIRIN           (1 << 1)
-#define FUSB300_EPSET1_DIR(x)          ((x & 0x1) << 1)
-#define FUSB300_EPSET1_DIRIN           (1 << 1)
-#define FUSB300_EPSET1_DIR_MSK         ((0x1) << 1)
-#define FUSB300_EPSET1_ACTDIS          0
-#define FUSB300_EPSET1_ACTEN           1
-
-/*
- * *EPn Setting 2 (EPn_SET2, offset = 028H+(n-1)*30H, n=1~15)
- * */
-#define FUSB300_EPSET2_ADDROFS(x)      ((x & 0x7FFF) << 16)
-#define FUSB300_EPSET2_ADDROFS_MSK     (0x7fff << 16)
-#define FUSB300_EPSET2_MPS(x)          (x & 0x7FF)
-#define FUSB300_EPSET2_MPS_MSK         0x7FF
-
-/*
- * * EPn FIFO Register (offset = 2cH+(n-1)*30H)
- * */
-#define FUSB300_FFR_RST                (1 << 31)
-#define FUSB300_FF_FUL         (1 << 30)
-#define FUSB300_FF_EMPTY       (1 << 29)
-#define FUSB300_FFR_BYCNT      0x1FFFF
-
-/*
- * *EPn Stream ID (EPn_STR_ID, offset = 040H+(n-1)*30H, n=1~15)
- * */
-#define FUSB300_STRID_STREN    (1 << 16)
-#define FUSB300_STRID_STRID(x) (x & 0xFFFF)
-
-/*
- * *HS PHY Test Mode (offset = 300H)
- * */
-#define FUSB300_HSPTM_TSTPKDONE                (1 << 4)
-#define FUSB300_HSPTM_TSTPKT           (1 << 3)
-#define FUSB300_HSPTM_TSTSET0NAK       (1 << 2)
-#define FUSB300_HSPTM_TSTKSTA          (1 << 1)
-#define FUSB300_HSPTM_TSTJSTA          (1 << 0)
-
-/*
- * *HS Control Register (offset = 304H)
- * */
-#define FUSB300_HSCR_HS_LPM_PERMIT     (1 << 8)
-#define FUSB300_HSCR_HS_LPM_RMWKUP     (1 << 7)
-#define FUSB300_HSCR_CAP_LPM_RMWKUP    (1 << 6)
-#define FUSB300_HSCR_HS_GOSUSP         (1 << 5)
-#define FUSB300_HSCR_HS_GORMWKU                (1 << 4)
-#define FUSB300_HSCR_CAP_RMWKUP                (1 << 3)
-#define FUSB300_HSCR_IDLECNT_0MS       0
-#define FUSB300_HSCR_IDLECNT_1MS       1
-#define FUSB300_HSCR_IDLECNT_2MS       2
-#define FUSB300_HSCR_IDLECNT_3MS       3
-#define FUSB300_HSCR_IDLECNT_4MS       4
-#define FUSB300_HSCR_IDLECNT_5MS       5
-#define FUSB300_HSCR_IDLECNT_6MS       6
-#define FUSB300_HSCR_IDLECNT_7MS       7
-
-/*
- * * SS Controller Register 0 (offset = 308H)
- * */
-#define FUSB300_SSCR0_MAX_INTERVAL(x)  ((x & 0x7) << 4)
-#define FUSB300_SSCR0_U2_FUN_EN                (1 << 1)
-#define FUSB300_SSCR0_U1_FUN_EN                (1 << 0)
-
-/*
- * * SS Controller Register 1 (offset = 30CH)
- * */
-#define FUSB300_SSCR1_GO_U3_DONE       (1 << 8)
-#define FUSB300_SSCR1_TXDEEMPH_LEVEL   (1 << 7)
-#define FUSB300_SSCR1_DIS_SCRMB                (1 << 6)
-#define FUSB300_SSCR1_FORCE_RECOVERY   (1 << 5)
-#define FUSB300_SSCR1_U3_WAKEUP_EN     (1 << 4)
-#define FUSB300_SSCR1_U2_EXIT_EN       (1 << 3)
-#define FUSB300_SSCR1_U1_EXIT_EN       (1 << 2)
-#define FUSB300_SSCR1_U2_ENTRY_EN      (1 << 1)
-#define FUSB300_SSCR1_U1_ENTRY_EN      (1 << 0)
-
-/*
- * *SS Controller Register 2  (offset = 310H)
- * */
-#define FUSB300_SSCR2_SS_TX_SWING              (1 << 25)
-#define FUSB300_SSCR2_FORCE_LINKPM_ACCEPT      (1 << 24)
-#define FUSB300_SSCR2_U2_INACT_TIMEOUT(x)      ((x & 0xFF) << 16)
-#define FUSB300_SSCR2_U1TIMEOUT(x)             ((x & 0xFF) << 8)
-#define FUSB300_SSCR2_U2TIMEOUT(x)             (x & 0xFF)
-
-/*
- * *SS Device Notification Control (DEV_NOTF, offset = 314H)
- * */
-#define FUSB300_DEVNOTF_CONTEXT0(x)            ((x & 0xFFFFFF) << 8)
-#define FUSB300_DEVNOTF_TYPE_DIS               0
-#define FUSB300_DEVNOTF_TYPE_FUNCWAKE          1
-#define FUSB300_DEVNOTF_TYPE_LTM               2
-#define FUSB300_DEVNOTF_TYPE_BUSINT_ADJMSG     3
-
-/*
- * *BFM Arbiter Priority Register (BFM_ARB offset = 31CH)
- * */
-#define FUSB300_BFMARB_ARB_M1  (1 << 3)
-#define FUSB300_BFMARB_ARB_M0  (1 << 2)
-#define FUSB300_BFMARB_ARB_S1  (1 << 1)
-#define FUSB300_BFMARB_ARB_S0  1
-
-/*
- * *Vendor Specific IO Control Register (offset = 320H)
- * */
-#define FUSB300_VSIC_VCTLOAD_N (1 << 8)
-#define FUSB300_VSIC_VCTL(x)   (x & 0x3F)
-
-/*
- * *SOF Mask Timer (offset = 324H)
- * */
-#define FUSB300_SOF_MASK_TIMER_HS      0x044c
-#define FUSB300_SOF_MASK_TIMER_FS      0x2710
-
-/*
- * *Error Flag and Control Status (offset = 328H)
- * */
-#define FUSB300_EFCS_PM_STATE_U3       3
-#define FUSB300_EFCS_PM_STATE_U2       2
-#define FUSB300_EFCS_PM_STATE_U1       1
-#define FUSB300_EFCS_PM_STATE_U0       0
-
-/*
- * *Interrupt Group 0 Register (offset = 400H)
- * */
-#define FUSB300_IGR0_EP15_PRD_INT      (1 << 31)
-#define FUSB300_IGR0_EP14_PRD_INT      (1 << 30)
-#define FUSB300_IGR0_EP13_PRD_INT      (1 << 29)
-#define FUSB300_IGR0_EP12_PRD_INT      (1 << 28)
-#define FUSB300_IGR0_EP11_PRD_INT      (1 << 27)
-#define FUSB300_IGR0_EP10_PRD_INT      (1 << 26)
-#define FUSB300_IGR0_EP9_PRD_INT       (1 << 25)
-#define FUSB300_IGR0_EP8_PRD_INT       (1 << 24)
-#define FUSB300_IGR0_EP7_PRD_INT       (1 << 23)
-#define FUSB300_IGR0_EP6_PRD_INT       (1 << 22)
-#define FUSB300_IGR0_EP5_PRD_INT       (1 << 21)
-#define FUSB300_IGR0_EP4_PRD_INT       (1 << 20)
-#define FUSB300_IGR0_EP3_PRD_INT       (1 << 19)
-#define FUSB300_IGR0_EP2_PRD_INT       (1 << 18)
-#define FUSB300_IGR0_EP1_PRD_INT       (1 << 17)
-#define FUSB300_IGR0_EPn_PRD_INT(n)    (1 << (n + 16))
-
-#define FUSB300_IGR0_EP15_FIFO_INT     (1 << 15)
-#define FUSB300_IGR0_EP14_FIFO_INT     (1 << 14)
-#define FUSB300_IGR0_EP13_FIFO_INT     (1 << 13)
-#define FUSB300_IGR0_EP12_FIFO_INT     (1 << 12)
-#define FUSB300_IGR0_EP11_FIFO_INT     (1 << 11)
-#define FUSB300_IGR0_EP10_FIFO_INT     (1 << 10)
-#define FUSB300_IGR0_EP9_FIFO_INT      (1 << 9)
-#define FUSB300_IGR0_EP8_FIFO_INT      (1 << 8)
-#define FUSB300_IGR0_EP7_FIFO_INT      (1 << 7)
-#define FUSB300_IGR0_EP6_FIFO_INT      (1 << 6)
-#define FUSB300_IGR0_EP5_FIFO_INT      (1 << 5)
-#define FUSB300_IGR0_EP4_FIFO_INT      (1 << 4)
-#define FUSB300_IGR0_EP3_FIFO_INT      (1 << 3)
-#define FUSB300_IGR0_EP2_FIFO_INT      (1 << 2)
-#define FUSB300_IGR0_EP1_FIFO_INT      (1 << 1)
-#define FUSB300_IGR0_EPn_FIFO_INT(n)   (1 << n)
-
-/*
- * *Interrupt Group 1 Register (offset = 404H)
- * */
-#define FUSB300_IGR1_INTGRP5           (1 << 31)
-#define FUSB300_IGR1_VBUS_CHG_INT      (1 << 30)
-#define FUSB300_IGR1_SYNF1_EMPTY_INT   (1 << 29)
-#define FUSB300_IGR1_SYNF0_EMPTY_INT   (1 << 28)
-#define FUSB300_IGR1_U3_EXIT_FAIL_INT  (1 << 27)
-#define FUSB300_IGR1_U2_EXIT_FAIL_INT  (1 << 26)
-#define FUSB300_IGR1_U1_EXIT_FAIL_INT  (1 << 25)
-#define FUSB300_IGR1_U2_ENTRY_FAIL_INT (1 << 24)
-#define FUSB300_IGR1_U1_ENTRY_FAIL_INT (1 << 23)
-#define FUSB300_IGR1_U3_EXIT_INT       (1 << 22)
-#define FUSB300_IGR1_U2_EXIT_INT       (1 << 21)
-#define FUSB300_IGR1_U1_EXIT_INT       (1 << 20)
-#define FUSB300_IGR1_U3_ENTRY_INT      (1 << 19)
-#define FUSB300_IGR1_U2_ENTRY_INT      (1 << 18)
-#define FUSB300_IGR1_U1_ENTRY_INT      (1 << 17)
-#define FUSB300_IGR1_HOT_RST_INT       (1 << 16)
-#define FUSB300_IGR1_WARM_RST_INT      (1 << 15)
-#define FUSB300_IGR1_RESM_INT          (1 << 14)
-#define FUSB300_IGR1_SUSP_INT          (1 << 13)
-#define FUSB300_IGR1_HS_LPM_INT                (1 << 12)
-#define FUSB300_IGR1_USBRST_INT                (1 << 11)
-#define FUSB300_IGR1_DEV_MODE_CHG_INT  (1 << 9)
-#define FUSB300_IGR1_CX_COMABT_INT     (1 << 8)
-#define FUSB300_IGR1_CX_COMFAIL_INT    (1 << 7)
-#define FUSB300_IGR1_CX_CMDEND_INT     (1 << 6)
-#define FUSB300_IGR1_CX_OUT_INT                (1 << 5)
-#define FUSB300_IGR1_CX_IN_INT         (1 << 4)
-#define FUSB300_IGR1_CX_SETUP_INT      (1 << 3)
-#define FUSB300_IGR1_INTGRP4           (1 << 2)
-#define FUSB300_IGR1_INTGRP3           (1 << 1)
-#define FUSB300_IGR1_INTGRP2           (1 << 0)
-
-/*
- * *Interrupt Group 2 Register (offset = 408H)
- * */
-#define FUSB300_IGR2_EP6_STR_ACCEPT_INT                (1 << 29)
-#define FUSB300_IGR2_EP6_STR_RESUME_INT                (1 << 28)
-#define FUSB300_IGR2_EP6_STR_REQ_INT           (1 << 27)
-#define FUSB300_IGR2_EP6_STR_NOTRDY_INT                (1 << 26)
-#define FUSB300_IGR2_EP6_STR_PRIME_INT         (1 << 25)
-#define FUSB300_IGR2_EP5_STR_ACCEPT_INT                (1 << 24)
-#define FUSB300_IGR2_EP5_STR_RESUME_INT                (1 << 23)
-#define FUSB300_IGR2_EP5_STR_REQ_INT           (1 << 22)
-#define FUSB300_IGR2_EP5_STR_NOTRDY_INT                (1 << 21)
-#define FUSB300_IGR2_EP5_STR_PRIME_INT         (1 << 20)
-#define FUSB300_IGR2_EP4_STR_ACCEPT_INT                (1 << 19)
-#define FUSB300_IGR2_EP4_STR_RESUME_INT                (1 << 18)
-#define FUSB300_IGR2_EP4_STR_REQ_INT           (1 << 17)
-#define FUSB300_IGR2_EP4_STR_NOTRDY_INT                (1 << 16)
-#define FUSB300_IGR2_EP4_STR_PRIME_INT         (1 << 15)
-#define FUSB300_IGR2_EP3_STR_ACCEPT_INT                (1 << 14)
-#define FUSB300_IGR2_EP3_STR_RESUME_INT                (1 << 13)
-#define FUSB300_IGR2_EP3_STR_REQ_INT           (1 << 12)
-#define FUSB300_IGR2_EP3_STR_NOTRDY_INT                (1 << 11)
-#define FUSB300_IGR2_EP3_STR_PRIME_INT         (1 << 10)
-#define FUSB300_IGR2_EP2_STR_ACCEPT_INT                (1 << 9)
-#define FUSB300_IGR2_EP2_STR_RESUME_INT                (1 << 8)
-#define FUSB300_IGR2_EP2_STR_REQ_INT           (1 << 7)
-#define FUSB300_IGR2_EP2_STR_NOTRDY_INT                (1 << 6)
-#define FUSB300_IGR2_EP2_STR_PRIME_INT         (1 << 5)
-#define FUSB300_IGR2_EP1_STR_ACCEPT_INT                (1 << 4)
-#define FUSB300_IGR2_EP1_STR_RESUME_INT                (1 << 3)
-#define FUSB300_IGR2_EP1_STR_REQ_INT           (1 << 2)
-#define FUSB300_IGR2_EP1_STR_NOTRDY_INT                (1 << 1)
-#define FUSB300_IGR2_EP1_STR_PRIME_INT         (1 << 0)
-
-#define FUSB300_IGR2_EP_STR_ACCEPT_INT(n)      (1 << (5 * n - 1))
-#define FUSB300_IGR2_EP_STR_RESUME_INT(n)      (1 << (5 * n - 2))
-#define FUSB300_IGR2_EP_STR_REQ_INT(n)         (1 << (5 * n - 3))
-#define FUSB300_IGR2_EP_STR_NOTRDY_INT(n)      (1 << (5 * n - 4))
-#define FUSB300_IGR2_EP_STR_PRIME_INT(n)       (1 << (5 * n - 5))
-
-/*
- * *Interrupt Group 3 Register (offset = 40CH)
- * */
-#define FUSB300_IGR3_EP12_STR_ACCEPT_INT       (1 << 29)
-#define FUSB300_IGR3_EP12_STR_RESUME_INT       (1 << 28)
-#define FUSB300_IGR3_EP12_STR_REQ_INT          (1 << 27)
-#define FUSB300_IGR3_EP12_STR_NOTRDY_INT       (1 << 26)
-#define FUSB300_IGR3_EP12_STR_PRIME_INT                (1 << 25)
-#define FUSB300_IGR3_EP11_STR_ACCEPT_INT       (1 << 24)
-#define FUSB300_IGR3_EP11_STR_RESUME_INT       (1 << 23)
-#define FUSB300_IGR3_EP11_STR_REQ_INT          (1 << 22)
-#define FUSB300_IGR3_EP11_STR_NOTRDY_INT       (1 << 21)
-#define FUSB300_IGR3_EP11_STR_PRIME_INT                (1 << 20)
-#define FUSB300_IGR3_EP10_STR_ACCEPT_INT       (1 << 19)
-#define FUSB300_IGR3_EP10_STR_RESUME_INT       (1 << 18)
-#define FUSB300_IGR3_EP10_STR_REQ_INT          (1 << 17)
-#define FUSB300_IGR3_EP10_STR_NOTRDY_INT       (1 << 16)
-#define FUSB300_IGR3_EP10_STR_PRIME_INT                (1 << 15)
-#define FUSB300_IGR3_EP9_STR_ACCEPT_INT                (1 << 14)
-#define FUSB300_IGR3_EP9_STR_RESUME_INT                (1 << 13)
-#define FUSB300_IGR3_EP9_STR_REQ_INT           (1 << 12)
-#define FUSB300_IGR3_EP9_STR_NOTRDY_INT                (1 << 11)
-#define FUSB300_IGR3_EP9_STR_PRIME_INT         (1 << 10)
-#define FUSB300_IGR3_EP8_STR_ACCEPT_INT                (1 << 9)
-#define FUSB300_IGR3_EP8_STR_RESUME_INT                (1 << 8)
-#define FUSB300_IGR3_EP8_STR_REQ_INT           (1 << 7)
-#define FUSB300_IGR3_EP8_STR_NOTRDY_INT                (1 << 6)
-#define FUSB300_IGR3_EP8_STR_PRIME_INT         (1 << 5)
-#define FUSB300_IGR3_EP7_STR_ACCEPT_INT                (1 << 4)
-#define FUSB300_IGR3_EP7_STR_RESUME_INT                (1 << 3)
-#define FUSB300_IGR3_EP7_STR_REQ_INT           (1 << 2)
-#define FUSB300_IGR3_EP7_STR_NOTRDY_INT                (1 << 1)
-#define FUSB300_IGR3_EP7_STR_PRIME_INT         (1 << 0)
-
-#define FUSB300_IGR3_EP_STR_ACCEPT_INT(n)      (1 << (5 * (n - 6) - 1))
-#define FUSB300_IGR3_EP_STR_RESUME_INT(n)      (1 << (5 * (n - 6) - 2))
-#define FUSB300_IGR3_EP_STR_REQ_INT(n)         (1 << (5 * (n - 6) - 3))
-#define FUSB300_IGR3_EP_STR_NOTRDY_INT(n)      (1 << (5 * (n - 6) - 4))
-#define FUSB300_IGR3_EP_STR_PRIME_INT(n)       (1 << (5 * (n - 6) - 5))
-
-/*
- * *Interrupt Group 4 Register (offset = 410H)
- * */
-#define FUSB300_IGR4_EP15_RX0_INT              (1 << 31)
-#define FUSB300_IGR4_EP14_RX0_INT              (1 << 30)
-#define FUSB300_IGR4_EP13_RX0_INT              (1 << 29)
-#define FUSB300_IGR4_EP12_RX0_INT              (1 << 28)
-#define FUSB300_IGR4_EP11_RX0_INT              (1 << 27)
-#define FUSB300_IGR4_EP10_RX0_INT              (1 << 26)
-#define FUSB300_IGR4_EP9_RX0_INT               (1 << 25)
-#define FUSB300_IGR4_EP8_RX0_INT               (1 << 24)
-#define FUSB300_IGR4_EP7_RX0_INT               (1 << 23)
-#define FUSB300_IGR4_EP6_RX0_INT               (1 << 22)
-#define FUSB300_IGR4_EP5_RX0_INT               (1 << 21)
-#define FUSB300_IGR4_EP4_RX0_INT               (1 << 20)
-#define FUSB300_IGR4_EP3_RX0_INT               (1 << 19)
-#define FUSB300_IGR4_EP2_RX0_INT               (1 << 18)
-#define FUSB300_IGR4_EP1_RX0_INT               (1 << 17)
-#define FUSB300_IGR4_EP_RX0_INT(x)             (1 << (x + 16))
-#define FUSB300_IGR4_EP15_STR_ACCEPT_INT       (1 << 14)
-#define FUSB300_IGR4_EP15_STR_RESUME_INT       (1 << 13)
-#define FUSB300_IGR4_EP15_STR_REQ_INT          (1 << 12)
-#define FUSB300_IGR4_EP15_STR_NOTRDY_INT       (1 << 11)
-#define FUSB300_IGR4_EP15_STR_PRIME_INT                (1 << 10)
-#define FUSB300_IGR4_EP14_STR_ACCEPT_INT       (1 << 9)
-#define FUSB300_IGR4_EP14_STR_RESUME_INT       (1 << 8)
-#define FUSB300_IGR4_EP14_STR_REQ_INT          (1 << 7)
-#define FUSB300_IGR4_EP14_STR_NOTRDY_INT       (1 << 6)
-#define FUSB300_IGR4_EP14_STR_PRIME_INT                (1 << 5)
-#define FUSB300_IGR4_EP13_STR_ACCEPT_INT       (1 << 4)
-#define FUSB300_IGR4_EP13_STR_RESUME_INT       (1 << 3)
-#define FUSB300_IGR4_EP13_STR_REQ_INT          (1 << 2)
-#define FUSB300_IGR4_EP13_STR_NOTRDY_INT       (1 << 1)
-#define FUSB300_IGR4_EP13_STR_PRIME_INT                (1 << 0)
-
-#define FUSB300_IGR4_EP_STR_ACCEPT_INT(n)      (1 << (5 * (n - 12) - 1))
-#define FUSB300_IGR4_EP_STR_RESUME_INT(n)      (1 << (5 * (n - 12) - 2))
-#define FUSB300_IGR4_EP_STR_REQ_INT(n)         (1 << (5 * (n - 12) - 3))
-#define FUSB300_IGR4_EP_STR_NOTRDY_INT(n)      (1 << (5 * (n - 12) - 4))
-#define FUSB300_IGR4_EP_STR_PRIME_INT(n)       (1 << (5 * (n - 12) - 5))
-
-/*
- * *Interrupt Group 5 Register (offset = 414H)
- * */
-#define FUSB300_IGR5_EP_STL_INT(n)     (1 << n)
-
-/*
- * *Interrupt Enable Group 0 Register (offset = 420H)
- * */
-#define FUSB300_IGER0_EEP15_PRD_INT    (1 << 31)
-#define FUSB300_IGER0_EEP14_PRD_INT    (1 << 30)
-#define FUSB300_IGER0_EEP13_PRD_INT    (1 << 29)
-#define FUSB300_IGER0_EEP12_PRD_INT    (1 << 28)
-#define FUSB300_IGER0_EEP11_PRD_INT    (1 << 27)
-#define FUSB300_IGER0_EEP10_PRD_INT    (1 << 26)
-#define FUSB300_IGER0_EEP9_PRD_INT     (1 << 25)
-#define FUSB300_IGER0_EP8_PRD_INT      (1 << 24)
-#define FUSB300_IGER0_EEP7_PRD_INT     (1 << 23)
-#define FUSB300_IGER0_EEP6_PRD_INT     (1 << 22)
-#define FUSB300_IGER0_EEP5_PRD_INT     (1 << 21)
-#define FUSB300_IGER0_EEP4_PRD_INT     (1 << 20)
-#define FUSB300_IGER0_EEP3_PRD_INT     (1 << 19)
-#define FUSB300_IGER0_EEP2_PRD_INT     (1 << 18)
-#define FUSB300_IGER0_EEP1_PRD_INT     (1 << 17)
-#define FUSB300_IGER0_EEPn_PRD_INT(n)  (1 << (n + 16))
-
-#define FUSB300_IGER0_EEP15_FIFO_INT   (1 << 15)
-#define FUSB300_IGER0_EEP14_FIFO_INT   (1 << 14)
-#define FUSB300_IGER0_EEP13_FIFO_INT   (1 << 13)
-#define FUSB300_IGER0_EEP12_FIFO_INT   (1 << 12)
-#define FUSB300_IGER0_EEP11_FIFO_INT   (1 << 11)
-#define FUSB300_IGER0_EEP10_FIFO_INT   (1 << 10)
-#define FUSB300_IGER0_EEP9_FIFO_INT    (1 << 9)
-#define FUSB300_IGER0_EEP8_FIFO_INT    (1 << 8)
-#define FUSB300_IGER0_EEP7_FIFO_INT    (1 << 7)
-#define FUSB300_IGER0_EEP6_FIFO_INT    (1 << 6)
-#define FUSB300_IGER0_EEP5_FIFO_INT    (1 << 5)
-#define FUSB300_IGER0_EEP4_FIFO_INT    (1 << 4)
-#define FUSB300_IGER0_EEP3_FIFO_INT    (1 << 3)
-#define FUSB300_IGER0_EEP2_FIFO_INT    (1 << 2)
-#define FUSB300_IGER0_EEP1_FIFO_INT    (1 << 1)
-#define FUSB300_IGER0_EEPn_FIFO_INT(n) (1 << n)
-
-/*
- * *Interrupt Enable Group 1 Register (offset = 424H)
- * */
-#define FUSB300_IGER1_EINT_GRP5                (1 << 31)
-#define FUSB300_IGER1_VBUS_CHG_INT     (1 << 30)
-#define FUSB300_IGER1_SYNF1_EMPTY_INT  (1 << 29)
-#define FUSB300_IGER1_SYNF0_EMPTY_INT  (1 << 28)
-#define FUSB300_IGER1_U3_EXIT_FAIL_INT (1 << 27)
-#define FUSB300_IGER1_U2_EXIT_FAIL_INT (1 << 26)
-#define FUSB300_IGER1_U1_EXIT_FAIL_INT (1 << 25)
-#define FUSB300_IGER1_U2_ENTRY_FAIL_INT        (1 << 24)
-#define FUSB300_IGER1_U1_ENTRY_FAIL_INT        (1 << 23)
-#define FUSB300_IGER1_U3_EXIT_INT      (1 << 22)
-#define FUSB300_IGER1_U2_EXIT_INT      (1 << 21)
-#define FUSB300_IGER1_U1_EXIT_INT      (1 << 20)
-#define FUSB300_IGER1_U3_ENTRY_INT     (1 << 19)
-#define FUSB300_IGER1_U2_ENTRY_INT     (1 << 18)
-#define FUSB300_IGER1_U1_ENTRY_INT     (1 << 17)
-#define FUSB300_IGER1_HOT_RST_INT      (1 << 16)
-#define FUSB300_IGER1_WARM_RST_INT     (1 << 15)
-#define FUSB300_IGER1_RESM_INT         (1 << 14)
-#define FUSB300_IGER1_SUSP_INT         (1 << 13)
-#define FUSB300_IGER1_LPM_INT          (1 << 12)
-#define FUSB300_IGER1_HS_RST_INT       (1 << 11)
-#define FUSB300_IGER1_EDEV_MODE_CHG_INT        (1 << 9)
-#define FUSB300_IGER1_CX_COMABT_INT    (1 << 8)
-#define FUSB300_IGER1_CX_COMFAIL_INT   (1 << 7)
-#define FUSB300_IGER1_CX_CMDEND_INT    (1 << 6)
-#define FUSB300_IGER1_CX_OUT_INT       (1 << 5)
-#define FUSB300_IGER1_CX_IN_INT                (1 << 4)
-#define FUSB300_IGER1_CX_SETUP_INT     (1 << 3)
-#define FUSB300_IGER1_INTGRP4          (1 << 2)
-#define FUSB300_IGER1_INTGRP3          (1 << 1)
-#define FUSB300_IGER1_INTGRP2          (1 << 0)
-
-/*
- * *Interrupt Enable Group 2 Register (offset = 428H)
- * */
-#define FUSB300_IGER2_EEP_STR_ACCEPT_INT(n)    (1 << (5 * n - 1))
-#define FUSB300_IGER2_EEP_STR_RESUME_INT(n)    (1 << (5 * n - 2))
-#define FUSB300_IGER2_EEP_STR_REQ_INT(n)       (1 << (5 * n - 3))
-#define FUSB300_IGER2_EEP_STR_NOTRDY_INT(n)    (1 << (5 * n - 4))
-#define FUSB300_IGER2_EEP_STR_PRIME_INT(n)     (1 << (5 * n - 5))
-
-/*
- * *Interrupt Enable Group 3 Register (offset = 42CH)
- * */
-
-#define FUSB300_IGER3_EEP_STR_ACCEPT_INT(n)    (1 << (5 * (n - 6) - 1))
-#define FUSB300_IGER3_EEP_STR_RESUME_INT(n)    (1 << (5 * (n - 6) - 2))
-#define FUSB300_IGER3_EEP_STR_REQ_INT(n)       (1 << (5 * (n - 6) - 3))
-#define FUSB300_IGER3_EEP_STR_NOTRDY_INT(n)    (1 << (5 * (n - 6) - 4))
-#define FUSB300_IGER3_EEP_STR_PRIME_INT(n)     (1 << (5 * (n - 6) - 5))
-
-/*
- * *Interrupt Enable Group 4 Register (offset = 430H)
- * */
-
-#define FUSB300_IGER4_EEP_RX0_INT(n)           (1 << (n + 16))
-#define FUSB300_IGER4_EEP_STR_ACCEPT_INT(n)    (1 << (5 * (n - 6) - 1))
-#define FUSB300_IGER4_EEP_STR_RESUME_INT(n)    (1 << (5 * (n - 6) - 2))
-#define FUSB300_IGER4_EEP_STR_REQ_INT(n)       (1 << (5 * (n - 6) - 3))
-#define FUSB300_IGER4_EEP_STR_NOTRDY_INT(n)    (1 << (5 * (n - 6) - 4))
-#define FUSB300_IGER4_EEP_STR_PRIME_INT(n)     (1 << (5 * (n - 6) - 5))
-
-/* EP PRD Ready (EP_PRD_RDY, offset = 504H) */
-
-#define FUSB300_EPPRDR_EP15_PRD_RDY            (1 << 15)
-#define FUSB300_EPPRDR_EP14_PRD_RDY            (1 << 14)
-#define FUSB300_EPPRDR_EP13_PRD_RDY            (1 << 13)
-#define FUSB300_EPPRDR_EP12_PRD_RDY            (1 << 12)
-#define FUSB300_EPPRDR_EP11_PRD_RDY            (1 << 11)
-#define FUSB300_EPPRDR_EP10_PRD_RDY            (1 << 10)
-#define FUSB300_EPPRDR_EP9_PRD_RDY             (1 << 9)
-#define FUSB300_EPPRDR_EP8_PRD_RDY             (1 << 8)
-#define FUSB300_EPPRDR_EP7_PRD_RDY             (1 << 7)
-#define FUSB300_EPPRDR_EP6_PRD_RDY             (1 << 6)
-#define FUSB300_EPPRDR_EP5_PRD_RDY             (1 << 5)
-#define FUSB300_EPPRDR_EP4_PRD_RDY             (1 << 4)
-#define FUSB300_EPPRDR_EP3_PRD_RDY             (1 << 3)
-#define FUSB300_EPPRDR_EP2_PRD_RDY             (1 << 2)
-#define FUSB300_EPPRDR_EP1_PRD_RDY             (1 << 1)
-#define FUSB300_EPPRDR_EP_PRD_RDY(n)           (1 << n)
-
-/* AHB Bus Control Register (offset = 514H) */
-#define FUSB300_AHBBCR_S1_SPLIT_ON             (1 << 17)
-#define FUSB300_AHBBCR_S0_SPLIT_ON             (1 << 16)
-#define FUSB300_AHBBCR_S1_1entry               (0 << 12)
-#define FUSB300_AHBBCR_S1_4entry               (3 << 12)
-#define FUSB300_AHBBCR_S1_8entry               (5 << 12)
-#define FUSB300_AHBBCR_S1_16entry              (7 << 12)
-#define FUSB300_AHBBCR_S0_1entry               (0 << 8)
-#define FUSB300_AHBBCR_S0_4entry               (3 << 8)
-#define FUSB300_AHBBCR_S0_8entry               (5 << 8)
-#define FUSB300_AHBBCR_S0_16entry              (7 << 8)
-#define FUSB300_AHBBCR_M1_BURST_SINGLE         (0 << 4)
-#define FUSB300_AHBBCR_M1_BURST_INCR           (1 << 4)
-#define FUSB300_AHBBCR_M1_BURST_INCR4          (3 << 4)
-#define FUSB300_AHBBCR_M1_BURST_INCR8          (5 << 4)
-#define FUSB300_AHBBCR_M1_BURST_INCR16         (7 << 4)
-#define FUSB300_AHBBCR_M0_BURST_SINGLE         0
-#define FUSB300_AHBBCR_M0_BURST_INCR           1
-#define FUSB300_AHBBCR_M0_BURST_INCR4          3
-#define FUSB300_AHBBCR_M0_BURST_INCR8          5
-#define FUSB300_AHBBCR_M0_BURST_INCR16         7
-#define FUSB300_IGER5_EEP_STL_INT(n)           (1 << n)
-
-/* WORD 0 Data Structure of PRD Table */
-#define FUSB300_EPPRD0_M                       (1 << 30)
-#define FUSB300_EPPRD0_O                       (1 << 29)
-/* The finished prd */
-#define FUSB300_EPPRD0_F                       (1 << 28)
-#define FUSB300_EPPRD0_I                       (1 << 27)
-#define FUSB300_EPPRD0_A                       (1 << 26)
-/* To decide HW point to first prd at next time */
-#define FUSB300_EPPRD0_L                       (1 << 25)
-#define FUSB300_EPPRD0_H                       (1 << 24)
-#define FUSB300_EPPRD0_BTC(n)                  (n & 0xFFFFFF)
-
-/*----------------------------------------------------------------------*/
-#define FUSB300_MAX_NUM_EP             16
-
-#define FUSB300_FIFO_ENTRY_NUM         8
-#define FUSB300_MAX_FIFO_ENTRY         8
-
-#define SS_CTL_MAX_PACKET_SIZE         0x200
-#define SS_BULK_MAX_PACKET_SIZE                0x400
-#define SS_INT_MAX_PACKET_SIZE         0x400
-#define SS_ISO_MAX_PACKET_SIZE         0x400
-
-#define HS_BULK_MAX_PACKET_SIZE                0x200
-#define HS_CTL_MAX_PACKET_SIZE         0x40
-#define HS_INT_MAX_PACKET_SIZE         0x400
-#define HS_ISO_MAX_PACKET_SIZE         0x400
-
-struct fusb300_ep_info {
-       u8      epnum;
-       u8      type;
-       u8      interval;
-       u8      dir_in;
-       u16     maxpacket;
-       u16     addrofs;
-       u16     bw_num;
-};
-
-struct fusb300_request {
-
-       struct usb_request      req;
-       struct list_head        queue;
-};
-
-
-struct fusb300_ep {
-       struct usb_ep           ep;
-       struct fusb300          *fusb300;
-
-       struct list_head        queue;
-       unsigned                stall:1;
-       unsigned                wedged:1;
-       unsigned                use_dma:1;
-
-       unsigned char           epnum;
-       unsigned char           type;
-};
-
-struct fusb300 {
-       spinlock_t              lock;
-       void __iomem            *reg;
-
-       unsigned long           irq_trigger;
-
-       struct usb_gadget               gadget;
-       struct usb_gadget_driver        *driver;
-
-       struct fusb300_ep       *ep[FUSB300_MAX_NUM_EP];
-
-       struct usb_request      *ep0_req;       /* for internal request */
-       __le16                  ep0_data;
-       u32                     ep0_length;     /* for internal request */
-       u8                      ep0_dir;        /* 0/0x80  out/in */
-
-       u8                      fifo_entry_num; /* next start fifo entry */
-       u32                     addrofs;        /* next fifo address offset */
-       u8                      reenum;         /* if re-enumeration */
-};
-
-#define to_fusb300(g)          (container_of((g), struct fusb300, gadget))
-
-#endif
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
deleted file mode 100644 (file)
index bcd04bc..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * USB device controllers have lots of quirks.  Use these macros in
- * gadget drivers or other code that needs to deal with them, and which
- * autoconfigures instead of using early binding to the hardware.
- *
- * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by
- * some config file that gets updated as new hardware is supported.
- * (And avoiding all runtime comparisons in typical one-choice configs!)
- *
- * NOTE:  some of these controller drivers may not be available yet.
- * Some are available on 2.4 kernels; several are available, but not
- * yet pushed in the 2.6 mainline tree.
- */
-
-#ifndef __GADGET_CHIPS_H
-#define __GADGET_CHIPS_H
-
-#include <linux/usb/gadget.h>
-
-/*
- * NOTICE: the entries below are alphabetical and should be kept
- * that way.
- *
- * Always be sure to add new entries to the correct position or
- * accept the bashing later.
- *
- * If you have forgotten the alphabetical order let VIM/EMACS
- * do that for you.
- */
-#define gadget_is_at91(g)              (!strcmp("at91_udc", (g)->name))
-#define gadget_is_goku(g)              (!strcmp("goku_udc", (g)->name))
-#define gadget_is_musbhdrc(g)          (!strcmp("musb-hdrc", (g)->name))
-#define gadget_is_net2280(g)           (!strcmp("net2280", (g)->name))
-#define gadget_is_pxa(g)               (!strcmp("pxa25x_udc", (g)->name))
-#define gadget_is_pxa27x(g)            (!strcmp("pxa27x_udc", (g)->name))
-
-/**
- * gadget_supports_altsettings - return true if altsettings work
- * @gadget: the gadget in question
- */
-static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
-{
-       /* PXA 21x/25x/26x has no altsettings at all */
-       if (gadget_is_pxa(gadget))
-               return false;
-
-       /* PXA 27x and 3xx have *broken* altsetting support */
-       if (gadget_is_pxa27x(gadget))
-               return false;
-
-       /* Everything else is *presumably* fine ... */
-       return true;
-}
-
-#endif /* __GADGET_CHIPS_H */
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
deleted file mode 100644 (file)
index 6c85839..0000000
+++ /dev/null
@@ -1,1823 +0,0 @@
-/*
- * Toshiba TC86C001 ("Goku-S") USB Device Controller driver
- *
- * Copyright (C) 2000-2002 Lineo
- *      by Stuart Lynne, Tom Rushworth, and Bruce Balden
- * Copyright (C) 2002 Toshiba Corporation
- * Copyright (C) 2003 MontaVista Software (source@mvista.com)
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-/*
- * This device has ep0 and three semi-configurable bulk/interrupt endpoints.
- *
- *  - Endpoint numbering is fixed: ep{1,2,3}-bulk
- *  - Gadget drivers can choose ep maxpacket (8/16/32/64)
- *  - Gadget drivers can choose direction (IN, OUT)
- *  - DMA works with ep1 (OUT transfers) and ep2 (IN transfers).
- */
-
-// #define     VERBOSE         /* extra debug messages (success too) */
-// #define     USB_TRACE       /* packet-level success messages */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/prefetch.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/unaligned.h>
-
-
-#include "goku_udc.h"
-
-#define        DRIVER_DESC             "TC86C001 USB Device Controller"
-#define        DRIVER_VERSION          "30-Oct 2003"
-
-static const char driver_name [] = "goku_udc";
-static const char driver_desc [] = DRIVER_DESC;
-
-MODULE_AUTHOR("source@mvista.com");
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
-
-/*
- * IN dma behaves ok under testing, though the IN-dma abort paths don't
- * seem to behave quite as expected.  Used by default.
- *
- * OUT dma documents design problems handling the common "short packet"
- * transfer termination policy; it couldn't be enabled by default, even
- * if the OUT-dma abort problems had a resolution.
- */
-static unsigned use_dma = 1;
-
-#if 0
-//#include <linux/moduleparam.h>
-/* "modprobe goku_udc use_dma=1" etc
- *     0 to disable dma
- *     1 to use IN dma only (normal operation)
- *     2 to use IN and OUT dma
- */
-module_param(use_dma, uint, S_IRUGO);
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-static void nuke(struct goku_ep *, int status);
-
-static inline void
-command(struct goku_udc_regs __iomem *regs, int command, unsigned epnum)
-{
-       writel(COMMAND_EP(epnum) | command, &regs->Command);
-       udelay(300);
-}
-
-static int
-goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
-{
-       struct goku_udc *dev;
-       struct goku_ep  *ep;
-       u32             mode;
-       u16             max;
-       unsigned long   flags;
-
-       ep = container_of(_ep, struct goku_ep, ep);
-       if (!_ep || !desc
-                       || desc->bDescriptorType != USB_DT_ENDPOINT)
-               return -EINVAL;
-       dev = ep->dev;
-       if (ep == &dev->ep[0])
-               return -EINVAL;
-       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-       if (ep->num != usb_endpoint_num(desc))
-               return -EINVAL;
-
-       switch (usb_endpoint_type(desc)) {
-       case USB_ENDPOINT_XFER_BULK:
-       case USB_ENDPOINT_XFER_INT:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if ((readl(ep->reg_status) & EPxSTATUS_EP_MASK)
-                       != EPxSTATUS_EP_INVALID)
-               return -EBUSY;
-
-       /* enabling the no-toggle interrupt mode would need an api hook */
-       mode = 0;
-       max = get_unaligned_le16(&desc->wMaxPacketSize);
-       switch (max) {
-       case 64:        mode++;
-       case 32:        mode++;
-       case 16:        mode++;
-       case 8:         mode <<= 3;
-                       break;
-       default:
-               return -EINVAL;
-       }
-       mode |= 2 << 1;         /* bulk, or intr-with-toggle */
-
-       /* ep1/ep2 dma direction is chosen early; it works in the other
-        * direction, with pio.  be cautious with out-dma.
-        */
-       ep->is_in = usb_endpoint_dir_in(desc);
-       if (ep->is_in) {
-               mode |= 1;
-               ep->dma = (use_dma != 0) && (ep->num == UDC_MSTRD_ENDPOINT);
-       } else {
-               ep->dma = (use_dma == 2) && (ep->num == UDC_MSTWR_ENDPOINT);
-               if (ep->dma)
-                       DBG(dev, "%s out-dma hides short packets\n",
-                               ep->ep.name);
-       }
-
-       spin_lock_irqsave(&ep->dev->lock, flags);
-
-       /* ep1 and ep2 can do double buffering and/or dma */
-       if (ep->num < 3) {
-               struct goku_udc_regs __iomem    *regs = ep->dev->regs;
-               u32                             tmp;
-
-               /* double buffer except (for now) with pio in */
-               tmp = ((ep->dma || !ep->is_in)
-                               ? 0x10  /* double buffered */
-                               : 0x11  /* single buffer */
-                       ) << ep->num;
-               tmp |= readl(&regs->EPxSingle);
-               writel(tmp, &regs->EPxSingle);
-
-               tmp = (ep->dma ? 0x10/*dma*/ : 0x11/*pio*/) << ep->num;
-               tmp |= readl(&regs->EPxBCS);
-               writel(tmp, &regs->EPxBCS);
-       }
-       writel(mode, ep->reg_mode);
-       command(ep->dev->regs, COMMAND_RESET, ep->num);
-       ep->ep.maxpacket = max;
-       ep->stopped = 0;
-       ep->ep.desc = desc;
-       spin_unlock_irqrestore(&ep->dev->lock, flags);
-
-       DBG(dev, "enable %s %s %s maxpacket %u\n", ep->ep.name,
-               ep->is_in ? "IN" : "OUT",
-               ep->dma ? "dma" : "pio",
-               max);
-
-       return 0;
-}
-
-static void ep_reset(struct goku_udc_regs __iomem *regs, struct goku_ep *ep)
-{
-       struct goku_udc         *dev = ep->dev;
-
-       if (regs) {
-               command(regs, COMMAND_INVALID, ep->num);
-               if (ep->num) {
-                       if (ep->num == UDC_MSTWR_ENDPOINT)
-                               dev->int_enable &= ~(INT_MSTWREND
-                                                       |INT_MSTWRTMOUT);
-                       else if (ep->num == UDC_MSTRD_ENDPOINT)
-                               dev->int_enable &= ~INT_MSTRDEND;
-                       dev->int_enable &= ~INT_EPxDATASET (ep->num);
-               } else
-                       dev->int_enable &= ~INT_EP0;
-               writel(dev->int_enable, &regs->int_enable);
-               readl(&regs->int_enable);
-               if (ep->num < 3) {
-                       struct goku_udc_regs __iomem    *r = ep->dev->regs;
-                       u32                             tmp;
-
-                       tmp = readl(&r->EPxSingle);
-                       tmp &= ~(0x11 << ep->num);
-                       writel(tmp, &r->EPxSingle);
-
-                       tmp = readl(&r->EPxBCS);
-                       tmp &= ~(0x11 << ep->num);
-                       writel(tmp, &r->EPxBCS);
-               }
-               /* reset dma in case we're still using it */
-               if (ep->dma) {
-                       u32     master;
-
-                       master = readl(&regs->dma_master) & MST_RW_BITS;
-                       if (ep->num == UDC_MSTWR_ENDPOINT) {
-                               master &= ~MST_W_BITS;
-                               master |= MST_WR_RESET;
-                       } else {
-                               master &= ~MST_R_BITS;
-                               master |= MST_RD_RESET;
-                       }
-                       writel(master, &regs->dma_master);
-               }
-       }
-
-       usb_ep_set_maxpacket_limit(&ep->ep, MAX_FIFO_SIZE);
-       ep->ep.desc = NULL;
-       ep->stopped = 1;
-       ep->irqs = 0;
-       ep->dma = 0;
-}
-
-static int goku_ep_disable(struct usb_ep *_ep)
-{
-       struct goku_ep  *ep;
-       struct goku_udc *dev;
-       unsigned long   flags;
-
-       ep = container_of(_ep, struct goku_ep, ep);
-       if (!_ep || !ep->ep.desc)
-               return -ENODEV;
-       dev = ep->dev;
-       if (dev->ep0state == EP0_SUSPEND)
-               return -EBUSY;
-
-       VDBG(dev, "disable %s\n", _ep->name);
-
-       spin_lock_irqsave(&dev->lock, flags);
-       nuke(ep, -ESHUTDOWN);
-       ep_reset(dev->regs, ep);
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_request *
-goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
-{
-       struct goku_request     *req;
-
-       if (!_ep)
-               return NULL;
-       req = kzalloc(sizeof *req, gfp_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD(&req->queue);
-       return &req->req;
-}
-
-static void
-goku_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct goku_request     *req;
-
-       if (!_ep || !_req)
-               return;
-
-       req = container_of(_req, struct goku_request, req);
-       WARN_ON(!list_empty(&req->queue));
-       kfree(req);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void
-done(struct goku_ep *ep, struct goku_request *req, int status)
-{
-       struct goku_udc         *dev;
-       unsigned                stopped = ep->stopped;
-
-       list_del_init(&req->queue);
-
-       if (likely(req->req.status == -EINPROGRESS))
-               req->req.status = status;
-       else
-               status = req->req.status;
-
-       dev = ep->dev;
-
-       if (ep->dma)
-               usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
-
-#ifndef USB_TRACE
-       if (status && status != -ESHUTDOWN)
-#endif
-               VDBG(dev, "complete %s req %p stat %d len %u/%u\n",
-                       ep->ep.name, &req->req, status,
-                       req->req.actual, req->req.length);
-
-       /* don't modify queue heads during completion callback */
-       ep->stopped = 1;
-       spin_unlock(&dev->lock);
-       req->req.complete(&ep->ep, &req->req);
-       spin_lock(&dev->lock);
-       ep->stopped = stopped;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline int
-write_packet(u32 __iomem *fifo, u8 *buf, struct goku_request *req, unsigned max)
-{
-       unsigned        length, count;
-
-       length = min(req->req.length - req->req.actual, max);
-       req->req.actual += length;
-
-       count = length;
-       while (likely(count--))
-               writel(*buf++, fifo);
-       return length;
-}
-
-// return:  0 = still running, 1 = completed, negative = errno
-static int write_fifo(struct goku_ep *ep, struct goku_request *req)
-{
-       struct goku_udc *dev = ep->dev;
-       u32             tmp;
-       u8              *buf;
-       unsigned        count;
-       int             is_last;
-
-       tmp = readl(&dev->regs->DataSet);
-       buf = req->req.buf + req->req.actual;
-       prefetch(buf);
-
-       dev = ep->dev;
-       if (unlikely(ep->num == 0 && dev->ep0state != EP0_IN))
-               return -EL2HLT;
-
-       /* NOTE:  just single-buffered PIO-IN for now.  */
-       if (unlikely((tmp & DATASET_A(ep->num)) != 0))
-               return 0;
-
-       /* clear our "packet available" irq */
-       if (ep->num != 0)
-               writel(~INT_EPxDATASET(ep->num), &dev->regs->int_status);
-
-       count = write_packet(ep->reg_fifo, buf, req, ep->ep.maxpacket);
-
-       /* last packet often short (sometimes a zlp, especially on ep0) */
-       if (unlikely(count != ep->ep.maxpacket)) {
-               writel(~(1<<ep->num), &dev->regs->EOP);
-               if (ep->num == 0) {
-                       dev->ep[0].stopped = 1;
-                       dev->ep0state = EP0_STATUS;
-               }
-               is_last = 1;
-       } else {
-               if (likely(req->req.length != req->req.actual)
-                               || req->req.zero)
-                       is_last = 0;
-               else
-                       is_last = 1;
-       }
-#if 0          /* printk seemed to trash is_last...*/
-//#ifdef USB_TRACE
-       VDBG(dev, "wrote %s %u bytes%s IN %u left %p\n",
-               ep->ep.name, count, is_last ? "/last" : "",
-               req->req.length - req->req.actual, req);
-#endif
-
-       /* requests complete when all IN data is in the FIFO,
-        * or sometimes later, if a zlp was needed.
-        */
-       if (is_last) {
-               done(ep, req, 0);
-               return 1;
-       }
-
-       return 0;
-}
-
-static int read_fifo(struct goku_ep *ep, struct goku_request *req)
-{
-       struct goku_udc_regs __iomem    *regs;
-       u32                             size, set;
-       u8                              *buf;
-       unsigned                        bufferspace, is_short, dbuff;
-
-       regs = ep->dev->regs;
-top:
-       buf = req->req.buf + req->req.actual;
-       prefetchw(buf);
-
-       if (unlikely(ep->num == 0 && ep->dev->ep0state != EP0_OUT))
-               return -EL2HLT;
-
-       dbuff = (ep->num == 1 || ep->num == 2);
-       do {
-               /* ack dataset irq matching the status we'll handle */
-               if (ep->num != 0)
-                       writel(~INT_EPxDATASET(ep->num), &regs->int_status);
-
-               set = readl(&regs->DataSet) & DATASET_AB(ep->num);
-               size = readl(&regs->EPxSizeLA[ep->num]);
-               bufferspace = req->req.length - req->req.actual;
-
-               /* usually do nothing without an OUT packet */
-               if (likely(ep->num != 0 || bufferspace != 0)) {
-                       if (unlikely(set == 0))
-                               break;
-                       /* use ep1/ep2 double-buffering for OUT */
-                       if (!(size & PACKET_ACTIVE))
-                               size = readl(&regs->EPxSizeLB[ep->num]);
-                       if (!(size & PACKET_ACTIVE))    /* "can't happen" */
-                               break;
-                       size &= DATASIZE;       /* EPxSizeH == 0 */
-
-               /* ep0out no-out-data case for set_config, etc */
-               } else
-                       size = 0;
-
-               /* read all bytes from this packet */
-               req->req.actual += size;
-               is_short = (size < ep->ep.maxpacket);
-#ifdef USB_TRACE
-               VDBG(ep->dev, "read %s %u bytes%s OUT req %p %u/%u\n",
-                       ep->ep.name, size, is_short ? "/S" : "",
-                       req, req->req.actual, req->req.length);
-#endif
-               while (likely(size-- != 0)) {
-                       u8      byte = (u8) readl(ep->reg_fifo);
-
-                       if (unlikely(bufferspace == 0)) {
-                               /* this happens when the driver's buffer
-                                * is smaller than what the host sent.
-                                * discard the extra data in this packet.
-                                */
-                               if (req->req.status != -EOVERFLOW)
-                                       DBG(ep->dev, "%s overflow %u\n",
-                                               ep->ep.name, size);
-                               req->req.status = -EOVERFLOW;
-                       } else {
-                               *buf++ = byte;
-                               bufferspace--;
-                       }
-               }
-
-               /* completion */
-               if (unlikely(is_short || req->req.actual == req->req.length)) {
-                       if (unlikely(ep->num == 0)) {
-                               /* non-control endpoints now usable? */
-                               if (ep->dev->req_config)
-                                       writel(ep->dev->configured
-                                                       ? USBSTATE_CONFIGURED
-                                                       : 0,
-                                               &regs->UsbState);
-                               /* ep0out status stage */
-                               writel(~(1<<0), &regs->EOP);
-                               ep->stopped = 1;
-                               ep->dev->ep0state = EP0_STATUS;
-                       }
-                       done(ep, req, 0);
-
-                       /* empty the second buffer asap */
-                       if (dbuff && !list_empty(&ep->queue)) {
-                               req = list_entry(ep->queue.next,
-                                               struct goku_request, queue);
-                               goto top;
-                       }
-                       return 1;
-               }
-       } while (dbuff);
-       return 0;
-}
-
-static inline void
-pio_irq_enable(struct goku_udc *dev,
-               struct goku_udc_regs __iomem *regs, int epnum)
-{
-       dev->int_enable |= INT_EPxDATASET (epnum);
-       writel(dev->int_enable, &regs->int_enable);
-       /* write may still be posted */
-}
-
-static inline void
-pio_irq_disable(struct goku_udc *dev,
-               struct goku_udc_regs __iomem *regs, int epnum)
-{
-       dev->int_enable &= ~INT_EPxDATASET (epnum);
-       writel(dev->int_enable, &regs->int_enable);
-       /* write may still be posted */
-}
-
-static inline void
-pio_advance(struct goku_ep *ep)
-{
-       struct goku_request     *req;
-
-       if (unlikely(list_empty (&ep->queue)))
-               return;
-       req = list_entry(ep->queue.next, struct goku_request, queue);
-       (ep->is_in ? write_fifo : read_fifo)(ep, req);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-// return:  0 = q running, 1 = q stopped, negative = errno
-static int start_dma(struct goku_ep *ep, struct goku_request *req)
-{
-       struct goku_udc_regs __iomem    *regs = ep->dev->regs;
-       u32                             master;
-       u32                             start = req->req.dma;
-       u32                             end = start + req->req.length - 1;
-
-       master = readl(&regs->dma_master) & MST_RW_BITS;
-
-       /* re-init the bits affecting IN dma; careful with zlps */
-       if (likely(ep->is_in)) {
-               if (unlikely(master & MST_RD_ENA)) {
-                       DBG (ep->dev, "start, IN active dma %03x!!\n",
-                               master);
-//                     return -EL2HLT;
-               }
-               writel(end, &regs->in_dma_end);
-               writel(start, &regs->in_dma_start);
-
-               master &= ~MST_R_BITS;
-               if (unlikely(req->req.length == 0))
-                       master = MST_RD_ENA | MST_RD_EOPB;
-               else if ((req->req.length % ep->ep.maxpacket) != 0
-                                       || req->req.zero)
-                       master = MST_RD_ENA | MST_EOPB_ENA;
-               else
-                       master = MST_RD_ENA | MST_EOPB_DIS;
-
-               ep->dev->int_enable |= INT_MSTRDEND;
-
-       /* Goku DMA-OUT merges short packets, which plays poorly with
-        * protocols where short packets mark the transfer boundaries.
-        * The chip supports a nonstandard policy with INT_MSTWRTMOUT,
-        * ending transfers after 3 SOFs; we don't turn it on.
-        */
-       } else {
-               if (unlikely(master & MST_WR_ENA)) {
-                       DBG (ep->dev, "start, OUT active dma %03x!!\n",
-                               master);
-//                     return -EL2HLT;
-               }
-               writel(end, &regs->out_dma_end);
-               writel(start, &regs->out_dma_start);
-
-               master &= ~MST_W_BITS;
-               master |= MST_WR_ENA | MST_TIMEOUT_DIS;
-
-               ep->dev->int_enable |= INT_MSTWREND|INT_MSTWRTMOUT;
-       }
-
-       writel(master, &regs->dma_master);
-       writel(ep->dev->int_enable, &regs->int_enable);
-       return 0;
-}
-
-static void dma_advance(struct goku_udc *dev, struct goku_ep *ep)
-{
-       struct goku_request             *req;
-       struct goku_udc_regs __iomem    *regs = ep->dev->regs;
-       u32                             master;
-
-       master = readl(&regs->dma_master);
-
-       if (unlikely(list_empty(&ep->queue))) {
-stop:
-               if (ep->is_in)
-                       dev->int_enable &= ~INT_MSTRDEND;
-               else
-                       dev->int_enable &= ~(INT_MSTWREND|INT_MSTWRTMOUT);
-               writel(dev->int_enable, &regs->int_enable);
-               return;
-       }
-       req = list_entry(ep->queue.next, struct goku_request, queue);
-
-       /* normal hw dma completion (not abort) */
-       if (likely(ep->is_in)) {
-               if (unlikely(master & MST_RD_ENA))
-                       return;
-               req->req.actual = readl(&regs->in_dma_current);
-       } else {
-               if (unlikely(master & MST_WR_ENA))
-                       return;
-
-               /* hardware merges short packets, and also hides packet
-                * overruns.  a partial packet MAY be in the fifo here.
-                */
-               req->req.actual = readl(&regs->out_dma_current);
-       }
-       req->req.actual -= req->req.dma;
-       req->req.actual++;
-
-#ifdef USB_TRACE
-       VDBG(dev, "done %s %s dma, %u/%u bytes, req %p\n",
-               ep->ep.name, ep->is_in ? "IN" : "OUT",
-               req->req.actual, req->req.length, req);
-#endif
-       done(ep, req, 0);
-       if (list_empty(&ep->queue))
-               goto stop;
-       req = list_entry(ep->queue.next, struct goku_request, queue);
-       (void) start_dma(ep, req);
-}
-
-static void abort_dma(struct goku_ep *ep, int status)
-{
-       struct goku_udc_regs __iomem    *regs = ep->dev->regs;
-       struct goku_request             *req;
-       u32                             curr, master;
-
-       /* NAK future host requests, hoping the implicit delay lets the
-        * dma engine finish reading (or writing) its latest packet and
-        * empty the dma buffer (up to 16 bytes).
-        *
-        * This avoids needing to clean up a partial packet in the fifo;
-        * we can't do that for IN without side effects to HALT and TOGGLE.
-        */
-       command(regs, COMMAND_FIFO_DISABLE, ep->num);
-       req = list_entry(ep->queue.next, struct goku_request, queue);
-       master = readl(&regs->dma_master) & MST_RW_BITS;
-
-       /* FIXME using these resets isn't usably documented. this may
-        * not work unless it's followed by disabling the endpoint.
-        *
-        * FIXME the OUT reset path doesn't even behave consistently.
-        */
-       if (ep->is_in) {
-               if (unlikely((readl(&regs->dma_master) & MST_RD_ENA) == 0))
-                       goto finished;
-               curr = readl(&regs->in_dma_current);
-
-               writel(curr, &regs->in_dma_end);
-               writel(curr, &regs->in_dma_start);
-
-               master &= ~MST_R_BITS;
-               master |= MST_RD_RESET;
-               writel(master, &regs->dma_master);
-
-               if (readl(&regs->dma_master) & MST_RD_ENA)
-                       DBG(ep->dev, "IN dma active after reset!\n");
-
-       } else {
-               if (unlikely((readl(&regs->dma_master) & MST_WR_ENA) == 0))
-                       goto finished;
-               curr = readl(&regs->out_dma_current);
-
-               writel(curr, &regs->out_dma_end);
-               writel(curr, &regs->out_dma_start);
-
-               master &= ~MST_W_BITS;
-               master |= MST_WR_RESET;
-               writel(master, &regs->dma_master);
-
-               if (readl(&regs->dma_master) & MST_WR_ENA)
-                       DBG(ep->dev, "OUT dma active after reset!\n");
-       }
-       req->req.actual = (curr - req->req.dma) + 1;
-       req->req.status = status;
-
-       VDBG(ep->dev, "%s %s %s %d/%d\n", __func__, ep->ep.name,
-               ep->is_in ? "IN" : "OUT",
-               req->req.actual, req->req.length);
-
-       command(regs, COMMAND_FIFO_ENABLE, ep->num);
-
-       return;
-
-finished:
-       /* dma already completed; no abort needed */
-       command(regs, COMMAND_FIFO_ENABLE, ep->num);
-       req->req.actual = req->req.length;
-       req->req.status = 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
-{
-       struct goku_request     *req;
-       struct goku_ep          *ep;
-       struct goku_udc         *dev;
-       unsigned long           flags;
-       int                     status;
-
-       /* always require a cpu-view buffer so pio works */
-       req = container_of(_req, struct goku_request, req);
-       if (unlikely(!_req || !_req->complete
-                       || !_req->buf || !list_empty(&req->queue)))
-               return -EINVAL;
-       ep = container_of(_ep, struct goku_ep, ep);
-       if (unlikely(!_ep || (!ep->ep.desc && ep->num != 0)))
-               return -EINVAL;
-       dev = ep->dev;
-       if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN))
-               return -ESHUTDOWN;
-
-       /* can't touch registers when suspended */
-       if (dev->ep0state == EP0_SUSPEND)
-               return -EBUSY;
-
-       /* set up dma mapping in case the caller didn't */
-       if (ep->dma) {
-               status = usb_gadget_map_request(&dev->gadget, &req->req,
-                               ep->is_in);
-               if (status)
-                       return status;
-       }
-
-#ifdef USB_TRACE
-       VDBG(dev, "%s queue req %p, len %u buf %p\n",
-                       _ep->name, _req, _req->length, _req->buf);
-#endif
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       _req->status = -EINPROGRESS;
-       _req->actual = 0;
-
-       /* for ep0 IN without premature status, zlp is required and
-        * writing EOP starts the status stage (OUT).
-        */
-       if (unlikely(ep->num == 0 && ep->is_in))
-               _req->zero = 1;
-
-       /* kickstart this i/o queue? */
-       status = 0;
-       if (list_empty(&ep->queue) && likely(!ep->stopped)) {
-               /* dma:  done after dma completion IRQ (or error)
-                * pio:  done after last fifo operation
-                */
-               if (ep->dma)
-                       status = start_dma(ep, req);
-               else
-                       status = (ep->is_in ? write_fifo : read_fifo)(ep, req);
-
-               if (unlikely(status != 0)) {
-                       if (status > 0)
-                               status = 0;
-                       req = NULL;
-               }
-
-       } /* else pio or dma irq handler advances the queue. */
-
-       if (likely(req != NULL))
-               list_add_tail(&req->queue, &ep->queue);
-
-       if (likely(!list_empty(&ep->queue))
-                       && likely(ep->num != 0)
-                       && !ep->dma
-                       && !(dev->int_enable & INT_EPxDATASET (ep->num)))
-               pio_irq_enable(dev, dev->regs, ep->num);
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       /* pci writes may still be posted */
-       return status;
-}
-
-/* dequeue ALL requests */
-static void nuke(struct goku_ep *ep, int status)
-{
-       struct goku_request     *req;
-
-       ep->stopped = 1;
-       if (list_empty(&ep->queue))
-               return;
-       if (ep->dma)
-               abort_dma(ep, status);
-       while (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next, struct goku_request, queue);
-               done(ep, req, status);
-       }
-}
-
-/* dequeue JUST ONE request */
-static int goku_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct goku_request     *req;
-       struct goku_ep          *ep;
-       struct goku_udc         *dev;
-       unsigned long           flags;
-
-       ep = container_of(_ep, struct goku_ep, ep);
-       if (!_ep || !_req || (!ep->ep.desc && ep->num != 0))
-               return -EINVAL;
-       dev = ep->dev;
-       if (!dev->driver)
-               return -ESHUTDOWN;
-
-       /* we can't touch (dma) registers when suspended */
-       if (dev->ep0state == EP0_SUSPEND)
-               return -EBUSY;
-
-       VDBG(dev, "%s %s %s %s %p\n", __func__, _ep->name,
-               ep->is_in ? "IN" : "OUT",
-               ep->dma ? "dma" : "pio",
-               _req);
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       /* make sure it's actually queued on this endpoint */
-       list_for_each_entry (req, &ep->queue, queue) {
-               if (&req->req == _req)
-                       break;
-       }
-       if (&req->req != _req) {
-               spin_unlock_irqrestore (&dev->lock, flags);
-               return -EINVAL;
-       }
-
-       if (ep->dma && ep->queue.next == &req->queue && !ep->stopped) {
-               abort_dma(ep, -ECONNRESET);
-               done(ep, req, -ECONNRESET);
-               dma_advance(dev, ep);
-       } else if (!list_empty(&req->queue))
-               done(ep, req, -ECONNRESET);
-       else
-               req = NULL;
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return req ? 0 : -EOPNOTSUPP;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void goku_clear_halt(struct goku_ep *ep)
-{
-       // assert (ep->num !=0)
-       VDBG(ep->dev, "%s clear halt\n", ep->ep.name);
-       command(ep->dev->regs, COMMAND_SETDATA0, ep->num);
-       command(ep->dev->regs, COMMAND_STALL_CLEAR, ep->num);
-       if (ep->stopped) {
-               ep->stopped = 0;
-               if (ep->dma) {
-                       struct goku_request     *req;
-
-                       if (list_empty(&ep->queue))
-                               return;
-                       req = list_entry(ep->queue.next, struct goku_request,
-                                               queue);
-                       (void) start_dma(ep, req);
-               } else
-                       pio_advance(ep);
-       }
-}
-
-static int goku_set_halt(struct usb_ep *_ep, int value)
-{
-       struct goku_ep  *ep;
-       unsigned long   flags;
-       int             retval = 0;
-
-       if (!_ep)
-               return -ENODEV;
-       ep = container_of (_ep, struct goku_ep, ep);
-
-       if (ep->num == 0) {
-               if (value) {
-                       ep->dev->ep0state = EP0_STALL;
-                       ep->dev->ep[0].stopped = 1;
-               } else
-                       return -EINVAL;
-
-       /* don't change EPxSTATUS_EP_INVALID to READY */
-       } else if (!ep->ep.desc) {
-               DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name);
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&ep->dev->lock, flags);
-       if (!list_empty(&ep->queue))
-               retval = -EAGAIN;
-       else if (ep->is_in && value
-                       /* data in (either) packet buffer? */
-                       && (readl(&ep->dev->regs->DataSet)
-                                       & DATASET_AB(ep->num)))
-               retval = -EAGAIN;
-       else if (!value)
-               goku_clear_halt(ep);
-       else {
-               ep->stopped = 1;
-               VDBG(ep->dev, "%s set halt\n", ep->ep.name);
-               command(ep->dev->regs, COMMAND_STALL, ep->num);
-               readl(ep->reg_status);
-       }
-       spin_unlock_irqrestore(&ep->dev->lock, flags);
-       return retval;
-}
-
-static int goku_fifo_status(struct usb_ep *_ep)
-{
-       struct goku_ep                  *ep;
-       struct goku_udc_regs __iomem    *regs;
-       u32                             size;
-
-       if (!_ep)
-               return -ENODEV;
-       ep = container_of(_ep, struct goku_ep, ep);
-
-       /* size is only reported sanely for OUT */
-       if (ep->is_in)
-               return -EOPNOTSUPP;
-
-       /* ignores 16-byte dma buffer; SizeH == 0 */
-       regs = ep->dev->regs;
-       size = readl(&regs->EPxSizeLA[ep->num]) & DATASIZE;
-       size += readl(&regs->EPxSizeLB[ep->num]) & DATASIZE;
-       VDBG(ep->dev, "%s %s %u\n", __func__, ep->ep.name, size);
-       return size;
-}
-
-static void goku_fifo_flush(struct usb_ep *_ep)
-{
-       struct goku_ep                  *ep;
-       struct goku_udc_regs __iomem    *regs;
-       u32                             size;
-
-       if (!_ep)
-               return;
-       ep = container_of(_ep, struct goku_ep, ep);
-       VDBG(ep->dev, "%s %s\n", __func__, ep->ep.name);
-
-       /* don't change EPxSTATUS_EP_INVALID to READY */
-       if (!ep->ep.desc && ep->num != 0) {
-               DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name);
-               return;
-       }
-
-       regs = ep->dev->regs;
-       size = readl(&regs->EPxSizeLA[ep->num]);
-       size &= DATASIZE;
-
-       /* Non-desirable behavior:  FIFO_CLEAR also clears the
-        * endpoint halt feature.  For OUT, we _could_ just read
-        * the bytes out (PIO, if !ep->dma); for in, no choice.
-        */
-       if (size)
-               command(regs, COMMAND_FIFO_CLEAR, ep->num);
-}
-
-static struct usb_ep_ops goku_ep_ops = {
-       .enable         = goku_ep_enable,
-       .disable        = goku_ep_disable,
-
-       .alloc_request  = goku_alloc_request,
-       .free_request   = goku_free_request,
-
-       .queue          = goku_queue,
-       .dequeue        = goku_dequeue,
-
-       .set_halt       = goku_set_halt,
-       .fifo_status    = goku_fifo_status,
-       .fifo_flush     = goku_fifo_flush,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int goku_get_frame(struct usb_gadget *_gadget)
-{
-       return -EOPNOTSUPP;
-}
-
-static int goku_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-static int goku_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-
-static const struct usb_gadget_ops goku_ops = {
-       .get_frame      = goku_get_frame,
-       .udc_start      = goku_udc_start,
-       .udc_stop       = goku_udc_stop,
-       // no remote wakeup
-       // not selfpowered
-};
-
-/*-------------------------------------------------------------------------*/
-
-static inline const char *dmastr(void)
-{
-       if (use_dma == 0)
-               return "(dma disabled)";
-       else if (use_dma == 2)
-               return "(dma IN and OUT)";
-       else
-               return "(dma IN)";
-}
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-
-static const char proc_node_name [] = "driver/udc";
-
-#define FOURBITS "%s%s%s%s"
-#define EIGHTBITS FOURBITS FOURBITS
-
-static void dump_intmask(struct seq_file *m, const char *label, u32 mask)
-{
-       /* int_status is the same format ... */
-       seq_printf(m,
-               "%s %05X =" FOURBITS EIGHTBITS EIGHTBITS "\n",
-               label, mask,
-               (mask & INT_PWRDETECT) ? " power" : "",
-               (mask & INT_SYSERROR) ? " sys" : "",
-               (mask & INT_MSTRDEND) ? " in-dma" : "",
-               (mask & INT_MSTWRTMOUT) ? " wrtmo" : "",
-
-               (mask & INT_MSTWREND) ? " out-dma" : "",
-               (mask & INT_MSTWRSET) ? " wrset" : "",
-               (mask & INT_ERR) ? " err" : "",
-               (mask & INT_SOF) ? " sof" : "",
-
-               (mask & INT_EP3NAK) ? " ep3nak" : "",
-               (mask & INT_EP2NAK) ? " ep2nak" : "",
-               (mask & INT_EP1NAK) ? " ep1nak" : "",
-               (mask & INT_EP3DATASET) ? " ep3" : "",
-
-               (mask & INT_EP2DATASET) ? " ep2" : "",
-               (mask & INT_EP1DATASET) ? " ep1" : "",
-               (mask & INT_STATUSNAK) ? " ep0snak" : "",
-               (mask & INT_STATUS) ? " ep0status" : "",
-
-               (mask & INT_SETUP) ? " setup" : "",
-               (mask & INT_ENDPOINT0) ? " ep0" : "",
-               (mask & INT_USBRESET) ? " reset" : "",
-               (mask & INT_SUSPEND) ? " suspend" : "");
-}
-
-
-static int udc_proc_read(struct seq_file *m, void *v)
-{
-       struct goku_udc                 *dev = m->private;
-       struct goku_udc_regs __iomem    *regs = dev->regs;
-       unsigned long                   flags;
-       int                             i, is_usb_connected;
-       u32                             tmp;
-
-       local_irq_save(flags);
-
-       /* basic device status */
-       tmp = readl(&regs->power_detect);
-       is_usb_connected = tmp & PW_DETECT;
-       seq_printf(m,
-               "%s - %s\n"
-               "%s version: %s %s\n"
-               "Gadget driver: %s\n"
-               "Host %s, %s\n"
-               "\n",
-               pci_name(dev->pdev), driver_desc,
-               driver_name, DRIVER_VERSION, dmastr(),
-               dev->driver ? dev->driver->driver.name : "(none)",
-               is_usb_connected
-                       ? ((tmp & PW_PULLUP) ? "full speed" : "powered")
-                       : "disconnected",
-               ({const char *state;
-               switch(dev->ep0state){
-               case EP0_DISCONNECT:    state = "ep0_disconnect"; break;
-               case EP0_IDLE:          state = "ep0_idle"; break;
-               case EP0_IN:            state = "ep0_in"; break;
-               case EP0_OUT:           state = "ep0_out"; break;
-               case EP0_STATUS:        state = "ep0_status"; break;
-               case EP0_STALL:         state = "ep0_stall"; break;
-               case EP0_SUSPEND:       state = "ep0_suspend"; break;
-               default:                state = "ep0_?"; break;
-               } state; })
-               );
-
-       dump_intmask(m, "int_status", readl(&regs->int_status));
-       dump_intmask(m, "int_enable", readl(&regs->int_enable));
-
-       if (!is_usb_connected || !dev->driver || (tmp & PW_PULLUP) == 0)
-               goto done;
-
-       /* registers for (active) device and ep0 */
-       if (seq_printf(m, "\nirqs %lu\ndataset %02x "
-                       "single.bcs %02x.%02x state %x addr %u\n",
-                       dev->irqs, readl(&regs->DataSet),
-                       readl(&regs->EPxSingle), readl(&regs->EPxBCS),
-                       readl(&regs->UsbState),
-                       readl(&regs->address)) < 0)
-               goto done;
-
-       tmp = readl(&regs->dma_master);
-       if (seq_printf(m,
-               "dma %03X =" EIGHTBITS "%s %s\n", tmp,
-               (tmp & MST_EOPB_DIS) ? " eopb-" : "",
-               (tmp & MST_EOPB_ENA) ? " eopb+" : "",
-               (tmp & MST_TIMEOUT_DIS) ? " tmo-" : "",
-               (tmp & MST_TIMEOUT_ENA) ? " tmo+" : "",
-
-               (tmp & MST_RD_EOPB) ? " eopb" : "",
-               (tmp & MST_RD_RESET) ? " in_reset" : "",
-               (tmp & MST_WR_RESET) ? " out_reset" : "",
-               (tmp & MST_RD_ENA) ? " IN" : "",
-
-               (tmp & MST_WR_ENA) ? " OUT" : "",
-               (tmp & MST_CONNECTION)
-                       ? "ep1in/ep2out"
-                       : "ep1out/ep2in") < 0)
-               goto done;
-
-       /* dump endpoint queues */
-       for (i = 0; i < 4; i++) {
-               struct goku_ep          *ep = &dev->ep [i];
-               struct goku_request     *req;
-
-               if (i && !ep->ep.desc)
-                       continue;
-
-               tmp = readl(ep->reg_status);
-               if (seq_printf(m,
-                       "%s %s max %u %s, irqs %lu, "
-                       "status %02x (%s) " FOURBITS "\n",
-                       ep->ep.name,
-                       ep->is_in ? "in" : "out",
-                       ep->ep.maxpacket,
-                       ep->dma ? "dma" : "pio",
-                       ep->irqs,
-                       tmp, ({ char *s;
-                       switch (tmp & EPxSTATUS_EP_MASK) {
-                       case EPxSTATUS_EP_READY:
-                               s = "ready"; break;
-                       case EPxSTATUS_EP_DATAIN:
-                               s = "packet"; break;
-                       case EPxSTATUS_EP_FULL:
-                               s = "full"; break;
-                       case EPxSTATUS_EP_TX_ERR:       // host will retry
-                               s = "tx_err"; break;
-                       case EPxSTATUS_EP_RX_ERR:
-                               s = "rx_err"; break;
-                       case EPxSTATUS_EP_BUSY:         /* ep0 only */
-                               s = "busy"; break;
-                       case EPxSTATUS_EP_STALL:
-                               s = "stall"; break;
-                       case EPxSTATUS_EP_INVALID:      // these "can't happen"
-                               s = "invalid"; break;
-                       default:
-                               s = "?"; break;
-                       } s; }),
-                       (tmp & EPxSTATUS_TOGGLE) ? "data1" : "data0",
-                       (tmp & EPxSTATUS_SUSPEND) ? " suspend" : "",
-                       (tmp & EPxSTATUS_FIFO_DISABLE) ? " disable" : "",
-                       (tmp & EPxSTATUS_STAGE_ERROR) ? " ep0stat" : ""
-                       ) < 0)
-                       goto done;
-
-               if (list_empty(&ep->queue)) {
-                       if (seq_puts(m, "\t(nothing queued)\n") < 0)
-                               goto done;
-                       continue;
-               }
-               list_for_each_entry(req, &ep->queue, queue) {
-                       if (ep->dma && req->queue.prev == &ep->queue) {
-                               if (i == UDC_MSTRD_ENDPOINT)
-                                       tmp = readl(&regs->in_dma_current);
-                               else
-                                       tmp = readl(&regs->out_dma_current);
-                               tmp -= req->req.dma;
-                               tmp++;
-                       } else
-                               tmp = req->req.actual;
-
-                       if (seq_printf(m,
-                               "\treq %p len %u/%u buf %p\n",
-                               &req->req, tmp, req->req.length,
-                               req->req.buf) < 0)
-                               goto done;
-               }
-       }
-
-done:
-       local_irq_restore(flags);
-       return 0;
-}
-
-/*
- * seq_file wrappers for procfile show routines.
- */
-static int udc_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, udc_proc_read, PDE_DATA(file_inode(file)));
-}
-
-static const struct file_operations udc_proc_fops = {
-       .open           = udc_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
-
-/*-------------------------------------------------------------------------*/
-
-static void udc_reinit (struct goku_udc *dev)
-{
-       static char *names [] = { "ep0", "ep1-bulk", "ep2-bulk", "ep3-bulk" };
-
-       unsigned i;
-
-       INIT_LIST_HEAD (&dev->gadget.ep_list);
-       dev->gadget.ep0 = &dev->ep [0].ep;
-       dev->gadget.speed = USB_SPEED_UNKNOWN;
-       dev->ep0state = EP0_DISCONNECT;
-       dev->irqs = 0;
-
-       for (i = 0; i < 4; i++) {
-               struct goku_ep  *ep = &dev->ep[i];
-
-               ep->num = i;
-               ep->ep.name = names[i];
-               ep->reg_fifo = &dev->regs->ep_fifo [i];
-               ep->reg_status = &dev->regs->ep_status [i];
-               ep->reg_mode = &dev->regs->ep_mode[i];
-
-               ep->ep.ops = &goku_ep_ops;
-               list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
-               ep->dev = dev;
-               INIT_LIST_HEAD (&ep->queue);
-
-               ep_reset(NULL, ep);
-       }
-
-       dev->ep[0].reg_mode = NULL;
-       usb_ep_set_maxpacket_limit(&dev->ep[0].ep, MAX_EP0_SIZE);
-       list_del_init (&dev->ep[0].ep.ep_list);
-}
-
-static void udc_reset(struct goku_udc *dev)
-{
-       struct goku_udc_regs __iomem    *regs = dev->regs;
-
-       writel(0, &regs->power_detect);
-       writel(0, &regs->int_enable);
-       readl(&regs->int_enable);
-       dev->int_enable = 0;
-
-       /* deassert reset, leave USB D+ at hi-Z (no pullup)
-        * don't let INT_PWRDETECT sequence begin
-        */
-       udelay(250);
-       writel(PW_RESETB, &regs->power_detect);
-       readl(&regs->int_enable);
-}
-
-static void ep0_start(struct goku_udc *dev)
-{
-       struct goku_udc_regs __iomem    *regs = dev->regs;
-       unsigned                        i;
-
-       VDBG(dev, "%s\n", __func__);
-
-       udc_reset(dev);
-       udc_reinit (dev);
-       //writel(MST_EOPB_ENA | MST_TIMEOUT_ENA, &regs->dma_master);
-
-       /* hw handles set_address, set_feature, get_status; maybe more */
-       writel(   G_REQMODE_SET_INTF | G_REQMODE_GET_INTF
-               | G_REQMODE_SET_CONF | G_REQMODE_GET_CONF
-               | G_REQMODE_GET_DESC
-               | G_REQMODE_CLEAR_FEAT
-               , &regs->reqmode);
-
-       for (i = 0; i < 4; i++)
-               dev->ep[i].irqs = 0;
-
-       /* can't modify descriptors after writing UsbReady */
-       for (i = 0; i < DESC_LEN; i++)
-               writel(0, &regs->descriptors[i]);
-       writel(0, &regs->UsbReady);
-
-       /* expect ep0 requests when the host drops reset */
-       writel(PW_RESETB | PW_PULLUP, &regs->power_detect);
-       dev->int_enable = INT_DEVWIDE | INT_EP0;
-       writel(dev->int_enable, &dev->regs->int_enable);
-       readl(&regs->int_enable);
-       dev->gadget.speed = USB_SPEED_FULL;
-       dev->ep0state = EP0_IDLE;
-}
-
-static void udc_enable(struct goku_udc *dev)
-{
-       /* start enumeration now, or after power detect irq */
-       if (readl(&dev->regs->power_detect) & PW_DETECT)
-               ep0_start(dev);
-       else {
-               DBG(dev, "%s\n", __func__);
-               dev->int_enable = INT_PWRDETECT;
-               writel(dev->int_enable, &dev->regs->int_enable);
-       }
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* keeping it simple:
- * - one bus driver, initted first;
- * - one function driver, initted second
- */
-
-/* when a driver is successfully registered, it will receive
- * control requests including set_configuration(), which enables
- * non-control requests.  then usb traffic follows until a
- * disconnect is reported.  then a host may connect again, or
- * the driver might get unbound.
- */
-static int goku_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct goku_udc *dev = to_goku_udc(g);
-
-       /* hook up the driver */
-       driver->driver.bus = NULL;
-       dev->driver = driver;
-
-       /*
-        * then enable host detection and ep0; and we're ready
-        * for set_configuration as well as eventual disconnect.
-        */
-       udc_enable(dev);
-
-       return 0;
-}
-
-static void stop_activity(struct goku_udc *dev)
-{
-       unsigned        i;
-
-       DBG (dev, "%s\n", __func__);
-
-       /* disconnect gadget driver after quiesceing hw and the driver */
-       udc_reset (dev);
-       for (i = 0; i < 4; i++)
-               nuke(&dev->ep [i], -ESHUTDOWN);
-
-       if (dev->driver)
-               udc_enable(dev);
-}
-
-static int goku_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct goku_udc *dev = to_goku_udc(g);
-       unsigned long   flags;
-
-       spin_lock_irqsave(&dev->lock, flags);
-       dev->driver = NULL;
-       stop_activity(dev);
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void ep0_setup(struct goku_udc *dev)
-{
-       struct goku_udc_regs __iomem    *regs = dev->regs;
-       struct usb_ctrlrequest          ctrl;
-       int                             tmp;
-
-       /* read SETUP packet and enter DATA stage */
-       ctrl.bRequestType = readl(&regs->bRequestType);
-       ctrl.bRequest = readl(&regs->bRequest);
-       ctrl.wValue  = cpu_to_le16((readl(&regs->wValueH)  << 8)
-                                       | readl(&regs->wValueL));
-       ctrl.wIndex  = cpu_to_le16((readl(&regs->wIndexH)  << 8)
-                                       | readl(&regs->wIndexL));
-       ctrl.wLength = cpu_to_le16((readl(&regs->wLengthH) << 8)
-                                       | readl(&regs->wLengthL));
-       writel(0, &regs->SetupRecv);
-
-       nuke(&dev->ep[0], 0);
-       dev->ep[0].stopped = 0;
-       if (likely(ctrl.bRequestType & USB_DIR_IN)) {
-               dev->ep[0].is_in = 1;
-               dev->ep0state = EP0_IN;
-               /* detect early status stages */
-               writel(ICONTROL_STATUSNAK, &dev->regs->IntControl);
-       } else {
-               dev->ep[0].is_in = 0;
-               dev->ep0state = EP0_OUT;
-
-               /* NOTE:  CLEAR_FEATURE is done in software so that we can
-                * synchronize transfer restarts after bulk IN stalls.  data
-                * won't even enter the fifo until the halt is cleared.
-                */
-               switch (ctrl.bRequest) {
-               case USB_REQ_CLEAR_FEATURE:
-                       switch (ctrl.bRequestType) {
-                       case USB_RECIP_ENDPOINT:
-                               tmp = le16_to_cpu(ctrl.wIndex) & 0x0f;
-                               /* active endpoint */
-                               if (tmp > 3 ||
-                                   (!dev->ep[tmp].ep.desc && tmp != 0))
-                                       goto stall;
-                               if (ctrl.wIndex & cpu_to_le16(
-                                               USB_DIR_IN)) {
-                                       if (!dev->ep[tmp].is_in)
-                                               goto stall;
-                               } else {
-                                       if (dev->ep[tmp].is_in)
-                                               goto stall;
-                               }
-                               if (ctrl.wValue != cpu_to_le16(
-                                               USB_ENDPOINT_HALT))
-                                       goto stall;
-                               if (tmp)
-                                       goku_clear_halt(&dev->ep[tmp]);
-succeed:
-                               /* start ep0out status stage */
-                               writel(~(1<<0), &regs->EOP);
-                               dev->ep[0].stopped = 1;
-                               dev->ep0state = EP0_STATUS;
-                               return;
-                       case USB_RECIP_DEVICE:
-                               /* device remote wakeup: always clear */
-                               if (ctrl.wValue != cpu_to_le16(1))
-                                       goto stall;
-                               VDBG(dev, "clear dev remote wakeup\n");
-                               goto succeed;
-                       case USB_RECIP_INTERFACE:
-                               goto stall;
-                       default:                /* pass to gadget driver */
-                               break;
-                       }
-                       break;
-               default:
-                       break;
-               }
-       }
-
-#ifdef USB_TRACE
-       VDBG(dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
-               ctrl.bRequestType, ctrl.bRequest,
-               le16_to_cpu(ctrl.wValue), le16_to_cpu(ctrl.wIndex),
-               le16_to_cpu(ctrl.wLength));
-#endif
-
-       /* hw wants to know when we're configured (or not) */
-       dev->req_config = (ctrl.bRequest == USB_REQ_SET_CONFIGURATION
-                               && ctrl.bRequestType == USB_RECIP_DEVICE);
-       if (unlikely(dev->req_config))
-               dev->configured = (ctrl.wValue != cpu_to_le16(0));
-
-       /* delegate everything to the gadget driver.
-        * it may respond after this irq handler returns.
-        */
-       spin_unlock (&dev->lock);
-       tmp = dev->driver->setup(&dev->gadget, &ctrl);
-       spin_lock (&dev->lock);
-       if (unlikely(tmp < 0)) {
-stall:
-#ifdef USB_TRACE
-               VDBG(dev, "req %02x.%02x protocol STALL; err %d\n",
-                               ctrl.bRequestType, ctrl.bRequest, tmp);
-#endif
-               command(regs, COMMAND_STALL, 0);
-               dev->ep[0].stopped = 1;
-               dev->ep0state = EP0_STALL;
-       }
-
-       /* expect at least one data or status stage irq */
-}
-
-#define ACK(irqbit) { \
-               stat &= ~irqbit; \
-               writel(~irqbit, &regs->int_status); \
-               handled = 1; \
-               }
-
-static irqreturn_t goku_irq(int irq, void *_dev)
-{
-       struct goku_udc                 *dev = _dev;
-       struct goku_udc_regs __iomem    *regs = dev->regs;
-       struct goku_ep                  *ep;
-       u32                             stat, handled = 0;
-       unsigned                        i, rescans = 5;
-
-       spin_lock(&dev->lock);
-
-rescan:
-       stat = readl(&regs->int_status) & dev->int_enable;
-        if (!stat)
-               goto done;
-       dev->irqs++;
-
-       /* device-wide irqs */
-       if (unlikely(stat & INT_DEVWIDE)) {
-               if (stat & INT_SYSERROR) {
-                       ERROR(dev, "system error\n");
-                       stop_activity(dev);
-                       stat = 0;
-                       handled = 1;
-                       // FIXME have a neater way to prevent re-enumeration
-                       dev->driver = NULL;
-                       goto done;
-               }
-               if (stat & INT_PWRDETECT) {
-                       writel(~stat, &regs->int_status);
-                       if (readl(&dev->regs->power_detect) & PW_DETECT) {
-                               VDBG(dev, "connect\n");
-                               ep0_start(dev);
-                       } else {
-                               DBG(dev, "disconnect\n");
-                               if (dev->gadget.speed == USB_SPEED_FULL)
-                                       stop_activity(dev);
-                               dev->ep0state = EP0_DISCONNECT;
-                               dev->int_enable = INT_DEVWIDE;
-                               writel(dev->int_enable, &dev->regs->int_enable);
-                       }
-                       stat = 0;
-                       handled = 1;
-                       goto done;
-               }
-               if (stat & INT_SUSPEND) {
-                       ACK(INT_SUSPEND);
-                       if (readl(&regs->ep_status[0]) & EPxSTATUS_SUSPEND) {
-                               switch (dev->ep0state) {
-                               case EP0_DISCONNECT:
-                               case EP0_SUSPEND:
-                                       goto pm_next;
-                               default:
-                                       break;
-                               }
-                               DBG(dev, "USB suspend\n");
-                               dev->ep0state = EP0_SUSPEND;
-                               if (dev->gadget.speed != USB_SPEED_UNKNOWN
-                                               && dev->driver
-                                               && dev->driver->suspend) {
-                                       spin_unlock(&dev->lock);
-                                       dev->driver->suspend(&dev->gadget);
-                                       spin_lock(&dev->lock);
-                               }
-                       } else {
-                               if (dev->ep0state != EP0_SUSPEND) {
-                                       DBG(dev, "bogus USB resume %d\n",
-                                               dev->ep0state);
-                                       goto pm_next;
-                               }
-                               DBG(dev, "USB resume\n");
-                               dev->ep0state = EP0_IDLE;
-                               if (dev->gadget.speed != USB_SPEED_UNKNOWN
-                                               && dev->driver
-                                               && dev->driver->resume) {
-                                       spin_unlock(&dev->lock);
-                                       dev->driver->resume(&dev->gadget);
-                                       spin_lock(&dev->lock);
-                               }
-                       }
-               }
-pm_next:
-               if (stat & INT_USBRESET) {              /* hub reset done */
-                       ACK(INT_USBRESET);
-                       INFO(dev, "USB reset done, gadget %s\n",
-                               dev->driver->driver.name);
-               }
-               // and INT_ERR on some endpoint's crc/bitstuff/... problem
-       }
-
-       /* progress ep0 setup, data, or status stages.
-        * no transition {EP0_STATUS, EP0_STALL} --> EP0_IDLE; saves irqs
-        */
-       if (stat & INT_SETUP) {
-               ACK(INT_SETUP);
-               dev->ep[0].irqs++;
-               ep0_setup(dev);
-       }
-        if (stat & INT_STATUSNAK) {
-               ACK(INT_STATUSNAK|INT_ENDPOINT0);
-               if (dev->ep0state == EP0_IN) {
-                       ep = &dev->ep[0];
-                       ep->irqs++;
-                       nuke(ep, 0);
-                       writel(~(1<<0), &regs->EOP);
-                       dev->ep0state = EP0_STATUS;
-               }
-       }
-        if (stat & INT_ENDPOINT0) {
-               ACK(INT_ENDPOINT0);
-               ep = &dev->ep[0];
-               ep->irqs++;
-               pio_advance(ep);
-        }
-
-       /* dma completion */
-        if (stat & INT_MSTRDEND) {     /* IN */
-               ACK(INT_MSTRDEND);
-               ep = &dev->ep[UDC_MSTRD_ENDPOINT];
-               ep->irqs++;
-               dma_advance(dev, ep);
-        }
-        if (stat & INT_MSTWREND) {     /* OUT */
-               ACK(INT_MSTWREND);
-               ep = &dev->ep[UDC_MSTWR_ENDPOINT];
-               ep->irqs++;
-               dma_advance(dev, ep);
-        }
-        if (stat & INT_MSTWRTMOUT) {   /* OUT */
-               ACK(INT_MSTWRTMOUT);
-               ep = &dev->ep[UDC_MSTWR_ENDPOINT];
-               ep->irqs++;
-               ERROR(dev, "%s write timeout ?\n", ep->ep.name);
-               // reset dma? then dma_advance()
-        }
-
-       /* pio */
-       for (i = 1; i < 4; i++) {
-               u32             tmp = INT_EPxDATASET(i);
-
-               if (!(stat & tmp))
-                       continue;
-               ep = &dev->ep[i];
-               pio_advance(ep);
-               if (list_empty (&ep->queue))
-                       pio_irq_disable(dev, regs, i);
-               stat &= ~tmp;
-               handled = 1;
-               ep->irqs++;
-       }
-
-       if (rescans--)
-               goto rescan;
-
-done:
-       (void)readl(&regs->int_enable);
-       spin_unlock(&dev->lock);
-       if (stat)
-               DBG(dev, "unhandled irq status: %05x (%05x, %05x)\n", stat,
-                               readl(&regs->int_status), dev->int_enable);
-       return IRQ_RETVAL(handled);
-}
-
-#undef ACK
-
-/*-------------------------------------------------------------------------*/
-
-static void gadget_release(struct device *_dev)
-{
-       struct goku_udc *dev = dev_get_drvdata(_dev);
-
-       kfree(dev);
-}
-
-/* tear down the binding between this driver and the pci device */
-
-static void goku_remove(struct pci_dev *pdev)
-{
-       struct goku_udc         *dev = pci_get_drvdata(pdev);
-
-       DBG(dev, "%s\n", __func__);
-
-       usb_del_gadget_udc(&dev->gadget);
-
-       BUG_ON(dev->driver);
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-       remove_proc_entry(proc_node_name, NULL);
-#endif
-       if (dev->regs)
-               udc_reset(dev);
-       if (dev->got_irq)
-               free_irq(pdev->irq, dev);
-       if (dev->regs)
-               iounmap(dev->regs);
-       if (dev->got_region)
-               release_mem_region(pci_resource_start (pdev, 0),
-                               pci_resource_len (pdev, 0));
-       if (dev->enabled)
-               pci_disable_device(pdev);
-
-       dev->regs = NULL;
-
-       INFO(dev, "unbind\n");
-}
-
-/* wrap this driver around the specified pci device, but
- * don't respond over USB until a gadget driver binds to us.
- */
-
-static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-       struct goku_udc         *dev = NULL;
-       unsigned long           resource, len;
-       void __iomem            *base = NULL;
-       int                     retval;
-
-       if (!pdev->irq) {
-               printk(KERN_ERR "Check PCI %s IRQ setup!\n", pci_name(pdev));
-               retval = -ENODEV;
-               goto err;
-       }
-
-       /* alloc, and start init */
-       dev = kzalloc (sizeof *dev, GFP_KERNEL);
-       if (dev == NULL){
-               pr_debug("enomem %s\n", pci_name(pdev));
-               retval = -ENOMEM;
-               goto err;
-       }
-
-       spin_lock_init(&dev->lock);
-       dev->pdev = pdev;
-       dev->gadget.ops = &goku_ops;
-       dev->gadget.max_speed = USB_SPEED_FULL;
-
-       /* the "gadget" abstracts/virtualizes the controller */
-       dev->gadget.name = driver_name;
-
-       /* now all the pci goodies ... */
-       retval = pci_enable_device(pdev);
-       if (retval < 0) {
-               DBG(dev, "can't enable, %d\n", retval);
-               goto err;
-       }
-       dev->enabled = 1;
-
-       resource = pci_resource_start(pdev, 0);
-       len = pci_resource_len(pdev, 0);
-       if (!request_mem_region(resource, len, driver_name)) {
-               DBG(dev, "controller already in use\n");
-               retval = -EBUSY;
-               goto err;
-       }
-       dev->got_region = 1;
-
-       base = ioremap_nocache(resource, len);
-       if (base == NULL) {
-               DBG(dev, "can't map memory\n");
-               retval = -EFAULT;
-               goto err;
-       }
-       dev->regs = (struct goku_udc_regs __iomem *) base;
-
-       pci_set_drvdata(pdev, dev);
-       INFO(dev, "%s\n", driver_desc);
-       INFO(dev, "version: " DRIVER_VERSION " %s\n", dmastr());
-       INFO(dev, "irq %d, pci mem %p\n", pdev->irq, base);
-
-       /* init to known state, then setup irqs */
-       udc_reset(dev);
-       udc_reinit (dev);
-       if (request_irq(pdev->irq, goku_irq, IRQF_SHARED,
-                       driver_name, dev) != 0) {
-               DBG(dev, "request interrupt %d failed\n", pdev->irq);
-               retval = -EBUSY;
-               goto err;
-       }
-       dev->got_irq = 1;
-       if (use_dma)
-               pci_set_master(pdev);
-
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-       proc_create_data(proc_node_name, 0, NULL, &udc_proc_fops, dev);
-#endif
-
-       retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
-                       gadget_release);
-       if (retval)
-               goto err;
-
-       return 0;
-
-err:
-       if (dev)
-               goku_remove (pdev);
-       return retval;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static const struct pci_device_id pci_ids[] = { {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-       .class_mask =   ~0,
-       .vendor =       0x102f,         /* Toshiba */
-       .device =       0x0107,         /* this UDC */
-       .subvendor =    PCI_ANY_ID,
-       .subdevice =    PCI_ANY_ID,
-
-}, { /* end: all zeroes */ }
-};
-MODULE_DEVICE_TABLE (pci, pci_ids);
-
-static struct pci_driver goku_pci_driver = {
-       .name =         (char *) driver_name,
-       .id_table =     pci_ids,
-
-       .probe =        goku_probe,
-       .remove =       goku_remove,
-
-       /* FIXME add power management support */
-};
-
-module_pci_driver(goku_pci_driver);
diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h
deleted file mode 100644 (file)
index 86d2ada..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Toshiba TC86C001 ("Goku-S") USB Device Controller driver
- *
- * Copyright (C) 2000-2002 Lineo
- *      by Stuart Lynne, Tom Rushworth, and Bruce Balden
- * Copyright (C) 2002 Toshiba Corporation
- * Copyright (C) 2003 MontaVista Software (source@mvista.com)
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-/*
- * PCI BAR 0 points to these registers.
- */
-struct goku_udc_regs {
-       /* irq management */
-       u32     int_status;             /* 0x000 */
-       u32     int_enable;
-#define INT_SUSPEND            0x00001         /* or resume */
-#define INT_USBRESET           0x00002
-#define INT_ENDPOINT0          0x00004
-#define INT_SETUP              0x00008
-#define INT_STATUS             0x00010
-#define INT_STATUSNAK          0x00020
-#define INT_EPxDATASET(n)      (0x00020 << (n))        /* 0 < n < 4 */
-#      define INT_EP1DATASET           0x00040
-#      define INT_EP2DATASET           0x00080
-#      define INT_EP3DATASET           0x00100
-#define INT_EPnNAK(n)          (0x00100 < (n))         /* 0 < n < 4 */
-#      define INT_EP1NAK               0x00200
-#      define INT_EP2NAK               0x00400
-#      define INT_EP3NAK               0x00800
-#define INT_SOF                        0x01000
-#define INT_ERR                        0x02000
-#define INT_MSTWRSET           0x04000
-#define INT_MSTWREND           0x08000
-#define INT_MSTWRTMOUT         0x10000
-#define INT_MSTRDEND           0x20000
-#define INT_SYSERROR           0x40000
-#define INT_PWRDETECT          0x80000
-
-#define        INT_DEVWIDE \
-       (INT_PWRDETECT|INT_SYSERROR/*|INT_ERR*/|INT_USBRESET|INT_SUSPEND)
-#define        INT_EP0 \
-       (INT_SETUP|INT_ENDPOINT0/*|INT_STATUS*/|INT_STATUSNAK)
-
-       u32     dma_master;
-#define MST_EOPB_DIS           0x0800
-#define MST_EOPB_ENA           0x0400
-#define MST_TIMEOUT_DIS                0x0200
-#define MST_TIMEOUT_ENA                0x0100
-#define MST_RD_EOPB            0x0080          /* write-only */
-#define MST_RD_RESET           0x0040
-#define MST_WR_RESET           0x0020
-#define MST_RD_ENA             0x0004          /* 1:start, 0:ignore */
-#define MST_WR_ENA             0x0002          /* 1:start, 0:ignore */
-#define MST_CONNECTION         0x0001          /* 0 for ep1out/ep2in */
-
-#define MST_R_BITS             (MST_EOPB_DIS|MST_EOPB_ENA \
-                                       |MST_RD_ENA|MST_RD_RESET)
-#define MST_W_BITS             (MST_TIMEOUT_DIS|MST_TIMEOUT_ENA \
-                                       |MST_WR_ENA|MST_WR_RESET)
-#define MST_RW_BITS            (MST_R_BITS|MST_W_BITS \
-                                       |MST_CONNECTION)
-
-/* these values assume (dma_master & MST_CONNECTION) == 0 */
-#define UDC_MSTWR_ENDPOINT        1
-#define UDC_MSTRD_ENDPOINT        2
-
-       /* dma master write */
-       u32     out_dma_start;
-       u32     out_dma_end;
-       u32     out_dma_current;
-
-       /* dma master read */
-       u32     in_dma_start;
-       u32     in_dma_end;
-       u32     in_dma_current;
-
-       u32     power_detect;
-#define PW_DETECT              0x04
-#define PW_RESETB              0x02
-#define PW_PULLUP              0x01
-
-       u8      _reserved0 [0x1d8];
-
-       /* endpoint registers */
-       u32     ep_fifo [4];            /* 0x200 */
-       u8      _reserved1 [0x10];
-       u32     ep_mode [4];            /* only 1-3 valid */
-       u8      _reserved2 [0x10];
-
-       u32     ep_status [4];
-#define EPxSTATUS_TOGGLE       0x40
-#define EPxSTATUS_SUSPEND      0x20
-#define EPxSTATUS_EP_MASK      (0x07<<2)
-#      define EPxSTATUS_EP_READY       (0<<2)
-#      define EPxSTATUS_EP_DATAIN      (1<<2)
-#      define EPxSTATUS_EP_FULL        (2<<2)
-#      define EPxSTATUS_EP_TX_ERR      (3<<2)
-#      define EPxSTATUS_EP_RX_ERR      (4<<2)
-#      define EPxSTATUS_EP_BUSY        (5<<2)
-#      define EPxSTATUS_EP_STALL       (6<<2)
-#      define EPxSTATUS_EP_INVALID     (7<<2)
-#define EPxSTATUS_FIFO_DISABLE 0x02
-#define EPxSTATUS_STAGE_ERROR  0x01
-
-       u8      _reserved3 [0x10];
-       u32     EPxSizeLA[4];
-#define PACKET_ACTIVE          (1<<7)
-#define DATASIZE               0x7f
-       u8      _reserved3a [0x10];
-       u32     EPxSizeLB[4];           /* only 1,2 valid */
-       u8      _reserved3b [0x10];
-       u32     EPxSizeHA[4];           /* only 1-3 valid */
-       u8      _reserved3c [0x10];
-       u32     EPxSizeHB[4];           /* only 1,2 valid */
-       u8      _reserved4[0x30];
-
-       /* SETUP packet contents */
-       u32     bRequestType;           /* 0x300 */
-       u32     bRequest;
-       u32     wValueL;
-       u32     wValueH;
-       u32     wIndexL;
-       u32     wIndexH;
-       u32     wLengthL;
-       u32     wLengthH;
-
-       /* command interaction/handshaking */
-       u32     SetupRecv;              /* 0x320 */
-       u32     CurrConfig;
-       u32     StdRequest;
-       u32     Request;
-       u32     DataSet;
-#define DATASET_A(epnum)       (1<<(2*(epnum)))
-#define DATASET_B(epnum)       (2<<(2*(epnum)))
-#define DATASET_AB(epnum)      (3<<(2*(epnum)))
-       u8      _reserved5[4];
-
-       u32     UsbState;
-#define USBSTATE_CONFIGURED    0x04
-#define USBSTATE_ADDRESSED     0x02
-#define USBSTATE_DEFAULT       0x01
-
-       u32     EOP;
-
-       u32     Command;                /* 0x340 */
-#define COMMAND_SETDATA0       2
-#define COMMAND_RESET          3
-#define COMMAND_STALL          4
-#define COMMAND_INVALID                5
-#define COMMAND_FIFO_DISABLE   7
-#define COMMAND_FIFO_ENABLE    8
-#define COMMAND_INIT_DESCRIPTOR        9
-#define COMMAND_FIFO_CLEAR     10      /* also stall */
-#define COMMAND_STALL_CLEAR    11
-#define COMMAND_EP(n)          ((n) << 4)
-
-       u32     EPxSingle;
-       u8      _reserved6[4];
-       u32     EPxBCS;
-       u8      _reserved7[8];
-       u32     IntControl;
-#define ICONTROL_STATUSNAK     1
-       u8      _reserved8[4];
-
-       u32     reqmode;        // 0x360 standard request mode, low 8 bits
-#define G_REQMODE_SET_INTF     (1<<7)
-#define G_REQMODE_GET_INTF     (1<<6)
-#define G_REQMODE_SET_CONF     (1<<5)
-#define G_REQMODE_GET_CONF     (1<<4)
-#define G_REQMODE_GET_DESC     (1<<3)
-#define G_REQMODE_SET_FEAT     (1<<2)
-#define G_REQMODE_CLEAR_FEAT   (1<<1)
-#define G_REQMODE_GET_STATUS   (1<<0)
-
-       u32     ReqMode;
-       u8      _reserved9[0x18];
-       u32     PortStatus;             /* 0x380 */
-       u8      _reserved10[8];
-       u32     address;
-       u32     buff_test;
-       u8      _reserved11[4];
-       u32     UsbReady;
-       u8      _reserved12[4];
-       u32     SetDescStall;           /* 0x3a0 */
-       u8      _reserved13[0x45c];
-
-       /* hardware could handle limited GET_DESCRIPTOR duties */
-#define        DESC_LEN        0x80
-       u32     descriptors[DESC_LEN];  /* 0x800 */
-       u8      _reserved14[0x600];
-
-} __attribute__ ((packed));
-
-#define        MAX_FIFO_SIZE   64
-#define        MAX_EP0_SIZE    8               /* ep0 fifo is bigger, though */
-
-
-/*-------------------------------------------------------------------------*/
-
-/* DRIVER DATA STRUCTURES and UTILITIES */
-
-struct goku_ep {
-       struct usb_ep                           ep;
-       struct goku_udc                         *dev;
-       unsigned long                           irqs;
-
-       unsigned                                num:8,
-                                               dma:1,
-                                               is_in:1,
-                                               stopped:1;
-
-       /* analogous to a host-side qh */
-       struct list_head                        queue;
-
-       u32 __iomem                             *reg_fifo;
-       u32 __iomem                             *reg_mode;
-       u32 __iomem                             *reg_status;
-};
-
-struct goku_request {
-       struct usb_request              req;
-       struct list_head                queue;
-
-       unsigned                        mapped:1;
-};
-
-enum ep0state {
-       EP0_DISCONNECT,         /* no host */
-       EP0_IDLE,               /* between STATUS ack and SETUP report */
-       EP0_IN, EP0_OUT,        /* data stage */
-       EP0_STATUS,             /* status stage */
-       EP0_STALL,              /* data or status stages */
-       EP0_SUSPEND,            /* usb suspend */
-};
-
-struct goku_udc {
-       /* each pci device provides one gadget, several endpoints */
-       struct usb_gadget               gadget;
-       spinlock_t                      lock;
-       struct goku_ep                  ep[4];
-       struct usb_gadget_driver        *driver;
-
-       enum ep0state                   ep0state;
-       unsigned                        got_irq:1,
-                                       got_region:1,
-                                       req_config:1,
-                                       configured:1,
-                                       enabled:1;
-
-       /* pci state used to access those endpoints */
-       struct pci_dev                  *pdev;
-       struct goku_udc_regs __iomem    *regs;
-       u32                             int_enable;
-
-       /* statistics... */
-       unsigned long                   irqs;
-};
-#define to_goku_udc(g)         (container_of((g), struct goku_udc, gadget))
-
-/*-------------------------------------------------------------------------*/
-
-#define xprintk(dev,level,fmt,args...) \
-       printk(level "%s %s: " fmt , driver_name , \
-                       pci_name(dev->pdev) , ## args)
-
-#ifdef DEBUG
-#define DBG(dev,fmt,args...) \
-       xprintk(dev , KERN_DEBUG , fmt , ## args)
-#else
-#define DBG(dev,fmt,args...) \
-       do { } while (0)
-#endif /* DEBUG */
-
-#ifdef VERBOSE
-#define VDBG DBG
-#else
-#define VDBG(dev,fmt,args...) \
-       do { } while (0)
-#endif /* VERBOSE */
-
-#define ERROR(dev,fmt,args...) \
-       xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARNING(dev,fmt,args...) \
-       xprintk(dev , KERN_WARNING , fmt , ## args)
-#define INFO(dev,fmt,args...) \
-       xprintk(dev , KERN_INFO , fmt , ## args)
-
diff --git a/drivers/usb/gadget/gr_udc.c b/drivers/usb/gadget/gr_udc.c
deleted file mode 100644 (file)
index 5d93f2b..0000000
+++ /dev/null
@@ -1,2235 +0,0 @@
-/*
- * USB Peripheral Controller driver for Aeroflex Gaisler GRUSBDC.
- *
- * 2013 (c) Aeroflex Gaisler AB
- *
- * This driver supports GRUSBDC USB Device Controller cores available in the
- * GRLIB VHDL IP core library.
- *
- * Full documentation of the GRUSBDC core can be found here:
- * http://www.gaisler.com/products/grlib/grip.pdf
- *
- * 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.
- *
- * Contributors:
- * - Andreas Larsson <andreas@gaisler.com>
- * - Marko Isomaki
- */
-
-/*
- * A GRUSBDC core can have up to 16 IN endpoints and 16 OUT endpoints each
- * individually configurable to any of the four USB transfer types. This driver
- * only supports cores in DMA mode.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/of_platform.h>
-#include <linux/of_irq.h>
-#include <linux/of_address.h>
-
-#include <asm/byteorder.h>
-
-#include "gr_udc.h"
-
-#define        DRIVER_NAME     "gr_udc"
-#define        DRIVER_DESC     "Aeroflex Gaisler GRUSBDC USB Peripheral Controller"
-
-static const char driver_name[] = DRIVER_NAME;
-static const char driver_desc[] = DRIVER_DESC;
-
-#define gr_read32(x) (ioread32be((x)))
-#define gr_write32(x, v) (iowrite32be((v), (x)))
-
-/* USB speed and corresponding string calculated from status register value */
-#define GR_SPEED(status) \
-       ((status & GR_STATUS_SP) ? USB_SPEED_FULL : USB_SPEED_HIGH)
-#define GR_SPEED_STR(status) usb_speed_string(GR_SPEED(status))
-
-/* Size of hardware buffer calculated from epctrl register value */
-#define GR_BUFFER_SIZE(epctrl)                                       \
-       ((((epctrl) & GR_EPCTRL_BUFSZ_MASK) >> GR_EPCTRL_BUFSZ_POS) * \
-        GR_EPCTRL_BUFSZ_SCALER)
-
-/* ---------------------------------------------------------------------- */
-/* Debug printout functionality */
-
-static const char * const gr_modestring[] = {"control", "iso", "bulk", "int"};
-
-static const char *gr_ep0state_string(enum gr_ep0state state)
-{
-       static const char *const names[] = {
-               [GR_EP0_DISCONNECT] = "disconnect",
-               [GR_EP0_SETUP] = "setup",
-               [GR_EP0_IDATA] = "idata",
-               [GR_EP0_ODATA] = "odata",
-               [GR_EP0_ISTATUS] = "istatus",
-               [GR_EP0_OSTATUS] = "ostatus",
-               [GR_EP0_STALL] = "stall",
-               [GR_EP0_SUSPEND] = "suspend",
-       };
-
-       if (state < 0 || state >= ARRAY_SIZE(names))
-               return "UNKNOWN";
-
-       return names[state];
-}
-
-#ifdef VERBOSE_DEBUG
-
-static void gr_dbgprint_request(const char *str, struct gr_ep *ep,
-                               struct gr_request *req)
-{
-       int buflen = ep->is_in ? req->req.length : req->req.actual;
-       int rowlen = 32;
-       int plen = min(rowlen, buflen);
-
-       dev_dbg(ep->dev->dev, "%s: 0x%p, %d bytes data%s:\n", str, req, buflen,
-               (buflen > plen ? " (truncated)" : ""));
-       print_hex_dump_debug("   ", DUMP_PREFIX_NONE,
-                            rowlen, 4, req->req.buf, plen, false);
-}
-
-static void gr_dbgprint_devreq(struct gr_udc *dev, u8 type, u8 request,
-                              u16 value, u16 index, u16 length)
-{
-       dev_vdbg(dev->dev, "REQ: %02x.%02x v%04x i%04x l%04x\n",
-                type, request, value, index, length);
-}
-#else /* !VERBOSE_DEBUG */
-
-static void gr_dbgprint_request(const char *str, struct gr_ep *ep,
-                               struct gr_request *req) {}
-
-static void gr_dbgprint_devreq(struct gr_udc *dev, u8 type, u8 request,
-                              u16 value, u16 index, u16 length) {}
-
-#endif /* VERBOSE_DEBUG */
-
-/* ---------------------------------------------------------------------- */
-/* Debugfs functionality */
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FS
-
-static void gr_seq_ep_show(struct seq_file *seq, struct gr_ep *ep)
-{
-       u32 epctrl = gr_read32(&ep->regs->epctrl);
-       u32 epstat = gr_read32(&ep->regs->epstat);
-       int mode = (epctrl & GR_EPCTRL_TT_MASK) >> GR_EPCTRL_TT_POS;
-       struct gr_request *req;
-
-       seq_printf(seq, "%s:\n", ep->ep.name);
-       seq_printf(seq, "  mode = %s\n", gr_modestring[mode]);
-       seq_printf(seq, "  halted: %d\n", !!(epctrl & GR_EPCTRL_EH));
-       seq_printf(seq, "  disabled: %d\n", !!(epctrl & GR_EPCTRL_ED));
-       seq_printf(seq, "  valid: %d\n", !!(epctrl & GR_EPCTRL_EV));
-       seq_printf(seq, "  dma_start = %d\n", ep->dma_start);
-       seq_printf(seq, "  stopped = %d\n", ep->stopped);
-       seq_printf(seq, "  wedged = %d\n", ep->wedged);
-       seq_printf(seq, "  callback = %d\n", ep->callback);
-       seq_printf(seq, "  maxpacket = %d\n", ep->ep.maxpacket);
-       seq_printf(seq, "  maxpacket_limit = %d\n", ep->ep.maxpacket_limit);
-       seq_printf(seq, "  bytes_per_buffer = %d\n", ep->bytes_per_buffer);
-       if (mode == 1 || mode == 3)
-               seq_printf(seq, "  nt = %d\n",
-                          (epctrl & GR_EPCTRL_NT_MASK) >> GR_EPCTRL_NT_POS);
-
-       seq_printf(seq, "  Buffer 0: %s %s%d\n",
-                  epstat & GR_EPSTAT_B0 ? "valid" : "invalid",
-                  epstat & GR_EPSTAT_BS ? " " : "selected ",
-                  (epstat & GR_EPSTAT_B0CNT_MASK) >> GR_EPSTAT_B0CNT_POS);
-       seq_printf(seq, "  Buffer 1: %s %s%d\n",
-                  epstat & GR_EPSTAT_B1 ? "valid" : "invalid",
-                  epstat & GR_EPSTAT_BS ? "selected " : " ",
-                  (epstat & GR_EPSTAT_B1CNT_MASK) >> GR_EPSTAT_B1CNT_POS);
-
-       if (list_empty(&ep->queue)) {
-               seq_puts(seq, "  Queue: empty\n\n");
-               return;
-       }
-
-       seq_puts(seq, "  Queue:\n");
-       list_for_each_entry(req, &ep->queue, queue) {
-               struct gr_dma_desc *desc;
-               struct gr_dma_desc *next;
-
-               seq_printf(seq, "    0x%p: 0x%p %d %d\n", req,
-                          &req->req.buf, req->req.actual, req->req.length);
-
-               next = req->first_desc;
-               do {
-                       desc = next;
-                       next = desc->next_desc;
-                       seq_printf(seq, "    %c 0x%p (0x%08x): 0x%05x 0x%08x\n",
-                                  desc == req->curr_desc ? 'c' : ' ',
-                                  desc, desc->paddr, desc->ctrl, desc->data);
-               } while (desc != req->last_desc);
-       }
-       seq_puts(seq, "\n");
-}
-
-
-static int gr_seq_show(struct seq_file *seq, void *v)
-{
-       struct gr_udc *dev = seq->private;
-       u32 control = gr_read32(&dev->regs->control);
-       u32 status = gr_read32(&dev->regs->status);
-       struct gr_ep *ep;
-
-       seq_printf(seq, "usb state = %s\n",
-                  usb_state_string(dev->gadget.state));
-       seq_printf(seq, "address = %d\n",
-                  (control & GR_CONTROL_UA_MASK) >> GR_CONTROL_UA_POS);
-       seq_printf(seq, "speed = %s\n", GR_SPEED_STR(status));
-       seq_printf(seq, "ep0state = %s\n", gr_ep0state_string(dev->ep0state));
-       seq_printf(seq, "irq_enabled = %d\n", dev->irq_enabled);
-       seq_printf(seq, "remote_wakeup = %d\n", dev->remote_wakeup);
-       seq_printf(seq, "test_mode = %d\n", dev->test_mode);
-       seq_puts(seq, "\n");
-
-       list_for_each_entry(ep, &dev->ep_list, ep_list)
-               gr_seq_ep_show(seq, ep);
-
-       return 0;
-}
-
-static int gr_dfs_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, gr_seq_show, inode->i_private);
-}
-
-static const struct file_operations gr_dfs_fops = {
-       .owner          = THIS_MODULE,
-       .open           = gr_dfs_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static void gr_dfs_create(struct gr_udc *dev)
-{
-       const char *name = "gr_udc_state";
-
-       dev->dfs_root = debugfs_create_dir(dev_name(dev->dev), NULL);
-       dev->dfs_state = debugfs_create_file(name, 0444, dev->dfs_root, dev,
-                                            &gr_dfs_fops);
-}
-
-static void gr_dfs_delete(struct gr_udc *dev)
-{
-       /* Handles NULL and ERR pointers internally */
-       debugfs_remove(dev->dfs_state);
-       debugfs_remove(dev->dfs_root);
-}
-
-#else /* !CONFIG_USB_GADGET_DEBUG_FS */
-
-static void gr_dfs_create(struct gr_udc *dev) {}
-static void gr_dfs_delete(struct gr_udc *dev) {}
-
-#endif /* CONFIG_USB_GADGET_DEBUG_FS */
-
-/* ---------------------------------------------------------------------- */
-/* DMA and request handling */
-
-/* Allocates a new struct gr_dma_desc, sets paddr and zeroes the rest */
-static struct gr_dma_desc *gr_alloc_dma_desc(struct gr_ep *ep, gfp_t gfp_flags)
-{
-       dma_addr_t paddr;
-       struct gr_dma_desc *dma_desc;
-
-       dma_desc = dma_pool_alloc(ep->dev->desc_pool, gfp_flags, &paddr);
-       if (!dma_desc) {
-               dev_err(ep->dev->dev, "Could not allocate from DMA pool\n");
-               return NULL;
-       }
-
-       memset(dma_desc, 0, sizeof(*dma_desc));
-       dma_desc->paddr = paddr;
-
-       return dma_desc;
-}
-
-static inline void gr_free_dma_desc(struct gr_udc *dev,
-                                   struct gr_dma_desc *desc)
-{
-       dma_pool_free(dev->desc_pool, desc, (dma_addr_t)desc->paddr);
-}
-
-/* Frees the chain of struct gr_dma_desc for the given request */
-static void gr_free_dma_desc_chain(struct gr_udc *dev, struct gr_request *req)
-{
-       struct gr_dma_desc *desc;
-       struct gr_dma_desc *next;
-
-       next = req->first_desc;
-       if (!next)
-               return;
-
-       do {
-               desc = next;
-               next = desc->next_desc;
-               gr_free_dma_desc(dev, desc);
-       } while (desc != req->last_desc);
-
-       req->first_desc = NULL;
-       req->curr_desc = NULL;
-       req->last_desc = NULL;
-}
-
-static void gr_ep0_setup(struct gr_udc *dev, struct gr_request *req);
-
-/*
- * Frees allocated resources and calls the appropriate completion function/setup
- * package handler for a finished request.
- *
- * Must be called with dev->lock held and irqs disabled.
- */
-static void gr_finish_request(struct gr_ep *ep, struct gr_request *req,
-                             int status)
-       __releases(&dev->lock)
-       __acquires(&dev->lock)
-{
-       struct gr_udc *dev;
-
-       list_del_init(&req->queue);
-
-       if (likely(req->req.status == -EINPROGRESS))
-               req->req.status = status;
-       else
-               status = req->req.status;
-
-       dev = ep->dev;
-       usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
-       gr_free_dma_desc_chain(dev, req);
-
-       if (ep->is_in) /* For OUT, actual gets updated bit by bit */
-               req->req.actual = req->req.length;
-
-       if (!status) {
-               if (ep->is_in)
-                       gr_dbgprint_request("SENT", ep, req);
-               else
-                       gr_dbgprint_request("RECV", ep, req);
-       }
-
-       /* Prevent changes to ep->queue during callback */
-       ep->callback = 1;
-       if (req == dev->ep0reqo && !status) {
-               if (req->setup)
-                       gr_ep0_setup(dev, req);
-               else
-                       dev_err(dev->dev,
-                               "Unexpected non setup packet on ep0in\n");
-       } else if (req->req.complete) {
-               spin_unlock(&dev->lock);
-
-               req->req.complete(&ep->ep, &req->req);
-
-               spin_lock(&dev->lock);
-       }
-       ep->callback = 0;
-}
-
-static struct usb_request *gr_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
-{
-       struct gr_request *req;
-
-       req = kzalloc(sizeof(*req), gfp_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD(&req->queue);
-
-       return &req->req;
-}
-
-/*
- * Starts DMA for endpoint ep if there are requests in the queue.
- *
- * Must be called with dev->lock held and with !ep->stopped.
- */
-static void gr_start_dma(struct gr_ep *ep)
-{
-       struct gr_request *req;
-       u32 dmactrl;
-
-       if (list_empty(&ep->queue)) {
-               ep->dma_start = 0;
-               return;
-       }
-
-       req = list_first_entry(&ep->queue, struct gr_request, queue);
-
-       /* A descriptor should already have been allocated */
-       BUG_ON(!req->curr_desc);
-
-       wmb(); /* Make sure all is settled before handing it over to DMA */
-
-       /* Set the descriptor pointer in the hardware */
-       gr_write32(&ep->regs->dmaaddr, req->curr_desc->paddr);
-
-       /* Announce available descriptors */
-       dmactrl = gr_read32(&ep->regs->dmactrl);
-       gr_write32(&ep->regs->dmactrl, dmactrl | GR_DMACTRL_DA);
-
-       ep->dma_start = 1;
-}
-
-/*
- * Finishes the first request in the ep's queue and, if available, starts the
- * next request in queue.
- *
- * Must be called with dev->lock held, irqs disabled and with !ep->stopped.
- */
-static void gr_dma_advance(struct gr_ep *ep, int status)
-{
-       struct gr_request *req;
-
-       req = list_first_entry(&ep->queue, struct gr_request, queue);
-       gr_finish_request(ep, req, status);
-       gr_start_dma(ep); /* Regardless of ep->dma_start */
-}
-
-/*
- * Abort DMA for an endpoint. Sets the abort DMA bit which causes an ongoing DMA
- * transfer to be canceled and clears GR_DMACTRL_DA.
- *
- * Must be called with dev->lock held.
- */
-static void gr_abort_dma(struct gr_ep *ep)
-{
-       u32 dmactrl;
-
-       dmactrl = gr_read32(&ep->regs->dmactrl);
-       gr_write32(&ep->regs->dmactrl, dmactrl | GR_DMACTRL_AD);
-}
-
-/*
- * Allocates and sets up a struct gr_dma_desc and putting it on the descriptor
- * chain.
- *
- * Size is not used for OUT endpoints. Hardware can not be instructed to handle
- * smaller buffer than MAXPL in the OUT direction.
- */
-static int gr_add_dma_desc(struct gr_ep *ep, struct gr_request *req,
-                          dma_addr_t data, unsigned size, gfp_t gfp_flags)
-{
-       struct gr_dma_desc *desc;
-
-       desc = gr_alloc_dma_desc(ep, gfp_flags);
-       if (!desc)
-               return -ENOMEM;
-
-       desc->data = data;
-       if (ep->is_in)
-               desc->ctrl =
-                       (GR_DESC_IN_CTRL_LEN_MASK & size) | GR_DESC_IN_CTRL_EN;
-       else
-               desc->ctrl = GR_DESC_OUT_CTRL_IE;
-
-       if (!req->first_desc) {
-               req->first_desc = desc;
-               req->curr_desc = desc;
-       } else {
-               req->last_desc->next_desc = desc;
-               req->last_desc->next = desc->paddr;
-               req->last_desc->ctrl |= GR_DESC_OUT_CTRL_NX;
-       }
-       req->last_desc = desc;
-
-       return 0;
-}
-
-/*
- * Sets up a chain of struct gr_dma_descriptors pointing to buffers that
- * together covers req->req.length bytes of the buffer at DMA address
- * req->req.dma for the OUT direction.
- *
- * The first descriptor in the chain is enabled, the rest disabled. The
- * interrupt handler will later enable them one by one when needed so we can
- * find out when the transfer is finished. For OUT endpoints, all descriptors
- * therefore generate interrutps.
- */
-static int gr_setup_out_desc_list(struct gr_ep *ep, struct gr_request *req,
-                                 gfp_t gfp_flags)
-{
-       u16 bytes_left; /* Bytes left to provide descriptors for */
-       u16 bytes_used; /* Bytes accommodated for */
-       int ret = 0;
-
-       req->first_desc = NULL; /* Signals that no allocation is done yet */
-       bytes_left = req->req.length;
-       bytes_used = 0;
-       while (bytes_left > 0) {
-               dma_addr_t start = req->req.dma + bytes_used;
-               u16 size = min(bytes_left, ep->bytes_per_buffer);
-
-               /* Should not happen however - gr_queue stops such lengths */
-               if (size < ep->bytes_per_buffer)
-                       dev_warn(ep->dev->dev,
-                                "Buffer overrun risk: %u < %u bytes/buffer\n",
-                                size, ep->bytes_per_buffer);
-
-               ret = gr_add_dma_desc(ep, req, start, size, gfp_flags);
-               if (ret)
-                       goto alloc_err;
-
-               bytes_left -= size;
-               bytes_used += size;
-       }
-
-       req->first_desc->ctrl |= GR_DESC_OUT_CTRL_EN;
-
-       return 0;
-
-alloc_err:
-       gr_free_dma_desc_chain(ep->dev, req);
-
-       return ret;
-}
-
-/*
- * Sets up a chain of struct gr_dma_descriptors pointing to buffers that
- * together covers req->req.length bytes of the buffer at DMA address
- * req->req.dma for the IN direction.
- *
- * When more data is provided than the maximum payload size, the hardware splits
- * this up into several payloads automatically. Moreover, ep->bytes_per_buffer
- * is always set to a multiple of the maximum payload (restricted to the valid
- * number of maximum payloads during high bandwidth isochronous or interrupt
- * transfers)
- *
- * All descriptors are enabled from the beginning and we only generate an
- * interrupt for the last one indicating that the entire request has been pushed
- * to hardware.
- */
-static int gr_setup_in_desc_list(struct gr_ep *ep, struct gr_request *req,
-                                gfp_t gfp_flags)
-{
-       u16 bytes_left; /* Bytes left in req to provide descriptors for */
-       u16 bytes_used; /* Bytes in req accommodated for */
-       int ret = 0;
-
-       req->first_desc = NULL; /* Signals that no allocation is done yet */
-       bytes_left = req->req.length;
-       bytes_used = 0;
-       do { /* Allow for zero length packets */
-               dma_addr_t start = req->req.dma + bytes_used;
-               u16 size = min(bytes_left, ep->bytes_per_buffer);
-
-               ret = gr_add_dma_desc(ep, req, start, size, gfp_flags);
-               if (ret)
-                       goto alloc_err;
-
-               bytes_left -= size;
-               bytes_used += size;
-       } while (bytes_left > 0);
-
-       /*
-        * Send an extra zero length packet to indicate that no more data is
-        * available when req->req.zero is set and the data length is even
-        * multiples of ep->ep.maxpacket.
-        */
-       if (req->req.zero && (req->req.length % ep->ep.maxpacket == 0)) {
-               ret = gr_add_dma_desc(ep, req, 0, 0, gfp_flags);
-               if (ret)
-                       goto alloc_err;
-       }
-
-       /*
-        * For IN packets we only want to know when the last packet has been
-        * transmitted (not just put into internal buffers).
-        */
-       req->last_desc->ctrl |= GR_DESC_IN_CTRL_PI;
-
-       return 0;
-
-alloc_err:
-       gr_free_dma_desc_chain(ep->dev, req);
-
-       return ret;
-}
-
-/* Must be called with dev->lock held */
-static int gr_queue(struct gr_ep *ep, struct gr_request *req, gfp_t gfp_flags)
-{
-       struct gr_udc *dev = ep->dev;
-       int ret;
-
-       if (unlikely(!ep->ep.desc && ep->num != 0)) {
-               dev_err(dev->dev, "No ep descriptor for %s\n", ep->ep.name);
-               return -EINVAL;
-       }
-
-       if (unlikely(!req->req.buf || !list_empty(&req->queue))) {
-               dev_err(dev->dev,
-                       "Invalid request for %s: buf=%p list_empty=%d\n",
-                       ep->ep.name, req->req.buf, list_empty(&req->queue));
-               return -EINVAL;
-       }
-
-       /*
-        * The DMA controller can not handle smaller OUT buffers than
-        * maxpacket. It could lead to buffer overruns if unexpectedly long
-        * packet are received.
-        */
-       if (!ep->is_in && (req->req.length % ep->ep.maxpacket) != 0) {
-               dev_err(dev->dev,
-                       "OUT request length %d is not multiple of maxpacket\n",
-                       req->req.length);
-               return -EMSGSIZE;
-       }
-
-       if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
-               dev_err(dev->dev, "-ESHUTDOWN");
-               return -ESHUTDOWN;
-       }
-
-       /* Can't touch registers when suspended */
-       if (dev->ep0state == GR_EP0_SUSPEND) {
-               dev_err(dev->dev, "-EBUSY");
-               return -EBUSY;
-       }
-
-       /* Set up DMA mapping in case the caller didn't */
-       ret = usb_gadget_map_request(&dev->gadget, &req->req, ep->is_in);
-       if (ret) {
-               dev_err(dev->dev, "usb_gadget_map_request");
-               return ret;
-       }
-
-       if (ep->is_in)
-               ret = gr_setup_in_desc_list(ep, req, gfp_flags);
-       else
-               ret = gr_setup_out_desc_list(ep, req, gfp_flags);
-       if (ret)
-               return ret;
-
-       req->req.status = -EINPROGRESS;
-       req->req.actual = 0;
-       list_add_tail(&req->queue, &ep->queue);
-
-       /* Start DMA if not started, otherwise interrupt handler handles it */
-       if (!ep->dma_start && likely(!ep->stopped))
-               gr_start_dma(ep);
-
-       return 0;
-}
-
-/*
- * Queue a request from within the driver.
- *
- * Must be called with dev->lock held.
- */
-static inline int gr_queue_int(struct gr_ep *ep, struct gr_request *req,
-                              gfp_t gfp_flags)
-{
-       if (ep->is_in)
-               gr_dbgprint_request("RESP", ep, req);
-
-       return gr_queue(ep, req, gfp_flags);
-}
-
-/* ---------------------------------------------------------------------- */
-/* General helper functions */
-
-/*
- * Dequeue ALL requests.
- *
- * Must be called with dev->lock held and irqs disabled.
- */
-static void gr_ep_nuke(struct gr_ep *ep)
-{
-       struct gr_request *req;
-
-       ep->stopped = 1;
-       ep->dma_start = 0;
-       gr_abort_dma(ep);
-
-       while (!list_empty(&ep->queue)) {
-               req = list_first_entry(&ep->queue, struct gr_request, queue);
-               gr_finish_request(ep, req, -ESHUTDOWN);
-       }
-}
-
-/*
- * Reset the hardware state of this endpoint.
- *
- * Must be called with dev->lock held.
- */
-static void gr_ep_reset(struct gr_ep *ep)
-{
-       gr_write32(&ep->regs->epctrl, 0);
-       gr_write32(&ep->regs->dmactrl, 0);
-
-       ep->ep.maxpacket = MAX_CTRL_PL_SIZE;
-       ep->ep.desc = NULL;
-       ep->stopped = 1;
-       ep->dma_start = 0;
-}
-
-/*
- * Generate STALL on ep0in/out.
- *
- * Must be called with dev->lock held.
- */
-static void gr_control_stall(struct gr_udc *dev)
-{
-       u32 epctrl;
-
-       epctrl = gr_read32(&dev->epo[0].regs->epctrl);
-       gr_write32(&dev->epo[0].regs->epctrl, epctrl | GR_EPCTRL_CS);
-       epctrl = gr_read32(&dev->epi[0].regs->epctrl);
-       gr_write32(&dev->epi[0].regs->epctrl, epctrl | GR_EPCTRL_CS);
-
-       dev->ep0state = GR_EP0_STALL;
-}
-
-/*
- * Halts, halts and wedges, or clears halt for an endpoint.
- *
- * Must be called with dev->lock held.
- */
-static int gr_ep_halt_wedge(struct gr_ep *ep, int halt, int wedge, int fromhost)
-{
-       u32 epctrl;
-       int retval = 0;
-
-       if (ep->num && !ep->ep.desc)
-               return -EINVAL;
-
-       if (ep->num && ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC)
-               return -EOPNOTSUPP;
-
-       /* Never actually halt ep0, and therefore never clear halt for ep0 */
-       if (!ep->num) {
-               if (halt && !fromhost) {
-                       /* ep0 halt from gadget - generate protocol stall */
-                       gr_control_stall(ep->dev);
-                       dev_dbg(ep->dev->dev, "EP: stall ep0\n");
-                       return 0;
-               }
-               return -EINVAL;
-       }
-
-       dev_dbg(ep->dev->dev, "EP: %s halt %s\n",
-               (halt ? (wedge ? "wedge" : "set") : "clear"), ep->ep.name);
-
-       epctrl = gr_read32(&ep->regs->epctrl);
-       if (halt) {
-               /* Set HALT */
-               gr_write32(&ep->regs->epctrl, epctrl | GR_EPCTRL_EH);
-               ep->stopped = 1;
-               if (wedge)
-                       ep->wedged = 1;
-       } else {
-               gr_write32(&ep->regs->epctrl, epctrl & ~GR_EPCTRL_EH);
-               ep->stopped = 0;
-               ep->wedged = 0;
-
-               /* Things might have been queued up in the meantime */
-               if (!ep->dma_start)
-                       gr_start_dma(ep);
-       }
-
-       return retval;
-}
-
-/* Must be called with dev->lock held */
-static inline void gr_set_ep0state(struct gr_udc *dev, enum gr_ep0state value)
-{
-       if (dev->ep0state != value)
-               dev_vdbg(dev->dev, "STATE:  ep0state=%s\n",
-                        gr_ep0state_string(value));
-       dev->ep0state = value;
-}
-
-/*
- * Should only be called when endpoints can not generate interrupts.
- *
- * Must be called with dev->lock held.
- */
-static void gr_disable_interrupts_and_pullup(struct gr_udc *dev)
-{
-       gr_write32(&dev->regs->control, 0);
-       wmb(); /* Make sure that we do not deny one of our interrupts */
-       dev->irq_enabled = 0;
-}
-
-/*
- * Stop all device activity and disable data line pullup.
- *
- * Must be called with dev->lock held and irqs disabled.
- */
-static void gr_stop_activity(struct gr_udc *dev)
-{
-       struct gr_ep *ep;
-
-       list_for_each_entry(ep, &dev->ep_list, ep_list)
-               gr_ep_nuke(ep);
-
-       gr_disable_interrupts_and_pullup(dev);
-
-       gr_set_ep0state(dev, GR_EP0_DISCONNECT);
-       usb_gadget_set_state(&dev->gadget, USB_STATE_NOTATTACHED);
-}
-
-/* ---------------------------------------------------------------------- */
-/* ep0 setup packet handling */
-
-static void gr_ep0_testmode_complete(struct usb_ep *_ep,
-                                    struct usb_request *_req)
-{
-       struct gr_ep *ep;
-       struct gr_udc *dev;
-       u32 control;
-
-       ep = container_of(_ep, struct gr_ep, ep);
-       dev = ep->dev;
-
-       spin_lock(&dev->lock);
-
-       control = gr_read32(&dev->regs->control);
-       control |= GR_CONTROL_TM | (dev->test_mode << GR_CONTROL_TS_POS);
-       gr_write32(&dev->regs->control, control);
-
-       spin_unlock(&dev->lock);
-}
-
-static void gr_ep0_dummy_complete(struct usb_ep *_ep, struct usb_request *_req)
-{
-       /* Nothing needs to be done here */
-}
-
-/*
- * Queue a response on ep0in.
- *
- * Must be called with dev->lock held.
- */
-static int gr_ep0_respond(struct gr_udc *dev, u8 *buf, int length,
-                         void (*complete)(struct usb_ep *ep,
-                                          struct usb_request *req))
-{
-       u8 *reqbuf = dev->ep0reqi->req.buf;
-       int status;
-       int i;
-
-       for (i = 0; i < length; i++)
-               reqbuf[i] = buf[i];
-       dev->ep0reqi->req.length = length;
-       dev->ep0reqi->req.complete = complete;
-
-       status = gr_queue_int(&dev->epi[0], dev->ep0reqi, GFP_ATOMIC);
-       if (status < 0)
-               dev_err(dev->dev,
-                       "Could not queue ep0in setup response: %d\n", status);
-
-       return status;
-}
-
-/*
- * Queue a 2 byte response on ep0in.
- *
- * Must be called with dev->lock held.
- */
-static inline int gr_ep0_respond_u16(struct gr_udc *dev, u16 response)
-{
-       __le16 le_response = cpu_to_le16(response);
-
-       return gr_ep0_respond(dev, (u8 *)&le_response, 2,
-                             gr_ep0_dummy_complete);
-}
-
-/*
- * Queue a ZLP response on ep0in.
- *
- * Must be called with dev->lock held.
- */
-static inline int gr_ep0_respond_empty(struct gr_udc *dev)
-{
-       return gr_ep0_respond(dev, NULL, 0, gr_ep0_dummy_complete);
-}
-
-/*
- * This is run when a SET_ADDRESS request is received. First writes
- * the new address to the control register which is updated internally
- * when the next IN packet is ACKED.
- *
- * Must be called with dev->lock held.
- */
-static void gr_set_address(struct gr_udc *dev, u8 address)
-{
-       u32 control;
-
-       control = gr_read32(&dev->regs->control) & ~GR_CONTROL_UA_MASK;
-       control |= (address << GR_CONTROL_UA_POS) & GR_CONTROL_UA_MASK;
-       control |= GR_CONTROL_SU;
-       gr_write32(&dev->regs->control, control);
-}
-
-/*
- * Returns negative for STALL, 0 for successful handling and positive for
- * delegation.
- *
- * Must be called with dev->lock held.
- */
-static int gr_device_request(struct gr_udc *dev, u8 type, u8 request,
-                            u16 value, u16 index)
-{
-       u16 response;
-       u8 test;
-
-       switch (request) {
-       case USB_REQ_SET_ADDRESS:
-               dev_dbg(dev->dev, "STATUS: address %d\n", value & 0xff);
-               gr_set_address(dev, value & 0xff);
-               if (value)
-                       usb_gadget_set_state(&dev->gadget, USB_STATE_ADDRESS);
-               else
-                       usb_gadget_set_state(&dev->gadget, USB_STATE_DEFAULT);
-               return gr_ep0_respond_empty(dev);
-
-       case USB_REQ_GET_STATUS:
-               /* Self powered | remote wakeup */
-               response = 0x0001 | (dev->remote_wakeup ? 0x0002 : 0);
-               return gr_ep0_respond_u16(dev, response);
-
-       case USB_REQ_SET_FEATURE:
-               switch (value) {
-               case USB_DEVICE_REMOTE_WAKEUP:
-                       /* Allow remote wakeup */
-                       dev->remote_wakeup = 1;
-                       return gr_ep0_respond_empty(dev);
-
-               case USB_DEVICE_TEST_MODE:
-                       /* The hardware does not support TEST_FORCE_EN */
-                       test = index >> 8;
-                       if (test >= TEST_J && test <= TEST_PACKET) {
-                               dev->test_mode = test;
-                               return gr_ep0_respond(dev, NULL, 0,
-                                                     gr_ep0_testmode_complete);
-                       }
-               }
-               break;
-
-       case USB_REQ_CLEAR_FEATURE:
-               switch (value) {
-               case USB_DEVICE_REMOTE_WAKEUP:
-                       /* Disallow remote wakeup */
-                       dev->remote_wakeup = 0;
-                       return gr_ep0_respond_empty(dev);
-               }
-               break;
-       }
-
-       return 1; /* Delegate the rest */
-}
-
-/*
- * Returns negative for STALL, 0 for successful handling and positive for
- * delegation.
- *
- * Must be called with dev->lock held.
- */
-static int gr_interface_request(struct gr_udc *dev, u8 type, u8 request,
-                               u16 value, u16 index)
-{
-       if (dev->gadget.state != USB_STATE_CONFIGURED)
-               return -1;
-
-       /*
-        * Should return STALL for invalid interfaces, but udc driver does not
-        * know anything about that. However, many gadget drivers do not handle
-        * GET_STATUS so we need to take care of that.
-        */
-
-       switch (request) {
-       case USB_REQ_GET_STATUS:
-               return gr_ep0_respond_u16(dev, 0x0000);
-
-       case USB_REQ_SET_FEATURE:
-       case USB_REQ_CLEAR_FEATURE:
-               /*
-                * No possible valid standard requests. Still let gadget drivers
-                * have a go at it.
-                */
-               break;
-       }
-
-       return 1; /* Delegate the rest */
-}
-
-/*
- * Returns negative for STALL, 0 for successful handling and positive for
- * delegation.
- *
- * Must be called with dev->lock held.
- */
-static int gr_endpoint_request(struct gr_udc *dev, u8 type, u8 request,
-                              u16 value, u16 index)
-{
-       struct gr_ep *ep;
-       int status;
-       int halted;
-       u8 epnum = index & USB_ENDPOINT_NUMBER_MASK;
-       u8 is_in = index & USB_ENDPOINT_DIR_MASK;
-
-       if ((is_in && epnum >= dev->nepi) || (!is_in && epnum >= dev->nepo))
-               return -1;
-
-       if (dev->gadget.state != USB_STATE_CONFIGURED && epnum != 0)
-               return -1;
-
-       ep = (is_in ? &dev->epi[epnum] : &dev->epo[epnum]);
-
-       switch (request) {
-       case USB_REQ_GET_STATUS:
-               halted = gr_read32(&ep->regs->epctrl) & GR_EPCTRL_EH;
-               return gr_ep0_respond_u16(dev, halted ? 0x0001 : 0);
-
-       case USB_REQ_SET_FEATURE:
-               switch (value) {
-               case USB_ENDPOINT_HALT:
-                       status = gr_ep_halt_wedge(ep, 1, 0, 1);
-                       if (status >= 0)
-                               status = gr_ep0_respond_empty(dev);
-                       return status;
-               }
-               break;
-
-       case USB_REQ_CLEAR_FEATURE:
-               switch (value) {
-               case USB_ENDPOINT_HALT:
-                       if (ep->wedged)
-                               return -1;
-                       status = gr_ep_halt_wedge(ep, 0, 0, 1);
-                       if (status >= 0)
-                               status = gr_ep0_respond_empty(dev);
-                       return status;
-               }
-               break;
-       }
-
-       return 1; /* Delegate the rest */
-}
-
-/* Must be called with dev->lock held */
-static void gr_ep0out_requeue(struct gr_udc *dev)
-{
-       int ret = gr_queue_int(&dev->epo[0], dev->ep0reqo, GFP_ATOMIC);
-
-       if (ret)
-               dev_err(dev->dev, "Could not queue ep0out setup request: %d\n",
-                       ret);
-}
-
-/*
- * The main function dealing with setup requests on ep0.
- *
- * Must be called with dev->lock held and irqs disabled
- */
-static void gr_ep0_setup(struct gr_udc *dev, struct gr_request *req)
-       __releases(&dev->lock)
-       __acquires(&dev->lock)
-{
-       union {
-               struct usb_ctrlrequest ctrl;
-               u8 raw[8];
-               u32 word[2];
-       } u;
-       u8 type;
-       u8 request;
-       u16 value;
-       u16 index;
-       u16 length;
-       int i;
-       int status;
-
-       /* Restore from ep0 halt */
-       if (dev->ep0state == GR_EP0_STALL) {
-               gr_set_ep0state(dev, GR_EP0_SETUP);
-               if (!req->req.actual)
-                       goto out;
-       }
-
-       if (dev->ep0state == GR_EP0_ISTATUS) {
-               gr_set_ep0state(dev, GR_EP0_SETUP);
-               if (req->req.actual > 0)
-                       dev_dbg(dev->dev,
-                               "Unexpected setup packet at state %s\n",
-                               gr_ep0state_string(GR_EP0_ISTATUS));
-               else
-                       goto out; /* Got expected ZLP */
-       } else if (dev->ep0state != GR_EP0_SETUP) {
-               dev_info(dev->dev,
-                        "Unexpected ep0out request at state %s - stalling\n",
-                        gr_ep0state_string(dev->ep0state));
-               gr_control_stall(dev);
-               gr_set_ep0state(dev, GR_EP0_SETUP);
-               goto out;
-       } else if (!req->req.actual) {
-               dev_dbg(dev->dev, "Unexpected ZLP at state %s\n",
-                       gr_ep0state_string(dev->ep0state));
-               goto out;
-       }
-
-       /* Handle SETUP packet */
-       for (i = 0; i < req->req.actual; i++)
-               u.raw[i] = ((u8 *)req->req.buf)[i];
-
-       type = u.ctrl.bRequestType;
-       request = u.ctrl.bRequest;
-       value = le16_to_cpu(u.ctrl.wValue);
-       index = le16_to_cpu(u.ctrl.wIndex);
-       length = le16_to_cpu(u.ctrl.wLength);
-
-       gr_dbgprint_devreq(dev, type, request, value, index, length);
-
-       /* Check for data stage */
-       if (length) {
-               if (type & USB_DIR_IN)
-                       gr_set_ep0state(dev, GR_EP0_IDATA);
-               else
-                       gr_set_ep0state(dev, GR_EP0_ODATA);
-       }
-
-       status = 1; /* Positive status flags delegation */
-       if ((type & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
-               switch (type & USB_RECIP_MASK) {
-               case USB_RECIP_DEVICE:
-                       status = gr_device_request(dev, type, request,
-                                                  value, index);
-                       break;
-               case USB_RECIP_ENDPOINT:
-                       status =  gr_endpoint_request(dev, type, request,
-                                                     value, index);
-                       break;
-               case USB_RECIP_INTERFACE:
-                       status = gr_interface_request(dev, type, request,
-                                                     value, index);
-                       break;
-               }
-       }
-
-       if (status > 0) {
-               spin_unlock(&dev->lock);
-
-               dev_vdbg(dev->dev, "DELEGATE\n");
-               status = dev->driver->setup(&dev->gadget, &u.ctrl);
-
-               spin_lock(&dev->lock);
-       }
-
-       /* Generate STALL on both ep0out and ep0in if requested */
-       if (unlikely(status < 0)) {
-               dev_vdbg(dev->dev, "STALL\n");
-               gr_control_stall(dev);
-       }
-
-       if ((type & USB_TYPE_MASK) == USB_TYPE_STANDARD &&
-           request == USB_REQ_SET_CONFIGURATION) {
-               if (!value) {
-                       dev_dbg(dev->dev, "STATUS: deconfigured\n");
-                       usb_gadget_set_state(&dev->gadget, USB_STATE_ADDRESS);
-               } else if (status >= 0) {
-                       /* Not configured unless gadget OK:s it */
-                       dev_dbg(dev->dev, "STATUS: configured: %d\n", value);
-                       usb_gadget_set_state(&dev->gadget,
-                                            USB_STATE_CONFIGURED);
-               }
-       }
-
-       /* Get ready for next stage */
-       if (dev->ep0state == GR_EP0_ODATA)
-               gr_set_ep0state(dev, GR_EP0_OSTATUS);
-       else if (dev->ep0state == GR_EP0_IDATA)
-               gr_set_ep0state(dev, GR_EP0_ISTATUS);
-       else
-               gr_set_ep0state(dev, GR_EP0_SETUP);
-
-out:
-       gr_ep0out_requeue(dev);
-}
-
-/* ---------------------------------------------------------------------- */
-/* VBUS and USB reset handling */
-
-/* Must be called with dev->lock held and irqs disabled  */
-static void gr_vbus_connected(struct gr_udc *dev, u32 status)
-{
-       u32 control;
-
-       dev->gadget.speed = GR_SPEED(status);
-       usb_gadget_set_state(&dev->gadget, USB_STATE_POWERED);
-
-       /* Turn on full interrupts and pullup */
-       control = (GR_CONTROL_SI | GR_CONTROL_UI | GR_CONTROL_VI |
-                  GR_CONTROL_SP | GR_CONTROL_EP);
-       gr_write32(&dev->regs->control, control);
-}
-
-/* Must be called with dev->lock held */
-static void gr_enable_vbus_detect(struct gr_udc *dev)
-{
-       u32 status;
-
-       dev->irq_enabled = 1;
-       wmb(); /* Make sure we do not ignore an interrupt */
-       gr_write32(&dev->regs->control, GR_CONTROL_VI);
-
-       /* Take care of the case we are already plugged in at this point */
-       status = gr_read32(&dev->regs->status);
-       if (status & GR_STATUS_VB)
-               gr_vbus_connected(dev, status);
-}
-
-/* Must be called with dev->lock held and irqs disabled */
-static void gr_vbus_disconnected(struct gr_udc *dev)
-{
-       gr_stop_activity(dev);
-
-       /* Report disconnect */
-       if (dev->driver && dev->driver->disconnect) {
-               spin_unlock(&dev->lock);
-
-               dev->driver->disconnect(&dev->gadget);
-
-               spin_lock(&dev->lock);
-       }
-
-       gr_enable_vbus_detect(dev);
-}
-
-/* Must be called with dev->lock held and irqs disabled */
-static void gr_udc_usbreset(struct gr_udc *dev, u32 status)
-{
-       gr_set_address(dev, 0);
-       gr_set_ep0state(dev, GR_EP0_SETUP);
-       usb_gadget_set_state(&dev->gadget, USB_STATE_DEFAULT);
-       dev->gadget.speed = GR_SPEED(status);
-
-       gr_ep_nuke(&dev->epo[0]);
-       gr_ep_nuke(&dev->epi[0]);
-       dev->epo[0].stopped = 0;
-       dev->epi[0].stopped = 0;
-       gr_ep0out_requeue(dev);
-}
-
-/* ---------------------------------------------------------------------- */
-/* Irq handling */
-
-/*
- * Handles interrupts from in endpoints. Returns whether something was handled.
- *
- * Must be called with dev->lock held, irqs disabled and with !ep->stopped.
- */
-static int gr_handle_in_ep(struct gr_ep *ep)
-{
-       struct gr_request *req;
-
-       req = list_first_entry(&ep->queue, struct gr_request, queue);
-       if (!req->last_desc)
-               return 0;
-
-       if (ACCESS_ONCE(req->last_desc->ctrl) & GR_DESC_IN_CTRL_EN)
-               return 0; /* Not put in hardware buffers yet */
-
-       if (gr_read32(&ep->regs->epstat) & (GR_EPSTAT_B1 | GR_EPSTAT_B0))
-               return 0; /* Not transmitted yet, still in hardware buffers */
-
-       /* Write complete */
-       gr_dma_advance(ep, 0);
-
-       return 1;
-}
-
-/*
- * Handles interrupts from out endpoints. Returns whether something was handled.
- *
- * Must be called with dev->lock held, irqs disabled and with !ep->stopped.
- */
-static int gr_handle_out_ep(struct gr_ep *ep)
-{
-       u32 ep_dmactrl;
-       u32 ctrl;
-       u16 len;
-       struct gr_request *req;
-       struct gr_udc *dev = ep->dev;
-
-       req = list_first_entry(&ep->queue, struct gr_request, queue);
-       if (!req->curr_desc)
-               return 0;
-
-       ctrl = ACCESS_ONCE(req->curr_desc->ctrl);
-       if (ctrl & GR_DESC_OUT_CTRL_EN)
-               return 0; /* Not received yet */
-
-       /* Read complete */
-       len = ctrl & GR_DESC_OUT_CTRL_LEN_MASK;
-       req->req.actual += len;
-       if (ctrl & GR_DESC_OUT_CTRL_SE)
-               req->setup = 1;
-
-       if (len < ep->ep.maxpacket || req->req.actual == req->req.length) {
-               /* Short packet or the expected size - we are done */
-
-               if ((ep == &dev->epo[0]) && (dev->ep0state == GR_EP0_OSTATUS)) {
-                       /*
-                        * Send a status stage ZLP to ack the DATA stage in the
-                        * OUT direction. This needs to be done before
-                        * gr_dma_advance as that can lead to a call to
-                        * ep0_setup that can change dev->ep0state.
-                        */
-                       gr_ep0_respond_empty(dev);
-                       gr_set_ep0state(dev, GR_EP0_SETUP);
-               }
-
-               gr_dma_advance(ep, 0);
-       } else {
-               /* Not done yet. Enable the next descriptor to receive more. */
-               req->curr_desc = req->curr_desc->next_desc;
-               req->curr_desc->ctrl |= GR_DESC_OUT_CTRL_EN;
-
-               ep_dmactrl = gr_read32(&ep->regs->dmactrl);
-               gr_write32(&ep->regs->dmactrl, ep_dmactrl | GR_DMACTRL_DA);
-       }
-
-       return 1;
-}
-
-/*
- * Handle state changes. Returns whether something was handled.
- *
- * Must be called with dev->lock held and irqs disabled.
- */
-static int gr_handle_state_changes(struct gr_udc *dev)
-{
-       u32 status = gr_read32(&dev->regs->status);
-       int handled = 0;
-       int powstate = !(dev->gadget.state == USB_STATE_NOTATTACHED ||
-                        dev->gadget.state == USB_STATE_ATTACHED);
-
-       /* VBUS valid detected */
-       if (!powstate && (status & GR_STATUS_VB)) {
-               dev_dbg(dev->dev, "STATUS: vbus valid detected\n");
-               gr_vbus_connected(dev, status);
-               handled = 1;
-       }
-
-       /* Disconnect */
-       if (powstate && !(status & GR_STATUS_VB)) {
-               dev_dbg(dev->dev, "STATUS: vbus invalid detected\n");
-               gr_vbus_disconnected(dev);
-               handled = 1;
-       }
-
-       /* USB reset detected */
-       if (status & GR_STATUS_UR) {
-               dev_dbg(dev->dev, "STATUS: USB reset - speed is %s\n",
-                       GR_SPEED_STR(status));
-               gr_write32(&dev->regs->status, GR_STATUS_UR);
-               gr_udc_usbreset(dev, status);
-               handled = 1;
-       }
-
-       /* Speed change */
-       if (dev->gadget.speed != GR_SPEED(status)) {
-               dev_dbg(dev->dev, "STATUS: USB Speed change to %s\n",
-                       GR_SPEED_STR(status));
-               dev->gadget.speed = GR_SPEED(status);
-               handled = 1;
-       }
-
-       /* Going into suspend */
-       if ((dev->ep0state != GR_EP0_SUSPEND) && !(status & GR_STATUS_SU)) {
-               dev_dbg(dev->dev, "STATUS: USB suspend\n");
-               gr_set_ep0state(dev, GR_EP0_SUSPEND);
-               dev->suspended_from = dev->gadget.state;
-               usb_gadget_set_state(&dev->gadget, USB_STATE_SUSPENDED);
-
-               if ((dev->gadget.speed != USB_SPEED_UNKNOWN) &&
-                   dev->driver && dev->driver->suspend) {
-                       spin_unlock(&dev->lock);
-
-                       dev->driver->suspend(&dev->gadget);
-
-                       spin_lock(&dev->lock);
-               }
-               handled = 1;
-       }
-
-       /* Coming out of suspend */
-       if ((dev->ep0state == GR_EP0_SUSPEND) && (status & GR_STATUS_SU)) {
-               dev_dbg(dev->dev, "STATUS: USB resume\n");
-               if (dev->suspended_from == USB_STATE_POWERED)
-                       gr_set_ep0state(dev, GR_EP0_DISCONNECT);
-               else
-                       gr_set_ep0state(dev, GR_EP0_SETUP);
-               usb_gadget_set_state(&dev->gadget, dev->suspended_from);
-
-               if ((dev->gadget.speed != USB_SPEED_UNKNOWN) &&
-                   dev->driver && dev->driver->resume) {
-                       spin_unlock(&dev->lock);
-
-                       dev->driver->resume(&dev->gadget);
-
-                       spin_lock(&dev->lock);
-               }
-               handled = 1;
-       }
-
-       return handled;
-}
-
-/* Non-interrupt context irq handler */
-static irqreturn_t gr_irq_handler(int irq, void *_dev)
-{
-       struct gr_udc *dev = _dev;
-       struct gr_ep *ep;
-       int handled = 0;
-       int i;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       if (!dev->irq_enabled)
-               goto out;
-
-       /*
-        * Check IN ep interrupts. We check these before the OUT eps because
-        * some gadgets reuse the request that might already be currently
-        * outstanding and needs to be completed (mainly setup requests).
-        */
-       for (i = 0; i < dev->nepi; i++) {
-               ep = &dev->epi[i];
-               if (!ep->stopped && !ep->callback && !list_empty(&ep->queue))
-                       handled = gr_handle_in_ep(ep) || handled;
-       }
-
-       /* Check OUT ep interrupts */
-       for (i = 0; i < dev->nepo; i++) {
-               ep = &dev->epo[i];
-               if (!ep->stopped && !ep->callback && !list_empty(&ep->queue))
-                       handled = gr_handle_out_ep(ep) || handled;
-       }
-
-       /* Check status interrupts */
-       handled = gr_handle_state_changes(dev) || handled;
-
-       /*
-        * Check AMBA DMA errors. Only check if we didn't find anything else to
-        * handle because this shouldn't happen if we did everything right.
-        */
-       if (!handled) {
-               list_for_each_entry(ep, &dev->ep_list, ep_list) {
-                       if (gr_read32(&ep->regs->dmactrl) & GR_DMACTRL_AE) {
-                               dev_err(dev->dev,
-                                       "AMBA Error occurred for %s\n",
-                                       ep->ep.name);
-                               handled = 1;
-                       }
-               }
-       }
-
-out:
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return handled ? IRQ_HANDLED : IRQ_NONE;
-}
-
-/* Interrupt context irq handler */
-static irqreturn_t gr_irq(int irq, void *_dev)
-{
-       struct gr_udc *dev = _dev;
-
-       if (!dev->irq_enabled)
-               return IRQ_NONE;
-
-       return IRQ_WAKE_THREAD;
-}
-
-/* ---------------------------------------------------------------------- */
-/* USB ep ops */
-
-/* Enable endpoint. Not for ep0in and ep0out that are handled separately. */
-static int gr_ep_enable(struct usb_ep *_ep,
-                       const struct usb_endpoint_descriptor *desc)
-{
-       struct gr_udc *dev;
-       struct gr_ep *ep;
-       u8 mode;
-       u8 nt;
-       u16 max;
-       u16 buffer_size = 0;
-       u32 epctrl;
-
-       ep = container_of(_ep, struct gr_ep, ep);
-       if (!_ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT)
-               return -EINVAL;
-
-       dev = ep->dev;
-
-       /* 'ep0' IN and OUT are reserved */
-       if (ep == &dev->epo[0] || ep == &dev->epi[0])
-               return -EINVAL;
-
-       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       /* Make sure we are clear for enabling */
-       epctrl = gr_read32(&ep->regs->epctrl);
-       if (epctrl & GR_EPCTRL_EV)
-               return -EBUSY;
-
-       /* Check that directions match */
-       if (!ep->is_in != !usb_endpoint_dir_in(desc))
-               return -EINVAL;
-
-       /* Check ep num */
-       if ((!ep->is_in && ep->num >= dev->nepo) ||
-           (ep->is_in && ep->num >= dev->nepi))
-               return -EINVAL;
-
-       if (usb_endpoint_xfer_control(desc)) {
-               mode = 0;
-       } else if (usb_endpoint_xfer_isoc(desc)) {
-               mode = 1;
-       } else if (usb_endpoint_xfer_bulk(desc)) {
-               mode = 2;
-       } else if (usb_endpoint_xfer_int(desc)) {
-               mode = 3;
-       } else {
-               dev_err(dev->dev, "Unknown transfer type for %s\n",
-                       ep->ep.name);
-               return -EINVAL;
-       }
-
-       /*
-        * Bits 10-0 set the max payload. 12-11 set the number of
-        * additional transactions.
-        */
-       max = 0x7ff & usb_endpoint_maxp(desc);
-       nt = 0x3 & (usb_endpoint_maxp(desc) >> 11);
-       buffer_size = GR_BUFFER_SIZE(epctrl);
-       if (nt && (mode == 0 || mode == 2)) {
-               dev_err(dev->dev,
-                       "%s mode: multiple trans./microframe not valid\n",
-                       (mode == 2 ? "Bulk" : "Control"));
-               return -EINVAL;
-       } else if (nt == 0x11) {
-               dev_err(dev->dev, "Invalid value for trans./microframe\n");
-               return -EINVAL;
-       } else if ((nt + 1) * max > buffer_size) {
-               dev_err(dev->dev, "Hw buffer size %d < max payload %d * %d\n",
-                       buffer_size, (nt + 1), max);
-               return -EINVAL;
-       } else if (max == 0) {
-               dev_err(dev->dev, "Max payload cannot be set to 0\n");
-               return -EINVAL;
-       } else if (max > ep->ep.maxpacket_limit) {
-               dev_err(dev->dev, "Requested max payload %d > limit %d\n",
-                       max, ep->ep.maxpacket_limit);
-               return -EINVAL;
-       }
-
-       spin_lock(&ep->dev->lock);
-
-       if (!ep->stopped) {
-               spin_unlock(&ep->dev->lock);
-               return -EBUSY;
-       }
-
-       ep->stopped = 0;
-       ep->wedged = 0;
-       ep->ep.desc = desc;
-       ep->ep.maxpacket = max;
-       ep->dma_start = 0;
-
-
-       if (nt) {
-               /*
-                * Maximum possible size of all payloads in one microframe
-                * regardless of direction when using high-bandwidth mode.
-                */
-               ep->bytes_per_buffer = (nt + 1) * max;
-       } else if (ep->is_in) {
-               /*
-                * The biggest multiple of maximum packet size that fits into
-                * the buffer. The hardware will split up into many packets in
-                * the IN direction.
-                */
-               ep->bytes_per_buffer = (buffer_size / max) * max;
-       } else {
-               /*
-                * Only single packets will be placed the buffers in the OUT
-                * direction.
-                */
-               ep->bytes_per_buffer = max;
-       }
-
-       epctrl = (max << GR_EPCTRL_MAXPL_POS)
-               | (nt << GR_EPCTRL_NT_POS)
-               | (mode << GR_EPCTRL_TT_POS)
-               | GR_EPCTRL_EV;
-       if (ep->is_in)
-               epctrl |= GR_EPCTRL_PI;
-       gr_write32(&ep->regs->epctrl, epctrl);
-
-       gr_write32(&ep->regs->dmactrl, GR_DMACTRL_IE | GR_DMACTRL_AI);
-
-       spin_unlock(&ep->dev->lock);
-
-       dev_dbg(ep->dev->dev, "EP: %s enabled - %s with %d bytes/buffer\n",
-               ep->ep.name, gr_modestring[mode], ep->bytes_per_buffer);
-       return 0;
-}
-
-/* Disable endpoint. Not for ep0in and ep0out that are handled separately. */
-static int gr_ep_disable(struct usb_ep *_ep)
-{
-       struct gr_ep *ep;
-       struct gr_udc *dev;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct gr_ep, ep);
-       if (!_ep || !ep->ep.desc)
-               return -ENODEV;
-
-       dev = ep->dev;
-
-       /* 'ep0' IN and OUT are reserved */
-       if (ep == &dev->epo[0] || ep == &dev->epi[0])
-               return -EINVAL;
-
-       if (dev->ep0state == GR_EP0_SUSPEND)
-               return -EBUSY;
-
-       dev_dbg(ep->dev->dev, "EP: disable %s\n", ep->ep.name);
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       gr_ep_nuke(ep);
-       gr_ep_reset(ep);
-       ep->ep.desc = NULL;
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return 0;
-}
-
-/*
- * Frees a request, but not any DMA buffers associated with it
- * (gr_finish_request should already have taken care of that).
- */
-static void gr_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct gr_request *req;
-
-       if (!_ep || !_req)
-               return;
-       req = container_of(_req, struct gr_request, req);
-
-       /* Leads to memory leak */
-       WARN(!list_empty(&req->queue),
-            "request not dequeued properly before freeing\n");
-
-       kfree(req);
-}
-
-/* Queue a request from the gadget */
-static int gr_queue_ext(struct usb_ep *_ep, struct usb_request *_req,
-                       gfp_t gfp_flags)
-{
-       struct gr_ep *ep;
-       struct gr_request *req;
-       struct gr_udc *dev;
-       int ret;
-
-       if (unlikely(!_ep || !_req))
-               return -EINVAL;
-
-       ep = container_of(_ep, struct gr_ep, ep);
-       req = container_of(_req, struct gr_request, req);
-       dev = ep->dev;
-
-       spin_lock(&ep->dev->lock);
-
-       /*
-        * The ep0 pointer in the gadget struct is used both for ep0in and
-        * ep0out. In a data stage in the out direction ep0out needs to be used
-        * instead of the default ep0in. Completion functions might use
-        * driver_data, so that needs to be copied as well.
-        */
-       if ((ep == &dev->epi[0]) && (dev->ep0state == GR_EP0_ODATA)) {
-               ep = &dev->epo[0];
-               ep->ep.driver_data = dev->epi[0].ep.driver_data;
-       }
-
-       if (ep->is_in)
-               gr_dbgprint_request("EXTERN", ep, req);
-
-       ret = gr_queue(ep, req, GFP_ATOMIC);
-
-       spin_unlock(&ep->dev->lock);
-
-       return ret;
-}
-
-/* Dequeue JUST ONE request */
-static int gr_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct gr_request *req;
-       struct gr_ep *ep;
-       struct gr_udc *dev;
-       int ret = 0;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct gr_ep, ep);
-       if (!_ep || !_req || (!ep->ep.desc && ep->num != 0))
-               return -EINVAL;
-       dev = ep->dev;
-       if (!dev->driver)
-               return -ESHUTDOWN;
-
-       /* We can't touch (DMA) registers when suspended */
-       if (dev->ep0state == GR_EP0_SUSPEND)
-               return -EBUSY;
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       /* Make sure it's actually queued on this endpoint */
-       list_for_each_entry(req, &ep->queue, queue) {
-               if (&req->req == _req)
-                       break;
-       }
-       if (&req->req != _req) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       if (list_first_entry(&ep->queue, struct gr_request, queue) == req) {
-               /* This request is currently being processed */
-               gr_abort_dma(ep);
-               if (ep->stopped)
-                       gr_finish_request(ep, req, -ECONNRESET);
-               else
-                       gr_dma_advance(ep, -ECONNRESET);
-       } else if (!list_empty(&req->queue)) {
-               /* Not being processed - gr_finish_request dequeues it */
-               gr_finish_request(ep, req, -ECONNRESET);
-       } else {
-               ret = -EOPNOTSUPP;
-       }
-
-out:
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return ret;
-}
-
-/* Helper for gr_set_halt and gr_set_wedge */
-static int gr_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge)
-{
-       int ret;
-       struct gr_ep *ep;
-
-       if (!_ep)
-               return -ENODEV;
-       ep = container_of(_ep, struct gr_ep, ep);
-
-       spin_lock(&ep->dev->lock);
-
-       /* Halting an IN endpoint should fail if queue is not empty */
-       if (halt && ep->is_in && !list_empty(&ep->queue)) {
-               ret = -EAGAIN;
-               goto out;
-       }
-
-       ret = gr_ep_halt_wedge(ep, halt, wedge, 0);
-
-out:
-       spin_unlock(&ep->dev->lock);
-
-       return ret;
-}
-
-/* Halt endpoint */
-static int gr_set_halt(struct usb_ep *_ep, int halt)
-{
-       return gr_set_halt_wedge(_ep, halt, 0);
-}
-
-/* Halt and wedge endpoint */
-static int gr_set_wedge(struct usb_ep *_ep)
-{
-       return gr_set_halt_wedge(_ep, 1, 1);
-}
-
-/*
- * Return the total number of bytes currently stored in the internal buffers of
- * the endpoint.
- */
-static int gr_fifo_status(struct usb_ep *_ep)
-{
-       struct gr_ep *ep;
-       u32 epstat;
-       u32 bytes = 0;
-
-       if (!_ep)
-               return -ENODEV;
-       ep = container_of(_ep, struct gr_ep, ep);
-
-       epstat = gr_read32(&ep->regs->epstat);
-
-       if (epstat & GR_EPSTAT_B0)
-               bytes += (epstat & GR_EPSTAT_B0CNT_MASK) >> GR_EPSTAT_B0CNT_POS;
-       if (epstat & GR_EPSTAT_B1)
-               bytes += (epstat & GR_EPSTAT_B1CNT_MASK) >> GR_EPSTAT_B1CNT_POS;
-
-       return bytes;
-}
-
-
-/* Empty data from internal buffers of an endpoint. */
-static void gr_fifo_flush(struct usb_ep *_ep)
-{
-       struct gr_ep *ep;
-       u32 epctrl;
-
-       if (!_ep)
-               return;
-       ep = container_of(_ep, struct gr_ep, ep);
-       dev_vdbg(ep->dev->dev, "EP: flush fifo %s\n", ep->ep.name);
-
-       spin_lock(&ep->dev->lock);
-
-       epctrl = gr_read32(&ep->regs->epctrl);
-       epctrl |= GR_EPCTRL_CB;
-       gr_write32(&ep->regs->epctrl, epctrl);
-
-       spin_unlock(&ep->dev->lock);
-}
-
-static struct usb_ep_ops gr_ep_ops = {
-       .enable         = gr_ep_enable,
-       .disable        = gr_ep_disable,
-
-       .alloc_request  = gr_alloc_request,
-       .free_request   = gr_free_request,
-
-       .queue          = gr_queue_ext,
-       .dequeue        = gr_dequeue,
-
-       .set_halt       = gr_set_halt,
-       .set_wedge      = gr_set_wedge,
-       .fifo_status    = gr_fifo_status,
-       .fifo_flush     = gr_fifo_flush,
-};
-
-/* ---------------------------------------------------------------------- */
-/* USB Gadget ops */
-
-static int gr_get_frame(struct usb_gadget *_gadget)
-{
-       struct gr_udc *dev;
-
-       if (!_gadget)
-               return -ENODEV;
-       dev = container_of(_gadget, struct gr_udc, gadget);
-       return gr_read32(&dev->regs->status) & GR_STATUS_FN_MASK;
-}
-
-static int gr_wakeup(struct usb_gadget *_gadget)
-{
-       struct gr_udc *dev;
-
-       if (!_gadget)
-               return -ENODEV;
-       dev = container_of(_gadget, struct gr_udc, gadget);
-
-       /* Remote wakeup feature not enabled by host*/
-       if (!dev->remote_wakeup)
-               return -EINVAL;
-
-       spin_lock(&dev->lock);
-
-       gr_write32(&dev->regs->control,
-                  gr_read32(&dev->regs->control) | GR_CONTROL_RW);
-
-       spin_unlock(&dev->lock);
-
-       return 0;
-}
-
-static int gr_pullup(struct usb_gadget *_gadget, int is_on)
-{
-       struct gr_udc *dev;
-       u32 control;
-
-       if (!_gadget)
-               return -ENODEV;
-       dev = container_of(_gadget, struct gr_udc, gadget);
-
-       spin_lock(&dev->lock);
-
-       control = gr_read32(&dev->regs->control);
-       if (is_on)
-               control |= GR_CONTROL_EP;
-       else
-               control &= ~GR_CONTROL_EP;
-       gr_write32(&dev->regs->control, control);
-
-       spin_unlock(&dev->lock);
-
-       return 0;
-}
-
-static int gr_udc_start(struct usb_gadget *gadget,
-                       struct usb_gadget_driver *driver)
-{
-       struct gr_udc *dev = to_gr_udc(gadget);
-
-       spin_lock(&dev->lock);
-
-       /* Hook up the driver */
-       driver->driver.bus = NULL;
-       dev->driver = driver;
-
-       /* Get ready for host detection */
-       gr_enable_vbus_detect(dev);
-
-       spin_unlock(&dev->lock);
-
-       dev_info(dev->dev, "Started with gadget driver '%s'\n",
-                driver->driver.name);
-
-       return 0;
-}
-
-static int gr_udc_stop(struct usb_gadget *gadget,
-                      struct usb_gadget_driver *driver)
-{
-       struct gr_udc *dev = to_gr_udc(gadget);
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       dev->driver = NULL;
-       gr_stop_activity(dev);
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       dev_info(dev->dev, "Stopped\n");
-
-       return 0;
-}
-
-static const struct usb_gadget_ops gr_ops = {
-       .get_frame      = gr_get_frame,
-       .wakeup         = gr_wakeup,
-       .pullup         = gr_pullup,
-       .udc_start      = gr_udc_start,
-       .udc_stop       = gr_udc_stop,
-       /* Other operations not supported */
-};
-
-/* ---------------------------------------------------------------------- */
-/* Module probe, removal and of-matching */
-
-static const char * const onames[] = {
-       "ep0out", "ep1out", "ep2out", "ep3out", "ep4out", "ep5out",
-       "ep6out", "ep7out", "ep8out", "ep9out", "ep10out", "ep11out",
-       "ep12out", "ep13out", "ep14out", "ep15out"
-};
-
-static const char * const inames[] = {
-       "ep0in", "ep1in", "ep2in", "ep3in", "ep4in", "ep5in",
-       "ep6in", "ep7in", "ep8in", "ep9in", "ep10in", "ep11in",
-       "ep12in", "ep13in", "ep14in", "ep15in"
-};
-
-/* Must be called with dev->lock held */
-static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit)
-{
-       struct gr_ep *ep;
-       struct gr_request *req;
-       struct usb_request *_req;
-       void *buf;
-
-       if (is_in) {
-               ep = &dev->epi[num];
-               ep->ep.name = inames[num];
-               ep->regs = &dev->regs->epi[num];
-       } else {
-               ep = &dev->epo[num];
-               ep->ep.name = onames[num];
-               ep->regs = &dev->regs->epo[num];
-       }
-
-       gr_ep_reset(ep);
-       ep->num = num;
-       ep->is_in = is_in;
-       ep->dev = dev;
-       ep->ep.ops = &gr_ep_ops;
-       INIT_LIST_HEAD(&ep->queue);
-
-       if (num == 0) {
-               _req = gr_alloc_request(&ep->ep, GFP_ATOMIC);
-               buf = devm_kzalloc(dev->dev, PAGE_SIZE, GFP_DMA | GFP_ATOMIC);
-               if (!_req || !buf) {
-                       /* possible _req freed by gr_probe via gr_remove */
-                       return -ENOMEM;
-               }
-
-               req = container_of(_req, struct gr_request, req);
-               req->req.buf = buf;
-               req->req.length = MAX_CTRL_PL_SIZE;
-
-               if (is_in)
-                       dev->ep0reqi = req; /* Complete gets set as used */
-               else
-                       dev->ep0reqo = req; /* Completion treated separately */
-
-               usb_ep_set_maxpacket_limit(&ep->ep, MAX_CTRL_PL_SIZE);
-               ep->bytes_per_buffer = MAX_CTRL_PL_SIZE;
-       } else {
-               usb_ep_set_maxpacket_limit(&ep->ep, (u16)maxplimit);
-               list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
-       }
-       list_add_tail(&ep->ep_list, &dev->ep_list);
-
-       return 0;
-}
-
-/* Must be called with dev->lock held */
-static int gr_udc_init(struct gr_udc *dev)
-{
-       struct device_node *np = dev->dev->of_node;
-       u32 epctrl_val;
-       u32 dmactrl_val;
-       int i;
-       int ret = 0;
-       u32 bufsize;
-
-       gr_set_address(dev, 0);
-
-       INIT_LIST_HEAD(&dev->gadget.ep_list);
-       dev->gadget.speed = USB_SPEED_UNKNOWN;
-       dev->gadget.ep0 = &dev->epi[0].ep;
-
-       INIT_LIST_HEAD(&dev->ep_list);
-       gr_set_ep0state(dev, GR_EP0_DISCONNECT);
-
-       for (i = 0; i < dev->nepo; i++) {
-               if (of_property_read_u32_index(np, "epobufsizes", i, &bufsize))
-                       bufsize = 1024;
-               ret = gr_ep_init(dev, i, 0, bufsize);
-               if (ret)
-                       return ret;
-       }
-
-       for (i = 0; i < dev->nepi; i++) {
-               if (of_property_read_u32_index(np, "epibufsizes", i, &bufsize))
-                       bufsize = 1024;
-               ret = gr_ep_init(dev, i, 1, bufsize);
-               if (ret)
-                       return ret;
-       }
-
-       /* Must be disabled by default */
-       dev->remote_wakeup = 0;
-
-       /* Enable ep0out and ep0in */
-       epctrl_val = (MAX_CTRL_PL_SIZE << GR_EPCTRL_MAXPL_POS) | GR_EPCTRL_EV;
-       dmactrl_val = GR_DMACTRL_IE | GR_DMACTRL_AI;
-       gr_write32(&dev->epo[0].regs->epctrl, epctrl_val);
-       gr_write32(&dev->epi[0].regs->epctrl, epctrl_val | GR_EPCTRL_PI);
-       gr_write32(&dev->epo[0].regs->dmactrl, dmactrl_val);
-       gr_write32(&dev->epi[0].regs->dmactrl, dmactrl_val);
-
-       return 0;
-}
-
-static int gr_remove(struct platform_device *pdev)
-{
-       struct gr_udc *dev = platform_get_drvdata(pdev);
-
-       if (dev->added)
-               usb_del_gadget_udc(&dev->gadget); /* Shuts everything down */
-       if (dev->driver)
-               return -EBUSY;
-
-       gr_dfs_delete(dev);
-       if (dev->desc_pool)
-               dma_pool_destroy(dev->desc_pool);
-       platform_set_drvdata(pdev, NULL);
-
-       gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req);
-       gr_free_request(&dev->epo[0].ep, &dev->ep0reqo->req);
-
-       return 0;
-}
-static int gr_request_irq(struct gr_udc *dev, int irq)
-{
-       return devm_request_threaded_irq(dev->dev, irq, gr_irq, gr_irq_handler,
-                                        IRQF_SHARED, driver_name, dev);
-}
-
-static int gr_probe(struct platform_device *pdev)
-{
-       struct gr_udc *dev;
-       struct resource *res;
-       struct gr_regs __iomem *regs;
-       int retval;
-       u32 status;
-
-       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-       if (!dev)
-               return -ENOMEM;
-       dev->dev = &pdev->dev;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       regs = devm_ioremap_resource(dev->dev, res);
-       if (IS_ERR(regs))
-               return PTR_ERR(regs);
-
-       dev->irq = platform_get_irq(pdev, 0);
-       if (dev->irq <= 0) {
-               dev_err(dev->dev, "No irq found\n");
-               return -ENODEV;
-       }
-
-       /* Some core configurations has separate irqs for IN and OUT events */
-       dev->irqi = platform_get_irq(pdev, 1);
-       if (dev->irqi > 0) {
-               dev->irqo = platform_get_irq(pdev, 2);
-               if (dev->irqo <= 0) {
-                       dev_err(dev->dev, "Found irqi but not irqo\n");
-                       return -ENODEV;
-               }
-       } else {
-               dev->irqi = 0;
-       }
-
-       dev->gadget.name = driver_name;
-       dev->gadget.max_speed = USB_SPEED_HIGH;
-       dev->gadget.ops = &gr_ops;
-       dev->gadget.quirk_ep_out_aligned_size = true;
-
-       spin_lock_init(&dev->lock);
-       dev->regs = regs;
-
-       platform_set_drvdata(pdev, dev);
-
-       /* Determine number of endpoints and data interface mode */
-       status = gr_read32(&dev->regs->status);
-       dev->nepi = ((status & GR_STATUS_NEPI_MASK) >> GR_STATUS_NEPI_POS) + 1;
-       dev->nepo = ((status & GR_STATUS_NEPO_MASK) >> GR_STATUS_NEPO_POS) + 1;
-
-       if (!(status & GR_STATUS_DM)) {
-               dev_err(dev->dev, "Slave mode cores are not supported\n");
-               return -ENODEV;
-       }
-
-       /* --- Effects of the following calls might need explicit cleanup --- */
-
-       /* Create DMA pool for descriptors */
-       dev->desc_pool = dma_pool_create("desc_pool", dev->dev,
-                                        sizeof(struct gr_dma_desc), 4, 0);
-       if (!dev->desc_pool) {
-               dev_err(dev->dev, "Could not allocate DMA pool");
-               return -ENOMEM;
-       }
-
-       spin_lock(&dev->lock);
-
-       /* Inside lock so that no gadget can use this udc until probe is done */
-       retval = usb_add_gadget_udc(dev->dev, &dev->gadget);
-       if (retval) {
-               dev_err(dev->dev, "Could not add gadget udc");
-               goto out;
-       }
-       dev->added = 1;
-
-       retval = gr_udc_init(dev);
-       if (retval)
-               goto out;
-
-       gr_dfs_create(dev);
-
-       /* Clear all interrupt enables that might be left on since last boot */
-       gr_disable_interrupts_and_pullup(dev);
-
-       retval = gr_request_irq(dev, dev->irq);
-       if (retval) {
-               dev_err(dev->dev, "Failed to request irq %d\n", dev->irq);
-               goto out;
-       }
-
-       if (dev->irqi) {
-               retval = gr_request_irq(dev, dev->irqi);
-               if (retval) {
-                       dev_err(dev->dev, "Failed to request irqi %d\n",
-                               dev->irqi);
-                       goto out;
-               }
-               retval = gr_request_irq(dev, dev->irqo);
-               if (retval) {
-                       dev_err(dev->dev, "Failed to request irqo %d\n",
-                               dev->irqo);
-                       goto out;
-               }
-       }
-
-       if (dev->irqi)
-               dev_info(dev->dev, "regs: %p, irqs %d, %d, %d\n", dev->regs,
-                        dev->irq, dev->irqi, dev->irqo);
-       else
-               dev_info(dev->dev, "regs: %p, irq %d\n", dev->regs, dev->irq);
-
-out:
-       spin_unlock(&dev->lock);
-
-       if (retval)
-               gr_remove(pdev);
-
-       return retval;
-}
-
-static const struct of_device_id gr_match[] = {
-       {.name = "GAISLER_USBDC"},
-       {.name = "01_021"},
-       {},
-};
-MODULE_DEVICE_TABLE(of, gr_match);
-
-static struct platform_driver gr_driver = {
-       .driver = {
-               .name = DRIVER_NAME,
-               .owner = THIS_MODULE,
-               .of_match_table = gr_match,
-       },
-       .probe = gr_probe,
-       .remove = gr_remove,
-};
-module_platform_driver(gr_driver);
-
-MODULE_AUTHOR("Aeroflex Gaisler AB.");
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/gr_udc.h b/drivers/usb/gadget/gr_udc.h
deleted file mode 100644 (file)
index 8388897..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * USB Peripheral Controller driver for Aeroflex Gaisler GRUSBDC.
- *
- * 2013 (c) Aeroflex Gaisler AB
- *
- * This driver supports GRUSBDC USB Device Controller cores available in the
- * GRLIB VHDL IP core library.
- *
- * Full documentation of the GRUSBDC core can be found here:
- * http://www.gaisler.com/products/grlib/grip.pdf
- *
- * 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.
- *
- * Contributors:
- * - Andreas Larsson <andreas@gaisler.com>
- * - Marko Isomaki
- */
-
-/* Control registers on the AMBA bus */
-
-#define GR_MAXEP       16      /* Max # endpoints for *each* direction */
-
-struct gr_epregs {
-       u32 epctrl;
-       union {
-               struct { /* Slave mode*/
-                       u32 slvctrl;
-                       u32 slvdata;
-               };
-               struct { /* DMA mode*/
-                       u32 dmactrl;
-                       u32 dmaaddr;
-               };
-       };
-       u32 epstat;
-};
-
-struct gr_regs {
-       struct gr_epregs        epo[GR_MAXEP];  /* 0x000 - 0x0fc */
-       struct gr_epregs        epi[GR_MAXEP];  /* 0x100 - 0x1fc */
-       u32                     control;        /* 0x200 */
-       u32                     status;         /* 0x204 */
-};
-
-#define GR_EPCTRL_BUFSZ_SCALER 8
-#define GR_EPCTRL_BUFSZ_MASK   0xffe00000
-#define GR_EPCTRL_BUFSZ_POS    21
-#define GR_EPCTRL_PI           BIT(20)
-#define GR_EPCTRL_CB           BIT(19)
-#define GR_EPCTRL_CS           BIT(18)
-#define GR_EPCTRL_MAXPL_MASK   0x0003ff80
-#define GR_EPCTRL_MAXPL_POS    7
-#define GR_EPCTRL_NT_MASK      0x00000060
-#define GR_EPCTRL_NT_POS       5
-#define GR_EPCTRL_TT_MASK      0x00000018
-#define GR_EPCTRL_TT_POS       3
-#define GR_EPCTRL_EH           BIT(2)
-#define GR_EPCTRL_ED           BIT(1)
-#define GR_EPCTRL_EV           BIT(0)
-
-#define GR_DMACTRL_AE          BIT(10)
-#define GR_DMACTRL_AD          BIT(3)
-#define GR_DMACTRL_AI          BIT(2)
-#define GR_DMACTRL_IE          BIT(1)
-#define GR_DMACTRL_DA          BIT(0)
-
-#define GR_EPSTAT_PT           BIT(29)
-#define GR_EPSTAT_PR           BIT(29)
-#define GR_EPSTAT_B1CNT_MASK   0x1fff0000
-#define GR_EPSTAT_B1CNT_POS    16
-#define GR_EPSTAT_B0CNT_MASK   0x0000fff8
-#define GR_EPSTAT_B0CNT_POS    3
-#define GR_EPSTAT_B1           BIT(2)
-#define GR_EPSTAT_B0           BIT(1)
-#define GR_EPSTAT_BS           BIT(0)
-
-#define GR_CONTROL_SI          BIT(31)
-#define GR_CONTROL_UI          BIT(30)
-#define GR_CONTROL_VI          BIT(29)
-#define GR_CONTROL_SP          BIT(28)
-#define GR_CONTROL_FI          BIT(27)
-#define GR_CONTROL_EP          BIT(14)
-#define GR_CONTROL_DH          BIT(13)
-#define GR_CONTROL_RW          BIT(12)
-#define GR_CONTROL_TS_MASK     0x00000e00
-#define GR_CONTROL_TS_POS      9
-#define GR_CONTROL_TM          BIT(8)
-#define GR_CONTROL_UA_MASK     0x000000fe
-#define GR_CONTROL_UA_POS      1
-#define GR_CONTROL_SU          BIT(0)
-
-#define GR_STATUS_NEPI_MASK    0xf0000000
-#define GR_STATUS_NEPI_POS     28
-#define GR_STATUS_NEPO_MASK    0x0f000000
-#define GR_STATUS_NEPO_POS     24
-#define GR_STATUS_DM           BIT(23)
-#define GR_STATUS_SU           BIT(17)
-#define GR_STATUS_UR           BIT(16)
-#define GR_STATUS_VB           BIT(15)
-#define GR_STATUS_SP           BIT(14)
-#define GR_STATUS_AF_MASK      0x00003800
-#define GR_STATUS_AF_POS       11
-#define GR_STATUS_FN_MASK      0x000007ff
-#define GR_STATUS_FN_POS       0
-
-
-#define MAX_CTRL_PL_SIZE 64 /* As per USB standard for full and high speed */
-
-/*-------------------------------------------------------------------------*/
-
-/* Driver data structures and utilities */
-
-struct gr_dma_desc {
-       u32 ctrl;
-       u32 data;
-       u32 next;
-
-       /* These must be last because hw uses the previous three */
-       u32 paddr;
-       struct gr_dma_desc *next_desc;
-};
-
-#define GR_DESC_OUT_CTRL_SE            BIT(17)
-#define GR_DESC_OUT_CTRL_IE            BIT(15)
-#define GR_DESC_OUT_CTRL_NX            BIT(14)
-#define GR_DESC_OUT_CTRL_EN            BIT(13)
-#define GR_DESC_OUT_CTRL_LEN_MASK      0x00001fff
-
-#define GR_DESC_IN_CTRL_MO             BIT(18)
-#define GR_DESC_IN_CTRL_PI             BIT(17)
-#define GR_DESC_IN_CTRL_ML             BIT(16)
-#define GR_DESC_IN_CTRL_IE             BIT(15)
-#define GR_DESC_IN_CTRL_NX             BIT(14)
-#define GR_DESC_IN_CTRL_EN             BIT(13)
-#define GR_DESC_IN_CTRL_LEN_MASK       0x00001fff
-
-#define GR_DESC_DMAADDR_MASK           0xfffffffc
-
-struct gr_ep {
-       struct usb_ep ep;
-       struct gr_udc *dev;
-       u16 bytes_per_buffer;
-       unsigned int dma_start;
-       struct gr_epregs __iomem *regs;
-
-       unsigned num:8;
-       unsigned is_in:1;
-       unsigned stopped:1;
-       unsigned wedged:1;
-       unsigned callback:1;
-
-       /* analogous to a host-side qh */
-       struct list_head queue;
-
-       struct list_head ep_list;
-};
-
-struct gr_request {
-       struct usb_request req;
-       struct list_head queue;
-
-       /* Chain of dma descriptors */
-       struct gr_dma_desc *first_desc; /* First in the chain */
-       struct gr_dma_desc *curr_desc; /* Current descriptor */
-       struct gr_dma_desc *last_desc; /* Last in the chain */
-
-       u8 setup; /* Setup packet */
-};
-
-enum gr_ep0state {
-       GR_EP0_DISCONNECT = 0,  /* No host */
-       GR_EP0_SETUP,           /* Between STATUS ack and SETUP report */
-       GR_EP0_IDATA,           /* IN data stage */
-       GR_EP0_ODATA,           /* OUT data stage */
-       GR_EP0_ISTATUS,         /* Status stage after IN data stage */
-       GR_EP0_OSTATUS,         /* Status stage after OUT data stage */
-       GR_EP0_STALL,           /* Data or status stages */
-       GR_EP0_SUSPEND,         /* USB suspend */
-};
-
-struct gr_udc {
-       struct usb_gadget gadget;
-       struct gr_ep epi[GR_MAXEP];
-       struct gr_ep epo[GR_MAXEP];
-       struct usb_gadget_driver *driver;
-       struct dma_pool *desc_pool;
-       struct device *dev;
-
-       enum gr_ep0state ep0state;
-       struct gr_request *ep0reqo;
-       struct gr_request *ep0reqi;
-
-       struct gr_regs __iomem *regs;
-       int irq;
-       int irqi;
-       int irqo;
-
-       unsigned added:1;
-       unsigned irq_enabled:1;
-       unsigned remote_wakeup:1;
-
-       u8 test_mode;
-
-       enum usb_device_state suspended_from;
-
-       unsigned int nepi;
-       unsigned int nepo;
-
-       struct list_head ep_list;
-
-       spinlock_t lock; /* General lock, a.k.a. "dev->lock" in comments */
-
-       struct dentry *dfs_root;
-       struct dentry *dfs_state;
-};
-
-#define to_gr_udc(gadget)      (container_of((gadget), struct gr_udc, gadget))
index fbb32aa6f6909249709adc4c6318b887694fb1bd..d4570744e1064abc9a7fb2bb4311eeac06836d0b 100644 (file)
@@ -3,6 +3,7 @@
 #
 
 ccflags-y                      := -I$(PWD)/drivers/usb/gadget/
+ccflags-y                      += -I$(PWD)/drivers/usb/gadget/udc/
 
 g_zero-y                       := zero.o
 g_audio-y                      := audio.o
diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c
deleted file mode 100644 (file)
index 1629ad7..0000000
+++ /dev/null
@@ -1,3424 +0,0 @@
-/*
- * USB Gadget driver for LPC32xx
- *
- * Authors:
- *    Kevin Wells <kevin.wells@nxp.com>
- *    Mike James
- *    Roland Stigge <stigge@antcom.de>
- *
- * Copyright (C) 2006 Philips Semiconductors
- * Copyright (C) 2009 NXP Semiconductors
- * Copyright (C) 2012 Roland Stigge
- *
- * Note: This driver is based on original work done by Mike James for
- *       the LPC3180.
- *
- * 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 <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/clk.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/i2c.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/workqueue.h>
-#include <linux/of.h>
-#include <linux/usb/isp1301.h>
-
-#include <asm/byteorder.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-#include <asm/irq.h>
-
-#include <mach/platform.h>
-#include <mach/irqs.h>
-#include <mach/board.h>
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#endif
-
-/*
- * USB device configuration structure
- */
-typedef void (*usc_chg_event)(int);
-struct lpc32xx_usbd_cfg {
-       int vbus_drv_pol;   /* 0=active low drive for VBUS via ISP1301 */
-       usc_chg_event conn_chgb; /* Connection change event (optional) */
-       usc_chg_event susp_chgb; /* Suspend/resume event (optional) */
-       usc_chg_event rmwk_chgb; /* Enable/disable remote wakeup */
-};
-
-/*
- * controller driver data structures
- */
-
-/* 16 endpoints (not to be confused with 32 hardware endpoints) */
-#define        NUM_ENDPOINTS   16
-
-/*
- * IRQ indices make reading the code a little easier
- */
-#define IRQ_USB_LP     0
-#define IRQ_USB_HP     1
-#define IRQ_USB_DEVDMA 2
-#define IRQ_USB_ATX    3
-
-#define EP_OUT 0 /* RX (from host) */
-#define EP_IN 1 /* TX (to host) */
-
-/* Returns the interrupt mask for the selected hardware endpoint */
-#define EP_MASK_SEL(ep, dir) (1 << (((ep) * 2) + dir))
-
-#define EP_INT_TYPE 0
-#define EP_ISO_TYPE 1
-#define EP_BLK_TYPE 2
-#define EP_CTL_TYPE 3
-
-/* EP0 states */
-#define WAIT_FOR_SETUP 0 /* Wait for setup packet */
-#define DATA_IN        1 /* Expect dev->host transfer */
-#define DATA_OUT       2 /* Expect host->dev transfer */
-
-/* DD (DMA Descriptor) structure, requires word alignment, this is already
- * defined in the LPC32XX USB device header file, but this version is slightly
- * modified to tag some work data with each DMA descriptor. */
-struct lpc32xx_usbd_dd_gad {
-       u32 dd_next_phy;
-       u32 dd_setup;
-       u32 dd_buffer_addr;
-       u32 dd_status;
-       u32 dd_iso_ps_mem_addr;
-       u32 this_dma;
-       u32 iso_status[6]; /* 5 spare */
-       u32 dd_next_v;
-};
-
-/*
- * Logical endpoint structure
- */
-struct lpc32xx_ep {
-       struct usb_ep           ep;
-       struct list_head        queue;
-       struct lpc32xx_udc      *udc;
-
-       u32                     hwep_num_base; /* Physical hardware EP */
-       u32                     hwep_num; /* Maps to hardware endpoint */
-       u32                     maxpacket;
-       u32                     lep;
-
-       bool                    is_in;
-       bool                    req_pending;
-       u32                     eptype;
-
-       u32                     totalints;
-
-       bool                    wedge;
-};
-
-/*
- * Common UDC structure
- */
-struct lpc32xx_udc {
-       struct usb_gadget       gadget;
-       struct usb_gadget_driver *driver;
-       struct platform_device  *pdev;
-       struct device           *dev;
-       struct dentry           *pde;
-       spinlock_t              lock;
-       struct i2c_client       *isp1301_i2c_client;
-
-       /* Board and device specific */
-       struct lpc32xx_usbd_cfg *board;
-       u32                     io_p_start;
-       u32                     io_p_size;
-       void __iomem            *udp_baseaddr;
-       int                     udp_irq[4];
-       struct clk              *usb_pll_clk;
-       struct clk              *usb_slv_clk;
-       struct clk              *usb_otg_clk;
-
-       /* DMA support */
-       u32                     *udca_v_base;
-       u32                     udca_p_base;
-       struct dma_pool         *dd_cache;
-
-       /* Common EP and control data */
-       u32                     enabled_devints;
-       u32                     enabled_hwepints;
-       u32                     dev_status;
-       u32                     realized_eps;
-
-       /* VBUS detection, pullup, and power flags */
-       u8                      vbus;
-       u8                      last_vbus;
-       int                     pullup;
-       int                     poweron;
-
-       /* Work queues related to I2C support */
-       struct work_struct      pullup_job;
-       struct work_struct      vbus_job;
-       struct work_struct      power_job;
-
-       /* USB device peripheral - various */
-       struct lpc32xx_ep       ep[NUM_ENDPOINTS];
-       bool                    enabled;
-       bool                    clocked;
-       bool                    suspended;
-       bool                    selfpowered;
-       int                     ep0state;
-       atomic_t                enabled_ep_cnt;
-       wait_queue_head_t       ep_disable_wait_queue;
-};
-
-/*
- * Endpoint request
- */
-struct lpc32xx_request {
-       struct usb_request      req;
-       struct list_head        queue;
-       struct lpc32xx_usbd_dd_gad *dd_desc_ptr;
-       bool                    mapped;
-       bool                    send_zlp;
-};
-
-static inline struct lpc32xx_udc *to_udc(struct usb_gadget *g)
-{
-       return container_of(g, struct lpc32xx_udc, gadget);
-}
-
-#define ep_dbg(epp, fmt, arg...) \
-       dev_dbg(epp->udc->dev, "%s: " fmt, __func__, ## arg)
-#define ep_err(epp, fmt, arg...) \
-       dev_err(epp->udc->dev, "%s: " fmt, __func__, ## arg)
-#define ep_info(epp, fmt, arg...) \
-       dev_info(epp->udc->dev, "%s: " fmt, __func__, ## arg)
-#define ep_warn(epp, fmt, arg...) \
-       dev_warn(epp->udc->dev, "%s:" fmt, __func__, ## arg)
-
-#define UDCA_BUFF_SIZE (128)
-
-/* TODO: When the clock framework is introduced in LPC32xx, IO_ADDRESS will
- * be replaced with an inremap()ed pointer
- * */
-#define USB_CTRL               IO_ADDRESS(LPC32XX_CLK_PM_BASE + 0x64)
-
-/* USB_CTRL bit defines */
-#define USB_SLAVE_HCLK_EN      (1 << 24)
-#define USB_HOST_NEED_CLK_EN   (1 << 21)
-#define USB_DEV_NEED_CLK_EN    (1 << 22)
-
-/**********************************************************************
- * USB device controller register offsets
- **********************************************************************/
-
-#define USBD_DEVINTST(x)       ((x) + 0x200)
-#define USBD_DEVINTEN(x)       ((x) + 0x204)
-#define USBD_DEVINTCLR(x)      ((x) + 0x208)
-#define USBD_DEVINTSET(x)      ((x) + 0x20C)
-#define USBD_CMDCODE(x)                ((x) + 0x210)
-#define USBD_CMDDATA(x)                ((x) + 0x214)
-#define USBD_RXDATA(x)         ((x) + 0x218)
-#define USBD_TXDATA(x)         ((x) + 0x21C)
-#define USBD_RXPLEN(x)         ((x) + 0x220)
-#define USBD_TXPLEN(x)         ((x) + 0x224)
-#define USBD_CTRL(x)           ((x) + 0x228)
-#define USBD_DEVINTPRI(x)      ((x) + 0x22C)
-#define USBD_EPINTST(x)                ((x) + 0x230)
-#define USBD_EPINTEN(x)                ((x) + 0x234)
-#define USBD_EPINTCLR(x)       ((x) + 0x238)
-#define USBD_EPINTSET(x)       ((x) + 0x23C)
-#define USBD_EPINTPRI(x)       ((x) + 0x240)
-#define USBD_REEP(x)           ((x) + 0x244)
-#define USBD_EPIND(x)          ((x) + 0x248)
-#define USBD_EPMAXPSIZE(x)     ((x) + 0x24C)
-/* DMA support registers only below */
-/* Set, clear, or get enabled state of the DMA request status. If
- * enabled, an IN or OUT token will start a DMA transfer for the EP */
-#define USBD_DMARST(x)         ((x) + 0x250)
-#define USBD_DMARCLR(x)                ((x) + 0x254)
-#define USBD_DMARSET(x)                ((x) + 0x258)
-/* DMA UDCA head pointer */
-#define USBD_UDCAH(x)          ((x) + 0x280)
-/* EP DMA status, enable, and disable. This is used to specifically
- * enabled or disable DMA for a specific EP */
-#define USBD_EPDMAST(x)                ((x) + 0x284)
-#define USBD_EPDMAEN(x)                ((x) + 0x288)
-#define USBD_EPDMADIS(x)       ((x) + 0x28C)
-/* DMA master interrupts enable and pending interrupts */
-#define USBD_DMAINTST(x)       ((x) + 0x290)
-#define USBD_DMAINTEN(x)       ((x) + 0x294)
-/* DMA end of transfer interrupt enable, disable, status */
-#define USBD_EOTINTST(x)       ((x) + 0x2A0)
-#define USBD_EOTINTCLR(x)      ((x) + 0x2A4)
-#define USBD_EOTINTSET(x)      ((x) + 0x2A8)
-/* New DD request interrupt enable, disable, status */
-#define USBD_NDDRTINTST(x)     ((x) + 0x2AC)
-#define USBD_NDDRTINTCLR(x)    ((x) + 0x2B0)
-#define USBD_NDDRTINTSET(x)    ((x) + 0x2B4)
-/* DMA error interrupt enable, disable, status */
-#define USBD_SYSERRTINTST(x)   ((x) + 0x2B8)
-#define USBD_SYSERRTINTCLR(x)  ((x) + 0x2BC)
-#define USBD_SYSERRTINTSET(x)  ((x) + 0x2C0)
-
-/**********************************************************************
- * USBD_DEVINTST/USBD_DEVINTEN/USBD_DEVINTCLR/USBD_DEVINTSET/
- * USBD_DEVINTPRI register definitions
- **********************************************************************/
-#define USBD_ERR_INT           (1 << 9)
-#define USBD_EP_RLZED          (1 << 8)
-#define USBD_TXENDPKT          (1 << 7)
-#define USBD_RXENDPKT          (1 << 6)
-#define USBD_CDFULL            (1 << 5)
-#define USBD_CCEMPTY           (1 << 4)
-#define USBD_DEV_STAT          (1 << 3)
-#define USBD_EP_SLOW           (1 << 2)
-#define USBD_EP_FAST           (1 << 1)
-#define USBD_FRAME             (1 << 0)
-
-/**********************************************************************
- * USBD_EPINTST/USBD_EPINTEN/USBD_EPINTCLR/USBD_EPINTSET/
- * USBD_EPINTPRI register definitions
- **********************************************************************/
-/* End point selection macro (RX) */
-#define USBD_RX_EP_SEL(e)      (1 << ((e) << 1))
-
-/* End point selection macro (TX) */
-#define USBD_TX_EP_SEL(e)      (1 << (((e) << 1) + 1))
-
-/**********************************************************************
- * USBD_REEP/USBD_DMARST/USBD_DMARCLR/USBD_DMARSET/USBD_EPDMAST/
- * USBD_EPDMAEN/USBD_EPDMADIS/
- * USBD_NDDRTINTST/USBD_NDDRTINTCLR/USBD_NDDRTINTSET/
- * USBD_EOTINTST/USBD_EOTINTCLR/USBD_EOTINTSET/
- * USBD_SYSERRTINTST/USBD_SYSERRTINTCLR/USBD_SYSERRTINTSET
- * register definitions
- **********************************************************************/
-/* Endpoint selection macro */
-#define USBD_EP_SEL(e)         (1 << (e))
-
-/**********************************************************************
- * SBD_DMAINTST/USBD_DMAINTEN
- **********************************************************************/
-#define USBD_SYS_ERR_INT       (1 << 2)
-#define USBD_NEW_DD_INT                (1 << 1)
-#define USBD_EOT_INT           (1 << 0)
-
-/**********************************************************************
- * USBD_RXPLEN register definitions
- **********************************************************************/
-#define USBD_PKT_RDY           (1 << 11)
-#define USBD_DV                        (1 << 10)
-#define USBD_PK_LEN_MASK       0x3FF
-
-/**********************************************************************
- * USBD_CTRL register definitions
- **********************************************************************/
-#define USBD_LOG_ENDPOINT(e)   ((e) << 2)
-#define USBD_WR_EN             (1 << 1)
-#define USBD_RD_EN             (1 << 0)
-
-/**********************************************************************
- * USBD_CMDCODE register definitions
- **********************************************************************/
-#define USBD_CMD_CODE(c)       ((c) << 16)
-#define USBD_CMD_PHASE(p)      ((p) << 8)
-
-/**********************************************************************
- * USBD_DMARST/USBD_DMARCLR/USBD_DMARSET register definitions
- **********************************************************************/
-#define USBD_DMAEP(e)          (1 << (e))
-
-/* DD (DMA Descriptor) structure, requires word alignment */
-struct lpc32xx_usbd_dd {
-       u32 *dd_next;
-       u32 dd_setup;
-       u32 dd_buffer_addr;
-       u32 dd_status;
-       u32 dd_iso_ps_mem_addr;
-};
-
-/* dd_setup bit defines */
-#define DD_SETUP_ATLE_DMA_MODE 0x01
-#define DD_SETUP_NEXT_DD_VALID 0x04
-#define DD_SETUP_ISO_EP                0x10
-#define DD_SETUP_PACKETLEN(n)  (((n) & 0x7FF) << 5)
-#define DD_SETUP_DMALENBYTES(n)        (((n) & 0xFFFF) << 16)
-
-/* dd_status bit defines */
-#define DD_STATUS_DD_RETIRED   0x01
-#define DD_STATUS_STS_MASK     0x1E
-#define DD_STATUS_STS_NS       0x00 /* Not serviced */
-#define DD_STATUS_STS_BS       0x02 /* Being serviced */
-#define DD_STATUS_STS_NC       0x04 /* Normal completion */
-#define DD_STATUS_STS_DUR      0x06 /* Data underrun (short packet) */
-#define DD_STATUS_STS_DOR      0x08 /* Data overrun */
-#define DD_STATUS_STS_SE       0x12 /* System error */
-#define DD_STATUS_PKT_VAL      0x20 /* Packet valid */
-#define DD_STATUS_LSB_EX       0x40 /* LS byte extracted (ATLE) */
-#define DD_STATUS_MSB_EX       0x80 /* MS byte extracted (ATLE) */
-#define DD_STATUS_MLEN(n)      (((n) >> 8) & 0x3F)
-#define DD_STATUS_CURDMACNT(n) (((n) >> 16) & 0xFFFF)
-
-/*
- *
- * Protocol engine bits below
- *
- */
-/* Device Interrupt Bit Definitions */
-#define FRAME_INT              0x00000001
-#define EP_FAST_INT            0x00000002
-#define EP_SLOW_INT            0x00000004
-#define DEV_STAT_INT           0x00000008
-#define CCEMTY_INT             0x00000010
-#define CDFULL_INT             0x00000020
-#define RxENDPKT_INT           0x00000040
-#define TxENDPKT_INT           0x00000080
-#define EP_RLZED_INT           0x00000100
-#define ERR_INT                        0x00000200
-
-/* Rx & Tx Packet Length Definitions */
-#define PKT_LNGTH_MASK         0x000003FF
-#define PKT_DV                 0x00000400
-#define PKT_RDY                        0x00000800
-
-/* USB Control Definitions */
-#define CTRL_RD_EN             0x00000001
-#define CTRL_WR_EN             0x00000002
-
-/* Command Codes */
-#define CMD_SET_ADDR           0x00D00500
-#define CMD_CFG_DEV            0x00D80500
-#define CMD_SET_MODE           0x00F30500
-#define CMD_RD_FRAME           0x00F50500
-#define DAT_RD_FRAME           0x00F50200
-#define CMD_RD_TEST            0x00FD0500
-#define DAT_RD_TEST            0x00FD0200
-#define CMD_SET_DEV_STAT       0x00FE0500
-#define CMD_GET_DEV_STAT       0x00FE0500
-#define DAT_GET_DEV_STAT       0x00FE0200
-#define CMD_GET_ERR_CODE       0x00FF0500
-#define DAT_GET_ERR_CODE       0x00FF0200
-#define CMD_RD_ERR_STAT                0x00FB0500
-#define DAT_RD_ERR_STAT                0x00FB0200
-#define DAT_WR_BYTE(x)         (0x00000100 | ((x) << 16))
-#define CMD_SEL_EP(x)          (0x00000500 | ((x) << 16))
-#define DAT_SEL_EP(x)          (0x00000200 | ((x) << 16))
-#define CMD_SEL_EP_CLRI(x)     (0x00400500 | ((x) << 16))
-#define DAT_SEL_EP_CLRI(x)     (0x00400200 | ((x) << 16))
-#define CMD_SET_EP_STAT(x)     (0x00400500 | ((x) << 16))
-#define CMD_CLR_BUF            0x00F20500
-#define DAT_CLR_BUF            0x00F20200
-#define CMD_VALID_BUF          0x00FA0500
-
-/* Device Address Register Definitions */
-#define DEV_ADDR_MASK          0x7F
-#define DEV_EN                 0x80
-
-/* Device Configure Register Definitions */
-#define CONF_DVICE             0x01
-
-/* Device Mode Register Definitions */
-#define AP_CLK                 0x01
-#define INAK_CI                        0x02
-#define INAK_CO                        0x04
-#define INAK_II                        0x08
-#define INAK_IO                        0x10
-#define INAK_BI                        0x20
-#define INAK_BO                        0x40
-
-/* Device Status Register Definitions */
-#define DEV_CON                        0x01
-#define DEV_CON_CH             0x02
-#define DEV_SUS                        0x04
-#define DEV_SUS_CH             0x08
-#define DEV_RST                        0x10
-
-/* Error Code Register Definitions */
-#define ERR_EC_MASK            0x0F
-#define ERR_EA                 0x10
-
-/* Error Status Register Definitions */
-#define ERR_PID                        0x01
-#define ERR_UEPKT              0x02
-#define ERR_DCRC               0x04
-#define ERR_TIMOUT             0x08
-#define ERR_EOP                        0x10
-#define ERR_B_OVRN             0x20
-#define ERR_BTSTF              0x40
-#define ERR_TGL                        0x80
-
-/* Endpoint Select Register Definitions */
-#define EP_SEL_F               0x01
-#define EP_SEL_ST              0x02
-#define EP_SEL_STP             0x04
-#define EP_SEL_PO              0x08
-#define EP_SEL_EPN             0x10
-#define EP_SEL_B_1_FULL                0x20
-#define EP_SEL_B_2_FULL                0x40
-
-/* Endpoint Status Register Definitions */
-#define EP_STAT_ST             0x01
-#define EP_STAT_DA             0x20
-#define EP_STAT_RF_MO          0x40
-#define EP_STAT_CND_ST         0x80
-
-/* Clear Buffer Register Definitions */
-#define CLR_BUF_PO             0x01
-
-/* DMA Interrupt Bit Definitions */
-#define EOT_INT                        0x01
-#define NDD_REQ_INT            0x02
-#define SYS_ERR_INT            0x04
-
-#define        DRIVER_VERSION  "1.03"
-static const char driver_name[] = "lpc32xx_udc";
-
-/*
- *
- * proc interface support
- *
- */
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-static char *epnames[] = {"INT", "ISO", "BULK", "CTRL"};
-static const char debug_filename[] = "driver/udc";
-
-static void proc_ep_show(struct seq_file *s, struct lpc32xx_ep *ep)
-{
-       struct lpc32xx_request *req;
-
-       seq_printf(s, "\n");
-       seq_printf(s, "%12s, maxpacket %4d %3s",
-                       ep->ep.name, ep->ep.maxpacket,
-                       ep->is_in ? "in" : "out");
-       seq_printf(s, " type %4s", epnames[ep->eptype]);
-       seq_printf(s, " ints: %12d", ep->totalints);
-
-       if (list_empty(&ep->queue))
-               seq_printf(s, "\t(queue empty)\n");
-       else {
-               list_for_each_entry(req, &ep->queue, queue) {
-                       u32 length = req->req.actual;
-
-                       seq_printf(s, "\treq %p len %d/%d buf %p\n",
-                                  &req->req, length,
-                                  req->req.length, req->req.buf);
-               }
-       }
-}
-
-static int proc_udc_show(struct seq_file *s, void *unused)
-{
-       struct lpc32xx_udc *udc = s->private;
-       struct lpc32xx_ep *ep;
-       unsigned long flags;
-
-       seq_printf(s, "%s: version %s\n", driver_name, DRIVER_VERSION);
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       seq_printf(s, "vbus %s, pullup %s, %s powered%s, gadget %s\n\n",
-                  udc->vbus ? "present" : "off",
-                  udc->enabled ? (udc->vbus ? "active" : "enabled") :
-                  "disabled",
-                  udc->selfpowered ? "self" : "VBUS",
-                  udc->suspended ? ", suspended" : "",
-                  udc->driver ? udc->driver->driver.name : "(none)");
-
-       if (udc->enabled && udc->vbus) {
-               proc_ep_show(s, &udc->ep[0]);
-               list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list)
-                       proc_ep_show(s, ep);
-       }
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-static int proc_udc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, proc_udc_show, PDE_DATA(inode));
-}
-
-static const struct file_operations proc_ops = {
-       .owner          = THIS_MODULE,
-       .open           = proc_udc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static void create_debug_file(struct lpc32xx_udc *udc)
-{
-       udc->pde = debugfs_create_file(debug_filename, 0, NULL, udc, &proc_ops);
-}
-
-static void remove_debug_file(struct lpc32xx_udc *udc)
-{
-       if (udc->pde)
-               debugfs_remove(udc->pde);
-}
-
-#else
-static inline void create_debug_file(struct lpc32xx_udc *udc) {}
-static inline void remove_debug_file(struct lpc32xx_udc *udc) {}
-#endif
-
-/* Primary initialization sequence for the ISP1301 transceiver */
-static void isp1301_udc_configure(struct lpc32xx_udc *udc)
-{
-       /* LPC32XX only supports DAT_SE0 USB mode */
-       /* This sequence is important */
-
-       /* Disable transparent UART mode first */
-       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-               (ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR),
-               MC1_UART_EN);
-
-       /* Set full speed and SE0 mode */
-       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-               (ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), ~0);
-       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-               ISP1301_I2C_MODE_CONTROL_1, (MC1_SPEED_REG | MC1_DAT_SE0));
-
-       /*
-        * The PSW_OE enable bit state is reversed in the ISP1301 User's Guide
-        */
-       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-               (ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR), ~0);
-       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-               ISP1301_I2C_MODE_CONTROL_2, (MC2_BI_DI | MC2_SPD_SUSP_CTRL));
-
-       /* Driver VBUS_DRV high or low depending on board setup */
-       if (udc->board->vbus_drv_pol != 0)
-               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-                       ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV);
-       else
-               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-                       ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
-                       OTG1_VBUS_DRV);
-
-       /* Bi-directional mode with suspend control
-        * Enable both pulldowns for now - the pullup will be enable when VBUS
-        * is detected */
-       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-               (ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), ~0);
-       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-               ISP1301_I2C_OTG_CONTROL_1,
-               (0 | OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));
-
-       /* Discharge VBUS (just in case) */
-       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-               ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DISCHRG);
-       msleep(1);
-       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-               (ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR),
-               OTG1_VBUS_DISCHRG);
-
-       /* Clear and enable VBUS high edge interrupt */
-       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-               ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
-       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-               ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
-       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-               ISP1301_I2C_INTERRUPT_FALLING, INT_VBUS_VLD);
-       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-               ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
-       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-               ISP1301_I2C_INTERRUPT_RISING, INT_VBUS_VLD);
-
-       /* Enable usb_need_clk clock after transceiver is initialized */
-       writel((readl(USB_CTRL) | USB_DEV_NEED_CLK_EN), USB_CTRL);
-
-       dev_info(udc->dev, "ISP1301 Vendor ID  : 0x%04x\n",
-                i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00));
-       dev_info(udc->dev, "ISP1301 Product ID : 0x%04x\n",
-                i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x02));
-       dev_info(udc->dev, "ISP1301 Version ID : 0x%04x\n",
-                i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x14));
-}
-
-/* Enables or disables the USB device pullup via the ISP1301 transceiver */
-static void isp1301_pullup_set(struct lpc32xx_udc *udc)
-{
-       if (udc->pullup)
-               /* Enable pullup for bus signalling */
-               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-                       ISP1301_I2C_OTG_CONTROL_1, OTG1_DP_PULLUP);
-       else
-               /* Enable pullup for bus signalling */
-               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-                       ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
-                       OTG1_DP_PULLUP);
-}
-
-static void pullup_work(struct work_struct *work)
-{
-       struct lpc32xx_udc *udc =
-               container_of(work, struct lpc32xx_udc, pullup_job);
-
-       isp1301_pullup_set(udc);
-}
-
-static void isp1301_pullup_enable(struct lpc32xx_udc *udc, int en_pullup,
-                                 int block)
-{
-       if (en_pullup == udc->pullup)
-               return;
-
-       udc->pullup = en_pullup;
-       if (block)
-               isp1301_pullup_set(udc);
-       else
-               /* defer slow i2c pull up setting */
-               schedule_work(&udc->pullup_job);
-}
-
-#ifdef CONFIG_PM
-/* Powers up or down the ISP1301 transceiver */
-static void isp1301_set_powerstate(struct lpc32xx_udc *udc, int enable)
-{
-       if (enable != 0)
-               /* Power up ISP1301 - this ISP1301 will automatically wakeup
-                  when VBUS is detected */
-               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-                       ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR,
-                       MC2_GLOBAL_PWR_DN);
-       else
-               /* Power down ISP1301 */
-               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-                       ISP1301_I2C_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
-}
-
-static void power_work(struct work_struct *work)
-{
-       struct lpc32xx_udc *udc =
-               container_of(work, struct lpc32xx_udc, power_job);
-
-       isp1301_set_powerstate(udc, udc->poweron);
-}
-#endif
-
-/*
- *
- * USB protocol engine command/data read/write helper functions
- *
- */
-/* Issues a single command to the USB device state machine */
-static void udc_protocol_cmd_w(struct lpc32xx_udc *udc, u32 cmd)
-{
-       u32 pass = 0;
-       int to;
-
-       /* EP may lock on CLRI if this read isn't done */
-       u32 tmp = readl(USBD_DEVINTST(udc->udp_baseaddr));
-       (void) tmp;
-
-       while (pass == 0) {
-               writel(USBD_CCEMPTY, USBD_DEVINTCLR(udc->udp_baseaddr));
-
-               /* Write command code */
-               writel(cmd, USBD_CMDCODE(udc->udp_baseaddr));
-               to = 10000;
-               while (((readl(USBD_DEVINTST(udc->udp_baseaddr)) &
-                        USBD_CCEMPTY) == 0) && (to > 0)) {
-                       to--;
-               }
-
-               if (to > 0)
-                       pass = 1;
-
-               cpu_relax();
-       }
-}
-
-/* Issues 2 commands (or command and data) to the USB device state machine */
-static inline void udc_protocol_cmd_data_w(struct lpc32xx_udc *udc, u32 cmd,
-                                          u32 data)
-{
-       udc_protocol_cmd_w(udc, cmd);
-       udc_protocol_cmd_w(udc, data);
-}
-
-/* Issues a single command to the USB device state machine and reads
- * response data */
-static u32 udc_protocol_cmd_r(struct lpc32xx_udc *udc, u32 cmd)
-{
-       u32 tmp;
-       int to = 1000;
-
-       /* Write a command and read data from the protocol engine */
-       writel((USBD_CDFULL | USBD_CCEMPTY),
-                    USBD_DEVINTCLR(udc->udp_baseaddr));
-
-       /* Write command code */
-       udc_protocol_cmd_w(udc, cmd);
-
-       tmp = readl(USBD_DEVINTST(udc->udp_baseaddr));
-       while ((!(readl(USBD_DEVINTST(udc->udp_baseaddr)) & USBD_CDFULL))
-              && (to > 0))
-               to--;
-       if (!to)
-               dev_dbg(udc->dev,
-                       "Protocol engine didn't receive response (CDFULL)\n");
-
-       return readl(USBD_CMDDATA(udc->udp_baseaddr));
-}
-
-/*
- *
- * USB device interrupt mask support functions
- *
- */
-/* Enable one or more USB device interrupts */
-static inline void uda_enable_devint(struct lpc32xx_udc *udc, u32 devmask)
-{
-       udc->enabled_devints |= devmask;
-       writel(udc->enabled_devints, USBD_DEVINTEN(udc->udp_baseaddr));
-}
-
-/* Disable one or more USB device interrupts */
-static inline void uda_disable_devint(struct lpc32xx_udc *udc, u32 mask)
-{
-       udc->enabled_devints &= ~mask;
-       writel(udc->enabled_devints, USBD_DEVINTEN(udc->udp_baseaddr));
-}
-
-/* Clear one or more USB device interrupts */
-static inline void uda_clear_devint(struct lpc32xx_udc *udc, u32 mask)
-{
-       writel(mask, USBD_DEVINTCLR(udc->udp_baseaddr));
-}
-
-/*
- *
- * Endpoint interrupt disable/enable functions
- *
- */
-/* Enable one or more USB endpoint interrupts */
-static void uda_enable_hwepint(struct lpc32xx_udc *udc, u32 hwep)
-{
-       udc->enabled_hwepints |= (1 << hwep);
-       writel(udc->enabled_hwepints, USBD_EPINTEN(udc->udp_baseaddr));
-}
-
-/* Disable one or more USB endpoint interrupts */
-static void uda_disable_hwepint(struct lpc32xx_udc *udc, u32 hwep)
-{
-       udc->enabled_hwepints &= ~(1 << hwep);
-       writel(udc->enabled_hwepints, USBD_EPINTEN(udc->udp_baseaddr));
-}
-
-/* Clear one or more USB endpoint interrupts */
-static inline void uda_clear_hwepint(struct lpc32xx_udc *udc, u32 hwep)
-{
-       writel((1 << hwep), USBD_EPINTCLR(udc->udp_baseaddr));
-}
-
-/* Enable DMA for the HW channel */
-static inline void udc_ep_dma_enable(struct lpc32xx_udc *udc, u32 hwep)
-{
-       writel((1 << hwep), USBD_EPDMAEN(udc->udp_baseaddr));
-}
-
-/* Disable DMA for the HW channel */
-static inline void udc_ep_dma_disable(struct lpc32xx_udc *udc, u32 hwep)
-{
-       writel((1 << hwep), USBD_EPDMADIS(udc->udp_baseaddr));
-}
-
-/*
- *
- * Endpoint realize/unrealize functions
- *
- */
-/* Before an endpoint can be used, it needs to be realized
- * in the USB protocol engine - this realizes the endpoint.
- * The interrupt (FIFO or DMA) is not enabled with this function */
-static void udc_realize_hwep(struct lpc32xx_udc *udc, u32 hwep,
-                            u32 maxpacket)
-{
-       int to = 1000;
-
-       writel(USBD_EP_RLZED, USBD_DEVINTCLR(udc->udp_baseaddr));
-       writel(hwep, USBD_EPIND(udc->udp_baseaddr));
-       udc->realized_eps |= (1 << hwep);
-       writel(udc->realized_eps, USBD_REEP(udc->udp_baseaddr));
-       writel(maxpacket, USBD_EPMAXPSIZE(udc->udp_baseaddr));
-
-       /* Wait until endpoint is realized in hardware */
-       while ((!(readl(USBD_DEVINTST(udc->udp_baseaddr)) &
-                 USBD_EP_RLZED)) && (to > 0))
-               to--;
-       if (!to)
-               dev_dbg(udc->dev, "EP not correctly realized in hardware\n");
-
-       writel(USBD_EP_RLZED, USBD_DEVINTCLR(udc->udp_baseaddr));
-}
-
-/* Unrealize an EP */
-static void udc_unrealize_hwep(struct lpc32xx_udc *udc, u32 hwep)
-{
-       udc->realized_eps &= ~(1 << hwep);
-       writel(udc->realized_eps, USBD_REEP(udc->udp_baseaddr));
-}
-
-/*
- *
- * Endpoint support functions
- *
- */
-/* Select and clear endpoint interrupt */
-static u32 udc_selep_clrint(struct lpc32xx_udc *udc, u32 hwep)
-{
-       udc_protocol_cmd_w(udc, CMD_SEL_EP_CLRI(hwep));
-       return udc_protocol_cmd_r(udc, DAT_SEL_EP_CLRI(hwep));
-}
-
-/* Disables the endpoint in the USB protocol engine */
-static void udc_disable_hwep(struct lpc32xx_udc *udc, u32 hwep)
-{
-       udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep),
-                               DAT_WR_BYTE(EP_STAT_DA));
-}
-
-/* Stalls the endpoint - endpoint will return STALL */
-static void udc_stall_hwep(struct lpc32xx_udc *udc, u32 hwep)
-{
-       udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep),
-                               DAT_WR_BYTE(EP_STAT_ST));
-}
-
-/* Clear stall or reset endpoint */
-static void udc_clrstall_hwep(struct lpc32xx_udc *udc, u32 hwep)
-{
-       udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep),
-                               DAT_WR_BYTE(0));
-}
-
-/* Select an endpoint for endpoint status, clear, validate */
-static void udc_select_hwep(struct lpc32xx_udc *udc, u32 hwep)
-{
-       udc_protocol_cmd_w(udc, CMD_SEL_EP(hwep));
-}
-
-/*
- *
- * Endpoint buffer management functions
- *
- */
-/* Clear the current endpoint's buffer */
-static void udc_clr_buffer_hwep(struct lpc32xx_udc *udc, u32 hwep)
-{
-       udc_select_hwep(udc, hwep);
-       udc_protocol_cmd_w(udc, CMD_CLR_BUF);
-}
-
-/* Validate the current endpoint's buffer */
-static void udc_val_buffer_hwep(struct lpc32xx_udc *udc, u32 hwep)
-{
-       udc_select_hwep(udc, hwep);
-       udc_protocol_cmd_w(udc, CMD_VALID_BUF);
-}
-
-static inline u32 udc_clearep_getsts(struct lpc32xx_udc *udc, u32 hwep)
-{
-       /* Clear EP interrupt */
-       uda_clear_hwepint(udc, hwep);
-       return udc_selep_clrint(udc, hwep);
-}
-
-/*
- *
- * USB EP DMA support
- *
- */
-/* Allocate a DMA Descriptor */
-static struct lpc32xx_usbd_dd_gad *udc_dd_alloc(struct lpc32xx_udc *udc)
-{
-       dma_addr_t                      dma;
-       struct lpc32xx_usbd_dd_gad      *dd;
-
-       dd = (struct lpc32xx_usbd_dd_gad *) dma_pool_alloc(
-                       udc->dd_cache, (GFP_KERNEL | GFP_DMA), &dma);
-       if (dd)
-               dd->this_dma = dma;
-
-       return dd;
-}
-
-/* Free a DMA Descriptor */
-static void udc_dd_free(struct lpc32xx_udc *udc, struct lpc32xx_usbd_dd_gad *dd)
-{
-       dma_pool_free(udc->dd_cache, dd, dd->this_dma);
-}
-
-/*
- *
- * USB setup and shutdown functions
- *
- */
-/* Enables or disables most of the USB system clocks when low power mode is
- * needed. Clocks are typically started on a connection event, and disabled
- * when a cable is disconnected */
-static void udc_clk_set(struct lpc32xx_udc *udc, int enable)
-{
-       if (enable != 0) {
-               if (udc->clocked)
-                       return;
-
-               udc->clocked = 1;
-
-               /* 48MHz PLL up */
-               clk_enable(udc->usb_pll_clk);
-
-               /* Enable the USB device clock */
-               writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN,
-                            USB_CTRL);
-
-               clk_enable(udc->usb_otg_clk);
-       } else {
-               if (!udc->clocked)
-                       return;
-
-               udc->clocked = 0;
-
-               /* Never disable the USB_HCLK during normal operation */
-
-               /* 48MHz PLL dpwn */
-               clk_disable(udc->usb_pll_clk);
-
-               /* Disable the USB device clock */
-               writel(readl(USB_CTRL) & ~USB_DEV_NEED_CLK_EN,
-                            USB_CTRL);
-
-               clk_disable(udc->usb_otg_clk);
-       }
-}
-
-/* Set/reset USB device address */
-static void udc_set_address(struct lpc32xx_udc *udc, u32 addr)
-{
-       /* Address will be latched at the end of the status phase, or
-          latched immediately if function is called twice */
-       udc_protocol_cmd_data_w(udc, CMD_SET_ADDR,
-                               DAT_WR_BYTE(DEV_EN | addr));
-}
-
-/* Setup up a IN request for DMA transfer - this consists of determining the
- * list of DMA addresses for the transfer, allocating DMA Descriptors,
- * installing the DD into the UDCA, and then enabling the DMA for that EP */
-static int udc_ep_in_req_dma(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
-{
-       struct lpc32xx_request *req;
-       u32 hwep = ep->hwep_num;
-
-       ep->req_pending = 1;
-
-       /* There will always be a request waiting here */
-       req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
-
-       /* Place the DD Descriptor into the UDCA */
-       udc->udca_v_base[hwep] = req->dd_desc_ptr->this_dma;
-
-       /* Enable DMA and interrupt for the HW EP */
-       udc_ep_dma_enable(udc, hwep);
-
-       /* Clear ZLP if last packet is not of MAXP size */
-       if (req->req.length % ep->ep.maxpacket)
-               req->send_zlp = 0;
-
-       return 0;
-}
-
-/* Setup up a OUT request for DMA transfer - this consists of determining the
- * list of DMA addresses for the transfer, allocating DMA Descriptors,
- * installing the DD into the UDCA, and then enabling the DMA for that EP */
-static int udc_ep_out_req_dma(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
-{
-       struct lpc32xx_request *req;
-       u32 hwep = ep->hwep_num;
-
-       ep->req_pending = 1;
-
-       /* There will always be a request waiting here */
-       req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
-
-       /* Place the DD Descriptor into the UDCA */
-       udc->udca_v_base[hwep] = req->dd_desc_ptr->this_dma;
-
-       /* Enable DMA and interrupt for the HW EP */
-       udc_ep_dma_enable(udc, hwep);
-       return 0;
-}
-
-static void udc_disable(struct lpc32xx_udc *udc)
-{
-       u32 i;
-
-       /* Disable device */
-       udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(0));
-       udc_protocol_cmd_data_w(udc, CMD_SET_DEV_STAT, DAT_WR_BYTE(0));
-
-       /* Disable all device interrupts (including EP0) */
-       uda_disable_devint(udc, 0x3FF);
-
-       /* Disable and reset all endpoint interrupts */
-       for (i = 0; i < 32; i++) {
-               uda_disable_hwepint(udc, i);
-               uda_clear_hwepint(udc, i);
-               udc_disable_hwep(udc, i);
-               udc_unrealize_hwep(udc, i);
-               udc->udca_v_base[i] = 0;
-
-               /* Disable and clear all interrupts and DMA */
-               udc_ep_dma_disable(udc, i);
-               writel((1 << i), USBD_EOTINTCLR(udc->udp_baseaddr));
-               writel((1 << i), USBD_NDDRTINTCLR(udc->udp_baseaddr));
-               writel((1 << i), USBD_SYSERRTINTCLR(udc->udp_baseaddr));
-               writel((1 << i), USBD_DMARCLR(udc->udp_baseaddr));
-       }
-
-       /* Disable DMA interrupts */
-       writel(0, USBD_DMAINTEN(udc->udp_baseaddr));
-
-       writel(0, USBD_UDCAH(udc->udp_baseaddr));
-}
-
-static void udc_enable(struct lpc32xx_udc *udc)
-{
-       u32 i;
-       struct lpc32xx_ep *ep = &udc->ep[0];
-
-       /* Start with known state */
-       udc_disable(udc);
-
-       /* Enable device */
-       udc_protocol_cmd_data_w(udc, CMD_SET_DEV_STAT, DAT_WR_BYTE(DEV_CON));
-
-       /* EP interrupts on high priority, FRAME interrupt on low priority */
-       writel(USBD_EP_FAST, USBD_DEVINTPRI(udc->udp_baseaddr));
-       writel(0xFFFF, USBD_EPINTPRI(udc->udp_baseaddr));
-
-       /* Clear any pending device interrupts */
-       writel(0x3FF, USBD_DEVINTCLR(udc->udp_baseaddr));
-
-       /* Setup UDCA - not yet used (DMA) */
-       writel(udc->udca_p_base, USBD_UDCAH(udc->udp_baseaddr));
-
-       /* Only enable EP0 in and out for now, EP0 only works in FIFO mode */
-       for (i = 0; i <= 1; i++) {
-               udc_realize_hwep(udc, i, ep->ep.maxpacket);
-               uda_enable_hwepint(udc, i);
-               udc_select_hwep(udc, i);
-               udc_clrstall_hwep(udc, i);
-               udc_clr_buffer_hwep(udc, i);
-       }
-
-       /* Device interrupt setup */
-       uda_clear_devint(udc, (USBD_ERR_INT | USBD_DEV_STAT | USBD_EP_SLOW |
-                              USBD_EP_FAST));
-       uda_enable_devint(udc, (USBD_ERR_INT | USBD_DEV_STAT | USBD_EP_SLOW |
-                               USBD_EP_FAST));
-
-       /* Set device address to 0 - called twice to force a latch in the USB
-          engine without the need of a setup packet status closure */
-       udc_set_address(udc, 0);
-       udc_set_address(udc, 0);
-
-       /* Enable master DMA interrupts */
-       writel((USBD_SYS_ERR_INT | USBD_EOT_INT),
-                    USBD_DMAINTEN(udc->udp_baseaddr));
-
-       udc->dev_status = 0;
-}
-
-/*
- *
- * USB device board specific events handled via callbacks
- *
- */
-/* Connection change event - notify board function of change */
-static void uda_power_event(struct lpc32xx_udc *udc, u32 conn)
-{
-       /* Just notify of a connection change event (optional) */
-       if (udc->board->conn_chgb != NULL)
-               udc->board->conn_chgb(conn);
-}
-
-/* Suspend/resume event - notify board function of change */
-static void uda_resm_susp_event(struct lpc32xx_udc *udc, u32 conn)
-{
-       /* Just notify of a Suspend/resume change event (optional) */
-       if (udc->board->susp_chgb != NULL)
-               udc->board->susp_chgb(conn);
-
-       if (conn)
-               udc->suspended = 0;
-       else
-               udc->suspended = 1;
-}
-
-/* Remote wakeup enable/disable - notify board function of change */
-static void uda_remwkp_cgh(struct lpc32xx_udc *udc)
-{
-       if (udc->board->rmwk_chgb != NULL)
-               udc->board->rmwk_chgb(udc->dev_status &
-                                     (1 << USB_DEVICE_REMOTE_WAKEUP));
-}
-
-/* Reads data from FIFO, adjusts for alignment and data size */
-static void udc_pop_fifo(struct lpc32xx_udc *udc, u8 *data, u32 bytes)
-{
-       int n, i, bl;
-       u16 *p16;
-       u32 *p32, tmp, cbytes;
-
-       /* Use optimal data transfer method based on source address and size */
-       switch (((u32) data) & 0x3) {
-       case 0: /* 32-bit aligned */
-               p32 = (u32 *) data;
-               cbytes = (bytes & ~0x3);
-
-               /* Copy 32-bit aligned data first */
-               for (n = 0; n < cbytes; n += 4)
-                       *p32++ = readl(USBD_RXDATA(udc->udp_baseaddr));
-
-               /* Handle any remaining bytes */
-               bl = bytes - cbytes;
-               if (bl) {
-                       tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
-                       for (n = 0; n < bl; n++)
-                               data[cbytes + n] = ((tmp >> (n * 8)) & 0xFF);
-
-               }
-               break;
-
-       case 1: /* 8-bit aligned */
-       case 3:
-               /* Each byte has to be handled independently */
-               for (n = 0; n < bytes; n += 4) {
-                       tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
-
-                       bl = bytes - n;
-                       if (bl > 3)
-                               bl = 3;
-
-                       for (i = 0; i < bl; i++)
-                               data[n + i] = (u8) ((tmp >> (n * 8)) & 0xFF);
-               }
-               break;
-
-       case 2: /* 16-bit aligned */
-               p16 = (u16 *) data;
-               cbytes = (bytes & ~0x3);
-
-               /* Copy 32-bit sized objects first with 16-bit alignment */
-               for (n = 0; n < cbytes; n += 4) {
-                       tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
-                       *p16++ = (u16)(tmp & 0xFFFF);
-                       *p16++ = (u16)((tmp >> 16) & 0xFFFF);
-               }
-
-               /* Handle any remaining bytes */
-               bl = bytes - cbytes;
-               if (bl) {
-                       tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
-                       for (n = 0; n < bl; n++)
-                               data[cbytes + n] = ((tmp >> (n * 8)) & 0xFF);
-               }
-               break;
-       }
-}
-
-/* Read data from the FIFO for an endpoint. This function is for endpoints (such
- * as EP0) that don't use DMA. This function should only be called if a packet
- * is known to be ready to read for the endpoint. Note that the endpoint must
- * be selected in the protocol engine prior to this call. */
-static u32 udc_read_hwep(struct lpc32xx_udc *udc, u32 hwep, u32 *data,
-                        u32 bytes)
-{
-       u32 tmpv;
-       int to = 1000;
-       u32 tmp, hwrep = ((hwep & 0x1E) << 1) | CTRL_RD_EN;
-
-       /* Setup read of endpoint */
-       writel(hwrep, USBD_CTRL(udc->udp_baseaddr));
-
-       /* Wait until packet is ready */
-       while ((((tmpv = readl(USBD_RXPLEN(udc->udp_baseaddr))) &
-                PKT_RDY) == 0) && (to > 0))
-               to--;
-       if (!to)
-               dev_dbg(udc->dev, "No packet ready on FIFO EP read\n");
-
-       /* Mask out count */
-       tmp = tmpv & PKT_LNGTH_MASK;
-       if (bytes < tmp)
-               tmp = bytes;
-
-       if ((tmp > 0) && (data != NULL))
-               udc_pop_fifo(udc, (u8 *) data, tmp);
-
-       writel(((hwep & 0x1E) << 1), USBD_CTRL(udc->udp_baseaddr));
-
-       /* Clear the buffer */
-       udc_clr_buffer_hwep(udc, hwep);
-
-       return tmp;
-}
-
-/* Stuffs data into the FIFO, adjusts for alignment and data size */
-static void udc_stuff_fifo(struct lpc32xx_udc *udc, u8 *data, u32 bytes)
-{
-       int n, i, bl;
-       u16 *p16;
-       u32 *p32, tmp, cbytes;
-
-       /* Use optimal data transfer method based on source address and size */
-       switch (((u32) data) & 0x3) {
-       case 0: /* 32-bit aligned */
-               p32 = (u32 *) data;
-               cbytes = (bytes & ~0x3);
-
-               /* Copy 32-bit aligned data first */
-               for (n = 0; n < cbytes; n += 4)
-                       writel(*p32++, USBD_TXDATA(udc->udp_baseaddr));
-
-               /* Handle any remaining bytes */
-               bl = bytes - cbytes;
-               if (bl) {
-                       tmp = 0;
-                       for (n = 0; n < bl; n++)
-                               tmp |= data[cbytes + n] << (n * 8);
-
-                       writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
-               }
-               break;
-
-       case 1: /* 8-bit aligned */
-       case 3:
-               /* Each byte has to be handled independently */
-               for (n = 0; n < bytes; n += 4) {
-                       bl = bytes - n;
-                       if (bl > 4)
-                               bl = 4;
-
-                       tmp = 0;
-                       for (i = 0; i < bl; i++)
-                               tmp |= data[n + i] << (i * 8);
-
-                       writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
-               }
-               break;
-
-       case 2: /* 16-bit aligned */
-               p16 = (u16 *) data;
-               cbytes = (bytes & ~0x3);
-
-               /* Copy 32-bit aligned data first */
-               for (n = 0; n < cbytes; n += 4) {
-                       tmp = *p16++ & 0xFFFF;
-                       tmp |= (*p16++ & 0xFFFF) << 16;
-                       writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
-               }
-
-               /* Handle any remaining bytes */
-               bl = bytes - cbytes;
-               if (bl) {
-                       tmp = 0;
-                       for (n = 0; n < bl; n++)
-                               tmp |= data[cbytes + n] << (n * 8);
-
-                       writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
-               }
-               break;
-       }
-}
-
-/* Write data to the FIFO for an endpoint. This function is for endpoints (such
- * as EP0) that don't use DMA. Note that the endpoint must be selected in the
- * protocol engine prior to this call. */
-static void udc_write_hwep(struct lpc32xx_udc *udc, u32 hwep, u32 *data,
-                          u32 bytes)
-{
-       u32 hwwep = ((hwep & 0x1E) << 1) | CTRL_WR_EN;
-
-       if ((bytes > 0) && (data == NULL))
-               return;
-
-       /* Setup write of endpoint */
-       writel(hwwep, USBD_CTRL(udc->udp_baseaddr));
-
-       writel(bytes, USBD_TXPLEN(udc->udp_baseaddr));
-
-       /* Need at least 1 byte to trigger TX */
-       if (bytes == 0)
-               writel(0, USBD_TXDATA(udc->udp_baseaddr));
-       else
-               udc_stuff_fifo(udc, (u8 *) data, bytes);
-
-       writel(((hwep & 0x1E) << 1), USBD_CTRL(udc->udp_baseaddr));
-
-       udc_val_buffer_hwep(udc, hwep);
-}
-
-/* USB device reset - resets USB to a default state with just EP0
-   enabled */
-static void uda_usb_reset(struct lpc32xx_udc *udc)
-{
-       u32 i = 0;
-       /* Re-init device controller and EP0 */
-       udc_enable(udc);
-       udc->gadget.speed = USB_SPEED_FULL;
-
-       for (i = 1; i < NUM_ENDPOINTS; i++) {
-               struct lpc32xx_ep *ep = &udc->ep[i];
-               ep->req_pending = 0;
-       }
-}
-
-/* Send a ZLP on EP0 */
-static void udc_ep0_send_zlp(struct lpc32xx_udc *udc)
-{
-       udc_write_hwep(udc, EP_IN, NULL, 0);
-}
-
-/* Get current frame number */
-static u16 udc_get_current_frame(struct lpc32xx_udc *udc)
-{
-       u16 flo, fhi;
-
-       udc_protocol_cmd_w(udc, CMD_RD_FRAME);
-       flo = (u16) udc_protocol_cmd_r(udc, DAT_RD_FRAME);
-       fhi = (u16) udc_protocol_cmd_r(udc, DAT_RD_FRAME);
-
-       return (fhi << 8) | flo;
-}
-
-/* Set the device as configured - enables all endpoints */
-static inline void udc_set_device_configured(struct lpc32xx_udc *udc)
-{
-       udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(CONF_DVICE));
-}
-
-/* Set the device as unconfigured - disables all endpoints */
-static inline void udc_set_device_unconfigured(struct lpc32xx_udc *udc)
-{
-       udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(0));
-}
-
-/* reinit == restore initial software state */
-static void udc_reinit(struct lpc32xx_udc *udc)
-{
-       u32 i;
-
-       INIT_LIST_HEAD(&udc->gadget.ep_list);
-       INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
-
-       for (i = 0; i < NUM_ENDPOINTS; i++) {
-               struct lpc32xx_ep *ep = &udc->ep[i];
-
-               if (i != 0)
-                       list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
-               usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
-               INIT_LIST_HEAD(&ep->queue);
-               ep->req_pending = 0;
-       }
-
-       udc->ep0state = WAIT_FOR_SETUP;
-}
-
-/* Must be called with lock */
-static void done(struct lpc32xx_ep *ep, struct lpc32xx_request *req, int status)
-{
-       struct lpc32xx_udc *udc = ep->udc;
-
-       list_del_init(&req->queue);
-       if (req->req.status == -EINPROGRESS)
-               req->req.status = status;
-       else
-               status = req->req.status;
-
-       if (ep->lep) {
-               usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
-
-               /* Free DDs */
-               udc_dd_free(udc, req->dd_desc_ptr);
-       }
-
-       if (status && status != -ESHUTDOWN)
-               ep_dbg(ep, "%s done %p, status %d\n", ep->ep.name, req, status);
-
-       ep->req_pending = 0;
-       spin_unlock(&udc->lock);
-       req->req.complete(&ep->ep, &req->req);
-       spin_lock(&udc->lock);
-}
-
-/* Must be called with lock */
-static void nuke(struct lpc32xx_ep *ep, int status)
-{
-       struct lpc32xx_request *req;
-
-       while (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
-               done(ep, req, status);
-       }
-
-       if (status == -ESHUTDOWN) {
-               uda_disable_hwepint(ep->udc, ep->hwep_num);
-               udc_disable_hwep(ep->udc, ep->hwep_num);
-       }
-}
-
-/* IN endpoint 0 transfer */
-static int udc_ep0_in_req(struct lpc32xx_udc *udc)
-{
-       struct lpc32xx_request *req;
-       struct lpc32xx_ep *ep0 = &udc->ep[0];
-       u32 tsend, ts = 0;
-
-       if (list_empty(&ep0->queue))
-               /* Nothing to send */
-               return 0;
-       else
-               req = list_entry(ep0->queue.next, struct lpc32xx_request,
-                                queue);
-
-       tsend = ts = req->req.length - req->req.actual;
-       if (ts == 0) {
-               /* Send a ZLP */
-               udc_ep0_send_zlp(udc);
-               done(ep0, req, 0);
-               return 1;
-       } else if (ts > ep0->ep.maxpacket)
-               ts = ep0->ep.maxpacket; /* Just send what we can */
-
-       /* Write data to the EP0 FIFO and start transfer */
-       udc_write_hwep(udc, EP_IN, (req->req.buf + req->req.actual), ts);
-
-       /* Increment data pointer */
-       req->req.actual += ts;
-
-       if (tsend >= ep0->ep.maxpacket)
-               return 0; /* Stay in data transfer state */
-
-       /* Transfer request is complete */
-       udc->ep0state = WAIT_FOR_SETUP;
-       done(ep0, req, 0);
-       return 1;
-}
-
-/* OUT endpoint 0 transfer */
-static int udc_ep0_out_req(struct lpc32xx_udc *udc)
-{
-       struct lpc32xx_request *req;
-       struct lpc32xx_ep *ep0 = &udc->ep[0];
-       u32 tr, bufferspace;
-
-       if (list_empty(&ep0->queue))
-               return 0;
-       else
-               req = list_entry(ep0->queue.next, struct lpc32xx_request,
-                                queue);
-
-       if (req) {
-               if (req->req.length == 0) {
-                       /* Just dequeue request */
-                       done(ep0, req, 0);
-                       udc->ep0state = WAIT_FOR_SETUP;
-                       return 1;
-               }
-
-               /* Get data from FIFO */
-               bufferspace = req->req.length - req->req.actual;
-               if (bufferspace > ep0->ep.maxpacket)
-                       bufferspace = ep0->ep.maxpacket;
-
-               /* Copy data to buffer */
-               prefetchw(req->req.buf + req->req.actual);
-               tr = udc_read_hwep(udc, EP_OUT, req->req.buf + req->req.actual,
-                                  bufferspace);
-               req->req.actual += bufferspace;
-
-               if (tr < ep0->ep.maxpacket) {
-                       /* This is the last packet */
-                       done(ep0, req, 0);
-                       udc->ep0state = WAIT_FOR_SETUP;
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-
-/* Must be called with lock */
-static void stop_activity(struct lpc32xx_udc *udc)
-{
-       struct usb_gadget_driver *driver = udc->driver;
-       int i;
-
-       if (udc->gadget.speed == USB_SPEED_UNKNOWN)
-               driver = NULL;
-
-       udc->gadget.speed = USB_SPEED_UNKNOWN;
-       udc->suspended = 0;
-
-       for (i = 0; i < NUM_ENDPOINTS; i++) {
-               struct lpc32xx_ep *ep = &udc->ep[i];
-               nuke(ep, -ESHUTDOWN);
-       }
-       if (driver) {
-               spin_unlock(&udc->lock);
-               driver->disconnect(&udc->gadget);
-               spin_lock(&udc->lock);
-       }
-
-       isp1301_pullup_enable(udc, 0, 0);
-       udc_disable(udc);
-       udc_reinit(udc);
-}
-
-/*
- * Activate or kill host pullup
- * Can be called with or without lock
- */
-static void pullup(struct lpc32xx_udc *udc, int is_on)
-{
-       if (!udc->clocked)
-               return;
-
-       if (!udc->enabled || !udc->vbus)
-               is_on = 0;
-
-       if (is_on != udc->pullup)
-               isp1301_pullup_enable(udc, is_on, 0);
-}
-
-/* Must be called without lock */
-static int lpc32xx_ep_disable(struct usb_ep *_ep)
-{
-       struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
-       struct lpc32xx_udc *udc = ep->udc;
-       unsigned long   flags;
-
-       if ((ep->hwep_num_base == 0) || (ep->hwep_num == 0))
-               return -EINVAL;
-       spin_lock_irqsave(&udc->lock, flags);
-
-       nuke(ep, -ESHUTDOWN);
-
-       /* Clear all DMA statuses for this EP */
-       udc_ep_dma_disable(udc, ep->hwep_num);
-       writel(1 << ep->hwep_num, USBD_EOTINTCLR(udc->udp_baseaddr));
-       writel(1 << ep->hwep_num, USBD_NDDRTINTCLR(udc->udp_baseaddr));
-       writel(1 << ep->hwep_num, USBD_SYSERRTINTCLR(udc->udp_baseaddr));
-       writel(1 << ep->hwep_num, USBD_DMARCLR(udc->udp_baseaddr));
-
-       /* Remove the DD pointer in the UDCA */
-       udc->udca_v_base[ep->hwep_num] = 0;
-
-       /* Disable and reset endpoint and interrupt */
-       uda_clear_hwepint(udc, ep->hwep_num);
-       udc_unrealize_hwep(udc, ep->hwep_num);
-
-       ep->hwep_num = 0;
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       atomic_dec(&udc->enabled_ep_cnt);
-       wake_up(&udc->ep_disable_wait_queue);
-
-       return 0;
-}
-
-/* Must be called without lock */
-static int lpc32xx_ep_enable(struct usb_ep *_ep,
-                            const struct usb_endpoint_descriptor *desc)
-{
-       struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
-       struct lpc32xx_udc *udc = ep->udc;
-       u16 maxpacket;
-       u32 tmp;
-       unsigned long flags;
-
-       /* Verify EP data */
-       if ((!_ep) || (!ep) || (!desc) ||
-           (desc->bDescriptorType != USB_DT_ENDPOINT)) {
-               dev_dbg(udc->dev, "bad ep or descriptor\n");
-               return -EINVAL;
-       }
-       maxpacket = usb_endpoint_maxp(desc);
-       if ((maxpacket == 0) || (maxpacket > ep->maxpacket)) {
-               dev_dbg(udc->dev, "bad ep descriptor's packet size\n");
-               return -EINVAL;
-       }
-
-       /* Don't touch EP0 */
-       if (ep->hwep_num_base == 0) {
-               dev_dbg(udc->dev, "Can't re-enable EP0!!!\n");
-               return -EINVAL;
-       }
-
-       /* Is driver ready? */
-       if ((!udc->driver) || (udc->gadget.speed == USB_SPEED_UNKNOWN)) {
-               dev_dbg(udc->dev, "bogus device state\n");
-               return -ESHUTDOWN;
-       }
-
-       tmp = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-       switch (tmp) {
-       case USB_ENDPOINT_XFER_CONTROL:
-               return -EINVAL;
-
-       case USB_ENDPOINT_XFER_INT:
-               if (maxpacket > ep->maxpacket) {
-                       dev_dbg(udc->dev,
-                               "Bad INT endpoint maxpacket %d\n", maxpacket);
-                       return -EINVAL;
-               }
-               break;
-
-       case USB_ENDPOINT_XFER_BULK:
-               switch (maxpacket) {
-               case 8:
-               case 16:
-               case 32:
-               case 64:
-                       break;
-
-               default:
-                       dev_dbg(udc->dev,
-                               "Bad BULK endpoint maxpacket %d\n", maxpacket);
-                       return -EINVAL;
-               }
-               break;
-
-       case USB_ENDPOINT_XFER_ISOC:
-               break;
-       }
-       spin_lock_irqsave(&udc->lock, flags);
-
-       /* Initialize endpoint to match the selected descriptor */
-       ep->is_in = (desc->bEndpointAddress & USB_DIR_IN) != 0;
-       ep->ep.maxpacket = maxpacket;
-
-       /* Map hardware endpoint from base and direction */
-       if (ep->is_in)
-               /* IN endpoints are offset 1 from the OUT endpoint */
-               ep->hwep_num = ep->hwep_num_base + EP_IN;
-       else
-               ep->hwep_num = ep->hwep_num_base;
-
-       ep_dbg(ep, "EP enabled: %s, HW:%d, MP:%d IN:%d\n", ep->ep.name,
-              ep->hwep_num, maxpacket, (ep->is_in == 1));
-
-       /* Realize the endpoint, interrupt is enabled later when
-        * buffers are queued, IN EPs will NAK until buffers are ready */
-       udc_realize_hwep(udc, ep->hwep_num, ep->ep.maxpacket);
-       udc_clr_buffer_hwep(udc, ep->hwep_num);
-       uda_disable_hwepint(udc, ep->hwep_num);
-       udc_clrstall_hwep(udc, ep->hwep_num);
-
-       /* Clear all DMA statuses for this EP */
-       udc_ep_dma_disable(udc, ep->hwep_num);
-       writel(1 << ep->hwep_num, USBD_EOTINTCLR(udc->udp_baseaddr));
-       writel(1 << ep->hwep_num, USBD_NDDRTINTCLR(udc->udp_baseaddr));
-       writel(1 << ep->hwep_num, USBD_SYSERRTINTCLR(udc->udp_baseaddr));
-       writel(1 << ep->hwep_num, USBD_DMARCLR(udc->udp_baseaddr));
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       atomic_inc(&udc->enabled_ep_cnt);
-       return 0;
-}
-
-/*
- * Allocate a USB request list
- * Can be called with or without lock
- */
-static struct usb_request *lpc32xx_ep_alloc_request(struct usb_ep *_ep,
-                                                   gfp_t gfp_flags)
-{
-       struct lpc32xx_request *req;
-
-       req = kzalloc(sizeof(struct lpc32xx_request), gfp_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD(&req->queue);
-       return &req->req;
-}
-
-/*
- * De-allocate a USB request list
- * Can be called with or without lock
- */
-static void lpc32xx_ep_free_request(struct usb_ep *_ep,
-                                   struct usb_request *_req)
-{
-       struct lpc32xx_request *req;
-
-       req = container_of(_req, struct lpc32xx_request, req);
-       BUG_ON(!list_empty(&req->queue));
-       kfree(req);
-}
-
-/* Must be called without lock */
-static int lpc32xx_ep_queue(struct usb_ep *_ep,
-                           struct usb_request *_req, gfp_t gfp_flags)
-{
-       struct lpc32xx_request *req;
-       struct lpc32xx_ep *ep;
-       struct lpc32xx_udc *udc;
-       unsigned long flags;
-       int status = 0;
-
-       req = container_of(_req, struct lpc32xx_request, req);
-       ep = container_of(_ep, struct lpc32xx_ep, ep);
-
-       if (!_req || !_req->complete || !_req->buf ||
-           !list_empty(&req->queue))
-               return -EINVAL;
-
-       udc = ep->udc;
-
-       if (!_ep) {
-               dev_dbg(udc->dev, "invalid ep\n");
-               return -EINVAL;
-       }
-
-
-       if ((!udc) || (!udc->driver) ||
-           (udc->gadget.speed == USB_SPEED_UNKNOWN)) {
-               dev_dbg(udc->dev, "invalid device\n");
-               return -EINVAL;
-       }
-
-       if (ep->lep) {
-               struct lpc32xx_usbd_dd_gad *dd;
-
-               status = usb_gadget_map_request(&udc->gadget, _req, ep->is_in);
-               if (status)
-                       return status;
-
-               /* For the request, build a list of DDs */
-               dd = udc_dd_alloc(udc);
-               if (!dd) {
-                       /* Error allocating DD */
-                       return -ENOMEM;
-               }
-               req->dd_desc_ptr = dd;
-
-               /* Setup the DMA descriptor */
-               dd->dd_next_phy = dd->dd_next_v = 0;
-               dd->dd_buffer_addr = req->req.dma;
-               dd->dd_status = 0;
-
-               /* Special handling for ISO EPs */
-               if (ep->eptype == EP_ISO_TYPE) {
-                       dd->dd_setup = DD_SETUP_ISO_EP |
-                               DD_SETUP_PACKETLEN(0) |
-                               DD_SETUP_DMALENBYTES(1);
-                       dd->dd_iso_ps_mem_addr = dd->this_dma + 24;
-                       if (ep->is_in)
-                               dd->iso_status[0] = req->req.length;
-                       else
-                               dd->iso_status[0] = 0;
-               } else
-                       dd->dd_setup = DD_SETUP_PACKETLEN(ep->ep.maxpacket) |
-                               DD_SETUP_DMALENBYTES(req->req.length);
-       }
-
-       ep_dbg(ep, "%s queue req %p len %d buf %p (in=%d) z=%d\n", _ep->name,
-              _req, _req->length, _req->buf, ep->is_in, _req->zero);
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       _req->status = -EINPROGRESS;
-       _req->actual = 0;
-       req->send_zlp = _req->zero;
-
-       /* Kickstart empty queues */
-       if (list_empty(&ep->queue)) {
-               list_add_tail(&req->queue, &ep->queue);
-
-               if (ep->hwep_num_base == 0) {
-                       /* Handle expected data direction */
-                       if (ep->is_in) {
-                               /* IN packet to host */
-                               udc->ep0state = DATA_IN;
-                               status = udc_ep0_in_req(udc);
-                       } else {
-                               /* OUT packet from host */
-                               udc->ep0state = DATA_OUT;
-                               status = udc_ep0_out_req(udc);
-                       }
-               } else if (ep->is_in) {
-                       /* IN packet to host and kick off transfer */
-                       if (!ep->req_pending)
-                               udc_ep_in_req_dma(udc, ep);
-               } else
-                       /* OUT packet from host and kick off list */
-                       if (!ep->req_pending)
-                               udc_ep_out_req_dma(udc, ep);
-       } else
-               list_add_tail(&req->queue, &ep->queue);
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return (status < 0) ? status : 0;
-}
-
-/* Must be called without lock */
-static int lpc32xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct lpc32xx_ep *ep;
-       struct lpc32xx_request *req;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct lpc32xx_ep, ep);
-       if (!_ep || ep->hwep_num_base == 0)
-               return -EINVAL;
-
-       spin_lock_irqsave(&ep->udc->lock, flags);
-
-       /* make sure it's actually queued on this endpoint */
-       list_for_each_entry(req, &ep->queue, queue) {
-               if (&req->req == _req)
-                       break;
-       }
-       if (&req->req != _req) {
-               spin_unlock_irqrestore(&ep->udc->lock, flags);
-               return -EINVAL;
-       }
-
-       done(ep, req, -ECONNRESET);
-
-       spin_unlock_irqrestore(&ep->udc->lock, flags);
-
-       return 0;
-}
-
-/* Must be called without lock */
-static int lpc32xx_ep_set_halt(struct usb_ep *_ep, int value)
-{
-       struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
-       struct lpc32xx_udc *udc = ep->udc;
-       unsigned long flags;
-
-       if ((!ep) || (ep->hwep_num <= 1))
-               return -EINVAL;
-
-       /* Don't halt an IN EP */
-       if (ep->is_in)
-               return -EAGAIN;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       if (value == 1) {
-               /* stall */
-               udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(ep->hwep_num),
-                                       DAT_WR_BYTE(EP_STAT_ST));
-       } else {
-               /* End stall */
-               ep->wedge = 0;
-               udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(ep->hwep_num),
-                                       DAT_WR_BYTE(0));
-       }
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-/* set the halt feature and ignores clear requests */
-static int lpc32xx_ep_set_wedge(struct usb_ep *_ep)
-{
-       struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
-
-       if (!_ep || !ep->udc)
-               return -EINVAL;
-
-       ep->wedge = 1;
-
-       return usb_ep_set_halt(_ep);
-}
-
-static const struct usb_ep_ops lpc32xx_ep_ops = {
-       .enable         = lpc32xx_ep_enable,
-       .disable        = lpc32xx_ep_disable,
-       .alloc_request  = lpc32xx_ep_alloc_request,
-       .free_request   = lpc32xx_ep_free_request,
-       .queue          = lpc32xx_ep_queue,
-       .dequeue        = lpc32xx_ep_dequeue,
-       .set_halt       = lpc32xx_ep_set_halt,
-       .set_wedge      = lpc32xx_ep_set_wedge,
-};
-
-/* Send a ZLP on a non-0 IN EP */
-void udc_send_in_zlp(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
-{
-       /* Clear EP status */
-       udc_clearep_getsts(udc, ep->hwep_num);
-
-       /* Send ZLP via FIFO mechanism */
-       udc_write_hwep(udc, ep->hwep_num, NULL, 0);
-}
-
-/*
- * Handle EP completion for ZLP
- * This function will only be called when a delayed ZLP needs to be sent out
- * after a DMA transfer has filled both buffers.
- */
-void udc_handle_eps(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
-{
-       u32 epstatus;
-       struct lpc32xx_request *req;
-
-       if (ep->hwep_num <= 0)
-               return;
-
-       uda_clear_hwepint(udc, ep->hwep_num);
-
-       /* If this interrupt isn't enabled, return now */
-       if (!(udc->enabled_hwepints & (1 << ep->hwep_num)))
-               return;
-
-       /* Get endpoint status */
-       epstatus = udc_clearep_getsts(udc, ep->hwep_num);
-
-       /*
-        * This should never happen, but protect against writing to the
-        * buffer when full.
-        */
-       if (epstatus & EP_SEL_F)
-               return;
-
-       if (ep->is_in) {
-               udc_send_in_zlp(udc, ep);
-               uda_disable_hwepint(udc, ep->hwep_num);
-       } else
-               return;
-
-       /* If there isn't a request waiting, something went wrong */
-       req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
-       if (req) {
-               done(ep, req, 0);
-
-               /* Start another request if ready */
-               if (!list_empty(&ep->queue)) {
-                       if (ep->is_in)
-                               udc_ep_in_req_dma(udc, ep);
-                       else
-                               udc_ep_out_req_dma(udc, ep);
-               } else
-                       ep->req_pending = 0;
-       }
-}
-
-
-/* DMA end of transfer completion */
-static void udc_handle_dma_ep(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
-{
-       u32 status, epstatus;
-       struct lpc32xx_request *req;
-       struct lpc32xx_usbd_dd_gad *dd;
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-       ep->totalints++;
-#endif
-
-       req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
-       if (!req) {
-               ep_err(ep, "DMA interrupt on no req!\n");
-               return;
-       }
-       dd = req->dd_desc_ptr;
-
-       /* DMA descriptor should always be retired for this call */
-       if (!(dd->dd_status & DD_STATUS_DD_RETIRED))
-               ep_warn(ep, "DMA descriptor did not retire\n");
-
-       /* Disable DMA */
-       udc_ep_dma_disable(udc, ep->hwep_num);
-       writel((1 << ep->hwep_num), USBD_EOTINTCLR(udc->udp_baseaddr));
-       writel((1 << ep->hwep_num), USBD_NDDRTINTCLR(udc->udp_baseaddr));
-
-       /* System error? */
-       if (readl(USBD_SYSERRTINTST(udc->udp_baseaddr)) &
-           (1 << ep->hwep_num)) {
-               writel((1 << ep->hwep_num),
-                            USBD_SYSERRTINTCLR(udc->udp_baseaddr));
-               ep_err(ep, "AHB critical error!\n");
-               ep->req_pending = 0;
-
-               /* The error could have occurred on a packet of a multipacket
-                * transfer, so recovering the transfer is not possible. Close
-                * the request with an error */
-               done(ep, req, -ECONNABORTED);
-               return;
-       }
-
-       /* Handle the current DD's status */
-       status = dd->dd_status;
-       switch (status & DD_STATUS_STS_MASK) {
-       case DD_STATUS_STS_NS:
-               /* DD not serviced? This shouldn't happen! */
-               ep->req_pending = 0;
-               ep_err(ep, "DMA critical EP error: DD not serviced (0x%x)!\n",
-                      status);
-
-               done(ep, req, -ECONNABORTED);
-               return;
-
-       case DD_STATUS_STS_BS:
-               /* Interrupt only fires on EOT - This shouldn't happen! */
-               ep->req_pending = 0;
-               ep_err(ep, "DMA critical EP error: EOT prior to service completion (0x%x)!\n",
-                      status);
-               done(ep, req, -ECONNABORTED);
-               return;
-
-       case DD_STATUS_STS_NC:
-       case DD_STATUS_STS_DUR:
-               /* Really just a short packet, not an underrun */
-               /* This is a good status and what we expect */
-               break;
-
-       default:
-               /* Data overrun, system error, or unknown */
-               ep->req_pending = 0;
-               ep_err(ep, "DMA critical EP error: System error (0x%x)!\n",
-                      status);
-               done(ep, req, -ECONNABORTED);
-               return;
-       }
-
-       /* ISO endpoints are handled differently */
-       if (ep->eptype == EP_ISO_TYPE) {
-               if (ep->is_in)
-                       req->req.actual = req->req.length;
-               else
-                       req->req.actual = dd->iso_status[0] & 0xFFFF;
-       } else
-               req->req.actual += DD_STATUS_CURDMACNT(status);
-
-       /* Send a ZLP if necessary. This will be done for non-int
-        * packets which have a size that is a divisor of MAXP */
-       if (req->send_zlp) {
-               /*
-                * If at least 1 buffer is available, send the ZLP now.
-                * Otherwise, the ZLP send needs to be deferred until a
-                * buffer is available.
-                */
-               if (udc_clearep_getsts(udc, ep->hwep_num) & EP_SEL_F) {
-                       udc_clearep_getsts(udc, ep->hwep_num);
-                       uda_enable_hwepint(udc, ep->hwep_num);
-                       epstatus = udc_clearep_getsts(udc, ep->hwep_num);
-
-                       /* Let the EP interrupt handle the ZLP */
-                       return;
-               } else
-                       udc_send_in_zlp(udc, ep);
-       }
-
-       /* Transfer request is complete */
-       done(ep, req, 0);
-
-       /* Start another request if ready */
-       udc_clearep_getsts(udc, ep->hwep_num);
-       if (!list_empty((&ep->queue))) {
-               if (ep->is_in)
-                       udc_ep_in_req_dma(udc, ep);
-               else
-                       udc_ep_out_req_dma(udc, ep);
-       } else
-               ep->req_pending = 0;
-
-}
-
-/*
- *
- * Endpoint 0 functions
- *
- */
-static void udc_handle_dev(struct lpc32xx_udc *udc)
-{
-       u32 tmp;
-
-       udc_protocol_cmd_w(udc, CMD_GET_DEV_STAT);
-       tmp = udc_protocol_cmd_r(udc, DAT_GET_DEV_STAT);
-
-       if (tmp & DEV_RST)
-               uda_usb_reset(udc);
-       else if (tmp & DEV_CON_CH)
-               uda_power_event(udc, (tmp & DEV_CON));
-       else if (tmp & DEV_SUS_CH) {
-               if (tmp & DEV_SUS) {
-                       if (udc->vbus == 0)
-                               stop_activity(udc);
-                       else if ((udc->gadget.speed != USB_SPEED_UNKNOWN) &&
-                                udc->driver) {
-                               /* Power down transceiver */
-                               udc->poweron = 0;
-                               schedule_work(&udc->pullup_job);
-                               uda_resm_susp_event(udc, 1);
-                       }
-               } else if ((udc->gadget.speed != USB_SPEED_UNKNOWN) &&
-                          udc->driver && udc->vbus) {
-                       uda_resm_susp_event(udc, 0);
-                       /* Power up transceiver */
-                       udc->poweron = 1;
-                       schedule_work(&udc->pullup_job);
-               }
-       }
-}
-
-static int udc_get_status(struct lpc32xx_udc *udc, u16 reqtype, u16 wIndex)
-{
-       struct lpc32xx_ep *ep;
-       u32 ep0buff = 0, tmp;
-
-       switch (reqtype & USB_RECIP_MASK) {
-       case USB_RECIP_INTERFACE:
-               break; /* Not supported */
-
-       case USB_RECIP_DEVICE:
-               ep0buff = (udc->selfpowered << USB_DEVICE_SELF_POWERED);
-               if (udc->dev_status & (1 << USB_DEVICE_REMOTE_WAKEUP))
-                       ep0buff |= (1 << USB_DEVICE_REMOTE_WAKEUP);
-               break;
-
-       case USB_RECIP_ENDPOINT:
-               tmp = wIndex & USB_ENDPOINT_NUMBER_MASK;
-               ep = &udc->ep[tmp];
-               if ((tmp == 0) || (tmp >= NUM_ENDPOINTS))
-                       return -EOPNOTSUPP;
-
-               if (wIndex & USB_DIR_IN) {
-                       if (!ep->is_in)
-                               return -EOPNOTSUPP; /* Something's wrong */
-               } else if (ep->is_in)
-                       return -EOPNOTSUPP; /* Not an IN endpoint */
-
-               /* Get status of the endpoint */
-               udc_protocol_cmd_w(udc, CMD_SEL_EP(ep->hwep_num));
-               tmp = udc_protocol_cmd_r(udc, DAT_SEL_EP(ep->hwep_num));
-
-               if (tmp & EP_SEL_ST)
-                       ep0buff = (1 << USB_ENDPOINT_HALT);
-               else
-                       ep0buff = 0;
-               break;
-
-       default:
-               break;
-       }
-
-       /* Return data */
-       udc_write_hwep(udc, EP_IN, &ep0buff, 2);
-
-       return 0;
-}
-
-static void udc_handle_ep0_setup(struct lpc32xx_udc *udc)
-{
-       struct lpc32xx_ep *ep, *ep0 = &udc->ep[0];
-       struct usb_ctrlrequest ctrlpkt;
-       int i, bytes;
-       u16 wIndex, wValue, wLength, reqtype, req, tmp;
-
-       /* Nuke previous transfers */
-       nuke(ep0, -EPROTO);
-
-       /* Get setup packet */
-       bytes = udc_read_hwep(udc, EP_OUT, (u32 *) &ctrlpkt, 8);
-       if (bytes != 8) {
-               ep_warn(ep0, "Incorrectly sized setup packet (s/b 8, is %d)!\n",
-                       bytes);
-               return;
-       }
-
-       /* Native endianness */
-       wIndex = le16_to_cpu(ctrlpkt.wIndex);
-       wValue = le16_to_cpu(ctrlpkt.wValue);
-       wLength = le16_to_cpu(ctrlpkt.wLength);
-       reqtype = le16_to_cpu(ctrlpkt.bRequestType);
-
-       /* Set direction of EP0 */
-       if (likely(reqtype & USB_DIR_IN))
-               ep0->is_in = 1;
-       else
-               ep0->is_in = 0;
-
-       /* Handle SETUP packet */
-       req = le16_to_cpu(ctrlpkt.bRequest);
-       switch (req) {
-       case USB_REQ_CLEAR_FEATURE:
-       case USB_REQ_SET_FEATURE:
-               switch (reqtype) {
-               case (USB_TYPE_STANDARD | USB_RECIP_DEVICE):
-                       if (wValue != USB_DEVICE_REMOTE_WAKEUP)
-                               goto stall; /* Nothing else handled */
-
-                       /* Tell board about event */
-                       if (req == USB_REQ_CLEAR_FEATURE)
-                               udc->dev_status &=
-                                       ~(1 << USB_DEVICE_REMOTE_WAKEUP);
-                       else
-                               udc->dev_status |=
-                                       (1 << USB_DEVICE_REMOTE_WAKEUP);
-                       uda_remwkp_cgh(udc);
-                       goto zlp_send;
-
-               case (USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
-                       tmp = wIndex & USB_ENDPOINT_NUMBER_MASK;
-                       if ((wValue != USB_ENDPOINT_HALT) ||
-                           (tmp >= NUM_ENDPOINTS))
-                               break;
-
-                       /* Find hardware endpoint from logical endpoint */
-                       ep = &udc->ep[tmp];
-                       tmp = ep->hwep_num;
-                       if (tmp == 0)
-                               break;
-
-                       if (req == USB_REQ_SET_FEATURE)
-                               udc_stall_hwep(udc, tmp);
-                       else if (!ep->wedge)
-                               udc_clrstall_hwep(udc, tmp);
-
-                       goto zlp_send;
-
-               default:
-                       break;
-               }
-
-
-       case USB_REQ_SET_ADDRESS:
-               if (reqtype == (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) {
-                       udc_set_address(udc, wValue);
-                       goto zlp_send;
-               }
-               break;
-
-       case USB_REQ_GET_STATUS:
-               udc_get_status(udc, reqtype, wIndex);
-               return;
-
-       default:
-               break; /* Let GadgetFS handle the descriptor instead */
-       }
-
-       if (likely(udc->driver)) {
-               /* device-2-host (IN) or no data setup command, process
-                * immediately */
-               spin_unlock(&udc->lock);
-               i = udc->driver->setup(&udc->gadget, &ctrlpkt);
-
-               spin_lock(&udc->lock);
-               if (req == USB_REQ_SET_CONFIGURATION) {
-                       /* Configuration is set after endpoints are realized */
-                       if (wValue) {
-                               /* Set configuration */
-                               udc_set_device_configured(udc);
-
-                               udc_protocol_cmd_data_w(udc, CMD_SET_MODE,
-                                                       DAT_WR_BYTE(AP_CLK |
-                                                       INAK_BI | INAK_II));
-                       } else {
-                               /* Clear configuration */
-                               udc_set_device_unconfigured(udc);
-
-                               /* Disable NAK interrupts */
-                               udc_protocol_cmd_data_w(udc, CMD_SET_MODE,
-                                                       DAT_WR_BYTE(AP_CLK));
-                       }
-               }
-
-               if (i < 0) {
-                       /* setup processing failed, force stall */
-                       dev_dbg(udc->dev,
-                               "req %02x.%02x protocol STALL; stat %d\n",
-                               reqtype, req, i);
-                       udc->ep0state = WAIT_FOR_SETUP;
-                       goto stall;
-               }
-       }
-
-       if (!ep0->is_in)
-               udc_ep0_send_zlp(udc); /* ZLP IN packet on data phase */
-
-       return;
-
-stall:
-       udc_stall_hwep(udc, EP_IN);
-       return;
-
-zlp_send:
-       udc_ep0_send_zlp(udc);
-       return;
-}
-
-/* IN endpoint 0 transfer */
-static void udc_handle_ep0_in(struct lpc32xx_udc *udc)
-{
-       struct lpc32xx_ep *ep0 = &udc->ep[0];
-       u32 epstatus;
-
-       /* Clear EP interrupt */
-       epstatus = udc_clearep_getsts(udc, EP_IN);
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-       ep0->totalints++;
-#endif
-
-       /* Stalled? Clear stall and reset buffers */
-       if (epstatus & EP_SEL_ST) {
-               udc_clrstall_hwep(udc, EP_IN);
-               nuke(ep0, -ECONNABORTED);
-               udc->ep0state = WAIT_FOR_SETUP;
-               return;
-       }
-
-       /* Is a buffer available? */
-       if (!(epstatus & EP_SEL_F)) {
-               /* Handle based on current state */
-               if (udc->ep0state == DATA_IN)
-                       udc_ep0_in_req(udc);
-               else {
-                       /* Unknown state for EP0 oe end of DATA IN phase */
-                       nuke(ep0, -ECONNABORTED);
-                       udc->ep0state = WAIT_FOR_SETUP;
-               }
-       }
-}
-
-/* OUT endpoint 0 transfer */
-static void udc_handle_ep0_out(struct lpc32xx_udc *udc)
-{
-       struct lpc32xx_ep *ep0 = &udc->ep[0];
-       u32 epstatus;
-
-       /* Clear EP interrupt */
-       epstatus = udc_clearep_getsts(udc, EP_OUT);
-
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-       ep0->totalints++;
-#endif
-
-       /* Stalled? */
-       if (epstatus & EP_SEL_ST) {
-               udc_clrstall_hwep(udc, EP_OUT);
-               nuke(ep0, -ECONNABORTED);
-               udc->ep0state = WAIT_FOR_SETUP;
-               return;
-       }
-
-       /* A NAK may occur if a packet couldn't be received yet */
-       if (epstatus & EP_SEL_EPN)
-               return;
-       /* Setup packet incoming? */
-       if (epstatus & EP_SEL_STP) {
-               nuke(ep0, 0);
-               udc->ep0state = WAIT_FOR_SETUP;
-       }
-
-       /* Data available? */
-       if (epstatus & EP_SEL_F)
-               /* Handle based on current state */
-               switch (udc->ep0state) {
-               case WAIT_FOR_SETUP:
-                       udc_handle_ep0_setup(udc);
-                       break;
-
-               case DATA_OUT:
-                       udc_ep0_out_req(udc);
-                       break;
-
-               default:
-                       /* Unknown state for EP0 */
-                       nuke(ep0, -ECONNABORTED);
-                       udc->ep0state = WAIT_FOR_SETUP;
-               }
-}
-
-/* Must be called without lock */
-static int lpc32xx_get_frame(struct usb_gadget *gadget)
-{
-       int frame;
-       unsigned long flags;
-       struct lpc32xx_udc *udc = to_udc(gadget);
-
-       if (!udc->clocked)
-               return -EINVAL;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       frame = (int) udc_get_current_frame(udc);
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return frame;
-}
-
-static int lpc32xx_wakeup(struct usb_gadget *gadget)
-{
-       return -ENOTSUPP;
-}
-
-static int lpc32xx_set_selfpowered(struct usb_gadget *gadget, int is_on)
-{
-       struct lpc32xx_udc *udc = to_udc(gadget);
-
-       /* Always self-powered */
-       udc->selfpowered = (is_on != 0);
-
-       return 0;
-}
-
-/*
- * vbus is here!  turn everything on that's ready
- * Must be called without lock
- */
-static int lpc32xx_vbus_session(struct usb_gadget *gadget, int is_active)
-{
-       unsigned long flags;
-       struct lpc32xx_udc *udc = to_udc(gadget);
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       /* Doesn't need lock */
-       if (udc->driver) {
-               udc_clk_set(udc, 1);
-               udc_enable(udc);
-               pullup(udc, is_active);
-       } else {
-               stop_activity(udc);
-               pullup(udc, 0);
-
-               spin_unlock_irqrestore(&udc->lock, flags);
-               /*
-                *  Wait for all the endpoints to disable,
-                *  before disabling clocks. Don't wait if
-                *  endpoints are not enabled.
-                */
-               if (atomic_read(&udc->enabled_ep_cnt))
-                       wait_event_interruptible(udc->ep_disable_wait_queue,
-                                (atomic_read(&udc->enabled_ep_cnt) == 0));
-
-               spin_lock_irqsave(&udc->lock, flags);
-
-               udc_clk_set(udc, 0);
-       }
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-/* Can be called with or without lock */
-static int lpc32xx_pullup(struct usb_gadget *gadget, int is_on)
-{
-       struct lpc32xx_udc *udc = to_udc(gadget);
-
-       /* Doesn't need lock */
-       pullup(udc, is_on);
-
-       return 0;
-}
-
-static int lpc32xx_start(struct usb_gadget *, struct usb_gadget_driver *);
-static int lpc32xx_stop(struct usb_gadget *, struct usb_gadget_driver *);
-
-static const struct usb_gadget_ops lpc32xx_udc_ops = {
-       .get_frame              = lpc32xx_get_frame,
-       .wakeup                 = lpc32xx_wakeup,
-       .set_selfpowered        = lpc32xx_set_selfpowered,
-       .vbus_session           = lpc32xx_vbus_session,
-       .pullup                 = lpc32xx_pullup,
-       .udc_start              = lpc32xx_start,
-       .udc_stop               = lpc32xx_stop,
-};
-
-static void nop_release(struct device *dev)
-{
-       /* nothing to free */
-}
-
-static const struct lpc32xx_udc controller_template = {
-       .gadget = {
-               .ops    = &lpc32xx_udc_ops,
-               .name   = driver_name,
-               .dev    = {
-                       .init_name = "gadget",
-                       .release = nop_release,
-               }
-       },
-       .ep[0] = {
-               .ep = {
-                       .name   = "ep0",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 64,
-               .hwep_num_base  = 0,
-               .hwep_num       = 0, /* Can be 0 or 1, has special handling */
-               .lep            = 0,
-               .eptype         = EP_CTL_TYPE,
-       },
-       .ep[1] = {
-               .ep = {
-                       .name   = "ep1-int",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 64,
-               .hwep_num_base  = 2,
-               .hwep_num       = 0, /* 2 or 3, will be set later */
-               .lep            = 1,
-               .eptype         = EP_INT_TYPE,
-       },
-       .ep[2] = {
-               .ep = {
-                       .name   = "ep2-bulk",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 64,
-               .hwep_num_base  = 4,
-               .hwep_num       = 0, /* 4 or 5, will be set later */
-               .lep            = 2,
-               .eptype         = EP_BLK_TYPE,
-       },
-       .ep[3] = {
-               .ep = {
-                       .name   = "ep3-iso",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 1023,
-               .hwep_num_base  = 6,
-               .hwep_num       = 0, /* 6 or 7, will be set later */
-               .lep            = 3,
-               .eptype         = EP_ISO_TYPE,
-       },
-       .ep[4] = {
-               .ep = {
-                       .name   = "ep4-int",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 64,
-               .hwep_num_base  = 8,
-               .hwep_num       = 0, /* 8 or 9, will be set later */
-               .lep            = 4,
-               .eptype         = EP_INT_TYPE,
-       },
-       .ep[5] = {
-               .ep = {
-                       .name   = "ep5-bulk",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 64,
-               .hwep_num_base  = 10,
-               .hwep_num       = 0, /* 10 or 11, will be set later */
-               .lep            = 5,
-               .eptype         = EP_BLK_TYPE,
-       },
-       .ep[6] = {
-               .ep = {
-                       .name   = "ep6-iso",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 1023,
-               .hwep_num_base  = 12,
-               .hwep_num       = 0, /* 12 or 13, will be set later */
-               .lep            = 6,
-               .eptype         = EP_ISO_TYPE,
-       },
-       .ep[7] = {
-               .ep = {
-                       .name   = "ep7-int",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 64,
-               .hwep_num_base  = 14,
-               .hwep_num       = 0,
-               .lep            = 7,
-               .eptype         = EP_INT_TYPE,
-       },
-       .ep[8] = {
-               .ep = {
-                       .name   = "ep8-bulk",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 64,
-               .hwep_num_base  = 16,
-               .hwep_num       = 0,
-               .lep            = 8,
-               .eptype         = EP_BLK_TYPE,
-       },
-       .ep[9] = {
-               .ep = {
-                       .name   = "ep9-iso",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 1023,
-               .hwep_num_base  = 18,
-               .hwep_num       = 0,
-               .lep            = 9,
-               .eptype         = EP_ISO_TYPE,
-       },
-       .ep[10] = {
-               .ep = {
-                       .name   = "ep10-int",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 64,
-               .hwep_num_base  = 20,
-               .hwep_num       = 0,
-               .lep            = 10,
-               .eptype         = EP_INT_TYPE,
-       },
-       .ep[11] = {
-               .ep = {
-                       .name   = "ep11-bulk",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 64,
-               .hwep_num_base  = 22,
-               .hwep_num       = 0,
-               .lep            = 11,
-               .eptype         = EP_BLK_TYPE,
-       },
-       .ep[12] = {
-               .ep = {
-                       .name   = "ep12-iso",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 1023,
-               .hwep_num_base  = 24,
-               .hwep_num       = 0,
-               .lep            = 12,
-               .eptype         = EP_ISO_TYPE,
-       },
-       .ep[13] = {
-               .ep = {
-                       .name   = "ep13-int",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 64,
-               .hwep_num_base  = 26,
-               .hwep_num       = 0,
-               .lep            = 13,
-               .eptype         = EP_INT_TYPE,
-       },
-       .ep[14] = {
-               .ep = {
-                       .name   = "ep14-bulk",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 64,
-               .hwep_num_base  = 28,
-               .hwep_num       = 0,
-               .lep            = 14,
-               .eptype         = EP_BLK_TYPE,
-       },
-       .ep[15] = {
-               .ep = {
-                       .name   = "ep15-bulk",
-                       .ops    = &lpc32xx_ep_ops,
-               },
-               .maxpacket      = 1023,
-               .hwep_num_base  = 30,
-               .hwep_num       = 0,
-               .lep            = 15,
-               .eptype         = EP_BLK_TYPE,
-       },
-};
-
-/* ISO and status interrupts */
-static irqreturn_t lpc32xx_usb_lp_irq(int irq, void *_udc)
-{
-       u32 tmp, devstat;
-       struct lpc32xx_udc *udc = _udc;
-
-       spin_lock(&udc->lock);
-
-       /* Read the device status register */
-       devstat = readl(USBD_DEVINTST(udc->udp_baseaddr));
-
-       devstat &= ~USBD_EP_FAST;
-       writel(devstat, USBD_DEVINTCLR(udc->udp_baseaddr));
-       devstat = devstat & udc->enabled_devints;
-
-       /* Device specific handling needed? */
-       if (devstat & USBD_DEV_STAT)
-               udc_handle_dev(udc);
-
-       /* Start of frame? (devstat & FRAME_INT):
-        * The frame interrupt isn't really needed for ISO support,
-        * as the driver will queue the necessary packets */
-
-       /* Error? */
-       if (devstat & ERR_INT) {
-               /* All types of errors, from cable removal during transfer to
-                * misc protocol and bit errors. These are mostly for just info,
-                * as the USB hardware will work around these. If these errors
-                * happen alot, something is wrong. */
-               udc_protocol_cmd_w(udc, CMD_RD_ERR_STAT);
-               tmp = udc_protocol_cmd_r(udc, DAT_RD_ERR_STAT);
-               dev_dbg(udc->dev, "Device error (0x%x)!\n", tmp);
-       }
-
-       spin_unlock(&udc->lock);
-
-       return IRQ_HANDLED;
-}
-
-/* EP interrupts */
-static irqreturn_t lpc32xx_usb_hp_irq(int irq, void *_udc)
-{
-       u32 tmp;
-       struct lpc32xx_udc *udc = _udc;
-
-       spin_lock(&udc->lock);
-
-       /* Read the device status register */
-       writel(USBD_EP_FAST, USBD_DEVINTCLR(udc->udp_baseaddr));
-
-       /* Endpoints */
-       tmp = readl(USBD_EPINTST(udc->udp_baseaddr));
-
-       /* Special handling for EP0 */
-       if (tmp & (EP_MASK_SEL(0, EP_OUT) | EP_MASK_SEL(0, EP_IN))) {
-               /* Handle EP0 IN */
-               if (tmp & (EP_MASK_SEL(0, EP_IN)))
-                       udc_handle_ep0_in(udc);
-
-               /* Handle EP0 OUT */
-               if (tmp & (EP_MASK_SEL(0, EP_OUT)))
-                       udc_handle_ep0_out(udc);
-       }
-
-       /* All other EPs */
-       if (tmp & ~(EP_MASK_SEL(0, EP_OUT) | EP_MASK_SEL(0, EP_IN))) {
-               int i;
-
-               /* Handle other EP interrupts */
-               for (i = 1; i < NUM_ENDPOINTS; i++) {
-                       if (tmp & (1 << udc->ep[i].hwep_num))
-                               udc_handle_eps(udc, &udc->ep[i]);
-               }
-       }
-
-       spin_unlock(&udc->lock);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t lpc32xx_usb_devdma_irq(int irq, void *_udc)
-{
-       struct lpc32xx_udc *udc = _udc;
-
-       int i;
-       u32 tmp;
-
-       spin_lock(&udc->lock);
-
-       /* Handle EP DMA EOT interrupts */
-       tmp = readl(USBD_EOTINTST(udc->udp_baseaddr)) |
-               (readl(USBD_EPDMAST(udc->udp_baseaddr)) &
-                readl(USBD_NDDRTINTST(udc->udp_baseaddr))) |
-               readl(USBD_SYSERRTINTST(udc->udp_baseaddr));
-       for (i = 1; i < NUM_ENDPOINTS; i++) {
-               if (tmp & (1 << udc->ep[i].hwep_num))
-                       udc_handle_dma_ep(udc, &udc->ep[i]);
-       }
-
-       spin_unlock(&udc->lock);
-
-       return IRQ_HANDLED;
-}
-
-/*
- *
- * VBUS detection, pullup handler, and Gadget cable state notification
- *
- */
-static void vbus_work(struct work_struct *work)
-{
-       u8 value;
-       struct lpc32xx_udc *udc = container_of(work, struct lpc32xx_udc,
-                                              vbus_job);
-
-       if (udc->enabled != 0) {
-               /* Discharge VBUS real quick */
-               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-                       ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DISCHRG);
-
-               /* Give VBUS some time (100mS) to discharge */
-               msleep(100);
-
-               /* Disable VBUS discharge resistor */
-               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-                       ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
-                       OTG1_VBUS_DISCHRG);
-
-               /* Clear interrupt */
-               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-                       ISP1301_I2C_INTERRUPT_LATCH |
-                       ISP1301_I2C_REG_CLEAR_ADDR, ~0);
-
-               /* Get the VBUS status from the transceiver */
-               value = i2c_smbus_read_byte_data(udc->isp1301_i2c_client,
-                                                ISP1301_I2C_INTERRUPT_SOURCE);
-
-               /* VBUS on or off? */
-               if (value & INT_SESS_VLD)
-                       udc->vbus = 1;
-               else
-                       udc->vbus = 0;
-
-               /* VBUS changed? */
-               if (udc->last_vbus != udc->vbus) {
-                       udc->last_vbus = udc->vbus;
-                       lpc32xx_vbus_session(&udc->gadget, udc->vbus);
-               }
-       }
-
-       /* Re-enable after completion */
-       enable_irq(udc->udp_irq[IRQ_USB_ATX]);
-}
-
-static irqreturn_t lpc32xx_usb_vbus_irq(int irq, void *_udc)
-{
-       struct lpc32xx_udc *udc = _udc;
-
-       /* Defer handling of VBUS IRQ to work queue */
-       disable_irq_nosync(udc->udp_irq[IRQ_USB_ATX]);
-       schedule_work(&udc->vbus_job);
-
-       return IRQ_HANDLED;
-}
-
-static int lpc32xx_start(struct usb_gadget *gadget,
-                        struct usb_gadget_driver *driver)
-{
-       struct lpc32xx_udc *udc = to_udc(gadget);
-       int i;
-
-       if (!driver || driver->max_speed < USB_SPEED_FULL || !driver->setup) {
-               dev_err(udc->dev, "bad parameter.\n");
-               return -EINVAL;
-       }
-
-       if (udc->driver) {
-               dev_err(udc->dev, "UDC already has a gadget driver\n");
-               return -EBUSY;
-       }
-
-       udc->driver = driver;
-       udc->gadget.dev.of_node = udc->dev->of_node;
-       udc->enabled = 1;
-       udc->selfpowered = 1;
-       udc->vbus = 0;
-
-       /* Force VBUS process once to check for cable insertion */
-       udc->last_vbus = udc->vbus = 0;
-       schedule_work(&udc->vbus_job);
-
-       /* Do not re-enable ATX IRQ (3) */
-       for (i = IRQ_USB_LP; i < IRQ_USB_ATX; i++)
-               enable_irq(udc->udp_irq[i]);
-
-       return 0;
-}
-
-static int lpc32xx_stop(struct usb_gadget *gadget,
-                       struct usb_gadget_driver *driver)
-{
-       int i;
-       struct lpc32xx_udc *udc = to_udc(gadget);
-
-       if (!driver || driver != udc->driver)
-               return -EINVAL;
-
-       for (i = IRQ_USB_LP; i <= IRQ_USB_ATX; i++)
-               disable_irq(udc->udp_irq[i]);
-
-       if (udc->clocked) {
-               spin_lock(&udc->lock);
-               stop_activity(udc);
-               spin_unlock(&udc->lock);
-
-               /*
-                *  Wait for all the endpoints to disable,
-                *  before disabling clocks. Don't wait if
-                *  endpoints are not enabled.
-                */
-               if (atomic_read(&udc->enabled_ep_cnt))
-                       wait_event_interruptible(udc->ep_disable_wait_queue,
-                               (atomic_read(&udc->enabled_ep_cnt) == 0));
-
-               spin_lock(&udc->lock);
-               udc_clk_set(udc, 0);
-               spin_unlock(&udc->lock);
-       }
-
-       udc->enabled = 0;
-       udc->driver = NULL;
-
-       return 0;
-}
-
-static void lpc32xx_udc_shutdown(struct platform_device *dev)
-{
-       /* Force disconnect on reboot */
-       struct lpc32xx_udc *udc = platform_get_drvdata(dev);
-
-       pullup(udc, 0);
-}
-
-/*
- * Callbacks to be overridden by options passed via OF (TODO)
- */
-
-static void lpc32xx_usbd_conn_chg(int conn)
-{
-       /* Do nothing, it might be nice to enable an LED
-        * based on conn state being !0 */
-}
-
-static void lpc32xx_usbd_susp_chg(int susp)
-{
-       /* Device suspend if susp != 0 */
-}
-
-static void lpc32xx_rmwkup_chg(int remote_wakup_enable)
-{
-       /* Enable or disable USB remote wakeup */
-}
-
-struct lpc32xx_usbd_cfg lpc32xx_usbddata = {
-       .vbus_drv_pol = 0,
-       .conn_chgb = &lpc32xx_usbd_conn_chg,
-       .susp_chgb = &lpc32xx_usbd_susp_chg,
-       .rmwk_chgb = &lpc32xx_rmwkup_chg,
-};
-
-
-static u64 lpc32xx_usbd_dmamask = ~(u32) 0x7F;
-
-static int lpc32xx_udc_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct lpc32xx_udc *udc;
-       int retval, i;
-       struct resource *res;
-       dma_addr_t dma_handle;
-       struct device_node *isp1301_node;
-
-       udc = kmemdup(&controller_template, sizeof(*udc), GFP_KERNEL);
-       if (!udc)
-               return -ENOMEM;
-
-       for (i = 0; i <= 15; i++)
-               udc->ep[i].udc = udc;
-       udc->gadget.ep0 = &udc->ep[0].ep;
-
-       /* init software state */
-       udc->gadget.dev.parent = dev;
-       udc->pdev = pdev;
-       udc->dev = &pdev->dev;
-       udc->enabled = 0;
-
-       if (pdev->dev.of_node) {
-               isp1301_node = of_parse_phandle(pdev->dev.of_node,
-                                               "transceiver", 0);
-       } else {
-               isp1301_node = NULL;
-       }
-
-       udc->isp1301_i2c_client = isp1301_get_client(isp1301_node);
-       if (!udc->isp1301_i2c_client) {
-               retval = -EPROBE_DEFER;
-               goto phy_fail;
-       }
-
-       dev_info(udc->dev, "ISP1301 I2C device at address 0x%x\n",
-                udc->isp1301_i2c_client->addr);
-
-       pdev->dev.dma_mask = &lpc32xx_usbd_dmamask;
-       retval = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
-       if (retval)
-               goto resource_fail;
-
-       udc->board = &lpc32xx_usbddata;
-
-       /*
-        * Resources are mapped as follows:
-        *  IORESOURCE_MEM, base address and size of USB space
-        *  IORESOURCE_IRQ, USB device low priority interrupt number
-        *  IORESOURCE_IRQ, USB device high priority interrupt number
-        *  IORESOURCE_IRQ, USB device interrupt number
-        *  IORESOURCE_IRQ, USB transceiver interrupt number
-        */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               retval = -ENXIO;
-               goto resource_fail;
-       }
-
-       spin_lock_init(&udc->lock);
-
-       /* Get IRQs */
-       for (i = 0; i < 4; i++) {
-               udc->udp_irq[i] = platform_get_irq(pdev, i);
-               if (udc->udp_irq[i] < 0) {
-                       dev_err(udc->dev,
-                               "irq resource %d not available!\n", i);
-                       retval = udc->udp_irq[i];
-                       goto irq_fail;
-               }
-       }
-
-       udc->io_p_start = res->start;
-       udc->io_p_size = resource_size(res);
-       if (!request_mem_region(udc->io_p_start, udc->io_p_size, driver_name)) {
-               dev_err(udc->dev, "someone's using UDC memory\n");
-               retval = -EBUSY;
-               goto request_mem_region_fail;
-       }
-
-       udc->udp_baseaddr = ioremap(udc->io_p_start, udc->io_p_size);
-       if (!udc->udp_baseaddr) {
-               retval = -ENOMEM;
-               dev_err(udc->dev, "IO map failure\n");
-               goto io_map_fail;
-       }
-
-       /* Enable AHB slave USB clock, needed for further USB clock control */
-       writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL);
-
-       /* Get required clocks */
-       udc->usb_pll_clk = clk_get(&pdev->dev, "ck_pll5");
-       if (IS_ERR(udc->usb_pll_clk)) {
-               dev_err(udc->dev, "failed to acquire USB PLL\n");
-               retval = PTR_ERR(udc->usb_pll_clk);
-               goto pll_get_fail;
-       }
-       udc->usb_slv_clk = clk_get(&pdev->dev, "ck_usbd");
-       if (IS_ERR(udc->usb_slv_clk)) {
-               dev_err(udc->dev, "failed to acquire USB device clock\n");
-               retval = PTR_ERR(udc->usb_slv_clk);
-               goto usb_clk_get_fail;
-       }
-       udc->usb_otg_clk = clk_get(&pdev->dev, "ck_usb_otg");
-       if (IS_ERR(udc->usb_otg_clk)) {
-               dev_err(udc->dev, "failed to acquire USB otg clock\n");
-               retval = PTR_ERR(udc->usb_otg_clk);
-               goto usb_otg_clk_get_fail;
-       }
-
-       /* Setup PLL clock to 48MHz */
-       retval = clk_enable(udc->usb_pll_clk);
-       if (retval < 0) {
-               dev_err(udc->dev, "failed to start USB PLL\n");
-               goto pll_enable_fail;
-       }
-
-       retval = clk_set_rate(udc->usb_pll_clk, 48000);
-       if (retval < 0) {
-               dev_err(udc->dev, "failed to set USB clock rate\n");
-               goto pll_set_fail;
-       }
-
-       writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN, USB_CTRL);
-
-       /* Enable USB device clock */
-       retval = clk_enable(udc->usb_slv_clk);
-       if (retval < 0) {
-               dev_err(udc->dev, "failed to start USB device clock\n");
-               goto usb_clk_enable_fail;
-       }
-
-       /* Enable USB OTG clock */
-       retval = clk_enable(udc->usb_otg_clk);
-       if (retval < 0) {
-               dev_err(udc->dev, "failed to start USB otg clock\n");
-               goto usb_otg_clk_enable_fail;
-       }
-
-       /* Setup deferred workqueue data */
-       udc->poweron = udc->pullup = 0;
-       INIT_WORK(&udc->pullup_job, pullup_work);
-       INIT_WORK(&udc->vbus_job, vbus_work);
-#ifdef CONFIG_PM
-       INIT_WORK(&udc->power_job, power_work);
-#endif
-
-       /* All clocks are now on */
-       udc->clocked = 1;
-
-       isp1301_udc_configure(udc);
-       /* Allocate memory for the UDCA */
-       udc->udca_v_base = dma_alloc_coherent(&pdev->dev, UDCA_BUFF_SIZE,
-                                             &dma_handle,
-                                             (GFP_KERNEL | GFP_DMA));
-       if (!udc->udca_v_base) {
-               dev_err(udc->dev, "error getting UDCA region\n");
-               retval = -ENOMEM;
-               goto i2c_fail;
-       }
-       udc->udca_p_base = dma_handle;
-       dev_dbg(udc->dev, "DMA buffer(0x%x bytes), P:0x%08x, V:0x%p\n",
-               UDCA_BUFF_SIZE, udc->udca_p_base, udc->udca_v_base);
-
-       /* Setup the DD DMA memory pool */
-       udc->dd_cache = dma_pool_create("udc_dd", udc->dev,
-                                       sizeof(struct lpc32xx_usbd_dd_gad),
-                                       sizeof(u32), 0);
-       if (!udc->dd_cache) {
-               dev_err(udc->dev, "error getting DD DMA region\n");
-               retval = -ENOMEM;
-               goto dma_alloc_fail;
-       }
-
-       /* Clear USB peripheral and initialize gadget endpoints */
-       udc_disable(udc);
-       udc_reinit(udc);
-
-       /* Request IRQs - low and high priority USB device IRQs are routed to
-        * the same handler, while the DMA interrupt is routed elsewhere */
-       retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq,
-                            0, "udc_lp", udc);
-       if (retval < 0) {
-               dev_err(udc->dev, "LP request irq %d failed\n",
-                       udc->udp_irq[IRQ_USB_LP]);
-               goto irq_lp_fail;
-       }
-       retval = request_irq(udc->udp_irq[IRQ_USB_HP], lpc32xx_usb_hp_irq,
-                            0, "udc_hp", udc);
-       if (retval < 0) {
-               dev_err(udc->dev, "HP request irq %d failed\n",
-                       udc->udp_irq[IRQ_USB_HP]);
-               goto irq_hp_fail;
-       }
-
-       retval = request_irq(udc->udp_irq[IRQ_USB_DEVDMA],
-                            lpc32xx_usb_devdma_irq, 0, "udc_dma", udc);
-       if (retval < 0) {
-               dev_err(udc->dev, "DEV request irq %d failed\n",
-                       udc->udp_irq[IRQ_USB_DEVDMA]);
-               goto irq_dev_fail;
-       }
-
-       /* The transceiver interrupt is used for VBUS detection and will
-          kick off the VBUS handler function */
-       retval = request_irq(udc->udp_irq[IRQ_USB_ATX], lpc32xx_usb_vbus_irq,
-                            0, "udc_otg", udc);
-       if (retval < 0) {
-               dev_err(udc->dev, "VBUS request irq %d failed\n",
-                       udc->udp_irq[IRQ_USB_ATX]);
-               goto irq_xcvr_fail;
-       }
-
-       /* Initialize wait queue */
-       init_waitqueue_head(&udc->ep_disable_wait_queue);
-       atomic_set(&udc->enabled_ep_cnt, 0);
-
-       /* Keep all IRQs disabled until GadgetFS starts up */
-       for (i = IRQ_USB_LP; i <= IRQ_USB_ATX; i++)
-               disable_irq(udc->udp_irq[i]);
-
-       retval = usb_add_gadget_udc(dev, &udc->gadget);
-       if (retval < 0)
-               goto add_gadget_fail;
-
-       dev_set_drvdata(dev, udc);
-       device_init_wakeup(dev, 1);
-       create_debug_file(udc);
-
-       /* Disable clocks for now */
-       udc_clk_set(udc, 0);
-
-       dev_info(udc->dev, "%s version %s\n", driver_name, DRIVER_VERSION);
-       return 0;
-
-add_gadget_fail:
-       free_irq(udc->udp_irq[IRQ_USB_ATX], udc);
-irq_xcvr_fail:
-       free_irq(udc->udp_irq[IRQ_USB_DEVDMA], udc);
-irq_dev_fail:
-       free_irq(udc->udp_irq[IRQ_USB_HP], udc);
-irq_hp_fail:
-       free_irq(udc->udp_irq[IRQ_USB_LP], udc);
-irq_lp_fail:
-       dma_pool_destroy(udc->dd_cache);
-dma_alloc_fail:
-       dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
-                         udc->udca_v_base, udc->udca_p_base);
-i2c_fail:
-       clk_disable(udc->usb_otg_clk);
-usb_otg_clk_enable_fail:
-       clk_disable(udc->usb_slv_clk);
-usb_clk_enable_fail:
-pll_set_fail:
-       clk_disable(udc->usb_pll_clk);
-pll_enable_fail:
-       clk_put(udc->usb_otg_clk);
-usb_otg_clk_get_fail:
-       clk_put(udc->usb_slv_clk);
-usb_clk_get_fail:
-       clk_put(udc->usb_pll_clk);
-pll_get_fail:
-       iounmap(udc->udp_baseaddr);
-io_map_fail:
-       release_mem_region(udc->io_p_start, udc->io_p_size);
-       dev_err(udc->dev, "%s probe failed, %d\n", driver_name, retval);
-request_mem_region_fail:
-irq_fail:
-resource_fail:
-phy_fail:
-       kfree(udc);
-       return retval;
-}
-
-static int lpc32xx_udc_remove(struct platform_device *pdev)
-{
-       struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
-
-       usb_del_gadget_udc(&udc->gadget);
-       if (udc->driver)
-               return -EBUSY;
-
-       udc_clk_set(udc, 1);
-       udc_disable(udc);
-       pullup(udc, 0);
-
-       free_irq(udc->udp_irq[IRQ_USB_ATX], udc);
-
-       device_init_wakeup(&pdev->dev, 0);
-       remove_debug_file(udc);
-
-       dma_pool_destroy(udc->dd_cache);
-       dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
-                         udc->udca_v_base, udc->udca_p_base);
-       free_irq(udc->udp_irq[IRQ_USB_DEVDMA], udc);
-       free_irq(udc->udp_irq[IRQ_USB_HP], udc);
-       free_irq(udc->udp_irq[IRQ_USB_LP], udc);
-
-       clk_disable(udc->usb_otg_clk);
-       clk_put(udc->usb_otg_clk);
-       clk_disable(udc->usb_slv_clk);
-       clk_put(udc->usb_slv_clk);
-       clk_disable(udc->usb_pll_clk);
-       clk_put(udc->usb_pll_clk);
-       iounmap(udc->udp_baseaddr);
-       release_mem_region(udc->io_p_start, udc->io_p_size);
-       kfree(udc);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int lpc32xx_udc_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-       struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
-
-       if (udc->clocked) {
-               /* Power down ISP */
-               udc->poweron = 0;
-               isp1301_set_powerstate(udc, 0);
-
-               /* Disable clocking */
-               udc_clk_set(udc, 0);
-
-               /* Keep clock flag on, so we know to re-enable clocks
-                  on resume */
-               udc->clocked = 1;
-
-               /* Kill global USB clock */
-               clk_disable(udc->usb_slv_clk);
-       }
-
-       return 0;
-}
-
-static int lpc32xx_udc_resume(struct platform_device *pdev)
-{
-       struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
-
-       if (udc->clocked) {
-               /* Enable global USB clock */
-               clk_enable(udc->usb_slv_clk);
-
-               /* Enable clocking */
-               udc_clk_set(udc, 1);
-
-               /* ISP back to normal power mode */
-               udc->poweron = 1;
-               isp1301_set_powerstate(udc, 1);
-       }
-
-       return 0;
-}
-#else
-#define        lpc32xx_udc_suspend     NULL
-#define        lpc32xx_udc_resume      NULL
-#endif
-
-#ifdef CONFIG_OF
-static const struct of_device_id lpc32xx_udc_of_match[] = {
-       { .compatible = "nxp,lpc3220-udc", },
-       { },
-};
-MODULE_DEVICE_TABLE(of, lpc32xx_udc_of_match);
-#endif
-
-static struct platform_driver lpc32xx_udc_driver = {
-       .remove         = lpc32xx_udc_remove,
-       .shutdown       = lpc32xx_udc_shutdown,
-       .suspend        = lpc32xx_udc_suspend,
-       .resume         = lpc32xx_udc_resume,
-       .driver         = {
-               .name   = (char *) driver_name,
-               .owner  = THIS_MODULE,
-               .of_match_table = of_match_ptr(lpc32xx_udc_of_match),
-       },
-};
-
-module_platform_driver_probe(lpc32xx_udc_driver, lpc32xx_udc_probe);
-
-MODULE_DESCRIPTION("LPC32XX udc driver");
-MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
-MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:lpc32xx_udc");
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
deleted file mode 100644 (file)
index de88d33..0000000
+++ /dev/null
@@ -1,1706 +0,0 @@
-/*
- * M66592 UDC (USB gadget)
- *
- * Copyright (C) 2006-2007 Renesas Solutions Corp.
- *
- * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include "m66592-udc.h"
-
-MODULE_DESCRIPTION("M66592 USB gadget driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Yoshihiro Shimoda");
-MODULE_ALIAS("platform:m66592_udc");
-
-#define DRIVER_VERSION "21 July 2009"
-
-static const char udc_name[] = "m66592_udc";
-static const char *m66592_ep_name[] = {
-       "ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7"
-};
-
-static void disable_controller(struct m66592 *m66592);
-static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req);
-static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req);
-static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
-                       gfp_t gfp_flags);
-
-static void transfer_complete(struct m66592_ep *ep,
-               struct m66592_request *req, int status);
-
-/*-------------------------------------------------------------------------*/
-static inline u16 get_usb_speed(struct m66592 *m66592)
-{
-       return (m66592_read(m66592, M66592_DVSTCTR) & M66592_RHST);
-}
-
-static void enable_pipe_irq(struct m66592 *m66592, u16 pipenum,
-               unsigned long reg)
-{
-       u16 tmp;
-
-       tmp = m66592_read(m66592, M66592_INTENB0);
-       m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
-                       M66592_INTENB0);
-       m66592_bset(m66592, (1 << pipenum), reg);
-       m66592_write(m66592, tmp, M66592_INTENB0);
-}
-
-static void disable_pipe_irq(struct m66592 *m66592, u16 pipenum,
-               unsigned long reg)
-{
-       u16 tmp;
-
-       tmp = m66592_read(m66592, M66592_INTENB0);
-       m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
-                       M66592_INTENB0);
-       m66592_bclr(m66592, (1 << pipenum), reg);
-       m66592_write(m66592, tmp, M66592_INTENB0);
-}
-
-static void m66592_usb_connect(struct m66592 *m66592)
-{
-       m66592_bset(m66592, M66592_CTRE, M66592_INTENB0);
-       m66592_bset(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
-                       M66592_INTENB0);
-       m66592_bset(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
-
-       m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
-}
-
-static void m66592_usb_disconnect(struct m66592 *m66592)
-__releases(m66592->lock)
-__acquires(m66592->lock)
-{
-       m66592_bclr(m66592, M66592_CTRE, M66592_INTENB0);
-       m66592_bclr(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
-                       M66592_INTENB0);
-       m66592_bclr(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
-       m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
-
-       m66592->gadget.speed = USB_SPEED_UNKNOWN;
-       spin_unlock(&m66592->lock);
-       m66592->driver->disconnect(&m66592->gadget);
-       spin_lock(&m66592->lock);
-
-       disable_controller(m66592);
-       INIT_LIST_HEAD(&m66592->ep[0].queue);
-}
-
-static inline u16 control_reg_get_pid(struct m66592 *m66592, u16 pipenum)
-{
-       u16 pid = 0;
-       unsigned long offset;
-
-       if (pipenum == 0)
-               pid = m66592_read(m66592, M66592_DCPCTR) & M66592_PID;
-       else if (pipenum < M66592_MAX_NUM_PIPE) {
-               offset = get_pipectr_addr(pipenum);
-               pid = m66592_read(m66592, offset) & M66592_PID;
-       } else
-               pr_err("unexpect pipe num (%d)\n", pipenum);
-
-       return pid;
-}
-
-static inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum,
-               u16 pid)
-{
-       unsigned long offset;
-
-       if (pipenum == 0)
-               m66592_mdfy(m66592, pid, M66592_PID, M66592_DCPCTR);
-       else if (pipenum < M66592_MAX_NUM_PIPE) {
-               offset = get_pipectr_addr(pipenum);
-               m66592_mdfy(m66592, pid, M66592_PID, offset);
-       } else
-               pr_err("unexpect pipe num (%d)\n", pipenum);
-}
-
-static inline void pipe_start(struct m66592 *m66592, u16 pipenum)
-{
-       control_reg_set_pid(m66592, pipenum, M66592_PID_BUF);
-}
-
-static inline void pipe_stop(struct m66592 *m66592, u16 pipenum)
-{
-       control_reg_set_pid(m66592, pipenum, M66592_PID_NAK);
-}
-
-static inline void pipe_stall(struct m66592 *m66592, u16 pipenum)
-{
-       control_reg_set_pid(m66592, pipenum, M66592_PID_STALL);
-}
-
-static inline u16 control_reg_get(struct m66592 *m66592, u16 pipenum)
-{
-       u16 ret = 0;
-       unsigned long offset;
-
-       if (pipenum == 0)
-               ret = m66592_read(m66592, M66592_DCPCTR);
-       else if (pipenum < M66592_MAX_NUM_PIPE) {
-               offset = get_pipectr_addr(pipenum);
-               ret = m66592_read(m66592, offset);
-       } else
-               pr_err("unexpect pipe num (%d)\n", pipenum);
-
-       return ret;
-}
-
-static inline void control_reg_sqclr(struct m66592 *m66592, u16 pipenum)
-{
-       unsigned long offset;
-
-       pipe_stop(m66592, pipenum);
-
-       if (pipenum == 0)
-               m66592_bset(m66592, M66592_SQCLR, M66592_DCPCTR);
-       else if (pipenum < M66592_MAX_NUM_PIPE) {
-               offset = get_pipectr_addr(pipenum);
-               m66592_bset(m66592, M66592_SQCLR, offset);
-       } else
-               pr_err("unexpect pipe num(%d)\n", pipenum);
-}
-
-static inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
-{
-       u16 tmp;
-       int size;
-
-       if (pipenum == 0) {
-               tmp = m66592_read(m66592, M66592_DCPCFG);
-               if ((tmp & M66592_CNTMD) != 0)
-                       size = 256;
-               else {
-                       tmp = m66592_read(m66592, M66592_DCPMAXP);
-                       size = tmp & M66592_MAXP;
-               }
-       } else {
-               m66592_write(m66592, pipenum, M66592_PIPESEL);
-               tmp = m66592_read(m66592, M66592_PIPECFG);
-               if ((tmp & M66592_CNTMD) != 0) {
-                       tmp = m66592_read(m66592, M66592_PIPEBUF);
-                       size = ((tmp >> 10) + 1) * 64;
-               } else {
-                       tmp = m66592_read(m66592, M66592_PIPEMAXP);
-                       size = tmp & M66592_MXPS;
-               }
-       }
-
-       return size;
-}
-
-static inline void pipe_change(struct m66592 *m66592, u16 pipenum)
-{
-       struct m66592_ep *ep = m66592->pipenum2ep[pipenum];
-       unsigned short mbw;
-
-       if (ep->use_dma)
-               return;
-
-       m66592_mdfy(m66592, pipenum, M66592_CURPIPE, ep->fifosel);
-
-       ndelay(450);
-
-       if (m66592->pdata->on_chip)
-               mbw = M66592_MBW_32;
-       else
-               mbw = M66592_MBW_16;
-
-       m66592_bset(m66592, mbw, ep->fifosel);
-}
-
-static int pipe_buffer_setting(struct m66592 *m66592,
-               struct m66592_pipe_info *info)
-{
-       u16 bufnum = 0, buf_bsize = 0;
-       u16 pipecfg = 0;
-
-       if (info->pipe == 0)
-               return -EINVAL;
-
-       m66592_write(m66592, info->pipe, M66592_PIPESEL);
-
-       if (info->dir_in)
-               pipecfg |= M66592_DIR;
-       pipecfg |= info->type;
-       pipecfg |= info->epnum;
-       switch (info->type) {
-       case M66592_INT:
-               bufnum = 4 + (info->pipe - M66592_BASE_PIPENUM_INT);
-               buf_bsize = 0;
-               break;
-       case M66592_BULK:
-               /* isochronous pipes may be used as bulk pipes */
-               if (info->pipe >= M66592_BASE_PIPENUM_BULK)
-                       bufnum = info->pipe - M66592_BASE_PIPENUM_BULK;
-               else
-                       bufnum = info->pipe - M66592_BASE_PIPENUM_ISOC;
-
-               bufnum = M66592_BASE_BUFNUM + (bufnum * 16);
-               buf_bsize = 7;
-               pipecfg |= M66592_DBLB;
-               if (!info->dir_in)
-                       pipecfg |= M66592_SHTNAK;
-               break;
-       case M66592_ISO:
-               bufnum = M66592_BASE_BUFNUM +
-                        (info->pipe - M66592_BASE_PIPENUM_ISOC) * 16;
-               buf_bsize = 7;
-               break;
-       }
-
-       if (buf_bsize && ((bufnum + 16) >= M66592_MAX_BUFNUM)) {
-               pr_err("m66592 pipe memory is insufficient\n");
-               return -ENOMEM;
-       }
-
-       m66592_write(m66592, pipecfg, M66592_PIPECFG);
-       m66592_write(m66592, (buf_bsize << 10) | (bufnum), M66592_PIPEBUF);
-       m66592_write(m66592, info->maxpacket, M66592_PIPEMAXP);
-       if (info->interval)
-               info->interval--;
-       m66592_write(m66592, info->interval, M66592_PIPEPERI);
-
-       return 0;
-}
-
-static void pipe_buffer_release(struct m66592 *m66592,
-                               struct m66592_pipe_info *info)
-{
-       if (info->pipe == 0)
-               return;
-
-       if (is_bulk_pipe(info->pipe)) {
-               m66592->bulk--;
-       } else if (is_interrupt_pipe(info->pipe))
-               m66592->interrupt--;
-       else if (is_isoc_pipe(info->pipe)) {
-               m66592->isochronous--;
-               if (info->type == M66592_BULK)
-                       m66592->bulk--;
-       } else
-               pr_err("ep_release: unexpect pipenum (%d)\n",
-                               info->pipe);
-}
-
-static void pipe_initialize(struct m66592_ep *ep)
-{
-       struct m66592 *m66592 = ep->m66592;
-       unsigned short mbw;
-
-       m66592_mdfy(m66592, 0, M66592_CURPIPE, ep->fifosel);
-
-       m66592_write(m66592, M66592_ACLRM, ep->pipectr);
-       m66592_write(m66592, 0, ep->pipectr);
-       m66592_write(m66592, M66592_SQCLR, ep->pipectr);
-       if (ep->use_dma) {
-               m66592_mdfy(m66592, ep->pipenum, M66592_CURPIPE, ep->fifosel);
-
-               ndelay(450);
-
-               if (m66592->pdata->on_chip)
-                       mbw = M66592_MBW_32;
-               else
-                       mbw = M66592_MBW_16;
-
-               m66592_bset(m66592, mbw, ep->fifosel);
-       }
-}
-
-static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
-               const struct usb_endpoint_descriptor *desc,
-               u16 pipenum, int dma)
-{
-       if ((pipenum != 0) && dma) {
-               if (m66592->num_dma == 0) {
-                       m66592->num_dma++;
-                       ep->use_dma = 1;
-                       ep->fifoaddr = M66592_D0FIFO;
-                       ep->fifosel = M66592_D0FIFOSEL;
-                       ep->fifoctr = M66592_D0FIFOCTR;
-                       ep->fifotrn = M66592_D0FIFOTRN;
-               } else if (!m66592->pdata->on_chip && m66592->num_dma == 1) {
-                       m66592->num_dma++;
-                       ep->use_dma = 1;
-                       ep->fifoaddr = M66592_D1FIFO;
-                       ep->fifosel = M66592_D1FIFOSEL;
-                       ep->fifoctr = M66592_D1FIFOCTR;
-                       ep->fifotrn = M66592_D1FIFOTRN;
-               } else {
-                       ep->use_dma = 0;
-                       ep->fifoaddr = M66592_CFIFO;
-                       ep->fifosel = M66592_CFIFOSEL;
-                       ep->fifoctr = M66592_CFIFOCTR;
-                       ep->fifotrn = 0;
-               }
-       } else {
-               ep->use_dma = 0;
-               ep->fifoaddr = M66592_CFIFO;
-               ep->fifosel = M66592_CFIFOSEL;
-               ep->fifoctr = M66592_CFIFOCTR;
-               ep->fifotrn = 0;
-       }
-
-       ep->pipectr = get_pipectr_addr(pipenum);
-       ep->pipenum = pipenum;
-       ep->ep.maxpacket = usb_endpoint_maxp(desc);
-       m66592->pipenum2ep[pipenum] = ep;
-       m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep;
-       INIT_LIST_HEAD(&ep->queue);
-}
-
-static void m66592_ep_release(struct m66592_ep *ep)
-{
-       struct m66592 *m66592 = ep->m66592;
-       u16 pipenum = ep->pipenum;
-
-       if (pipenum == 0)
-               return;
-
-       if (ep->use_dma)
-               m66592->num_dma--;
-       ep->pipenum = 0;
-       ep->busy = 0;
-       ep->use_dma = 0;
-}
-
-static int alloc_pipe_config(struct m66592_ep *ep,
-               const struct usb_endpoint_descriptor *desc)
-{
-       struct m66592 *m66592 = ep->m66592;
-       struct m66592_pipe_info info;
-       int dma = 0;
-       int *counter;
-       int ret;
-
-       ep->ep.desc = desc;
-
-       BUG_ON(ep->pipenum);
-
-       switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
-       case USB_ENDPOINT_XFER_BULK:
-               if (m66592->bulk >= M66592_MAX_NUM_BULK) {
-                       if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
-                               pr_err("bulk pipe is insufficient\n");
-                               return -ENODEV;
-                       } else {
-                               info.pipe = M66592_BASE_PIPENUM_ISOC
-                                               + m66592->isochronous;
-                               counter = &m66592->isochronous;
-                       }
-               } else {
-                       info.pipe = M66592_BASE_PIPENUM_BULK + m66592->bulk;
-                       counter = &m66592->bulk;
-               }
-               info.type = M66592_BULK;
-               dma = 1;
-               break;
-       case USB_ENDPOINT_XFER_INT:
-               if (m66592->interrupt >= M66592_MAX_NUM_INT) {
-                       pr_err("interrupt pipe is insufficient\n");
-                       return -ENODEV;
-               }
-               info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt;
-               info.type = M66592_INT;
-               counter = &m66592->interrupt;
-               break;
-       case USB_ENDPOINT_XFER_ISOC:
-               if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
-                       pr_err("isochronous pipe is insufficient\n");
-                       return -ENODEV;
-               }
-               info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous;
-               info.type = M66592_ISO;
-               counter = &m66592->isochronous;
-               break;
-       default:
-               pr_err("unexpect xfer type\n");
-               return -EINVAL;
-       }
-       ep->type = info.type;
-
-       info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-       info.maxpacket = usb_endpoint_maxp(desc);
-       info.interval = desc->bInterval;
-       if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-               info.dir_in = 1;
-       else
-               info.dir_in = 0;
-
-       ret = pipe_buffer_setting(m66592, &info);
-       if (ret < 0) {
-               pr_err("pipe_buffer_setting fail\n");
-               return ret;
-       }
-
-       (*counter)++;
-       if ((counter == &m66592->isochronous) && info.type == M66592_BULK)
-               m66592->bulk++;
-
-       m66592_ep_setting(m66592, ep, desc, info.pipe, dma);
-       pipe_initialize(ep);
-
-       return 0;
-}
-
-static int free_pipe_config(struct m66592_ep *ep)
-{
-       struct m66592 *m66592 = ep->m66592;
-       struct m66592_pipe_info info;
-
-       info.pipe = ep->pipenum;
-       info.type = ep->type;
-       pipe_buffer_release(m66592, &info);
-       m66592_ep_release(ep);
-
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-static void pipe_irq_enable(struct m66592 *m66592, u16 pipenum)
-{
-       enable_irq_ready(m66592, pipenum);
-       enable_irq_nrdy(m66592, pipenum);
-}
-
-static void pipe_irq_disable(struct m66592 *m66592, u16 pipenum)
-{
-       disable_irq_ready(m66592, pipenum);
-       disable_irq_nrdy(m66592, pipenum);
-}
-
-/* if complete is true, gadget driver complete function is not call */
-static void control_end(struct m66592 *m66592, unsigned ccpl)
-{
-       m66592->ep[0].internal_ccpl = ccpl;
-       pipe_start(m66592, 0);
-       m66592_bset(m66592, M66592_CCPL, M66592_DCPCTR);
-}
-
-static void start_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
-{
-       struct m66592 *m66592 = ep->m66592;
-
-       pipe_change(m66592, ep->pipenum);
-       m66592_mdfy(m66592, M66592_ISEL | M66592_PIPE0,
-                       (M66592_ISEL | M66592_CURPIPE),
-                       M66592_CFIFOSEL);
-       m66592_write(m66592, M66592_BCLR, ep->fifoctr);
-       if (req->req.length == 0) {
-               m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
-               pipe_start(m66592, 0);
-               transfer_complete(ep, req, 0);
-       } else {
-               m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
-               irq_ep0_write(ep, req);
-       }
-}
-
-static void start_packet_write(struct m66592_ep *ep, struct m66592_request *req)
-{
-       struct m66592 *m66592 = ep->m66592;
-       u16 tmp;
-
-       pipe_change(m66592, ep->pipenum);
-       disable_irq_empty(m66592, ep->pipenum);
-       pipe_start(m66592, ep->pipenum);
-
-       tmp = m66592_read(m66592, ep->fifoctr);
-       if (unlikely((tmp & M66592_FRDY) == 0))
-               pipe_irq_enable(m66592, ep->pipenum);
-       else
-               irq_packet_write(ep, req);
-}
-
-static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
-{
-       struct m66592 *m66592 = ep->m66592;
-       u16 pipenum = ep->pipenum;
-
-       if (ep->pipenum == 0) {
-               m66592_mdfy(m66592, M66592_PIPE0,
-                               (M66592_ISEL | M66592_CURPIPE),
-                               M66592_CFIFOSEL);
-               m66592_write(m66592, M66592_BCLR, ep->fifoctr);
-               pipe_start(m66592, pipenum);
-               pipe_irq_enable(m66592, pipenum);
-       } else {
-               if (ep->use_dma) {
-                       m66592_bset(m66592, M66592_TRCLR, ep->fifosel);
-                       pipe_change(m66592, pipenum);
-                       m66592_bset(m66592, M66592_TRENB, ep->fifosel);
-                       m66592_write(m66592,
-                               (req->req.length + ep->ep.maxpacket - 1)
-                                       / ep->ep.maxpacket,
-                               ep->fifotrn);
-               }
-               pipe_start(m66592, pipenum);    /* trigger once */
-               pipe_irq_enable(m66592, pipenum);
-       }
-}
-
-static void start_packet(struct m66592_ep *ep, struct m66592_request *req)
-{
-       if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
-               start_packet_write(ep, req);
-       else
-               start_packet_read(ep, req);
-}
-
-static void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
-{
-       u16 ctsq;
-
-       ctsq = m66592_read(ep->m66592, M66592_INTSTS0) & M66592_CTSQ;
-
-       switch (ctsq) {
-       case M66592_CS_RDDS:
-               start_ep0_write(ep, req);
-               break;
-       case M66592_CS_WRDS:
-               start_packet_read(ep, req);
-               break;
-
-       case M66592_CS_WRND:
-               control_end(ep->m66592, 0);
-               break;
-       default:
-               pr_err("start_ep0: unexpect ctsq(%x)\n", ctsq);
-               break;
-       }
-}
-
-static void init_controller(struct m66592 *m66592)
-{
-       unsigned int endian;
-
-       if (m66592->pdata->on_chip) {
-               if (m66592->pdata->endian)
-                       endian = 0; /* big endian */
-               else
-                       endian = M66592_LITTLE; /* little endian */
-
-               m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */
-               m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
-               m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
-               m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
-
-               /* This is a workaound for SH7722 2nd cut */
-               m66592_bset(m66592, 0x8000, M66592_DVSTCTR);
-               m66592_bset(m66592, 0x1000, M66592_TESTMODE);
-               m66592_bclr(m66592, 0x8000, M66592_DVSTCTR);
-
-               m66592_bset(m66592, M66592_INTL, M66592_INTENB1);
-
-               m66592_write(m66592, 0, M66592_CFBCFG);
-               m66592_write(m66592, 0, M66592_D0FBCFG);
-               m66592_bset(m66592, endian, M66592_CFBCFG);
-               m66592_bset(m66592, endian, M66592_D0FBCFG);
-       } else {
-               unsigned int clock, vif, irq_sense;
-
-               if (m66592->pdata->endian)
-                       endian = M66592_BIGEND; /* big endian */
-               else
-                       endian = 0; /* little endian */
-
-               if (m66592->pdata->vif)
-                       vif = M66592_LDRV; /* 3.3v */
-               else
-                       vif = 0; /* 1.5v */
-
-               switch (m66592->pdata->xtal) {
-               case M66592_PLATDATA_XTAL_12MHZ:
-                       clock = M66592_XTAL12;
-                       break;
-               case M66592_PLATDATA_XTAL_24MHZ:
-                       clock = M66592_XTAL24;
-                       break;
-               case M66592_PLATDATA_XTAL_48MHZ:
-                       clock = M66592_XTAL48;
-                       break;
-               default:
-                       pr_warning("m66592-udc: xtal configuration error\n");
-                       clock = 0;
-               }
-
-               switch (m66592->irq_trigger) {
-               case IRQF_TRIGGER_LOW:
-                       irq_sense = M66592_INTL;
-                       break;
-               case IRQF_TRIGGER_FALLING:
-                       irq_sense = 0;
-                       break;
-               default:
-                       pr_warning("m66592-udc: irq trigger config error\n");
-                       irq_sense = 0;
-               }
-
-               m66592_bset(m66592,
-                           (vif & M66592_LDRV) | (endian & M66592_BIGEND),
-                           M66592_PINCFG);
-               m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */
-               m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL,
-                           M66592_SYSCFG);
-               m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
-               m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
-               m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
-
-               m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
-
-               msleep(3);
-
-               m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
-
-               msleep(1);
-
-               m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
-
-               m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
-               m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
-                            M66592_DMA0CFG);
-       }
-}
-
-static void disable_controller(struct m66592 *m66592)
-{
-       m66592_bclr(m66592, M66592_UTST, M66592_TESTMODE);
-       if (!m66592->pdata->on_chip) {
-               m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
-               udelay(1);
-               m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
-               udelay(1);
-               m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
-               udelay(1);
-               m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
-       }
-}
-
-static void m66592_start_xclock(struct m66592 *m66592)
-{
-       u16 tmp;
-
-       if (!m66592->pdata->on_chip) {
-               tmp = m66592_read(m66592, M66592_SYSCFG);
-               if (!(tmp & M66592_XCKE))
-                       m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
-       }
-}
-
-/*-------------------------------------------------------------------------*/
-static void transfer_complete(struct m66592_ep *ep,
-               struct m66592_request *req, int status)
-__releases(m66592->lock)
-__acquires(m66592->lock)
-{
-       int restart = 0;
-
-       if (unlikely(ep->pipenum == 0)) {
-               if (ep->internal_ccpl) {
-                       ep->internal_ccpl = 0;
-                       return;
-               }
-       }
-
-       list_del_init(&req->queue);
-       if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
-               req->req.status = -ESHUTDOWN;
-       else
-               req->req.status = status;
-
-       if (!list_empty(&ep->queue))
-               restart = 1;
-
-       spin_unlock(&ep->m66592->lock);
-       req->req.complete(&ep->ep, &req->req);
-       spin_lock(&ep->m66592->lock);
-
-       if (restart) {
-               req = list_entry(ep->queue.next, struct m66592_request, queue);
-               if (ep->ep.desc)
-                       start_packet(ep, req);
-       }
-}
-
-static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
-{
-       int i;
-       u16 tmp;
-       unsigned bufsize;
-       size_t size;
-       void *buf;
-       u16 pipenum = ep->pipenum;
-       struct m66592 *m66592 = ep->m66592;
-
-       pipe_change(m66592, pipenum);
-       m66592_bset(m66592, M66592_ISEL, ep->fifosel);
-
-       i = 0;
-       do {
-               tmp = m66592_read(m66592, ep->fifoctr);
-               if (i++ > 100000) {
-                       pr_err("pipe0 is busy. maybe cpu i/o bus "
-                               "conflict. please power off this controller.");
-                       return;
-               }
-               ndelay(1);
-       } while ((tmp & M66592_FRDY) == 0);
-
-       /* prepare parameters */
-       bufsize = get_buffer_size(m66592, pipenum);
-       buf = req->req.buf + req->req.actual;
-       size = min(bufsize, req->req.length - req->req.actual);
-
-       /* write fifo */
-       if (req->req.buf) {
-               if (size > 0)
-                       m66592_write_fifo(m66592, ep, buf, size);
-               if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
-                       m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
-       }
-
-       /* update parameters */
-       req->req.actual += size;
-
-       /* check transfer finish */
-       if ((!req->req.zero && (req->req.actual == req->req.length))
-                       || (size % ep->ep.maxpacket)
-                       || (size == 0)) {
-               disable_irq_ready(m66592, pipenum);
-               disable_irq_empty(m66592, pipenum);
-       } else {
-               disable_irq_ready(m66592, pipenum);
-               enable_irq_empty(m66592, pipenum);
-       }
-       pipe_start(m66592, pipenum);
-}
-
-static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
-{
-       u16 tmp;
-       unsigned bufsize;
-       size_t size;
-       void *buf;
-       u16 pipenum = ep->pipenum;
-       struct m66592 *m66592 = ep->m66592;
-
-       pipe_change(m66592, pipenum);
-       tmp = m66592_read(m66592, ep->fifoctr);
-       if (unlikely((tmp & M66592_FRDY) == 0)) {
-               pipe_stop(m66592, pipenum);
-               pipe_irq_disable(m66592, pipenum);
-               pr_err("write fifo not ready. pipnum=%d\n", pipenum);
-               return;
-       }
-
-       /* prepare parameters */
-       bufsize = get_buffer_size(m66592, pipenum);
-       buf = req->req.buf + req->req.actual;
-       size = min(bufsize, req->req.length - req->req.actual);
-
-       /* write fifo */
-       if (req->req.buf) {
-               m66592_write_fifo(m66592, ep, buf, size);
-               if ((size == 0)
-                               || ((size % ep->ep.maxpacket) != 0)
-                               || ((bufsize != ep->ep.maxpacket)
-                                       && (bufsize > size)))
-                       m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
-       }
-
-       /* update parameters */
-       req->req.actual += size;
-       /* check transfer finish */
-       if ((!req->req.zero && (req->req.actual == req->req.length))
-                       || (size % ep->ep.maxpacket)
-                       || (size == 0)) {
-               disable_irq_ready(m66592, pipenum);
-               enable_irq_empty(m66592, pipenum);
-       } else {
-               disable_irq_empty(m66592, pipenum);
-               pipe_irq_enable(m66592, pipenum);
-       }
-}
-
-static void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req)
-{
-       u16 tmp;
-       int rcv_len, bufsize, req_len;
-       int size;
-       void *buf;
-       u16 pipenum = ep->pipenum;
-       struct m66592 *m66592 = ep->m66592;
-       int finish = 0;
-
-       pipe_change(m66592, pipenum);
-       tmp = m66592_read(m66592, ep->fifoctr);
-       if (unlikely((tmp & M66592_FRDY) == 0)) {
-               req->req.status = -EPIPE;
-               pipe_stop(m66592, pipenum);
-               pipe_irq_disable(m66592, pipenum);
-               pr_err("read fifo not ready");
-               return;
-       }
-
-       /* prepare parameters */
-       rcv_len = tmp & M66592_DTLN;
-       bufsize = get_buffer_size(m66592, pipenum);
-
-       buf = req->req.buf + req->req.actual;
-       req_len = req->req.length - req->req.actual;
-       if (rcv_len < bufsize)
-               size = min(rcv_len, req_len);
-       else
-               size = min(bufsize, req_len);
-
-       /* update parameters */
-       req->req.actual += size;
-
-       /* check transfer finish */
-       if ((!req->req.zero && (req->req.actual == req->req.length))
-                       || (size % ep->ep.maxpacket)
-                       || (size == 0)) {
-               pipe_stop(m66592, pipenum);
-               pipe_irq_disable(m66592, pipenum);
-               finish = 1;
-       }
-
-       /* read fifo */
-       if (req->req.buf) {
-               if (size == 0)
-                       m66592_write(m66592, M66592_BCLR, ep->fifoctr);
-               else
-                       m66592_read_fifo(m66592, ep->fifoaddr, buf, size);
-       }
-
-       if ((ep->pipenum != 0) && finish)
-               transfer_complete(ep, req, 0);
-}
-
-static void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb)
-{
-       u16 check;
-       u16 pipenum;
-       struct m66592_ep *ep;
-       struct m66592_request *req;
-
-       if ((status & M66592_BRDY0) && (enb & M66592_BRDY0)) {
-               m66592_write(m66592, ~M66592_BRDY0, M66592_BRDYSTS);
-               m66592_mdfy(m66592, M66592_PIPE0, M66592_CURPIPE,
-                               M66592_CFIFOSEL);
-
-               ep = &m66592->ep[0];
-               req = list_entry(ep->queue.next, struct m66592_request, queue);
-               irq_packet_read(ep, req);
-       } else {
-               for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
-                       check = 1 << pipenum;
-                       if ((status & check) && (enb & check)) {
-                               m66592_write(m66592, ~check, M66592_BRDYSTS);
-                               ep = m66592->pipenum2ep[pipenum];
-                               req = list_entry(ep->queue.next,
-                                                struct m66592_request, queue);
-                               if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
-                                       irq_packet_write(ep, req);
-                               else
-                                       irq_packet_read(ep, req);
-                       }
-               }
-       }
-}
-
-static void irq_pipe_empty(struct m66592 *m66592, u16 status, u16 enb)
-{
-       u16 tmp;
-       u16 check;
-       u16 pipenum;
-       struct m66592_ep *ep;
-       struct m66592_request *req;
-
-       if ((status & M66592_BEMP0) && (enb & M66592_BEMP0)) {
-               m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
-
-               ep = &m66592->ep[0];
-               req = list_entry(ep->queue.next, struct m66592_request, queue);
-               irq_ep0_write(ep, req);
-       } else {
-               for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
-                       check = 1 << pipenum;
-                       if ((status & check) && (enb & check)) {
-                               m66592_write(m66592, ~check, M66592_BEMPSTS);
-                               tmp = control_reg_get(m66592, pipenum);
-                               if ((tmp & M66592_INBUFM) == 0) {
-                                       disable_irq_empty(m66592, pipenum);
-                                       pipe_irq_disable(m66592, pipenum);
-                                       pipe_stop(m66592, pipenum);
-                                       ep = m66592->pipenum2ep[pipenum];
-                                       req = list_entry(ep->queue.next,
-                                                        struct m66592_request,
-                                                        queue);
-                                       if (!list_empty(&ep->queue))
-                                               transfer_complete(ep, req, 0);
-                               }
-                       }
-               }
-       }
-}
-
-static void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
-__releases(m66592->lock)
-__acquires(m66592->lock)
-{
-       struct m66592_ep *ep;
-       u16 pid;
-       u16 status = 0;
-       u16 w_index = le16_to_cpu(ctrl->wIndex);
-
-       switch (ctrl->bRequestType & USB_RECIP_MASK) {
-       case USB_RECIP_DEVICE:
-               status = 1 << USB_DEVICE_SELF_POWERED;
-               break;
-       case USB_RECIP_INTERFACE:
-               status = 0;
-               break;
-       case USB_RECIP_ENDPOINT:
-               ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
-               pid = control_reg_get_pid(m66592, ep->pipenum);
-               if (pid == M66592_PID_STALL)
-                       status = 1 << USB_ENDPOINT_HALT;
-               else
-                       status = 0;
-               break;
-       default:
-               pipe_stall(m66592, 0);
-               return;         /* exit */
-       }
-
-       m66592->ep0_data = cpu_to_le16(status);
-       m66592->ep0_req->buf = &m66592->ep0_data;
-       m66592->ep0_req->length = 2;
-       /* AV: what happens if we get called again before that gets through? */
-       spin_unlock(&m66592->lock);
-       m66592_queue(m66592->gadget.ep0, m66592->ep0_req, GFP_KERNEL);
-       spin_lock(&m66592->lock);
-}
-
-static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
-{
-       switch (ctrl->bRequestType & USB_RECIP_MASK) {
-       case USB_RECIP_DEVICE:
-               control_end(m66592, 1);
-               break;
-       case USB_RECIP_INTERFACE:
-               control_end(m66592, 1);
-               break;
-       case USB_RECIP_ENDPOINT: {
-               struct m66592_ep *ep;
-               struct m66592_request *req;
-               u16 w_index = le16_to_cpu(ctrl->wIndex);
-
-               ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
-               pipe_stop(m66592, ep->pipenum);
-               control_reg_sqclr(m66592, ep->pipenum);
-
-               control_end(m66592, 1);
-
-               req = list_entry(ep->queue.next,
-               struct m66592_request, queue);
-               if (ep->busy) {
-                       ep->busy = 0;
-                       if (list_empty(&ep->queue))
-                               break;
-                       start_packet(ep, req);
-               } else if (!list_empty(&ep->queue))
-                       pipe_start(m66592, ep->pipenum);
-               }
-               break;
-       default:
-               pipe_stall(m66592, 0);
-               break;
-       }
-}
-
-static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
-{
-       u16 tmp;
-       int timeout = 3000;
-
-       switch (ctrl->bRequestType & USB_RECIP_MASK) {
-       case USB_RECIP_DEVICE:
-               switch (le16_to_cpu(ctrl->wValue)) {
-               case USB_DEVICE_TEST_MODE:
-                       control_end(m66592, 1);
-                       /* Wait for the completion of status stage */
-                       do {
-                               tmp = m66592_read(m66592, M66592_INTSTS0) &
-                                                               M66592_CTSQ;
-                               udelay(1);
-                       } while (tmp != M66592_CS_IDST || timeout-- > 0);
-
-                       if (tmp == M66592_CS_IDST)
-                               m66592_bset(m66592,
-                                           le16_to_cpu(ctrl->wIndex >> 8),
-                                           M66592_TESTMODE);
-                       break;
-               default:
-                       pipe_stall(m66592, 0);
-                       break;
-               }
-               break;
-       case USB_RECIP_INTERFACE:
-               control_end(m66592, 1);
-               break;
-       case USB_RECIP_ENDPOINT: {
-               struct m66592_ep *ep;
-               u16 w_index = le16_to_cpu(ctrl->wIndex);
-
-               ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
-               pipe_stall(m66592, ep->pipenum);
-
-               control_end(m66592, 1);
-               }
-               break;
-       default:
-               pipe_stall(m66592, 0);
-               break;
-       }
-}
-
-/* if return value is true, call class driver's setup() */
-static int setup_packet(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
-{
-       u16 *p = (u16 *)ctrl;
-       unsigned long offset = M66592_USBREQ;
-       int i, ret = 0;
-
-       /* read fifo */
-       m66592_write(m66592, ~M66592_VALID, M66592_INTSTS0);
-
-       for (i = 0; i < 4; i++)
-               p[i] = m66592_read(m66592, offset + i*2);
-
-       /* check request */
-       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
-               switch (ctrl->bRequest) {
-               case USB_REQ_GET_STATUS:
-                       get_status(m66592, ctrl);
-                       break;
-               case USB_REQ_CLEAR_FEATURE:
-                       clear_feature(m66592, ctrl);
-                       break;
-               case USB_REQ_SET_FEATURE:
-                       set_feature(m66592, ctrl);
-                       break;
-               default:
-                       ret = 1;
-                       break;
-               }
-       } else
-               ret = 1;
-       return ret;
-}
-
-static void m66592_update_usb_speed(struct m66592 *m66592)
-{
-       u16 speed = get_usb_speed(m66592);
-
-       switch (speed) {
-       case M66592_HSMODE:
-               m66592->gadget.speed = USB_SPEED_HIGH;
-               break;
-       case M66592_FSMODE:
-               m66592->gadget.speed = USB_SPEED_FULL;
-               break;
-       default:
-               m66592->gadget.speed = USB_SPEED_UNKNOWN;
-               pr_err("USB speed unknown\n");
-       }
-}
-
-static void irq_device_state(struct m66592 *m66592)
-{
-       u16 dvsq;
-
-       dvsq = m66592_read(m66592, M66592_INTSTS0) & M66592_DVSQ;
-       m66592_write(m66592, ~M66592_DVST, M66592_INTSTS0);
-
-       if (dvsq == M66592_DS_DFLT) {   /* bus reset */
-               m66592->driver->disconnect(&m66592->gadget);
-               m66592_update_usb_speed(m66592);
-       }
-       if (m66592->old_dvsq == M66592_DS_CNFG && dvsq != M66592_DS_CNFG)
-               m66592_update_usb_speed(m66592);
-       if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS)
-                       && m66592->gadget.speed == USB_SPEED_UNKNOWN)
-               m66592_update_usb_speed(m66592);
-
-       m66592->old_dvsq = dvsq;
-}
-
-static void irq_control_stage(struct m66592 *m66592)
-__releases(m66592->lock)
-__acquires(m66592->lock)
-{
-       struct usb_ctrlrequest ctrl;
-       u16 ctsq;
-
-       ctsq = m66592_read(m66592, M66592_INTSTS0) & M66592_CTSQ;
-       m66592_write(m66592, ~M66592_CTRT, M66592_INTSTS0);
-
-       switch (ctsq) {
-       case M66592_CS_IDST: {
-               struct m66592_ep *ep;
-               struct m66592_request *req;
-               ep = &m66592->ep[0];
-               req = list_entry(ep->queue.next, struct m66592_request, queue);
-               transfer_complete(ep, req, 0);
-               }
-               break;
-
-       case M66592_CS_RDDS:
-       case M66592_CS_WRDS:
-       case M66592_CS_WRND:
-               if (setup_packet(m66592, &ctrl)) {
-                       spin_unlock(&m66592->lock);
-                       if (m66592->driver->setup(&m66592->gadget, &ctrl) < 0)
-                               pipe_stall(m66592, 0);
-                       spin_lock(&m66592->lock);
-               }
-               break;
-       case M66592_CS_RDSS:
-       case M66592_CS_WRSS:
-               control_end(m66592, 0);
-               break;
-       default:
-               pr_err("ctrl_stage: unexpect ctsq(%x)\n", ctsq);
-               break;
-       }
-}
-
-static irqreturn_t m66592_irq(int irq, void *_m66592)
-{
-       struct m66592 *m66592 = _m66592;
-       u16 intsts0;
-       u16 intenb0;
-       u16 brdysts, nrdysts, bempsts;
-       u16 brdyenb, nrdyenb, bempenb;
-       u16 savepipe;
-       u16 mask0;
-
-       spin_lock(&m66592->lock);
-
-       intsts0 = m66592_read(m66592, M66592_INTSTS0);
-       intenb0 = m66592_read(m66592, M66592_INTENB0);
-
-       if (m66592->pdata->on_chip && !intsts0 && !intenb0) {
-               /*
-                * When USB clock stops, it cannot read register. Even if a
-                * clock stops, the interrupt occurs. So this driver turn on
-                * a clock by this timing and do re-reading of register.
-                */
-               m66592_start_xclock(m66592);
-               intsts0 = m66592_read(m66592, M66592_INTSTS0);
-               intenb0 = m66592_read(m66592, M66592_INTENB0);
-       }
-
-       savepipe = m66592_read(m66592, M66592_CFIFOSEL);
-
-       mask0 = intsts0 & intenb0;
-       if (mask0) {
-               brdysts = m66592_read(m66592, M66592_BRDYSTS);
-               nrdysts = m66592_read(m66592, M66592_NRDYSTS);
-               bempsts = m66592_read(m66592, M66592_BEMPSTS);
-               brdyenb = m66592_read(m66592, M66592_BRDYENB);
-               nrdyenb = m66592_read(m66592, M66592_NRDYENB);
-               bempenb = m66592_read(m66592, M66592_BEMPENB);
-
-               if (mask0 & M66592_VBINT) {
-                       m66592_write(m66592,  0xffff & ~M66592_VBINT,
-                                       M66592_INTSTS0);
-                       m66592_start_xclock(m66592);
-
-                       /* start vbus sampling */
-                       m66592->old_vbus = m66592_read(m66592, M66592_INTSTS0)
-                                       & M66592_VBSTS;
-                       m66592->scount = M66592_MAX_SAMPLING;
-
-                       mod_timer(&m66592->timer,
-                                       jiffies + msecs_to_jiffies(50));
-               }
-               if (intsts0 & M66592_DVSQ)
-                       irq_device_state(m66592);
-
-               if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE)
-                               && (brdysts & brdyenb)) {
-                       irq_pipe_ready(m66592, brdysts, brdyenb);
-               }
-               if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE)
-                               && (bempsts & bempenb)) {
-                       irq_pipe_empty(m66592, bempsts, bempenb);
-               }
-
-               if (intsts0 & M66592_CTRT)
-                       irq_control_stage(m66592);
-       }
-
-       m66592_write(m66592, savepipe, M66592_CFIFOSEL);
-
-       spin_unlock(&m66592->lock);
-       return IRQ_HANDLED;
-}
-
-static void m66592_timer(unsigned long _m66592)
-{
-       struct m66592 *m66592 = (struct m66592 *)_m66592;
-       unsigned long flags;
-       u16 tmp;
-
-       spin_lock_irqsave(&m66592->lock, flags);
-       tmp = m66592_read(m66592, M66592_SYSCFG);
-       if (!(tmp & M66592_RCKE)) {
-               m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
-               udelay(10);
-               m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
-       }
-       if (m66592->scount > 0) {
-               tmp = m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS;
-               if (tmp == m66592->old_vbus) {
-                       m66592->scount--;
-                       if (m66592->scount == 0) {
-                               if (tmp == M66592_VBSTS)
-                                       m66592_usb_connect(m66592);
-                               else
-                                       m66592_usb_disconnect(m66592);
-                       } else {
-                               mod_timer(&m66592->timer,
-                                       jiffies + msecs_to_jiffies(50));
-                       }
-               } else {
-                       m66592->scount = M66592_MAX_SAMPLING;
-                       m66592->old_vbus = tmp;
-                       mod_timer(&m66592->timer,
-                                       jiffies + msecs_to_jiffies(50));
-               }
-       }
-       spin_unlock_irqrestore(&m66592->lock, flags);
-}
-
-/*-------------------------------------------------------------------------*/
-static int m66592_enable(struct usb_ep *_ep,
-                        const struct usb_endpoint_descriptor *desc)
-{
-       struct m66592_ep *ep;
-
-       ep = container_of(_ep, struct m66592_ep, ep);
-       return alloc_pipe_config(ep, desc);
-}
-
-static int m66592_disable(struct usb_ep *_ep)
-{
-       struct m66592_ep *ep;
-       struct m66592_request *req;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct m66592_ep, ep);
-       BUG_ON(!ep);
-
-       while (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next, struct m66592_request, queue);
-               spin_lock_irqsave(&ep->m66592->lock, flags);
-               transfer_complete(ep, req, -ECONNRESET);
-               spin_unlock_irqrestore(&ep->m66592->lock, flags);
-       }
-
-       pipe_irq_disable(ep->m66592, ep->pipenum);
-       return free_pipe_config(ep);
-}
-
-static struct usb_request *m66592_alloc_request(struct usb_ep *_ep,
-                                               gfp_t gfp_flags)
-{
-       struct m66592_request *req;
-
-       req = kzalloc(sizeof(struct m66592_request), gfp_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD(&req->queue);
-
-       return &req->req;
-}
-
-static void m66592_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct m66592_request *req;
-
-       req = container_of(_req, struct m66592_request, req);
-       kfree(req);
-}
-
-static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
-                       gfp_t gfp_flags)
-{
-       struct m66592_ep *ep;
-       struct m66592_request *req;
-       unsigned long flags;
-       int request = 0;
-
-       ep = container_of(_ep, struct m66592_ep, ep);
-       req = container_of(_req, struct m66592_request, req);
-
-       if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       spin_lock_irqsave(&ep->m66592->lock, flags);
-
-       if (list_empty(&ep->queue))
-               request = 1;
-
-       list_add_tail(&req->queue, &ep->queue);
-       req->req.actual = 0;
-       req->req.status = -EINPROGRESS;
-
-       if (ep->ep.desc == NULL)        /* control */
-               start_ep0(ep, req);
-       else {
-               if (request && !ep->busy)
-                       start_packet(ep, req);
-       }
-
-       spin_unlock_irqrestore(&ep->m66592->lock, flags);
-
-       return 0;
-}
-
-static int m66592_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct m66592_ep *ep;
-       struct m66592_request *req;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct m66592_ep, ep);
-       req = container_of(_req, struct m66592_request, req);
-
-       spin_lock_irqsave(&ep->m66592->lock, flags);
-       if (!list_empty(&ep->queue))
-               transfer_complete(ep, req, -ECONNRESET);
-       spin_unlock_irqrestore(&ep->m66592->lock, flags);
-
-       return 0;
-}
-
-static int m66592_set_halt(struct usb_ep *_ep, int value)
-{
-       struct m66592_ep *ep;
-       struct m66592_request *req;
-       unsigned long flags;
-       int ret = 0;
-
-       ep = container_of(_ep, struct m66592_ep, ep);
-       req = list_entry(ep->queue.next, struct m66592_request, queue);
-
-       spin_lock_irqsave(&ep->m66592->lock, flags);
-       if (!list_empty(&ep->queue)) {
-               ret = -EAGAIN;
-               goto out;
-       }
-       if (value) {
-               ep->busy = 1;
-               pipe_stall(ep->m66592, ep->pipenum);
-       } else {
-               ep->busy = 0;
-               pipe_stop(ep->m66592, ep->pipenum);
-       }
-
-out:
-       spin_unlock_irqrestore(&ep->m66592->lock, flags);
-       return ret;
-}
-
-static void m66592_fifo_flush(struct usb_ep *_ep)
-{
-       struct m66592_ep *ep;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct m66592_ep, ep);
-       spin_lock_irqsave(&ep->m66592->lock, flags);
-       if (list_empty(&ep->queue) && !ep->busy) {
-               pipe_stop(ep->m66592, ep->pipenum);
-               m66592_bclr(ep->m66592, M66592_BCLR, ep->fifoctr);
-       }
-       spin_unlock_irqrestore(&ep->m66592->lock, flags);
-}
-
-static struct usb_ep_ops m66592_ep_ops = {
-       .enable         = m66592_enable,
-       .disable        = m66592_disable,
-
-       .alloc_request  = m66592_alloc_request,
-       .free_request   = m66592_free_request,
-
-       .queue          = m66592_queue,
-       .dequeue        = m66592_dequeue,
-
-       .set_halt       = m66592_set_halt,
-       .fifo_flush     = m66592_fifo_flush,
-};
-
-/*-------------------------------------------------------------------------*/
-static int m66592_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct m66592 *m66592 = to_m66592(g);
-
-       /* hook up the driver */
-       driver->driver.bus = NULL;
-       m66592->driver = driver;
-
-       m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
-       if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
-               m66592_start_xclock(m66592);
-               /* start vbus sampling */
-               m66592->old_vbus = m66592_read(m66592,
-                                        M66592_INTSTS0) & M66592_VBSTS;
-               m66592->scount = M66592_MAX_SAMPLING;
-               mod_timer(&m66592->timer, jiffies + msecs_to_jiffies(50));
-       }
-
-       return 0;
-}
-
-static int m66592_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct m66592 *m66592 = to_m66592(g);
-
-       m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
-
-       init_controller(m66592);
-       disable_controller(m66592);
-
-       m66592->driver = NULL;
-
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-static int m66592_get_frame(struct usb_gadget *_gadget)
-{
-       struct m66592 *m66592 = gadget_to_m66592(_gadget);
-       return m66592_read(m66592, M66592_FRMNUM) & 0x03FF;
-}
-
-static int m66592_pullup(struct usb_gadget *gadget, int is_on)
-{
-       struct m66592 *m66592 = gadget_to_m66592(gadget);
-       unsigned long flags;
-
-       spin_lock_irqsave(&m66592->lock, flags);
-       if (is_on)
-               m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
-       else
-               m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
-       spin_unlock_irqrestore(&m66592->lock, flags);
-
-       return 0;
-}
-
-static const struct usb_gadget_ops m66592_gadget_ops = {
-       .get_frame              = m66592_get_frame,
-       .udc_start              = m66592_udc_start,
-       .udc_stop               = m66592_udc_stop,
-       .pullup                 = m66592_pullup,
-};
-
-static int __exit m66592_remove(struct platform_device *pdev)
-{
-       struct m66592           *m66592 = platform_get_drvdata(pdev);
-
-       usb_del_gadget_udc(&m66592->gadget);
-
-       del_timer_sync(&m66592->timer);
-       iounmap(m66592->reg);
-       free_irq(platform_get_irq(pdev, 0), m66592);
-       m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
-       if (m66592->pdata->on_chip) {
-               clk_disable(m66592->clk);
-               clk_put(m66592->clk);
-       }
-       kfree(m66592);
-       return 0;
-}
-
-static void nop_completion(struct usb_ep *ep, struct usb_request *r)
-{
-}
-
-static int m66592_probe(struct platform_device *pdev)
-{
-       struct resource *res, *ires;
-       void __iomem *reg = NULL;
-       struct m66592 *m66592 = NULL;
-       char clk_name[8];
-       int ret = 0;
-       int i;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENODEV;
-               pr_err("platform_get_resource error.\n");
-               goto clean_up;
-       }
-
-       ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!ires) {
-               ret = -ENODEV;
-               dev_err(&pdev->dev,
-                       "platform_get_resource IORESOURCE_IRQ error.\n");
-               goto clean_up;
-       }
-
-       reg = ioremap(res->start, resource_size(res));
-       if (reg == NULL) {
-               ret = -ENOMEM;
-               pr_err("ioremap error.\n");
-               goto clean_up;
-       }
-
-       if (dev_get_platdata(&pdev->dev) == NULL) {
-               dev_err(&pdev->dev, "no platform data\n");
-               ret = -ENODEV;
-               goto clean_up;
-       }
-
-       /* initialize ucd */
-       m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
-       if (m66592 == NULL) {
-               ret = -ENOMEM;
-               goto clean_up;
-       }
-
-       m66592->pdata = dev_get_platdata(&pdev->dev);
-       m66592->irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
-
-       spin_lock_init(&m66592->lock);
-       platform_set_drvdata(pdev, m66592);
-
-       m66592->gadget.ops = &m66592_gadget_ops;
-       m66592->gadget.max_speed = USB_SPEED_HIGH;
-       m66592->gadget.name = udc_name;
-
-       init_timer(&m66592->timer);
-       m66592->timer.function = m66592_timer;
-       m66592->timer.data = (unsigned long)m66592;
-       m66592->reg = reg;
-
-       ret = request_irq(ires->start, m66592_irq, IRQF_SHARED,
-                       udc_name, m66592);
-       if (ret < 0) {
-               pr_err("request_irq error (%d)\n", ret);
-               goto clean_up;
-       }
-
-       if (m66592->pdata->on_chip) {
-               snprintf(clk_name, sizeof(clk_name), "usbf%d", pdev->id);
-               m66592->clk = clk_get(&pdev->dev, clk_name);
-               if (IS_ERR(m66592->clk)) {
-                       dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
-                               clk_name);
-                       ret = PTR_ERR(m66592->clk);
-                       goto clean_up2;
-               }
-               clk_enable(m66592->clk);
-       }
-
-       INIT_LIST_HEAD(&m66592->gadget.ep_list);
-       m66592->gadget.ep0 = &m66592->ep[0].ep;
-       INIT_LIST_HEAD(&m66592->gadget.ep0->ep_list);
-       for (i = 0; i < M66592_MAX_NUM_PIPE; i++) {
-               struct m66592_ep *ep = &m66592->ep[i];
-
-               if (i != 0) {
-                       INIT_LIST_HEAD(&m66592->ep[i].ep.ep_list);
-                       list_add_tail(&m66592->ep[i].ep.ep_list,
-                                       &m66592->gadget.ep_list);
-               }
-               ep->m66592 = m66592;
-               INIT_LIST_HEAD(&ep->queue);
-               ep->ep.name = m66592_ep_name[i];
-               ep->ep.ops = &m66592_ep_ops;
-               usb_ep_set_maxpacket_limit(&ep->ep, 512);
-       }
-       usb_ep_set_maxpacket_limit(&m66592->ep[0].ep, 64);
-       m66592->ep[0].pipenum = 0;
-       m66592->ep[0].fifoaddr = M66592_CFIFO;
-       m66592->ep[0].fifosel = M66592_CFIFOSEL;
-       m66592->ep[0].fifoctr = M66592_CFIFOCTR;
-       m66592->ep[0].fifotrn = 0;
-       m66592->ep[0].pipectr = get_pipectr_addr(0);
-       m66592->pipenum2ep[0] = &m66592->ep[0];
-       m66592->epaddr2ep[0] = &m66592->ep[0];
-
-       m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
-       if (m66592->ep0_req == NULL) {
-               ret = -ENOMEM;
-               goto clean_up3;
-       }
-       m66592->ep0_req->complete = nop_completion;
-
-       init_controller(m66592);
-
-       ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
-       if (ret)
-               goto err_add_udc;
-
-       dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
-       return 0;
-
-err_add_udc:
-       m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
-
-clean_up3:
-       if (m66592->pdata->on_chip) {
-               clk_disable(m66592->clk);
-               clk_put(m66592->clk);
-       }
-clean_up2:
-       free_irq(ires->start, m66592);
-clean_up:
-       if (m66592) {
-               if (m66592->ep0_req)
-                       m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
-               kfree(m66592);
-       }
-       if (reg)
-               iounmap(reg);
-
-       return ret;
-}
-
-/*-------------------------------------------------------------------------*/
-static struct platform_driver m66592_driver = {
-       .remove =       __exit_p(m66592_remove),
-       .driver         = {
-               .name = (char *) udc_name,
-               .owner  = THIS_MODULE,
-       },
-};
-
-module_platform_driver_probe(m66592_driver, m66592_probe);
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
deleted file mode 100644 (file)
index 96d49d7..0000000
+++ /dev/null
@@ -1,606 +0,0 @@
-/*
- * M66592 UDC (USB gadget)
- *
- * Copyright (C) 2006-2007 Renesas Solutions Corp.
- *
- * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- */
-
-#ifndef __M66592_UDC_H__
-#define __M66592_UDC_H__
-
-#include <linux/clk.h>
-#include <linux/usb/m66592.h>
-
-#define M66592_SYSCFG          0x00
-#define M66592_XTAL            0xC000  /* b15-14: Crystal selection */
-#define   M66592_XTAL48                 0x8000         /* 48MHz */
-#define   M66592_XTAL24                 0x4000         /* 24MHz */
-#define   M66592_XTAL12                 0x0000         /* 12MHz */
-#define M66592_XCKE            0x2000  /* b13: External clock enable */
-#define M66592_RCKE            0x1000  /* b12: Register clock enable */
-#define M66592_PLLC            0x0800  /* b11: PLL control */
-#define M66592_SCKE            0x0400  /* b10: USB clock enable */
-#define M66592_ATCKM           0x0100  /* b8: Automatic clock supply */
-#define M66592_HSE             0x0080  /* b7: Hi-speed enable */
-#define M66592_DCFM            0x0040  /* b6: Controller function select  */
-#define M66592_DMRPD           0x0020  /* b5: D- pull down control */
-#define M66592_DPRPU           0x0010  /* b4: D+ pull up control */
-#define M66592_FSRPC           0x0004  /* b2: Full-speed receiver enable */
-#define M66592_PCUT            0x0002  /* b1: Low power sleep enable */
-#define M66592_USBE            0x0001  /* b0: USB module operation enable */
-
-#define M66592_SYSSTS          0x02
-#define M66592_LNST            0x0003  /* b1-0: D+, D- line status */
-#define   M66592_SE1            0x0003         /* SE1 */
-#define   M66592_KSTS           0x0002         /* K State */
-#define   M66592_JSTS           0x0001         /* J State */
-#define   M66592_SE0            0x0000         /* SE0 */
-
-#define M66592_DVSTCTR         0x04
-#define M66592_WKUP            0x0100  /* b8: Remote wakeup */
-#define M66592_RWUPE           0x0080  /* b7: Remote wakeup sense */
-#define M66592_USBRST          0x0040  /* b6: USB reset enable */
-#define M66592_RESUME          0x0020  /* b5: Resume enable */
-#define M66592_UACT            0x0010  /* b4: USB bus enable */
-#define M66592_RHST            0x0003  /* b1-0: Reset handshake status */
-#define   M66592_HSMODE                 0x0003         /* Hi-Speed mode */
-#define   M66592_FSMODE                 0x0002         /* Full-Speed mode */
-#define   M66592_HSPROC                 0x0001         /* HS handshake is processing */
-
-#define M66592_TESTMODE                0x06
-#define M66592_UTST            0x000F  /* b4-0: Test select */
-#define   M66592_H_TST_PACKET   0x000C         /* HOST TEST Packet */
-#define   M66592_H_TST_SE0_NAK  0x000B         /* HOST TEST SE0 NAK */
-#define   M66592_H_TST_K        0x000A         /* HOST TEST K */
-#define   M66592_H_TST_J        0x0009         /* HOST TEST J */
-#define   M66592_H_TST_NORMAL   0x0000         /* HOST Normal Mode */
-#define   M66592_P_TST_PACKET   0x0004         /* PERI TEST Packet */
-#define   M66592_P_TST_SE0_NAK  0x0003         /* PERI TEST SE0 NAK */
-#define   M66592_P_TST_K        0x0002         /* PERI TEST K */
-#define   M66592_P_TST_J        0x0001         /* PERI TEST J */
-#define   M66592_P_TST_NORMAL   0x0000         /* PERI Normal Mode */
-
-/* built-in registers */
-#define M66592_CFBCFG          0x0A
-#define M66592_D0FBCFG         0x0C
-#define M66592_LITTLE          0x0100  /* b8: Little endian mode */
-/* external chip case */
-#define M66592_PINCFG          0x0A
-#define M66592_LDRV            0x8000  /* b15: Drive Current Adjust */
-#define M66592_BIGEND          0x0100  /* b8: Big endian mode */
-
-#define M66592_DMA0CFG         0x0C
-#define M66592_DMA1CFG         0x0E
-#define M66592_DREQA           0x4000  /* b14: Dreq active select */
-#define M66592_BURST           0x2000  /* b13: Burst mode */
-#define M66592_DACKA           0x0400  /* b10: Dack active select */
-#define M66592_DFORM           0x0380  /* b9-7: DMA mode select */
-#define   M66592_CPU_ADR_RD_WR  0x0000   /* Address + RD/WR mode (CPU bus) */
-#define   M66592_CPU_DACK_RD_WR         0x0100   /* DACK + RD/WR mode (CPU bus) */
-#define   M66592_CPU_DACK_ONLY  0x0180   /* DACK only mode (CPU bus) */
-#define   M66592_SPLIT_DACK_ONLY 0x0200   /* DACK only mode (SPLIT bus) */
-#define   M66592_SPLIT_DACK_DSTB 0x0300   /* DACK + DSTB0 mode (SPLIT bus) */
-#define M66592_DENDA           0x0040  /* b6: Dend active select */
-#define M66592_PKTM            0x0020  /* b5: Packet mode */
-#define M66592_DENDE           0x0010  /* b4: Dend enable */
-#define M66592_OBUS            0x0004  /* b2: OUTbus mode */
-
-/* common case */
-#define M66592_CFIFO           0x10
-#define M66592_D0FIFO          0x14
-#define M66592_D1FIFO          0x18
-
-#define M66592_CFIFOSEL                0x1E
-#define M66592_D0FIFOSEL       0x24
-#define M66592_D1FIFOSEL       0x2A
-#define M66592_RCNT            0x8000  /* b15: Read count mode */
-#define M66592_REW             0x4000  /* b14: Buffer rewind */
-#define M66592_DCLRM           0x2000  /* b13: DMA buffer clear mode */
-#define M66592_DREQE           0x1000  /* b12: DREQ output enable */
-#define M66592_MBW_8           0x0000   /*  8bit */
-#define M66592_MBW_16          0x0400   /* 16bit */
-#define M66592_MBW_32          0x0800   /* 32bit */
-#define M66592_TRENB           0x0200  /* b9: Transaction counter enable */
-#define M66592_TRCLR           0x0100  /* b8: Transaction counter clear */
-#define M66592_DEZPM           0x0080  /* b7: Zero-length packet mode */
-#define M66592_ISEL            0x0020  /* b5: DCP FIFO port direction select */
-#define M66592_CURPIPE         0x0007  /* b2-0: PIPE select */
-
-#define M66592_CFIFOCTR                0x20
-#define M66592_D0FIFOCTR       0x26
-#define M66592_D1FIFOCTR       0x2c
-#define M66592_BVAL            0x8000  /* b15: Buffer valid flag */
-#define M66592_BCLR            0x4000  /* b14: Buffer clear */
-#define M66592_FRDY            0x2000  /* b13: FIFO ready */
-#define M66592_DTLN            0x0FFF  /* b11-0: FIFO received data length */
-
-#define M66592_CFIFOSIE                0x22
-#define M66592_TGL             0x8000  /* b15: Buffer toggle */
-#define M66592_SCLR            0x4000  /* b14: Buffer clear */
-#define M66592_SBUSY           0x2000  /* b13: SIE_FIFO busy */
-
-#define M66592_D0FIFOTRN       0x28
-#define M66592_D1FIFOTRN       0x2E
-#define M66592_TRNCNT          0xFFFF  /* b15-0: Transaction counter */
-
-#define M66592_INTENB0 0x30
-#define M66592_VBSE    0x8000  /* b15: VBUS interrupt */
-#define M66592_RSME    0x4000  /* b14: Resume interrupt */
-#define M66592_SOFE    0x2000  /* b13: Frame update interrupt */
-#define M66592_DVSE    0x1000  /* b12: Device state transition interrupt */
-#define M66592_CTRE    0x0800  /* b11: Control transfer stage transition irq */
-#define M66592_BEMPE   0x0400  /* b10: Buffer empty interrupt */
-#define M66592_NRDYE   0x0200  /* b9: Buffer not ready interrupt */
-#define M66592_BRDYE   0x0100  /* b8: Buffer ready interrupt */
-#define M66592_URST    0x0080  /* b7: USB reset detected interrupt */
-#define M66592_SADR    0x0040  /* b6: Set address executed interrupt */
-#define M66592_SCFG    0x0020  /* b5: Set configuration executed interrupt */
-#define M66592_SUSP    0x0010  /* b4: Suspend detected interrupt */
-#define M66592_WDST    0x0008  /* b3: Control write data stage completed irq */
-#define M66592_RDST    0x0004  /* b2: Control read data stage completed irq */
-#define M66592_CMPL    0x0002  /* b1: Control transfer complete interrupt */
-#define M66592_SERR    0x0001  /* b0: Sequence error interrupt */
-
-#define M66592_INTENB1 0x32
-#define M66592_BCHGE   0x4000  /* b14: USB us chenge interrupt */
-#define M66592_DTCHE   0x1000  /* b12: Detach sense interrupt */
-#define M66592_SIGNE   0x0020  /* b5: SETUP IGNORE interrupt */
-#define M66592_SACKE   0x0010  /* b4: SETUP ACK interrupt */
-#define M66592_BRDYM   0x0004  /* b2: BRDY clear timing */
-#define M66592_INTL    0x0002  /* b1: Interrupt sense select */
-#define M66592_PCSE    0x0001  /* b0: PCUT enable by CS assert */
-
-#define M66592_BRDYENB         0x36
-#define M66592_BRDYSTS         0x46
-#define M66592_BRDY7           0x0080  /* b7: PIPE7 */
-#define M66592_BRDY6           0x0040  /* b6: PIPE6 */
-#define M66592_BRDY5           0x0020  /* b5: PIPE5 */
-#define M66592_BRDY4           0x0010  /* b4: PIPE4 */
-#define M66592_BRDY3           0x0008  /* b3: PIPE3 */
-#define M66592_BRDY2           0x0004  /* b2: PIPE2 */
-#define M66592_BRDY1           0x0002  /* b1: PIPE1 */
-#define M66592_BRDY0           0x0001  /* b1: PIPE0 */
-
-#define M66592_NRDYENB         0x38
-#define M66592_NRDYSTS         0x48
-#define M66592_NRDY7           0x0080  /* b7: PIPE7 */
-#define M66592_NRDY6           0x0040  /* b6: PIPE6 */
-#define M66592_NRDY5           0x0020  /* b5: PIPE5 */
-#define M66592_NRDY4           0x0010  /* b4: PIPE4 */
-#define M66592_NRDY3           0x0008  /* b3: PIPE3 */
-#define M66592_NRDY2           0x0004  /* b2: PIPE2 */
-#define M66592_NRDY1           0x0002  /* b1: PIPE1 */
-#define M66592_NRDY0           0x0001  /* b1: PIPE0 */
-
-#define M66592_BEMPENB         0x3A
-#define M66592_BEMPSTS         0x4A
-#define M66592_BEMP7           0x0080  /* b7: PIPE7 */
-#define M66592_BEMP6           0x0040  /* b6: PIPE6 */
-#define M66592_BEMP5           0x0020  /* b5: PIPE5 */
-#define M66592_BEMP4           0x0010  /* b4: PIPE4 */
-#define M66592_BEMP3           0x0008  /* b3: PIPE3 */
-#define M66592_BEMP2           0x0004  /* b2: PIPE2 */
-#define M66592_BEMP1           0x0002  /* b1: PIPE1 */
-#define M66592_BEMP0           0x0001  /* b0: PIPE0 */
-
-#define M66592_SOFCFG          0x3C
-#define M66592_SOFM            0x000C  /* b3-2: SOF palse mode */
-#define   M66592_SOF_125US      0x0008   /* SOF OUT 125us uFrame Signal */
-#define   M66592_SOF_1MS        0x0004   /* SOF OUT 1ms Frame Signal */
-#define   M66592_SOF_DISABLE    0x0000   /* SOF OUT Disable */
-
-#define M66592_INTSTS0         0x40
-#define M66592_VBINT           0x8000  /* b15: VBUS interrupt */
-#define M66592_RESM            0x4000  /* b14: Resume interrupt */
-#define M66592_SOFR            0x2000  /* b13: SOF frame update interrupt */
-#define M66592_DVST            0x1000  /* b12: Device state transition */
-#define M66592_CTRT            0x0800  /* b11: Control stage transition */
-#define M66592_BEMP            0x0400  /* b10: Buffer empty interrupt */
-#define M66592_NRDY            0x0200  /* b9: Buffer not ready interrupt */
-#define M66592_BRDY            0x0100  /* b8: Buffer ready interrupt */
-#define M66592_VBSTS           0x0080  /* b7: VBUS input port */
-#define M66592_DVSQ            0x0070  /* b6-4: Device state */
-#define   M66592_DS_SPD_CNFG    0x0070    /* Suspend Configured */
-#define   M66592_DS_SPD_ADDR    0x0060    /* Suspend Address */
-#define   M66592_DS_SPD_DFLT    0x0050    /* Suspend Default */
-#define   M66592_DS_SPD_POWR    0x0040    /* Suspend Powered */
-#define   M66592_DS_SUSP        0x0040    /* Suspend */
-#define   M66592_DS_CNFG        0x0030    /* Configured */
-#define   M66592_DS_ADDS        0x0020    /* Address */
-#define   M66592_DS_DFLT        0x0010    /* Default */
-#define   M66592_DS_POWR        0x0000    /* Powered */
-#define M66592_DVSQS           0x0030  /* b5-4: Device state */
-#define M66592_VALID           0x0008  /* b3: Setup packet detected flag */
-#define M66592_CTSQ            0x0007  /* b2-0: Control transfer stage */
-#define   M66592_CS_SQER        0x0006   /* Sequence error */
-#define   M66592_CS_WRND        0x0005   /* Control write nodata status */
-#define   M66592_CS_WRSS        0x0004   /* Control write status stage */
-#define   M66592_CS_WRDS        0x0003   /* Control write data stage */
-#define   M66592_CS_RDSS        0x0002   /* Control read status stage */
-#define   M66592_CS_RDDS        0x0001   /* Control read data stage */
-#define   M66592_CS_IDST        0x0000   /* Idle or setup stage */
-
-#define M66592_INTSTS1         0x42
-#define M66592_BCHG            0x4000  /* b14: USB bus chenge interrupt */
-#define M66592_DTCH            0x1000  /* b12: Detach sense interrupt */
-#define M66592_SIGN            0x0020  /* b5: SETUP IGNORE interrupt */
-#define M66592_SACK            0x0010  /* b4: SETUP ACK interrupt */
-
-#define M66592_FRMNUM          0x4C
-#define M66592_OVRN            0x8000  /* b15: Overrun error */
-#define M66592_CRCE            0x4000  /* b14: Received data error */
-#define M66592_SOFRM           0x0800  /* b11: SOF output mode */
-#define M66592_FRNM            0x07FF  /* b10-0: Frame number */
-
-#define M66592_UFRMNUM         0x4E
-#define M66592_UFRNM           0x0007  /* b2-0: Micro frame number */
-
-#define M66592_RECOVER         0x50
-#define M66592_STSRECOV                0x0700  /* Status recovery */
-#define   M66592_STSR_HI        0x0400           /* FULL(0) or HI(1) Speed */
-#define   M66592_STSR_DEFAULT   0x0100           /* Default state */
-#define   M66592_STSR_ADDRESS   0x0200           /* Address state */
-#define   M66592_STSR_CONFIG    0x0300           /* Configured state */
-#define M66592_USBADDR         0x007F  /* b6-0: USB address */
-
-#define M66592_USBREQ                  0x54
-#define M66592_bRequest                        0xFF00  /* b15-8: bRequest */
-#define   M66592_GET_STATUS             0x0000
-#define   M66592_CLEAR_FEATURE          0x0100
-#define   M66592_ReqRESERVED            0x0200
-#define   M66592_SET_FEATURE            0x0300
-#define   M66592_ReqRESERVED1           0x0400
-#define   M66592_SET_ADDRESS            0x0500
-#define   M66592_GET_DESCRIPTOR                 0x0600
-#define   M66592_SET_DESCRIPTOR                 0x0700
-#define   M66592_GET_CONFIGURATION      0x0800
-#define   M66592_SET_CONFIGURATION      0x0900
-#define   M66592_GET_INTERFACE          0x0A00
-#define   M66592_SET_INTERFACE          0x0B00
-#define   M66592_SYNCH_FRAME            0x0C00
-#define M66592_bmRequestType           0x00FF  /* b7-0: bmRequestType */
-#define M66592_bmRequestTypeDir                0x0080  /* b7  : Data direction */
-#define   M66592_HOST_TO_DEVICE                 0x0000
-#define   M66592_DEVICE_TO_HOST                 0x0080
-#define M66592_bmRequestTypeType       0x0060  /* b6-5: Type */
-#define   M66592_STANDARD               0x0000
-#define   M66592_CLASS                  0x0020
-#define   M66592_VENDOR                         0x0040
-#define M66592_bmRequestTypeRecip      0x001F  /* b4-0: Recipient */
-#define   M66592_DEVICE                         0x0000
-#define   M66592_INTERFACE              0x0001
-#define   M66592_ENDPOINT               0x0002
-
-#define M66592_USBVAL                          0x56
-#define M66592_wValue                          0xFFFF  /* b15-0: wValue */
-/* Standard Feature Selector */
-#define   M66592_ENDPOINT_HALT                 0x0000
-#define   M66592_DEVICE_REMOTE_WAKEUP          0x0001
-#define   M66592_TEST_MODE                     0x0002
-/* Descriptor Types */
-#define M66592_DT_TYPE                         0xFF00
-#define M66592_GET_DT_TYPE(v)                  (((v) & DT_TYPE) >> 8)
-#define   M66592_DT_DEVICE                     0x01
-#define   M66592_DT_CONFIGURATION              0x02
-#define   M66592_DT_STRING                     0x03
-#define   M66592_DT_INTERFACE                  0x04
-#define   M66592_DT_ENDPOINT                   0x05
-#define   M66592_DT_DEVICE_QUALIFIER           0x06
-#define   M66592_DT_OTHER_SPEED_CONFIGURATION  0x07
-#define   M66592_DT_INTERFACE_POWER            0x08
-#define M66592_DT_INDEX                                0x00FF
-#define M66592_CONF_NUM                                0x00FF
-#define M66592_ALT_SET                         0x00FF
-
-#define M66592_USBINDEX                        0x58
-#define M66592_wIndex                  0xFFFF  /* b15-0: wIndex */
-#define M66592_TEST_SELECT             0xFF00  /* b15-b8: Test Mode */
-#define   M66592_TEST_J                         0x0100   /* Test_J */
-#define   M66592_TEST_K                         0x0200   /* Test_K */
-#define   M66592_TEST_SE0_NAK           0x0300   /* Test_SE0_NAK */
-#define   M66592_TEST_PACKET            0x0400   /* Test_Packet */
-#define   M66592_TEST_FORCE_ENABLE      0x0500   /* Test_Force_Enable */
-#define   M66592_TEST_STSelectors       0x0600   /* Standard test selectors */
-#define   M66592_TEST_Reserved          0x4000   /* Reserved */
-#define   M66592_TEST_VSTModes          0xC000   /* Vendor-specific tests */
-#define M66592_EP_DIR                  0x0080  /* b7: Endpoint Direction */
-#define   M66592_EP_DIR_IN              0x0080
-#define   M66592_EP_DIR_OUT             0x0000
-
-#define M66592_USBLENG         0x5A
-#define M66592_wLength         0xFFFF  /* b15-0: wLength */
-
-#define M66592_DCPCFG          0x5C
-#define M66592_CNTMD           0x0100  /* b8: Continuous transfer mode */
-#define M66592_DIR             0x0010  /* b4: Control transfer DIR select */
-
-#define M66592_DCPMAXP         0x5E
-#define M66592_DEVSEL          0xC000  /* b15-14: Device address select */
-#define   M66592_DEVICE_0       0x0000           /* Device address 0 */
-#define   M66592_DEVICE_1       0x4000           /* Device address 1 */
-#define   M66592_DEVICE_2       0x8000           /* Device address 2 */
-#define   M66592_DEVICE_3       0xC000           /* Device address 3 */
-#define M66592_MAXP            0x007F  /* b6-0: Maxpacket size of ep0 */
-
-#define M66592_DCPCTR          0x60
-#define M66592_BSTS            0x8000  /* b15: Buffer status */
-#define M66592_SUREQ           0x4000  /* b14: Send USB request  */
-#define M66592_SQCLR           0x0100  /* b8: Sequence toggle bit clear */
-#define M66592_SQSET           0x0080  /* b7: Sequence toggle bit set */
-#define M66592_SQMON           0x0040  /* b6: Sequence toggle bit monitor */
-#define M66592_CCPL            0x0004  /* b2: control transfer complete */
-#define M66592_PID             0x0003  /* b1-0: Response PID */
-#define   M66592_PID_STALL      0x0002           /* STALL */
-#define   M66592_PID_BUF        0x0001           /* BUF */
-#define   M66592_PID_NAK        0x0000           /* NAK */
-
-#define M66592_PIPESEL         0x64
-#define M66592_PIPENM          0x0007  /* b2-0: Pipe select */
-#define   M66592_PIPE0          0x0000           /* PIPE 0 */
-#define   M66592_PIPE1          0x0001           /* PIPE 1 */
-#define   M66592_PIPE2          0x0002           /* PIPE 2 */
-#define   M66592_PIPE3          0x0003           /* PIPE 3 */
-#define   M66592_PIPE4          0x0004           /* PIPE 4 */
-#define   M66592_PIPE5          0x0005           /* PIPE 5 */
-#define   M66592_PIPE6          0x0006           /* PIPE 6 */
-#define   M66592_PIPE7          0x0007           /* PIPE 7 */
-
-#define M66592_PIPECFG         0x66
-#define M66592_TYP             0xC000  /* b15-14: Transfer type */
-#define   M66592_ISO            0xC000           /* Isochronous */
-#define   M66592_INT            0x8000           /* Interrupt */
-#define   M66592_BULK           0x4000           /* Bulk */
-#define M66592_BFRE            0x0400  /* b10: Buffer ready interrupt mode */
-#define M66592_DBLB            0x0200  /* b9: Double buffer mode select */
-#define M66592_CNTMD           0x0100  /* b8: Continuous transfer mode */
-#define M66592_SHTNAK          0x0080  /* b7: Transfer end NAK */
-#define M66592_DIR             0x0010  /* b4: Transfer direction select */
-#define   M66592_DIR_H_OUT      0x0010           /* HOST OUT */
-#define   M66592_DIR_P_IN       0x0010           /* PERI IN */
-#define   M66592_DIR_H_IN       0x0000           /* HOST IN */
-#define   M66592_DIR_P_OUT      0x0000           /* PERI OUT */
-#define M66592_EPNUM           0x000F  /* b3-0: Eendpoint number select */
-#define   M66592_EP1            0x0001
-#define   M66592_EP2            0x0002
-#define   M66592_EP3            0x0003
-#define   M66592_EP4            0x0004
-#define   M66592_EP5            0x0005
-#define   M66592_EP6            0x0006
-#define   M66592_EP7            0x0007
-#define   M66592_EP8            0x0008
-#define   M66592_EP9            0x0009
-#define   M66592_EP10           0x000A
-#define   M66592_EP11           0x000B
-#define   M66592_EP12           0x000C
-#define   M66592_EP13           0x000D
-#define   M66592_EP14           0x000E
-#define   M66592_EP15           0x000F
-
-#define M66592_PIPEBUF         0x68
-#define M66592_BUFSIZE         0x7C00  /* b14-10: Pipe buffer size */
-#define M66592_BUF_SIZE(x)     ((((x) / 64) - 1) << 10)
-#define M66592_BUFNMB          0x00FF  /* b7-0: Pipe buffer number */
-
-#define M66592_PIPEMAXP                0x6A
-#define M66592_MXPS            0x07FF  /* b10-0: Maxpacket size */
-
-#define M66592_PIPEPERI                0x6C
-#define M66592_IFIS            0x1000  /* b12: ISO in-buffer flush mode */
-#define M66592_IITV            0x0007  /* b2-0: ISO interval */
-
-#define M66592_PIPE1CTR                0x70
-#define M66592_PIPE2CTR                0x72
-#define M66592_PIPE3CTR                0x74
-#define M66592_PIPE4CTR                0x76
-#define M66592_PIPE5CTR                0x78
-#define M66592_PIPE6CTR                0x7A
-#define M66592_PIPE7CTR                0x7C
-#define M66592_BSTS            0x8000  /* b15: Buffer status */
-#define M66592_INBUFM          0x4000  /* b14: IN buffer monitor (PIPE 1-5) */
-#define M66592_ACLRM           0x0200  /* b9: Out buffer auto clear mode */
-#define M66592_SQCLR           0x0100  /* b8: Sequence toggle bit clear */
-#define M66592_SQSET           0x0080  /* b7: Sequence toggle bit set */
-#define M66592_SQMON           0x0040  /* b6: Sequence toggle bit monitor */
-#define M66592_PID             0x0003  /* b1-0: Response PID */
-
-#define M66592_INVALID_REG     0x7E
-
-
-#define get_pipectr_addr(pipenum)      (M66592_PIPE1CTR + (pipenum - 1) * 2)
-
-#define M66592_MAX_SAMPLING    10
-
-#define M66592_MAX_NUM_PIPE    8
-#define M66592_MAX_NUM_BULK    3
-#define M66592_MAX_NUM_ISOC    2
-#define M66592_MAX_NUM_INT     2
-
-#define M66592_BASE_PIPENUM_BULK       3
-#define M66592_BASE_PIPENUM_ISOC       1
-#define M66592_BASE_PIPENUM_INT                6
-
-#define M66592_BASE_BUFNUM     6
-#define M66592_MAX_BUFNUM      0x4F
-
-struct m66592_pipe_info {
-       u16     pipe;
-       u16     epnum;
-       u16     maxpacket;
-       u16     type;
-       u16     interval;
-       u16     dir_in;
-};
-
-struct m66592_request {
-       struct usb_request      req;
-       struct list_head        queue;
-};
-
-struct m66592_ep {
-       struct usb_ep           ep;
-       struct m66592           *m66592;
-
-       struct list_head        queue;
-       unsigned                busy:1;
-       unsigned                internal_ccpl:1;        /* use only control */
-
-       /* this member can able to after m66592_enable */
-       unsigned                use_dma:1;
-       u16                     pipenum;
-       u16                     type;
-
-       /* register address */
-       unsigned long           fifoaddr;
-       unsigned long           fifosel;
-       unsigned long           fifoctr;
-       unsigned long           fifotrn;
-       unsigned long           pipectr;
-};
-
-struct m66592 {
-       spinlock_t              lock;
-       void __iomem            *reg;
-       struct clk *clk;
-       struct m66592_platdata  *pdata;
-       unsigned long           irq_trigger;
-
-       struct usb_gadget               gadget;
-       struct usb_gadget_driver        *driver;
-
-       struct m66592_ep        ep[M66592_MAX_NUM_PIPE];
-       struct m66592_ep        *pipenum2ep[M66592_MAX_NUM_PIPE];
-       struct m66592_ep        *epaddr2ep[16];
-
-       struct usb_request      *ep0_req;       /* for internal request */
-       __le16                  ep0_data;       /* for internal request */
-       u16                     old_vbus;
-
-       struct timer_list       timer;
-
-       int                     scount;
-
-       int                     old_dvsq;
-
-       /* pipe config */
-       int bulk;
-       int interrupt;
-       int isochronous;
-       int num_dma;
-};
-#define to_m66592(g)   (container_of((g), struct m66592, gadget))
-
-#define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget)
-#define m66592_to_gadget(m66592) (&m66592->gadget)
-
-#define is_bulk_pipe(pipenum)  \
-       ((pipenum >= M66592_BASE_PIPENUM_BULK) && \
-        (pipenum < (M66592_BASE_PIPENUM_BULK + M66592_MAX_NUM_BULK)))
-#define is_interrupt_pipe(pipenum)     \
-       ((pipenum >= M66592_BASE_PIPENUM_INT) && \
-        (pipenum < (M66592_BASE_PIPENUM_INT + M66592_MAX_NUM_INT)))
-#define is_isoc_pipe(pipenum)  \
-       ((pipenum >= M66592_BASE_PIPENUM_ISOC) && \
-        (pipenum < (M66592_BASE_PIPENUM_ISOC + M66592_MAX_NUM_ISOC)))
-
-#define enable_irq_ready(m66592, pipenum)      \
-       enable_pipe_irq(m66592, pipenum, M66592_BRDYENB)
-#define disable_irq_ready(m66592, pipenum)     \
-       disable_pipe_irq(m66592, pipenum, M66592_BRDYENB)
-#define enable_irq_empty(m66592, pipenum)      \
-       enable_pipe_irq(m66592, pipenum, M66592_BEMPENB)
-#define disable_irq_empty(m66592, pipenum)     \
-       disable_pipe_irq(m66592, pipenum, M66592_BEMPENB)
-#define enable_irq_nrdy(m66592, pipenum)       \
-       enable_pipe_irq(m66592, pipenum, M66592_NRDYENB)
-#define disable_irq_nrdy(m66592, pipenum)      \
-       disable_pipe_irq(m66592, pipenum, M66592_NRDYENB)
-
-/*-------------------------------------------------------------------------*/
-static inline u16 m66592_read(struct m66592 *m66592, unsigned long offset)
-{
-       return ioread16(m66592->reg + offset);
-}
-
-static inline void m66592_read_fifo(struct m66592 *m66592,
-               unsigned long offset,
-               void *buf, unsigned long len)
-{
-       void __iomem *fifoaddr = m66592->reg + offset;
-
-       if (m66592->pdata->on_chip) {
-               len = (len + 3) / 4;
-               ioread32_rep(fifoaddr, buf, len);
-       } else {
-               len = (len + 1) / 2;
-               ioread16_rep(fifoaddr, buf, len);
-       }
-}
-
-static inline void m66592_write(struct m66592 *m66592, u16 val,
-                               unsigned long offset)
-{
-       iowrite16(val, m66592->reg + offset);
-}
-
-static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
-               unsigned long offset)
-{
-       u16 tmp;
-       tmp = m66592_read(m66592, offset);
-       tmp = tmp & (~pat);
-       tmp = tmp | val;
-       m66592_write(m66592, tmp, offset);
-}
-
-#define m66592_bclr(m66592, val, offset)       \
-                       m66592_mdfy(m66592, 0, val, offset)
-#define m66592_bset(m66592, val, offset)       \
-                       m66592_mdfy(m66592, val, 0, offset)
-
-static inline void m66592_write_fifo(struct m66592 *m66592,
-               struct m66592_ep *ep,
-               void *buf, unsigned long len)
-{
-       void __iomem *fifoaddr = m66592->reg + ep->fifoaddr;
-
-       if (m66592->pdata->on_chip) {
-               unsigned long count;
-               unsigned char *pb;
-               int i;
-
-               count = len / 4;
-               iowrite32_rep(fifoaddr, buf, count);
-
-               if (len & 0x00000003) {
-                       pb = buf + count * 4;
-                       for (i = 0; i < (len & 0x00000003); i++) {
-                               if (m66592_read(m66592, M66592_CFBCFG)) /* le */
-                                       iowrite8(pb[i], fifoaddr + (3 - i));
-                               else
-                                       iowrite8(pb[i], fifoaddr + i);
-                       }
-               }
-       } else {
-               unsigned long odd = len & 0x0001;
-
-               len = len / 2;
-               iowrite16_rep(fifoaddr, buf, len);
-               if (odd) {
-                       unsigned char *p = buf + len*2;
-                       if (m66592->pdata->wr0_shorted_to_wr1)
-                               m66592_bclr(m66592, M66592_MBW_16, ep->fifosel);
-                       iowrite8(*p, fifoaddr);
-                       if (m66592->pdata->wr0_shorted_to_wr1)
-                               m66592_bset(m66592, M66592_MBW_16, ep->fifosel);
-               }
-       }
-}
-
-#endif /* ifndef __M66592_UDC_H__ */
-
-
diff --git a/drivers/usb/gadget/mv_u3d.h b/drivers/usb/gadget/mv_u3d.h
deleted file mode 100644 (file)
index e32a787..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- */
-
-#ifndef __MV_U3D_H
-#define __MV_U3D_H
-
-#define MV_U3D_EP_CONTEXT_ALIGNMENT    32
-#define MV_U3D_TRB_ALIGNMENT   16
-#define MV_U3D_DMA_BOUNDARY    4096
-#define MV_U3D_EP0_MAX_PKT_SIZE        512
-
-/* ep0 transfer state */
-#define MV_U3D_WAIT_FOR_SETUP          0
-#define MV_U3D_DATA_STATE_XMIT         1
-#define MV_U3D_DATA_STATE_NEED_ZLP     2
-#define MV_U3D_WAIT_FOR_OUT_STATUS     3
-#define MV_U3D_DATA_STATE_RECV         4
-#define MV_U3D_STATUS_STAGE            5
-
-#define MV_U3D_EP_MAX_LENGTH_TRANSFER  0x10000
-
-/* USB3 Interrupt Status */
-#define MV_U3D_USBINT_SETUP            0x00000001
-#define MV_U3D_USBINT_RX_COMPLETE      0x00000002
-#define MV_U3D_USBINT_TX_COMPLETE      0x00000004
-#define MV_U3D_USBINT_UNDER_RUN        0x00000008
-#define MV_U3D_USBINT_RXDESC_ERR       0x00000010
-#define MV_U3D_USBINT_TXDESC_ERR       0x00000020
-#define MV_U3D_USBINT_RX_TRB_COMPLETE  0x00000040
-#define MV_U3D_USBINT_TX_TRB_COMPLETE  0x00000080
-#define MV_U3D_USBINT_VBUS_VALID       0x00010000
-#define MV_U3D_USBINT_STORAGE_CMD_FULL 0x00020000
-#define MV_U3D_USBINT_LINK_CHG         0x01000000
-
-/* USB3 Interrupt Enable */
-#define MV_U3D_INTR_ENABLE_SETUP               0x00000001
-#define MV_U3D_INTR_ENABLE_RX_COMPLETE         0x00000002
-#define MV_U3D_INTR_ENABLE_TX_COMPLETE         0x00000004
-#define MV_U3D_INTR_ENABLE_UNDER_RUN           0x00000008
-#define MV_U3D_INTR_ENABLE_RXDESC_ERR          0x00000010
-#define MV_U3D_INTR_ENABLE_TXDESC_ERR          0x00000020
-#define MV_U3D_INTR_ENABLE_RX_TRB_COMPLETE     0x00000040
-#define MV_U3D_INTR_ENABLE_TX_TRB_COMPLETE     0x00000080
-#define MV_U3D_INTR_ENABLE_RX_BUFFER_ERR       0x00000100
-#define MV_U3D_INTR_ENABLE_VBUS_VALID          0x00010000
-#define MV_U3D_INTR_ENABLE_STORAGE_CMD_FULL    0x00020000
-#define MV_U3D_INTR_ENABLE_LINK_CHG            0x01000000
-#define MV_U3D_INTR_ENABLE_PRIME_STATUS        0x02000000
-
-/* USB3 Link Change */
-#define MV_U3D_LINK_CHANGE_LINK_UP             0x00000001
-#define MV_U3D_LINK_CHANGE_SUSPEND             0x00000002
-#define MV_U3D_LINK_CHANGE_RESUME              0x00000004
-#define MV_U3D_LINK_CHANGE_WRESET              0x00000008
-#define MV_U3D_LINK_CHANGE_HRESET              0x00000010
-#define MV_U3D_LINK_CHANGE_VBUS_INVALID        0x00000020
-#define MV_U3D_LINK_CHANGE_INACT               0x00000040
-#define MV_U3D_LINK_CHANGE_DISABLE_AFTER_U0    0x00000080
-#define MV_U3D_LINK_CHANGE_U1                  0x00000100
-#define MV_U3D_LINK_CHANGE_U2                  0x00000200
-#define MV_U3D_LINK_CHANGE_U3                  0x00000400
-
-/* bridge setting */
-#define MV_U3D_BRIDGE_SETTING_VBUS_VALID       (1 << 16)
-
-/* Command Register Bit Masks */
-#define MV_U3D_CMD_RUN_STOP            0x00000001
-#define MV_U3D_CMD_CTRL_RESET          0x00000002
-
-/* ep control register */
-#define MV_U3D_EPXCR_EP_TYPE_CONTROL           0
-#define MV_U3D_EPXCR_EP_TYPE_ISOC              1
-#define MV_U3D_EPXCR_EP_TYPE_BULK              2
-#define MV_U3D_EPXCR_EP_TYPE_INT               3
-#define MV_U3D_EPXCR_EP_ENABLE_SHIFT           4
-#define MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT      12
-#define MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT     16
-#define MV_U3D_USB_BULK_BURST_OUT              6
-#define MV_U3D_USB_BULK_BURST_IN               14
-
-#define MV_U3D_EPXCR_EP_FLUSH          (1 << 7)
-#define MV_U3D_EPXCR_EP_HALT           (1 << 1)
-#define MV_U3D_EPXCR_EP_INIT           (1)
-
-/* TX/RX Status Register */
-#define MV_U3D_XFERSTATUS_COMPLETE_SHIFT       24
-#define MV_U3D_COMPLETE_INVALID        0
-#define MV_U3D_COMPLETE_SUCCESS        1
-#define MV_U3D_COMPLETE_BUFF_ERR       2
-#define MV_U3D_COMPLETE_SHORT_PACKET   3
-#define MV_U3D_COMPLETE_TRB_ERR        5
-#define MV_U3D_XFERSTATUS_TRB_LENGTH_MASK      (0xFFFFFF)
-
-#define MV_U3D_USB_LINK_BYPASS_VBUS    0x8
-
-#define MV_U3D_LTSSM_PHY_INIT_DONE             0x80000000
-#define MV_U3D_LTSSM_NEVER_GO_COMPLIANCE       0x40000000
-
-#define MV_U3D_USB3_OP_REGS_OFFSET     0x100
-#define MV_U3D_USB3_PHY_OFFSET         0xB800
-
-#define DCS_ENABLE     0x1
-
-/* timeout */
-#define MV_U3D_RESET_TIMEOUT           10000
-#define MV_U3D_FLUSH_TIMEOUT           100000
-#define MV_U3D_OWN_TIMEOUT             10000
-#define LOOPS_USEC_SHIFT       4
-#define LOOPS_USEC             (1 << LOOPS_USEC_SHIFT)
-#define LOOPS(timeout)         ((timeout) >> LOOPS_USEC_SHIFT)
-
-/* ep direction */
-#define MV_U3D_EP_DIR_IN               1
-#define MV_U3D_EP_DIR_OUT              0
-#define mv_u3d_ep_dir(ep)      (((ep)->ep_num == 0) ? \
-                               ((ep)->u3d->ep0_dir) : ((ep)->direction))
-
-/* usb capability registers */
-struct mv_u3d_cap_regs {
-       u32     rsvd[5];
-       u32     dboff;  /* doorbell register offset */
-       u32     rtsoff; /* runtime register offset */
-       u32     vuoff;  /* vendor unique register offset */
-};
-
-/* operation registers */
-struct mv_u3d_op_regs {
-       u32     usbcmd;         /* Command register */
-       u32     rsvd1[11];
-       u32     dcbaapl;        /* Device Context Base Address low register */
-       u32     dcbaaph;        /* Device Context Base Address high register */
-       u32     rsvd2[243];
-       u32     portsc;         /* port status and control register*/
-       u32     portlinkinfo;   /* port link info register*/
-       u32     rsvd3[9917];
-       u32     doorbell;       /* doorbell register */
-};
-
-/* control enpoint enable registers */
-struct epxcr {
-       u32     epxoutcr0;      /* ep out control 0 register */
-       u32     epxoutcr1;      /* ep out control 1 register */
-       u32     epxincr0;       /* ep in control 0 register */
-       u32     epxincr1;       /* ep in control 1 register */
-};
-
-/* transfer status registers */
-struct xferstatus {
-       u32     curdeqlo;       /* current TRB pointer low */
-       u32     curdeqhi;       /* current TRB pointer high */
-       u32     statuslo;       /* transfer status low */
-       u32     statushi;       /* transfer status high */
-};
-
-/* vendor unique control registers */
-struct mv_u3d_vuc_regs {
-       u32     ctrlepenable;   /* control endpoint enable register */
-       u32     setuplock;      /* setup lock register */
-       u32     endcomplete;    /* endpoint transfer complete register */
-       u32     intrcause;      /* interrupt cause register */
-       u32     intrenable;     /* interrupt enable register */
-       u32     trbcomplete;    /* TRB complete register */
-       u32     linkchange;     /* link change register */
-       u32     rsvd1[5];
-       u32     trbunderrun;    /* TRB underrun register */
-       u32     rsvd2[43];
-       u32     bridgesetting;  /* bridge setting register */
-       u32     rsvd3[7];
-       struct xferstatus       txst[16];       /* TX status register */
-       struct xferstatus       rxst[16];       /* RX status register */
-       u32     ltssm;          /* LTSSM control register */
-       u32     pipe;           /* PIPE control register */
-       u32     linkcr0;        /* link control 0 register */
-       u32     linkcr1;        /* link control 1 register */
-       u32     rsvd6[60];
-       u32     mib0;           /* MIB0 counter register */
-       u32     usblink;        /* usb link control register */
-       u32     ltssmstate;     /* LTSSM state register */
-       u32     linkerrorcause; /* link error cause register */
-       u32     rsvd7[60];
-       u32     devaddrtiebrkr; /* device address and tie breaker */
-       u32     itpinfo0;       /* ITP info 0 register */
-       u32     itpinfo1;       /* ITP info 1 register */
-       u32     rsvd8[61];
-       struct epxcr    epcr[16];       /* ep control register */
-       u32     rsvd9[64];
-       u32     phyaddr;        /* PHY address register */
-       u32     phydata;        /* PHY data register */
-};
-
-/* Endpoint context structure */
-struct mv_u3d_ep_context {
-       u32     rsvd0;
-       u32     rsvd1;
-       u32     trb_addr_lo;            /* TRB address low 32 bit */
-       u32     trb_addr_hi;            /* TRB address high 32 bit */
-       u32     rsvd2;
-       u32     rsvd3;
-       struct usb_ctrlrequest setup_buffer;    /* setup data buffer */
-};
-
-/* TRB control data structure */
-struct mv_u3d_trb_ctrl {
-       u32     own:1;          /* owner of TRB */
-       u32     rsvd1:3;
-       u32     chain:1;        /* associate this TRB with the
-                               next TRB on the Ring */
-       u32     ioc:1;          /* interrupt on complete */
-       u32     rsvd2:4;
-       u32     type:6;         /* TRB type */
-#define TYPE_NORMAL    1
-#define TYPE_DATA      3
-#define TYPE_LINK      6
-       u32     dir:1;          /* Working at data stage of control endpoint
-                               operation. 0 is OUT and 1 is IN. */
-       u32     rsvd3:15;
-};
-
-/* TRB data structure
- * For multiple TRB, all the TRBs' physical address should be continuous.
- */
-struct mv_u3d_trb_hw {
-       u32     buf_addr_lo;    /* data buffer address low 32 bit */
-       u32     buf_addr_hi;    /* data buffer address high 32 bit */
-       u32     trb_len;        /* transfer length */
-       struct mv_u3d_trb_ctrl  ctrl;   /* TRB control data */
-};
-
-/* TRB structure */
-struct mv_u3d_trb {
-       struct mv_u3d_trb_hw *trb_hw;   /* point to the trb_hw structure */
-       dma_addr_t trb_dma;             /* dma address for this trb_hw */
-       struct list_head trb_list;      /* trb list */
-};
-
-/* device data structure */
-struct mv_u3d {
-       struct usb_gadget               gadget;
-       struct usb_gadget_driver        *driver;
-       spinlock_t                      lock;   /* device lock */
-       struct completion               *done;
-       struct device                   *dev;
-       int                             irq;
-
-       /* usb controller registers */
-       struct mv_u3d_cap_regs __iomem  *cap_regs;
-       struct mv_u3d_op_regs __iomem   *op_regs;
-       struct mv_u3d_vuc_regs __iomem  *vuc_regs;
-       void __iomem                    *phy_regs;
-
-       unsigned int                    max_eps;
-       struct mv_u3d_ep_context        *ep_context;
-       size_t                          ep_context_size;
-       dma_addr_t                      ep_context_dma;
-
-       struct dma_pool                 *trb_pool; /* for TRB data structure */
-       struct mv_u3d_ep                *eps;
-
-       struct mv_u3d_req               *status_req; /* ep0 status request */
-       struct usb_ctrlrequest          local_setup_buff; /* store setup data*/
-
-       unsigned int            resume_state;   /* USB state to resume */
-       unsigned int            usb_state;      /* USB current state */
-       unsigned int            ep0_state;      /* Endpoint zero state */
-       unsigned int            ep0_dir;
-
-       unsigned int            dev_addr;       /* device address */
-
-       unsigned int            errors;
-
-       unsigned                softconnect:1;
-       unsigned                vbus_active:1;  /* vbus is active or not */
-       unsigned                remote_wakeup:1; /* support remote wakeup */
-       unsigned                clock_gating:1; /* clock gating or not */
-       unsigned                active:1;       /* udc is active or not */
-       unsigned                vbus_valid_detect:1; /* udc vbus detection */
-
-       struct mv_usb_addon_irq *vbus;
-       unsigned int            power;
-
-       struct clk              *clk;
-};
-
-/* endpoint data structure */
-struct mv_u3d_ep {
-       struct usb_ep           ep;
-       struct mv_u3d           *u3d;
-       struct list_head        queue;  /* ep request queued hardware */
-       struct list_head        req_list; /* list of ep request */
-       struct mv_u3d_ep_context        *ep_context; /* ep context */
-       u32                     direction;
-       char                    name[14];
-       u32                     processing; /* there is ep request
-                                               queued on haredware */
-       spinlock_t              req_lock; /* ep lock */
-       unsigned                wedge:1;
-       unsigned                enabled:1;
-       unsigned                ep_type:2;
-       unsigned                ep_num:8;
-};
-
-/* request data structure */
-struct mv_u3d_req {
-       struct usb_request      req;
-       struct mv_u3d_ep        *ep;
-       struct list_head        queue;  /* ep requst queued on hardware */
-       struct list_head        list;   /* ep request list */
-       struct list_head        trb_list; /* trb list of a request */
-
-       struct mv_u3d_trb       *trb_head; /* point to first trb of a request */
-       unsigned                trb_count; /* TRB number in the chain */
-       unsigned                chain;     /* TRB chain or not */
-};
-
-#endif
diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c
deleted file mode 100644 (file)
index 1624871..0000000
+++ /dev/null
@@ -1,2070 +0,0 @@
-/*
- * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/notifier.h>
-#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/pm.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/platform_data/mv_usb.h>
-#include <linux/clk.h>
-
-#include "mv_u3d.h"
-
-#define DRIVER_DESC            "Marvell PXA USB3.0 Device Controller driver"
-
-static const char driver_name[] = "mv_u3d";
-static const char driver_desc[] = DRIVER_DESC;
-
-static void mv_u3d_nuke(struct mv_u3d_ep *ep, int status);
-static void mv_u3d_stop_activity(struct mv_u3d *u3d,
-                       struct usb_gadget_driver *driver);
-
-/* for endpoint 0 operations */
-static const struct usb_endpoint_descriptor mv_u3d_ep0_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-       .bEndpointAddress =     0,
-       .bmAttributes =         USB_ENDPOINT_XFER_CONTROL,
-       .wMaxPacketSize =       MV_U3D_EP0_MAX_PKT_SIZE,
-};
-
-static void mv_u3d_ep0_reset(struct mv_u3d *u3d)
-{
-       struct mv_u3d_ep *ep;
-       u32 epxcr;
-       int i;
-
-       for (i = 0; i < 2; i++) {
-               ep = &u3d->eps[i];
-               ep->u3d = u3d;
-
-               /* ep0 ep context, ep0 in and out share the same ep context */
-               ep->ep_context = &u3d->ep_context[1];
-       }
-
-       /* reset ep state machine */
-       /* reset ep0 out */
-       epxcr = ioread32(&u3d->vuc_regs->epcr[0].epxoutcr0);
-       epxcr |= MV_U3D_EPXCR_EP_INIT;
-       iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxoutcr0);
-       udelay(5);
-       epxcr &= ~MV_U3D_EPXCR_EP_INIT;
-       iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxoutcr0);
-
-       epxcr = ((MV_U3D_EP0_MAX_PKT_SIZE
-               << MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT)
-               | (1 << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT)
-               | (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
-               | MV_U3D_EPXCR_EP_TYPE_CONTROL);
-       iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxoutcr1);
-
-       /* reset ep0 in */
-       epxcr = ioread32(&u3d->vuc_regs->epcr[0].epxincr0);
-       epxcr |= MV_U3D_EPXCR_EP_INIT;
-       iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxincr0);
-       udelay(5);
-       epxcr &= ~MV_U3D_EPXCR_EP_INIT;
-       iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxincr0);
-
-       epxcr = ((MV_U3D_EP0_MAX_PKT_SIZE
-               << MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT)
-               | (1 << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT)
-               | (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
-               | MV_U3D_EPXCR_EP_TYPE_CONTROL);
-       iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxincr1);
-}
-
-static void mv_u3d_ep0_stall(struct mv_u3d *u3d)
-{
-       u32 tmp;
-       dev_dbg(u3d->dev, "%s\n", __func__);
-
-       /* set TX and RX to stall */
-       tmp = ioread32(&u3d->vuc_regs->epcr[0].epxoutcr0);
-       tmp |= MV_U3D_EPXCR_EP_HALT;
-       iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxoutcr0);
-
-       tmp = ioread32(&u3d->vuc_regs->epcr[0].epxincr0);
-       tmp |= MV_U3D_EPXCR_EP_HALT;
-       iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxincr0);
-
-       /* update ep0 state */
-       u3d->ep0_state = MV_U3D_WAIT_FOR_SETUP;
-       u3d->ep0_dir = MV_U3D_EP_DIR_OUT;
-}
-
-static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
-       struct mv_u3d_req *curr_req)
-{
-       struct mv_u3d_trb       *curr_trb;
-       dma_addr_t cur_deq_lo;
-       struct mv_u3d_ep_context        *curr_ep_context;
-       int trb_complete, actual, remaining_length = 0;
-       int direction, ep_num;
-       int retval = 0;
-       u32 tmp, status, length;
-
-       curr_ep_context = &u3d->ep_context[index];
-       direction = index % 2;
-       ep_num = index / 2;
-
-       trb_complete = 0;
-       actual = curr_req->req.length;
-
-       while (!list_empty(&curr_req->trb_list)) {
-               curr_trb = list_entry(curr_req->trb_list.next,
-                                       struct mv_u3d_trb, trb_list);
-               if (!curr_trb->trb_hw->ctrl.own) {
-                       dev_err(u3d->dev, "%s, TRB own error!\n",
-                               u3d->eps[index].name);
-                       return 1;
-               }
-
-               curr_trb->trb_hw->ctrl.own = 0;
-               if (direction == MV_U3D_EP_DIR_OUT) {
-                       tmp = ioread32(&u3d->vuc_regs->rxst[ep_num].statuslo);
-                       cur_deq_lo =
-                               ioread32(&u3d->vuc_regs->rxst[ep_num].curdeqlo);
-               } else {
-                       tmp = ioread32(&u3d->vuc_regs->txst[ep_num].statuslo);
-                       cur_deq_lo =
-                               ioread32(&u3d->vuc_regs->txst[ep_num].curdeqlo);
-               }
-
-               status = tmp >> MV_U3D_XFERSTATUS_COMPLETE_SHIFT;
-               length = tmp & MV_U3D_XFERSTATUS_TRB_LENGTH_MASK;
-
-               if (status == MV_U3D_COMPLETE_SUCCESS ||
-                       (status == MV_U3D_COMPLETE_SHORT_PACKET &&
-                       direction == MV_U3D_EP_DIR_OUT)) {
-                       remaining_length += length;
-                       actual -= remaining_length;
-               } else {
-                       dev_err(u3d->dev,
-                               "complete_tr error: ep=%d %s: error = 0x%x\n",
-                               index >> 1, direction ? "SEND" : "RECV",
-                               status);
-                       retval = -EPROTO;
-               }
-
-               list_del_init(&curr_trb->trb_list);
-       }
-       if (retval)
-               return retval;
-
-       curr_req->req.actual = actual;
-       return 0;
-}
-
-/*
- * mv_u3d_done() - retire a request; caller blocked irqs
- * @status : request status to be set, only works when
- * request is still in progress.
- */
-static
-void mv_u3d_done(struct mv_u3d_ep *ep, struct mv_u3d_req *req, int status)
-       __releases(&ep->udc->lock)
-       __acquires(&ep->udc->lock)
-{
-       struct mv_u3d *u3d = (struct mv_u3d *)ep->u3d;
-
-       dev_dbg(u3d->dev, "mv_u3d_done: remove req->queue\n");
-       /* Removed the req from ep queue */
-       list_del_init(&req->queue);
-
-       /* req.status should be set as -EINPROGRESS in ep_queue() */
-       if (req->req.status == -EINPROGRESS)
-               req->req.status = status;
-       else
-               status = req->req.status;
-
-       /* Free trb for the request */
-       if (!req->chain)
-               dma_pool_free(u3d->trb_pool,
-                       req->trb_head->trb_hw, req->trb_head->trb_dma);
-       else {
-               dma_unmap_single(ep->u3d->gadget.dev.parent,
-                       (dma_addr_t)req->trb_head->trb_dma,
-                       req->trb_count * sizeof(struct mv_u3d_trb_hw),
-                       DMA_BIDIRECTIONAL);
-               kfree(req->trb_head->trb_hw);
-       }
-       kfree(req->trb_head);
-
-       usb_gadget_unmap_request(&u3d->gadget, &req->req, mv_u3d_ep_dir(ep));
-
-       if (status && (status != -ESHUTDOWN)) {
-               dev_dbg(u3d->dev, "complete %s req %p stat %d len %u/%u",
-                       ep->ep.name, &req->req, status,
-                       req->req.actual, req->req.length);
-       }
-
-       spin_unlock(&ep->u3d->lock);
-       /*
-        * complete() is from gadget layer,
-        * eg fsg->bulk_in_complete()
-        */
-       if (req->req.complete)
-               req->req.complete(&ep->ep, &req->req);
-
-       spin_lock(&ep->u3d->lock);
-}
-
-static int mv_u3d_queue_trb(struct mv_u3d_ep *ep, struct mv_u3d_req *req)
-{
-       u32 tmp, direction;
-       struct mv_u3d *u3d;
-       struct mv_u3d_ep_context *ep_context;
-       int retval = 0;
-
-       u3d = ep->u3d;
-       direction = mv_u3d_ep_dir(ep);
-
-       /* ep0 in and out share the same ep context slot 1*/
-       if (ep->ep_num == 0)
-               ep_context = &(u3d->ep_context[1]);
-       else
-               ep_context = &(u3d->ep_context[ep->ep_num * 2 + direction]);
-
-       /* check if the pipe is empty or not */
-       if (!list_empty(&ep->queue)) {
-               dev_err(u3d->dev, "add trb to non-empty queue!\n");
-               retval = -ENOMEM;
-               WARN_ON(1);
-       } else {
-               ep_context->rsvd0 = cpu_to_le32(1);
-               ep_context->rsvd1 = 0;
-
-               /* Configure the trb address and set the DCS bit.
-                * Both DCS bit and own bit in trb should be set.
-                */
-               ep_context->trb_addr_lo =
-                       cpu_to_le32(req->trb_head->trb_dma | DCS_ENABLE);
-               ep_context->trb_addr_hi = 0;
-
-               /* Ensure that updates to the EP Context will
-                * occure before Ring Bell.
-                */
-               wmb();
-
-               /* ring bell the ep */
-               if (ep->ep_num == 0)
-                       tmp = 0x1;
-               else
-                       tmp = ep->ep_num * 2
-                               + ((direction == MV_U3D_EP_DIR_OUT) ? 0 : 1);
-
-               iowrite32(tmp, &u3d->op_regs->doorbell);
-       }
-       return retval;
-}
-
-static struct mv_u3d_trb *mv_u3d_build_trb_one(struct mv_u3d_req *req,
-                               unsigned *length, dma_addr_t *dma)
-{
-       u32 temp;
-       unsigned int direction;
-       struct mv_u3d_trb *trb;
-       struct mv_u3d_trb_hw *trb_hw;
-       struct mv_u3d *u3d;
-
-       /* how big will this transfer be? */
-       *length = req->req.length - req->req.actual;
-       BUG_ON(*length > (unsigned)MV_U3D_EP_MAX_LENGTH_TRANSFER);
-
-       u3d = req->ep->u3d;
-
-       trb = kzalloc(sizeof(*trb), GFP_ATOMIC);
-       if (!trb)
-               return NULL;
-
-       /*
-        * Be careful that no _GFP_HIGHMEM is set,
-        * or we can not use dma_to_virt
-        * cannot use GFP_KERNEL in spin lock
-        */
-       trb_hw = dma_pool_alloc(u3d->trb_pool, GFP_ATOMIC, dma);
-       if (!trb_hw) {
-               kfree(trb);
-               dev_err(u3d->dev,
-                       "%s, dma_pool_alloc fail\n", __func__);
-               return NULL;
-       }
-       trb->trb_dma = *dma;
-       trb->trb_hw = trb_hw;
-
-       /* initialize buffer page pointers */
-       temp = (u32)(req->req.dma + req->req.actual);
-
-       trb_hw->buf_addr_lo = cpu_to_le32(temp);
-       trb_hw->buf_addr_hi = 0;
-       trb_hw->trb_len = cpu_to_le32(*length);
-       trb_hw->ctrl.own = 1;
-
-       if (req->ep->ep_num == 0)
-               trb_hw->ctrl.type = TYPE_DATA;
-       else
-               trb_hw->ctrl.type = TYPE_NORMAL;
-
-       req->req.actual += *length;
-
-       direction = mv_u3d_ep_dir(req->ep);
-       if (direction == MV_U3D_EP_DIR_IN)
-               trb_hw->ctrl.dir = 1;
-       else
-               trb_hw->ctrl.dir = 0;
-
-       /* Enable interrupt for the last trb of a request */
-       if (!req->req.no_interrupt)
-               trb_hw->ctrl.ioc = 1;
-
-       trb_hw->ctrl.chain = 0;
-
-       wmb();
-       return trb;
-}
-
-static int mv_u3d_build_trb_chain(struct mv_u3d_req *req, unsigned *length,
-               struct mv_u3d_trb *trb, int *is_last)
-{
-       u32 temp;
-       unsigned int direction;
-       struct mv_u3d *u3d;
-
-       /* how big will this transfer be? */
-       *length = min(req->req.length - req->req.actual,
-                       (unsigned)MV_U3D_EP_MAX_LENGTH_TRANSFER);
-
-       u3d = req->ep->u3d;
-
-       trb->trb_dma = 0;
-
-       /* initialize buffer page pointers */
-       temp = (u32)(req->req.dma + req->req.actual);
-
-       trb->trb_hw->buf_addr_lo = cpu_to_le32(temp);
-       trb->trb_hw->buf_addr_hi = 0;
-       trb->trb_hw->trb_len = cpu_to_le32(*length);
-       trb->trb_hw->ctrl.own = 1;
-
-       if (req->ep->ep_num == 0)
-               trb->trb_hw->ctrl.type = TYPE_DATA;
-       else
-               trb->trb_hw->ctrl.type = TYPE_NORMAL;
-
-       req->req.actual += *length;
-
-       direction = mv_u3d_ep_dir(req->ep);
-       if (direction == MV_U3D_EP_DIR_IN)
-               trb->trb_hw->ctrl.dir = 1;
-       else
-               trb->trb_hw->ctrl.dir = 0;
-
-       /* zlp is needed if req->req.zero is set */
-       if (req->req.zero) {
-               if (*length == 0 || (*length % req->ep->ep.maxpacket) != 0)
-                       *is_last = 1;
-               else
-                       *is_last = 0;
-       } else if (req->req.length == req->req.actual)
-               *is_last = 1;
-       else
-               *is_last = 0;
-
-       /* Enable interrupt for the last trb of a request */
-       if (*is_last && !req->req.no_interrupt)
-               trb->trb_hw->ctrl.ioc = 1;
-
-       if (*is_last)
-               trb->trb_hw->ctrl.chain = 0;
-       else {
-               trb->trb_hw->ctrl.chain = 1;
-               dev_dbg(u3d->dev, "chain trb\n");
-       }
-
-       wmb();
-
-       return 0;
-}
-
-/* generate TRB linked list for a request
- * usb controller only supports continous trb chain,
- * that trb structure physical address should be continous.
- */
-static int mv_u3d_req_to_trb(struct mv_u3d_req *req)
-{
-       unsigned count;
-       int is_last;
-       struct mv_u3d_trb *trb;
-       struct mv_u3d_trb_hw *trb_hw;
-       struct mv_u3d *u3d;
-       dma_addr_t dma;
-       unsigned length;
-       unsigned trb_num;
-
-       u3d = req->ep->u3d;
-
-       INIT_LIST_HEAD(&req->trb_list);
-
-       length = req->req.length - req->req.actual;
-       /* normally the request transfer length is less than 16KB.
-        * we use buil_trb_one() to optimize it.
-        */
-       if (length <= (unsigned)MV_U3D_EP_MAX_LENGTH_TRANSFER) {
-               trb = mv_u3d_build_trb_one(req, &count, &dma);
-               list_add_tail(&trb->trb_list, &req->trb_list);
-               req->trb_head = trb;
-               req->trb_count = 1;
-               req->chain = 0;
-       } else {
-               trb_num = length / MV_U3D_EP_MAX_LENGTH_TRANSFER;
-               if (length % MV_U3D_EP_MAX_LENGTH_TRANSFER)
-                       trb_num++;
-
-               trb = kcalloc(trb_num, sizeof(*trb), GFP_ATOMIC);
-               if (!trb)
-                       return -ENOMEM;
-
-               trb_hw = kcalloc(trb_num, sizeof(*trb_hw), GFP_ATOMIC);
-               if (!trb_hw) {
-                       kfree(trb);
-                       return -ENOMEM;
-               }
-
-               do {
-                       trb->trb_hw = trb_hw;
-                       if (mv_u3d_build_trb_chain(req, &count,
-                                               trb, &is_last)) {
-                               dev_err(u3d->dev,
-                                       "%s, mv_u3d_build_trb_chain fail\n",
-                                       __func__);
-                               return -EIO;
-                       }
-
-                       list_add_tail(&trb->trb_list, &req->trb_list);
-                       req->trb_count++;
-                       trb++;
-                       trb_hw++;
-               } while (!is_last);
-
-               req->trb_head = list_entry(req->trb_list.next,
-                                       struct mv_u3d_trb, trb_list);
-               req->trb_head->trb_dma = dma_map_single(u3d->gadget.dev.parent,
-                                       req->trb_head->trb_hw,
-                                       trb_num * sizeof(*trb_hw),
-                                       DMA_BIDIRECTIONAL);
-
-               req->chain = 1;
-       }
-
-       return 0;
-}
-
-static int
-mv_u3d_start_queue(struct mv_u3d_ep *ep)
-{
-       struct mv_u3d *u3d = ep->u3d;
-       struct mv_u3d_req *req;
-       int ret;
-
-       if (!list_empty(&ep->req_list) && !ep->processing)
-               req = list_entry(ep->req_list.next, struct mv_u3d_req, list);
-       else
-               return 0;
-
-       ep->processing = 1;
-
-       /* set up dma mapping */
-       ret = usb_gadget_map_request(&u3d->gadget, &req->req,
-                                       mv_u3d_ep_dir(ep));
-       if (ret)
-               return ret;
-
-       req->req.status = -EINPROGRESS;
-       req->req.actual = 0;
-       req->trb_count = 0;
-
-       /* build trbs and push them to device queue */
-       if (!mv_u3d_req_to_trb(req)) {
-               ret = mv_u3d_queue_trb(ep, req);
-               if (ret) {
-                       ep->processing = 0;
-                       return ret;
-               }
-       } else {
-               ep->processing = 0;
-               dev_err(u3d->dev, "%s, mv_u3d_req_to_trb fail\n", __func__);
-               return -ENOMEM;
-       }
-
-       /* irq handler advances the queue */
-       if (req)
-               list_add_tail(&req->queue, &ep->queue);
-
-       return 0;
-}
-
-static int mv_u3d_ep_enable(struct usb_ep *_ep,
-               const struct usb_endpoint_descriptor *desc)
-{
-       struct mv_u3d *u3d;
-       struct mv_u3d_ep *ep;
-       struct mv_u3d_ep_context *ep_context;
-       u16 max = 0;
-       unsigned maxburst = 0;
-       u32 epxcr, direction;
-
-       if (!_ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT)
-               return -EINVAL;
-
-       ep = container_of(_ep, struct mv_u3d_ep, ep);
-       u3d = ep->u3d;
-
-       if (!u3d->driver || u3d->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       direction = mv_u3d_ep_dir(ep);
-       max = le16_to_cpu(desc->wMaxPacketSize);
-
-       if (!_ep->maxburst)
-               _ep->maxburst = 1;
-       maxburst = _ep->maxburst;
-
-       /* Get the endpoint context address */
-       ep_context = (struct mv_u3d_ep_context *)ep->ep_context;
-
-       /* Set the max burst size */
-       switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
-       case USB_ENDPOINT_XFER_BULK:
-               if (maxburst > 16) {
-                       dev_dbg(u3d->dev,
-                               "max burst should not be greater "
-                               "than 16 on bulk ep\n");
-                       maxburst = 1;
-                       _ep->maxburst = maxburst;
-               }
-               dev_dbg(u3d->dev,
-                       "maxburst: %d on bulk %s\n", maxburst, ep->name);
-               break;
-       case USB_ENDPOINT_XFER_CONTROL:
-               /* control transfer only supports maxburst as one */
-               maxburst = 1;
-               _ep->maxburst = maxburst;
-               break;
-       case USB_ENDPOINT_XFER_INT:
-               if (maxburst != 1) {
-                       dev_dbg(u3d->dev,
-                               "max burst should be 1 on int ep "
-                               "if transfer size is not 1024\n");
-                       maxburst = 1;
-                       _ep->maxburst = maxburst;
-               }
-               break;
-       case USB_ENDPOINT_XFER_ISOC:
-               if (maxburst != 1) {
-                       dev_dbg(u3d->dev,
-                               "max burst should be 1 on isoc ep "
-                               "if transfer size is not 1024\n");
-                       maxburst = 1;
-                       _ep->maxburst = maxburst;
-               }
-               break;
-       default:
-               goto en_done;
-       }
-
-       ep->ep.maxpacket = max;
-       ep->ep.desc = desc;
-       ep->enabled = 1;
-
-       /* Enable the endpoint for Rx or Tx and set the endpoint type */
-       if (direction == MV_U3D_EP_DIR_OUT) {
-               epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
-               epxcr |= MV_U3D_EPXCR_EP_INIT;
-               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
-               udelay(5);
-               epxcr &= ~MV_U3D_EPXCR_EP_INIT;
-               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
-
-               epxcr = ((max << MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT)
-                     | ((maxburst - 1) << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT)
-                     | (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
-                     | (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK));
-               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr1);
-       } else {
-               epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
-               epxcr |= MV_U3D_EPXCR_EP_INIT;
-               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
-               udelay(5);
-               epxcr &= ~MV_U3D_EPXCR_EP_INIT;
-               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
-
-               epxcr = ((max << MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT)
-                     | ((maxburst - 1) << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT)
-                     | (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
-                     | (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK));
-               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr1);
-       }
-
-       return 0;
-en_done:
-       return -EINVAL;
-}
-
-static int  mv_u3d_ep_disable(struct usb_ep *_ep)
-{
-       struct mv_u3d *u3d;
-       struct mv_u3d_ep *ep;
-       struct mv_u3d_ep_context *ep_context;
-       u32 epxcr, direction;
-       unsigned long flags;
-
-       if (!_ep)
-               return -EINVAL;
-
-       ep = container_of(_ep, struct mv_u3d_ep, ep);
-       if (!ep->ep.desc)
-               return -EINVAL;
-
-       u3d = ep->u3d;
-
-       /* Get the endpoint context address */
-       ep_context = ep->ep_context;
-
-       direction = mv_u3d_ep_dir(ep);
-
-       /* nuke all pending requests (does flush) */
-       spin_lock_irqsave(&u3d->lock, flags);
-       mv_u3d_nuke(ep, -ESHUTDOWN);
-       spin_unlock_irqrestore(&u3d->lock, flags);
-
-       /* Disable the endpoint for Rx or Tx and reset the endpoint type */
-       if (direction == MV_U3D_EP_DIR_OUT) {
-               epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr1);
-               epxcr &= ~((1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
-                     | USB_ENDPOINT_XFERTYPE_MASK);
-               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr1);
-       } else {
-               epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr1);
-               epxcr &= ~((1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
-                     | USB_ENDPOINT_XFERTYPE_MASK);
-               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr1);
-       }
-
-       ep->enabled = 0;
-
-       ep->ep.desc = NULL;
-       return 0;
-}
-
-static struct usb_request *
-mv_u3d_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
-{
-       struct mv_u3d_req *req = NULL;
-
-       req = kzalloc(sizeof *req, gfp_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD(&req->queue);
-
-       return &req->req;
-}
-
-static void mv_u3d_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct mv_u3d_req *req = container_of(_req, struct mv_u3d_req, req);
-
-       kfree(req);
-}
-
-static void mv_u3d_ep_fifo_flush(struct usb_ep *_ep)
-{
-       struct mv_u3d *u3d;
-       u32 direction;
-       struct mv_u3d_ep *ep = container_of(_ep, struct mv_u3d_ep, ep);
-       unsigned int loops;
-       u32 tmp;
-
-       /* if endpoint is not enabled, cannot flush endpoint */
-       if (!ep->enabled)
-               return;
-
-       u3d = ep->u3d;
-       direction = mv_u3d_ep_dir(ep);
-
-       /* ep0 need clear bit after flushing fifo. */
-       if (!ep->ep_num) {
-               if (direction == MV_U3D_EP_DIR_OUT) {
-                       tmp = ioread32(&u3d->vuc_regs->epcr[0].epxoutcr0);
-                       tmp |= MV_U3D_EPXCR_EP_FLUSH;
-                       iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxoutcr0);
-                       udelay(10);
-                       tmp &= ~MV_U3D_EPXCR_EP_FLUSH;
-                       iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxoutcr0);
-               } else {
-                       tmp = ioread32(&u3d->vuc_regs->epcr[0].epxincr0);
-                       tmp |= MV_U3D_EPXCR_EP_FLUSH;
-                       iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxincr0);
-                       udelay(10);
-                       tmp &= ~MV_U3D_EPXCR_EP_FLUSH;
-                       iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxincr0);
-               }
-               return;
-       }
-
-       if (direction == MV_U3D_EP_DIR_OUT) {
-               tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
-               tmp |= MV_U3D_EPXCR_EP_FLUSH;
-               iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
-
-               /* Wait until flushing completed */
-               loops = LOOPS(MV_U3D_FLUSH_TIMEOUT);
-               while (ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0) &
-                       MV_U3D_EPXCR_EP_FLUSH) {
-                       /*
-                        * EP_FLUSH bit should be cleared to indicate this
-                        * operation is complete
-                        */
-                       if (loops == 0) {
-                               dev_dbg(u3d->dev,
-                                   "EP FLUSH TIMEOUT for ep%d%s\n", ep->ep_num,
-                                   direction ? "in" : "out");
-                               return;
-                       }
-                       loops--;
-                       udelay(LOOPS_USEC);
-               }
-       } else {        /* EP_DIR_IN */
-               tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
-               tmp |= MV_U3D_EPXCR_EP_FLUSH;
-               iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
-
-               /* Wait until flushing completed */
-               loops = LOOPS(MV_U3D_FLUSH_TIMEOUT);
-               while (ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0) &
-                       MV_U3D_EPXCR_EP_FLUSH) {
-                       /*
-                       * EP_FLUSH bit should be cleared to indicate this
-                       * operation is complete
-                       */
-                       if (loops == 0) {
-                               dev_dbg(u3d->dev,
-                                   "EP FLUSH TIMEOUT for ep%d%s\n", ep->ep_num,
-                                   direction ? "in" : "out");
-                               return;
-                       }
-                       loops--;
-                       udelay(LOOPS_USEC);
-               }
-       }
-}
-
-/* queues (submits) an I/O request to an endpoint */
-static int
-mv_u3d_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
-{
-       struct mv_u3d_ep *ep;
-       struct mv_u3d_req *req;
-       struct mv_u3d *u3d;
-       unsigned long flags;
-       int is_first_req = 0;
-
-       if (unlikely(!_ep || !_req))
-               return -EINVAL;
-
-       ep = container_of(_ep, struct mv_u3d_ep, ep);
-       u3d = ep->u3d;
-
-       req = container_of(_req, struct mv_u3d_req, req);
-
-       if (!ep->ep_num
-               && u3d->ep0_state == MV_U3D_STATUS_STAGE
-               && !_req->length) {
-               dev_dbg(u3d->dev, "ep0 status stage\n");
-               u3d->ep0_state = MV_U3D_WAIT_FOR_SETUP;
-               return 0;
-       }
-
-       dev_dbg(u3d->dev, "%s: %s, req: 0x%p\n",
-                       __func__, _ep->name, req);
-
-       /* catch various bogus parameters */
-       if (!req->req.complete || !req->req.buf
-                       || !list_empty(&req->queue)) {
-               dev_err(u3d->dev,
-                       "%s, bad params, _req: 0x%p,"
-                       "req->req.complete: 0x%p, req->req.buf: 0x%p,"
-                       "list_empty: 0x%x\n",
-                       __func__, _req,
-                       req->req.complete, req->req.buf,
-                       list_empty(&req->queue));
-               return -EINVAL;
-       }
-       if (unlikely(!ep->ep.desc)) {
-               dev_err(u3d->dev, "%s, bad ep\n", __func__);
-               return -EINVAL;
-       }
-       if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
-               if (req->req.length > ep->ep.maxpacket)
-                       return -EMSGSIZE;
-       }
-
-       if (!u3d->driver || u3d->gadget.speed == USB_SPEED_UNKNOWN) {
-               dev_err(u3d->dev,
-                       "bad params of driver/speed\n");
-               return -ESHUTDOWN;
-       }
-
-       req->ep = ep;
-
-       /* Software list handles usb request. */
-       spin_lock_irqsave(&ep->req_lock, flags);
-       is_first_req = list_empty(&ep->req_list);
-       list_add_tail(&req->list, &ep->req_list);
-       spin_unlock_irqrestore(&ep->req_lock, flags);
-       if (!is_first_req) {
-               dev_dbg(u3d->dev, "list is not empty\n");
-               return 0;
-       }
-
-       dev_dbg(u3d->dev, "call mv_u3d_start_queue from usb_ep_queue\n");
-       spin_lock_irqsave(&u3d->lock, flags);
-       mv_u3d_start_queue(ep);
-       spin_unlock_irqrestore(&u3d->lock, flags);
-       return 0;
-}
-
-/* dequeues (cancels, unlinks) an I/O request from an endpoint */
-static int mv_u3d_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct mv_u3d_ep *ep;
-       struct mv_u3d_req *req;
-       struct mv_u3d *u3d;
-       struct mv_u3d_ep_context *ep_context;
-       struct mv_u3d_req *next_req;
-
-       unsigned long flags;
-       int ret = 0;
-
-       if (!_ep || !_req)
-               return -EINVAL;
-
-       ep = container_of(_ep, struct mv_u3d_ep, ep);
-       u3d = ep->u3d;
-
-       spin_lock_irqsave(&ep->u3d->lock, flags);
-
-       /* make sure it's actually queued on this endpoint */
-       list_for_each_entry(req, &ep->queue, queue) {
-               if (&req->req == _req)
-                       break;
-       }
-       if (&req->req != _req) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       /* The request is in progress, or completed but not dequeued */
-       if (ep->queue.next == &req->queue) {
-               _req->status = -ECONNRESET;
-               mv_u3d_ep_fifo_flush(_ep);
-
-               /* The request isn't the last request in this ep queue */
-               if (req->queue.next != &ep->queue) {
-                       dev_dbg(u3d->dev,
-                               "it is the last request in this ep queue\n");
-                       ep_context = ep->ep_context;
-                       next_req = list_entry(req->queue.next,
-                                       struct mv_u3d_req, queue);
-
-                       /* Point first TRB of next request to the EP context. */
-                       iowrite32((unsigned long) next_req->trb_head,
-                                       &ep_context->trb_addr_lo);
-               } else {
-                       struct mv_u3d_ep_context *ep_context;
-                       ep_context = ep->ep_context;
-                       ep_context->trb_addr_lo = 0;
-                       ep_context->trb_addr_hi = 0;
-               }
-
-       } else
-               WARN_ON(1);
-
-       mv_u3d_done(ep, req, -ECONNRESET);
-
-       /* remove the req from the ep req list */
-       if (!list_empty(&ep->req_list)) {
-               struct mv_u3d_req *curr_req;
-               curr_req = list_entry(ep->req_list.next,
-                                       struct mv_u3d_req, list);
-               if (curr_req == req) {
-                       list_del_init(&req->list);
-                       ep->processing = 0;
-               }
-       }
-
-out:
-       spin_unlock_irqrestore(&ep->u3d->lock, flags);
-       return ret;
-}
-
-static void
-mv_u3d_ep_set_stall(struct mv_u3d *u3d, u8 ep_num, u8 direction, int stall)
-{
-       u32 tmp;
-       struct mv_u3d_ep *ep = u3d->eps;
-
-       dev_dbg(u3d->dev, "%s\n", __func__);
-       if (direction == MV_U3D_EP_DIR_OUT) {
-               tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
-               if (stall)
-                       tmp |= MV_U3D_EPXCR_EP_HALT;
-               else
-                       tmp &= ~MV_U3D_EPXCR_EP_HALT;
-               iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
-       } else {
-               tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
-               if (stall)
-                       tmp |= MV_U3D_EPXCR_EP_HALT;
-               else
-                       tmp &= ~MV_U3D_EPXCR_EP_HALT;
-               iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
-       }
-}
-
-static int mv_u3d_ep_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge)
-{
-       struct mv_u3d_ep *ep;
-       unsigned long flags = 0;
-       int status = 0;
-       struct mv_u3d *u3d;
-
-       ep = container_of(_ep, struct mv_u3d_ep, ep);
-       u3d = ep->u3d;
-       if (!ep->ep.desc) {
-               status = -EINVAL;
-               goto out;
-       }
-
-       if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
-               status = -EOPNOTSUPP;
-               goto out;
-       }
-
-       /*
-        * Attempt to halt IN ep will fail if any transfer requests
-        * are still queue
-        */
-       if (halt && (mv_u3d_ep_dir(ep) == MV_U3D_EP_DIR_IN)
-                       && !list_empty(&ep->queue)) {
-               status = -EAGAIN;
-               goto out;
-       }
-
-       spin_lock_irqsave(&ep->u3d->lock, flags);
-       mv_u3d_ep_set_stall(u3d, ep->ep_num, mv_u3d_ep_dir(ep), halt);
-       if (halt && wedge)
-               ep->wedge = 1;
-       else if (!halt)
-               ep->wedge = 0;
-       spin_unlock_irqrestore(&ep->u3d->lock, flags);
-
-       if (ep->ep_num == 0)
-               u3d->ep0_dir = MV_U3D_EP_DIR_OUT;
-out:
-       return status;
-}
-
-static int mv_u3d_ep_set_halt(struct usb_ep *_ep, int halt)
-{
-       return mv_u3d_ep_set_halt_wedge(_ep, halt, 0);
-}
-
-static int mv_u3d_ep_set_wedge(struct usb_ep *_ep)
-{
-       return mv_u3d_ep_set_halt_wedge(_ep, 1, 1);
-}
-
-static struct usb_ep_ops mv_u3d_ep_ops = {
-       .enable         = mv_u3d_ep_enable,
-       .disable        = mv_u3d_ep_disable,
-
-       .alloc_request  = mv_u3d_alloc_request,
-       .free_request   = mv_u3d_free_request,
-
-       .queue          = mv_u3d_ep_queue,
-       .dequeue        = mv_u3d_ep_dequeue,
-
-       .set_wedge      = mv_u3d_ep_set_wedge,
-       .set_halt       = mv_u3d_ep_set_halt,
-       .fifo_flush     = mv_u3d_ep_fifo_flush,
-};
-
-static void mv_u3d_controller_stop(struct mv_u3d *u3d)
-{
-       u32 tmp;
-
-       if (!u3d->clock_gating && u3d->vbus_valid_detect)
-               iowrite32(MV_U3D_INTR_ENABLE_VBUS_VALID,
-                               &u3d->vuc_regs->intrenable);
-       else
-               iowrite32(0, &u3d->vuc_regs->intrenable);
-       iowrite32(~0x0, &u3d->vuc_regs->endcomplete);
-       iowrite32(~0x0, &u3d->vuc_regs->trbunderrun);
-       iowrite32(~0x0, &u3d->vuc_regs->trbcomplete);
-       iowrite32(~0x0, &u3d->vuc_regs->linkchange);
-       iowrite32(0x1, &u3d->vuc_regs->setuplock);
-
-       /* Reset the RUN bit in the command register to stop USB */
-       tmp = ioread32(&u3d->op_regs->usbcmd);
-       tmp &= ~MV_U3D_CMD_RUN_STOP;
-       iowrite32(tmp, &u3d->op_regs->usbcmd);
-       dev_dbg(u3d->dev, "after u3d_stop, USBCMD 0x%x\n",
-               ioread32(&u3d->op_regs->usbcmd));
-}
-
-static void mv_u3d_controller_start(struct mv_u3d *u3d)
-{
-       u32 usbintr;
-       u32 temp;
-
-       /* enable link LTSSM state machine */
-       temp = ioread32(&u3d->vuc_regs->ltssm);
-       temp |= MV_U3D_LTSSM_PHY_INIT_DONE;
-       iowrite32(temp, &u3d->vuc_regs->ltssm);
-
-       /* Enable interrupts */
-       usbintr = MV_U3D_INTR_ENABLE_LINK_CHG | MV_U3D_INTR_ENABLE_TXDESC_ERR |
-               MV_U3D_INTR_ENABLE_RXDESC_ERR | MV_U3D_INTR_ENABLE_TX_COMPLETE |
-               MV_U3D_INTR_ENABLE_RX_COMPLETE | MV_U3D_INTR_ENABLE_SETUP |
-               (u3d->vbus_valid_detect ? MV_U3D_INTR_ENABLE_VBUS_VALID : 0);
-       iowrite32(usbintr, &u3d->vuc_regs->intrenable);
-
-       /* Enable ctrl ep */
-       iowrite32(0x1, &u3d->vuc_regs->ctrlepenable);
-
-       /* Set the Run bit in the command register */
-       iowrite32(MV_U3D_CMD_RUN_STOP, &u3d->op_regs->usbcmd);
-       dev_dbg(u3d->dev, "after u3d_start, USBCMD 0x%x\n",
-               ioread32(&u3d->op_regs->usbcmd));
-}
-
-static int mv_u3d_controller_reset(struct mv_u3d *u3d)
-{
-       unsigned int loops;
-       u32 tmp;
-
-       /* Stop the controller */
-       tmp = ioread32(&u3d->op_regs->usbcmd);
-       tmp &= ~MV_U3D_CMD_RUN_STOP;
-       iowrite32(tmp, &u3d->op_regs->usbcmd);
-
-       /* Reset the controller to get default values */
-       iowrite32(MV_U3D_CMD_CTRL_RESET, &u3d->op_regs->usbcmd);
-
-       /* wait for reset to complete */
-       loops = LOOPS(MV_U3D_RESET_TIMEOUT);
-       while (ioread32(&u3d->op_regs->usbcmd) & MV_U3D_CMD_CTRL_RESET) {
-               if (loops == 0) {
-                       dev_err(u3d->dev,
-                               "Wait for RESET completed TIMEOUT\n");
-                       return -ETIMEDOUT;
-               }
-               loops--;
-               udelay(LOOPS_USEC);
-       }
-
-       /* Configure the Endpoint Context Address */
-       iowrite32(u3d->ep_context_dma, &u3d->op_regs->dcbaapl);
-       iowrite32(0, &u3d->op_regs->dcbaaph);
-
-       return 0;
-}
-
-static int mv_u3d_enable(struct mv_u3d *u3d)
-{
-       struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
-       int retval;
-
-       if (u3d->active)
-               return 0;
-
-       if (!u3d->clock_gating) {
-               u3d->active = 1;
-               return 0;
-       }
-
-       dev_dbg(u3d->dev, "enable u3d\n");
-       clk_enable(u3d->clk);
-       if (pdata->phy_init) {
-               retval = pdata->phy_init(u3d->phy_regs);
-               if (retval) {
-                       dev_err(u3d->dev,
-                               "init phy error %d\n", retval);
-                       clk_disable(u3d->clk);
-                       return retval;
-               }
-       }
-       u3d->active = 1;
-
-       return 0;
-}
-
-static void mv_u3d_disable(struct mv_u3d *u3d)
-{
-       struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
-       if (u3d->clock_gating && u3d->active) {
-               dev_dbg(u3d->dev, "disable u3d\n");
-               if (pdata->phy_deinit)
-                       pdata->phy_deinit(u3d->phy_regs);
-               clk_disable(u3d->clk);
-               u3d->active = 0;
-       }
-}
-
-static int mv_u3d_vbus_session(struct usb_gadget *gadget, int is_active)
-{
-       struct mv_u3d *u3d;
-       unsigned long flags;
-       int retval = 0;
-
-       u3d = container_of(gadget, struct mv_u3d, gadget);
-
-       spin_lock_irqsave(&u3d->lock, flags);
-
-       u3d->vbus_active = (is_active != 0);
-       dev_dbg(u3d->dev, "%s: softconnect %d, vbus_active %d\n",
-               __func__, u3d->softconnect, u3d->vbus_active);
-       /*
-        * 1. external VBUS detect: we can disable/enable clock on demand.
-        * 2. UDC VBUS detect: we have to enable clock all the time.
-        * 3. No VBUS detect: we have to enable clock all the time.
-        */
-       if (u3d->driver && u3d->softconnect && u3d->vbus_active) {
-               retval = mv_u3d_enable(u3d);
-               if (retval == 0) {
-                       /*
-                        * after clock is disabled, we lost all the register
-                        *  context. We have to re-init registers
-                        */
-                       mv_u3d_controller_reset(u3d);
-                       mv_u3d_ep0_reset(u3d);
-                       mv_u3d_controller_start(u3d);
-               }
-       } else if (u3d->driver && u3d->softconnect) {
-               if (!u3d->active)
-                       goto out;
-
-               /* stop all the transfer in queue*/
-               mv_u3d_stop_activity(u3d, u3d->driver);
-               mv_u3d_controller_stop(u3d);
-               mv_u3d_disable(u3d);
-       }
-
-out:
-       spin_unlock_irqrestore(&u3d->lock, flags);
-       return retval;
-}
-
-/* constrain controller's VBUS power usage
- * This call is used by gadget drivers during SET_CONFIGURATION calls,
- * reporting how much power the device may consume.  For example, this
- * could affect how quickly batteries are recharged.
- *
- * Returns zero on success, else negative errno.
- */
-static int mv_u3d_vbus_draw(struct usb_gadget *gadget, unsigned mA)
-{
-       struct mv_u3d *u3d = container_of(gadget, struct mv_u3d, gadget);
-
-       u3d->power = mA;
-
-       return 0;
-}
-
-static int mv_u3d_pullup(struct usb_gadget *gadget, int is_on)
-{
-       struct mv_u3d *u3d = container_of(gadget, struct mv_u3d, gadget);
-       unsigned long flags;
-       int retval = 0;
-
-       spin_lock_irqsave(&u3d->lock, flags);
-
-       dev_dbg(u3d->dev, "%s: softconnect %d, vbus_active %d\n",
-               __func__, u3d->softconnect, u3d->vbus_active);
-       u3d->softconnect = (is_on != 0);
-       if (u3d->driver && u3d->softconnect && u3d->vbus_active) {
-               retval = mv_u3d_enable(u3d);
-               if (retval == 0) {
-                       /*
-                        * after clock is disabled, we lost all the register
-                        *  context. We have to re-init registers
-                        */
-                       mv_u3d_controller_reset(u3d);
-                       mv_u3d_ep0_reset(u3d);
-                       mv_u3d_controller_start(u3d);
-               }
-       } else if (u3d->driver && u3d->vbus_active) {
-               /* stop all the transfer in queue*/
-               mv_u3d_stop_activity(u3d, u3d->driver);
-               mv_u3d_controller_stop(u3d);
-               mv_u3d_disable(u3d);
-       }
-
-       spin_unlock_irqrestore(&u3d->lock, flags);
-
-       return retval;
-}
-
-static int mv_u3d_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget);
-       struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
-       unsigned long flags;
-
-       if (u3d->driver)
-               return -EBUSY;
-
-       spin_lock_irqsave(&u3d->lock, flags);
-
-       if (!u3d->clock_gating) {
-               clk_enable(u3d->clk);
-               if (pdata->phy_init)
-                       pdata->phy_init(u3d->phy_regs);
-       }
-
-       /* hook up the driver ... */
-       driver->driver.bus = NULL;
-       u3d->driver = driver;
-
-       u3d->ep0_dir = USB_DIR_OUT;
-
-       spin_unlock_irqrestore(&u3d->lock, flags);
-
-       u3d->vbus_valid_detect = 1;
-
-       return 0;
-}
-
-static int mv_u3d_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget);
-       struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
-       unsigned long flags;
-
-       u3d->vbus_valid_detect = 0;
-       spin_lock_irqsave(&u3d->lock, flags);
-
-       /* enable clock to access controller register */
-       clk_enable(u3d->clk);
-       if (pdata->phy_init)
-               pdata->phy_init(u3d->phy_regs);
-
-       mv_u3d_controller_stop(u3d);
-       /* stop all usb activities */
-       u3d->gadget.speed = USB_SPEED_UNKNOWN;
-       mv_u3d_stop_activity(u3d, driver);
-       mv_u3d_disable(u3d);
-
-       if (pdata->phy_deinit)
-               pdata->phy_deinit(u3d->phy_regs);
-       clk_disable(u3d->clk);
-
-       spin_unlock_irqrestore(&u3d->lock, flags);
-
-       u3d->driver = NULL;
-
-       return 0;
-}
-
-/* device controller usb_gadget_ops structure */
-static const struct usb_gadget_ops mv_u3d_ops = {
-       /* notify controller that VBUS is powered or not */
-       .vbus_session   = mv_u3d_vbus_session,
-
-       /* constrain controller's VBUS power usage */
-       .vbus_draw      = mv_u3d_vbus_draw,
-
-       .pullup         = mv_u3d_pullup,
-       .udc_start      = mv_u3d_start,
-       .udc_stop       = mv_u3d_stop,
-};
-
-static int mv_u3d_eps_init(struct mv_u3d *u3d)
-{
-       struct mv_u3d_ep        *ep;
-       char name[14];
-       int i;
-
-       /* initialize ep0, ep0 in/out use eps[1] */
-       ep = &u3d->eps[1];
-       ep->u3d = u3d;
-       strncpy(ep->name, "ep0", sizeof(ep->name));
-       ep->ep.name = ep->name;
-       ep->ep.ops = &mv_u3d_ep_ops;
-       ep->wedge = 0;
-       usb_ep_set_maxpacket_limit(&ep->ep, MV_U3D_EP0_MAX_PKT_SIZE);
-       ep->ep_num = 0;
-       ep->ep.desc = &mv_u3d_ep0_desc;
-       INIT_LIST_HEAD(&ep->queue);
-       INIT_LIST_HEAD(&ep->req_list);
-       ep->ep_type = USB_ENDPOINT_XFER_CONTROL;
-
-       /* add ep0 ep_context */
-       ep->ep_context = &u3d->ep_context[1];
-
-       /* initialize other endpoints */
-       for (i = 2; i < u3d->max_eps * 2; i++) {
-               ep = &u3d->eps[i];
-               if (i & 1) {
-                       snprintf(name, sizeof(name), "ep%din", i >> 1);
-                       ep->direction = MV_U3D_EP_DIR_IN;
-               } else {
-                       snprintf(name, sizeof(name), "ep%dout", i >> 1);
-                       ep->direction = MV_U3D_EP_DIR_OUT;
-               }
-               ep->u3d = u3d;
-               strncpy(ep->name, name, sizeof(ep->name));
-               ep->ep.name = ep->name;
-
-               ep->ep.ops = &mv_u3d_ep_ops;
-               usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
-               ep->ep_num = i / 2;
-
-               INIT_LIST_HEAD(&ep->queue);
-               list_add_tail(&ep->ep.ep_list, &u3d->gadget.ep_list);
-
-               INIT_LIST_HEAD(&ep->req_list);
-               spin_lock_init(&ep->req_lock);
-               ep->ep_context = &u3d->ep_context[i];
-       }
-
-       return 0;
-}
-
-/* delete all endpoint requests, called with spinlock held */
-static void mv_u3d_nuke(struct mv_u3d_ep *ep, int status)
-{
-       /* endpoint fifo flush */
-       mv_u3d_ep_fifo_flush(&ep->ep);
-
-       while (!list_empty(&ep->queue)) {
-               struct mv_u3d_req *req = NULL;
-               req = list_entry(ep->queue.next, struct mv_u3d_req, queue);
-               mv_u3d_done(ep, req, status);
-       }
-}
-
-/* stop all USB activities */
-static
-void mv_u3d_stop_activity(struct mv_u3d *u3d, struct usb_gadget_driver *driver)
-{
-       struct mv_u3d_ep        *ep;
-
-       mv_u3d_nuke(&u3d->eps[1], -ESHUTDOWN);
-
-       list_for_each_entry(ep, &u3d->gadget.ep_list, ep.ep_list) {
-               mv_u3d_nuke(ep, -ESHUTDOWN);
-       }
-
-       /* report disconnect; the driver is already quiesced */
-       if (driver) {
-               spin_unlock(&u3d->lock);
-               driver->disconnect(&u3d->gadget);
-               spin_lock(&u3d->lock);
-       }
-}
-
-static void mv_u3d_irq_process_error(struct mv_u3d *u3d)
-{
-       /* Increment the error count */
-       u3d->errors++;
-       dev_err(u3d->dev, "%s\n", __func__);
-}
-
-static void mv_u3d_irq_process_link_change(struct mv_u3d *u3d)
-{
-       u32 linkchange;
-
-       linkchange = ioread32(&u3d->vuc_regs->linkchange);
-       iowrite32(linkchange, &u3d->vuc_regs->linkchange);
-
-       dev_dbg(u3d->dev, "linkchange: 0x%x\n", linkchange);
-
-       if (linkchange & MV_U3D_LINK_CHANGE_LINK_UP) {
-               dev_dbg(u3d->dev, "link up: ltssm state: 0x%x\n",
-                       ioread32(&u3d->vuc_regs->ltssmstate));
-
-               u3d->usb_state = USB_STATE_DEFAULT;
-               u3d->ep0_dir = MV_U3D_EP_DIR_OUT;
-               u3d->ep0_state = MV_U3D_WAIT_FOR_SETUP;
-
-               /* set speed */
-               u3d->gadget.speed = USB_SPEED_SUPER;
-       }
-
-       if (linkchange & MV_U3D_LINK_CHANGE_SUSPEND) {
-               dev_dbg(u3d->dev, "link suspend\n");
-               u3d->resume_state = u3d->usb_state;
-               u3d->usb_state = USB_STATE_SUSPENDED;
-       }
-
-       if (linkchange & MV_U3D_LINK_CHANGE_RESUME) {
-               dev_dbg(u3d->dev, "link resume\n");
-               u3d->usb_state = u3d->resume_state;
-               u3d->resume_state = 0;
-       }
-
-       if (linkchange & MV_U3D_LINK_CHANGE_WRESET) {
-               dev_dbg(u3d->dev, "warm reset\n");
-               u3d->usb_state = USB_STATE_POWERED;
-       }
-
-       if (linkchange & MV_U3D_LINK_CHANGE_HRESET) {
-               dev_dbg(u3d->dev, "hot reset\n");
-               u3d->usb_state = USB_STATE_DEFAULT;
-       }
-
-       if (linkchange & MV_U3D_LINK_CHANGE_INACT)
-               dev_dbg(u3d->dev, "inactive\n");
-
-       if (linkchange & MV_U3D_LINK_CHANGE_DISABLE_AFTER_U0)
-               dev_dbg(u3d->dev, "ss.disabled\n");
-
-       if (linkchange & MV_U3D_LINK_CHANGE_VBUS_INVALID) {
-               dev_dbg(u3d->dev, "vbus invalid\n");
-               u3d->usb_state = USB_STATE_ATTACHED;
-               u3d->vbus_valid_detect = 1;
-               /* if external vbus detect is not supported,
-                * we handle it here.
-                */
-               if (!u3d->vbus) {
-                       spin_unlock(&u3d->lock);
-                       mv_u3d_vbus_session(&u3d->gadget, 0);
-                       spin_lock(&u3d->lock);
-               }
-       }
-}
-
-static void mv_u3d_ch9setaddress(struct mv_u3d *u3d,
-                               struct usb_ctrlrequest *setup)
-{
-       u32 tmp;
-
-       if (u3d->usb_state != USB_STATE_DEFAULT) {
-               dev_err(u3d->dev,
-                       "%s, cannot setaddr in this state (%d)\n",
-                       __func__, u3d->usb_state);
-               goto err;
-       }
-
-       u3d->dev_addr = (u8)setup->wValue;
-
-       dev_dbg(u3d->dev, "%s: 0x%x\n", __func__, u3d->dev_addr);
-
-       if (u3d->dev_addr > 127) {
-               dev_err(u3d->dev,
-                       "%s, u3d address is wrong (out of range)\n", __func__);
-               u3d->dev_addr = 0;
-               goto err;
-       }
-
-       /* update usb state */
-       u3d->usb_state = USB_STATE_ADDRESS;
-
-       /* set the new address */
-       tmp = ioread32(&u3d->vuc_regs->devaddrtiebrkr);
-       tmp &= ~0x7F;
-       tmp |= (u32)u3d->dev_addr;
-       iowrite32(tmp, &u3d->vuc_regs->devaddrtiebrkr);
-
-       return;
-err:
-       mv_u3d_ep0_stall(u3d);
-}
-
-static int mv_u3d_is_set_configuration(struct usb_ctrlrequest *setup)
-{
-       if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD)
-               if (setup->bRequest == USB_REQ_SET_CONFIGURATION)
-                       return 1;
-
-       return 0;
-}
-
-static void mv_u3d_handle_setup_packet(struct mv_u3d *u3d, u8 ep_num,
-       struct usb_ctrlrequest *setup)
-       __releases(&u3c->lock)
-       __acquires(&u3c->lock)
-{
-       bool delegate = false;
-
-       mv_u3d_nuke(&u3d->eps[ep_num * 2 + MV_U3D_EP_DIR_IN], -ESHUTDOWN);
-
-       dev_dbg(u3d->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
-                       setup->bRequestType, setup->bRequest,
-                       setup->wValue, setup->wIndex, setup->wLength);
-
-       /* We process some stardard setup requests here */
-       if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
-               switch (setup->bRequest) {
-               case USB_REQ_GET_STATUS:
-                       delegate = true;
-                       break;
-
-               case USB_REQ_SET_ADDRESS:
-                       mv_u3d_ch9setaddress(u3d, setup);
-                       break;
-
-               case USB_REQ_CLEAR_FEATURE:
-                       delegate = true;
-                       break;
-
-               case USB_REQ_SET_FEATURE:
-                       delegate = true;
-                       break;
-
-               default:
-                       delegate = true;
-               }
-       } else
-               delegate = true;
-
-       /* delegate USB standard requests to the gadget driver */
-       if (delegate == true) {
-               /* USB requests handled by gadget */
-               if (setup->wLength) {
-                       /* DATA phase from gadget, STATUS phase from u3d */
-                       u3d->ep0_dir = (setup->bRequestType & USB_DIR_IN)
-                                       ? MV_U3D_EP_DIR_IN : MV_U3D_EP_DIR_OUT;
-                       spin_unlock(&u3d->lock);
-                       if (u3d->driver->setup(&u3d->gadget,
-                               &u3d->local_setup_buff) < 0) {
-                               dev_err(u3d->dev, "setup error!\n");
-                               mv_u3d_ep0_stall(u3d);
-                       }
-                       spin_lock(&u3d->lock);
-               } else {
-                       /* no DATA phase, STATUS phase from gadget */
-                       u3d->ep0_dir = MV_U3D_EP_DIR_IN;
-                       u3d->ep0_state = MV_U3D_STATUS_STAGE;
-                       spin_unlock(&u3d->lock);
-                       if (u3d->driver->setup(&u3d->gadget,
-                               &u3d->local_setup_buff) < 0)
-                               mv_u3d_ep0_stall(u3d);
-                       spin_lock(&u3d->lock);
-               }
-
-               if (mv_u3d_is_set_configuration(setup)) {
-                       dev_dbg(u3d->dev, "u3d configured\n");
-                       u3d->usb_state = USB_STATE_CONFIGURED;
-               }
-       }
-}
-
-static void mv_u3d_get_setup_data(struct mv_u3d *u3d, u8 ep_num, u8 *buffer_ptr)
-{
-       struct mv_u3d_ep_context *epcontext;
-
-       epcontext = &u3d->ep_context[ep_num * 2 + MV_U3D_EP_DIR_IN];
-
-       /* Copy the setup packet to local buffer */
-       memcpy(buffer_ptr, (u8 *) &epcontext->setup_buffer, 8);
-}
-
-static void mv_u3d_irq_process_setup(struct mv_u3d *u3d)
-{
-       u32 tmp, i;
-       /* Process all Setup packet received interrupts */
-       tmp = ioread32(&u3d->vuc_regs->setuplock);
-       if (tmp) {
-               for (i = 0; i < u3d->max_eps; i++) {
-                       if (tmp & (1 << i)) {
-                               mv_u3d_get_setup_data(u3d, i,
-                                       (u8 *)(&u3d->local_setup_buff));
-                               mv_u3d_handle_setup_packet(u3d, i,
-                                       &u3d->local_setup_buff);
-                       }
-               }
-       }
-
-       iowrite32(tmp, &u3d->vuc_regs->setuplock);
-}
-
-static void mv_u3d_irq_process_tr_complete(struct mv_u3d *u3d)
-{
-       u32 tmp, bit_pos;
-       int i, ep_num = 0, direction = 0;
-       struct mv_u3d_ep        *curr_ep;
-       struct mv_u3d_req *curr_req, *temp_req;
-       int status;
-
-       tmp = ioread32(&u3d->vuc_regs->endcomplete);
-
-       dev_dbg(u3d->dev, "tr_complete: ep: 0x%x\n", tmp);
-       if (!tmp)
-               return;
-       iowrite32(tmp, &u3d->vuc_regs->endcomplete);
-
-       for (i = 0; i < u3d->max_eps * 2; i++) {
-               ep_num = i >> 1;
-               direction = i % 2;
-
-               bit_pos = 1 << (ep_num + 16 * direction);
-
-               if (!(bit_pos & tmp))
-                       continue;
-
-               if (i == 0)
-                       curr_ep = &u3d->eps[1];
-               else
-                       curr_ep = &u3d->eps[i];
-
-               /* remove req out of ep request list after completion */
-               dev_dbg(u3d->dev, "tr comp: check req_list\n");
-               spin_lock(&curr_ep->req_lock);
-               if (!list_empty(&curr_ep->req_list)) {
-                       struct mv_u3d_req *req;
-                       req = list_entry(curr_ep->req_list.next,
-                                               struct mv_u3d_req, list);
-                       list_del_init(&req->list);
-                       curr_ep->processing = 0;
-               }
-               spin_unlock(&curr_ep->req_lock);
-
-               /* process the req queue until an uncomplete request */
-               list_for_each_entry_safe(curr_req, temp_req,
-                       &curr_ep->queue, queue) {
-                       status = mv_u3d_process_ep_req(u3d, i, curr_req);
-                       if (status)
-                               break;
-                       /* write back status to req */
-                       curr_req->req.status = status;
-
-                       /* ep0 request completion */
-                       if (ep_num == 0) {
-                               mv_u3d_done(curr_ep, curr_req, 0);
-                               break;
-                       } else {
-                               mv_u3d_done(curr_ep, curr_req, status);
-                       }
-               }
-
-               dev_dbg(u3d->dev, "call mv_u3d_start_queue from ep complete\n");
-               mv_u3d_start_queue(curr_ep);
-       }
-}
-
-static irqreturn_t mv_u3d_irq(int irq, void *dev)
-{
-       struct mv_u3d *u3d = (struct mv_u3d *)dev;
-       u32 status, intr;
-       u32 bridgesetting;
-       u32 trbunderrun;
-
-       spin_lock(&u3d->lock);
-
-       status = ioread32(&u3d->vuc_regs->intrcause);
-       intr = ioread32(&u3d->vuc_regs->intrenable);
-       status &= intr;
-
-       if (status == 0) {
-               spin_unlock(&u3d->lock);
-               dev_err(u3d->dev, "irq error!\n");
-               return IRQ_NONE;
-       }
-
-       if (status & MV_U3D_USBINT_VBUS_VALID) {
-               bridgesetting = ioread32(&u3d->vuc_regs->bridgesetting);
-               if (bridgesetting & MV_U3D_BRIDGE_SETTING_VBUS_VALID) {
-                       /* write vbus valid bit of bridge setting to clear */
-                       bridgesetting = MV_U3D_BRIDGE_SETTING_VBUS_VALID;
-                       iowrite32(bridgesetting, &u3d->vuc_regs->bridgesetting);
-                       dev_dbg(u3d->dev, "vbus valid\n");
-
-                       u3d->usb_state = USB_STATE_POWERED;
-                       u3d->vbus_valid_detect = 0;
-                       /* if external vbus detect is not supported,
-                        * we handle it here.
-                        */
-                       if (!u3d->vbus) {
-                               spin_unlock(&u3d->lock);
-                               mv_u3d_vbus_session(&u3d->gadget, 1);
-                               spin_lock(&u3d->lock);
-                       }
-               } else
-                       dev_err(u3d->dev, "vbus bit is not set\n");
-       }
-
-       /* RX data is already in the 16KB FIFO.*/
-       if (status & MV_U3D_USBINT_UNDER_RUN) {
-               trbunderrun = ioread32(&u3d->vuc_regs->trbunderrun);
-               dev_err(u3d->dev, "under run, ep%d\n", trbunderrun);
-               iowrite32(trbunderrun, &u3d->vuc_regs->trbunderrun);
-               mv_u3d_irq_process_error(u3d);
-       }
-
-       if (status & (MV_U3D_USBINT_RXDESC_ERR | MV_U3D_USBINT_TXDESC_ERR)) {
-               /* write one to clear */
-               iowrite32(status & (MV_U3D_USBINT_RXDESC_ERR
-                       | MV_U3D_USBINT_TXDESC_ERR),
-                       &u3d->vuc_regs->intrcause);
-               dev_err(u3d->dev, "desc err 0x%x\n", status);
-               mv_u3d_irq_process_error(u3d);
-       }
-
-       if (status & MV_U3D_USBINT_LINK_CHG)
-               mv_u3d_irq_process_link_change(u3d);
-
-       if (status & MV_U3D_USBINT_TX_COMPLETE)
-               mv_u3d_irq_process_tr_complete(u3d);
-
-       if (status & MV_U3D_USBINT_RX_COMPLETE)
-               mv_u3d_irq_process_tr_complete(u3d);
-
-       if (status & MV_U3D_USBINT_SETUP)
-               mv_u3d_irq_process_setup(u3d);
-
-       spin_unlock(&u3d->lock);
-       return IRQ_HANDLED;
-}
-
-static int mv_u3d_remove(struct platform_device *dev)
-{
-       struct mv_u3d *u3d = platform_get_drvdata(dev);
-
-       BUG_ON(u3d == NULL);
-
-       usb_del_gadget_udc(&u3d->gadget);
-
-       /* free memory allocated in probe */
-       if (u3d->trb_pool)
-               dma_pool_destroy(u3d->trb_pool);
-
-       if (u3d->ep_context)
-               dma_free_coherent(&dev->dev, u3d->ep_context_size,
-                       u3d->ep_context, u3d->ep_context_dma);
-
-       kfree(u3d->eps);
-
-       if (u3d->irq)
-               free_irq(u3d->irq, u3d);
-
-       if (u3d->cap_regs)
-               iounmap(u3d->cap_regs);
-       u3d->cap_regs = NULL;
-
-       kfree(u3d->status_req);
-
-       clk_put(u3d->clk);
-
-       kfree(u3d);
-
-       return 0;
-}
-
-static int mv_u3d_probe(struct platform_device *dev)
-{
-       struct mv_u3d *u3d = NULL;
-       struct mv_usb_platform_data *pdata = dev_get_platdata(&dev->dev);
-       int retval = 0;
-       struct resource *r;
-       size_t size;
-
-       if (!dev_get_platdata(&dev->dev)) {
-               dev_err(&dev->dev, "missing platform_data\n");
-               retval = -ENODEV;
-               goto err_pdata;
-       }
-
-       u3d = kzalloc(sizeof(*u3d), GFP_KERNEL);
-       if (!u3d) {
-               retval = -ENOMEM;
-               goto err_alloc_private;
-       }
-
-       spin_lock_init(&u3d->lock);
-
-       platform_set_drvdata(dev, u3d);
-
-       u3d->dev = &dev->dev;
-       u3d->vbus = pdata->vbus;
-
-       u3d->clk = clk_get(&dev->dev, NULL);
-       if (IS_ERR(u3d->clk)) {
-               retval = PTR_ERR(u3d->clk);
-               goto err_get_clk;
-       }
-
-       r = platform_get_resource_byname(dev, IORESOURCE_MEM, "capregs");
-       if (!r) {
-               dev_err(&dev->dev, "no I/O memory resource defined\n");
-               retval = -ENODEV;
-               goto err_get_cap_regs;
-       }
-
-       u3d->cap_regs = (struct mv_u3d_cap_regs __iomem *)
-               ioremap(r->start, resource_size(r));
-       if (!u3d->cap_regs) {
-               dev_err(&dev->dev, "failed to map I/O memory\n");
-               retval = -EBUSY;
-               goto err_map_cap_regs;
-       } else {
-               dev_dbg(&dev->dev, "cap_regs address: 0x%lx/0x%lx\n",
-                       (unsigned long) r->start,
-                       (unsigned long) u3d->cap_regs);
-       }
-
-       /* we will access controller register, so enable the u3d controller */
-       clk_enable(u3d->clk);
-
-       if (pdata->phy_init) {
-               retval = pdata->phy_init(u3d->phy_regs);
-               if (retval) {
-                       dev_err(&dev->dev, "init phy error %d\n", retval);
-                       goto err_u3d_enable;
-               }
-       }
-
-       u3d->op_regs = (struct mv_u3d_op_regs __iomem *)(u3d->cap_regs
-               + MV_U3D_USB3_OP_REGS_OFFSET);
-
-       u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)(u3d->cap_regs
-               + ioread32(&u3d->cap_regs->vuoff));
-
-       u3d->max_eps = 16;
-
-       /*
-        * some platform will use usb to download image, it may not disconnect
-        * usb gadget before loading kernel. So first stop u3d here.
-        */
-       mv_u3d_controller_stop(u3d);
-       iowrite32(0xFFFFFFFF, &u3d->vuc_regs->intrcause);
-
-       if (pdata->phy_deinit)
-               pdata->phy_deinit(u3d->phy_regs);
-       clk_disable(u3d->clk);
-
-       size = u3d->max_eps * sizeof(struct mv_u3d_ep_context) * 2;
-       size = (size + MV_U3D_EP_CONTEXT_ALIGNMENT - 1)
-               & ~(MV_U3D_EP_CONTEXT_ALIGNMENT - 1);
-       u3d->ep_context = dma_alloc_coherent(&dev->dev, size,
-                                       &u3d->ep_context_dma, GFP_KERNEL);
-       if (!u3d->ep_context) {
-               dev_err(&dev->dev, "allocate ep context memory failed\n");
-               retval = -ENOMEM;
-               goto err_alloc_ep_context;
-       }
-       u3d->ep_context_size = size;
-
-       /* create TRB dma_pool resource */
-       u3d->trb_pool = dma_pool_create("u3d_trb",
-                       &dev->dev,
-                       sizeof(struct mv_u3d_trb_hw),
-                       MV_U3D_TRB_ALIGNMENT,
-                       MV_U3D_DMA_BOUNDARY);
-
-       if (!u3d->trb_pool) {
-               retval = -ENOMEM;
-               goto err_alloc_trb_pool;
-       }
-
-       size = u3d->max_eps * sizeof(struct mv_u3d_ep) * 2;
-       u3d->eps = kzalloc(size, GFP_KERNEL);
-       if (!u3d->eps) {
-               retval = -ENOMEM;
-               goto err_alloc_eps;
-       }
-
-       /* initialize ep0 status request structure */
-       u3d->status_req = kzalloc(sizeof(struct mv_u3d_req) + 8, GFP_KERNEL);
-       if (!u3d->status_req) {
-               retval = -ENOMEM;
-               goto err_alloc_status_req;
-       }
-       INIT_LIST_HEAD(&u3d->status_req->queue);
-
-       /* allocate a small amount of memory to get valid address */
-       u3d->status_req->req.buf = (char *)u3d->status_req
-                                       + sizeof(struct mv_u3d_req);
-       u3d->status_req->req.dma = virt_to_phys(u3d->status_req->req.buf);
-
-       u3d->resume_state = USB_STATE_NOTATTACHED;
-       u3d->usb_state = USB_STATE_ATTACHED;
-       u3d->ep0_dir = MV_U3D_EP_DIR_OUT;
-       u3d->remote_wakeup = 0;
-
-       r = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-       if (!r) {
-               dev_err(&dev->dev, "no IRQ resource defined\n");
-               retval = -ENODEV;
-               goto err_get_irq;
-       }
-       u3d->irq = r->start;
-       if (request_irq(u3d->irq, mv_u3d_irq,
-               IRQF_SHARED, driver_name, u3d)) {
-               u3d->irq = 0;
-               dev_err(&dev->dev, "Request irq %d for u3d failed\n",
-                       u3d->irq);
-               retval = -ENODEV;
-               goto err_request_irq;
-       }
-
-       /* initialize gadget structure */
-       u3d->gadget.ops = &mv_u3d_ops;  /* usb_gadget_ops */
-       u3d->gadget.ep0 = &u3d->eps[1].ep;      /* gadget ep0 */
-       INIT_LIST_HEAD(&u3d->gadget.ep_list);   /* ep_list */
-       u3d->gadget.speed = USB_SPEED_UNKNOWN;  /* speed */
-
-       /* the "gadget" abstracts/virtualizes the controller */
-       u3d->gadget.name = driver_name;         /* gadget name */
-
-       mv_u3d_eps_init(u3d);
-
-       /* external vbus detection */
-       if (u3d->vbus) {
-               u3d->clock_gating = 1;
-               dev_err(&dev->dev, "external vbus detection\n");
-       }
-
-       if (!u3d->clock_gating)
-               u3d->vbus_active = 1;
-
-       /* enable usb3 controller vbus detection */
-       u3d->vbus_valid_detect = 1;
-
-       retval = usb_add_gadget_udc(&dev->dev, &u3d->gadget);
-       if (retval)
-               goto err_unregister;
-
-       dev_dbg(&dev->dev, "successful probe usb3 device %s clock gating.\n",
-               u3d->clock_gating ? "with" : "without");
-
-       return 0;
-
-err_unregister:
-       free_irq(u3d->irq, u3d);
-err_request_irq:
-err_get_irq:
-       kfree(u3d->status_req);
-err_alloc_status_req:
-       kfree(u3d->eps);
-err_alloc_eps:
-       dma_pool_destroy(u3d->trb_pool);
-err_alloc_trb_pool:
-       dma_free_coherent(&dev->dev, u3d->ep_context_size,
-               u3d->ep_context, u3d->ep_context_dma);
-err_alloc_ep_context:
-       if (pdata->phy_deinit)
-               pdata->phy_deinit(u3d->phy_regs);
-       clk_disable(u3d->clk);
-err_u3d_enable:
-       iounmap(u3d->cap_regs);
-err_map_cap_regs:
-err_get_cap_regs:
-err_get_clk:
-       clk_put(u3d->clk);
-       kfree(u3d);
-err_alloc_private:
-err_pdata:
-       return retval;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int mv_u3d_suspend(struct device *dev)
-{
-       struct mv_u3d *u3d = dev_get_drvdata(dev);
-
-       /*
-        * only cable is unplugged, usb can suspend.
-        * So do not care about clock_gating == 1, it is handled by
-        * vbus session.
-        */
-       if (!u3d->clock_gating) {
-               mv_u3d_controller_stop(u3d);
-
-               spin_lock_irq(&u3d->lock);
-               /* stop all usb activities */
-               mv_u3d_stop_activity(u3d, u3d->driver);
-               spin_unlock_irq(&u3d->lock);
-
-               mv_u3d_disable(u3d);
-       }
-
-       return 0;
-}
-
-static int mv_u3d_resume(struct device *dev)
-{
-       struct mv_u3d *u3d = dev_get_drvdata(dev);
-       int retval;
-
-       if (!u3d->clock_gating) {
-               retval = mv_u3d_enable(u3d);
-               if (retval)
-                       return retval;
-
-               if (u3d->driver && u3d->softconnect) {
-                       mv_u3d_controller_reset(u3d);
-                       mv_u3d_ep0_reset(u3d);
-                       mv_u3d_controller_start(u3d);
-               }
-       }
-
-       return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
-
-static void mv_u3d_shutdown(struct platform_device *dev)
-{
-       struct mv_u3d *u3d = platform_get_drvdata(dev);
-       u32 tmp;
-
-       tmp = ioread32(&u3d->op_regs->usbcmd);
-       tmp &= ~MV_U3D_CMD_RUN_STOP;
-       iowrite32(tmp, &u3d->op_regs->usbcmd);
-}
-
-static struct platform_driver mv_u3d_driver = {
-       .probe          = mv_u3d_probe,
-       .remove         = mv_u3d_remove,
-       .shutdown       = mv_u3d_shutdown,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "mv-u3d",
-               .pm     = &mv_u3d_pm_ops,
-       },
-};
-
-module_platform_driver(mv_u3d_driver);
-MODULE_ALIAS("platform:mv-u3d");
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Yu Xu <yuxu@marvell.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h
deleted file mode 100644 (file)
index be77f20..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) 2011 Marvell International Ltd. 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 as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#ifndef __MV_UDC_H
-#define __MV_UDC_H
-
-#define VUSBHS_MAX_PORTS       8
-
-#define DQH_ALIGNMENT          2048
-#define DTD_ALIGNMENT          64
-#define DMA_BOUNDARY           4096
-
-#define EP_DIR_IN      1
-#define EP_DIR_OUT     0
-
-#define DMA_ADDR_INVALID       (~(dma_addr_t)0)
-
-#define EP0_MAX_PKT_SIZE       64
-/* ep0 transfer state */
-#define WAIT_FOR_SETUP         0
-#define DATA_STATE_XMIT                1
-#define DATA_STATE_NEED_ZLP    2
-#define WAIT_FOR_OUT_STATUS    3
-#define DATA_STATE_RECV                4
-
-#define CAPLENGTH_MASK         (0xff)
-#define DCCPARAMS_DEN_MASK     (0x1f)
-
-#define HCSPARAMS_PPC          (0x10)
-
-/* Frame Index Register Bit Masks */
-#define USB_FRINDEX_MASKS      0x3fff
-
-/* Command Register Bit Masks */
-#define USBCMD_RUN_STOP                                (0x00000001)
-#define USBCMD_CTRL_RESET                      (0x00000002)
-#define USBCMD_SETUP_TRIPWIRE_SET              (0x00002000)
-#define USBCMD_SETUP_TRIPWIRE_CLEAR            (~USBCMD_SETUP_TRIPWIRE_SET)
-
-#define USBCMD_ATDTW_TRIPWIRE_SET              (0x00004000)
-#define USBCMD_ATDTW_TRIPWIRE_CLEAR            (~USBCMD_ATDTW_TRIPWIRE_SET)
-
-/* bit 15,3,2 are for frame list size */
-#define USBCMD_FRAME_SIZE_1024                 (0x00000000) /* 000 */
-#define USBCMD_FRAME_SIZE_512                  (0x00000004) /* 001 */
-#define USBCMD_FRAME_SIZE_256                  (0x00000008) /* 010 */
-#define USBCMD_FRAME_SIZE_128                  (0x0000000C) /* 011 */
-#define USBCMD_FRAME_SIZE_64                   (0x00008000) /* 100 */
-#define USBCMD_FRAME_SIZE_32                   (0x00008004) /* 101 */
-#define USBCMD_FRAME_SIZE_16                   (0x00008008) /* 110 */
-#define USBCMD_FRAME_SIZE_8                    (0x0000800C) /* 111 */
-
-#define EPCTRL_TX_ALL_MASK                     (0xFFFF0000)
-#define EPCTRL_RX_ALL_MASK                     (0x0000FFFF)
-
-#define EPCTRL_TX_DATA_TOGGLE_RST              (0x00400000)
-#define EPCTRL_TX_EP_STALL                     (0x00010000)
-#define EPCTRL_RX_EP_STALL                     (0x00000001)
-#define EPCTRL_RX_DATA_TOGGLE_RST              (0x00000040)
-#define EPCTRL_RX_ENABLE                       (0x00000080)
-#define EPCTRL_TX_ENABLE                       (0x00800000)
-#define EPCTRL_CONTROL                         (0x00000000)
-#define EPCTRL_ISOCHRONOUS                     (0x00040000)
-#define EPCTRL_BULK                            (0x00080000)
-#define EPCTRL_INT                             (0x000C0000)
-#define EPCTRL_TX_TYPE                         (0x000C0000)
-#define EPCTRL_RX_TYPE                         (0x0000000C)
-#define EPCTRL_DATA_TOGGLE_INHIBIT             (0x00000020)
-#define EPCTRL_TX_EP_TYPE_SHIFT                        (18)
-#define EPCTRL_RX_EP_TYPE_SHIFT                        (2)
-
-#define EPCOMPLETE_MAX_ENDPOINTS               (16)
-
-/* endpoint list address bit masks */
-#define USB_EP_LIST_ADDRESS_MASK              0xfffff800
-
-#define PORTSCX_W1C_BITS                       0x2a
-#define PORTSCX_PORT_RESET                     0x00000100
-#define PORTSCX_PORT_POWER                     0x00001000
-#define PORTSCX_FORCE_FULL_SPEED_CONNECT       0x01000000
-#define PORTSCX_PAR_XCVR_SELECT                        0xC0000000
-#define PORTSCX_PORT_FORCE_RESUME              0x00000040
-#define PORTSCX_PORT_SUSPEND                   0x00000080
-#define PORTSCX_PORT_SPEED_FULL                        0x00000000
-#define PORTSCX_PORT_SPEED_LOW                 0x04000000
-#define PORTSCX_PORT_SPEED_HIGH                        0x08000000
-#define PORTSCX_PORT_SPEED_MASK                        0x0C000000
-
-/* USB MODE Register Bit Masks */
-#define USBMODE_CTRL_MODE_IDLE                 0x00000000
-#define USBMODE_CTRL_MODE_DEVICE               0x00000002
-#define USBMODE_CTRL_MODE_HOST                 0x00000003
-#define USBMODE_CTRL_MODE_RSV                  0x00000001
-#define USBMODE_SETUP_LOCK_OFF                 0x00000008
-#define USBMODE_STREAM_DISABLE                 0x00000010
-
-/* USB STS Register Bit Masks */
-#define USBSTS_INT                     0x00000001
-#define USBSTS_ERR                     0x00000002
-#define USBSTS_PORT_CHANGE             0x00000004
-#define USBSTS_FRM_LST_ROLL            0x00000008
-#define USBSTS_SYS_ERR                 0x00000010
-#define USBSTS_IAA                     0x00000020
-#define USBSTS_RESET                   0x00000040
-#define USBSTS_SOF                     0x00000080
-#define USBSTS_SUSPEND                 0x00000100
-#define USBSTS_HC_HALTED               0x00001000
-#define USBSTS_RCL                     0x00002000
-#define USBSTS_PERIODIC_SCHEDULE       0x00004000
-#define USBSTS_ASYNC_SCHEDULE          0x00008000
-
-
-/* Interrupt Enable Register Bit Masks */
-#define USBINTR_INT_EN                          (0x00000001)
-#define USBINTR_ERR_INT_EN                      (0x00000002)
-#define USBINTR_PORT_CHANGE_DETECT_EN           (0x00000004)
-
-#define USBINTR_ASYNC_ADV_AAE                   (0x00000020)
-#define USBINTR_ASYNC_ADV_AAE_ENABLE            (0x00000020)
-#define USBINTR_ASYNC_ADV_AAE_DISABLE           (0xFFFFFFDF)
-
-#define USBINTR_RESET_EN                        (0x00000040)
-#define USBINTR_SOF_UFRAME_EN                   (0x00000080)
-#define USBINTR_DEVICE_SUSPEND                  (0x00000100)
-
-#define USB_DEVICE_ADDRESS_MASK                        (0xfe000000)
-#define USB_DEVICE_ADDRESS_BIT_SHIFT           (25)
-
-struct mv_cap_regs {
-       u32     caplength_hciversion;
-       u32     hcsparams;      /* HC structural parameters */
-       u32     hccparams;      /* HC Capability Parameters*/
-       u32     reserved[5];
-       u32     dciversion;     /* DC version number and reserved 16 bits */
-       u32     dccparams;      /* DC Capability Parameters */
-};
-
-struct mv_op_regs {
-       u32     usbcmd;         /* Command register */
-       u32     usbsts;         /* Status register */
-       u32     usbintr;        /* Interrupt enable */
-       u32     frindex;        /* Frame index */
-       u32     reserved1[1];
-       u32     deviceaddr;     /* Device Address */
-       u32     eplistaddr;     /* Endpoint List Address */
-       u32     ttctrl;         /* HOST TT status and control */
-       u32     burstsize;      /* Programmable Burst Size */
-       u32     txfilltuning;   /* Host Transmit Pre-Buffer Packet Tuning */
-       u32     reserved[4];
-       u32     epnak;          /* Endpoint NAK */
-       u32     epnaken;        /* Endpoint NAK Enable */
-       u32     configflag;     /* Configured Flag register */
-       u32     portsc[VUSBHS_MAX_PORTS]; /* Port Status/Control x, x = 1..8 */
-       u32     otgsc;
-       u32     usbmode;        /* USB Host/Device mode */
-       u32     epsetupstat;    /* Endpoint Setup Status */
-       u32     epprime;        /* Endpoint Initialize */
-       u32     epflush;        /* Endpoint De-initialize */
-       u32     epstatus;       /* Endpoint Status */
-       u32     epcomplete;     /* Endpoint Interrupt On Complete */
-       u32     epctrlx[16];    /* Endpoint Control, where x = 0.. 15 */
-       u32     mcr;            /* Mux Control */
-       u32     isr;            /* Interrupt Status */
-       u32     ier;            /* Interrupt Enable */
-};
-
-struct mv_udc {
-       struct usb_gadget               gadget;
-       struct usb_gadget_driver        *driver;
-       spinlock_t                      lock;
-       struct completion               *done;
-       struct platform_device          *dev;
-       int                             irq;
-
-       struct mv_cap_regs __iomem      *cap_regs;
-       struct mv_op_regs __iomem       *op_regs;
-       void __iomem                    *phy_regs;
-       unsigned int                    max_eps;
-       struct mv_dqh                   *ep_dqh;
-       size_t                          ep_dqh_size;
-       dma_addr_t                      ep_dqh_dma;
-
-       struct dma_pool                 *dtd_pool;
-       struct mv_ep                    *eps;
-
-       struct mv_dtd                   *dtd_head;
-       struct mv_dtd                   *dtd_tail;
-       unsigned int                    dtd_entries;
-
-       struct mv_req                   *status_req;
-       struct usb_ctrlrequest          local_setup_buff;
-
-       unsigned int            resume_state;   /* USB state to resume */
-       unsigned int            usb_state;      /* USB current state */
-       unsigned int            ep0_state;      /* Endpoint zero state */
-       unsigned int            ep0_dir;
-
-       unsigned int            dev_addr;
-       unsigned int            test_mode;
-
-       int                     errors;
-       unsigned                softconnect:1,
-                               vbus_active:1,
-                               remote_wakeup:1,
-                               softconnected:1,
-                               force_fs:1,
-                               clock_gating:1,
-                               active:1,
-                               stopped:1;      /* stop bit is setted */
-
-       struct work_struct      vbus_work;
-       struct workqueue_struct *qwork;
-
-       struct usb_phy          *transceiver;
-
-       struct mv_usb_platform_data     *pdata;
-
-       /* some SOC has mutiple clock sources for USB*/
-       struct clk      *clk;
-};
-
-/* endpoint data structure */
-struct mv_ep {
-       struct usb_ep           ep;
-       struct mv_udc           *udc;
-       struct list_head        queue;
-       struct mv_dqh           *dqh;
-       u32                     direction;
-       char                    name[14];
-       unsigned                stopped:1,
-                               wedge:1,
-                               ep_type:2,
-                               ep_num:8;
-};
-
-/* request data structure */
-struct mv_req {
-       struct usb_request      req;
-       struct mv_dtd           *dtd, *head, *tail;
-       struct mv_ep            *ep;
-       struct list_head        queue;
-       unsigned int            test_mode;
-       unsigned                dtd_count;
-       unsigned                mapped:1;
-};
-
-#define EP_QUEUE_HEAD_MULT_POS                 30
-#define EP_QUEUE_HEAD_ZLT_SEL                  0x20000000
-#define EP_QUEUE_HEAD_MAX_PKT_LEN_POS          16
-#define EP_QUEUE_HEAD_MAX_PKT_LEN(ep_info)     (((ep_info)>>16)&0x07ff)
-#define EP_QUEUE_HEAD_IOS                      0x00008000
-#define EP_QUEUE_HEAD_NEXT_TERMINATE           0x00000001
-#define EP_QUEUE_HEAD_IOC                      0x00008000
-#define EP_QUEUE_HEAD_MULTO                    0x00000C00
-#define EP_QUEUE_HEAD_STATUS_HALT              0x00000040
-#define EP_QUEUE_HEAD_STATUS_ACTIVE            0x00000080
-#define EP_QUEUE_CURRENT_OFFSET_MASK           0x00000FFF
-#define EP_QUEUE_HEAD_NEXT_POINTER_MASK                0xFFFFFFE0
-#define EP_QUEUE_FRINDEX_MASK                  0x000007FF
-#define EP_MAX_LENGTH_TRANSFER                 0x4000
-
-struct mv_dqh {
-       /* Bits 16..26 Bit 15 is Interrupt On Setup */
-       u32     max_packet_length;
-       u32     curr_dtd_ptr;           /* Current dTD Pointer */
-       u32     next_dtd_ptr;           /* Next dTD Pointer */
-       /* Total bytes (16..30), IOC (15), INT (8), STS (0-7) */
-       u32     size_ioc_int_sts;
-       u32     buff_ptr0;              /* Buffer pointer Page 0 (12-31) */
-       u32     buff_ptr1;              /* Buffer pointer Page 1 (12-31) */
-       u32     buff_ptr2;              /* Buffer pointer Page 2 (12-31) */
-       u32     buff_ptr3;              /* Buffer pointer Page 3 (12-31) */
-       u32     buff_ptr4;              /* Buffer pointer Page 4 (12-31) */
-       u32     reserved1;
-       /* 8 bytes of setup data that follows the Setup PID */
-       u8      setup_buffer[8];
-       u32     reserved2[4];
-};
-
-
-#define DTD_NEXT_TERMINATE             (0x00000001)
-#define DTD_IOC                                (0x00008000)
-#define DTD_STATUS_ACTIVE              (0x00000080)
-#define DTD_STATUS_HALTED              (0x00000040)
-#define DTD_STATUS_DATA_BUFF_ERR       (0x00000020)
-#define DTD_STATUS_TRANSACTION_ERR     (0x00000008)
-#define DTD_RESERVED_FIELDS            (0x00007F00)
-#define DTD_ERROR_MASK                 (0x68)
-#define DTD_ADDR_MASK                  (0xFFFFFFE0)
-#define DTD_PACKET_SIZE                        0x7FFF0000
-#define DTD_LENGTH_BIT_POS             (16)
-
-struct mv_dtd {
-       u32     dtd_next;
-       u32     size_ioc_sts;
-       u32     buff_ptr0;              /* Buffer pointer Page 0 */
-       u32     buff_ptr1;              /* Buffer pointer Page 1 */
-       u32     buff_ptr2;              /* Buffer pointer Page 2 */
-       u32     buff_ptr3;              /* Buffer pointer Page 3 */
-       u32     buff_ptr4;              /* Buffer pointer Page 4 */
-       u32     scratch_ptr;
-       /* 32 bytes */
-       dma_addr_t td_dma;              /* dma address for this td */
-       struct mv_dtd *next_dtd_virt;
-};
-
-#endif
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
deleted file mode 100644 (file)
index fcff3a5..0000000
+++ /dev/null
@@ -1,2423 +0,0 @@
-/*
- * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
- * Author: Chao Xie <chao.xie@marvell.com>
- *        Neil Zhang <zhangwm@marvell.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/otg.h>
-#include <linux/pm.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/platform_data/mv_usb.h>
-#include <asm/unaligned.h>
-
-#include "mv_udc.h"
-
-#define DRIVER_DESC            "Marvell PXA USB Device Controller driver"
-#define DRIVER_VERSION         "8 Nov 2010"
-
-#define ep_dir(ep)     (((ep)->ep_num == 0) ? \
-                               ((ep)->udc->ep0_dir) : ((ep)->direction))
-
-/* timeout value -- usec */
-#define RESET_TIMEOUT          10000
-#define FLUSH_TIMEOUT          10000
-#define EPSTATUS_TIMEOUT       10000
-#define PRIME_TIMEOUT          10000
-#define READSAFE_TIMEOUT       1000
-
-#define LOOPS_USEC_SHIFT       1
-#define LOOPS_USEC             (1 << LOOPS_USEC_SHIFT)
-#define LOOPS(timeout)         ((timeout) >> LOOPS_USEC_SHIFT)
-
-static DECLARE_COMPLETION(release_done);
-
-static const char driver_name[] = "mv_udc";
-static const char driver_desc[] = DRIVER_DESC;
-
-static void nuke(struct mv_ep *ep, int status);
-static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver);
-
-/* for endpoint 0 operations */
-static const struct usb_endpoint_descriptor mv_ep0_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-       .bEndpointAddress =     0,
-       .bmAttributes =         USB_ENDPOINT_XFER_CONTROL,
-       .wMaxPacketSize =       EP0_MAX_PKT_SIZE,
-};
-
-static void ep0_reset(struct mv_udc *udc)
-{
-       struct mv_ep *ep;
-       u32 epctrlx;
-       int i = 0;
-
-       /* ep0 in and out */
-       for (i = 0; i < 2; i++) {
-               ep = &udc->eps[i];
-               ep->udc = udc;
-
-               /* ep0 dQH */
-               ep->dqh = &udc->ep_dqh[i];
-
-               /* configure ep0 endpoint capabilities in dQH */
-               ep->dqh->max_packet_length =
-                       (EP0_MAX_PKT_SIZE << EP_QUEUE_HEAD_MAX_PKT_LEN_POS)
-                       | EP_QUEUE_HEAD_IOS;
-
-               ep->dqh->next_dtd_ptr = EP_QUEUE_HEAD_NEXT_TERMINATE;
-
-               epctrlx = readl(&udc->op_regs->epctrlx[0]);
-               if (i) {        /* TX */
-                       epctrlx |= EPCTRL_TX_ENABLE
-                               | (USB_ENDPOINT_XFER_CONTROL
-                                       << EPCTRL_TX_EP_TYPE_SHIFT);
-
-               } else {        /* RX */
-                       epctrlx |= EPCTRL_RX_ENABLE
-                               | (USB_ENDPOINT_XFER_CONTROL
-                                       << EPCTRL_RX_EP_TYPE_SHIFT);
-               }
-
-               writel(epctrlx, &udc->op_regs->epctrlx[0]);
-       }
-}
-
-/* protocol ep0 stall, will automatically be cleared on new transaction */
-static void ep0_stall(struct mv_udc *udc)
-{
-       u32     epctrlx;
-
-       /* set TX and RX to stall */
-       epctrlx = readl(&udc->op_regs->epctrlx[0]);
-       epctrlx |= EPCTRL_RX_EP_STALL | EPCTRL_TX_EP_STALL;
-       writel(epctrlx, &udc->op_regs->epctrlx[0]);
-
-       /* update ep0 state */
-       udc->ep0_state = WAIT_FOR_SETUP;
-       udc->ep0_dir = EP_DIR_OUT;
-}
-
-static int process_ep_req(struct mv_udc *udc, int index,
-       struct mv_req *curr_req)
-{
-       struct mv_dtd   *curr_dtd;
-       struct mv_dqh   *curr_dqh;
-       int td_complete, actual, remaining_length;
-       int i, direction;
-       int retval = 0;
-       u32 errors;
-       u32 bit_pos;
-
-       curr_dqh = &udc->ep_dqh[index];
-       direction = index % 2;
-
-       curr_dtd = curr_req->head;
-       td_complete = 0;
-       actual = curr_req->req.length;
-
-       for (i = 0; i < curr_req->dtd_count; i++) {
-               if (curr_dtd->size_ioc_sts & DTD_STATUS_ACTIVE) {
-                       dev_dbg(&udc->dev->dev, "%s, dTD not completed\n",
-                               udc->eps[index].name);
-                       return 1;
-               }
-
-               errors = curr_dtd->size_ioc_sts & DTD_ERROR_MASK;
-               if (!errors) {
-                       remaining_length =
-                               (curr_dtd->size_ioc_sts & DTD_PACKET_SIZE)
-                                       >> DTD_LENGTH_BIT_POS;
-                       actual -= remaining_length;
-
-                       if (remaining_length) {
-                               if (direction) {
-                                       dev_dbg(&udc->dev->dev,
-                                               "TX dTD remains data\n");
-                                       retval = -EPROTO;
-                                       break;
-                               } else
-                                       break;
-                       }
-               } else {
-                       dev_info(&udc->dev->dev,
-                               "complete_tr error: ep=%d %s: error = 0x%x\n",
-                               index >> 1, direction ? "SEND" : "RECV",
-                               errors);
-                       if (errors & DTD_STATUS_HALTED) {
-                               /* Clear the errors and Halt condition */
-                               curr_dqh->size_ioc_int_sts &= ~errors;
-                               retval = -EPIPE;
-                       } else if (errors & DTD_STATUS_DATA_BUFF_ERR) {
-                               retval = -EPROTO;
-                       } else if (errors & DTD_STATUS_TRANSACTION_ERR) {
-                               retval = -EILSEQ;
-                       }
-               }
-               if (i != curr_req->dtd_count - 1)
-                       curr_dtd = (struct mv_dtd *)curr_dtd->next_dtd_virt;
-       }
-       if (retval)
-               return retval;
-
-       if (direction == EP_DIR_OUT)
-               bit_pos = 1 << curr_req->ep->ep_num;
-       else
-               bit_pos = 1 << (16 + curr_req->ep->ep_num);
-
-       while ((curr_dqh->curr_dtd_ptr == curr_dtd->td_dma)) {
-               if (curr_dtd->dtd_next == EP_QUEUE_HEAD_NEXT_TERMINATE) {
-                       while (readl(&udc->op_regs->epstatus) & bit_pos)
-                               udelay(1);
-                       break;
-               }
-               udelay(1);
-       }
-
-       curr_req->req.actual = actual;
-
-       return 0;
-}
-
-/*
- * done() - retire a request; caller blocked irqs
- * @status : request status to be set, only works when
- * request is still in progress.
- */
-static void done(struct mv_ep *ep, struct mv_req *req, int status)
-       __releases(&ep->udc->lock)
-       __acquires(&ep->udc->lock)
-{
-       struct mv_udc *udc = NULL;
-       unsigned char stopped = ep->stopped;
-       struct mv_dtd *curr_td, *next_td;
-       int j;
-
-       udc = (struct mv_udc *)ep->udc;
-       /* Removed the req from fsl_ep->queue */
-       list_del_init(&req->queue);
-
-       /* req.status should be set as -EINPROGRESS in ep_queue() */
-       if (req->req.status == -EINPROGRESS)
-               req->req.status = status;
-       else
-               status = req->req.status;
-
-       /* Free dtd for the request */
-       next_td = req->head;
-       for (j = 0; j < req->dtd_count; j++) {
-               curr_td = next_td;
-               if (j != req->dtd_count - 1)
-                       next_td = curr_td->next_dtd_virt;
-               dma_pool_free(udc->dtd_pool, curr_td, curr_td->td_dma);
-       }
-
-       usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
-
-       if (status && (status != -ESHUTDOWN))
-               dev_info(&udc->dev->dev, "complete %s req %p stat %d len %u/%u",
-                       ep->ep.name, &req->req, status,
-                       req->req.actual, req->req.length);
-
-       ep->stopped = 1;
-
-       spin_unlock(&ep->udc->lock);
-       /*
-        * complete() is from gadget layer,
-        * eg fsg->bulk_in_complete()
-        */
-       if (req->req.complete)
-               req->req.complete(&ep->ep, &req->req);
-
-       spin_lock(&ep->udc->lock);
-       ep->stopped = stopped;
-}
-
-static int queue_dtd(struct mv_ep *ep, struct mv_req *req)
-{
-       struct mv_udc *udc;
-       struct mv_dqh *dqh;
-       u32 bit_pos, direction;
-       u32 usbcmd, epstatus;
-       unsigned int loops;
-       int retval = 0;
-
-       udc = ep->udc;
-       direction = ep_dir(ep);
-       dqh = &(udc->ep_dqh[ep->ep_num * 2 + direction]);
-       bit_pos = 1 << (((direction == EP_DIR_OUT) ? 0 : 16) + ep->ep_num);
-
-       /* check if the pipe is empty */
-       if (!(list_empty(&ep->queue))) {
-               struct mv_req *lastreq;
-               lastreq = list_entry(ep->queue.prev, struct mv_req, queue);
-               lastreq->tail->dtd_next =
-                       req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK;
-
-               wmb();
-
-               if (readl(&udc->op_regs->epprime) & bit_pos)
-                       goto done;
-
-               loops = LOOPS(READSAFE_TIMEOUT);
-               while (1) {
-                       /* start with setting the semaphores */
-                       usbcmd = readl(&udc->op_regs->usbcmd);
-                       usbcmd |= USBCMD_ATDTW_TRIPWIRE_SET;
-                       writel(usbcmd, &udc->op_regs->usbcmd);
-
-                       /* read the endpoint status */
-                       epstatus = readl(&udc->op_regs->epstatus) & bit_pos;
-
-                       /*
-                        * Reread the ATDTW semaphore bit to check if it is
-                        * cleared. When hardware see a hazard, it will clear
-                        * the bit or else we remain set to 1 and we can
-                        * proceed with priming of endpoint if not already
-                        * primed.
-                        */
-                       if (readl(&udc->op_regs->usbcmd)
-                               & USBCMD_ATDTW_TRIPWIRE_SET)
-                               break;
-
-                       loops--;
-                       if (loops == 0) {
-                               dev_err(&udc->dev->dev,
-                                       "Timeout for ATDTW_TRIPWIRE...\n");
-                               retval = -ETIME;
-                               goto done;
-                       }
-                       udelay(LOOPS_USEC);
-               }
-
-               /* Clear the semaphore */
-               usbcmd = readl(&udc->op_regs->usbcmd);
-               usbcmd &= USBCMD_ATDTW_TRIPWIRE_CLEAR;
-               writel(usbcmd, &udc->op_regs->usbcmd);
-
-               if (epstatus)
-                       goto done;
-       }
-
-       /* Write dQH next pointer and terminate bit to 0 */
-       dqh->next_dtd_ptr = req->head->td_dma
-                               & EP_QUEUE_HEAD_NEXT_POINTER_MASK;
-
-       /* clear active and halt bit, in case set from a previous error */
-       dqh->size_ioc_int_sts &= ~(DTD_STATUS_ACTIVE | DTD_STATUS_HALTED);
-
-       /* Ensure that updates to the QH will occure before priming. */
-       wmb();
-
-       /* Prime the Endpoint */
-       writel(bit_pos, &udc->op_regs->epprime);
-
-done:
-       return retval;
-}
-
-static struct mv_dtd *build_dtd(struct mv_req *req, unsigned *length,
-               dma_addr_t *dma, int *is_last)
-{
-       struct mv_dtd *dtd;
-       struct mv_udc *udc;
-       struct mv_dqh *dqh;
-       u32 temp, mult = 0;
-
-       /* how big will this transfer be? */
-       if (usb_endpoint_xfer_isoc(req->ep->ep.desc)) {
-               dqh = req->ep->dqh;
-               mult = (dqh->max_packet_length >> EP_QUEUE_HEAD_MULT_POS)
-                               & 0x3;
-               *length = min(req->req.length - req->req.actual,
-                               (unsigned)(mult * req->ep->ep.maxpacket));
-       } else
-               *length = min(req->req.length - req->req.actual,
-                               (unsigned)EP_MAX_LENGTH_TRANSFER);
-
-       udc = req->ep->udc;
-
-       /*
-        * Be careful that no _GFP_HIGHMEM is set,
-        * or we can not use dma_to_virt
-        */
-       dtd = dma_pool_alloc(udc->dtd_pool, GFP_ATOMIC, dma);
-       if (dtd == NULL)
-               return dtd;
-
-       dtd->td_dma = *dma;
-       /* initialize buffer page pointers */
-       temp = (u32)(req->req.dma + req->req.actual);
-       dtd->buff_ptr0 = cpu_to_le32(temp);
-       temp &= ~0xFFF;
-       dtd->buff_ptr1 = cpu_to_le32(temp + 0x1000);
-       dtd->buff_ptr2 = cpu_to_le32(temp + 0x2000);
-       dtd->buff_ptr3 = cpu_to_le32(temp + 0x3000);
-       dtd->buff_ptr4 = cpu_to_le32(temp + 0x4000);
-
-       req->req.actual += *length;
-
-       /* zlp is needed if req->req.zero is set */
-       if (req->req.zero) {
-               if (*length == 0 || (*length % req->ep->ep.maxpacket) != 0)
-                       *is_last = 1;
-               else
-                       *is_last = 0;
-       } else if (req->req.length == req->req.actual)
-               *is_last = 1;
-       else
-               *is_last = 0;
-
-       /* Fill in the transfer size; set active bit */
-       temp = ((*length << DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE);
-
-       /* Enable interrupt for the last dtd of a request */
-       if (*is_last && !req->req.no_interrupt)
-               temp |= DTD_IOC;
-
-       temp |= mult << 10;
-
-       dtd->size_ioc_sts = temp;
-
-       mb();
-
-       return dtd;
-}
-
-/* generate dTD linked list for a request */
-static int req_to_dtd(struct mv_req *req)
-{
-       unsigned count;
-       int is_last, is_first = 1;
-       struct mv_dtd *dtd, *last_dtd = NULL;
-       struct mv_udc *udc;
-       dma_addr_t dma;
-
-       udc = req->ep->udc;
-
-       do {
-               dtd = build_dtd(req, &count, &dma, &is_last);
-               if (dtd == NULL)
-                       return -ENOMEM;
-
-               if (is_first) {
-                       is_first = 0;
-                       req->head = dtd;
-               } else {
-                       last_dtd->dtd_next = dma;
-                       last_dtd->next_dtd_virt = dtd;
-               }
-               last_dtd = dtd;
-               req->dtd_count++;
-       } while (!is_last);
-
-       /* set terminate bit to 1 for the last dTD */
-       dtd->dtd_next = DTD_NEXT_TERMINATE;
-
-       req->tail = dtd;
-
-       return 0;
-}
-
-static int mv_ep_enable(struct usb_ep *_ep,
-               const struct usb_endpoint_descriptor *desc)
-{
-       struct mv_udc *udc;
-       struct mv_ep *ep;
-       struct mv_dqh *dqh;
-       u16 max = 0;
-       u32 bit_pos, epctrlx, direction;
-       unsigned char zlt = 0, ios = 0, mult = 0;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct mv_ep, ep);
-       udc = ep->udc;
-
-       if (!_ep || !desc
-                       || desc->bDescriptorType != USB_DT_ENDPOINT)
-               return -EINVAL;
-
-       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       direction = ep_dir(ep);
-       max = usb_endpoint_maxp(desc);
-
-       /*
-        * disable HW zero length termination select
-        * driver handles zero length packet through req->req.zero
-        */
-       zlt = 1;
-
-       bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num);
-
-       /* Check if the Endpoint is Primed */
-       if ((readl(&udc->op_regs->epprime) & bit_pos)
-               || (readl(&udc->op_regs->epstatus) & bit_pos)) {
-               dev_info(&udc->dev->dev,
-                       "ep=%d %s: Init ERROR: ENDPTPRIME=0x%x,"
-                       " ENDPTSTATUS=0x%x, bit_pos=0x%x\n",
-                       (unsigned)ep->ep_num, direction ? "SEND" : "RECV",
-                       (unsigned)readl(&udc->op_regs->epprime),
-                       (unsigned)readl(&udc->op_regs->epstatus),
-                       (unsigned)bit_pos);
-               goto en_done;
-       }
-       /* Set the max packet length, interrupt on Setup and Mult fields */
-       switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
-       case USB_ENDPOINT_XFER_BULK:
-               zlt = 1;
-               mult = 0;
-               break;
-       case USB_ENDPOINT_XFER_CONTROL:
-               ios = 1;
-       case USB_ENDPOINT_XFER_INT:
-               mult = 0;
-               break;
-       case USB_ENDPOINT_XFER_ISOC:
-               /* Calculate transactions needed for high bandwidth iso */
-               mult = (unsigned char)(1 + ((max >> 11) & 0x03));
-               max = max & 0x7ff;      /* bit 0~10 */
-               /* 3 transactions at most */
-               if (mult > 3)
-                       goto en_done;
-               break;
-       default:
-               goto en_done;
-       }
-
-       spin_lock_irqsave(&udc->lock, flags);
-       /* Get the endpoint queue head address */
-       dqh = ep->dqh;
-       dqh->max_packet_length = (max << EP_QUEUE_HEAD_MAX_PKT_LEN_POS)
-               | (mult << EP_QUEUE_HEAD_MULT_POS)
-               | (zlt ? EP_QUEUE_HEAD_ZLT_SEL : 0)
-               | (ios ? EP_QUEUE_HEAD_IOS : 0);
-       dqh->next_dtd_ptr = 1;
-       dqh->size_ioc_int_sts = 0;
-
-       ep->ep.maxpacket = max;
-       ep->ep.desc = desc;
-       ep->stopped = 0;
-
-       /* Enable the endpoint for Rx or Tx and set the endpoint type */
-       epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
-       if (direction == EP_DIR_IN) {
-               epctrlx &= ~EPCTRL_TX_ALL_MASK;
-               epctrlx |= EPCTRL_TX_ENABLE | EPCTRL_TX_DATA_TOGGLE_RST
-                       | ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                               << EPCTRL_TX_EP_TYPE_SHIFT);
-       } else {
-               epctrlx &= ~EPCTRL_RX_ALL_MASK;
-               epctrlx |= EPCTRL_RX_ENABLE | EPCTRL_RX_DATA_TOGGLE_RST
-                       | ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                               << EPCTRL_RX_EP_TYPE_SHIFT);
-       }
-       writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
-
-       /*
-        * Implement Guideline (GL# USB-7) The unused endpoint type must
-        * be programmed to bulk.
-        */
-       epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
-       if ((epctrlx & EPCTRL_RX_ENABLE) == 0) {
-               epctrlx |= (USB_ENDPOINT_XFER_BULK
-                               << EPCTRL_RX_EP_TYPE_SHIFT);
-               writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
-       }
-
-       epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
-       if ((epctrlx & EPCTRL_TX_ENABLE) == 0) {
-               epctrlx |= (USB_ENDPOINT_XFER_BULK
-                               << EPCTRL_TX_EP_TYPE_SHIFT);
-               writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
-       }
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-en_done:
-       return -EINVAL;
-}
-
-static int  mv_ep_disable(struct usb_ep *_ep)
-{
-       struct mv_udc *udc;
-       struct mv_ep *ep;
-       struct mv_dqh *dqh;
-       u32 bit_pos, epctrlx, direction;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct mv_ep, ep);
-       if ((_ep == NULL) || !ep->ep.desc)
-               return -EINVAL;
-
-       udc = ep->udc;
-
-       /* Get the endpoint queue head address */
-       dqh = ep->dqh;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       direction = ep_dir(ep);
-       bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num);
-
-       /* Reset the max packet length and the interrupt on Setup */
-       dqh->max_packet_length = 0;
-
-       /* Disable the endpoint for Rx or Tx and reset the endpoint type */
-       epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
-       epctrlx &= ~((direction == EP_DIR_IN)
-                       ? (EPCTRL_TX_ENABLE | EPCTRL_TX_TYPE)
-                       : (EPCTRL_RX_ENABLE | EPCTRL_RX_TYPE));
-       writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
-
-       /* nuke all pending requests (does flush) */
-       nuke(ep, -ESHUTDOWN);
-
-       ep->ep.desc = NULL;
-       ep->stopped = 1;
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-static struct usb_request *
-mv_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
-{
-       struct mv_req *req = NULL;
-
-       req = kzalloc(sizeof *req, gfp_flags);
-       if (!req)
-               return NULL;
-
-       req->req.dma = DMA_ADDR_INVALID;
-       INIT_LIST_HEAD(&req->queue);
-
-       return &req->req;
-}
-
-static void mv_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct mv_req *req = NULL;
-
-       req = container_of(_req, struct mv_req, req);
-
-       if (_req)
-               kfree(req);
-}
-
-static void mv_ep_fifo_flush(struct usb_ep *_ep)
-{
-       struct mv_udc *udc;
-       u32 bit_pos, direction;
-       struct mv_ep *ep;
-       unsigned int loops;
-
-       if (!_ep)
-               return;
-
-       ep = container_of(_ep, struct mv_ep, ep);
-       if (!ep->ep.desc)
-               return;
-
-       udc = ep->udc;
-       direction = ep_dir(ep);
-
-       if (ep->ep_num == 0)
-               bit_pos = (1 << 16) | 1;
-       else if (direction == EP_DIR_OUT)
-               bit_pos = 1 << ep->ep_num;
-       else
-               bit_pos = 1 << (16 + ep->ep_num);
-
-       loops = LOOPS(EPSTATUS_TIMEOUT);
-       do {
-               unsigned int inter_loops;
-
-               if (loops == 0) {
-                       dev_err(&udc->dev->dev,
-                               "TIMEOUT for ENDPTSTATUS=0x%x, bit_pos=0x%x\n",
-                               (unsigned)readl(&udc->op_regs->epstatus),
-                               (unsigned)bit_pos);
-                       return;
-               }
-               /* Write 1 to the Flush register */
-               writel(bit_pos, &udc->op_regs->epflush);
-
-               /* Wait until flushing completed */
-               inter_loops = LOOPS(FLUSH_TIMEOUT);
-               while (readl(&udc->op_regs->epflush)) {
-                       /*
-                        * ENDPTFLUSH bit should be cleared to indicate this
-                        * operation is complete
-                        */
-                       if (inter_loops == 0) {
-                               dev_err(&udc->dev->dev,
-                                       "TIMEOUT for ENDPTFLUSH=0x%x,"
-                                       "bit_pos=0x%x\n",
-                                       (unsigned)readl(&udc->op_regs->epflush),
-                                       (unsigned)bit_pos);
-                               return;
-                       }
-                       inter_loops--;
-                       udelay(LOOPS_USEC);
-               }
-               loops--;
-       } while (readl(&udc->op_regs->epstatus) & bit_pos);
-}
-
-/* queues (submits) an I/O request to an endpoint */
-static int
-mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
-{
-       struct mv_ep *ep = container_of(_ep, struct mv_ep, ep);
-       struct mv_req *req = container_of(_req, struct mv_req, req);
-       struct mv_udc *udc = ep->udc;
-       unsigned long flags;
-       int retval;
-
-       /* catch various bogus parameters */
-       if (!_req || !req->req.complete || !req->req.buf
-                       || !list_empty(&req->queue)) {
-               dev_err(&udc->dev->dev, "%s, bad params", __func__);
-               return -EINVAL;
-       }
-       if (unlikely(!_ep || !ep->ep.desc)) {
-               dev_err(&udc->dev->dev, "%s, bad ep", __func__);
-               return -EINVAL;
-       }
-
-       udc = ep->udc;
-       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       req->ep = ep;
-
-       /* map virtual address to hardware */
-       retval = usb_gadget_map_request(&udc->gadget, _req, ep_dir(ep));
-       if (retval)
-               return retval;
-
-       req->req.status = -EINPROGRESS;
-       req->req.actual = 0;
-       req->dtd_count = 0;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       /* build dtds and push them to device queue */
-       if (!req_to_dtd(req)) {
-               retval = queue_dtd(ep, req);
-               if (retval) {
-                       spin_unlock_irqrestore(&udc->lock, flags);
-                       dev_err(&udc->dev->dev, "Failed to queue dtd\n");
-                       goto err_unmap_dma;
-               }
-       } else {
-               spin_unlock_irqrestore(&udc->lock, flags);
-               dev_err(&udc->dev->dev, "Failed to dma_pool_alloc\n");
-               retval = -ENOMEM;
-               goto err_unmap_dma;
-       }
-
-       /* Update ep0 state */
-       if (ep->ep_num == 0)
-               udc->ep0_state = DATA_STATE_XMIT;
-
-       /* irq handler advances the queue */
-       list_add_tail(&req->queue, &ep->queue);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-
-err_unmap_dma:
-       usb_gadget_unmap_request(&udc->gadget, _req, ep_dir(ep));
-
-       return retval;
-}
-
-static void mv_prime_ep(struct mv_ep *ep, struct mv_req *req)
-{
-       struct mv_dqh *dqh = ep->dqh;
-       u32 bit_pos;
-
-       /* Write dQH next pointer and terminate bit to 0 */
-       dqh->next_dtd_ptr = req->head->td_dma
-               & EP_QUEUE_HEAD_NEXT_POINTER_MASK;
-
-       /* clear active and halt bit, in case set from a previous error */
-       dqh->size_ioc_int_sts &= ~(DTD_STATUS_ACTIVE | DTD_STATUS_HALTED);
-
-       /* Ensure that updates to the QH will occure before priming. */
-       wmb();
-
-       bit_pos = 1 << (((ep_dir(ep) == EP_DIR_OUT) ? 0 : 16) + ep->ep_num);
-
-       /* Prime the Endpoint */
-       writel(bit_pos, &ep->udc->op_regs->epprime);
-}
-
-/* dequeues (cancels, unlinks) an I/O request from an endpoint */
-static int mv_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct mv_ep *ep = container_of(_ep, struct mv_ep, ep);
-       struct mv_req *req;
-       struct mv_udc *udc = ep->udc;
-       unsigned long flags;
-       int stopped, ret = 0;
-       u32 epctrlx;
-
-       if (!_ep || !_req)
-               return -EINVAL;
-
-       spin_lock_irqsave(&ep->udc->lock, flags);
-       stopped = ep->stopped;
-
-       /* Stop the ep before we deal with the queue */
-       ep->stopped = 1;
-       epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
-       if (ep_dir(ep) == EP_DIR_IN)
-               epctrlx &= ~EPCTRL_TX_ENABLE;
-       else
-               epctrlx &= ~EPCTRL_RX_ENABLE;
-       writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
-
-       /* make sure it's actually queued on this endpoint */
-       list_for_each_entry(req, &ep->queue, queue) {
-               if (&req->req == _req)
-                       break;
-       }
-       if (&req->req != _req) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       /* The request is in progress, or completed but not dequeued */
-       if (ep->queue.next == &req->queue) {
-               _req->status = -ECONNRESET;
-               mv_ep_fifo_flush(_ep);  /* flush current transfer */
-
-               /* The request isn't the last request in this ep queue */
-               if (req->queue.next != &ep->queue) {
-                       struct mv_req *next_req;
-
-                       next_req = list_entry(req->queue.next,
-                               struct mv_req, queue);
-
-                       /* Point the QH to the first TD of next request */
-                       mv_prime_ep(ep, next_req);
-               } else {
-                       struct mv_dqh *qh;
-
-                       qh = ep->dqh;
-                       qh->next_dtd_ptr = 1;
-                       qh->size_ioc_int_sts = 0;
-               }
-
-               /* The request hasn't been processed, patch up the TD chain */
-       } else {
-               struct mv_req *prev_req;
-
-               prev_req = list_entry(req->queue.prev, struct mv_req, queue);
-               writel(readl(&req->tail->dtd_next),
-                               &prev_req->tail->dtd_next);
-
-       }
-
-       done(ep, req, -ECONNRESET);
-
-       /* Enable EP */
-out:
-       epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
-       if (ep_dir(ep) == EP_DIR_IN)
-               epctrlx |= EPCTRL_TX_ENABLE;
-       else
-               epctrlx |= EPCTRL_RX_ENABLE;
-       writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
-       ep->stopped = stopped;
-
-       spin_unlock_irqrestore(&ep->udc->lock, flags);
-       return ret;
-}
-
-static void ep_set_stall(struct mv_udc *udc, u8 ep_num, u8 direction, int stall)
-{
-       u32 epctrlx;
-
-       epctrlx = readl(&udc->op_regs->epctrlx[ep_num]);
-
-       if (stall) {
-               if (direction == EP_DIR_IN)
-                       epctrlx |= EPCTRL_TX_EP_STALL;
-               else
-                       epctrlx |= EPCTRL_RX_EP_STALL;
-       } else {
-               if (direction == EP_DIR_IN) {
-                       epctrlx &= ~EPCTRL_TX_EP_STALL;
-                       epctrlx |= EPCTRL_TX_DATA_TOGGLE_RST;
-               } else {
-                       epctrlx &= ~EPCTRL_RX_EP_STALL;
-                       epctrlx |= EPCTRL_RX_DATA_TOGGLE_RST;
-               }
-       }
-       writel(epctrlx, &udc->op_regs->epctrlx[ep_num]);
-}
-
-static int ep_is_stall(struct mv_udc *udc, u8 ep_num, u8 direction)
-{
-       u32 epctrlx;
-
-       epctrlx = readl(&udc->op_regs->epctrlx[ep_num]);
-
-       if (direction == EP_DIR_OUT)
-               return (epctrlx & EPCTRL_RX_EP_STALL) ? 1 : 0;
-       else
-               return (epctrlx & EPCTRL_TX_EP_STALL) ? 1 : 0;
-}
-
-static int mv_ep_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge)
-{
-       struct mv_ep *ep;
-       unsigned long flags = 0;
-       int status = 0;
-       struct mv_udc *udc;
-
-       ep = container_of(_ep, struct mv_ep, ep);
-       udc = ep->udc;
-       if (!_ep || !ep->ep.desc) {
-               status = -EINVAL;
-               goto out;
-       }
-
-       if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
-               status = -EOPNOTSUPP;
-               goto out;
-       }
-
-       /*
-        * Attempt to halt IN ep will fail if any transfer requests
-        * are still queue
-        */
-       if (halt && (ep_dir(ep) == EP_DIR_IN) && !list_empty(&ep->queue)) {
-               status = -EAGAIN;
-               goto out;
-       }
-
-       spin_lock_irqsave(&ep->udc->lock, flags);
-       ep_set_stall(udc, ep->ep_num, ep_dir(ep), halt);
-       if (halt && wedge)
-               ep->wedge = 1;
-       else if (!halt)
-               ep->wedge = 0;
-       spin_unlock_irqrestore(&ep->udc->lock, flags);
-
-       if (ep->ep_num == 0) {
-               udc->ep0_state = WAIT_FOR_SETUP;
-               udc->ep0_dir = EP_DIR_OUT;
-       }
-out:
-       return status;
-}
-
-static int mv_ep_set_halt(struct usb_ep *_ep, int halt)
-{
-       return mv_ep_set_halt_wedge(_ep, halt, 0);
-}
-
-static int mv_ep_set_wedge(struct usb_ep *_ep)
-{
-       return mv_ep_set_halt_wedge(_ep, 1, 1);
-}
-
-static struct usb_ep_ops mv_ep_ops = {
-       .enable         = mv_ep_enable,
-       .disable        = mv_ep_disable,
-
-       .alloc_request  = mv_alloc_request,
-       .free_request   = mv_free_request,
-
-       .queue          = mv_ep_queue,
-       .dequeue        = mv_ep_dequeue,
-
-       .set_wedge      = mv_ep_set_wedge,
-       .set_halt       = mv_ep_set_halt,
-       .fifo_flush     = mv_ep_fifo_flush,     /* flush fifo */
-};
-
-static void udc_clock_enable(struct mv_udc *udc)
-{
-       clk_prepare_enable(udc->clk);
-}
-
-static void udc_clock_disable(struct mv_udc *udc)
-{
-       clk_disable_unprepare(udc->clk);
-}
-
-static void udc_stop(struct mv_udc *udc)
-{
-       u32 tmp;
-
-       /* Disable interrupts */
-       tmp = readl(&udc->op_regs->usbintr);
-       tmp &= ~(USBINTR_INT_EN | USBINTR_ERR_INT_EN |
-               USBINTR_PORT_CHANGE_DETECT_EN | USBINTR_RESET_EN);
-       writel(tmp, &udc->op_regs->usbintr);
-
-       udc->stopped = 1;
-
-       /* Reset the Run the bit in the command register to stop VUSB */
-       tmp = readl(&udc->op_regs->usbcmd);
-       tmp &= ~USBCMD_RUN_STOP;
-       writel(tmp, &udc->op_regs->usbcmd);
-}
-
-static void udc_start(struct mv_udc *udc)
-{
-       u32 usbintr;
-
-       usbintr = USBINTR_INT_EN | USBINTR_ERR_INT_EN
-               | USBINTR_PORT_CHANGE_DETECT_EN
-               | USBINTR_RESET_EN | USBINTR_DEVICE_SUSPEND;
-       /* Enable interrupts */
-       writel(usbintr, &udc->op_regs->usbintr);
-
-       udc->stopped = 0;
-
-       /* Set the Run bit in the command register */
-       writel(USBCMD_RUN_STOP, &udc->op_regs->usbcmd);
-}
-
-static int udc_reset(struct mv_udc *udc)
-{
-       unsigned int loops;
-       u32 tmp, portsc;
-
-       /* Stop the controller */
-       tmp = readl(&udc->op_regs->usbcmd);
-       tmp &= ~USBCMD_RUN_STOP;
-       writel(tmp, &udc->op_regs->usbcmd);
-
-       /* Reset the controller to get default values */
-       writel(USBCMD_CTRL_RESET, &udc->op_regs->usbcmd);
-
-       /* wait for reset to complete */
-       loops = LOOPS(RESET_TIMEOUT);
-       while (readl(&udc->op_regs->usbcmd) & USBCMD_CTRL_RESET) {
-               if (loops == 0) {
-                       dev_err(&udc->dev->dev,
-                               "Wait for RESET completed TIMEOUT\n");
-                       return -ETIMEDOUT;
-               }
-               loops--;
-               udelay(LOOPS_USEC);
-       }
-
-       /* set controller to device mode */
-       tmp = readl(&udc->op_regs->usbmode);
-       tmp |= USBMODE_CTRL_MODE_DEVICE;
-
-       /* turn setup lockout off, require setup tripwire in usbcmd */
-       tmp |= USBMODE_SETUP_LOCK_OFF;
-
-       writel(tmp, &udc->op_regs->usbmode);
-
-       writel(0x0, &udc->op_regs->epsetupstat);
-
-       /* Configure the Endpoint List Address */
-       writel(udc->ep_dqh_dma & USB_EP_LIST_ADDRESS_MASK,
-               &udc->op_regs->eplistaddr);
-
-       portsc = readl(&udc->op_regs->portsc[0]);
-       if (readl(&udc->cap_regs->hcsparams) & HCSPARAMS_PPC)
-               portsc &= (~PORTSCX_W1C_BITS | ~PORTSCX_PORT_POWER);
-
-       if (udc->force_fs)
-               portsc |= PORTSCX_FORCE_FULL_SPEED_CONNECT;
-       else
-               portsc &= (~PORTSCX_FORCE_FULL_SPEED_CONNECT);
-
-       writel(portsc, &udc->op_regs->portsc[0]);
-
-       tmp = readl(&udc->op_regs->epctrlx[0]);
-       tmp &= ~(EPCTRL_TX_EP_STALL | EPCTRL_RX_EP_STALL);
-       writel(tmp, &udc->op_regs->epctrlx[0]);
-
-       return 0;
-}
-
-static int mv_udc_enable_internal(struct mv_udc *udc)
-{
-       int retval;
-
-       if (udc->active)
-               return 0;
-
-       dev_dbg(&udc->dev->dev, "enable udc\n");
-       udc_clock_enable(udc);
-       if (udc->pdata->phy_init) {
-               retval = udc->pdata->phy_init(udc->phy_regs);
-               if (retval) {
-                       dev_err(&udc->dev->dev,
-                               "init phy error %d\n", retval);
-                       udc_clock_disable(udc);
-                       return retval;
-               }
-       }
-       udc->active = 1;
-
-       return 0;
-}
-
-static int mv_udc_enable(struct mv_udc *udc)
-{
-       if (udc->clock_gating)
-               return mv_udc_enable_internal(udc);
-
-       return 0;
-}
-
-static void mv_udc_disable_internal(struct mv_udc *udc)
-{
-       if (udc->active) {
-               dev_dbg(&udc->dev->dev, "disable udc\n");
-               if (udc->pdata->phy_deinit)
-                       udc->pdata->phy_deinit(udc->phy_regs);
-               udc_clock_disable(udc);
-               udc->active = 0;
-       }
-}
-
-static void mv_udc_disable(struct mv_udc *udc)
-{
-       if (udc->clock_gating)
-               mv_udc_disable_internal(udc);
-}
-
-static int mv_udc_get_frame(struct usb_gadget *gadget)
-{
-       struct mv_udc *udc;
-       u16     retval;
-
-       if (!gadget)
-               return -ENODEV;
-
-       udc = container_of(gadget, struct mv_udc, gadget);
-
-       retval = readl(&udc->op_regs->frindex) & USB_FRINDEX_MASKS;
-
-       return retval;
-}
-
-/* Tries to wake up the host connected to this gadget */
-static int mv_udc_wakeup(struct usb_gadget *gadget)
-{
-       struct mv_udc *udc = container_of(gadget, struct mv_udc, gadget);
-       u32 portsc;
-
-       /* Remote wakeup feature not enabled by host */
-       if (!udc->remote_wakeup)
-               return -ENOTSUPP;
-
-       portsc = readl(&udc->op_regs->portsc);
-       /* not suspended? */
-       if (!(portsc & PORTSCX_PORT_SUSPEND))
-               return 0;
-       /* trigger force resume */
-       portsc |= PORTSCX_PORT_FORCE_RESUME;
-       writel(portsc, &udc->op_regs->portsc[0]);
-       return 0;
-}
-
-static int mv_udc_vbus_session(struct usb_gadget *gadget, int is_active)
-{
-       struct mv_udc *udc;
-       unsigned long flags;
-       int retval = 0;
-
-       udc = container_of(gadget, struct mv_udc, gadget);
-       spin_lock_irqsave(&udc->lock, flags);
-
-       udc->vbus_active = (is_active != 0);
-
-       dev_dbg(&udc->dev->dev, "%s: softconnect %d, vbus_active %d\n",
-               __func__, udc->softconnect, udc->vbus_active);
-
-       if (udc->driver && udc->softconnect && udc->vbus_active) {
-               retval = mv_udc_enable(udc);
-               if (retval == 0) {
-                       /* Clock is disabled, need re-init registers */
-                       udc_reset(udc);
-                       ep0_reset(udc);
-                       udc_start(udc);
-               }
-       } else if (udc->driver && udc->softconnect) {
-               if (!udc->active)
-                       goto out;
-
-               /* stop all the transfer in queue*/
-               stop_activity(udc, udc->driver);
-               udc_stop(udc);
-               mv_udc_disable(udc);
-       }
-
-out:
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return retval;
-}
-
-static int mv_udc_pullup(struct usb_gadget *gadget, int is_on)
-{
-       struct mv_udc *udc;
-       unsigned long flags;
-       int retval = 0;
-
-       udc = container_of(gadget, struct mv_udc, gadget);
-       spin_lock_irqsave(&udc->lock, flags);
-
-       udc->softconnect = (is_on != 0);
-
-       dev_dbg(&udc->dev->dev, "%s: softconnect %d, vbus_active %d\n",
-                       __func__, udc->softconnect, udc->vbus_active);
-
-       if (udc->driver && udc->softconnect && udc->vbus_active) {
-               retval = mv_udc_enable(udc);
-               if (retval == 0) {
-                       /* Clock is disabled, need re-init registers */
-                       udc_reset(udc);
-                       ep0_reset(udc);
-                       udc_start(udc);
-               }
-       } else if (udc->driver && udc->vbus_active) {
-               /* stop all the transfer in queue*/
-               stop_activity(udc, udc->driver);
-               udc_stop(udc);
-               mv_udc_disable(udc);
-       }
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return retval;
-}
-
-static int mv_udc_start(struct usb_gadget *, struct usb_gadget_driver *);
-static int mv_udc_stop(struct usb_gadget *, struct usb_gadget_driver *);
-/* device controller usb_gadget_ops structure */
-static const struct usb_gadget_ops mv_ops = {
-
-       /* returns the current frame number */
-       .get_frame      = mv_udc_get_frame,
-
-       /* tries to wake up the host connected to this gadget */
-       .wakeup         = mv_udc_wakeup,
-
-       /* notify controller that VBUS is powered or not */
-       .vbus_session   = mv_udc_vbus_session,
-
-       /* D+ pullup, software-controlled connect/disconnect to USB host */
-       .pullup         = mv_udc_pullup,
-       .udc_start      = mv_udc_start,
-       .udc_stop       = mv_udc_stop,
-};
-
-static int eps_init(struct mv_udc *udc)
-{
-       struct mv_ep    *ep;
-       char name[14];
-       int i;
-
-       /* initialize ep0 */
-       ep = &udc->eps[0];
-       ep->udc = udc;
-       strncpy(ep->name, "ep0", sizeof(ep->name));
-       ep->ep.name = ep->name;
-       ep->ep.ops = &mv_ep_ops;
-       ep->wedge = 0;
-       ep->stopped = 0;
-       usb_ep_set_maxpacket_limit(&ep->ep, EP0_MAX_PKT_SIZE);
-       ep->ep_num = 0;
-       ep->ep.desc = &mv_ep0_desc;
-       INIT_LIST_HEAD(&ep->queue);
-
-       ep->ep_type = USB_ENDPOINT_XFER_CONTROL;
-
-       /* initialize other endpoints */
-       for (i = 2; i < udc->max_eps * 2; i++) {
-               ep = &udc->eps[i];
-               if (i % 2) {
-                       snprintf(name, sizeof(name), "ep%din", i / 2);
-                       ep->direction = EP_DIR_IN;
-               } else {
-                       snprintf(name, sizeof(name), "ep%dout", i / 2);
-                       ep->direction = EP_DIR_OUT;
-               }
-               ep->udc = udc;
-               strncpy(ep->name, name, sizeof(ep->name));
-               ep->ep.name = ep->name;
-
-               ep->ep.ops = &mv_ep_ops;
-               ep->stopped = 0;
-               usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
-               ep->ep_num = i / 2;
-
-               INIT_LIST_HEAD(&ep->queue);
-               list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
-
-               ep->dqh = &udc->ep_dqh[i];
-       }
-
-       return 0;
-}
-
-/* delete all endpoint requests, called with spinlock held */
-static void nuke(struct mv_ep *ep, int status)
-{
-       /* called with spinlock held */
-       ep->stopped = 1;
-
-       /* endpoint fifo flush */
-       mv_ep_fifo_flush(&ep->ep);
-
-       while (!list_empty(&ep->queue)) {
-               struct mv_req *req = NULL;
-               req = list_entry(ep->queue.next, struct mv_req, queue);
-               done(ep, req, status);
-       }
-}
-
-/* stop all USB activities */
-static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver)
-{
-       struct mv_ep    *ep;
-
-       nuke(&udc->eps[0], -ESHUTDOWN);
-
-       list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
-               nuke(ep, -ESHUTDOWN);
-       }
-
-       /* report disconnect; the driver is already quiesced */
-       if (driver) {
-               spin_unlock(&udc->lock);
-               driver->disconnect(&udc->gadget);
-               spin_lock(&udc->lock);
-       }
-}
-
-static int mv_udc_start(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct mv_udc *udc;
-       int retval = 0;
-       unsigned long flags;
-
-       udc = container_of(gadget, struct mv_udc, gadget);
-
-       if (udc->driver)
-               return -EBUSY;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       /* hook up the driver ... */
-       driver->driver.bus = NULL;
-       udc->driver = driver;
-
-       udc->usb_state = USB_STATE_ATTACHED;
-       udc->ep0_state = WAIT_FOR_SETUP;
-       udc->ep0_dir = EP_DIR_OUT;
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       if (udc->transceiver) {
-               retval = otg_set_peripheral(udc->transceiver->otg,
-                                       &udc->gadget);
-               if (retval) {
-                       dev_err(&udc->dev->dev,
-                               "unable to register peripheral to otg\n");
-                       udc->driver = NULL;
-                       return retval;
-               }
-       }
-
-       /* pullup is always on */
-       mv_udc_pullup(&udc->gadget, 1);
-
-       /* When boot with cable attached, there will be no vbus irq occurred */
-       if (udc->qwork)
-               queue_work(udc->qwork, &udc->vbus_work);
-
-       return 0;
-}
-
-static int mv_udc_stop(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct mv_udc *udc;
-       unsigned long flags;
-
-       udc = container_of(gadget, struct mv_udc, gadget);
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       mv_udc_enable(udc);
-       udc_stop(udc);
-
-       /* stop all usb activities */
-       udc->gadget.speed = USB_SPEED_UNKNOWN;
-       stop_activity(udc, driver);
-       mv_udc_disable(udc);
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       /* unbind gadget driver */
-       udc->driver = NULL;
-
-       return 0;
-}
-
-static void mv_set_ptc(struct mv_udc *udc, u32 mode)
-{
-       u32 portsc;
-
-       portsc = readl(&udc->op_regs->portsc[0]);
-       portsc |= mode << 16;
-       writel(portsc, &udc->op_regs->portsc[0]);
-}
-
-static void prime_status_complete(struct usb_ep *ep, struct usb_request *_req)
-{
-       struct mv_ep *mvep = container_of(ep, struct mv_ep, ep);
-       struct mv_req *req = container_of(_req, struct mv_req, req);
-       struct mv_udc *udc;
-       unsigned long flags;
-
-       udc = mvep->udc;
-
-       dev_info(&udc->dev->dev, "switch to test mode %d\n", req->test_mode);
-
-       spin_lock_irqsave(&udc->lock, flags);
-       if (req->test_mode) {
-               mv_set_ptc(udc, req->test_mode);
-               req->test_mode = 0;
-       }
-       spin_unlock_irqrestore(&udc->lock, flags);
-}
-
-static int
-udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
-{
-       int retval = 0;
-       struct mv_req *req;
-       struct mv_ep *ep;
-
-       ep = &udc->eps[0];
-       udc->ep0_dir = direction;
-       udc->ep0_state = WAIT_FOR_OUT_STATUS;
-
-       req = udc->status_req;
-
-       /* fill in the reqest structure */
-       if (empty == false) {
-               *((u16 *) req->req.buf) = cpu_to_le16(status);
-               req->req.length = 2;
-       } else
-               req->req.length = 0;
-
-       req->ep = ep;
-       req->req.status = -EINPROGRESS;
-       req->req.actual = 0;
-       if (udc->test_mode) {
-               req->req.complete = prime_status_complete;
-               req->test_mode = udc->test_mode;
-               udc->test_mode = 0;
-       } else
-               req->req.complete = NULL;
-       req->dtd_count = 0;
-
-       if (req->req.dma == DMA_ADDR_INVALID) {
-               req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
-                               req->req.buf, req->req.length,
-                               ep_dir(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-               req->mapped = 1;
-       }
-
-       /* prime the data phase */
-       if (!req_to_dtd(req)) {
-               retval = queue_dtd(ep, req);
-               if (retval) {
-                       dev_err(&udc->dev->dev,
-                               "Failed to queue dtd when prime status\n");
-                       goto out;
-               }
-       } else{ /* no mem */
-               retval = -ENOMEM;
-               dev_err(&udc->dev->dev,
-                       "Failed to dma_pool_alloc when prime status\n");
-               goto out;
-       }
-
-       list_add_tail(&req->queue, &ep->queue);
-
-       return 0;
-out:
-       usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
-
-       return retval;
-}
-
-static void mv_udc_testmode(struct mv_udc *udc, u16 index)
-{
-       if (index <= TEST_FORCE_EN) {
-               udc->test_mode = index;
-               if (udc_prime_status(udc, EP_DIR_IN, 0, true))
-                       ep0_stall(udc);
-       } else
-               dev_err(&udc->dev->dev,
-                       "This test mode(%d) is not supported\n", index);
-}
-
-static void ch9setaddress(struct mv_udc *udc, struct usb_ctrlrequest *setup)
-{
-       udc->dev_addr = (u8)setup->wValue;
-
-       /* update usb state */
-       udc->usb_state = USB_STATE_ADDRESS;
-
-       if (udc_prime_status(udc, EP_DIR_IN, 0, true))
-               ep0_stall(udc);
-}
-
-static void ch9getstatus(struct mv_udc *udc, u8 ep_num,
-       struct usb_ctrlrequest *setup)
-{
-       u16 status = 0;
-       int retval;
-
-       if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
-               != (USB_DIR_IN | USB_TYPE_STANDARD))
-               return;
-
-       if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
-               status = 1 << USB_DEVICE_SELF_POWERED;
-               status |= udc->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP;
-       } else if ((setup->bRequestType & USB_RECIP_MASK)
-                       == USB_RECIP_INTERFACE) {
-               /* get interface status */
-               status = 0;
-       } else if ((setup->bRequestType & USB_RECIP_MASK)
-                       == USB_RECIP_ENDPOINT) {
-               u8 ep_num, direction;
-
-               ep_num = setup->wIndex & USB_ENDPOINT_NUMBER_MASK;
-               direction = (setup->wIndex & USB_ENDPOINT_DIR_MASK)
-                               ? EP_DIR_IN : EP_DIR_OUT;
-               status = ep_is_stall(udc, ep_num, direction)
-                               << USB_ENDPOINT_HALT;
-       }
-
-       retval = udc_prime_status(udc, EP_DIR_IN, status, false);
-       if (retval)
-               ep0_stall(udc);
-       else
-               udc->ep0_state = DATA_STATE_XMIT;
-}
-
-static void ch9clearfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup)
-{
-       u8 ep_num;
-       u8 direction;
-       struct mv_ep *ep;
-
-       if ((setup->bRequestType & (USB_TYPE_MASK | USB_RECIP_MASK))
-               == ((USB_TYPE_STANDARD | USB_RECIP_DEVICE))) {
-               switch (setup->wValue) {
-               case USB_DEVICE_REMOTE_WAKEUP:
-                       udc->remote_wakeup = 0;
-                       break;
-               default:
-                       goto out;
-               }
-       } else if ((setup->bRequestType & (USB_TYPE_MASK | USB_RECIP_MASK))
-               == ((USB_TYPE_STANDARD | USB_RECIP_ENDPOINT))) {
-               switch (setup->wValue) {
-               case USB_ENDPOINT_HALT:
-                       ep_num = setup->wIndex & USB_ENDPOINT_NUMBER_MASK;
-                       direction = (setup->wIndex & USB_ENDPOINT_DIR_MASK)
-                               ? EP_DIR_IN : EP_DIR_OUT;
-                       if (setup->wValue != 0 || setup->wLength != 0
-                               || ep_num > udc->max_eps)
-                               goto out;
-                       ep = &udc->eps[ep_num * 2 + direction];
-                       if (ep->wedge == 1)
-                               break;
-                       spin_unlock(&udc->lock);
-                       ep_set_stall(udc, ep_num, direction, 0);
-                       spin_lock(&udc->lock);
-                       break;
-               default:
-                       goto out;
-               }
-       } else
-               goto out;
-
-       if (udc_prime_status(udc, EP_DIR_IN, 0, true))
-               ep0_stall(udc);
-out:
-       return;
-}
-
-static void ch9setfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup)
-{
-       u8 ep_num;
-       u8 direction;
-
-       if ((setup->bRequestType & (USB_TYPE_MASK | USB_RECIP_MASK))
-               == ((USB_TYPE_STANDARD | USB_RECIP_DEVICE))) {
-               switch (setup->wValue) {
-               case USB_DEVICE_REMOTE_WAKEUP:
-                       udc->remote_wakeup = 1;
-                       break;
-               case USB_DEVICE_TEST_MODE:
-                       if (setup->wIndex & 0xFF
-                               ||  udc->gadget.speed != USB_SPEED_HIGH)
-                               ep0_stall(udc);
-
-                       if (udc->usb_state != USB_STATE_CONFIGURED
-                               && udc->usb_state != USB_STATE_ADDRESS
-                               && udc->usb_state != USB_STATE_DEFAULT)
-                               ep0_stall(udc);
-
-                       mv_udc_testmode(udc, (setup->wIndex >> 8));
-                       goto out;
-               default:
-                       goto out;
-               }
-       } else if ((setup->bRequestType & (USB_TYPE_MASK | USB_RECIP_MASK))
-               == ((USB_TYPE_STANDARD | USB_RECIP_ENDPOINT))) {
-               switch (setup->wValue) {
-               case USB_ENDPOINT_HALT:
-                       ep_num = setup->wIndex & USB_ENDPOINT_NUMBER_MASK;
-                       direction = (setup->wIndex & USB_ENDPOINT_DIR_MASK)
-                               ? EP_DIR_IN : EP_DIR_OUT;
-                       if (setup->wValue != 0 || setup->wLength != 0
-                               || ep_num > udc->max_eps)
-                               goto out;
-                       spin_unlock(&udc->lock);
-                       ep_set_stall(udc, ep_num, direction, 1);
-                       spin_lock(&udc->lock);
-                       break;
-               default:
-                       goto out;
-               }
-       } else
-               goto out;
-
-       if (udc_prime_status(udc, EP_DIR_IN, 0, true))
-               ep0_stall(udc);
-out:
-       return;
-}
-
-static void handle_setup_packet(struct mv_udc *udc, u8 ep_num,
-       struct usb_ctrlrequest *setup)
-       __releases(&ep->udc->lock)
-       __acquires(&ep->udc->lock)
-{
-       bool delegate = false;
-
-       nuke(&udc->eps[ep_num * 2 + EP_DIR_OUT], -ESHUTDOWN);
-
-       dev_dbg(&udc->dev->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
-                       setup->bRequestType, setup->bRequest,
-                       setup->wValue, setup->wIndex, setup->wLength);
-       /* We process some stardard setup requests here */
-       if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
-               switch (setup->bRequest) {
-               case USB_REQ_GET_STATUS:
-                       ch9getstatus(udc, ep_num, setup);
-                       break;
-
-               case USB_REQ_SET_ADDRESS:
-                       ch9setaddress(udc, setup);
-                       break;
-
-               case USB_REQ_CLEAR_FEATURE:
-                       ch9clearfeature(udc, setup);
-                       break;
-
-               case USB_REQ_SET_FEATURE:
-                       ch9setfeature(udc, setup);
-                       break;
-
-               default:
-                       delegate = true;
-               }
-       } else
-               delegate = true;
-
-       /* delegate USB standard requests to the gadget driver */
-       if (delegate == true) {
-               /* USB requests handled by gadget */
-               if (setup->wLength) {
-                       /* DATA phase from gadget, STATUS phase from udc */
-                       udc->ep0_dir = (setup->bRequestType & USB_DIR_IN)
-                                       ?  EP_DIR_IN : EP_DIR_OUT;
-                       spin_unlock(&udc->lock);
-                       if (udc->driver->setup(&udc->gadget,
-                               &udc->local_setup_buff) < 0)
-                               ep0_stall(udc);
-                       spin_lock(&udc->lock);
-                       udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
-                                       ?  DATA_STATE_XMIT : DATA_STATE_RECV;
-               } else {
-                       /* no DATA phase, IN STATUS phase from gadget */
-                       udc->ep0_dir = EP_DIR_IN;
-                       spin_unlock(&udc->lock);
-                       if (udc->driver->setup(&udc->gadget,
-                               &udc->local_setup_buff) < 0)
-                               ep0_stall(udc);
-                       spin_lock(&udc->lock);
-                       udc->ep0_state = WAIT_FOR_OUT_STATUS;
-               }
-       }
-}
-
-/* complete DATA or STATUS phase of ep0 prime status phase if needed */
-static void ep0_req_complete(struct mv_udc *udc,
-       struct mv_ep *ep0, struct mv_req *req)
-{
-       u32 new_addr;
-
-       if (udc->usb_state == USB_STATE_ADDRESS) {
-               /* set the new address */
-               new_addr = (u32)udc->dev_addr;
-               writel(new_addr << USB_DEVICE_ADDRESS_BIT_SHIFT,
-                       &udc->op_regs->deviceaddr);
-       }
-
-       done(ep0, req, 0);
-
-       switch (udc->ep0_state) {
-       case DATA_STATE_XMIT:
-               /* receive status phase */
-               if (udc_prime_status(udc, EP_DIR_OUT, 0, true))
-                       ep0_stall(udc);
-               break;
-       case DATA_STATE_RECV:
-               /* send status phase */
-               if (udc_prime_status(udc, EP_DIR_IN, 0 , true))
-                       ep0_stall(udc);
-               break;
-       case WAIT_FOR_OUT_STATUS:
-               udc->ep0_state = WAIT_FOR_SETUP;
-               break;
-       case WAIT_FOR_SETUP:
-               dev_err(&udc->dev->dev, "unexpect ep0 packets\n");
-               break;
-       default:
-               ep0_stall(udc);
-               break;
-       }
-}
-
-static void get_setup_data(struct mv_udc *udc, u8 ep_num, u8 *buffer_ptr)
-{
-       u32 temp;
-       struct mv_dqh *dqh;
-
-       dqh = &udc->ep_dqh[ep_num * 2 + EP_DIR_OUT];
-
-       /* Clear bit in ENDPTSETUPSTAT */
-       writel((1 << ep_num), &udc->op_regs->epsetupstat);
-
-       /* while a hazard exists when setup package arrives */
-       do {
-               /* Set Setup Tripwire */
-               temp = readl(&udc->op_regs->usbcmd);
-               writel(temp | USBCMD_SETUP_TRIPWIRE_SET, &udc->op_regs->usbcmd);
-
-               /* Copy the setup packet to local buffer */
-               memcpy(buffer_ptr, (u8 *) dqh->setup_buffer, 8);
-       } while (!(readl(&udc->op_regs->usbcmd) & USBCMD_SETUP_TRIPWIRE_SET));
-
-       /* Clear Setup Tripwire */
-       temp = readl(&udc->op_regs->usbcmd);
-       writel(temp & ~USBCMD_SETUP_TRIPWIRE_SET, &udc->op_regs->usbcmd);
-}
-
-static void irq_process_tr_complete(struct mv_udc *udc)
-{
-       u32 tmp, bit_pos;
-       int i, ep_num = 0, direction = 0;
-       struct mv_ep    *curr_ep;
-       struct mv_req *curr_req, *temp_req;
-       int status;
-
-       /*
-        * We use separate loops for ENDPTSETUPSTAT and ENDPTCOMPLETE
-        * because the setup packets are to be read ASAP
-        */
-
-       /* Process all Setup packet received interrupts */
-       tmp = readl(&udc->op_regs->epsetupstat);
-
-       if (tmp) {
-               for (i = 0; i < udc->max_eps; i++) {
-                       if (tmp & (1 << i)) {
-                               get_setup_data(udc, i,
-                                       (u8 *)(&udc->local_setup_buff));
-                               handle_setup_packet(udc, i,
-                                       &udc->local_setup_buff);
-                       }
-               }
-       }
-
-       /* Don't clear the endpoint setup status register here.
-        * It is cleared as a setup packet is read out of the buffer
-        */
-
-       /* Process non-setup transaction complete interrupts */
-       tmp = readl(&udc->op_regs->epcomplete);
-
-       if (!tmp)
-               return;
-
-       writel(tmp, &udc->op_regs->epcomplete);
-
-       for (i = 0; i < udc->max_eps * 2; i++) {
-               ep_num = i >> 1;
-               direction = i % 2;
-
-               bit_pos = 1 << (ep_num + 16 * direction);
-
-               if (!(bit_pos & tmp))
-                       continue;
-
-               if (i == 1)
-                       curr_ep = &udc->eps[0];
-               else
-                       curr_ep = &udc->eps[i];
-               /* process the req queue until an uncomplete request */
-               list_for_each_entry_safe(curr_req, temp_req,
-                       &curr_ep->queue, queue) {
-                       status = process_ep_req(udc, i, curr_req);
-                       if (status)
-                               break;
-
-                       /* write back status to req */
-                       curr_req->req.status = status;
-
-                       /* ep0 request completion */
-                       if (ep_num == 0) {
-                               ep0_req_complete(udc, curr_ep, curr_req);
-                               break;
-                       } else {
-                               done(curr_ep, curr_req, status);
-                       }
-               }
-       }
-}
-
-static void irq_process_reset(struct mv_udc *udc)
-{
-       u32 tmp;
-       unsigned int loops;
-
-       udc->ep0_dir = EP_DIR_OUT;
-       udc->ep0_state = WAIT_FOR_SETUP;
-       udc->remote_wakeup = 0;         /* default to 0 on reset */
-
-       /* The address bits are past bit 25-31. Set the address */
-       tmp = readl(&udc->op_regs->deviceaddr);
-       tmp &= ~(USB_DEVICE_ADDRESS_MASK);
-       writel(tmp, &udc->op_regs->deviceaddr);
-
-       /* Clear all the setup token semaphores */
-       tmp = readl(&udc->op_regs->epsetupstat);
-       writel(tmp, &udc->op_regs->epsetupstat);
-
-       /* Clear all the endpoint complete status bits */
-       tmp = readl(&udc->op_regs->epcomplete);
-       writel(tmp, &udc->op_regs->epcomplete);
-
-       /* wait until all endptprime bits cleared */
-       loops = LOOPS(PRIME_TIMEOUT);
-       while (readl(&udc->op_regs->epprime) & 0xFFFFFFFF) {
-               if (loops == 0) {
-                       dev_err(&udc->dev->dev,
-                               "Timeout for ENDPTPRIME = 0x%x\n",
-                               readl(&udc->op_regs->epprime));
-                       break;
-               }
-               loops--;
-               udelay(LOOPS_USEC);
-       }
-
-       /* Write 1s to the Flush register */
-       writel((u32)~0, &udc->op_regs->epflush);
-
-       if (readl(&udc->op_regs->portsc[0]) & PORTSCX_PORT_RESET) {
-               dev_info(&udc->dev->dev, "usb bus reset\n");
-               udc->usb_state = USB_STATE_DEFAULT;
-               /* reset all the queues, stop all USB activities */
-               stop_activity(udc, udc->driver);
-       } else {
-               dev_info(&udc->dev->dev, "USB reset portsc 0x%x\n",
-                       readl(&udc->op_regs->portsc));
-
-               /*
-                * re-initialize
-                * controller reset
-                */
-               udc_reset(udc);
-
-               /* reset all the queues, stop all USB activities */
-               stop_activity(udc, udc->driver);
-
-               /* reset ep0 dQH and endptctrl */
-               ep0_reset(udc);
-
-               /* enable interrupt and set controller to run state */
-               udc_start(udc);
-
-               udc->usb_state = USB_STATE_ATTACHED;
-       }
-}
-
-static void handle_bus_resume(struct mv_udc *udc)
-{
-       udc->usb_state = udc->resume_state;
-       udc->resume_state = 0;
-
-       /* report resume to the driver */
-       if (udc->driver) {
-               if (udc->driver->resume) {
-                       spin_unlock(&udc->lock);
-                       udc->driver->resume(&udc->gadget);
-                       spin_lock(&udc->lock);
-               }
-       }
-}
-
-static void irq_process_suspend(struct mv_udc *udc)
-{
-       udc->resume_state = udc->usb_state;
-       udc->usb_state = USB_STATE_SUSPENDED;
-
-       if (udc->driver->suspend) {
-               spin_unlock(&udc->lock);
-               udc->driver->suspend(&udc->gadget);
-               spin_lock(&udc->lock);
-       }
-}
-
-static void irq_process_port_change(struct mv_udc *udc)
-{
-       u32 portsc;
-
-       portsc = readl(&udc->op_regs->portsc[0]);
-       if (!(portsc & PORTSCX_PORT_RESET)) {
-               /* Get the speed */
-               u32 speed = portsc & PORTSCX_PORT_SPEED_MASK;
-               switch (speed) {
-               case PORTSCX_PORT_SPEED_HIGH:
-                       udc->gadget.speed = USB_SPEED_HIGH;
-                       break;
-               case PORTSCX_PORT_SPEED_FULL:
-                       udc->gadget.speed = USB_SPEED_FULL;
-                       break;
-               case PORTSCX_PORT_SPEED_LOW:
-                       udc->gadget.speed = USB_SPEED_LOW;
-                       break;
-               default:
-                       udc->gadget.speed = USB_SPEED_UNKNOWN;
-                       break;
-               }
-       }
-
-       if (portsc & PORTSCX_PORT_SUSPEND) {
-               udc->resume_state = udc->usb_state;
-               udc->usb_state = USB_STATE_SUSPENDED;
-               if (udc->driver->suspend) {
-                       spin_unlock(&udc->lock);
-                       udc->driver->suspend(&udc->gadget);
-                       spin_lock(&udc->lock);
-               }
-       }
-
-       if (!(portsc & PORTSCX_PORT_SUSPEND)
-               && udc->usb_state == USB_STATE_SUSPENDED) {
-               handle_bus_resume(udc);
-       }
-
-       if (!udc->resume_state)
-               udc->usb_state = USB_STATE_DEFAULT;
-}
-
-static void irq_process_error(struct mv_udc *udc)
-{
-       /* Increment the error count */
-       udc->errors++;
-}
-
-static irqreturn_t mv_udc_irq(int irq, void *dev)
-{
-       struct mv_udc *udc = (struct mv_udc *)dev;
-       u32 status, intr;
-
-       /* Disable ISR when stopped bit is set */
-       if (udc->stopped)
-               return IRQ_NONE;
-
-       spin_lock(&udc->lock);
-
-       status = readl(&udc->op_regs->usbsts);
-       intr = readl(&udc->op_regs->usbintr);
-       status &= intr;
-
-       if (status == 0) {
-               spin_unlock(&udc->lock);
-               return IRQ_NONE;
-       }
-
-       /* Clear all the interrupts occurred */
-       writel(status, &udc->op_regs->usbsts);
-
-       if (status & USBSTS_ERR)
-               irq_process_error(udc);
-
-       if (status & USBSTS_RESET)
-               irq_process_reset(udc);
-
-       if (status & USBSTS_PORT_CHANGE)
-               irq_process_port_change(udc);
-
-       if (status & USBSTS_INT)
-               irq_process_tr_complete(udc);
-
-       if (status & USBSTS_SUSPEND)
-               irq_process_suspend(udc);
-
-       spin_unlock(&udc->lock);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t mv_udc_vbus_irq(int irq, void *dev)
-{
-       struct mv_udc *udc = (struct mv_udc *)dev;
-
-       /* polling VBUS and init phy may cause too much time*/
-       if (udc->qwork)
-               queue_work(udc->qwork, &udc->vbus_work);
-
-       return IRQ_HANDLED;
-}
-
-static void mv_udc_vbus_work(struct work_struct *work)
-{
-       struct mv_udc *udc;
-       unsigned int vbus;
-
-       udc = container_of(work, struct mv_udc, vbus_work);
-       if (!udc->pdata->vbus)
-               return;
-
-       vbus = udc->pdata->vbus->poll();
-       dev_info(&udc->dev->dev, "vbus is %d\n", vbus);
-
-       if (vbus == VBUS_HIGH)
-               mv_udc_vbus_session(&udc->gadget, 1);
-       else if (vbus == VBUS_LOW)
-               mv_udc_vbus_session(&udc->gadget, 0);
-}
-
-/* release device structure */
-static void gadget_release(struct device *_dev)
-{
-       struct mv_udc *udc;
-
-       udc = dev_get_drvdata(_dev);
-
-       complete(udc->done);
-}
-
-static int mv_udc_remove(struct platform_device *pdev)
-{
-       struct mv_udc *udc;
-
-       udc = platform_get_drvdata(pdev);
-
-       usb_del_gadget_udc(&udc->gadget);
-
-       if (udc->qwork) {
-               flush_workqueue(udc->qwork);
-               destroy_workqueue(udc->qwork);
-       }
-
-       /* free memory allocated in probe */
-       if (udc->dtd_pool)
-               dma_pool_destroy(udc->dtd_pool);
-
-       if (udc->ep_dqh)
-               dma_free_coherent(&pdev->dev, udc->ep_dqh_size,
-                       udc->ep_dqh, udc->ep_dqh_dma);
-
-       mv_udc_disable(udc);
-
-       /* free dev, wait for the release() finished */
-       wait_for_completion(udc->done);
-
-       return 0;
-}
-
-static int mv_udc_probe(struct platform_device *pdev)
-{
-       struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
-       struct mv_udc *udc;
-       int retval = 0;
-       struct resource *r;
-       size_t size;
-
-       if (pdata == NULL) {
-               dev_err(&pdev->dev, "missing platform_data\n");
-               return -ENODEV;
-       }
-
-       udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL);
-       if (udc == NULL) {
-               dev_err(&pdev->dev, "failed to allocate memory for udc\n");
-               return -ENOMEM;
-       }
-
-       udc->done = &release_done;
-       udc->pdata = dev_get_platdata(&pdev->dev);
-       spin_lock_init(&udc->lock);
-
-       udc->dev = pdev;
-
-       if (pdata->mode == MV_USB_MODE_OTG) {
-               udc->transceiver = devm_usb_get_phy(&pdev->dev,
-                                       USB_PHY_TYPE_USB2);
-               if (IS_ERR(udc->transceiver)) {
-                       retval = PTR_ERR(udc->transceiver);
-
-                       if (retval == -ENXIO)
-                               return retval;
-
-                       udc->transceiver = NULL;
-                       return -EPROBE_DEFER;
-               }
-       }
-
-       /* udc only have one sysclk. */
-       udc->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(udc->clk))
-               return PTR_ERR(udc->clk);
-
-       r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
-       if (r == NULL) {
-               dev_err(&pdev->dev, "no I/O memory resource defined\n");
-               return -ENODEV;
-       }
-
-       udc->cap_regs = (struct mv_cap_regs __iomem *)
-               devm_ioremap(&pdev->dev, r->start, resource_size(r));
-       if (udc->cap_regs == NULL) {
-               dev_err(&pdev->dev, "failed to map I/O memory\n");
-               return -EBUSY;
-       }
-
-       r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "phyregs");
-       if (r == NULL) {
-               dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
-               return -ENODEV;
-       }
-
-       udc->phy_regs = ioremap(r->start, resource_size(r));
-       if (udc->phy_regs == NULL) {
-               dev_err(&pdev->dev, "failed to map phy I/O memory\n");
-               return -EBUSY;
-       }
-
-       /* we will acces controller register, so enable the clk */
-       retval = mv_udc_enable_internal(udc);
-       if (retval)
-               return retval;
-
-       udc->op_regs =
-               (struct mv_op_regs __iomem *)((unsigned long)udc->cap_regs
-               + (readl(&udc->cap_regs->caplength_hciversion)
-                       & CAPLENGTH_MASK));
-       udc->max_eps = readl(&udc->cap_regs->dccparams) & DCCPARAMS_DEN_MASK;
-
-       /*
-        * some platform will use usb to download image, it may not disconnect
-        * usb gadget before loading kernel. So first stop udc here.
-        */
-       udc_stop(udc);
-       writel(0xFFFFFFFF, &udc->op_regs->usbsts);
-
-       size = udc->max_eps * sizeof(struct mv_dqh) *2;
-       size = (size + DQH_ALIGNMENT - 1) & ~(DQH_ALIGNMENT - 1);
-       udc->ep_dqh = dma_alloc_coherent(&pdev->dev, size,
-                                       &udc->ep_dqh_dma, GFP_KERNEL);
-
-       if (udc->ep_dqh == NULL) {
-               dev_err(&pdev->dev, "allocate dQH memory failed\n");
-               retval = -ENOMEM;
-               goto err_disable_clock;
-       }
-       udc->ep_dqh_size = size;
-
-       /* create dTD dma_pool resource */
-       udc->dtd_pool = dma_pool_create("mv_dtd",
-                       &pdev->dev,
-                       sizeof(struct mv_dtd),
-                       DTD_ALIGNMENT,
-                       DMA_BOUNDARY);
-
-       if (!udc->dtd_pool) {
-               retval = -ENOMEM;
-               goto err_free_dma;
-       }
-
-       size = udc->max_eps * sizeof(struct mv_ep) *2;
-       udc->eps = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
-       if (udc->eps == NULL) {
-               dev_err(&pdev->dev, "allocate ep memory failed\n");
-               retval = -ENOMEM;
-               goto err_destroy_dma;
-       }
-
-       /* initialize ep0 status request structure */
-       udc->status_req = devm_kzalloc(&pdev->dev, sizeof(struct mv_req),
-                                       GFP_KERNEL);
-       if (!udc->status_req) {
-               dev_err(&pdev->dev, "allocate status_req memory failed\n");
-               retval = -ENOMEM;
-               goto err_destroy_dma;
-       }
-       INIT_LIST_HEAD(&udc->status_req->queue);
-
-       /* allocate a small amount of memory to get valid address */
-       udc->status_req->req.buf = kzalloc(8, GFP_KERNEL);
-       udc->status_req->req.dma = DMA_ADDR_INVALID;
-
-       udc->resume_state = USB_STATE_NOTATTACHED;
-       udc->usb_state = USB_STATE_POWERED;
-       udc->ep0_dir = EP_DIR_OUT;
-       udc->remote_wakeup = 0;
-
-       r = platform_get_resource(udc->dev, IORESOURCE_IRQ, 0);
-       if (r == NULL) {
-               dev_err(&pdev->dev, "no IRQ resource defined\n");
-               retval = -ENODEV;
-               goto err_destroy_dma;
-       }
-       udc->irq = r->start;
-       if (devm_request_irq(&pdev->dev, udc->irq, mv_udc_irq,
-               IRQF_SHARED, driver_name, udc)) {
-               dev_err(&pdev->dev, "Request irq %d for UDC failed\n",
-                       udc->irq);
-               retval = -ENODEV;
-               goto err_destroy_dma;
-       }
-
-       /* initialize gadget structure */
-       udc->gadget.ops = &mv_ops;      /* usb_gadget_ops */
-       udc->gadget.ep0 = &udc->eps[0].ep;      /* gadget ep0 */
-       INIT_LIST_HEAD(&udc->gadget.ep_list);   /* ep_list */
-       udc->gadget.speed = USB_SPEED_UNKNOWN;  /* speed */
-       udc->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */
-
-       /* the "gadget" abstracts/virtualizes the controller */
-       udc->gadget.name = driver_name;         /* gadget name */
-
-       eps_init(udc);
-
-       /* VBUS detect: we can disable/enable clock on demand.*/
-       if (udc->transceiver)
-               udc->clock_gating = 1;
-       else if (pdata->vbus) {
-               udc->clock_gating = 1;
-               retval = devm_request_threaded_irq(&pdev->dev,
-                               pdata->vbus->irq, NULL,
-                               mv_udc_vbus_irq, IRQF_ONESHOT, "vbus", udc);
-               if (retval) {
-                       dev_info(&pdev->dev,
-                               "Can not request irq for VBUS, "
-                               "disable clock gating\n");
-                       udc->clock_gating = 0;
-               }
-
-               udc->qwork = create_singlethread_workqueue("mv_udc_queue");
-               if (!udc->qwork) {
-                       dev_err(&pdev->dev, "cannot create workqueue\n");
-                       retval = -ENOMEM;
-                       goto err_destroy_dma;
-               }
-
-               INIT_WORK(&udc->vbus_work, mv_udc_vbus_work);
-       }
-
-       /*
-        * When clock gating is supported, we can disable clk and phy.
-        * If not, it means that VBUS detection is not supported, we
-        * have to enable vbus active all the time to let controller work.
-        */
-       if (udc->clock_gating)
-               mv_udc_disable_internal(udc);
-       else
-               udc->vbus_active = 1;
-
-       retval = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
-                       gadget_release);
-       if (retval)
-               goto err_create_workqueue;
-
-       platform_set_drvdata(pdev, udc);
-       dev_info(&pdev->dev, "successful probe UDC device %s clock gating.\n",
-               udc->clock_gating ? "with" : "without");
-
-       return 0;
-
-err_create_workqueue:
-       destroy_workqueue(udc->qwork);
-err_destroy_dma:
-       dma_pool_destroy(udc->dtd_pool);
-err_free_dma:
-       dma_free_coherent(&pdev->dev, udc->ep_dqh_size,
-                       udc->ep_dqh, udc->ep_dqh_dma);
-err_disable_clock:
-       mv_udc_disable_internal(udc);
-
-       return retval;
-}
-
-#ifdef CONFIG_PM
-static int mv_udc_suspend(struct device *dev)
-{
-       struct mv_udc *udc;
-
-       udc = dev_get_drvdata(dev);
-
-       /* if OTG is enabled, the following will be done in OTG driver*/
-       if (udc->transceiver)
-               return 0;
-
-       if (udc->pdata->vbus && udc->pdata->vbus->poll)
-               if (udc->pdata->vbus->poll() == VBUS_HIGH) {
-                       dev_info(&udc->dev->dev, "USB cable is connected!\n");
-                       return -EAGAIN;
-               }
-
-       /*
-        * only cable is unplugged, udc can suspend.
-        * So do not care about clock_gating == 1.
-        */
-       if (!udc->clock_gating) {
-               udc_stop(udc);
-
-               spin_lock_irq(&udc->lock);
-               /* stop all usb activities */
-               stop_activity(udc, udc->driver);
-               spin_unlock_irq(&udc->lock);
-
-               mv_udc_disable_internal(udc);
-       }
-
-       return 0;
-}
-
-static int mv_udc_resume(struct device *dev)
-{
-       struct mv_udc *udc;
-       int retval;
-
-       udc = dev_get_drvdata(dev);
-
-       /* if OTG is enabled, the following will be done in OTG driver*/
-       if (udc->transceiver)
-               return 0;
-
-       if (!udc->clock_gating) {
-               retval = mv_udc_enable_internal(udc);
-               if (retval)
-                       return retval;
-
-               if (udc->driver && udc->softconnect) {
-                       udc_reset(udc);
-                       ep0_reset(udc);
-                       udc_start(udc);
-               }
-       }
-
-       return 0;
-}
-
-static const struct dev_pm_ops mv_udc_pm_ops = {
-       .suspend        = mv_udc_suspend,
-       .resume         = mv_udc_resume,
-};
-#endif
-
-static void mv_udc_shutdown(struct platform_device *pdev)
-{
-       struct mv_udc *udc;
-       u32 mode;
-
-       udc = platform_get_drvdata(pdev);
-       /* reset controller mode to IDLE */
-       mv_udc_enable(udc);
-       mode = readl(&udc->op_regs->usbmode);
-       mode &= ~3;
-       writel(mode, &udc->op_regs->usbmode);
-       mv_udc_disable(udc);
-}
-
-static struct platform_driver udc_driver = {
-       .probe          = mv_udc_probe,
-       .remove         = mv_udc_remove,
-       .shutdown       = mv_udc_shutdown,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "mv-udc",
-#ifdef CONFIG_PM
-               .pm     = &mv_udc_pm_ops,
-#endif
-       },
-};
-
-module_platform_driver(udc_driver);
-MODULE_ALIAS("platform:mv-udc");
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c
deleted file mode 100644 (file)
index 059cfe5..0000000
+++ /dev/null
@@ -1,2710 +0,0 @@
-/*
- * Driver for PLX NET2272 USB device controller
- *
- * Copyright (C) 2005-2006 PLX Technology, Inc.
- * Copyright (C) 2006-2011 Analog Devices, Inc.
- *
- * 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 <linux/delay.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/prefetch.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/timer.h>
-#include <linux/usb.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include <asm/byteorder.h>
-#include <asm/unaligned.h>
-
-#include "net2272.h"
-
-#define DRIVER_DESC "PLX NET2272 USB Peripheral Controller"
-
-static const char driver_name[] = "net2272";
-static const char driver_vers[] = "2006 October 17/mainline";
-static const char driver_desc[] = DRIVER_DESC;
-
-static const char ep0name[] = "ep0";
-static const char * const ep_name[] = {
-       ep0name,
-       "ep-a", "ep-b", "ep-c",
-};
-
-#ifdef CONFIG_USB_NET2272_DMA
-/*
- * use_dma: the NET2272 can use an external DMA controller.
- * Note that since there is no generic DMA api, some functions,
- * notably request_dma, start_dma, and cancel_dma will need to be
- * modified for your platform's particular dma controller.
- *
- * If use_dma is disabled, pio will be used instead.
- */
-static bool use_dma = 0;
-module_param(use_dma, bool, 0644);
-
-/*
- * dma_ep: selects the endpoint for use with dma (1=ep-a, 2=ep-b)
- * The NET2272 can only use dma for a single endpoint at a time.
- * At some point this could be modified to allow either endpoint
- * to take control of dma as it becomes available.
- *
- * Note that DMA should not be used on OUT endpoints unless it can
- * be guaranteed that no short packets will arrive on an IN endpoint
- * while the DMA operation is pending.  Otherwise the OUT DMA will
- * terminate prematurely (See NET2272 Errata 630-0213-0101)
- */
-static ushort dma_ep = 1;
-module_param(dma_ep, ushort, 0644);
-
-/*
- * dma_mode: net2272 dma mode setting (see LOCCTL1 definiton):
- *     mode 0 == Slow DREQ mode
- *     mode 1 == Fast DREQ mode
- *     mode 2 == Burst mode
- */
-static ushort dma_mode = 2;
-module_param(dma_mode, ushort, 0644);
-#else
-#define use_dma 0
-#define dma_ep 1
-#define dma_mode 2
-#endif
-
-/*
- * fifo_mode: net2272 buffer configuration:
- *      mode 0 == ep-{a,b,c} 512db each
- *      mode 1 == ep-a 1k, ep-{b,c} 512db
- *      mode 2 == ep-a 1k, ep-b 1k, ep-c 512db
- *      mode 3 == ep-a 1k, ep-b disabled, ep-c 512db
- */
-static ushort fifo_mode = 0;
-module_param(fifo_mode, ushort, 0644);
-
-/*
- * enable_suspend: When enabled, the driver will respond to
- * USB suspend requests by powering down the NET2272.  Otherwise,
- * USB suspend requests will be ignored.  This is acceptible for
- * self-powered devices.  For bus powered devices set this to 1.
- */
-static ushort enable_suspend = 0;
-module_param(enable_suspend, ushort, 0644);
-
-static void assert_out_naking(struct net2272_ep *ep, const char *where)
-{
-       u8 tmp;
-
-#ifndef DEBUG
-       return;
-#endif
-
-       tmp = net2272_ep_read(ep, EP_STAT0);
-       if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) {
-               dev_dbg(ep->dev->dev, "%s %s %02x !NAK\n",
-                       ep->ep.name, where, tmp);
-               net2272_ep_write(ep, EP_RSPSET, 1 << ALT_NAK_OUT_PACKETS);
-       }
-}
-#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep, __func__)
-
-static void stop_out_naking(struct net2272_ep *ep)
-{
-       u8 tmp = net2272_ep_read(ep, EP_STAT0);
-
-       if ((tmp & (1 << NAK_OUT_PACKETS)) != 0)
-               net2272_ep_write(ep, EP_RSPCLR, 1 << ALT_NAK_OUT_PACKETS);
-}
-
-#define PIPEDIR(bAddress) (usb_pipein(bAddress) ? "in" : "out")
-
-static char *type_string(u8 bmAttributes)
-{
-       switch ((bmAttributes) & USB_ENDPOINT_XFERTYPE_MASK) {
-       case USB_ENDPOINT_XFER_BULK: return "bulk";
-       case USB_ENDPOINT_XFER_ISOC: return "iso";
-       case USB_ENDPOINT_XFER_INT:  return "intr";
-       default:                     return "control";
-       }
-}
-
-static char *buf_state_string(unsigned state)
-{
-       switch (state) {
-       case BUFF_FREE:  return "free";
-       case BUFF_VALID: return "valid";
-       case BUFF_LCL:   return "local";
-       case BUFF_USB:   return "usb";
-       default:         return "unknown";
-       }
-}
-
-static char *dma_mode_string(void)
-{
-       if (!use_dma)
-               return "PIO";
-       switch (dma_mode) {
-       case 0:  return "SLOW DREQ";
-       case 1:  return "FAST DREQ";
-       case 2:  return "BURST";
-       default: return "invalid";
-       }
-}
-
-static void net2272_dequeue_all(struct net2272_ep *);
-static int net2272_kick_dma(struct net2272_ep *, struct net2272_request *);
-static int net2272_fifo_status(struct usb_ep *);
-
-static struct usb_ep_ops net2272_ep_ops;
-
-/*---------------------------------------------------------------------------*/
-
-static int
-net2272_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
-{
-       struct net2272 *dev;
-       struct net2272_ep *ep;
-       u32 max;
-       u8 tmp;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct net2272_ep, ep);
-       if (!_ep || !desc || ep->desc || _ep->name == ep0name
-                       || desc->bDescriptorType != USB_DT_ENDPOINT)
-               return -EINVAL;
-       dev = ep->dev;
-       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       max = usb_endpoint_maxp(desc) & 0x1fff;
-
-       spin_lock_irqsave(&dev->lock, flags);
-       _ep->maxpacket = max & 0x7fff;
-       ep->desc = desc;
-
-       /* net2272_ep_reset() has already been called */
-       ep->stopped = 0;
-       ep->wedged = 0;
-
-       /* set speed-dependent max packet */
-       net2272_ep_write(ep, EP_MAXPKT0, max & 0xff);
-       net2272_ep_write(ep, EP_MAXPKT1, (max & 0xff00) >> 8);
-
-       /* set type, direction, address; reset fifo counters */
-       net2272_ep_write(ep, EP_STAT1, 1 << BUFFER_FLUSH);
-       tmp = usb_endpoint_type(desc);
-       if (usb_endpoint_xfer_bulk(desc)) {
-               /* catch some particularly blatant driver bugs */
-               if ((dev->gadget.speed == USB_SPEED_HIGH && max != 512) ||
-                   (dev->gadget.speed == USB_SPEED_FULL && max > 64)) {
-                       spin_unlock_irqrestore(&dev->lock, flags);
-                       return -ERANGE;
-               }
-       }
-       ep->is_iso = usb_endpoint_xfer_isoc(desc) ? 1 : 0;
-       tmp <<= ENDPOINT_TYPE;
-       tmp |= ((desc->bEndpointAddress & 0x0f) << ENDPOINT_NUMBER);
-       tmp |= usb_endpoint_dir_in(desc) << ENDPOINT_DIRECTION;
-       tmp |= (1 << ENDPOINT_ENABLE);
-
-       /* for OUT transfers, block the rx fifo until a read is posted */
-       ep->is_in = usb_endpoint_dir_in(desc);
-       if (!ep->is_in)
-               net2272_ep_write(ep, EP_RSPSET, 1 << ALT_NAK_OUT_PACKETS);
-
-       net2272_ep_write(ep, EP_CFG, tmp);
-
-       /* enable irqs */
-       tmp = (1 << ep->num) | net2272_read(dev, IRQENB0);
-       net2272_write(dev, IRQENB0, tmp);
-
-       tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
-               | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
-               | net2272_ep_read(ep, EP_IRQENB);
-       net2272_ep_write(ep, EP_IRQENB, tmp);
-
-       tmp = desc->bEndpointAddress;
-       dev_dbg(dev->dev, "enabled %s (ep%d%s-%s) max %04x cfg %02x\n",
-               _ep->name, tmp & 0x0f, PIPEDIR(tmp),
-               type_string(desc->bmAttributes), max,
-               net2272_ep_read(ep, EP_CFG));
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-       return 0;
-}
-
-static void net2272_ep_reset(struct net2272_ep *ep)
-{
-       u8 tmp;
-
-       ep->desc = NULL;
-       INIT_LIST_HEAD(&ep->queue);
-
-       usb_ep_set_maxpacket_limit(&ep->ep, ~0);
-       ep->ep.ops = &net2272_ep_ops;
-
-       /* disable irqs, endpoint */
-       net2272_ep_write(ep, EP_IRQENB, 0);
-
-       /* init to our chosen defaults, notably so that we NAK OUT
-        * packets until the driver queues a read.
-        */
-       tmp = (1 << NAK_OUT_PACKETS_MODE) | (1 << ALT_NAK_OUT_PACKETS);
-       net2272_ep_write(ep, EP_RSPSET, tmp);
-
-       tmp = (1 << INTERRUPT_MODE) | (1 << HIDE_STATUS_PHASE);
-       if (ep->num != 0)
-               tmp |= (1 << ENDPOINT_TOGGLE) | (1 << ENDPOINT_HALT);
-
-       net2272_ep_write(ep, EP_RSPCLR, tmp);
-
-       /* scrub most status bits, and flush any fifo state */
-       net2272_ep_write(ep, EP_STAT0,
-                         (1 << DATA_IN_TOKEN_INTERRUPT)
-                       | (1 << DATA_OUT_TOKEN_INTERRUPT)
-                       | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
-                       | (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-                       | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT));
-
-       net2272_ep_write(ep, EP_STAT1,
-                           (1 << TIMEOUT)
-                         | (1 << USB_OUT_ACK_SENT)
-                         | (1 << USB_OUT_NAK_SENT)
-                         | (1 << USB_IN_ACK_RCVD)
-                         | (1 << USB_IN_NAK_SENT)
-                         | (1 << USB_STALL_SENT)
-                         | (1 << LOCAL_OUT_ZLP)
-                         | (1 << BUFFER_FLUSH));
-
-       /* fifo size is handled seperately */
-}
-
-static int net2272_disable(struct usb_ep *_ep)
-{
-       struct net2272_ep *ep;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct net2272_ep, ep);
-       if (!_ep || !ep->desc || _ep->name == ep0name)
-               return -EINVAL;
-
-       spin_lock_irqsave(&ep->dev->lock, flags);
-       net2272_dequeue_all(ep);
-       net2272_ep_reset(ep);
-
-       dev_vdbg(ep->dev->dev, "disabled %s\n", _ep->name);
-
-       spin_unlock_irqrestore(&ep->dev->lock, flags);
-       return 0;
-}
-
-/*---------------------------------------------------------------------------*/
-
-static struct usb_request *
-net2272_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
-{
-       struct net2272_ep *ep;
-       struct net2272_request *req;
-
-       if (!_ep)
-               return NULL;
-       ep = container_of(_ep, struct net2272_ep, ep);
-
-       req = kzalloc(sizeof(*req), gfp_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD(&req->queue);
-
-       return &req->req;
-}
-
-static void
-net2272_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct net2272_ep *ep;
-       struct net2272_request *req;
-
-       ep = container_of(_ep, struct net2272_ep, ep);
-       if (!_ep || !_req)
-               return;
-
-       req = container_of(_req, struct net2272_request, req);
-       WARN_ON(!list_empty(&req->queue));
-       kfree(req);
-}
-
-static void
-net2272_done(struct net2272_ep *ep, struct net2272_request *req, int status)
-{
-       struct net2272 *dev;
-       unsigned stopped = ep->stopped;
-
-       if (ep->num == 0) {
-               if (ep->dev->protocol_stall) {
-                       ep->stopped = 1;
-                       set_halt(ep);
-               }
-               allow_status(ep);
-       }
-
-       list_del_init(&req->queue);
-
-       if (req->req.status == -EINPROGRESS)
-               req->req.status = status;
-       else
-               status = req->req.status;
-
-       dev = ep->dev;
-       if (use_dma && ep->dma)
-               usb_gadget_unmap_request(&dev->gadget, &req->req,
-                               ep->is_in);
-
-       if (status && status != -ESHUTDOWN)
-               dev_vdbg(dev->dev, "complete %s req %p stat %d len %u/%u buf %p\n",
-                       ep->ep.name, &req->req, status,
-                       req->req.actual, req->req.length, req->req.buf);
-
-       /* don't modify queue heads during completion callback */
-       ep->stopped = 1;
-       spin_unlock(&dev->lock);
-       req->req.complete(&ep->ep, &req->req);
-       spin_lock(&dev->lock);
-       ep->stopped = stopped;
-}
-
-static int
-net2272_write_packet(struct net2272_ep *ep, u8 *buf,
-       struct net2272_request *req, unsigned max)
-{
-       u16 __iomem *ep_data = net2272_reg_addr(ep->dev, EP_DATA);
-       u16 *bufp;
-       unsigned length, count;
-       u8 tmp;
-
-       length = min(req->req.length - req->req.actual, max);
-       req->req.actual += length;
-
-       dev_vdbg(ep->dev->dev, "write packet %s req %p max %u len %u avail %u\n",
-               ep->ep.name, req, max, length,
-               (net2272_ep_read(ep, EP_AVAIL1) << 8) | net2272_ep_read(ep, EP_AVAIL0));
-
-       count = length;
-       bufp = (u16 *)buf;
-
-       while (likely(count >= 2)) {
-               /* no byte-swap required; chip endian set during init */
-               writew(*bufp++, ep_data);
-               count -= 2;
-       }
-       buf = (u8 *)bufp;
-
-       /* write final byte by placing the NET2272 into 8-bit mode */
-       if (unlikely(count)) {
-               tmp = net2272_read(ep->dev, LOCCTL);
-               net2272_write(ep->dev, LOCCTL, tmp & ~(1 << DATA_WIDTH));
-               writeb(*buf, ep_data);
-               net2272_write(ep->dev, LOCCTL, tmp);
-       }
-       return length;
-}
-
-/* returns: 0: still running, 1: completed, negative: errno */
-static int
-net2272_write_fifo(struct net2272_ep *ep, struct net2272_request *req)
-{
-       u8 *buf;
-       unsigned count, max;
-       int status;
-
-       dev_vdbg(ep->dev->dev, "write_fifo %s actual %d len %d\n",
-               ep->ep.name, req->req.actual, req->req.length);
-
-       /*
-        * Keep loading the endpoint until the final packet is loaded,
-        * or the endpoint buffer is full.
-        */
- top:
-       /*
-        * Clear interrupt status
-        *  - Packet Transmitted interrupt will become set again when the
-        *    host successfully takes another packet
-        */
-       net2272_ep_write(ep, EP_STAT0, (1 << DATA_PACKET_TRANSMITTED_INTERRUPT));
-       while (!(net2272_ep_read(ep, EP_STAT0) & (1 << BUFFER_FULL))) {
-               buf = req->req.buf + req->req.actual;
-               prefetch(buf);
-
-               /* force pagesel */
-               net2272_ep_read(ep, EP_STAT0);
-
-               max = (net2272_ep_read(ep, EP_AVAIL1) << 8) |
-                       (net2272_ep_read(ep, EP_AVAIL0));
-
-               if (max < ep->ep.maxpacket)
-                       max = (net2272_ep_read(ep, EP_AVAIL1) << 8)
-                               | (net2272_ep_read(ep, EP_AVAIL0));
-
-               count = net2272_write_packet(ep, buf, req, max);
-               /* see if we are done */
-               if (req->req.length == req->req.actual) {
-                       /* validate short or zlp packet */
-                       if (count < ep->ep.maxpacket)
-                               set_fifo_bytecount(ep, 0);
-                       net2272_done(ep, req, 0);
-
-                       if (!list_empty(&ep->queue)) {
-                               req = list_entry(ep->queue.next,
-                                               struct net2272_request,
-                                               queue);
-                               status = net2272_kick_dma(ep, req);
-
-                               if (status < 0)
-                                       if ((net2272_ep_read(ep, EP_STAT0)
-                                                       & (1 << BUFFER_EMPTY)))
-                                               goto top;
-                       }
-                       return 1;
-               }
-               net2272_ep_write(ep, EP_STAT0, (1 << DATA_PACKET_TRANSMITTED_INTERRUPT));
-       }
-       return 0;
-}
-
-static void
-net2272_out_flush(struct net2272_ep *ep)
-{
-       ASSERT_OUT_NAKING(ep);
-
-       net2272_ep_write(ep, EP_STAT0, (1 << DATA_OUT_TOKEN_INTERRUPT)
-                       | (1 << DATA_PACKET_RECEIVED_INTERRUPT));
-       net2272_ep_write(ep, EP_STAT1, 1 << BUFFER_FLUSH);
-}
-
-static int
-net2272_read_packet(struct net2272_ep *ep, u8 *buf,
-       struct net2272_request *req, unsigned avail)
-{
-       u16 __iomem *ep_data = net2272_reg_addr(ep->dev, EP_DATA);
-       unsigned is_short;
-       u16 *bufp;
-
-       req->req.actual += avail;
-
-       dev_vdbg(ep->dev->dev, "read packet %s req %p len %u avail %u\n",
-               ep->ep.name, req, avail,
-               (net2272_ep_read(ep, EP_AVAIL1) << 8) | net2272_ep_read(ep, EP_AVAIL0));
-
-       is_short = (avail < ep->ep.maxpacket);
-
-       if (unlikely(avail == 0)) {
-               /* remove any zlp from the buffer */
-               (void)readw(ep_data);
-               return is_short;
-       }
-
-       /* Ensure we get the final byte */
-       if (unlikely(avail % 2))
-               avail++;
-       bufp = (u16 *)buf;
-
-       do {
-               *bufp++ = readw(ep_data);
-               avail -= 2;
-       } while (avail);
-
-       /*
-        * To avoid false endpoint available race condition must read
-        * ep stat0 twice in the case of a short transfer
-        */
-       if (net2272_ep_read(ep, EP_STAT0) & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT))
-               net2272_ep_read(ep, EP_STAT0);
-
-       return is_short;
-}
-
-static int
-net2272_read_fifo(struct net2272_ep *ep, struct net2272_request *req)
-{
-       u8 *buf;
-       unsigned is_short;
-       int count;
-       int tmp;
-       int cleanup = 0;
-       int status = -1;
-
-       dev_vdbg(ep->dev->dev, "read_fifo %s actual %d len %d\n",
-               ep->ep.name, req->req.actual, req->req.length);
-
- top:
-       do {
-               buf = req->req.buf + req->req.actual;
-               prefetchw(buf);
-
-               count = (net2272_ep_read(ep, EP_AVAIL1) << 8)
-                       | net2272_ep_read(ep, EP_AVAIL0);
-
-               net2272_ep_write(ep, EP_STAT0,
-                       (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT) |
-                       (1 << DATA_PACKET_RECEIVED_INTERRUPT));
-
-               tmp = req->req.length - req->req.actual;
-
-               if (count > tmp) {
-                       if ((tmp % ep->ep.maxpacket) != 0) {
-                               dev_err(ep->dev->dev,
-                                       "%s out fifo %d bytes, expected %d\n",
-                                       ep->ep.name, count, tmp);
-                               cleanup = 1;
-                       }
-                       count = (tmp > 0) ? tmp : 0;
-               }
-
-               is_short = net2272_read_packet(ep, buf, req, count);
-
-               /* completion */
-               if (unlikely(cleanup || is_short ||
-                               ((req->req.actual == req->req.length)
-                                && !req->req.zero))) {
-
-                       if (cleanup) {
-                               net2272_out_flush(ep);
-                               net2272_done(ep, req, -EOVERFLOW);
-                       } else
-                               net2272_done(ep, req, 0);
-
-                       /* re-initialize endpoint transfer registers
-                        * otherwise they may result in erroneous pre-validation
-                        * for subsequent control reads
-                        */
-                       if (unlikely(ep->num == 0)) {
-                               net2272_ep_write(ep, EP_TRANSFER2, 0);
-                               net2272_ep_write(ep, EP_TRANSFER1, 0);
-                               net2272_ep_write(ep, EP_TRANSFER0, 0);
-                       }
-
-                       if (!list_empty(&ep->queue)) {
-                               req = list_entry(ep->queue.next,
-                                       struct net2272_request, queue);
-                               status = net2272_kick_dma(ep, req);
-                               if ((status < 0) &&
-                                   !(net2272_ep_read(ep, EP_STAT0) & (1 << BUFFER_EMPTY)))
-                                       goto top;
-                       }
-                       return 1;
-               }
-       } while (!(net2272_ep_read(ep, EP_STAT0) & (1 << BUFFER_EMPTY)));
-
-       return 0;
-}
-
-static void
-net2272_pio_advance(struct net2272_ep *ep)
-{
-       struct net2272_request *req;
-
-       if (unlikely(list_empty(&ep->queue)))
-               return;
-
-       req = list_entry(ep->queue.next, struct net2272_request, queue);
-       (ep->is_in ? net2272_write_fifo : net2272_read_fifo)(ep, req);
-}
-
-/* returns 0 on success, else negative errno */
-static int
-net2272_request_dma(struct net2272 *dev, unsigned ep, u32 buf,
-       unsigned len, unsigned dir)
-{
-       dev_vdbg(dev->dev, "request_dma ep %d buf %08x len %d dir %d\n",
-               ep, buf, len, dir);
-
-       /* The NET2272 only supports a single dma channel */
-       if (dev->dma_busy)
-               return -EBUSY;
-       /*
-        * EP_TRANSFER (used to determine the number of bytes received
-        * in an OUT transfer) is 24 bits wide; don't ask for more than that.
-        */
-       if ((dir == 1) && (len > 0x1000000))
-               return -EINVAL;
-
-       dev->dma_busy = 1;
-
-       /* initialize platform's dma */
-#ifdef CONFIG_PCI
-       /* NET2272 addr, buffer addr, length, etc. */
-       switch (dev->dev_id) {
-       case PCI_DEVICE_ID_RDK1:
-               /* Setup PLX 9054 DMA mode */
-               writel((1 << LOCAL_BUS_WIDTH) |
-                       (1 << TA_READY_INPUT_ENABLE) |
-                       (0 << LOCAL_BURST_ENABLE) |
-                       (1 << DONE_INTERRUPT_ENABLE) |
-                       (1 << LOCAL_ADDRESSING_MODE) |
-                       (1 << DEMAND_MODE) |
-                       (1 << DMA_EOT_ENABLE) |
-                       (1 << FAST_SLOW_TERMINATE_MODE_SELECT) |
-                       (1 << DMA_CHANNEL_INTERRUPT_SELECT),
-                       dev->rdk1.plx9054_base_addr + DMAMODE0);
-
-               writel(0x100000, dev->rdk1.plx9054_base_addr + DMALADR0);
-               writel(buf, dev->rdk1.plx9054_base_addr + DMAPADR0);
-               writel(len, dev->rdk1.plx9054_base_addr + DMASIZ0);
-               writel((dir << DIRECTION_OF_TRANSFER) |
-                       (1 << INTERRUPT_AFTER_TERMINAL_COUNT),
-                       dev->rdk1.plx9054_base_addr + DMADPR0);
-               writel((1 << LOCAL_DMA_CHANNEL_0_INTERRUPT_ENABLE) |
-                       readl(dev->rdk1.plx9054_base_addr + INTCSR),
-                       dev->rdk1.plx9054_base_addr + INTCSR);
-
-               break;
-       }
-#endif
-
-       net2272_write(dev, DMAREQ,
-               (0 << DMA_BUFFER_VALID) |
-               (1 << DMA_REQUEST_ENABLE) |
-               (1 << DMA_CONTROL_DACK) |
-               (dev->dma_eot_polarity << EOT_POLARITY) |
-               (dev->dma_dack_polarity << DACK_POLARITY) |
-               (dev->dma_dreq_polarity << DREQ_POLARITY) |
-               ((ep >> 1) << DMA_ENDPOINT_SELECT));
-
-       (void) net2272_read(dev, SCRATCH);
-
-       return 0;
-}
-
-static void
-net2272_start_dma(struct net2272 *dev)
-{
-       /* start platform's dma controller */
-#ifdef CONFIG_PCI
-       switch (dev->dev_id) {
-       case PCI_DEVICE_ID_RDK1:
-               writeb((1 << CHANNEL_ENABLE) | (1 << CHANNEL_START),
-                       dev->rdk1.plx9054_base_addr + DMACSR0);
-               break;
-       }
-#endif
-}
-
-/* returns 0 on success, else negative errno */
-static int
-net2272_kick_dma(struct net2272_ep *ep, struct net2272_request *req)
-{
-       unsigned size;
-       u8 tmp;
-
-       if (!use_dma || (ep->num < 1) || (ep->num > 2) || !ep->dma)
-               return -EINVAL;
-
-       /* don't use dma for odd-length transfers
-        * otherwise, we'd need to deal with the last byte with pio
-        */
-       if (req->req.length & 1)
-               return -EINVAL;
-
-       dev_vdbg(ep->dev->dev, "kick_dma %s req %p dma %08llx\n",
-               ep->ep.name, req, (unsigned long long) req->req.dma);
-
-       net2272_ep_write(ep, EP_RSPSET, 1 << ALT_NAK_OUT_PACKETS);
-
-       /* The NET2272 can only use DMA on one endpoint at a time */
-       if (ep->dev->dma_busy)
-               return -EBUSY;
-
-       /* Make sure we only DMA an even number of bytes (we'll use
-        * pio to complete the transfer)
-        */
-       size = req->req.length;
-       size &= ~1;
-
-       /* device-to-host transfer */
-       if (ep->is_in) {
-               /* initialize platform's dma controller */
-               if (net2272_request_dma(ep->dev, ep->num, req->req.dma, size, 0))
-                       /* unable to obtain DMA channel; return error and use pio mode */
-                       return -EBUSY;
-               req->req.actual += size;
-
-       /* host-to-device transfer */
-       } else {
-               tmp = net2272_ep_read(ep, EP_STAT0);
-
-               /* initialize platform's dma controller */
-               if (net2272_request_dma(ep->dev, ep->num, req->req.dma, size, 1))
-                       /* unable to obtain DMA channel; return error and use pio mode */
-                       return -EBUSY;
-
-               if (!(tmp & (1 << BUFFER_EMPTY)))
-                       ep->not_empty = 1;
-               else
-                       ep->not_empty = 0;
-
-
-               /* allow the endpoint's buffer to fill */
-               net2272_ep_write(ep, EP_RSPCLR, 1 << ALT_NAK_OUT_PACKETS);
-
-               /* this transfer completed and data's already in the fifo
-                * return error so pio gets used.
-                */
-               if (tmp & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
-
-                       /* deassert dreq */
-                       net2272_write(ep->dev, DMAREQ,
-                               (0 << DMA_BUFFER_VALID) |
-                               (0 << DMA_REQUEST_ENABLE) |
-                               (1 << DMA_CONTROL_DACK) |
-                               (ep->dev->dma_eot_polarity << EOT_POLARITY) |
-                               (ep->dev->dma_dack_polarity << DACK_POLARITY) |
-                               (ep->dev->dma_dreq_polarity << DREQ_POLARITY) |
-                               ((ep->num >> 1) << DMA_ENDPOINT_SELECT));
-
-                       return -EBUSY;
-               }
-       }
-
-       /* Don't use per-packet interrupts: use dma interrupts only */
-       net2272_ep_write(ep, EP_IRQENB, 0);
-
-       net2272_start_dma(ep->dev);
-
-       return 0;
-}
-
-static void net2272_cancel_dma(struct net2272 *dev)
-{
-#ifdef CONFIG_PCI
-       switch (dev->dev_id) {
-       case PCI_DEVICE_ID_RDK1:
-               writeb(0, dev->rdk1.plx9054_base_addr + DMACSR0);
-               writeb(1 << CHANNEL_ABORT, dev->rdk1.plx9054_base_addr + DMACSR0);
-               while (!(readb(dev->rdk1.plx9054_base_addr + DMACSR0) &
-                        (1 << CHANNEL_DONE)))
-                       continue;       /* wait for dma to stabalize */
-
-               /* dma abort generates an interrupt */
-               writeb(1 << CHANNEL_CLEAR_INTERRUPT,
-                       dev->rdk1.plx9054_base_addr + DMACSR0);
-               break;
-       }
-#endif
-
-       dev->dma_busy = 0;
-}
-
-/*---------------------------------------------------------------------------*/
-
-static int
-net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
-{
-       struct net2272_request *req;
-       struct net2272_ep *ep;
-       struct net2272 *dev;
-       unsigned long flags;
-       int status = -1;
-       u8 s;
-
-       req = container_of(_req, struct net2272_request, req);
-       if (!_req || !_req->complete || !_req->buf
-                       || !list_empty(&req->queue))
-               return -EINVAL;
-       ep = container_of(_ep, struct net2272_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0))
-               return -EINVAL;
-       dev = ep->dev;
-       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       /* set up dma mapping in case the caller didn't */
-       if (use_dma && ep->dma) {
-               status = usb_gadget_map_request(&dev->gadget, _req,
-                               ep->is_in);
-               if (status)
-                       return status;
-       }
-
-       dev_vdbg(dev->dev, "%s queue req %p, len %d buf %p dma %08llx %s\n",
-               _ep->name, _req, _req->length, _req->buf,
-               (unsigned long long) _req->dma, _req->zero ? "zero" : "!zero");
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       _req->status = -EINPROGRESS;
-       _req->actual = 0;
-
-       /* kickstart this i/o queue? */
-       if (list_empty(&ep->queue) && !ep->stopped) {
-               /* maybe there's no control data, just status ack */
-               if (ep->num == 0 && _req->length == 0) {
-                       net2272_done(ep, req, 0);
-                       dev_vdbg(dev->dev, "%s status ack\n", ep->ep.name);
-                       goto done;
-               }
-
-               /* Return zlp, don't let it block subsequent packets */
-               s = net2272_ep_read(ep, EP_STAT0);
-               if (s & (1 << BUFFER_EMPTY)) {
-                       /* Buffer is empty check for a blocking zlp, handle it */
-                       if ((s & (1 << NAK_OUT_PACKETS)) &&
-                           net2272_ep_read(ep, EP_STAT1) & (1 << LOCAL_OUT_ZLP)) {
-                               dev_dbg(dev->dev, "WARNING: returning ZLP short packet termination!\n");
-                               /*
-                                * Request is going to terminate with a short packet ...
-                                * hope the client is ready for it!
-                                */
-                               status = net2272_read_fifo(ep, req);
-                               /* clear short packet naking */
-                               net2272_ep_write(ep, EP_STAT0, (1 << NAK_OUT_PACKETS));
-                               goto done;
-                       }
-               }
-
-               /* try dma first */
-               status = net2272_kick_dma(ep, req);
-
-               if (status < 0) {
-                       /* dma failed (most likely in use by another endpoint)
-                        * fallback to pio
-                        */
-                       status = 0;
-
-                       if (ep->is_in)
-                               status = net2272_write_fifo(ep, req);
-                       else {
-                               s = net2272_ep_read(ep, EP_STAT0);
-                               if ((s & (1 << BUFFER_EMPTY)) == 0)
-                                       status = net2272_read_fifo(ep, req);
-                       }
-
-                       if (unlikely(status != 0)) {
-                               if (status > 0)
-                                       status = 0;
-                               req = NULL;
-                       }
-               }
-       }
-       if (likely(req))
-               list_add_tail(&req->queue, &ep->queue);
-
-       if (likely(!list_empty(&ep->queue)))
-               net2272_ep_write(ep, EP_RSPCLR, 1 << ALT_NAK_OUT_PACKETS);
- done:
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return 0;
-}
-
-/* dequeue ALL requests */
-static void
-net2272_dequeue_all(struct net2272_ep *ep)
-{
-       struct net2272_request *req;
-
-       /* called with spinlock held */
-       ep->stopped = 1;
-
-       while (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next,
-                               struct net2272_request,
-                               queue);
-               net2272_done(ep, req, -ESHUTDOWN);
-       }
-}
-
-/* dequeue JUST ONE request */
-static int
-net2272_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct net2272_ep *ep;
-       struct net2272_request *req;
-       unsigned long flags;
-       int stopped;
-
-       ep = container_of(_ep, struct net2272_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0) || !_req)
-               return -EINVAL;
-
-       spin_lock_irqsave(&ep->dev->lock, flags);
-       stopped = ep->stopped;
-       ep->stopped = 1;
-
-       /* make sure it's still queued on this endpoint */
-       list_for_each_entry(req, &ep->queue, queue) {
-               if (&req->req == _req)
-                       break;
-       }
-       if (&req->req != _req) {
-               spin_unlock_irqrestore(&ep->dev->lock, flags);
-               return -EINVAL;
-       }
-
-       /* queue head may be partially complete */
-       if (ep->queue.next == &req->queue) {
-               dev_dbg(ep->dev->dev, "unlink (%s) pio\n", _ep->name);
-               net2272_done(ep, req, -ECONNRESET);
-       }
-       req = NULL;
-       ep->stopped = stopped;
-
-       spin_unlock_irqrestore(&ep->dev->lock, flags);
-       return 0;
-}
-
-/*---------------------------------------------------------------------------*/
-
-static int
-net2272_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
-{
-       struct net2272_ep *ep;
-       unsigned long flags;
-       int ret = 0;
-
-       ep = container_of(_ep, struct net2272_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0))
-               return -EINVAL;
-       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-       if (ep->desc /* not ep0 */ && usb_endpoint_xfer_isoc(ep->desc))
-               return -EINVAL;
-
-       spin_lock_irqsave(&ep->dev->lock, flags);
-       if (!list_empty(&ep->queue))
-               ret = -EAGAIN;
-       else if (ep->is_in && value && net2272_fifo_status(_ep) != 0)
-               ret = -EAGAIN;
-       else {
-               dev_vdbg(ep->dev->dev, "%s %s %s\n", _ep->name,
-                       value ? "set" : "clear",
-                       wedged ? "wedge" : "halt");
-               /* set/clear */
-               if (value) {
-                       if (ep->num == 0)
-                               ep->dev->protocol_stall = 1;
-                       else
-                               set_halt(ep);
-                       if (wedged)
-                               ep->wedged = 1;
-               } else {
-                       clear_halt(ep);
-                       ep->wedged = 0;
-               }
-       }
-       spin_unlock_irqrestore(&ep->dev->lock, flags);
-
-       return ret;
-}
-
-static int
-net2272_set_halt(struct usb_ep *_ep, int value)
-{
-       return net2272_set_halt_and_wedge(_ep, value, 0);
-}
-
-static int
-net2272_set_wedge(struct usb_ep *_ep)
-{
-       if (!_ep || _ep->name == ep0name)
-               return -EINVAL;
-       return net2272_set_halt_and_wedge(_ep, 1, 1);
-}
-
-static int
-net2272_fifo_status(struct usb_ep *_ep)
-{
-       struct net2272_ep *ep;
-       u16 avail;
-
-       ep = container_of(_ep, struct net2272_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0))
-               return -ENODEV;
-       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       avail = net2272_ep_read(ep, EP_AVAIL1) << 8;
-       avail |= net2272_ep_read(ep, EP_AVAIL0);
-       if (avail > ep->fifo_size)
-               return -EOVERFLOW;
-       if (ep->is_in)
-               avail = ep->fifo_size - avail;
-       return avail;
-}
-
-static void
-net2272_fifo_flush(struct usb_ep *_ep)
-{
-       struct net2272_ep *ep;
-
-       ep = container_of(_ep, struct net2272_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0))
-               return;
-       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return;
-
-       net2272_ep_write(ep, EP_STAT1, 1 << BUFFER_FLUSH);
-}
-
-static struct usb_ep_ops net2272_ep_ops = {
-       .enable        = net2272_enable,
-       .disable       = net2272_disable,
-
-       .alloc_request = net2272_alloc_request,
-       .free_request  = net2272_free_request,
-
-       .queue         = net2272_queue,
-       .dequeue       = net2272_dequeue,
-
-       .set_halt      = net2272_set_halt,
-       .set_wedge     = net2272_set_wedge,
-       .fifo_status   = net2272_fifo_status,
-       .fifo_flush    = net2272_fifo_flush,
-};
-
-/*---------------------------------------------------------------------------*/
-
-static int
-net2272_get_frame(struct usb_gadget *_gadget)
-{
-       struct net2272 *dev;
-       unsigned long flags;
-       u16 ret;
-
-       if (!_gadget)
-               return -ENODEV;
-       dev = container_of(_gadget, struct net2272, gadget);
-       spin_lock_irqsave(&dev->lock, flags);
-
-       ret = net2272_read(dev, FRAME1) << 8;
-       ret |= net2272_read(dev, FRAME0);
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-       return ret;
-}
-
-static int
-net2272_wakeup(struct usb_gadget *_gadget)
-{
-       struct net2272 *dev;
-       u8 tmp;
-       unsigned long flags;
-
-       if (!_gadget)
-               return 0;
-       dev = container_of(_gadget, struct net2272, gadget);
-
-       spin_lock_irqsave(&dev->lock, flags);
-       tmp = net2272_read(dev, USBCTL0);
-       if (tmp & (1 << IO_WAKEUP_ENABLE))
-               net2272_write(dev, USBCTL1, (1 << GENERATE_RESUME));
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return 0;
-}
-
-static int
-net2272_set_selfpowered(struct usb_gadget *_gadget, int value)
-{
-       struct net2272 *dev;
-
-       if (!_gadget)
-               return -ENODEV;
-       dev = container_of(_gadget, struct net2272, gadget);
-
-       dev->is_selfpowered = value;
-
-       return 0;
-}
-
-static int
-net2272_pullup(struct usb_gadget *_gadget, int is_on)
-{
-       struct net2272 *dev;
-       u8 tmp;
-       unsigned long flags;
-
-       if (!_gadget)
-               return -ENODEV;
-       dev = container_of(_gadget, struct net2272, gadget);
-
-       spin_lock_irqsave(&dev->lock, flags);
-       tmp = net2272_read(dev, USBCTL0);
-       dev->softconnect = (is_on != 0);
-       if (is_on)
-               tmp |= (1 << USB_DETECT_ENABLE);
-       else
-               tmp &= ~(1 << USB_DETECT_ENABLE);
-       net2272_write(dev, USBCTL0, tmp);
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return 0;
-}
-
-static int net2272_start(struct usb_gadget *_gadget,
-               struct usb_gadget_driver *driver);
-static int net2272_stop(struct usb_gadget *_gadget,
-               struct usb_gadget_driver *driver);
-
-static const struct usb_gadget_ops net2272_ops = {
-       .get_frame      = net2272_get_frame,
-       .wakeup         = net2272_wakeup,
-       .set_selfpowered = net2272_set_selfpowered,
-       .pullup         = net2272_pullup,
-       .udc_start      = net2272_start,
-       .udc_stop       = net2272_stop,
-};
-
-/*---------------------------------------------------------------------------*/
-
-static ssize_t
-registers_show(struct device *_dev, struct device_attribute *attr, char *buf)
-{
-       struct net2272 *dev;
-       char *next;
-       unsigned size, t;
-       unsigned long flags;
-       u8 t1, t2;
-       int i;
-       const char *s;
-
-       dev = dev_get_drvdata(_dev);
-       next = buf;
-       size = PAGE_SIZE;
-       spin_lock_irqsave(&dev->lock, flags);
-
-       if (dev->driver)
-               s = dev->driver->driver.name;
-       else
-               s = "(none)";
-
-       /* Main Control Registers */
-       t = scnprintf(next, size, "%s version %s,"
-               "chiprev %02x, locctl %02x\n"
-               "irqenb0 %02x irqenb1 %02x "
-               "irqstat0 %02x irqstat1 %02x\n",
-               driver_name, driver_vers, dev->chiprev,
-               net2272_read(dev, LOCCTL),
-               net2272_read(dev, IRQENB0),
-               net2272_read(dev, IRQENB1),
-               net2272_read(dev, IRQSTAT0),
-               net2272_read(dev, IRQSTAT1));
-       size -= t;
-       next += t;
-
-       /* DMA */
-       t1 = net2272_read(dev, DMAREQ);
-       t = scnprintf(next, size, "\ndmareq %02x: %s %s%s%s%s\n",
-               t1, ep_name[(t1 & 0x01) + 1],
-               t1 & (1 << DMA_CONTROL_DACK) ? "dack " : "",
-               t1 & (1 << DMA_REQUEST_ENABLE) ? "reqenb " : "",
-               t1 & (1 << DMA_REQUEST) ? "req " : "",
-               t1 & (1 << DMA_BUFFER_VALID) ? "valid " : "");
-       size -= t;
-       next += t;
-
-       /* USB Control Registers */
-       t1 = net2272_read(dev, USBCTL1);
-       if (t1 & (1 << VBUS_PIN)) {
-               if (t1 & (1 << USB_HIGH_SPEED))
-                       s = "high speed";
-               else if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-                       s = "powered";
-               else
-                       s = "full speed";
-       } else
-               s = "not attached";
-       t = scnprintf(next, size,
-               "usbctl0 %02x usbctl1 %02x addr 0x%02x (%s)\n",
-               net2272_read(dev, USBCTL0), t1,
-               net2272_read(dev, OURADDR), s);
-       size -= t;
-       next += t;
-
-       /* Endpoint Registers */
-       for (i = 0; i < 4; ++i) {
-               struct net2272_ep *ep;
-
-               ep = &dev->ep[i];
-               if (i && !ep->desc)
-                       continue;
-
-               t1 = net2272_ep_read(ep, EP_CFG);
-               t2 = net2272_ep_read(ep, EP_RSPSET);
-               t = scnprintf(next, size,
-                       "\n%s\tcfg %02x rsp (%02x) %s%s%s%s%s%s%s%s"
-                       "irqenb %02x\n",
-                       ep->ep.name, t1, t2,
-                       (t2 & (1 << ALT_NAK_OUT_PACKETS)) ? "NAK " : "",
-                       (t2 & (1 << HIDE_STATUS_PHASE)) ? "hide " : "",
-                       (t2 & (1 << AUTOVALIDATE)) ? "auto " : "",
-                       (t2 & (1 << INTERRUPT_MODE)) ? "interrupt " : "",
-                       (t2 & (1 << CONTROL_STATUS_PHASE_HANDSHAKE)) ? "status " : "",
-                       (t2 & (1 << NAK_OUT_PACKETS_MODE)) ? "NAKmode " : "",
-                       (t2 & (1 << ENDPOINT_TOGGLE)) ? "DATA1 " : "DATA0 ",
-                       (t2 & (1 << ENDPOINT_HALT)) ? "HALT " : "",
-                       net2272_ep_read(ep, EP_IRQENB));
-               size -= t;
-               next += t;
-
-               t = scnprintf(next, size,
-                       "\tstat0 %02x stat1 %02x avail %04x "
-                       "(ep%d%s-%s)%s\n",
-                       net2272_ep_read(ep, EP_STAT0),
-                       net2272_ep_read(ep, EP_STAT1),
-                       (net2272_ep_read(ep, EP_AVAIL1) << 8) | net2272_ep_read(ep, EP_AVAIL0),
-                       t1 & 0x0f,
-                       ep->is_in ? "in" : "out",
-                       type_string(t1 >> 5),
-                       ep->stopped ? "*" : "");
-               size -= t;
-               next += t;
-
-               t = scnprintf(next, size,
-                       "\tep_transfer %06x\n",
-                       ((net2272_ep_read(ep, EP_TRANSFER2) & 0xff) << 16) |
-                       ((net2272_ep_read(ep, EP_TRANSFER1) & 0xff) << 8) |
-                       ((net2272_ep_read(ep, EP_TRANSFER0) & 0xff)));
-               size -= t;
-               next += t;
-
-               t1 = net2272_ep_read(ep, EP_BUFF_STATES) & 0x03;
-               t2 = (net2272_ep_read(ep, EP_BUFF_STATES) >> 2) & 0x03;
-               t = scnprintf(next, size,
-                       "\tbuf-a %s buf-b %s\n",
-                       buf_state_string(t1),
-                       buf_state_string(t2));
-               size -= t;
-               next += t;
-       }
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return PAGE_SIZE - size;
-}
-static DEVICE_ATTR_RO(registers);
-
-/*---------------------------------------------------------------------------*/
-
-static void
-net2272_set_fifo_mode(struct net2272 *dev, int mode)
-{
-       u8 tmp;
-
-       tmp = net2272_read(dev, LOCCTL) & 0x3f;
-       tmp |= (mode << 6);
-       net2272_write(dev, LOCCTL, tmp);
-
-       INIT_LIST_HEAD(&dev->gadget.ep_list);
-
-       /* always ep-a, ep-c ... maybe not ep-b */
-       list_add_tail(&dev->ep[1].ep.ep_list, &dev->gadget.ep_list);
-
-       switch (mode) {
-       case 0:
-               list_add_tail(&dev->ep[2].ep.ep_list, &dev->gadget.ep_list);
-               dev->ep[1].fifo_size = dev->ep[2].fifo_size = 512;
-               break;
-       case 1:
-               list_add_tail(&dev->ep[2].ep.ep_list, &dev->gadget.ep_list);
-               dev->ep[1].fifo_size = 1024;
-               dev->ep[2].fifo_size = 512;
-               break;
-       case 2:
-               list_add_tail(&dev->ep[2].ep.ep_list, &dev->gadget.ep_list);
-               dev->ep[1].fifo_size = dev->ep[2].fifo_size = 1024;
-               break;
-       case 3:
-               dev->ep[1].fifo_size = 1024;
-               break;
-       }
-
-       /* ep-c is always 2 512 byte buffers */
-       list_add_tail(&dev->ep[3].ep.ep_list, &dev->gadget.ep_list);
-       dev->ep[3].fifo_size = 512;
-}
-
-/*---------------------------------------------------------------------------*/
-
-static void
-net2272_usb_reset(struct net2272 *dev)
-{
-       dev->gadget.speed = USB_SPEED_UNKNOWN;
-
-       net2272_cancel_dma(dev);
-
-       net2272_write(dev, IRQENB0, 0);
-       net2272_write(dev, IRQENB1, 0);
-
-       /* clear irq state */
-       net2272_write(dev, IRQSTAT0, 0xff);
-       net2272_write(dev, IRQSTAT1, ~(1 << SUSPEND_REQUEST_INTERRUPT));
-
-       net2272_write(dev, DMAREQ,
-               (0 << DMA_BUFFER_VALID) |
-               (0 << DMA_REQUEST_ENABLE) |
-               (1 << DMA_CONTROL_DACK) |
-               (dev->dma_eot_polarity << EOT_POLARITY) |
-               (dev->dma_dack_polarity << DACK_POLARITY) |
-               (dev->dma_dreq_polarity << DREQ_POLARITY) |
-               ((dma_ep >> 1) << DMA_ENDPOINT_SELECT));
-
-       net2272_cancel_dma(dev);
-       net2272_set_fifo_mode(dev, (fifo_mode <= 3) ? fifo_mode : 0);
-
-       /* Set the NET2272 ep fifo data width to 16-bit mode and for correct byte swapping
-        * note that the higher level gadget drivers are expected to convert data to little endian.
-        * Enable byte swap for your local bus/cpu if needed by setting BYTE_SWAP in LOCCTL here
-        */
-       net2272_write(dev, LOCCTL, net2272_read(dev, LOCCTL) | (1 << DATA_WIDTH));
-       net2272_write(dev, LOCCTL1, (dma_mode << DMA_MODE));
-}
-
-static void
-net2272_usb_reinit(struct net2272 *dev)
-{
-       int i;
-
-       /* basic endpoint init */
-       for (i = 0; i < 4; ++i) {
-               struct net2272_ep *ep = &dev->ep[i];
-
-               ep->ep.name = ep_name[i];
-               ep->dev = dev;
-               ep->num = i;
-               ep->not_empty = 0;
-
-               if (use_dma && ep->num == dma_ep)
-                       ep->dma = 1;
-
-               if (i > 0 && i <= 3)
-                       ep->fifo_size = 512;
-               else
-                       ep->fifo_size = 64;
-               net2272_ep_reset(ep);
-       }
-       usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 64);
-
-       dev->gadget.ep0 = &dev->ep[0].ep;
-       dev->ep[0].stopped = 0;
-       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
-}
-
-static void
-net2272_ep0_start(struct net2272 *dev)
-{
-       struct net2272_ep *ep0 = &dev->ep[0];
-
-       net2272_ep_write(ep0, EP_RSPSET,
-               (1 << NAK_OUT_PACKETS_MODE) |
-               (1 << ALT_NAK_OUT_PACKETS));
-       net2272_ep_write(ep0, EP_RSPCLR,
-               (1 << HIDE_STATUS_PHASE) |
-               (1 << CONTROL_STATUS_PHASE_HANDSHAKE));
-       net2272_write(dev, USBCTL0,
-               (dev->softconnect << USB_DETECT_ENABLE) |
-               (1 << USB_ROOT_PORT_WAKEUP_ENABLE) |
-               (1 << IO_WAKEUP_ENABLE));
-       net2272_write(dev, IRQENB0,
-               (1 << SETUP_PACKET_INTERRUPT_ENABLE) |
-               (1 << ENDPOINT_0_INTERRUPT_ENABLE) |
-               (1 << DMA_DONE_INTERRUPT_ENABLE));
-       net2272_write(dev, IRQENB1,
-               (1 << VBUS_INTERRUPT_ENABLE) |
-               (1 << ROOT_PORT_RESET_INTERRUPT_ENABLE) |
-               (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE));
-}
-
-/* when a driver is successfully registered, it will receive
- * control requests including set_configuration(), which enables
- * non-control requests.  then usb traffic follows until a
- * disconnect is reported.  then a host may connect again, or
- * the driver might get unbound.
- */
-static int net2272_start(struct usb_gadget *_gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct net2272 *dev;
-       unsigned i;
-
-       if (!driver || !driver->setup ||
-           driver->max_speed != USB_SPEED_HIGH)
-               return -EINVAL;
-
-       dev = container_of(_gadget, struct net2272, gadget);
-
-       for (i = 0; i < 4; ++i)
-               dev->ep[i].irqs = 0;
-       /* hook up the driver ... */
-       dev->softconnect = 1;
-       driver->driver.bus = NULL;
-       dev->driver = driver;
-
-       /* ... then enable host detection and ep0; and we're ready
-        * for set_configuration as well as eventual disconnect.
-        */
-       net2272_ep0_start(dev);
-
-       dev_dbg(dev->dev, "%s ready\n", driver->driver.name);
-
-       return 0;
-}
-
-static void
-stop_activity(struct net2272 *dev, struct usb_gadget_driver *driver)
-{
-       int i;
-
-       /* don't disconnect if it's not connected */
-       if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-               driver = NULL;
-
-       /* stop hardware; prevent new request submissions;
-        * and kill any outstanding requests.
-        */
-       net2272_usb_reset(dev);
-       for (i = 0; i < 4; ++i)
-               net2272_dequeue_all(&dev->ep[i]);
-
-       /* report disconnect; the driver is already quiesced */
-       if (driver) {
-               spin_unlock(&dev->lock);
-               driver->disconnect(&dev->gadget);
-               spin_lock(&dev->lock);
-       }
-
-       net2272_usb_reinit(dev);
-}
-
-static int net2272_stop(struct usb_gadget *_gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct net2272 *dev;
-       unsigned long flags;
-
-       dev = container_of(_gadget, struct net2272, gadget);
-
-       spin_lock_irqsave(&dev->lock, flags);
-       stop_activity(dev, driver);
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       dev->driver = NULL;
-
-       dev_dbg(dev->dev, "unregistered driver '%s'\n", driver->driver.name);
-       return 0;
-}
-
-/*---------------------------------------------------------------------------*/
-/* handle ep-a/ep-b dma completions */
-static void
-net2272_handle_dma(struct net2272_ep *ep)
-{
-       struct net2272_request *req;
-       unsigned len;
-       int status;
-
-       if (!list_empty(&ep->queue))
-               req = list_entry(ep->queue.next,
-                               struct net2272_request, queue);
-       else
-               req = NULL;
-
-       dev_vdbg(ep->dev->dev, "handle_dma %s req %p\n", ep->ep.name, req);
-
-       /* Ensure DREQ is de-asserted */
-       net2272_write(ep->dev, DMAREQ,
-               (0 << DMA_BUFFER_VALID)
-             | (0 << DMA_REQUEST_ENABLE)
-             | (1 << DMA_CONTROL_DACK)
-             | (ep->dev->dma_eot_polarity << EOT_POLARITY)
-             | (ep->dev->dma_dack_polarity << DACK_POLARITY)
-             | (ep->dev->dma_dreq_polarity << DREQ_POLARITY)
-             | (ep->dma << DMA_ENDPOINT_SELECT));
-
-       ep->dev->dma_busy = 0;
-
-       net2272_ep_write(ep, EP_IRQENB,
-                 (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
-               | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
-               | net2272_ep_read(ep, EP_IRQENB));
-
-       /* device-to-host transfer completed */
-       if (ep->is_in) {
-               /* validate a short packet or zlp if necessary */
-               if ((req->req.length % ep->ep.maxpacket != 0) ||
-                               req->req.zero)
-                       set_fifo_bytecount(ep, 0);
-
-               net2272_done(ep, req, 0);
-               if (!list_empty(&ep->queue)) {
-                       req = list_entry(ep->queue.next,
-                                       struct net2272_request, queue);
-                       status = net2272_kick_dma(ep, req);
-                       if (status < 0)
-                               net2272_pio_advance(ep);
-               }
-
-       /* host-to-device transfer completed */
-       } else {
-               /* terminated with a short packet? */
-               if (net2272_read(ep->dev, IRQSTAT0) &
-                               (1 << DMA_DONE_INTERRUPT)) {
-                       /* abort system dma */
-                       net2272_cancel_dma(ep->dev);
-               }
-
-               /* EP_TRANSFER will contain the number of bytes
-                * actually received.
-                * NOTE: There is no overflow detection on EP_TRANSFER:
-                * We can't deal with transfers larger than 2^24 bytes!
-                */
-               len = (net2272_ep_read(ep, EP_TRANSFER2) << 16)
-                       | (net2272_ep_read(ep, EP_TRANSFER1) << 8)
-                       | (net2272_ep_read(ep, EP_TRANSFER0));
-
-               if (ep->not_empty)
-                       len += 4;
-
-               req->req.actual += len;
-
-               /* get any remaining data */
-               net2272_pio_advance(ep);
-       }
-}
-
-/*---------------------------------------------------------------------------*/
-
-static void
-net2272_handle_ep(struct net2272_ep *ep)
-{
-       struct net2272_request *req;
-       u8 stat0, stat1;
-
-       if (!list_empty(&ep->queue))
-               req = list_entry(ep->queue.next,
-                       struct net2272_request, queue);
-       else
-               req = NULL;
-
-       /* ack all, and handle what we care about */
-       stat0 = net2272_ep_read(ep, EP_STAT0);
-       stat1 = net2272_ep_read(ep, EP_STAT1);
-       ep->irqs++;
-
-       dev_vdbg(ep->dev->dev, "%s ack ep_stat0 %02x, ep_stat1 %02x, req %p\n",
-               ep->ep.name, stat0, stat1, req ? &req->req : NULL);
-
-       net2272_ep_write(ep, EP_STAT0, stat0 &
-               ~((1 << NAK_OUT_PACKETS)
-               | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)));
-       net2272_ep_write(ep, EP_STAT1, stat1);
-
-       /* data packet(s) received (in the fifo, OUT)
-        * direction must be validated, otherwise control read status phase
-        * could be interpreted as a valid packet
-        */
-       if (!ep->is_in && (stat0 & (1 << DATA_PACKET_RECEIVED_INTERRUPT)))
-               net2272_pio_advance(ep);
-       /* data packet(s) transmitted (IN) */
-       else if (stat0 & (1 << DATA_PACKET_TRANSMITTED_INTERRUPT))
-               net2272_pio_advance(ep);
-}
-
-static struct net2272_ep *
-net2272_get_ep_by_addr(struct net2272 *dev, u16 wIndex)
-{
-       struct net2272_ep *ep;
-
-       if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
-               return &dev->ep[0];
-
-       list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
-               u8 bEndpointAddress;
-
-               if (!ep->desc)
-                       continue;
-               bEndpointAddress = ep->desc->bEndpointAddress;
-               if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
-                       continue;
-               if ((wIndex & 0x0f) == (bEndpointAddress & 0x0f))
-                       return ep;
-       }
-       return NULL;
-}
-
-/*
- * USB Test Packet:
- * JKJKJKJK * 9
- * JJKKJJKK * 8
- * JJJJKKKK * 8
- * JJJJJJJKKKKKKK * 8
- * JJJJJJJK * 8
- * {JKKKKKKK * 10}, JK
- */
-static const u8 net2272_test_packet[] = {
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
-       0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
-       0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-       0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD,
-       0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFD, 0x7E
-};
-
-static void
-net2272_set_test_mode(struct net2272 *dev, int mode)
-{
-       int i;
-
-       /* Disable all net2272 interrupts:
-        * Nothing but a power cycle should stop the test.
-        */
-       net2272_write(dev, IRQENB0, 0x00);
-       net2272_write(dev, IRQENB1, 0x00);
-
-       /* Force tranceiver to high-speed */
-       net2272_write(dev, XCVRDIAG, 1 << FORCE_HIGH_SPEED);
-
-       net2272_write(dev, PAGESEL, 0);
-       net2272_write(dev, EP_STAT0, 1 << DATA_PACKET_TRANSMITTED_INTERRUPT);
-       net2272_write(dev, EP_RSPCLR,
-                         (1 << CONTROL_STATUS_PHASE_HANDSHAKE)
-                       | (1 << HIDE_STATUS_PHASE));
-       net2272_write(dev, EP_CFG, 1 << ENDPOINT_DIRECTION);
-       net2272_write(dev, EP_STAT1, 1 << BUFFER_FLUSH);
-
-       /* wait for status phase to complete */
-       while (!(net2272_read(dev, EP_STAT0) &
-                               (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)))
-               ;
-
-       /* Enable test mode */
-       net2272_write(dev, USBTEST, mode);
-
-       /* load test packet */
-       if (mode == TEST_PACKET) {
-               /* switch to 8 bit mode */
-               net2272_write(dev, LOCCTL, net2272_read(dev, LOCCTL) &
-                               ~(1 << DATA_WIDTH));
-
-               for (i = 0; i < sizeof(net2272_test_packet); ++i)
-                       net2272_write(dev, EP_DATA, net2272_test_packet[i]);
-
-               /* Validate test packet */
-               net2272_write(dev, EP_TRANSFER0, 0);
-       }
-}
-
-static void
-net2272_handle_stat0_irqs(struct net2272 *dev, u8 stat)
-{
-       struct net2272_ep *ep;
-       u8 num, scratch;
-
-       /* starting a control request? */
-       if (unlikely(stat & (1 << SETUP_PACKET_INTERRUPT))) {
-               union {
-                       u8 raw[8];
-                       struct usb_ctrlrequest  r;
-               } u;
-               int tmp = 0;
-               struct net2272_request *req;
-
-               if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
-                       if (net2272_read(dev, USBCTL1) & (1 << USB_HIGH_SPEED))
-                               dev->gadget.speed = USB_SPEED_HIGH;
-                       else
-                               dev->gadget.speed = USB_SPEED_FULL;
-                       dev_dbg(dev->dev, "%s\n",
-                               usb_speed_string(dev->gadget.speed));
-               }
-
-               ep = &dev->ep[0];
-               ep->irqs++;
-
-               /* make sure any leftover interrupt state is cleared */
-               stat &= ~(1 << ENDPOINT_0_INTERRUPT);
-               while (!list_empty(&ep->queue)) {
-                       req = list_entry(ep->queue.next,
-                               struct net2272_request, queue);
-                       net2272_done(ep, req,
-                               (req->req.actual == req->req.length) ? 0 : -EPROTO);
-               }
-               ep->stopped = 0;
-               dev->protocol_stall = 0;
-               net2272_ep_write(ep, EP_STAT0,
-                           (1 << DATA_IN_TOKEN_INTERRUPT)
-                         | (1 << DATA_OUT_TOKEN_INTERRUPT)
-                         | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
-                         | (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-                         | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT));
-               net2272_ep_write(ep, EP_STAT1,
-                           (1 << TIMEOUT)
-                         | (1 << USB_OUT_ACK_SENT)
-                         | (1 << USB_OUT_NAK_SENT)
-                         | (1 << USB_IN_ACK_RCVD)
-                         | (1 << USB_IN_NAK_SENT)
-                         | (1 << USB_STALL_SENT)
-                         | (1 << LOCAL_OUT_ZLP));
-
-               /*
-                * Ensure Control Read pre-validation setting is beyond maximum size
-                *  - Control Writes can leave non-zero values in EP_TRANSFER. If
-                *    an EP0 transfer following the Control Write is a Control Read,
-                *    the NET2272 sees the non-zero EP_TRANSFER as an unexpected
-                *    pre-validation count.
-                *  - Setting EP_TRANSFER beyond the maximum EP0 transfer size ensures
-                *    the pre-validation count cannot cause an unexpected validatation
-                */
-               net2272_write(dev, PAGESEL, 0);
-               net2272_write(dev, EP_TRANSFER2, 0xff);
-               net2272_write(dev, EP_TRANSFER1, 0xff);
-               net2272_write(dev, EP_TRANSFER0, 0xff);
-
-               u.raw[0] = net2272_read(dev, SETUP0);
-               u.raw[1] = net2272_read(dev, SETUP1);
-               u.raw[2] = net2272_read(dev, SETUP2);
-               u.raw[3] = net2272_read(dev, SETUP3);
-               u.raw[4] = net2272_read(dev, SETUP4);
-               u.raw[5] = net2272_read(dev, SETUP5);
-               u.raw[6] = net2272_read(dev, SETUP6);
-               u.raw[7] = net2272_read(dev, SETUP7);
-               /*
-                * If you have a big endian cpu make sure le16_to_cpus
-                * performs the proper byte swapping here...
-                */
-               le16_to_cpus(&u.r.wValue);
-               le16_to_cpus(&u.r.wIndex);
-               le16_to_cpus(&u.r.wLength);
-
-               /* ack the irq */
-               net2272_write(dev, IRQSTAT0, 1 << SETUP_PACKET_INTERRUPT);
-               stat ^= (1 << SETUP_PACKET_INTERRUPT);
-
-               /* watch control traffic at the token level, and force
-                * synchronization before letting the status phase happen.
-                */
-               ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0;
-               if (ep->is_in) {
-                       scratch = (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
-                               | (1 << DATA_OUT_TOKEN_INTERRUPT_ENABLE)
-                               | (1 << DATA_IN_TOKEN_INTERRUPT_ENABLE);
-                       stop_out_naking(ep);
-               } else
-                       scratch = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
-                               | (1 << DATA_OUT_TOKEN_INTERRUPT_ENABLE)
-                               | (1 << DATA_IN_TOKEN_INTERRUPT_ENABLE);
-               net2272_ep_write(ep, EP_IRQENB, scratch);
-
-               if ((u.r.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD)
-                       goto delegate;
-               switch (u.r.bRequest) {
-               case USB_REQ_GET_STATUS: {
-                       struct net2272_ep *e;
-                       u16 status = 0;
-
-                       switch (u.r.bRequestType & USB_RECIP_MASK) {
-                       case USB_RECIP_ENDPOINT:
-                               e = net2272_get_ep_by_addr(dev, u.r.wIndex);
-                               if (!e || u.r.wLength > 2)
-                                       goto do_stall;
-                               if (net2272_ep_read(e, EP_RSPSET) & (1 << ENDPOINT_HALT))
-                                       status = __constant_cpu_to_le16(1);
-                               else
-                                       status = __constant_cpu_to_le16(0);
-
-                               /* don't bother with a request object! */
-                               net2272_ep_write(&dev->ep[0], EP_IRQENB, 0);
-                               writew(status, net2272_reg_addr(dev, EP_DATA));
-                               set_fifo_bytecount(&dev->ep[0], 0);
-                               allow_status(ep);
-                               dev_vdbg(dev->dev, "%s stat %02x\n",
-                                       ep->ep.name, status);
-                               goto next_endpoints;
-                       case USB_RECIP_DEVICE:
-                               if (u.r.wLength > 2)
-                                       goto do_stall;
-                               if (dev->is_selfpowered)
-                                       status = (1 << USB_DEVICE_SELF_POWERED);
-
-                               /* don't bother with a request object! */
-                               net2272_ep_write(&dev->ep[0], EP_IRQENB, 0);
-                               writew(status, net2272_reg_addr(dev, EP_DATA));
-                               set_fifo_bytecount(&dev->ep[0], 0);
-                               allow_status(ep);
-                               dev_vdbg(dev->dev, "device stat %02x\n", status);
-                               goto next_endpoints;
-                       case USB_RECIP_INTERFACE:
-                               if (u.r.wLength > 2)
-                                       goto do_stall;
-
-                               /* don't bother with a request object! */
-                               net2272_ep_write(&dev->ep[0], EP_IRQENB, 0);
-                               writew(status, net2272_reg_addr(dev, EP_DATA));
-                               set_fifo_bytecount(&dev->ep[0], 0);
-                               allow_status(ep);
-                               dev_vdbg(dev->dev, "interface status %02x\n", status);
-                               goto next_endpoints;
-                       }
-
-                       break;
-               }
-               case USB_REQ_CLEAR_FEATURE: {
-                       struct net2272_ep *e;
-
-                       if (u.r.bRequestType != USB_RECIP_ENDPOINT)
-                               goto delegate;
-                       if (u.r.wValue != USB_ENDPOINT_HALT ||
-                           u.r.wLength != 0)
-                               goto do_stall;
-                       e = net2272_get_ep_by_addr(dev, u.r.wIndex);
-                       if (!e)
-                               goto do_stall;
-                       if (e->wedged) {
-                               dev_vdbg(dev->dev, "%s wedged, halt not cleared\n",
-                                       ep->ep.name);
-                       } else {
-                               dev_vdbg(dev->dev, "%s clear halt\n", ep->ep.name);
-                               clear_halt(e);
-                       }
-                       allow_status(ep);
-                       goto next_endpoints;
-               }
-               case USB_REQ_SET_FEATURE: {
-                       struct net2272_ep *e;
-
-                       if (u.r.bRequestType == USB_RECIP_DEVICE) {
-                               if (u.r.wIndex != NORMAL_OPERATION)
-                                       net2272_set_test_mode(dev, (u.r.wIndex >> 8));
-                               allow_status(ep);
-                               dev_vdbg(dev->dev, "test mode: %d\n", u.r.wIndex);
-                               goto next_endpoints;
-                       } else if (u.r.bRequestType != USB_RECIP_ENDPOINT)
-                               goto delegate;
-                       if (u.r.wValue != USB_ENDPOINT_HALT ||
-                           u.r.wLength != 0)
-                               goto do_stall;
-                       e = net2272_get_ep_by_addr(dev, u.r.wIndex);
-                       if (!e)
-                               goto do_stall;
-                       set_halt(e);
-                       allow_status(ep);
-                       dev_vdbg(dev->dev, "%s set halt\n", ep->ep.name);
-                       goto next_endpoints;
-               }
-               case USB_REQ_SET_ADDRESS: {
-                       net2272_write(dev, OURADDR, u.r.wValue & 0xff);
-                       allow_status(ep);
-                       break;
-               }
-               default:
- delegate:
-                       dev_vdbg(dev->dev, "setup %02x.%02x v%04x i%04x "
-                               "ep_cfg %08x\n",
-                               u.r.bRequestType, u.r.bRequest,
-                               u.r.wValue, u.r.wIndex,
-                               net2272_ep_read(ep, EP_CFG));
-                       spin_unlock(&dev->lock);
-                       tmp = dev->driver->setup(&dev->gadget, &u.r);
-                       spin_lock(&dev->lock);
-               }
-
-               /* stall ep0 on error */
-               if (tmp < 0) {
- do_stall:
-                       dev_vdbg(dev->dev, "req %02x.%02x protocol STALL; stat %d\n",
-                               u.r.bRequestType, u.r.bRequest, tmp);
-                       dev->protocol_stall = 1;
-               }
-       /* endpoint dma irq? */
-       } else if (stat & (1 << DMA_DONE_INTERRUPT)) {
-               net2272_cancel_dma(dev);
-               net2272_write(dev, IRQSTAT0, 1 << DMA_DONE_INTERRUPT);
-               stat &= ~(1 << DMA_DONE_INTERRUPT);
-               num = (net2272_read(dev, DMAREQ) & (1 << DMA_ENDPOINT_SELECT))
-                       ? 2 : 1;
-
-               ep = &dev->ep[num];
-               net2272_handle_dma(ep);
-       }
-
- next_endpoints:
-       /* endpoint data irq? */
-       scratch = stat & 0x0f;
-       stat &= ~0x0f;
-       for (num = 0; scratch; num++) {
-               u8 t;
-
-               /* does this endpoint's FIFO and queue need tending? */
-               t = 1 << num;
-               if ((scratch & t) == 0)
-                       continue;
-               scratch ^= t;
-
-               ep = &dev->ep[num];
-               net2272_handle_ep(ep);
-       }
-
-       /* some interrupts we can just ignore */
-       stat &= ~(1 << SOF_INTERRUPT);
-
-       if (stat)
-               dev_dbg(dev->dev, "unhandled irqstat0 %02x\n", stat);
-}
-
-static void
-net2272_handle_stat1_irqs(struct net2272 *dev, u8 stat)
-{
-       u8 tmp, mask;
-
-       /* after disconnect there's nothing else to do! */
-       tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT);
-       mask = (1 << USB_HIGH_SPEED) | (1 << USB_FULL_SPEED);
-
-       if (stat & tmp) {
-               net2272_write(dev, IRQSTAT1, tmp);
-               if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) &&
-                               ((net2272_read(dev, USBCTL1) & mask) == 0))
-                       || ((net2272_read(dev, USBCTL1) & (1 << VBUS_PIN))
-                               == 0))
-                               && (dev->gadget.speed != USB_SPEED_UNKNOWN)) {
-                       dev_dbg(dev->dev, "disconnect %s\n",
-                               dev->driver->driver.name);
-                       stop_activity(dev, dev->driver);
-                       net2272_ep0_start(dev);
-                       return;
-               }
-               stat &= ~tmp;
-
-               if (!stat)
-                       return;
-       }
-
-       tmp = (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT);
-       if (stat & tmp) {
-               net2272_write(dev, IRQSTAT1, tmp);
-               if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
-                       if (dev->driver->suspend)
-                               dev->driver->suspend(&dev->gadget);
-                       if (!enable_suspend) {
-                               stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
-                               dev_dbg(dev->dev, "Suspend disabled, ignoring\n");
-                       }
-               } else {
-                       if (dev->driver->resume)
-                               dev->driver->resume(&dev->gadget);
-               }
-               stat &= ~tmp;
-       }
-
-       /* clear any other status/irqs */
-       if (stat)
-               net2272_write(dev, IRQSTAT1, stat);
-
-       /* some status we can just ignore */
-       stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
-                       | (1 << SUSPEND_REQUEST_INTERRUPT)
-                       | (1 << RESUME_INTERRUPT));
-       if (!stat)
-               return;
-       else
-               dev_dbg(dev->dev, "unhandled irqstat1 %02x\n", stat);
-}
-
-static irqreturn_t net2272_irq(int irq, void *_dev)
-{
-       struct net2272 *dev = _dev;
-#if defined(PLX_PCI_RDK) || defined(PLX_PCI_RDK2)
-       u32 intcsr;
-#endif
-#if defined(PLX_PCI_RDK)
-       u8 dmareq;
-#endif
-       spin_lock(&dev->lock);
-#if defined(PLX_PCI_RDK)
-       intcsr = readl(dev->rdk1.plx9054_base_addr + INTCSR);
-
-       if ((intcsr & LOCAL_INTERRUPT_TEST) == LOCAL_INTERRUPT_TEST) {
-               writel(intcsr & ~(1 << PCI_INTERRUPT_ENABLE),
-                               dev->rdk1.plx9054_base_addr + INTCSR);
-               net2272_handle_stat1_irqs(dev, net2272_read(dev, IRQSTAT1));
-               net2272_handle_stat0_irqs(dev, net2272_read(dev, IRQSTAT0));
-               intcsr = readl(dev->rdk1.plx9054_base_addr + INTCSR);
-               writel(intcsr | (1 << PCI_INTERRUPT_ENABLE),
-                       dev->rdk1.plx9054_base_addr + INTCSR);
-       }
-       if ((intcsr & DMA_CHANNEL_0_TEST) == DMA_CHANNEL_0_TEST) {
-               writeb((1 << CHANNEL_CLEAR_INTERRUPT | (0 << CHANNEL_ENABLE)),
-                               dev->rdk1.plx9054_base_addr + DMACSR0);
-
-               dmareq = net2272_read(dev, DMAREQ);
-               if (dmareq & 0x01)
-                       net2272_handle_dma(&dev->ep[2]);
-               else
-                       net2272_handle_dma(&dev->ep[1]);
-       }
-#endif
-#if defined(PLX_PCI_RDK2)
-       /* see if PCI int for us by checking irqstat */
-       intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT);
-       if (!intcsr & (1 << NET2272_PCI_IRQ)) {
-               spin_unlock(&dev->lock);
-               return IRQ_NONE;
-       }
-       /* check dma interrupts */
-#endif
-       /* Platform/devcice interrupt handler */
-#if !defined(PLX_PCI_RDK)
-       net2272_handle_stat1_irqs(dev, net2272_read(dev, IRQSTAT1));
-       net2272_handle_stat0_irqs(dev, net2272_read(dev, IRQSTAT0));
-#endif
-       spin_unlock(&dev->lock);
-
-       return IRQ_HANDLED;
-}
-
-static int net2272_present(struct net2272 *dev)
-{
-       /*
-        * Quick test to see if CPU can communicate properly with the NET2272.
-        * Verifies connection using writes and reads to write/read and
-        * read-only registers.
-        *
-        * This routine is strongly recommended especially during early bring-up
-        * of new hardware, however for designs that do not apply Power On System
-        * Tests (POST) it may discarded (or perhaps minimized).
-        */
-       unsigned int ii;
-       u8 val, refval;
-
-       /* Verify NET2272 write/read SCRATCH register can write and read */
-       refval = net2272_read(dev, SCRATCH);
-       for (ii = 0; ii < 0x100; ii += 7) {
-               net2272_write(dev, SCRATCH, ii);
-               val = net2272_read(dev, SCRATCH);
-               if (val != ii) {
-                       dev_dbg(dev->dev,
-                               "%s: write/read SCRATCH register test failed: "
-                               "wrote:0x%2.2x, read:0x%2.2x\n",
-                               __func__, ii, val);
-                       return -EINVAL;
-               }
-       }
-       /* To be nice, we write the original SCRATCH value back: */
-       net2272_write(dev, SCRATCH, refval);
-
-       /* Verify NET2272 CHIPREV register is read-only: */
-       refval = net2272_read(dev, CHIPREV_2272);
-       for (ii = 0; ii < 0x100; ii += 7) {
-               net2272_write(dev, CHIPREV_2272, ii);
-               val = net2272_read(dev, CHIPREV_2272);
-               if (val != refval) {
-                       dev_dbg(dev->dev,
-                               "%s: write/read CHIPREV register test failed: "
-                               "wrote 0x%2.2x, read:0x%2.2x expected:0x%2.2x\n",
-                               __func__, ii, val, refval);
-                       return -EINVAL;
-               }
-       }
-
-       /*
-        * Verify NET2272's "NET2270 legacy revision" register
-        *  - NET2272 has two revision registers. The NET2270 legacy revision
-        *    register should read the same value, regardless of the NET2272
-        *    silicon revision.  The legacy register applies to NET2270
-        *    firmware being applied to the NET2272.
-        */
-       val = net2272_read(dev, CHIPREV_LEGACY);
-       if (val != NET2270_LEGACY_REV) {
-               /*
-                * Unexpected legacy revision value
-                * - Perhaps the chip is a NET2270?
-                */
-               dev_dbg(dev->dev,
-                       "%s: WARNING: UNEXPECTED NET2272 LEGACY REGISTER VALUE:\n"
-                       " - CHIPREV_LEGACY: expected 0x%2.2x, got:0x%2.2x. (Not NET2272?)\n",
-                       __func__, NET2270_LEGACY_REV, val);
-               return -EINVAL;
-       }
-
-       /*
-        * Verify NET2272 silicon revision
-        *  - This revision register is appropriate for the silicon version
-        *    of the NET2272
-        */
-       val = net2272_read(dev, CHIPREV_2272);
-       switch (val) {
-       case CHIPREV_NET2272_R1:
-               /*
-                * NET2272 Rev 1 has DMA related errata:
-                *  - Newer silicon (Rev 1A or better) required
-                */
-               dev_dbg(dev->dev,
-                       "%s: Rev 1 detected: newer silicon recommended for DMA support\n",
-                       __func__);
-               break;
-       case CHIPREV_NET2272_R1A:
-               break;
-       default:
-               /* NET2272 silicon version *may* not work with this firmware */
-               dev_dbg(dev->dev,
-                       "%s: unexpected silicon revision register value: "
-                       " CHIPREV_2272: 0x%2.2x\n",
-                       __func__, val);
-               /*
-                * Return Success, even though the chip rev is not an expected value
-                *  - Older, pre-built firmware can attempt to operate on newer silicon
-                *  - Often, new silicon is perfectly compatible
-                */
-       }
-
-       /* Success: NET2272 checks out OK */
-       return 0;
-}
-
-static void
-net2272_gadget_release(struct device *_dev)
-{
-       struct net2272 *dev = dev_get_drvdata(_dev);
-       kfree(dev);
-}
-
-/*---------------------------------------------------------------------------*/
-
-static void
-net2272_remove(struct net2272 *dev)
-{
-       usb_del_gadget_udc(&dev->gadget);
-
-       /* start with the driver above us */
-       if (dev->driver) {
-               /* should have been done already by driver model core */
-               dev_warn(dev->dev, "pci remove, driver '%s' is still registered\n",
-                       dev->driver->driver.name);
-               usb_gadget_unregister_driver(dev->driver);
-       }
-
-       free_irq(dev->irq, dev);
-       iounmap(dev->base_addr);
-
-       device_remove_file(dev->dev, &dev_attr_registers);
-
-       dev_info(dev->dev, "unbind\n");
-}
-
-static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq)
-{
-       struct net2272 *ret;
-
-       if (!irq) {
-               dev_dbg(dev, "No IRQ!\n");
-               return ERR_PTR(-ENODEV);
-       }
-
-       /* alloc, and start init */
-       ret = kzalloc(sizeof(*ret), GFP_KERNEL);
-       if (!ret)
-               return ERR_PTR(-ENOMEM);
-
-       spin_lock_init(&ret->lock);
-       ret->irq = irq;
-       ret->dev = dev;
-       ret->gadget.ops = &net2272_ops;
-       ret->gadget.max_speed = USB_SPEED_HIGH;
-
-       /* the "gadget" abstracts/virtualizes the controller */
-       ret->gadget.name = driver_name;
-
-       return ret;
-}
-
-static int
-net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
-{
-       int ret;
-
-       /* See if there... */
-       if (net2272_present(dev)) {
-               dev_warn(dev->dev, "2272 not found!\n");
-               ret = -ENODEV;
-               goto err;
-       }
-
-       net2272_usb_reset(dev);
-       net2272_usb_reinit(dev);
-
-       ret = request_irq(dev->irq, net2272_irq, irqflags, driver_name, dev);
-       if (ret) {
-               dev_err(dev->dev, "request interrupt %i failed\n", dev->irq);
-               goto err;
-       }
-
-       dev->chiprev = net2272_read(dev, CHIPREV_2272);
-
-       /* done */
-       dev_info(dev->dev, "%s\n", driver_desc);
-       dev_info(dev->dev, "irq %i, mem %p, chip rev %04x, dma %s\n",
-               dev->irq, dev->base_addr, dev->chiprev,
-               dma_mode_string());
-       dev_info(dev->dev, "version: %s\n", driver_vers);
-
-       ret = device_create_file(dev->dev, &dev_attr_registers);
-       if (ret)
-               goto err_irq;
-
-       ret = usb_add_gadget_udc_release(dev->dev, &dev->gadget,
-                       net2272_gadget_release);
-       if (ret)
-               goto err_add_udc;
-
-       return 0;
-
-err_add_udc:
-       device_remove_file(dev->dev, &dev_attr_registers);
- err_irq:
-       free_irq(dev->irq, dev);
- err:
-       return ret;
-}
-
-#ifdef CONFIG_PCI
-
-/*
- * wrap this driver around the specified device, but
- * don't respond over USB until a gadget driver binds to us
- */
-
-static int
-net2272_rdk1_probe(struct pci_dev *pdev, struct net2272 *dev)
-{
-       unsigned long resource, len, tmp;
-       void __iomem *mem_mapped_addr[4];
-       int ret, i;
-
-       /*
-        * BAR 0 holds PLX 9054 config registers
-        * BAR 1 is i/o memory; unused here
-        * BAR 2 holds EPLD config registers
-        * BAR 3 holds NET2272 registers
-        */
-
-       /* Find and map all address spaces */
-       for (i = 0; i < 4; ++i) {
-               if (i == 1)
-                       continue;       /* BAR1 unused */
-
-               resource = pci_resource_start(pdev, i);
-               len = pci_resource_len(pdev, i);
-
-               if (!request_mem_region(resource, len, driver_name)) {
-                       dev_dbg(dev->dev, "controller already in use\n");
-                       ret = -EBUSY;
-                       goto err;
-               }
-
-               mem_mapped_addr[i] = ioremap_nocache(resource, len);
-               if (mem_mapped_addr[i] == NULL) {
-                       release_mem_region(resource, len);
-                       dev_dbg(dev->dev, "can't map memory\n");
-                       ret = -EFAULT;
-                       goto err;
-               }
-       }
-
-       dev->rdk1.plx9054_base_addr = mem_mapped_addr[0];
-       dev->rdk1.epld_base_addr = mem_mapped_addr[2];
-       dev->base_addr = mem_mapped_addr[3];
-
-       /* Set PLX 9054 bus width (16 bits) */
-       tmp = readl(dev->rdk1.plx9054_base_addr + LBRD1);
-       writel((tmp & ~(3 << MEMORY_SPACE_LOCAL_BUS_WIDTH)) | W16_BIT,
-                       dev->rdk1.plx9054_base_addr + LBRD1);
-
-       /* Enable PLX 9054 Interrupts */
-       writel(readl(dev->rdk1.plx9054_base_addr + INTCSR) |
-                       (1 << PCI_INTERRUPT_ENABLE) |
-                       (1 << LOCAL_INTERRUPT_INPUT_ENABLE),
-                       dev->rdk1.plx9054_base_addr + INTCSR);
-
-       writeb((1 << CHANNEL_CLEAR_INTERRUPT | (0 << CHANNEL_ENABLE)),
-                       dev->rdk1.plx9054_base_addr + DMACSR0);
-
-       /* reset */
-       writeb((1 << EPLD_DMA_ENABLE) |
-               (1 << DMA_CTL_DACK) |
-               (1 << DMA_TIMEOUT_ENABLE) |
-               (1 << USER) |
-               (0 << MPX_MODE) |
-               (1 << BUSWIDTH) |
-               (1 << NET2272_RESET),
-               dev->base_addr + EPLD_IO_CONTROL_REGISTER);
-
-       mb();
-       writeb(readb(dev->base_addr + EPLD_IO_CONTROL_REGISTER) &
-               ~(1 << NET2272_RESET),
-               dev->base_addr + EPLD_IO_CONTROL_REGISTER);
-       udelay(200);
-
-       return 0;
-
- err:
-       while (--i >= 0) {
-               iounmap(mem_mapped_addr[i]);
-               release_mem_region(pci_resource_start(pdev, i),
-                       pci_resource_len(pdev, i));
-       }
-
-       return ret;
-}
-
-static int
-net2272_rdk2_probe(struct pci_dev *pdev, struct net2272 *dev)
-{
-       unsigned long resource, len;
-       void __iomem *mem_mapped_addr[2];
-       int ret, i;
-
-       /*
-        * BAR 0 holds FGPA config registers
-        * BAR 1 holds NET2272 registers
-        */
-
-       /* Find and map all address spaces, bar2-3 unused in rdk 2 */
-       for (i = 0; i < 2; ++i) {
-               resource = pci_resource_start(pdev, i);
-               len = pci_resource_len(pdev, i);
-
-               if (!request_mem_region(resource, len, driver_name)) {
-                       dev_dbg(dev->dev, "controller already in use\n");
-                       ret = -EBUSY;
-                       goto err;
-               }
-
-               mem_mapped_addr[i] = ioremap_nocache(resource, len);
-               if (mem_mapped_addr[i] == NULL) {
-                       release_mem_region(resource, len);
-                       dev_dbg(dev->dev, "can't map memory\n");
-                       ret = -EFAULT;
-                       goto err;
-               }
-       }
-
-       dev->rdk2.fpga_base_addr = mem_mapped_addr[0];
-       dev->base_addr = mem_mapped_addr[1];
-
-       mb();
-       /* Set 2272 bus width (16 bits) and reset */
-       writel((1 << CHIP_RESET), dev->rdk2.fpga_base_addr + RDK2_LOCCTLRDK);
-       udelay(200);
-       writel((1 << BUS_WIDTH), dev->rdk2.fpga_base_addr + RDK2_LOCCTLRDK);
-       /* Print fpga version number */
-       dev_info(dev->dev, "RDK2 FPGA version %08x\n",
-               readl(dev->rdk2.fpga_base_addr + RDK2_FPGAREV));
-       /* Enable FPGA Interrupts */
-       writel((1 << NET2272_PCI_IRQ), dev->rdk2.fpga_base_addr + RDK2_IRQENB);
-
-       return 0;
-
- err:
-       while (--i >= 0) {
-               iounmap(mem_mapped_addr[i]);
-               release_mem_region(pci_resource_start(pdev, i),
-                       pci_resource_len(pdev, i));
-       }
-
-       return ret;
-}
-
-static int
-net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-       struct net2272 *dev;
-       int ret;
-
-       dev = net2272_probe_init(&pdev->dev, pdev->irq);
-       if (IS_ERR(dev))
-               return PTR_ERR(dev);
-       dev->dev_id = pdev->device;
-
-       if (pci_enable_device(pdev) < 0) {
-               ret = -ENODEV;
-               goto err_free;
-       }
-
-       pci_set_master(pdev);
-
-       switch (pdev->device) {
-       case PCI_DEVICE_ID_RDK1: ret = net2272_rdk1_probe(pdev, dev); break;
-       case PCI_DEVICE_ID_RDK2: ret = net2272_rdk2_probe(pdev, dev); break;
-       default: BUG();
-       }
-       if (ret)
-               goto err_pci;
-
-       ret = net2272_probe_fin(dev, 0);
-       if (ret)
-               goto err_pci;
-
-       pci_set_drvdata(pdev, dev);
-
-       return 0;
-
- err_pci:
-       pci_disable_device(pdev);
- err_free:
-       kfree(dev);
-
-       return ret;
-}
-
-static void
-net2272_rdk1_remove(struct pci_dev *pdev, struct net2272 *dev)
-{
-       int i;
-
-       /* disable PLX 9054 interrupts */
-       writel(readl(dev->rdk1.plx9054_base_addr + INTCSR) &
-               ~(1 << PCI_INTERRUPT_ENABLE),
-               dev->rdk1.plx9054_base_addr + INTCSR);
-
-       /* clean up resources allocated during probe() */
-       iounmap(dev->rdk1.plx9054_base_addr);
-       iounmap(dev->rdk1.epld_base_addr);
-
-       for (i = 0; i < 4; ++i) {
-               if (i == 1)
-                       continue;       /* BAR1 unused */
-               release_mem_region(pci_resource_start(pdev, i),
-                       pci_resource_len(pdev, i));
-       }
-}
-
-static void
-net2272_rdk2_remove(struct pci_dev *pdev, struct net2272 *dev)
-{
-       int i;
-
-       /* disable fpga interrupts
-       writel(readl(dev->rdk1.plx9054_base_addr + INTCSR) &
-                       ~(1 << PCI_INTERRUPT_ENABLE),
-                       dev->rdk1.plx9054_base_addr + INTCSR);
-       */
-
-       /* clean up resources allocated during probe() */
-       iounmap(dev->rdk2.fpga_base_addr);
-
-       for (i = 0; i < 2; ++i)
-               release_mem_region(pci_resource_start(pdev, i),
-                       pci_resource_len(pdev, i));
-}
-
-static void
-net2272_pci_remove(struct pci_dev *pdev)
-{
-       struct net2272 *dev = pci_get_drvdata(pdev);
-
-       net2272_remove(dev);
-
-       switch (pdev->device) {
-       case PCI_DEVICE_ID_RDK1: net2272_rdk1_remove(pdev, dev); break;
-       case PCI_DEVICE_ID_RDK2: net2272_rdk2_remove(pdev, dev); break;
-       default: BUG();
-       }
-
-       pci_disable_device(pdev);
-
-       kfree(dev);
-}
-
-/* Table of matching PCI IDs */
-static struct pci_device_id pci_ids[] = {
-       {       /* RDK 1 card */
-               .class       = ((PCI_CLASS_BRIDGE_OTHER << 8) | 0xfe),
-               .class_mask  = 0,
-               .vendor      = PCI_VENDOR_ID_PLX,
-               .device      = PCI_DEVICE_ID_RDK1,
-               .subvendor   = PCI_ANY_ID,
-               .subdevice   = PCI_ANY_ID,
-       },
-       {       /* RDK 2 card */
-               .class       = ((PCI_CLASS_BRIDGE_OTHER << 8) | 0xfe),
-               .class_mask  = 0,
-               .vendor      = PCI_VENDOR_ID_PLX,
-               .device      = PCI_DEVICE_ID_RDK2,
-               .subvendor   = PCI_ANY_ID,
-               .subdevice   = PCI_ANY_ID,
-       },
-       { }
-};
-MODULE_DEVICE_TABLE(pci, pci_ids);
-
-static struct pci_driver net2272_pci_driver = {
-       .name     = driver_name,
-       .id_table = pci_ids,
-
-       .probe    = net2272_pci_probe,
-       .remove   = net2272_pci_remove,
-};
-
-static int net2272_pci_register(void)
-{
-       return pci_register_driver(&net2272_pci_driver);
-}
-
-static void net2272_pci_unregister(void)
-{
-       pci_unregister_driver(&net2272_pci_driver);
-}
-
-#else
-static inline int net2272_pci_register(void) { return 0; }
-static inline void net2272_pci_unregister(void) { }
-#endif
-
-/*---------------------------------------------------------------------------*/
-
-static int
-net2272_plat_probe(struct platform_device *pdev)
-{
-       struct net2272 *dev;
-       int ret;
-       unsigned int irqflags;
-       resource_size_t base, len;
-       struct resource *iomem, *iomem_bus, *irq_res;
-
-       irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       iomem_bus = platform_get_resource(pdev, IORESOURCE_BUS, 0);
-       if (!irq_res || !iomem) {
-               dev_err(&pdev->dev, "must provide irq/base addr");
-               return -EINVAL;
-       }
-
-       dev = net2272_probe_init(&pdev->dev, irq_res->start);
-       if (IS_ERR(dev))
-               return PTR_ERR(dev);
-
-       irqflags = 0;
-       if (irq_res->flags & IORESOURCE_IRQ_HIGHEDGE)
-               irqflags |= IRQF_TRIGGER_RISING;
-       if (irq_res->flags & IORESOURCE_IRQ_LOWEDGE)
-               irqflags |= IRQF_TRIGGER_FALLING;
-       if (irq_res->flags & IORESOURCE_IRQ_HIGHLEVEL)
-               irqflags |= IRQF_TRIGGER_HIGH;
-       if (irq_res->flags & IORESOURCE_IRQ_LOWLEVEL)
-               irqflags |= IRQF_TRIGGER_LOW;
-
-       base = iomem->start;
-       len = resource_size(iomem);
-       if (iomem_bus)
-               dev->base_shift = iomem_bus->start;
-
-       if (!request_mem_region(base, len, driver_name)) {
-               dev_dbg(dev->dev, "get request memory region!\n");
-               ret = -EBUSY;
-               goto err;
-       }
-       dev->base_addr = ioremap_nocache(base, len);
-       if (!dev->base_addr) {
-               dev_dbg(dev->dev, "can't map memory\n");
-               ret = -EFAULT;
-               goto err_req;
-       }
-
-       ret = net2272_probe_fin(dev, IRQF_TRIGGER_LOW);
-       if (ret)
-               goto err_io;
-
-       platform_set_drvdata(pdev, dev);
-       dev_info(&pdev->dev, "running in 16-bit, %sbyte swap local bus mode\n",
-               (net2272_read(dev, LOCCTL) & (1 << BYTE_SWAP)) ? "" : "no ");
-
-       return 0;
-
- err_io:
-       iounmap(dev->base_addr);
- err_req:
-       release_mem_region(base, len);
- err:
-       return ret;
-}
-
-static int
-net2272_plat_remove(struct platform_device *pdev)
-{
-       struct net2272 *dev = platform_get_drvdata(pdev);
-
-       net2272_remove(dev);
-
-       release_mem_region(pdev->resource[0].start,
-               resource_size(&pdev->resource[0]));
-
-       kfree(dev);
-
-       return 0;
-}
-
-static struct platform_driver net2272_plat_driver = {
-       .probe   = net2272_plat_probe,
-       .remove  = net2272_plat_remove,
-       .driver  = {
-               .name  = driver_name,
-               .owner = THIS_MODULE,
-       },
-       /* FIXME .suspend, .resume */
-};
-MODULE_ALIAS("platform:net2272");
-
-static int __init net2272_init(void)
-{
-       int ret;
-
-       ret = net2272_pci_register();
-       if (ret)
-               return ret;
-       ret = platform_driver_register(&net2272_plat_driver);
-       if (ret)
-               goto err_pci;
-       return ret;
-
-err_pci:
-       net2272_pci_unregister();
-       return ret;
-}
-module_init(net2272_init);
-
-static void __exit net2272_cleanup(void)
-{
-       net2272_pci_unregister();
-       platform_driver_unregister(&net2272_plat_driver);
-}
-module_exit(net2272_cleanup);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("PLX Technology, Inc.");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/net2272.h b/drivers/usb/gadget/net2272.h
deleted file mode 100644 (file)
index e595057..0000000
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * PLX NET2272 high/full speed USB device controller
- *
- * Copyright (C) 2005-2006 PLX Technology, Inc.
- * Copyright (C) 2006-2011 Analog Devices, Inc.
- *
- * 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
- */
-
-#ifndef __NET2272_H__
-#define __NET2272_H__
-
-/* Main Registers */
-#define REGADDRPTR                     0x00
-#define REGDATA                                0x01
-#define IRQSTAT0                       0x02
-#define        ENDPOINT_0_INTERRUPT                    0
-#define        ENDPOINT_A_INTERRUPT                    1
-#define        ENDPOINT_B_INTERRUPT                    2
-#define        ENDPOINT_C_INTERRUPT                    3
-#define        VIRTUALIZED_ENDPOINT_INTERRUPT          4
-#define        SETUP_PACKET_INTERRUPT                  5
-#define        DMA_DONE_INTERRUPT                      6
-#define        SOF_INTERRUPT                           7
-#define IRQSTAT1                       0x03
-#define        CONTROL_STATUS_INTERRUPT                1
-#define        VBUS_INTERRUPT                          2
-#define        SUSPEND_REQUEST_INTERRUPT               3
-#define        SUSPEND_REQUEST_CHANGE_INTERRUPT        4
-#define        RESUME_INTERRUPT                        5
-#define        ROOT_PORT_RESET_INTERRUPT               6
-#define        RESET_STATUS                            7
-#define PAGESEL                                0x04
-#define DMAREQ                         0x1c
-#define        DMA_ENDPOINT_SELECT                     0
-#define        DREQ_POLARITY                           1
-#define        DACK_POLARITY                           2
-#define        EOT_POLARITY                            3
-#define        DMA_CONTROL_DACK                        4
-#define        DMA_REQUEST_ENABLE                      5
-#define        DMA_REQUEST                             6
-#define        DMA_BUFFER_VALID                        7
-#define SCRATCH                                0x1d
-#define IRQENB0                                0x20
-#define        ENDPOINT_0_INTERRUPT_ENABLE             0
-#define        ENDPOINT_A_INTERRUPT_ENABLE             1
-#define        ENDPOINT_B_INTERRUPT_ENABLE             2
-#define        ENDPOINT_C_INTERRUPT_ENABLE             3
-#define        VIRTUALIZED_ENDPOINT_INTERRUPT_ENABLE   4
-#define        SETUP_PACKET_INTERRUPT_ENABLE           5
-#define        DMA_DONE_INTERRUPT_ENABLE               6
-#define        SOF_INTERRUPT_ENABLE                    7
-#define IRQENB1                                0x21
-#define        VBUS_INTERRUPT_ENABLE                   2
-#define        SUSPEND_REQUEST_INTERRUPT_ENABLE        3
-#define        SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 4
-#define        RESUME_INTERRUPT_ENABLE                 5
-#define        ROOT_PORT_RESET_INTERRUPT_ENABLE        6
-#define LOCCTL                         0x22
-#define        DATA_WIDTH                              0
-#define        LOCAL_CLOCK_OUTPUT                      1
-#define                LOCAL_CLOCK_OUTPUT_OFF                  0
-#define                LOCAL_CLOCK_OUTPUT_3_75MHZ              1
-#define                LOCAL_CLOCK_OUTPUT_7_5MHZ               2
-#define                LOCAL_CLOCK_OUTPUT_15MHZ                3
-#define                LOCAL_CLOCK_OUTPUT_30MHZ                4
-#define                LOCAL_CLOCK_OUTPUT_60MHZ                5
-#define        DMA_SPLIT_BUS_MODE                      4
-#define        BYTE_SWAP                               5
-#define        BUFFER_CONFIGURATION                    6
-#define                BUFFER_CONFIGURATION_EPA512_EPB512      0
-#define                BUFFER_CONFIGURATION_EPA1024_EPB512     1
-#define                BUFFER_CONFIGURATION_EPA1024_EPB1024    2
-#define                BUFFER_CONFIGURATION_EPA1024DB          3
-#define CHIPREV_LEGACY                 0x23
-#define                NET2270_LEGACY_REV                      0x40
-#define LOCCTL1                                0x24
-#define        DMA_MODE                                0
-#define                SLOW_DREQ                               0
-#define                FAST_DREQ                               1
-#define                BURST_MODE                              2
-#define        DMA_DACK_ENABLE                         2
-#define CHIPREV_2272                   0x25
-#define                CHIPREV_NET2272_R1                      0x10
-#define                CHIPREV_NET2272_R1A                     0x11
-/* USB Registers */
-#define USBCTL0                                0x18
-#define        IO_WAKEUP_ENABLE                        1
-#define        USB_DETECT_ENABLE                       3
-#define        USB_ROOT_PORT_WAKEUP_ENABLE             5
-#define USBCTL1                                0x19
-#define        VBUS_PIN                                0
-#define                USB_FULL_SPEED                          1
-#define                USB_HIGH_SPEED                          2
-#define        GENERATE_RESUME                         3
-#define        VIRTUAL_ENDPOINT_ENABLE                 4
-#define FRAME0                         0x1a
-#define FRAME1                         0x1b
-#define OURADDR                                0x30
-#define        FORCE_IMMEDIATE                         7
-#define USBDIAG                                0x31
-#define        FORCE_TRANSMIT_CRC_ERROR                0
-#define        PREVENT_TRANSMIT_BIT_STUFF              1
-#define        FORCE_RECEIVE_ERROR                     2
-#define        FAST_TIMES                              4
-#define USBTEST                                0x32
-#define        TEST_MODE_SELECT                        0
-#define                NORMAL_OPERATION                        0
-#define                TEST_J                                  1
-#define                TEST_K                                  2
-#define                TEST_SE0_NAK                            3
-#define                TEST_PACKET                             4
-#define                TEST_FORCE_ENABLE                       5
-#define XCVRDIAG                       0x33
-#define        FORCE_FULL_SPEED                        2
-#define        FORCE_HIGH_SPEED                        3
-#define        OPMODE                                  4
-#define                NORMAL_OPERATION                        0
-#define                NON_DRIVING                             1
-#define                DISABLE_BITSTUFF_AND_NRZI_ENCODE        2
-#define        LINESTATE                               6
-#define                SE0_STATE                               0
-#define                J_STATE                                 1
-#define                K_STATE                                 2
-#define                SE1_STATE                               3
-#define VIRTOUT0                       0x34
-#define VIRTOUT1                       0x35
-#define VIRTIN0                                0x36
-#define VIRTIN1                                0x37
-#define SETUP0                         0x40
-#define SETUP1                         0x41
-#define SETUP2                         0x42
-#define SETUP3                         0x43
-#define SETUP4                         0x44
-#define SETUP5                         0x45
-#define SETUP6                         0x46
-#define SETUP7                         0x47
-/* Endpoint Registers (Paged via PAGESEL) */
-#define EP_DATA                                0x05
-#define EP_STAT0                       0x06
-#define        DATA_IN_TOKEN_INTERRUPT                 0
-#define        DATA_OUT_TOKEN_INTERRUPT                1
-#define        DATA_PACKET_TRANSMITTED_INTERRUPT       2
-#define        DATA_PACKET_RECEIVED_INTERRUPT          3
-#define        SHORT_PACKET_TRANSFERRED_INTERRUPT      4
-#define        NAK_OUT_PACKETS                         5
-#define        BUFFER_EMPTY                            6
-#define        BUFFER_FULL                             7
-#define EP_STAT1                       0x07
-#define        TIMEOUT                                 0
-#define        USB_OUT_ACK_SENT                        1
-#define        USB_OUT_NAK_SENT                        2
-#define        USB_IN_ACK_RCVD                         3
-#define        USB_IN_NAK_SENT                         4
-#define        USB_STALL_SENT                          5
-#define        LOCAL_OUT_ZLP                           6
-#define        BUFFER_FLUSH                            7
-#define EP_TRANSFER0                   0x08
-#define EP_TRANSFER1                   0x09
-#define EP_TRANSFER2                   0x0a
-#define EP_IRQENB                      0x0b
-#define        DATA_IN_TOKEN_INTERRUPT_ENABLE          0
-#define        DATA_OUT_TOKEN_INTERRUPT_ENABLE         1
-#define        DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE        2
-#define        DATA_PACKET_RECEIVED_INTERRUPT_ENABLE   3
-#define        SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE       4
-#define EP_AVAIL0                      0x0c
-#define EP_AVAIL1                      0x0d
-#define EP_RSPCLR                      0x0e
-#define EP_RSPSET                      0x0f
-#define        ENDPOINT_HALT                           0
-#define        ENDPOINT_TOGGLE                         1
-#define        NAK_OUT_PACKETS_MODE                    2
-#define        CONTROL_STATUS_PHASE_HANDSHAKE          3
-#define        INTERRUPT_MODE                          4
-#define        AUTOVALIDATE                            5
-#define        HIDE_STATUS_PHASE                       6
-#define        ALT_NAK_OUT_PACKETS                     7
-#define EP_MAXPKT0                     0x28
-#define EP_MAXPKT1                     0x29
-#define        ADDITIONAL_TRANSACTION_OPPORTUNITIES    3
-#define                NONE_ADDITIONAL_TRANSACTION             0
-#define                ONE_ADDITIONAL_TRANSACTION              1
-#define                TWO_ADDITIONAL_TRANSACTION              2
-#define EP_CFG                         0x2a
-#define        ENDPOINT_NUMBER                         0
-#define        ENDPOINT_DIRECTION                      4
-#define        ENDPOINT_TYPE                           5
-#define        ENDPOINT_ENABLE                         7
-#define EP_HBW                         0x2b
-#define        HIGH_BANDWIDTH_OUT_TRANSACTION_PID      0
-#define                DATA0_PID                               0
-#define                DATA1_PID                               1
-#define                DATA2_PID                               2
-#define                MDATA_PID                               3
-#define EP_BUFF_STATES                 0x2c
-#define        BUFFER_A_STATE                          0
-#define        BUFFER_B_STATE                          2
-#define                BUFF_FREE                               0
-#define                BUFF_VALID                              1
-#define                BUFF_LCL                                2
-#define                BUFF_USB                                3
-
-/*---------------------------------------------------------------------------*/
-
-#define PCI_DEVICE_ID_RDK1     0x9054
-
-/* PCI-RDK EPLD Registers */
-#define RDK_EPLD_IO_REGISTER1          0x00000000
-#define        RDK_EPLD_USB_RESET                              0
-#define        RDK_EPLD_USB_POWERDOWN                          1
-#define        RDK_EPLD_USB_WAKEUP                             2
-#define        RDK_EPLD_USB_EOT                                3
-#define        RDK_EPLD_DPPULL                                 4
-#define RDK_EPLD_IO_REGISTER2          0x00000004
-#define        RDK_EPLD_BUSWIDTH                               0
-#define        RDK_EPLD_USER                                   2
-#define        RDK_EPLD_RESET_INTERRUPT_ENABLE                 3
-#define        RDK_EPLD_DMA_TIMEOUT_ENABLE                     4
-#define RDK_EPLD_STATUS_REGISTER       0x00000008
-#define        RDK_EPLD_USB_LRESET                             0
-#define RDK_EPLD_REVISION_REGISTER     0x0000000c
-
-/* PCI-RDK PLX 9054 Registers */
-#define INTCSR                         0x68
-#define        PCI_INTERRUPT_ENABLE                            8
-#define        LOCAL_INTERRUPT_INPUT_ENABLE                    11
-#define        LOCAL_INPUT_INTERRUPT_ACTIVE                    15
-#define        LOCAL_DMA_CHANNEL_0_INTERRUPT_ENABLE            18
-#define        LOCAL_DMA_CHANNEL_1_INTERRUPT_ENABLE            19
-#define        DMA_CHANNEL_0_INTERRUPT_ACTIVE                  21
-#define        DMA_CHANNEL_1_INTERRUPT_ACTIVE                  22
-#define CNTRL                          0x6C
-#define        RELOAD_CONFIGURATION_REGISTERS                  29
-#define        PCI_ADAPTER_SOFTWARE_RESET                      30
-#define DMAMODE0                       0x80
-#define        LOCAL_BUS_WIDTH                                 0
-#define        INTERNAL_WAIT_STATES                            2
-#define        TA_READY_INPUT_ENABLE                           6
-#define        LOCAL_BURST_ENABLE                              8
-#define        SCATTER_GATHER_MODE                             9
-#define        DONE_INTERRUPT_ENABLE                           10
-#define        LOCAL_ADDRESSING_MODE                           11
-#define        DEMAND_MODE                                     12
-#define        DMA_EOT_ENABLE                                  14
-#define        FAST_SLOW_TERMINATE_MODE_SELECT                 15
-#define        DMA_CHANNEL_INTERRUPT_SELECT                    17
-#define DMAPADR0                       0x84
-#define DMALADR0                       0x88
-#define DMASIZ0                                0x8c
-#define DMADPR0                                0x90
-#define        DESCRIPTOR_LOCATION                             0
-#define        END_OF_CHAIN                                    1
-#define        INTERRUPT_AFTER_TERMINAL_COUNT                  2
-#define        DIRECTION_OF_TRANSFER                           3
-#define DMACSR0                                0xa8
-#define        CHANNEL_ENABLE                                  0
-#define        CHANNEL_START                                   1
-#define        CHANNEL_ABORT                                   2
-#define        CHANNEL_CLEAR_INTERRUPT                         3
-#define        CHANNEL_DONE                                    4
-#define DMATHR                         0xb0
-#define LBRD1                          0xf8
-#define        MEMORY_SPACE_LOCAL_BUS_WIDTH                    0
-#define        W8_BIT                                          0
-#define        W16_BIT                                         1
-
-/* Special OR'ing of INTCSR bits */
-#define LOCAL_INTERRUPT_TEST \
-       ((1 << LOCAL_INPUT_INTERRUPT_ACTIVE) | \
-        (1 << LOCAL_INTERRUPT_INPUT_ENABLE))
-
-#define DMA_CHANNEL_0_TEST \
-       ((1 << DMA_CHANNEL_0_INTERRUPT_ACTIVE) | \
-        (1 << LOCAL_DMA_CHANNEL_0_INTERRUPT_ENABLE))
-
-#define DMA_CHANNEL_1_TEST \
-       ((1 << DMA_CHANNEL_1_INTERRUPT_ACTIVE) | \
-        (1 << LOCAL_DMA_CHANNEL_1_INTERRUPT_ENABLE))
-
-/* EPLD Registers */
-#define RDK_EPLD_IO_REGISTER1                  0x00000000
-#define        RDK_EPLD_USB_RESET                      0
-#define        RDK_EPLD_USB_POWERDOWN                  1
-#define        RDK_EPLD_USB_WAKEUP                     2
-#define        RDK_EPLD_USB_EOT                        3
-#define        RDK_EPLD_DPPULL                         4
-#define RDK_EPLD_IO_REGISTER2                  0x00000004
-#define        RDK_EPLD_BUSWIDTH                       0
-#define        RDK_EPLD_USER                           2
-#define        RDK_EPLD_RESET_INTERRUPT_ENABLE         3
-#define        RDK_EPLD_DMA_TIMEOUT_ENABLE             4
-#define RDK_EPLD_STATUS_REGISTER               0x00000008
-#define RDK_EPLD_USB_LRESET                            0
-#define RDK_EPLD_REVISION_REGISTER             0x0000000c
-
-#define EPLD_IO_CONTROL_REGISTER               0x400
-#define        NET2272_RESET                           0
-#define        BUSWIDTH                                1
-#define        MPX_MODE                                3
-#define        USER                                    4
-#define        DMA_TIMEOUT_ENABLE                      5
-#define        DMA_CTL_DACK                            6
-#define        EPLD_DMA_ENABLE                         7
-#define EPLD_DMA_CONTROL_REGISTER              0x800
-#define        SPLIT_DMA_MODE                          0
-#define        SPLIT_DMA_DIRECTION                     1
-#define        SPLIT_DMA_ENABLE                        2
-#define        SPLIT_DMA_INTERRUPT_ENABLE              3
-#define        SPLIT_DMA_INTERRUPT                     4
-#define        EPLD_DMA_MODE                           5
-#define        EPLD_DMA_CONTROLLER_ENABLE              7
-#define SPLIT_DMA_ADDRESS_LOW                  0xc00
-#define SPLIT_DMA_ADDRESS_HIGH                 0x1000
-#define SPLIT_DMA_BYTE_COUNT_LOW               0x1400
-#define SPLIT_DMA_BYTE_COUNT_HIGH              0x1800
-#define EPLD_REVISION_REGISTER                 0x1c00
-#define SPLIT_DMA_RAM                          0x4000
-#define DMA_RAM_SIZE                           0x1000
-
-/*---------------------------------------------------------------------------*/
-
-#define PCI_DEVICE_ID_RDK2     0x3272
-
-/* PCI-RDK version 2 registers */
-
-/* Main Control Registers */
-
-#define RDK2_IRQENB                    0x00
-#define RDK2_IRQSTAT                   0x04
-#define        PB7                             23
-#define        PB6                             22
-#define        PB5                             21
-#define        PB4                             20
-#define        PB3                             19
-#define        PB2                             18
-#define        PB1                             17
-#define        PB0                             16
-#define        GP3                             23
-#define        GP2                             23
-#define        GP1                             23
-#define        GP0                             23
-#define        DMA_RETRY_ABORT                 6
-#define        DMA_PAUSE_DONE                  5
-#define        DMA_ABORT_DONE                  4
-#define        DMA_OUT_FIFO_TRANSFER_DONE      3
-#define        DMA_LOCAL_DONE                  2
-#define        DMA_PCI_DONE                    1
-#define        NET2272_PCI_IRQ                 0
-
-#define RDK2_LOCCTLRDK                 0x08
-#define        CHIP_RESET                      3
-#define        SPLIT_DMA                       2
-#define        MULTIPLEX_MODE                  1
-#define        BUS_WIDTH                       0
-
-#define RDK2_GPIOCTL                   0x10
-#define        GP3_OUT_ENABLE                                  7
-#define        GP2_OUT_ENABLE                                  6
-#define        GP1_OUT_ENABLE                                  5
-#define        GP0_OUT_ENABLE                                  4
-#define        GP3_DATA                                        3
-#define        GP2_DATA                                        2
-#define        GP1_DATA                                        1
-#define        GP0_DATA                                        0
-
-#define RDK2_LEDSW                     0x14
-#define        LED3                            27
-#define        LED2                            26
-#define        LED1                            25
-#define        LED0                            24
-#define        PBUTTON                         16
-#define        DIPSW                           0
-
-#define RDK2_DIAG                      0x18
-#define        RDK2_FAST_TIMES                         2
-#define        FORCE_PCI_SERR                          1
-#define        FORCE_PCI_INT                           0
-#define RDK2_FPGAREV                   0x1C
-
-/* Dma Control registers */
-#define RDK2_DMACTL                    0x80
-#define        ADDR_HOLD                               24
-#define        RETRY_COUNT                             16      /* 23:16 */
-#define        FIFO_THRESHOLD                          11      /* 15:11 */
-#define        MEM_WRITE_INVALIDATE                    10
-#define        READ_MULTIPLE                           9
-#define        READ_LINE                               8
-#define        RDK2_DMA_MODE                           6       /* 7:6 */
-#define        CONTROL_DACK                            5
-#define        EOT_ENABLE                              4
-#define        EOT_POLARITY                            3
-#define        DACK_POLARITY                           2
-#define        DREQ_POLARITY                           1
-#define        DMA_ENABLE                              0
-
-#define RDK2_DMASTAT                   0x84
-#define        GATHER_COUNT                            12      /* 14:12 */
-#define        FIFO_COUNT                              6       /* 11:6 */
-#define        FIFO_FLUSH                              5
-#define        FIFO_TRANSFER                           4
-#define        PAUSE_DONE                              3
-#define        ABORT_DONE                              2
-#define        DMA_ABORT                               1
-#define        DMA_START                               0
-
-#define RDK2_DMAPCICOUNT               0x88
-#define        DMA_DIRECTION                           31
-#define        DMA_PCI_BYTE_COUNT                      0       /* 0:23 */
-
-#define RDK2_DMALOCCOUNT               0x8C    /* 0:23 dma local byte count */
-
-#define RDK2_DMAADDR                   0x90    /* 2:31 PCI bus starting address */
-
-/*---------------------------------------------------------------------------*/
-
-#define REG_INDEXED_THRESHOLD  (1 << 5)
-
-/* DRIVER DATA STRUCTURES and UTILITIES */
-struct net2272_ep {
-       struct usb_ep ep;
-       struct net2272 *dev;
-       unsigned long irqs;
-
-       /* analogous to a host-side qh */
-       struct list_head queue;
-       const struct usb_endpoint_descriptor *desc;
-       unsigned num:8,
-                fifo_size:12,
-                stopped:1,
-                wedged:1,
-                is_in:1,
-                is_iso:1,
-                dma:1,
-                not_empty:1;
-};
-
-struct net2272 {
-       /* each device provides one gadget, several endpoints */
-       struct usb_gadget gadget;
-       struct device *dev;
-       unsigned short dev_id;
-
-       spinlock_t lock;
-       struct net2272_ep ep[4];
-       struct usb_gadget_driver *driver;
-       unsigned protocol_stall:1,
-                softconnect:1,
-                is_selfpowered:1,
-                wakeup:1,
-                dma_eot_polarity:1,
-                dma_dack_polarity:1,
-                dma_dreq_polarity:1,
-                dma_busy:1;
-       u16 chiprev;
-       u8 pagesel;
-
-       unsigned int irq;
-       unsigned short fifo_mode;
-
-       unsigned int base_shift;
-       u16 __iomem *base_addr;
-       union {
-#ifdef CONFIG_PCI
-               struct {
-                       void __iomem *plx9054_base_addr;
-                       void __iomem *epld_base_addr;
-               } rdk1;
-               struct {
-                       /* Bar0, Bar1 is base_addr both mem-mapped */
-                       void __iomem *fpga_base_addr;
-               } rdk2;
-#endif
-       };
-};
-
-static void __iomem *
-net2272_reg_addr(struct net2272 *dev, unsigned int reg)
-{
-       return dev->base_addr + (reg << dev->base_shift);
-}
-
-static void
-net2272_write(struct net2272 *dev, unsigned int reg, u8 value)
-{
-       if (reg >= REG_INDEXED_THRESHOLD) {
-               /*
-                * Indexed register; use REGADDRPTR/REGDATA
-                *  - Save and restore REGADDRPTR. This prevents REGADDRPTR from
-                *    changes between other code sections, but it is time consuming.
-                *  - Performance tips: either do not save and restore REGADDRPTR (if it
-                *    is safe) or do save/restore operations only in critical sections.
-               u8 tmp = readb(dev->base_addr + REGADDRPTR);
-                */
-               writeb((u8)reg, net2272_reg_addr(dev, REGADDRPTR));
-               writeb(value, net2272_reg_addr(dev, REGDATA));
-               /* writeb(tmp, net2272_reg_addr(dev, REGADDRPTR)); */
-       } else
-               writeb(value, net2272_reg_addr(dev, reg));
-}
-
-static u8
-net2272_read(struct net2272 *dev, unsigned int reg)
-{
-       u8 ret;
-
-       if (reg >= REG_INDEXED_THRESHOLD) {
-               /*
-                * Indexed register; use REGADDRPTR/REGDATA
-                *  - Save and restore REGADDRPTR. This prevents REGADDRPTR from
-                *    changes between other code sections, but it is time consuming.
-                *  - Performance tips: either do not save and restore REGADDRPTR (if it
-                *    is safe) or do save/restore operations only in critical sections.
-               u8 tmp = readb(dev->base_addr + REGADDRPTR);
-                */
-               writeb((u8)reg, net2272_reg_addr(dev, REGADDRPTR));
-               ret = readb(net2272_reg_addr(dev, REGDATA));
-               /* writeb(tmp, net2272_reg_addr(dev, REGADDRPTR)); */
-       } else
-               ret = readb(net2272_reg_addr(dev, reg));
-
-       return ret;
-}
-
-static void
-net2272_ep_write(struct net2272_ep *ep, unsigned int reg, u8 value)
-{
-       struct net2272 *dev = ep->dev;
-
-       if (dev->pagesel != ep->num) {
-               net2272_write(dev, PAGESEL, ep->num);
-               dev->pagesel = ep->num;
-       }
-       net2272_write(dev, reg, value);
-}
-
-static u8
-net2272_ep_read(struct net2272_ep *ep, unsigned int reg)
-{
-       struct net2272 *dev = ep->dev;
-
-       if (dev->pagesel != ep->num) {
-               net2272_write(dev, PAGESEL, ep->num);
-               dev->pagesel = ep->num;
-       }
-       return net2272_read(dev, reg);
-}
-
-static void allow_status(struct net2272_ep *ep)
-{
-       /* ep0 only */
-       net2272_ep_write(ep, EP_RSPCLR,
-               (1 << CONTROL_STATUS_PHASE_HANDSHAKE) |
-               (1 << ALT_NAK_OUT_PACKETS) |
-               (1 << NAK_OUT_PACKETS_MODE));
-       ep->stopped = 1;
-}
-
-static void set_halt(struct net2272_ep *ep)
-{
-       /* ep0 and bulk/intr endpoints */
-       net2272_ep_write(ep, EP_RSPCLR, 1 << CONTROL_STATUS_PHASE_HANDSHAKE);
-       net2272_ep_write(ep, EP_RSPSET, 1 << ENDPOINT_HALT);
-}
-
-static void clear_halt(struct net2272_ep *ep)
-{
-       /* ep0 and bulk/intr endpoints */
-       net2272_ep_write(ep, EP_RSPCLR,
-               (1 << ENDPOINT_HALT) | (1 << ENDPOINT_TOGGLE));
-}
-
-/* count (<= 4) bytes in the next fifo write will be valid */
-static void set_fifo_bytecount(struct net2272_ep *ep, unsigned count)
-{
-       /* net2272_ep_write will truncate to u8 for us */
-       net2272_ep_write(ep, EP_TRANSFER2, count >> 16);
-       net2272_ep_write(ep, EP_TRANSFER1, count >> 8);
-       net2272_ep_write(ep, EP_TRANSFER0, count);
-}
-
-struct net2272_request {
-       struct usb_request req;
-       struct list_head queue;
-       unsigned mapped:1,
-                valid:1;
-};
-
-#endif
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
deleted file mode 100644 (file)
index 248dccb..0000000
+++ /dev/null
@@ -1,3827 +0,0 @@
-/*
- * Driver for the PLX NET2280 USB device controller.
- * Specs and errata are available from <http://www.plxtech.com>.
- *
- * PLX Technology Inc. (formerly NetChip Technology) supported the
- * development of this driver.
- *
- *
- * CODE STATUS HIGHLIGHTS
- *
- * This driver should work well with most "gadget" drivers, including
- * the Mass Storage, Serial, and Ethernet/RNDIS gadget drivers
- * as well as Gadget Zero and Gadgetfs.
- *
- * DMA is enabled by default.  Drivers using transfer queues might use
- * DMA chaining to remove IRQ latencies between transfers.  (Except when
- * short OUT transfers happen.)  Drivers can use the req->no_interrupt
- * hint to completely eliminate some IRQs, if a later IRQ is guaranteed
- * and DMA chaining is enabled.
- *
- * MSI is enabled by default.  The legacy IRQ is used if MSI couldn't
- * be enabled.
- *
- * Note that almost all the errata workarounds here are only needed for
- * rev1 chips.  Rev1a silicon (0110) fixes almost all of them.
- */
-
-/*
- * Copyright (C) 2003 David Brownell
- * Copyright (C) 2003-2005 PLX Technology, Inc.
- * Copyright (C) 2014 Ricardo Ribalda - Qtechnology/AS
- *
- * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility
- *     with 2282 chip
- *
- * Modified Ricardo Ribalda Qtechnology AS  to provide compatibility
- *     with usb 338x chip. Based on PLX driver
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/prefetch.h>
-#include <linux/io.h>
-
-#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/unaligned.h>
-
-#define        DRIVER_DESC             "PLX NET228x/USB338x USB Peripheral Controller"
-#define        DRIVER_VERSION          "2005 Sept 27/v3.0"
-
-#define        EP_DONTUSE              13      /* nonzero */
-
-#define USE_RDK_LEDS           /* GPIO pins control three LEDs */
-
-
-static const char driver_name[] = "net2280";
-static const char driver_desc[] = DRIVER_DESC;
-
-static const u32 ep_bit[9] = { 0, 17, 2, 19, 4, 1, 18, 3, 20 };
-static const char ep0name[] = "ep0";
-static const char *const ep_name[] = {
-       ep0name,
-       "ep-a", "ep-b", "ep-c", "ep-d",
-       "ep-e", "ep-f", "ep-g", "ep-h",
-};
-
-/* use_dma -- general goodness, fewer interrupts, less cpu load (vs PIO)
- * use_dma_chaining -- dma descriptor queueing gives even more irq reduction
- *
- * The net2280 DMA engines are not tightly integrated with their FIFOs;
- * not all cases are (yet) handled well in this driver or the silicon.
- * Some gadget drivers work better with the dma support here than others.
- * These two parameters let you use PIO or more aggressive DMA.
- */
-static bool use_dma = true;
-static bool use_dma_chaining;
-static bool use_msi = true;
-
-/* "modprobe net2280 use_dma=n" etc */
-module_param(use_dma, bool, 0444);
-module_param(use_dma_chaining, bool, 0444);
-module_param(use_msi, bool, 0444);
-
-/* mode 0 == ep-{a,b,c,d} 1K fifo each
- * mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable
- * mode 2 == ep-a 2K fifo, ep-{b,c} 1K each, ep-d unavailable
- */
-static ushort fifo_mode;
-
-/* "modprobe net2280 fifo_mode=1" etc */
-module_param(fifo_mode, ushort, 0644);
-
-/* enable_suspend -- When enabled, the driver will respond to
- * USB suspend requests by powering down the NET2280.  Otherwise,
- * USB suspend requests will be ignored.  This is acceptable for
- * self-powered devices
- */
-static bool enable_suspend;
-
-/* "modprobe net2280 enable_suspend=1" etc */
-module_param(enable_suspend, bool, 0444);
-
-/* force full-speed operation */
-static bool full_speed;
-module_param(full_speed, bool, 0444);
-MODULE_PARM_DESC(full_speed, "force full-speed mode -- for testing only!");
-
-#define        DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out")
-
-static char *type_string(u8 bmAttributes)
-{
-       switch ((bmAttributes) & USB_ENDPOINT_XFERTYPE_MASK) {
-       case USB_ENDPOINT_XFER_BULK:    return "bulk";
-       case USB_ENDPOINT_XFER_ISOC:    return "iso";
-       case USB_ENDPOINT_XFER_INT:     return "intr";
-       }
-       return "control";
-}
-
-#include "net2280.h"
-
-#define valid_bit      cpu_to_le32(BIT(VALID_BIT))
-#define dma_done_ie    cpu_to_le32(BIT(DMA_DONE_INTERRUPT_ENABLE))
-
-/*-------------------------------------------------------------------------*/
-static inline void enable_pciirqenb(struct net2280_ep *ep)
-{
-       u32 tmp = readl(&ep->dev->regs->pciirqenb0);
-
-       if (ep->dev->quirks & PLX_LEGACY)
-               tmp |= BIT(ep->num);
-       else
-               tmp |= BIT(ep_bit[ep->num]);
-       writel(tmp, &ep->dev->regs->pciirqenb0);
-
-       return;
-}
-
-static int
-net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
-{
-       struct net2280          *dev;
-       struct net2280_ep       *ep;
-       u32                     max, tmp;
-       unsigned long           flags;
-       static const u32 ep_key[9] = { 1, 0, 1, 0, 1, 1, 0, 1, 0 };
-
-       ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || !desc || ep->desc || _ep->name == ep0name ||
-                       desc->bDescriptorType != USB_DT_ENDPOINT)
-               return -EINVAL;
-       dev = ep->dev;
-       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       /* erratum 0119 workaround ties up an endpoint number */
-       if ((desc->bEndpointAddress & 0x0f) == EP_DONTUSE)
-               return -EDOM;
-
-       if (dev->quirks & PLX_SUPERSPEED) {
-               if ((desc->bEndpointAddress & 0x0f) >= 0x0c)
-                       return -EDOM;
-               ep->is_in = !!usb_endpoint_dir_in(desc);
-               if (dev->enhanced_mode && ep->is_in && ep_key[ep->num])
-                       return -EINVAL;
-       }
-
-       /* sanity check ep-e/ep-f since their fifos are small */
-       max = usb_endpoint_maxp(desc) & 0x1fff;
-       if (ep->num > 4 && max > 64 && (dev->quirks & PLX_LEGACY))
-               return -ERANGE;
-
-       spin_lock_irqsave(&dev->lock, flags);
-       _ep->maxpacket = max & 0x7ff;
-       ep->desc = desc;
-
-       /* ep_reset() has already been called */
-       ep->stopped = 0;
-       ep->wedged = 0;
-       ep->out_overflow = 0;
-
-       /* set speed-dependent max packet; may kick in high bandwidth */
-       set_max_speed(ep, max);
-
-       /* FIFO lines can't go to different packets.  PIO is ok, so
-        * use it instead of troublesome (non-bulk) multi-packet DMA.
-        */
-       if (ep->dma && (max % 4) != 0 && use_dma_chaining) {
-               ep_dbg(ep->dev, "%s, no dma for maxpacket %d\n",
-                       ep->ep.name, ep->ep.maxpacket);
-               ep->dma = NULL;
-       }
-
-       /* set type, direction, address; reset fifo counters */
-       writel(BIT(FIFO_FLUSH), &ep->regs->ep_stat);
-       tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
-       if (tmp == USB_ENDPOINT_XFER_INT) {
-               /* erratum 0105 workaround prevents hs NYET */
-               if (dev->chiprev == 0100 &&
-                               dev->gadget.speed == USB_SPEED_HIGH &&
-                               !(desc->bEndpointAddress & USB_DIR_IN))
-                       writel(BIT(CLEAR_NAK_OUT_PACKETS_MODE),
-                               &ep->regs->ep_rsp);
-       } else if (tmp == USB_ENDPOINT_XFER_BULK) {
-               /* catch some particularly blatant driver bugs */
-               if ((dev->gadget.speed == USB_SPEED_SUPER && max != 1024) ||
-                   (dev->gadget.speed == USB_SPEED_HIGH && max != 512) ||
-                   (dev->gadget.speed == USB_SPEED_FULL && max > 64)) {
-                       spin_unlock_irqrestore(&dev->lock, flags);
-                       return -ERANGE;
-               }
-       }
-       ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC);
-       /* Enable this endpoint */
-       if (dev->quirks & PLX_LEGACY) {
-               tmp <<= ENDPOINT_TYPE;
-               tmp |= desc->bEndpointAddress;
-               /* default full fifo lines */
-               tmp |= (4 << ENDPOINT_BYTE_COUNT);
-               tmp |= BIT(ENDPOINT_ENABLE);
-               ep->is_in = (tmp & USB_DIR_IN) != 0;
-       } else {
-               /* In Legacy mode, only OUT endpoints are used */
-               if (dev->enhanced_mode && ep->is_in) {
-                       tmp <<= IN_ENDPOINT_TYPE;
-                       tmp |= BIT(IN_ENDPOINT_ENABLE);
-                       /* Not applicable to Legacy */
-                       tmp |= BIT(ENDPOINT_DIRECTION);
-               } else {
-                       tmp <<= OUT_ENDPOINT_TYPE;
-                       tmp |= BIT(OUT_ENDPOINT_ENABLE);
-                       tmp |= (ep->is_in << ENDPOINT_DIRECTION);
-               }
-
-               tmp |= usb_endpoint_num(desc);
-               tmp |= (ep->ep.maxburst << MAX_BURST_SIZE);
-       }
-
-       /* Make sure all the registers are written before ep_rsp*/
-       wmb();
-
-       /* for OUT transfers, block the rx fifo until a read is posted */
-       if (!ep->is_in)
-               writel(BIT(SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-       else if (!(dev->quirks & PLX_2280)) {
-               /* Added for 2282, Don't use nak packets on an in endpoint,
-                * this was ignored on 2280
-                */
-               writel(BIT(CLEAR_NAK_OUT_PACKETS) |
-                       BIT(CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
-       }
-
-       writel(tmp, &ep->cfg->ep_cfg);
-
-       /* enable irqs */
-       if (!ep->dma) {                         /* pio, per-packet */
-               enable_pciirqenb(ep);
-
-               tmp = BIT(DATA_PACKET_RECEIVED_INTERRUPT_ENABLE) |
-                       BIT(DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE);
-               if (dev->quirks & PLX_2280)
-                       tmp |= readl(&ep->regs->ep_irqenb);
-               writel(tmp, &ep->regs->ep_irqenb);
-       } else {                                /* dma, per-request */
-               tmp = BIT((8 + ep->num));       /* completion */
-               tmp |= readl(&dev->regs->pciirqenb1);
-               writel(tmp, &dev->regs->pciirqenb1);
-
-               /* for short OUT transfers, dma completions can't
-                * advance the queue; do it pio-style, by hand.
-                * NOTE erratum 0112 workaround #2
-                */
-               if ((desc->bEndpointAddress & USB_DIR_IN) == 0) {
-                       tmp = BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE);
-                       writel(tmp, &ep->regs->ep_irqenb);
-
-                       enable_pciirqenb(ep);
-               }
-       }
-
-       tmp = desc->bEndpointAddress;
-       ep_dbg(dev, "enabled %s (ep%d%s-%s) %s max %04x\n",
-               _ep->name, tmp & 0x0f, DIR_STRING(tmp),
-               type_string(desc->bmAttributes),
-               ep->dma ? "dma" : "pio", max);
-
-       /* pci writes may still be posted */
-       spin_unlock_irqrestore(&dev->lock, flags);
-       return 0;
-}
-
-static int handshake(u32 __iomem *ptr, u32 mask, u32 done, int usec)
-{
-       u32     result;
-
-       do {
-               result = readl(ptr);
-               if (result == ~(u32)0)          /* "device unplugged" */
-                       return -ENODEV;
-               result &= mask;
-               if (result == done)
-                       return 0;
-               udelay(1);
-               usec--;
-       } while (usec > 0);
-       return -ETIMEDOUT;
-}
-
-static const struct usb_ep_ops net2280_ep_ops;
-
-static void ep_reset_228x(struct net2280_regs __iomem *regs,
-                         struct net2280_ep *ep)
-{
-       u32             tmp;
-
-       ep->desc = NULL;
-       INIT_LIST_HEAD(&ep->queue);
-
-       usb_ep_set_maxpacket_limit(&ep->ep, ~0);
-       ep->ep.ops = &net2280_ep_ops;
-
-       /* disable the dma, irqs, endpoint... */
-       if (ep->dma) {
-               writel(0, &ep->dma->dmactl);
-               writel(BIT(DMA_SCATTER_GATHER_DONE_INTERRUPT) |
-                       BIT(DMA_TRANSACTION_DONE_INTERRUPT) |
-                       BIT(DMA_ABORT),
-                       &ep->dma->dmastat);
-
-               tmp = readl(&regs->pciirqenb0);
-               tmp &= ~BIT(ep->num);
-               writel(tmp, &regs->pciirqenb0);
-       } else {
-               tmp = readl(&regs->pciirqenb1);
-               tmp &= ~BIT((8 + ep->num));     /* completion */
-               writel(tmp, &regs->pciirqenb1);
-       }
-       writel(0, &ep->regs->ep_irqenb);
-
-       /* init to our chosen defaults, notably so that we NAK OUT
-        * packets until the driver queues a read (+note erratum 0112)
-        */
-       if (!ep->is_in || (ep->dev->quirks & PLX_2280)) {
-               tmp = BIT(SET_NAK_OUT_PACKETS_MODE) |
-               BIT(SET_NAK_OUT_PACKETS) |
-               BIT(CLEAR_EP_HIDE_STATUS_PHASE) |
-               BIT(CLEAR_INTERRUPT_MODE);
-       } else {
-               /* added for 2282 */
-               tmp = BIT(CLEAR_NAK_OUT_PACKETS_MODE) |
-               BIT(CLEAR_NAK_OUT_PACKETS) |
-               BIT(CLEAR_EP_HIDE_STATUS_PHASE) |
-               BIT(CLEAR_INTERRUPT_MODE);
-       }
-
-       if (ep->num != 0) {
-               tmp |= BIT(CLEAR_ENDPOINT_TOGGLE) |
-                       BIT(CLEAR_ENDPOINT_HALT);
-       }
-       writel(tmp, &ep->regs->ep_rsp);
-
-       /* scrub most status bits, and flush any fifo state */
-       if (ep->dev->quirks & PLX_2280)
-               tmp = BIT(FIFO_OVERFLOW) |
-                       BIT(FIFO_UNDERFLOW);
-       else
-               tmp = 0;
-
-       writel(tmp | BIT(TIMEOUT) |
-               BIT(USB_STALL_SENT) |
-               BIT(USB_IN_NAK_SENT) |
-               BIT(USB_IN_ACK_RCVD) |
-               BIT(USB_OUT_PING_NAK_SENT) |
-               BIT(USB_OUT_ACK_SENT) |
-               BIT(FIFO_FLUSH) |
-               BIT(SHORT_PACKET_OUT_DONE_INTERRUPT) |
-               BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT) |
-               BIT(DATA_PACKET_RECEIVED_INTERRUPT) |
-               BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
-               BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
-               BIT(DATA_IN_TOKEN_INTERRUPT),
-               &ep->regs->ep_stat);
-
-       /* fifo size is handled separately */
-}
-
-static void ep_reset_338x(struct net2280_regs __iomem *regs,
-                                       struct net2280_ep *ep)
-{
-       u32 tmp, dmastat;
-
-       ep->desc = NULL;
-       INIT_LIST_HEAD(&ep->queue);
-
-       usb_ep_set_maxpacket_limit(&ep->ep, ~0);
-       ep->ep.ops = &net2280_ep_ops;
-
-       /* disable the dma, irqs, endpoint... */
-       if (ep->dma) {
-               writel(0, &ep->dma->dmactl);
-               writel(BIT(DMA_ABORT_DONE_INTERRUPT) |
-                      BIT(DMA_PAUSE_DONE_INTERRUPT) |
-                      BIT(DMA_SCATTER_GATHER_DONE_INTERRUPT) |
-                      BIT(DMA_TRANSACTION_DONE_INTERRUPT),
-                      /* | BIT(DMA_ABORT), */
-                      &ep->dma->dmastat);
-
-               dmastat = readl(&ep->dma->dmastat);
-               if (dmastat == 0x5002) {
-                       ep_warn(ep->dev, "The dmastat return = %x!!\n",
-                              dmastat);
-                       writel(0x5a, &ep->dma->dmastat);
-               }
-
-               tmp = readl(&regs->pciirqenb0);
-               tmp &= ~BIT(ep_bit[ep->num]);
-               writel(tmp, &regs->pciirqenb0);
-       } else {
-               if (ep->num < 5) {
-                       tmp = readl(&regs->pciirqenb1);
-                       tmp &= ~BIT((8 + ep->num));     /* completion */
-                       writel(tmp, &regs->pciirqenb1);
-               }
-       }
-       writel(0, &ep->regs->ep_irqenb);
-
-       writel(BIT(SHORT_PACKET_OUT_DONE_INTERRUPT) |
-              BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT) |
-              BIT(FIFO_OVERFLOW) |
-              BIT(DATA_PACKET_RECEIVED_INTERRUPT) |
-              BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
-              BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
-              BIT(DATA_IN_TOKEN_INTERRUPT), &ep->regs->ep_stat);
-}
-
-static void nuke(struct net2280_ep *);
-
-static int net2280_disable(struct usb_ep *_ep)
-{
-       struct net2280_ep       *ep;
-       unsigned long           flags;
-
-       ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || !ep->desc || _ep->name == ep0name)
-               return -EINVAL;
-
-       spin_lock_irqsave(&ep->dev->lock, flags);
-       nuke(ep);
-
-       if (ep->dev->quirks & PLX_SUPERSPEED)
-               ep_reset_338x(ep->dev->regs, ep);
-       else
-               ep_reset_228x(ep->dev->regs, ep);
-
-       ep_vdbg(ep->dev, "disabled %s %s\n",
-                       ep->dma ? "dma" : "pio", _ep->name);
-
-       /* synch memory views with the device */
-       (void)readl(&ep->cfg->ep_cfg);
-
-       if (use_dma && !ep->dma && ep->num >= 1 && ep->num <= 4)
-               ep->dma = &ep->dev->dma[ep->num - 1];
-
-       spin_unlock_irqrestore(&ep->dev->lock, flags);
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_request
-*net2280_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
-{
-       struct net2280_ep       *ep;
-       struct net2280_request  *req;
-
-       if (!_ep)
-               return NULL;
-       ep = container_of(_ep, struct net2280_ep, ep);
-
-       req = kzalloc(sizeof(*req), gfp_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD(&req->queue);
-
-       /* this dma descriptor may be swapped with the previous dummy */
-       if (ep->dma) {
-               struct net2280_dma      *td;
-
-               td = pci_pool_alloc(ep->dev->requests, gfp_flags,
-                               &req->td_dma);
-               if (!td) {
-                       kfree(req);
-                       return NULL;
-               }
-               td->dmacount = 0;       /* not VALID */
-               td->dmadesc = td->dmaaddr;
-               req->td = td;
-       }
-       return &req->req;
-}
-
-static void net2280_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct net2280_ep       *ep;
-       struct net2280_request  *req;
-
-       ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || !_req)
-               return;
-
-       req = container_of(_req, struct net2280_request, req);
-       WARN_ON(!list_empty(&req->queue));
-       if (req->td)
-               pci_pool_free(ep->dev->requests, req->td, req->td_dma);
-       kfree(req);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* load a packet into the fifo we use for usb IN transfers.
- * works for all endpoints.
- *
- * NOTE: pio with ep-a..ep-d could stuff multiple packets into the fifo
- * at a time, but this code is simpler because it knows it only writes
- * one packet.  ep-a..ep-d should use dma instead.
- */
-static void write_fifo(struct net2280_ep *ep, struct usb_request *req)
-{
-       struct net2280_ep_regs  __iomem *regs = ep->regs;
-       u8                      *buf;
-       u32                     tmp;
-       unsigned                count, total;
-
-       /* INVARIANT:  fifo is currently empty. (testable) */
-
-       if (req) {
-               buf = req->buf + req->actual;
-               prefetch(buf);
-               total = req->length - req->actual;
-       } else {
-               total = 0;
-               buf = NULL;
-       }
-
-       /* write just one packet at a time */
-       count = ep->ep.maxpacket;
-       if (count > total)      /* min() cannot be used on a bitfield */
-               count = total;
-
-       ep_vdbg(ep->dev, "write %s fifo (IN) %d bytes%s req %p\n",
-                       ep->ep.name, count,
-                       (count != ep->ep.maxpacket) ? " (short)" : "",
-                       req);
-       while (count >= 4) {
-               /* NOTE be careful if you try to align these. fifo lines
-                * should normally be full (4 bytes) and successive partial
-                * lines are ok only in certain cases.
-                */
-               tmp = get_unaligned((u32 *)buf);
-               cpu_to_le32s(&tmp);
-               writel(tmp, &regs->ep_data);
-               buf += 4;
-               count -= 4;
-       }
-
-       /* last fifo entry is "short" unless we wrote a full packet.
-        * also explicitly validate last word in (periodic) transfers
-        * when maxpacket is not a multiple of 4 bytes.
-        */
-       if (count || total < ep->ep.maxpacket) {
-               tmp = count ? get_unaligned((u32 *)buf) : count;
-               cpu_to_le32s(&tmp);
-               set_fifo_bytecount(ep, count & 0x03);
-               writel(tmp, &regs->ep_data);
-       }
-
-       /* pci writes may still be posted */
-}
-
-/* work around erratum 0106: PCI and USB race over the OUT fifo.
- * caller guarantees chiprev 0100, out endpoint is NAKing, and
- * there's no real data in the fifo.
- *
- * NOTE:  also used in cases where that erratum doesn't apply:
- * where the host wrote "too much" data to us.
- */
-static void out_flush(struct net2280_ep *ep)
-{
-       u32     __iomem *statp;
-       u32     tmp;
-
-       ASSERT_OUT_NAKING(ep);
-
-       statp = &ep->regs->ep_stat;
-       writel(BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
-               BIT(DATA_PACKET_RECEIVED_INTERRUPT),
-               statp);
-       writel(BIT(FIFO_FLUSH), statp);
-       /* Make sure that stap is written */
-       mb();
-       tmp = readl(statp);
-       if (tmp & BIT(DATA_OUT_PING_TOKEN_INTERRUPT) &&
-                       /* high speed did bulk NYET; fifo isn't filling */
-                       ep->dev->gadget.speed == USB_SPEED_FULL) {
-               unsigned        usec;
-
-               usec = 50;              /* 64 byte bulk/interrupt */
-               handshake(statp, BIT(USB_OUT_PING_NAK_SENT),
-                               BIT(USB_OUT_PING_NAK_SENT), usec);
-               /* NAK done; now CLEAR_NAK_OUT_PACKETS is safe */
-       }
-}
-
-/* unload packet(s) from the fifo we use for usb OUT transfers.
- * returns true iff the request completed, because of short packet
- * or the request buffer having filled with full packets.
- *
- * for ep-a..ep-d this will read multiple packets out when they
- * have been accepted.
- */
-static int read_fifo(struct net2280_ep *ep, struct net2280_request *req)
-{
-       struct net2280_ep_regs  __iomem *regs = ep->regs;
-       u8                      *buf = req->req.buf + req->req.actual;
-       unsigned                count, tmp, is_short;
-       unsigned                cleanup = 0, prevent = 0;
-
-       /* erratum 0106 ... packets coming in during fifo reads might
-        * be incompletely rejected.  not all cases have workarounds.
-        */
-       if (ep->dev->chiprev == 0x0100 &&
-                       ep->dev->gadget.speed == USB_SPEED_FULL) {
-               udelay(1);
-               tmp = readl(&ep->regs->ep_stat);
-               if ((tmp & BIT(NAK_OUT_PACKETS)))
-                       cleanup = 1;
-               else if ((tmp & BIT(FIFO_FULL))) {
-                       start_out_naking(ep);
-                       prevent = 1;
-               }
-               /* else: hope we don't see the problem */
-       }
-
-       /* never overflow the rx buffer. the fifo reads packets until
-        * it sees a short one; we might not be ready for them all.
-        */
-       prefetchw(buf);
-       count = readl(&regs->ep_avail);
-       if (unlikely(count == 0)) {
-               udelay(1);
-               tmp = readl(&ep->regs->ep_stat);
-               count = readl(&regs->ep_avail);
-               /* handled that data already? */
-               if (count == 0 && (tmp & BIT(NAK_OUT_PACKETS)) == 0)
-                       return 0;
-       }
-
-       tmp = req->req.length - req->req.actual;
-       if (count > tmp) {
-               /* as with DMA, data overflow gets flushed */
-               if ((tmp % ep->ep.maxpacket) != 0) {
-                       ep_err(ep->dev,
-                               "%s out fifo %d bytes, expected %d\n",
-                               ep->ep.name, count, tmp);
-                       req->req.status = -EOVERFLOW;
-                       cleanup = 1;
-                       /* NAK_OUT_PACKETS will be set, so flushing is safe;
-                        * the next read will start with the next packet
-                        */
-               } /* else it's a ZLP, no worries */
-               count = tmp;
-       }
-       req->req.actual += count;
-
-       is_short = (count == 0) || ((count % ep->ep.maxpacket) != 0);
-
-       ep_vdbg(ep->dev, "read %s fifo (OUT) %d bytes%s%s%s req %p %d/%d\n",
-                       ep->ep.name, count, is_short ? " (short)" : "",
-                       cleanup ? " flush" : "", prevent ? " nak" : "",
-                       req, req->req.actual, req->req.length);
-
-       while (count >= 4) {
-               tmp = readl(&regs->ep_data);
-               cpu_to_le32s(&tmp);
-               put_unaligned(tmp, (u32 *)buf);
-               buf += 4;
-               count -= 4;
-       }
-       if (count) {
-               tmp = readl(&regs->ep_data);
-               /* LE conversion is implicit here: */
-               do {
-                       *buf++ = (u8) tmp;
-                       tmp >>= 8;
-               } while (--count);
-       }
-       if (cleanup)
-               out_flush(ep);
-       if (prevent) {
-               writel(BIT(CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-               (void) readl(&ep->regs->ep_rsp);
-       }
-
-       return is_short || ((req->req.actual == req->req.length) &&
-                       !req->req.zero);
-}
-
-/* fill out dma descriptor to match a given request */
-static void fill_dma_desc(struct net2280_ep *ep,
-                                       struct net2280_request *req, int valid)
-{
-       struct net2280_dma      *td = req->td;
-       u32                     dmacount = req->req.length;
-
-       /* don't let DMA continue after a short OUT packet,
-        * so overruns can't affect the next transfer.
-        * in case of overruns on max-size packets, we can't
-        * stop the fifo from filling but we can flush it.
-        */
-       if (ep->is_in)
-               dmacount |= BIT(DMA_DIRECTION);
-       if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) ||
-                                       !(ep->dev->quirks & PLX_2280))
-               dmacount |= BIT(END_OF_CHAIN);
-
-       req->valid = valid;
-       if (valid)
-               dmacount |= BIT(VALID_BIT);
-       if (likely(!req->req.no_interrupt || !use_dma_chaining))
-               dmacount |= BIT(DMA_DONE_INTERRUPT_ENABLE);
-
-       /* td->dmadesc = previously set by caller */
-       td->dmaaddr = cpu_to_le32 (req->req.dma);
-
-       /* 2280 may be polling VALID_BIT through ep->dma->dmadesc */
-       wmb();
-       td->dmacount = cpu_to_le32(dmacount);
-}
-
-static const u32 dmactl_default =
-               BIT(DMA_SCATTER_GATHER_DONE_INTERRUPT) |
-               BIT(DMA_CLEAR_COUNT_ENABLE) |
-               /* erratum 0116 workaround part 1 (use POLLING) */
-               (POLL_100_USEC << DESCRIPTOR_POLLING_RATE) |
-               BIT(DMA_VALID_BIT_POLLING_ENABLE) |
-               BIT(DMA_VALID_BIT_ENABLE) |
-               BIT(DMA_SCATTER_GATHER_ENABLE) |
-               /* erratum 0116 workaround part 2 (no AUTOSTART) */
-               BIT(DMA_ENABLE);
-
-static inline void spin_stop_dma(struct net2280_dma_regs __iomem *dma)
-{
-       handshake(&dma->dmactl, BIT(DMA_ENABLE), 0, 50);
-}
-
-static inline void stop_dma(struct net2280_dma_regs __iomem *dma)
-{
-       writel(readl(&dma->dmactl) & ~BIT(DMA_ENABLE), &dma->dmactl);
-       spin_stop_dma(dma);
-}
-
-static void start_queue(struct net2280_ep *ep, u32 dmactl, u32 td_dma)
-{
-       struct net2280_dma_regs __iomem *dma = ep->dma;
-       unsigned int tmp = BIT(VALID_BIT) | (ep->is_in << DMA_DIRECTION);
-
-       if (!(ep->dev->quirks & PLX_2280))
-               tmp |= BIT(END_OF_CHAIN);
-
-       writel(tmp, &dma->dmacount);
-       writel(readl(&dma->dmastat), &dma->dmastat);
-
-       writel(td_dma, &dma->dmadesc);
-       if (ep->dev->quirks & PLX_SUPERSPEED)
-               dmactl |= BIT(DMA_REQUEST_OUTSTANDING);
-       writel(dmactl, &dma->dmactl);
-
-       /* erratum 0116 workaround part 3:  pci arbiter away from net2280 */
-       (void) readl(&ep->dev->pci->pcimstctl);
-
-       writel(BIT(DMA_START), &dma->dmastat);
-
-       if (!ep->is_in)
-               stop_out_naking(ep);
-}
-
-static void start_dma(struct net2280_ep *ep, struct net2280_request *req)
-{
-       u32                     tmp;
-       struct net2280_dma_regs __iomem *dma = ep->dma;
-
-       /* FIXME can't use DMA for ZLPs */
-
-       /* on this path we "know" there's no dma active (yet) */
-       WARN_ON(readl(&dma->dmactl) & BIT(DMA_ENABLE));
-       writel(0, &ep->dma->dmactl);
-
-       /* previous OUT packet might have been short */
-       if (!ep->is_in && (readl(&ep->regs->ep_stat) &
-                               BIT(NAK_OUT_PACKETS))) {
-               writel(BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT),
-                       &ep->regs->ep_stat);
-
-               tmp = readl(&ep->regs->ep_avail);
-               if (tmp) {
-                       writel(readl(&dma->dmastat), &dma->dmastat);
-
-                       /* transfer all/some fifo data */
-                       writel(req->req.dma, &dma->dmaaddr);
-                       tmp = min(tmp, req->req.length);
-
-                       /* dma irq, faking scatterlist status */
-                       req->td->dmacount = cpu_to_le32(req->req.length - tmp);
-                       writel(BIT(DMA_DONE_INTERRUPT_ENABLE) | tmp,
-                                       &dma->dmacount);
-                       req->td->dmadesc = 0;
-                       req->valid = 1;
-
-                       writel(BIT(DMA_ENABLE), &dma->dmactl);
-                       writel(BIT(DMA_START), &dma->dmastat);
-                       return;
-               }
-       }
-
-       tmp = dmactl_default;
-
-       /* force packet boundaries between dma requests, but prevent the
-        * controller from automagically writing a last "short" packet
-        * (zero length) unless the driver explicitly said to do that.
-        */
-       if (ep->is_in) {
-               if (likely((req->req.length % ep->ep.maxpacket) ||
-                                                       req->req.zero)){
-                       tmp |= BIT(DMA_FIFO_VALIDATE);
-                       ep->in_fifo_validate = 1;
-               } else
-                       ep->in_fifo_validate = 0;
-       }
-
-       /* init req->td, pointing to the current dummy */
-       req->td->dmadesc = cpu_to_le32 (ep->td_dma);
-       fill_dma_desc(ep, req, 1);
-
-       if (!use_dma_chaining)
-               req->td->dmacount |= cpu_to_le32(BIT(END_OF_CHAIN));
-
-       start_queue(ep, tmp, req->td_dma);
-}
-
-static inline void resume_dma(struct net2280_ep *ep)
-{
-       writel(readl(&ep->dma->dmactl) | BIT(DMA_ENABLE), &ep->dma->dmactl);
-
-       ep->dma_started = true;
-}
-
-static inline void ep_stop_dma(struct net2280_ep *ep)
-{
-       writel(readl(&ep->dma->dmactl) & ~BIT(DMA_ENABLE), &ep->dma->dmactl);
-       spin_stop_dma(ep->dma);
-
-       ep->dma_started = false;
-}
-
-static inline void
-queue_dma(struct net2280_ep *ep, struct net2280_request *req, int valid)
-{
-       struct net2280_dma      *end;
-       dma_addr_t              tmp;
-
-       /* swap new dummy for old, link; fill and maybe activate */
-       end = ep->dummy;
-       ep->dummy = req->td;
-       req->td = end;
-
-       tmp = ep->td_dma;
-       ep->td_dma = req->td_dma;
-       req->td_dma = tmp;
-
-       end->dmadesc = cpu_to_le32 (ep->td_dma);
-
-       fill_dma_desc(ep, req, valid);
-}
-
-static void
-done(struct net2280_ep *ep, struct net2280_request *req, int status)
-{
-       struct net2280          *dev;
-       unsigned                stopped = ep->stopped;
-
-       list_del_init(&req->queue);
-
-       if (req->req.status == -EINPROGRESS)
-               req->req.status = status;
-       else
-               status = req->req.status;
-
-       dev = ep->dev;
-       if (ep->dma)
-               usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
-
-       if (status && status != -ESHUTDOWN)
-               ep_vdbg(dev, "complete %s req %p stat %d len %u/%u\n",
-                       ep->ep.name, &req->req, status,
-                       req->req.actual, req->req.length);
-
-       /* don't modify queue heads during completion callback */
-       ep->stopped = 1;
-       spin_unlock(&dev->lock);
-       req->req.complete(&ep->ep, &req->req);
-       spin_lock(&dev->lock);
-       ep->stopped = stopped;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-net2280_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
-{
-       struct net2280_request  *req;
-       struct net2280_ep       *ep;
-       struct net2280          *dev;
-       unsigned long           flags;
-
-       /* we always require a cpu-view buffer, so that we can
-        * always use pio (as fallback or whatever).
-        */
-       req = container_of(_req, struct net2280_request, req);
-       if (!_req || !_req->complete || !_req->buf ||
-                               !list_empty(&req->queue))
-               return -EINVAL;
-       if (_req->length > (~0 & DMA_BYTE_COUNT_MASK))
-               return -EDOM;
-       ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0))
-               return -EINVAL;
-       dev = ep->dev;
-       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       /* FIXME implement PIO fallback for ZLPs with DMA */
-       if (ep->dma && _req->length == 0)
-               return -EOPNOTSUPP;
-
-       /* set up dma mapping in case the caller didn't */
-       if (ep->dma) {
-               int ret;
-
-               ret = usb_gadget_map_request(&dev->gadget, _req,
-                               ep->is_in);
-               if (ret)
-                       return ret;
-       }
-
-#if 0
-       ep_vdbg(dev, "%s queue req %p, len %d buf %p\n",
-                       _ep->name, _req, _req->length, _req->buf);
-#endif
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       _req->status = -EINPROGRESS;
-       _req->actual = 0;
-
-       /* kickstart this i/o queue? */
-       if (list_empty(&ep->queue) && !ep->stopped) {
-               /* DMA request while EP halted */
-               if (ep->dma &&
-                   (readl(&ep->regs->ep_rsp) & BIT(CLEAR_ENDPOINT_HALT)) &&
-                       (dev->quirks & PLX_SUPERSPEED)) {
-                       int valid = 1;
-                       if (ep->is_in) {
-                               int expect;
-                               expect = likely(req->req.zero ||
-                                               ((req->req.length %
-                                                 ep->ep.maxpacket) != 0));
-                               if (expect != ep->in_fifo_validate)
-                                       valid = 0;
-                       }
-                       queue_dma(ep, req, valid);
-               }
-               /* use DMA if the endpoint supports it, else pio */
-               else if (ep->dma)
-                       start_dma(ep, req);
-               else {
-                       /* maybe there's no control data, just status ack */
-                       if (ep->num == 0 && _req->length == 0) {
-                               allow_status(ep);
-                               done(ep, req, 0);
-                               ep_vdbg(dev, "%s status ack\n", ep->ep.name);
-                               goto done;
-                       }
-
-                       /* PIO ... stuff the fifo, or unblock it.  */
-                       if (ep->is_in)
-                               write_fifo(ep, _req);
-                       else if (list_empty(&ep->queue)) {
-                               u32     s;
-
-                               /* OUT FIFO might have packet(s) buffered */
-                               s = readl(&ep->regs->ep_stat);
-                               if ((s & BIT(FIFO_EMPTY)) == 0) {
-                                       /* note:  _req->short_not_ok is
-                                        * ignored here since PIO _always_
-                                        * stops queue advance here, and
-                                        * _req->status doesn't change for
-                                        * short reads (only _req->actual)
-                                        */
-                                       if (read_fifo(ep, req) &&
-                                                       ep->num == 0) {
-                                               done(ep, req, 0);
-                                               allow_status(ep);
-                                               /* don't queue it */
-                                               req = NULL;
-                                       } else if (read_fifo(ep, req) &&
-                                                       ep->num != 0) {
-                                               done(ep, req, 0);
-                                               req = NULL;
-                                       } else
-                                               s = readl(&ep->regs->ep_stat);
-                               }
-
-                               /* don't NAK, let the fifo fill */
-                               if (req && (s & BIT(NAK_OUT_PACKETS)))
-                                       writel(BIT(CLEAR_NAK_OUT_PACKETS),
-                                                       &ep->regs->ep_rsp);
-                       }
-               }
-
-       } else if (ep->dma) {
-               int     valid = 1;
-
-               if (ep->is_in) {
-                       int     expect;
-
-                       /* preventing magic zlps is per-engine state, not
-                        * per-transfer; irq logic must recover hiccups.
-                        */
-                       expect = likely(req->req.zero ||
-                               (req->req.length % ep->ep.maxpacket));
-                       if (expect != ep->in_fifo_validate)
-                               valid = 0;
-               }
-               queue_dma(ep, req, valid);
-
-       } /* else the irq handler advances the queue. */
-
-       ep->responded = 1;
-       if (req)
-               list_add_tail(&req->queue, &ep->queue);
-done:
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       /* pci writes may still be posted */
-       return 0;
-}
-
-static inline void
-dma_done(struct net2280_ep *ep,        struct net2280_request *req, u32 dmacount,
-               int status)
-{
-       req->req.actual = req->req.length - (DMA_BYTE_COUNT_MASK & dmacount);
-       done(ep, req, status);
-}
-
-static void restart_dma(struct net2280_ep *ep);
-
-static void scan_dma_completions(struct net2280_ep *ep)
-{
-       /* only look at descriptors that were "naturally" retired,
-        * so fifo and list head state won't matter
-        */
-       while (!list_empty(&ep->queue)) {
-               struct net2280_request  *req;
-               u32                     tmp;
-
-               req = list_entry(ep->queue.next,
-                               struct net2280_request, queue);
-               if (!req->valid)
-                       break;
-               rmb();
-               tmp = le32_to_cpup(&req->td->dmacount);
-               if ((tmp & BIT(VALID_BIT)) != 0)
-                       break;
-
-               /* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short"
-                * cases where DMA must be aborted; this code handles
-                * all non-abort DMA completions.
-                */
-               if (unlikely(req->td->dmadesc == 0)) {
-                       /* paranoia */
-                       tmp = readl(&ep->dma->dmacount);
-                       if (tmp & DMA_BYTE_COUNT_MASK)
-                               break;
-                       /* single transfer mode */
-                       dma_done(ep, req, tmp, 0);
-                       break;
-               } else if (!ep->is_in &&
-                               (req->req.length % ep->ep.maxpacket) != 0) {
-                       tmp = readl(&ep->regs->ep_stat);
-                       if (ep->dev->quirks & PLX_SUPERSPEED)
-                               return dma_done(ep, req, tmp, 0);
-
-                       /* AVOID TROUBLE HERE by not issuing short reads from
-                        * your gadget driver.  That helps avoids errata 0121,
-                        * 0122, and 0124; not all cases trigger the warning.
-                        */
-                       if ((tmp & BIT(NAK_OUT_PACKETS)) == 0) {
-                               ep_warn(ep->dev, "%s lost packet sync!\n",
-                                               ep->ep.name);
-                               req->req.status = -EOVERFLOW;
-                       } else {
-                               tmp = readl(&ep->regs->ep_avail);
-                               if (tmp) {
-                                       /* fifo gets flushed later */
-                                       ep->out_overflow = 1;
-                                       ep_dbg(ep->dev,
-                                               "%s dma, discard %d len %d\n",
-                                               ep->ep.name, tmp,
-                                               req->req.length);
-                                       req->req.status = -EOVERFLOW;
-                               }
-                       }
-               }
-               dma_done(ep, req, tmp, 0);
-       }
-}
-
-static void restart_dma(struct net2280_ep *ep)
-{
-       struct net2280_request  *req;
-       u32                     dmactl = dmactl_default;
-
-       if (ep->stopped)
-               return;
-       req = list_entry(ep->queue.next, struct net2280_request, queue);
-
-       if (!use_dma_chaining) {
-               start_dma(ep, req);
-               return;
-       }
-
-       /* the 2280 will be processing the queue unless queue hiccups after
-        * the previous transfer:
-        *  IN:   wanted automagic zlp, head doesn't (or vice versa)
-        *        DMA_FIFO_VALIDATE doesn't init from dma descriptors.
-        *  OUT:  was "usb-short", we must restart.
-        */
-       if (ep->is_in && !req->valid) {
-               struct net2280_request  *entry, *prev = NULL;
-               int                     reqmode, done = 0;
-
-               ep_dbg(ep->dev, "%s dma hiccup td %p\n", ep->ep.name, req->td);
-               ep->in_fifo_validate = likely(req->req.zero ||
-                               (req->req.length % ep->ep.maxpacket) != 0);
-               if (ep->in_fifo_validate)
-                       dmactl |= BIT(DMA_FIFO_VALIDATE);
-               list_for_each_entry(entry, &ep->queue, queue) {
-                       __le32          dmacount;
-
-                       if (entry == req)
-                               continue;
-                       dmacount = entry->td->dmacount;
-                       if (!done) {
-                               reqmode = likely(entry->req.zero ||
-                                  (entry->req.length % ep->ep.maxpacket));
-                               if (reqmode == ep->in_fifo_validate) {
-                                       entry->valid = 1;
-                                       dmacount |= valid_bit;
-                                       entry->td->dmacount = dmacount;
-                                       prev = entry;
-                                       continue;
-                               } else {
-                                       /* force a hiccup */
-                                       prev->td->dmacount |= dma_done_ie;
-                                       done = 1;
-                               }
-                       }
-
-                       /* walk the rest of the queue so unlinks behave */
-                       entry->valid = 0;
-                       dmacount &= ~valid_bit;
-                       entry->td->dmacount = dmacount;
-                       prev = entry;
-               }
-       }
-
-       writel(0, &ep->dma->dmactl);
-       start_queue(ep, dmactl, req->td_dma);
-}
-
-static void abort_dma_228x(struct net2280_ep *ep)
-{
-       /* abort the current transfer */
-       if (likely(!list_empty(&ep->queue))) {
-               /* FIXME work around errata 0121, 0122, 0124 */
-               writel(BIT(DMA_ABORT), &ep->dma->dmastat);
-               spin_stop_dma(ep->dma);
-       } else
-               stop_dma(ep->dma);
-       scan_dma_completions(ep);
-}
-
-static void abort_dma_338x(struct net2280_ep *ep)
-{
-       writel(BIT(DMA_ABORT), &ep->dma->dmastat);
-       spin_stop_dma(ep->dma);
-}
-
-static void abort_dma(struct net2280_ep *ep)
-{
-       if (ep->dev->quirks & PLX_LEGACY)
-               return abort_dma_228x(ep);
-       return abort_dma_338x(ep);
-}
-
-/* dequeue ALL requests */
-static void nuke(struct net2280_ep *ep)
-{
-       struct net2280_request  *req;
-
-       /* called with spinlock held */
-       ep->stopped = 1;
-       if (ep->dma)
-               abort_dma(ep);
-       while (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next,
-                               struct net2280_request,
-                               queue);
-               done(ep, req, -ESHUTDOWN);
-       }
-}
-
-/* dequeue JUST ONE request */
-static int net2280_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct net2280_ep       *ep;
-       struct net2280_request  *req;
-       unsigned long           flags;
-       u32                     dmactl;
-       int                     stopped;
-
-       ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0) || !_req)
-               return -EINVAL;
-
-       spin_lock_irqsave(&ep->dev->lock, flags);
-       stopped = ep->stopped;
-
-       /* quiesce dma while we patch the queue */
-       dmactl = 0;
-       ep->stopped = 1;
-       if (ep->dma) {
-               dmactl = readl(&ep->dma->dmactl);
-               /* WARNING erratum 0127 may kick in ... */
-               stop_dma(ep->dma);
-               scan_dma_completions(ep);
-       }
-
-       /* make sure it's still queued on this endpoint */
-       list_for_each_entry(req, &ep->queue, queue) {
-               if (&req->req == _req)
-                       break;
-       }
-       if (&req->req != _req) {
-               spin_unlock_irqrestore(&ep->dev->lock, flags);
-               return -EINVAL;
-       }
-
-       /* queue head may be partially complete. */
-       if (ep->queue.next == &req->queue) {
-               if (ep->dma) {
-                       ep_dbg(ep->dev, "unlink (%s) dma\n", _ep->name);
-                       _req->status = -ECONNRESET;
-                       abort_dma(ep);
-                       if (likely(ep->queue.next == &req->queue)) {
-                               /* NOTE: misreports single-transfer mode*/
-                               req->td->dmacount = 0;  /* invalidate */
-                               dma_done(ep, req,
-                                       readl(&ep->dma->dmacount),
-                                       -ECONNRESET);
-                       }
-               } else {
-                       ep_dbg(ep->dev, "unlink (%s) pio\n", _ep->name);
-                       done(ep, req, -ECONNRESET);
-               }
-               req = NULL;
-
-       /* patch up hardware chaining data */
-       } else if (ep->dma && use_dma_chaining) {
-               if (req->queue.prev == ep->queue.next) {
-                       writel(le32_to_cpu(req->td->dmadesc),
-                               &ep->dma->dmadesc);
-                       if (req->td->dmacount & dma_done_ie)
-                               writel(readl(&ep->dma->dmacount) |
-                                               le32_to_cpu(dma_done_ie),
-                                       &ep->dma->dmacount);
-               } else {
-                       struct net2280_request  *prev;
-
-                       prev = list_entry(req->queue.prev,
-                               struct net2280_request, queue);
-                       prev->td->dmadesc = req->td->dmadesc;
-                       if (req->td->dmacount & dma_done_ie)
-                               prev->td->dmacount |= dma_done_ie;
-               }
-       }
-
-       if (req)
-               done(ep, req, -ECONNRESET);
-       ep->stopped = stopped;
-
-       if (ep->dma) {
-               /* turn off dma on inactive queues */
-               if (list_empty(&ep->queue))
-                       stop_dma(ep->dma);
-               else if (!ep->stopped) {
-                       /* resume current request, or start new one */
-                       if (req)
-                               writel(dmactl, &ep->dma->dmactl);
-                       else
-                               start_dma(ep, list_entry(ep->queue.next,
-                                       struct net2280_request, queue));
-               }
-       }
-
-       spin_unlock_irqrestore(&ep->dev->lock, flags);
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int net2280_fifo_status(struct usb_ep *_ep);
-
-static int
-net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
-{
-       struct net2280_ep       *ep;
-       unsigned long           flags;
-       int                     retval = 0;
-
-       ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0))
-               return -EINVAL;
-       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-       if (ep->desc /* not ep0 */ && (ep->desc->bmAttributes & 0x03)
-                                               == USB_ENDPOINT_XFER_ISOC)
-               return -EINVAL;
-
-       spin_lock_irqsave(&ep->dev->lock, flags);
-       if (!list_empty(&ep->queue))
-               retval = -EAGAIN;
-       else if (ep->is_in && value && net2280_fifo_status(_ep) != 0)
-               retval = -EAGAIN;
-       else {
-               ep_vdbg(ep->dev, "%s %s %s\n", _ep->name,
-                               value ? "set" : "clear",
-                               wedged ? "wedge" : "halt");
-               /* set/clear, then synch memory views with the device */
-               if (value) {
-                       if (ep->num == 0)
-                               ep->dev->protocol_stall = 1;
-                       else
-                               set_halt(ep);
-                       if (wedged)
-                               ep->wedged = 1;
-               } else {
-                       clear_halt(ep);
-                       if (ep->dev->quirks & PLX_SUPERSPEED &&
-                               !list_empty(&ep->queue) && ep->td_dma)
-                                       restart_dma(ep);
-                       ep->wedged = 0;
-               }
-               (void) readl(&ep->regs->ep_rsp);
-       }
-       spin_unlock_irqrestore(&ep->dev->lock, flags);
-
-       return retval;
-}
-
-static int net2280_set_halt(struct usb_ep *_ep, int value)
-{
-       return net2280_set_halt_and_wedge(_ep, value, 0);
-}
-
-static int net2280_set_wedge(struct usb_ep *_ep)
-{
-       if (!_ep || _ep->name == ep0name)
-               return -EINVAL;
-       return net2280_set_halt_and_wedge(_ep, 1, 1);
-}
-
-static int net2280_fifo_status(struct usb_ep *_ep)
-{
-       struct net2280_ep       *ep;
-       u32                     avail;
-
-       ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0))
-               return -ENODEV;
-       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       avail = readl(&ep->regs->ep_avail) & (BIT(12) - 1);
-       if (avail > ep->fifo_size)
-               return -EOVERFLOW;
-       if (ep->is_in)
-               avail = ep->fifo_size - avail;
-       return avail;
-}
-
-static void net2280_fifo_flush(struct usb_ep *_ep)
-{
-       struct net2280_ep       *ep;
-
-       ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0))
-               return;
-       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return;
-
-       writel(BIT(FIFO_FLUSH), &ep->regs->ep_stat);
-       (void) readl(&ep->regs->ep_rsp);
-}
-
-static const struct usb_ep_ops net2280_ep_ops = {
-       .enable         = net2280_enable,
-       .disable        = net2280_disable,
-
-       .alloc_request  = net2280_alloc_request,
-       .free_request   = net2280_free_request,
-
-       .queue          = net2280_queue,
-       .dequeue        = net2280_dequeue,
-
-       .set_halt       = net2280_set_halt,
-       .set_wedge      = net2280_set_wedge,
-       .fifo_status    = net2280_fifo_status,
-       .fifo_flush     = net2280_fifo_flush,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int net2280_get_frame(struct usb_gadget *_gadget)
-{
-       struct net2280          *dev;
-       unsigned long           flags;
-       u16                     retval;
-
-       if (!_gadget)
-               return -ENODEV;
-       dev = container_of(_gadget, struct net2280, gadget);
-       spin_lock_irqsave(&dev->lock, flags);
-       retval = get_idx_reg(dev->regs, REG_FRAME) & 0x03ff;
-       spin_unlock_irqrestore(&dev->lock, flags);
-       return retval;
-}
-
-static int net2280_wakeup(struct usb_gadget *_gadget)
-{
-       struct net2280          *dev;
-       u32                     tmp;
-       unsigned long           flags;
-
-       if (!_gadget)
-               return 0;
-       dev = container_of(_gadget, struct net2280, gadget);
-
-       spin_lock_irqsave(&dev->lock, flags);
-       tmp = readl(&dev->usb->usbctl);
-       if (tmp & BIT(DEVICE_REMOTE_WAKEUP_ENABLE))
-               writel(BIT(GENERATE_RESUME), &dev->usb->usbstat);
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       /* pci writes may still be posted */
-       return 0;
-}
-
-static int net2280_set_selfpowered(struct usb_gadget *_gadget, int value)
-{
-       struct net2280          *dev;
-       u32                     tmp;
-       unsigned long           flags;
-
-       if (!_gadget)
-               return 0;
-       dev = container_of(_gadget, struct net2280, gadget);
-
-       spin_lock_irqsave(&dev->lock, flags);
-       tmp = readl(&dev->usb->usbctl);
-       if (value) {
-               tmp |= BIT(SELF_POWERED_STATUS);
-               dev->selfpowered = 1;
-       } else {
-               tmp &= ~BIT(SELF_POWERED_STATUS);
-               dev->selfpowered = 0;
-       }
-       writel(tmp, &dev->usb->usbctl);
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return 0;
-}
-
-static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
-{
-       struct net2280  *dev;
-       u32             tmp;
-       unsigned long   flags;
-
-       if (!_gadget)
-               return -ENODEV;
-       dev = container_of(_gadget, struct net2280, gadget);
-
-       spin_lock_irqsave(&dev->lock, flags);
-       tmp = readl(&dev->usb->usbctl);
-       dev->softconnect = (is_on != 0);
-       if (is_on)
-               tmp |= BIT(USB_DETECT_ENABLE);
-       else
-               tmp &= ~BIT(USB_DETECT_ENABLE);
-       writel(tmp, &dev->usb->usbctl);
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return 0;
-}
-
-static int net2280_start(struct usb_gadget *_gadget,
-               struct usb_gadget_driver *driver);
-static int net2280_stop(struct usb_gadget *_gadget,
-               struct usb_gadget_driver *driver);
-
-static const struct usb_gadget_ops net2280_ops = {
-       .get_frame      = net2280_get_frame,
-       .wakeup         = net2280_wakeup,
-       .set_selfpowered = net2280_set_selfpowered,
-       .pullup         = net2280_pullup,
-       .udc_start      = net2280_start,
-       .udc_stop       = net2280_stop,
-};
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-
-/* FIXME move these into procfs, and use seq_file.
- * Sysfs _still_ doesn't behave for arbitrarily sized files,
- * and also doesn't help products using this with 2.4 kernels.
- */
-
-/* "function" sysfs attribute */
-static ssize_t function_show(struct device *_dev, struct device_attribute *attr,
-                            char *buf)
-{
-       struct net2280  *dev = dev_get_drvdata(_dev);
-
-       if (!dev->driver || !dev->driver->function ||
-                       strlen(dev->driver->function) > PAGE_SIZE)
-               return 0;
-       return scnprintf(buf, PAGE_SIZE, "%s\n", dev->driver->function);
-}
-static DEVICE_ATTR_RO(function);
-
-static ssize_t registers_show(struct device *_dev,
-                             struct device_attribute *attr, char *buf)
-{
-       struct net2280          *dev;
-       char                    *next;
-       unsigned                size, t;
-       unsigned long           flags;
-       int                     i;
-       u32                     t1, t2;
-       const char              *s;
-
-       dev = dev_get_drvdata(_dev);
-       next = buf;
-       size = PAGE_SIZE;
-       spin_lock_irqsave(&dev->lock, flags);
-
-       if (dev->driver)
-               s = dev->driver->driver.name;
-       else
-               s = "(none)";
-
-       /* Main Control Registers */
-       t = scnprintf(next, size, "%s version " DRIVER_VERSION
-                       ", chiprev %04x, dma %s\n\n"
-                       "devinit %03x fifoctl %08x gadget '%s'\n"
-                       "pci irqenb0 %02x irqenb1 %08x "
-                       "irqstat0 %04x irqstat1 %08x\n",
-                       driver_name, dev->chiprev,
-                       use_dma
-                               ? (use_dma_chaining ? "chaining" : "enabled")
-                               : "disabled",
-                       readl(&dev->regs->devinit),
-                       readl(&dev->regs->fifoctl),
-                       s,
-                       readl(&dev->regs->pciirqenb0),
-                       readl(&dev->regs->pciirqenb1),
-                       readl(&dev->regs->irqstat0),
-                       readl(&dev->regs->irqstat1));
-       size -= t;
-       next += t;
-
-       /* USB Control Registers */
-       t1 = readl(&dev->usb->usbctl);
-       t2 = readl(&dev->usb->usbstat);
-       if (t1 & BIT(VBUS_PIN)) {
-               if (t2 & BIT(HIGH_SPEED))
-                       s = "high speed";
-               else if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-                       s = "powered";
-               else
-                       s = "full speed";
-               /* full speed bit (6) not working?? */
-       } else
-                       s = "not attached";
-       t = scnprintf(next, size,
-                       "stdrsp %08x usbctl %08x usbstat %08x "
-                               "addr 0x%02x (%s)\n",
-                       readl(&dev->usb->stdrsp), t1, t2,
-                       readl(&dev->usb->ouraddr), s);
-       size -= t;
-       next += t;
-
-       /* PCI Master Control Registers */
-
-       /* DMA Control Registers */
-
-       /* Configurable EP Control Registers */
-       for (i = 0; i < dev->n_ep; i++) {
-               struct net2280_ep       *ep;
-
-               ep = &dev->ep[i];
-               if (i && !ep->desc)
-                       continue;
-
-               t1 = readl(&ep->cfg->ep_cfg);
-               t2 = readl(&ep->regs->ep_rsp) & 0xff;
-               t = scnprintf(next, size,
-                               "\n%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s"
-                                       "irqenb %02x\n",
-                               ep->ep.name, t1, t2,
-                               (t2 & BIT(CLEAR_NAK_OUT_PACKETS))
-                                       ? "NAK " : "",
-                               (t2 & BIT(CLEAR_EP_HIDE_STATUS_PHASE))
-                                       ? "hide " : "",
-                               (t2 & BIT(CLEAR_EP_FORCE_CRC_ERROR))
-                                       ? "CRC " : "",
-                               (t2 & BIT(CLEAR_INTERRUPT_MODE))
-                                       ? "interrupt " : "",
-                               (t2 & BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE))
-                                       ? "status " : "",
-                               (t2 & BIT(CLEAR_NAK_OUT_PACKETS_MODE))
-                                       ? "NAKmode " : "",
-                               (t2 & BIT(CLEAR_ENDPOINT_TOGGLE))
-                                       ? "DATA1 " : "DATA0 ",
-                               (t2 & BIT(CLEAR_ENDPOINT_HALT))
-                                       ? "HALT " : "",
-                               readl(&ep->regs->ep_irqenb));
-               size -= t;
-               next += t;
-
-               t = scnprintf(next, size,
-                               "\tstat %08x avail %04x "
-                               "(ep%d%s-%s)%s\n",
-                               readl(&ep->regs->ep_stat),
-                               readl(&ep->regs->ep_avail),
-                               t1 & 0x0f, DIR_STRING(t1),
-                               type_string(t1 >> 8),
-                               ep->stopped ? "*" : "");
-               size -= t;
-               next += t;
-
-               if (!ep->dma)
-                       continue;
-
-               t = scnprintf(next, size,
-                               "  dma\tctl %08x stat %08x count %08x\n"
-                               "\taddr %08x desc %08x\n",
-                               readl(&ep->dma->dmactl),
-                               readl(&ep->dma->dmastat),
-                               readl(&ep->dma->dmacount),
-                               readl(&ep->dma->dmaaddr),
-                               readl(&ep->dma->dmadesc));
-               size -= t;
-               next += t;
-
-       }
-
-       /* Indexed Registers (none yet) */
-
-       /* Statistics */
-       t = scnprintf(next, size, "\nirqs:  ");
-       size -= t;
-       next += t;
-       for (i = 0; i < dev->n_ep; i++) {
-               struct net2280_ep       *ep;
-
-               ep = &dev->ep[i];
-               if (i && !ep->irqs)
-                       continue;
-               t = scnprintf(next, size, " %s/%lu", ep->ep.name, ep->irqs);
-               size -= t;
-               next += t;
-
-       }
-       t = scnprintf(next, size, "\n");
-       size -= t;
-       next += t;
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return PAGE_SIZE - size;
-}
-static DEVICE_ATTR_RO(registers);
-
-static ssize_t queues_show(struct device *_dev, struct device_attribute *attr,
-                          char *buf)
-{
-       struct net2280          *dev;
-       char                    *next;
-       unsigned                size;
-       unsigned long           flags;
-       int                     i;
-
-       dev = dev_get_drvdata(_dev);
-       next = buf;
-       size = PAGE_SIZE;
-       spin_lock_irqsave(&dev->lock, flags);
-
-       for (i = 0; i < dev->n_ep; i++) {
-               struct net2280_ep               *ep = &dev->ep[i];
-               struct net2280_request          *req;
-               int                             t;
-
-               if (i != 0) {
-                       const struct usb_endpoint_descriptor    *d;
-
-                       d = ep->desc;
-                       if (!d)
-                               continue;
-                       t = d->bEndpointAddress;
-                       t = scnprintf(next, size,
-                               "\n%s (ep%d%s-%s) max %04x %s fifo %d\n",
-                               ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK,
-                               (t & USB_DIR_IN) ? "in" : "out",
-                               type_string(d->bmAttributes),
-                               usb_endpoint_maxp(d) & 0x1fff,
-                               ep->dma ? "dma" : "pio", ep->fifo_size
-                               );
-               } else /* ep0 should only have one transfer queued */
-                       t = scnprintf(next, size, "ep0 max 64 pio %s\n",
-                                       ep->is_in ? "in" : "out");
-               if (t <= 0 || t > size)
-                       goto done;
-               size -= t;
-               next += t;
-
-               if (list_empty(&ep->queue)) {
-                       t = scnprintf(next, size, "\t(nothing queued)\n");
-                       if (t <= 0 || t > size)
-                               goto done;
-                       size -= t;
-                       next += t;
-                       continue;
-               }
-               list_for_each_entry(req, &ep->queue, queue) {
-                       if (ep->dma && req->td_dma == readl(&ep->dma->dmadesc))
-                               t = scnprintf(next, size,
-                                       "\treq %p len %d/%d "
-                                       "buf %p (dmacount %08x)\n",
-                                       &req->req, req->req.actual,
-                                       req->req.length, req->req.buf,
-                                       readl(&ep->dma->dmacount));
-                       else
-                               t = scnprintf(next, size,
-                                       "\treq %p len %d/%d buf %p\n",
-                                       &req->req, req->req.actual,
-                                       req->req.length, req->req.buf);
-                       if (t <= 0 || t > size)
-                               goto done;
-                       size -= t;
-                       next += t;
-
-                       if (ep->dma) {
-                               struct net2280_dma      *td;
-
-                               td = req->td;
-                               t = scnprintf(next, size, "\t    td %08x "
-                                       " count %08x buf %08x desc %08x\n",
-                                       (u32) req->td_dma,
-                                       le32_to_cpu(td->dmacount),
-                                       le32_to_cpu(td->dmaaddr),
-                                       le32_to_cpu(td->dmadesc));
-                               if (t <= 0 || t > size)
-                                       goto done;
-                               size -= t;
-                               next += t;
-                       }
-               }
-       }
-
-done:
-       spin_unlock_irqrestore(&dev->lock, flags);
-       return PAGE_SIZE - size;
-}
-static DEVICE_ATTR_RO(queues);
-
-
-#else
-
-#define device_create_file(a, b)       (0)
-#define device_remove_file(a, b)       do { } while (0)
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/* another driver-specific mode might be a request type doing dma
- * to/from another device fifo instead of to/from memory.
- */
-
-static void set_fifo_mode(struct net2280 *dev, int mode)
-{
-       /* keeping high bits preserves BAR2 */
-       writel((0xffff << PCI_BASE2_RANGE) | mode, &dev->regs->fifoctl);
-
-       /* always ep-{a,b,e,f} ... maybe not ep-c or ep-d */
-       INIT_LIST_HEAD(&dev->gadget.ep_list);
-       list_add_tail(&dev->ep[1].ep.ep_list, &dev->gadget.ep_list);
-       list_add_tail(&dev->ep[2].ep.ep_list, &dev->gadget.ep_list);
-       switch (mode) {
-       case 0:
-               list_add_tail(&dev->ep[3].ep.ep_list, &dev->gadget.ep_list);
-               list_add_tail(&dev->ep[4].ep.ep_list, &dev->gadget.ep_list);
-               dev->ep[1].fifo_size = dev->ep[2].fifo_size = 1024;
-               break;
-       case 1:
-               dev->ep[1].fifo_size = dev->ep[2].fifo_size = 2048;
-               break;
-       case 2:
-               list_add_tail(&dev->ep[3].ep.ep_list, &dev->gadget.ep_list);
-               dev->ep[1].fifo_size = 2048;
-               dev->ep[2].fifo_size = 1024;
-               break;
-       }
-       /* fifo sizes for ep0, ep-c, ep-d, ep-e, and ep-f never change */
-       list_add_tail(&dev->ep[5].ep.ep_list, &dev->gadget.ep_list);
-       list_add_tail(&dev->ep[6].ep.ep_list, &dev->gadget.ep_list);
-}
-
-static void defect7374_disable_data_eps(struct net2280 *dev)
-{
-       /*
-        * For Defect 7374, disable data EPs (and more):
-        *  - This phase undoes the earlier phase of the Defect 7374 workaround,
-        *    returing ep regs back to normal.
-        */
-       struct net2280_ep *ep;
-       int i;
-       unsigned char ep_sel;
-       u32 tmp_reg;
-
-       for (i = 1; i < 5; i++) {
-               ep = &dev->ep[i];
-               writel(0, &ep->cfg->ep_cfg);
-       }
-
-       /* CSROUT, CSRIN, PCIOUT, PCIIN, STATIN, RCIN */
-       for (i = 0; i < 6; i++)
-               writel(0, &dev->dep[i].dep_cfg);
-
-       for (ep_sel = 0; ep_sel <= 21; ep_sel++) {
-               /* Select an endpoint for subsequent operations: */
-               tmp_reg = readl(&dev->plregs->pl_ep_ctrl);
-               writel(((tmp_reg & ~0x1f) | ep_sel), &dev->plregs->pl_ep_ctrl);
-
-               if (ep_sel < 2 || (ep_sel > 9 && ep_sel < 14) ||
-                                       ep_sel == 18 || ep_sel == 20)
-                       continue;
-
-               /* Change settings on some selected endpoints */
-               tmp_reg = readl(&dev->plregs->pl_ep_cfg_4);
-               tmp_reg &= ~BIT(NON_CTRL_IN_TOLERATE_BAD_DIR);
-               writel(tmp_reg, &dev->plregs->pl_ep_cfg_4);
-               tmp_reg = readl(&dev->plregs->pl_ep_ctrl);
-               tmp_reg |= BIT(EP_INITIALIZED);
-               writel(tmp_reg, &dev->plregs->pl_ep_ctrl);
-       }
-}
-
-static void defect7374_enable_data_eps_zero(struct net2280 *dev)
-{
-       u32 tmp = 0, tmp_reg;
-       u32 fsmvalue, scratch;
-       int i;
-       unsigned char ep_sel;
-
-       scratch = get_idx_reg(dev->regs, SCRATCH);
-       fsmvalue = scratch & (0xf << DEFECT7374_FSM_FIELD);
-       scratch &= ~(0xf << DEFECT7374_FSM_FIELD);
-
-       /*See if firmware needs to set up for workaround*/
-       if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ) {
-               ep_warn(dev, "Operate Defect 7374 workaround soft this time");
-               ep_warn(dev, "It will operate on cold-reboot and SS connect");
-
-               /*GPEPs:*/
-               tmp = ((0 << ENDPOINT_NUMBER) | BIT(ENDPOINT_DIRECTION) |
-                      (2 << OUT_ENDPOINT_TYPE) | (2 << IN_ENDPOINT_TYPE) |
-                      ((dev->enhanced_mode) ?
-                      BIT(OUT_ENDPOINT_ENABLE) : BIT(ENDPOINT_ENABLE)) |
-                      BIT(IN_ENDPOINT_ENABLE));
-
-               for (i = 1; i < 5; i++)
-                       writel(tmp, &dev->ep[i].cfg->ep_cfg);
-
-               /* CSRIN, PCIIN, STATIN, RCIN*/
-               tmp = ((0 << ENDPOINT_NUMBER) | BIT(ENDPOINT_ENABLE));
-               writel(tmp, &dev->dep[1].dep_cfg);
-               writel(tmp, &dev->dep[3].dep_cfg);
-               writel(tmp, &dev->dep[4].dep_cfg);
-               writel(tmp, &dev->dep[5].dep_cfg);
-
-               /*Implemented for development and debug.
-                * Can be refined/tuned later.*/
-               for (ep_sel = 0; ep_sel <= 21; ep_sel++) {
-                       /* Select an endpoint for subsequent operations: */
-                       tmp_reg = readl(&dev->plregs->pl_ep_ctrl);
-                       writel(((tmp_reg & ~0x1f) | ep_sel),
-                              &dev->plregs->pl_ep_ctrl);
-
-                       if (ep_sel == 1) {
-                               tmp =
-                                   (readl(&dev->plregs->pl_ep_ctrl) |
-                                    BIT(CLEAR_ACK_ERROR_CODE) | 0);
-                               writel(tmp, &dev->plregs->pl_ep_ctrl);
-                               continue;
-                       }
-
-                       if (ep_sel == 0 || (ep_sel > 9 && ep_sel < 14) ||
-                                       ep_sel == 18  || ep_sel == 20)
-                               continue;
-
-                       tmp = (readl(&dev->plregs->pl_ep_cfg_4) |
-                                BIT(NON_CTRL_IN_TOLERATE_BAD_DIR) | 0);
-                       writel(tmp, &dev->plregs->pl_ep_cfg_4);
-
-                       tmp = readl(&dev->plregs->pl_ep_ctrl) &
-                               ~BIT(EP_INITIALIZED);
-                       writel(tmp, &dev->plregs->pl_ep_ctrl);
-
-               }
-
-               /* Set FSM to focus on the first Control Read:
-                * - Tip: Connection speed is known upon the first
-                * setup request.*/
-               scratch |= DEFECT7374_FSM_WAITING_FOR_CONTROL_READ;
-               set_idx_reg(dev->regs, SCRATCH, scratch);
-
-       } else{
-               ep_warn(dev, "Defect 7374 workaround soft will NOT operate");
-               ep_warn(dev, "It will operate on cold-reboot and SS connect");
-       }
-}
-
-/* keeping it simple:
- * - one bus driver, initted first;
- * - one function driver, initted second
- *
- * most of the work to support multiple net2280 controllers would
- * be to associate this gadget driver (yes?) with all of them, or
- * perhaps to bind specific drivers to specific devices.
- */
-
-static void usb_reset_228x(struct net2280 *dev)
-{
-       u32     tmp;
-
-       dev->gadget.speed = USB_SPEED_UNKNOWN;
-       (void) readl(&dev->usb->usbctl);
-
-       net2280_led_init(dev);
-
-       /* disable automatic responses, and irqs */
-       writel(0, &dev->usb->stdrsp);
-       writel(0, &dev->regs->pciirqenb0);
-       writel(0, &dev->regs->pciirqenb1);
-
-       /* clear old dma and irq state */
-       for (tmp = 0; tmp < 4; tmp++) {
-               struct net2280_ep       *ep = &dev->ep[tmp + 1];
-               if (ep->dma)
-                       abort_dma(ep);
-       }
-
-       writel(~0, &dev->regs->irqstat0),
-       writel(~(u32)BIT(SUSPEND_REQUEST_INTERRUPT), &dev->regs->irqstat1),
-
-       /* reset, and enable pci */
-       tmp = readl(&dev->regs->devinit) |
-               BIT(PCI_ENABLE) |
-               BIT(FIFO_SOFT_RESET) |
-               BIT(USB_SOFT_RESET) |
-               BIT(M8051_RESET);
-       writel(tmp, &dev->regs->devinit);
-
-       /* standard fifo and endpoint allocations */
-       set_fifo_mode(dev, (fifo_mode <= 2) ? fifo_mode : 0);
-}
-
-static void usb_reset_338x(struct net2280 *dev)
-{
-       u32 tmp;
-       u32 fsmvalue;
-
-       dev->gadget.speed = USB_SPEED_UNKNOWN;
-       (void)readl(&dev->usb->usbctl);
-
-       net2280_led_init(dev);
-
-       fsmvalue = get_idx_reg(dev->regs, SCRATCH) &
-                       (0xf << DEFECT7374_FSM_FIELD);
-
-       /* See if firmware needs to set up for workaround: */
-       if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ) {
-               ep_info(dev, "%s: Defect 7374 FsmValue 0x%08x\n", __func__,
-                    fsmvalue);
-       } else {
-               /* disable automatic responses, and irqs */
-               writel(0, &dev->usb->stdrsp);
-               writel(0, &dev->regs->pciirqenb0);
-               writel(0, &dev->regs->pciirqenb1);
-       }
-
-       /* clear old dma and irq state */
-       for (tmp = 0; tmp < 4; tmp++) {
-               struct net2280_ep *ep = &dev->ep[tmp + 1];
-
-               if (ep->dma)
-                       abort_dma(ep);
-       }
-
-       writel(~0, &dev->regs->irqstat0), writel(~0, &dev->regs->irqstat1);
-
-       if (fsmvalue == DEFECT7374_FSM_SS_CONTROL_READ) {
-               /* reset, and enable pci */
-               tmp = readl(&dev->regs->devinit) |
-                   BIT(PCI_ENABLE) |
-                   BIT(FIFO_SOFT_RESET) |
-                   BIT(USB_SOFT_RESET) |
-                   BIT(M8051_RESET);
-
-               writel(tmp, &dev->regs->devinit);
-       }
-
-       /* always ep-{1,2,3,4} ... maybe not ep-3 or ep-4 */
-       INIT_LIST_HEAD(&dev->gadget.ep_list);
-
-       for (tmp = 1; tmp < dev->n_ep; tmp++)
-               list_add_tail(&dev->ep[tmp].ep.ep_list, &dev->gadget.ep_list);
-
-}
-
-static void usb_reset(struct net2280 *dev)
-{
-       if (dev->quirks & PLX_LEGACY)
-               return usb_reset_228x(dev);
-       return usb_reset_338x(dev);
-}
-
-static void usb_reinit_228x(struct net2280 *dev)
-{
-       u32     tmp;
-       int     init_dma;
-
-       /* use_dma changes are ignored till next device re-init */
-       init_dma = use_dma;
-
-       /* basic endpoint init */
-       for (tmp = 0; tmp < 7; tmp++) {
-               struct net2280_ep       *ep = &dev->ep[tmp];
-
-               ep->ep.name = ep_name[tmp];
-               ep->dev = dev;
-               ep->num = tmp;
-
-               if (tmp > 0 && tmp <= 4) {
-                       ep->fifo_size = 1024;
-                       if (init_dma)
-                               ep->dma = &dev->dma[tmp - 1];
-               } else
-                       ep->fifo_size = 64;
-               ep->regs = &dev->epregs[tmp];
-               ep->cfg = &dev->epregs[tmp];
-               ep_reset_228x(dev->regs, ep);
-       }
-       usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 64);
-       usb_ep_set_maxpacket_limit(&dev->ep[5].ep, 64);
-       usb_ep_set_maxpacket_limit(&dev->ep[6].ep, 64);
-
-       dev->gadget.ep0 = &dev->ep[0].ep;
-       dev->ep[0].stopped = 0;
-       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
-
-       /* we want to prevent lowlevel/insecure access from the USB host,
-        * but erratum 0119 means this enable bit is ignored
-        */
-       for (tmp = 0; tmp < 5; tmp++)
-               writel(EP_DONTUSE, &dev->dep[tmp].dep_cfg);
-}
-
-static void usb_reinit_338x(struct net2280 *dev)
-{
-       int init_dma;
-       int i;
-       u32 tmp, val;
-       u32 fsmvalue;
-       static const u32 ne[9] = { 0, 1, 2, 3, 4, 1, 2, 3, 4 };
-       static const u32 ep_reg_addr[9] = { 0x00, 0xC0, 0x00, 0xC0, 0x00,
-                                               0x00, 0xC0, 0x00, 0xC0 };
-
-       /* use_dma changes are ignored till next device re-init */
-       init_dma = use_dma;
-
-       /* basic endpoint init */
-       for (i = 0; i < dev->n_ep; i++) {
-               struct net2280_ep *ep = &dev->ep[i];
-
-               ep->ep.name = ep_name[i];
-               ep->dev = dev;
-               ep->num = i;
-
-               if (i > 0 && i <= 4 && init_dma)
-                       ep->dma = &dev->dma[i - 1];
-
-               if (dev->enhanced_mode) {
-                       ep->cfg = &dev->epregs[ne[i]];
-                       ep->regs = (struct net2280_ep_regs __iomem *)
-                               (((void *)&dev->epregs[ne[i]]) +
-                               ep_reg_addr[i]);
-                       ep->fiforegs = &dev->fiforegs[i];
-               } else {
-                       ep->cfg = &dev->epregs[i];
-                       ep->regs = &dev->epregs[i];
-                       ep->fiforegs = &dev->fiforegs[i];
-               }
-
-               ep->fifo_size = (i != 0) ? 2048 : 512;
-
-               ep_reset_338x(dev->regs, ep);
-       }
-       usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 512);
-
-       dev->gadget.ep0 = &dev->ep[0].ep;
-       dev->ep[0].stopped = 0;
-
-       /* Link layer set up */
-       fsmvalue = get_idx_reg(dev->regs, SCRATCH) &
-                               (0xf << DEFECT7374_FSM_FIELD);
-
-       /* See if driver needs to set up for workaround: */
-       if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ)
-               ep_info(dev, "%s: Defect 7374 FsmValue %08x\n",
-                                               __func__, fsmvalue);
-       else {
-               tmp = readl(&dev->usb_ext->usbctl2) &
-                   ~(BIT(U1_ENABLE) | BIT(U2_ENABLE) | BIT(LTM_ENABLE));
-               writel(tmp, &dev->usb_ext->usbctl2);
-       }
-
-       /* Hardware Defect and Workaround */
-       val = readl(&dev->ll_lfps_regs->ll_lfps_5);
-       val &= ~(0xf << TIMER_LFPS_6US);
-       val |= 0x5 << TIMER_LFPS_6US;
-       writel(val, &dev->ll_lfps_regs->ll_lfps_5);
-
-       val = readl(&dev->ll_lfps_regs->ll_lfps_6);
-       val &= ~(0xffff << TIMER_LFPS_80US);
-       val |= 0x0100 << TIMER_LFPS_80US;
-       writel(val, &dev->ll_lfps_regs->ll_lfps_6);
-
-       /*
-        * AA_AB Errata. Issue 4. Workaround for SuperSpeed USB
-        * Hot Reset Exit Handshake may Fail in Specific Case using
-        * Default Register Settings. Workaround for Enumeration test.
-        */
-       val = readl(&dev->ll_tsn_regs->ll_tsn_counters_2);
-       val &= ~(0x1f << HOT_TX_NORESET_TS2);
-       val |= 0x10 << HOT_TX_NORESET_TS2;
-       writel(val, &dev->ll_tsn_regs->ll_tsn_counters_2);
-
-       val = readl(&dev->ll_tsn_regs->ll_tsn_counters_3);
-       val &= ~(0x1f << HOT_RX_RESET_TS2);
-       val |= 0x3 << HOT_RX_RESET_TS2;
-       writel(val, &dev->ll_tsn_regs->ll_tsn_counters_3);
-
-       /*
-        * Set Recovery Idle to Recover bit:
-        * - On SS connections, setting Recovery Idle to Recover Fmw improves
-        *   link robustness with various hosts and hubs.
-        * - It is safe to set for all connection speeds; all chip revisions.
-        * - R-M-W to leave other bits undisturbed.
-        * - Reference PLX TT-7372
-       */
-       val = readl(&dev->ll_chicken_reg->ll_tsn_chicken_bit);
-       val |= BIT(RECOVERY_IDLE_TO_RECOVER_FMW);
-       writel(val, &dev->ll_chicken_reg->ll_tsn_chicken_bit);
-
-       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
-
-       /* disable dedicated endpoints */
-       writel(0x0D, &dev->dep[0].dep_cfg);
-       writel(0x0D, &dev->dep[1].dep_cfg);
-       writel(0x0E, &dev->dep[2].dep_cfg);
-       writel(0x0E, &dev->dep[3].dep_cfg);
-       writel(0x0F, &dev->dep[4].dep_cfg);
-       writel(0x0C, &dev->dep[5].dep_cfg);
-}
-
-static void usb_reinit(struct net2280 *dev)
-{
-       if (dev->quirks & PLX_LEGACY)
-               return usb_reinit_228x(dev);
-       return usb_reinit_338x(dev);
-}
-
-static void ep0_start_228x(struct net2280 *dev)
-{
-       writel(BIT(CLEAR_EP_HIDE_STATUS_PHASE) |
-               BIT(CLEAR_NAK_OUT_PACKETS) |
-               BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE),
-               &dev->epregs[0].ep_rsp);
-
-       /*
-        * hardware optionally handles a bunch of standard requests
-        * that the API hides from drivers anyway.  have it do so.
-        * endpoint status/features are handled in software, to
-        * help pass tests for some dubious behavior.
-        */
-       writel(BIT(SET_TEST_MODE) |
-               BIT(SET_ADDRESS) |
-               BIT(DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP) |
-               BIT(GET_DEVICE_STATUS) |
-               BIT(GET_INTERFACE_STATUS),
-               &dev->usb->stdrsp);
-       writel(BIT(USB_ROOT_PORT_WAKEUP_ENABLE) |
-               BIT(SELF_POWERED_USB_DEVICE) |
-               BIT(REMOTE_WAKEUP_SUPPORT) |
-               (dev->softconnect << USB_DETECT_ENABLE) |
-               BIT(SELF_POWERED_STATUS),
-               &dev->usb->usbctl);
-
-       /* enable irqs so we can see ep0 and general operation  */
-       writel(BIT(SETUP_PACKET_INTERRUPT_ENABLE) |
-               BIT(ENDPOINT_0_INTERRUPT_ENABLE),
-               &dev->regs->pciirqenb0);
-       writel(BIT(PCI_INTERRUPT_ENABLE) |
-               BIT(PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE) |
-               BIT(PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE) |
-               BIT(PCI_RETRY_ABORT_INTERRUPT_ENABLE) |
-               BIT(VBUS_INTERRUPT_ENABLE) |
-               BIT(ROOT_PORT_RESET_INTERRUPT_ENABLE) |
-               BIT(SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE),
-               &dev->regs->pciirqenb1);
-
-       /* don't leave any writes posted */
-       (void) readl(&dev->usb->usbctl);
-}
-
-static void ep0_start_338x(struct net2280 *dev)
-{
-       u32 fsmvalue;
-
-       fsmvalue = get_idx_reg(dev->regs, SCRATCH) &
-                       (0xf << DEFECT7374_FSM_FIELD);
-
-       if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ)
-               ep_info(dev, "%s: Defect 7374 FsmValue %08x\n", __func__,
-                    fsmvalue);
-       else
-               writel(BIT(CLEAR_NAK_OUT_PACKETS_MODE) |
-                      BIT(SET_EP_HIDE_STATUS_PHASE),
-                      &dev->epregs[0].ep_rsp);
-
-       /*
-        * hardware optionally handles a bunch of standard requests
-        * that the API hides from drivers anyway.  have it do so.
-        * endpoint status/features are handled in software, to
-        * help pass tests for some dubious behavior.
-        */
-       writel(BIT(SET_ISOCHRONOUS_DELAY) |
-              BIT(SET_SEL) |
-              BIT(SET_TEST_MODE) |
-              BIT(SET_ADDRESS) |
-              BIT(GET_INTERFACE_STATUS) |
-              BIT(GET_DEVICE_STATUS),
-               &dev->usb->stdrsp);
-       dev->wakeup_enable = 1;
-       writel(BIT(USB_ROOT_PORT_WAKEUP_ENABLE) |
-              (dev->softconnect << USB_DETECT_ENABLE) |
-              BIT(DEVICE_REMOTE_WAKEUP_ENABLE),
-              &dev->usb->usbctl);
-
-       /* enable irqs so we can see ep0 and general operation  */
-       writel(BIT(SETUP_PACKET_INTERRUPT_ENABLE) |
-              BIT(ENDPOINT_0_INTERRUPT_ENABLE),
-              &dev->regs->pciirqenb0);
-       writel(BIT(PCI_INTERRUPT_ENABLE) |
-              BIT(ROOT_PORT_RESET_INTERRUPT_ENABLE) |
-              BIT(SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE) |
-              BIT(VBUS_INTERRUPT_ENABLE),
-              &dev->regs->pciirqenb1);
-
-       /* don't leave any writes posted */
-       (void)readl(&dev->usb->usbctl);
-}
-
-static void ep0_start(struct net2280 *dev)
-{
-       if (dev->quirks & PLX_LEGACY)
-               return ep0_start_228x(dev);
-       return ep0_start_338x(dev);
-}
-
-/* when a driver is successfully registered, it will receive
- * control requests including set_configuration(), which enables
- * non-control requests.  then usb traffic follows until a
- * disconnect is reported.  then a host may connect again, or
- * the driver might get unbound.
- */
-static int net2280_start(struct usb_gadget *_gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct net2280          *dev;
-       int                     retval;
-       unsigned                i;
-
-       /* insist on high speed support from the driver, since
-        * (dev->usb->xcvrdiag & FORCE_FULL_SPEED_MODE)
-        * "must not be used in normal operation"
-        */
-       if (!driver || driver->max_speed < USB_SPEED_HIGH ||
-                       !driver->setup)
-               return -EINVAL;
-
-       dev = container_of(_gadget, struct net2280, gadget);
-
-       for (i = 0; i < dev->n_ep; i++)
-               dev->ep[i].irqs = 0;
-
-       /* hook up the driver ... */
-       dev->softconnect = 1;
-       driver->driver.bus = NULL;
-       dev->driver = driver;
-
-       retval = device_create_file(&dev->pdev->dev, &dev_attr_function);
-       if (retval)
-               goto err_unbind;
-       retval = device_create_file(&dev->pdev->dev, &dev_attr_queues);
-       if (retval)
-               goto err_func;
-
-       /* Enable force-full-speed testing mode, if desired */
-       if (full_speed && (dev->quirks & PLX_LEGACY))
-               writel(BIT(FORCE_FULL_SPEED_MODE), &dev->usb->xcvrdiag);
-
-       /* ... then enable host detection and ep0; and we're ready
-        * for set_configuration as well as eventual disconnect.
-        */
-       net2280_led_active(dev, 1);
-
-       if (dev->quirks & PLX_SUPERSPEED)
-               defect7374_enable_data_eps_zero(dev);
-
-       ep0_start(dev);
-
-       ep_dbg(dev, "%s ready, usbctl %08x stdrsp %08x\n",
-                       driver->driver.name,
-                       readl(&dev->usb->usbctl),
-                       readl(&dev->usb->stdrsp));
-
-       /* pci writes may still be posted */
-       return 0;
-
-err_func:
-       device_remove_file(&dev->pdev->dev, &dev_attr_function);
-err_unbind:
-       dev->driver = NULL;
-       return retval;
-}
-
-static void stop_activity(struct net2280 *dev, struct usb_gadget_driver *driver)
-{
-       int                     i;
-
-       /* don't disconnect if it's not connected */
-       if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-               driver = NULL;
-
-       /* stop hardware; prevent new request submissions;
-        * and kill any outstanding requests.
-        */
-       usb_reset(dev);
-       for (i = 0; i < dev->n_ep; i++)
-               nuke(&dev->ep[i]);
-
-       /* report disconnect; the driver is already quiesced */
-       if (driver) {
-               spin_unlock(&dev->lock);
-               driver->disconnect(&dev->gadget);
-               spin_lock(&dev->lock);
-       }
-
-       usb_reinit(dev);
-}
-
-static int net2280_stop(struct usb_gadget *_gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct net2280  *dev;
-       unsigned long   flags;
-
-       dev = container_of(_gadget, struct net2280, gadget);
-
-       spin_lock_irqsave(&dev->lock, flags);
-       stop_activity(dev, driver);
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       dev->driver = NULL;
-
-       net2280_led_active(dev, 0);
-
-       /* Disable full-speed test mode */
-       if (dev->quirks & PLX_LEGACY)
-               writel(0, &dev->usb->xcvrdiag);
-
-       device_remove_file(&dev->pdev->dev, &dev_attr_function);
-       device_remove_file(&dev->pdev->dev, &dev_attr_queues);
-
-       ep_dbg(dev, "unregistered driver '%s'\n",
-                       driver ? driver->driver.name : "");
-
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* handle ep0, ep-e, ep-f with 64 byte packets: packet per irq.
- * also works for dma-capable endpoints, in pio mode or just
- * to manually advance the queue after short OUT transfers.
- */
-static void handle_ep_small(struct net2280_ep *ep)
-{
-       struct net2280_request  *req;
-       u32                     t;
-       /* 0 error, 1 mid-data, 2 done */
-       int                     mode = 1;
-
-       if (!list_empty(&ep->queue))
-               req = list_entry(ep->queue.next,
-                       struct net2280_request, queue);
-       else
-               req = NULL;
-
-       /* ack all, and handle what we care about */
-       t = readl(&ep->regs->ep_stat);
-       ep->irqs++;
-#if 0
-       ep_vdbg(ep->dev, "%s ack ep_stat %08x, req %p\n",
-                       ep->ep.name, t, req ? &req->req : 0);
-#endif
-       if (!ep->is_in || (ep->dev->quirks & PLX_2280))
-               writel(t & ~BIT(NAK_OUT_PACKETS), &ep->regs->ep_stat);
-       else
-               /* Added for 2282 */
-               writel(t, &ep->regs->ep_stat);
-
-       /* for ep0, monitor token irqs to catch data stage length errors
-        * and to synchronize on status.
-        *
-        * also, to defer reporting of protocol stalls ... here's where
-        * data or status first appears, handling stalls here should never
-        * cause trouble on the host side..
-        *
-        * control requests could be slightly faster without token synch for
-        * status, but status can jam up that way.
-        */
-       if (unlikely(ep->num == 0)) {
-               if (ep->is_in) {
-                       /* status; stop NAKing */
-                       if (t & BIT(DATA_OUT_PING_TOKEN_INTERRUPT)) {
-                               if (ep->dev->protocol_stall) {
-                                       ep->stopped = 1;
-                                       set_halt(ep);
-                               }
-                               if (!req)
-                                       allow_status(ep);
-                               mode = 2;
-                       /* reply to extra IN data tokens with a zlp */
-                       } else if (t & BIT(DATA_IN_TOKEN_INTERRUPT)) {
-                               if (ep->dev->protocol_stall) {
-                                       ep->stopped = 1;
-                                       set_halt(ep);
-                                       mode = 2;
-                               } else if (ep->responded &&
-                                               !req && !ep->stopped)
-                                       write_fifo(ep, NULL);
-                       }
-               } else {
-                       /* status; stop NAKing */
-                       if (t & BIT(DATA_IN_TOKEN_INTERRUPT)) {
-                               if (ep->dev->protocol_stall) {
-                                       ep->stopped = 1;
-                                       set_halt(ep);
-                               }
-                               mode = 2;
-                       /* an extra OUT token is an error */
-                       } else if (((t & BIT(DATA_OUT_PING_TOKEN_INTERRUPT)) &&
-                                       req &&
-                                       req->req.actual == req->req.length) ||
-                                       (ep->responded && !req)) {
-                               ep->dev->protocol_stall = 1;
-                               set_halt(ep);
-                               ep->stopped = 1;
-                               if (req)
-                                       done(ep, req, -EOVERFLOW);
-                               req = NULL;
-                       }
-               }
-       }
-
-       if (unlikely(!req))
-               return;
-
-       /* manual DMA queue advance after short OUT */
-       if (likely(ep->dma)) {
-               if (t & BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
-                       u32     count;
-                       int     stopped = ep->stopped;
-
-                       /* TRANSFERRED works around OUT_DONE erratum 0112.
-                        * we expect (N <= maxpacket) bytes; host wrote M.
-                        * iff (M < N) we won't ever see a DMA interrupt.
-                        */
-                       ep->stopped = 1;
-                       for (count = 0; ; t = readl(&ep->regs->ep_stat)) {
-
-                               /* any preceding dma transfers must finish.
-                                * dma handles (M >= N), may empty the queue
-                                */
-                               scan_dma_completions(ep);
-                               if (unlikely(list_empty(&ep->queue) ||
-                                               ep->out_overflow)) {
-                                       req = NULL;
-                                       break;
-                               }
-                               req = list_entry(ep->queue.next,
-                                       struct net2280_request, queue);
-
-                               /* here either (M < N), a "real" short rx;
-                                * or (M == N) and the queue didn't empty
-                                */
-                               if (likely(t & BIT(FIFO_EMPTY))) {
-                                       count = readl(&ep->dma->dmacount);
-                                       count &= DMA_BYTE_COUNT_MASK;
-                                       if (readl(&ep->dma->dmadesc)
-                                                       != req->td_dma)
-                                               req = NULL;
-                                       break;
-                               }
-                               udelay(1);
-                       }
-
-                       /* stop DMA, leave ep NAKing */
-                       writel(BIT(DMA_ABORT), &ep->dma->dmastat);
-                       spin_stop_dma(ep->dma);
-
-                       if (likely(req)) {
-                               req->td->dmacount = 0;
-                               t = readl(&ep->regs->ep_avail);
-                               dma_done(ep, req, count,
-                                       (ep->out_overflow || t)
-                                               ? -EOVERFLOW : 0);
-                       }
-
-                       /* also flush to prevent erratum 0106 trouble */
-                       if (unlikely(ep->out_overflow ||
-                                       (ep->dev->chiprev == 0x0100 &&
-                                       ep->dev->gadget.speed
-                                       == USB_SPEED_FULL))) {
-                               out_flush(ep);
-                               ep->out_overflow = 0;
-                       }
-
-                       /* (re)start dma if needed, stop NAKing */
-                       ep->stopped = stopped;
-                       if (!list_empty(&ep->queue))
-                               restart_dma(ep);
-               } else
-                       ep_dbg(ep->dev, "%s dma ep_stat %08x ??\n",
-                                       ep->ep.name, t);
-               return;
-
-       /* data packet(s) received (in the fifo, OUT) */
-       } else if (t & BIT(DATA_PACKET_RECEIVED_INTERRUPT)) {
-               if (read_fifo(ep, req) && ep->num != 0)
-                       mode = 2;
-
-       /* data packet(s) transmitted (IN) */
-       } else if (t & BIT(DATA_PACKET_TRANSMITTED_INTERRUPT)) {
-               unsigned        len;
-
-               len = req->req.length - req->req.actual;
-               if (len > ep->ep.maxpacket)
-                       len = ep->ep.maxpacket;
-               req->req.actual += len;
-
-               /* if we wrote it all, we're usually done */
-               /* send zlps until the status stage */
-               if ((req->req.actual == req->req.length) &&
-                       (!req->req.zero || len != ep->ep.maxpacket) && ep->num)
-                               mode = 2;
-
-       /* there was nothing to do ...  */
-       } else if (mode == 1)
-               return;
-
-       /* done */
-       if (mode == 2) {
-               /* stream endpoints often resubmit/unlink in completion */
-               done(ep, req, 0);
-
-               /* maybe advance queue to next request */
-               if (ep->num == 0) {
-                       /* NOTE:  net2280 could let gadget driver start the
-                        * status stage later. since not all controllers let
-                        * them control that, the api doesn't (yet) allow it.
-                        */
-                       if (!ep->stopped)
-                               allow_status(ep);
-                       req = NULL;
-               } else {
-                       if (!list_empty(&ep->queue) && !ep->stopped)
-                               req = list_entry(ep->queue.next,
-                                       struct net2280_request, queue);
-                       else
-                               req = NULL;
-                       if (req && !ep->is_in)
-                               stop_out_naking(ep);
-               }
-       }
-
-       /* is there a buffer for the next packet?
-        * for best streaming performance, make sure there is one.
-        */
-       if (req && !ep->stopped) {
-
-               /* load IN fifo with next packet (may be zlp) */
-               if (t & BIT(DATA_PACKET_TRANSMITTED_INTERRUPT))
-                       write_fifo(ep, &req->req);
-       }
-}
-
-static struct net2280_ep *get_ep_by_addr(struct net2280 *dev, u16 wIndex)
-{
-       struct net2280_ep       *ep;
-
-       if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
-               return &dev->ep[0];
-       list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
-               u8      bEndpointAddress;
-
-               if (!ep->desc)
-                       continue;
-               bEndpointAddress = ep->desc->bEndpointAddress;
-               if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
-                       continue;
-               if ((wIndex & 0x0f) == (bEndpointAddress & 0x0f))
-                       return ep;
-       }
-       return NULL;
-}
-
-static void defect7374_workaround(struct net2280 *dev, struct usb_ctrlrequest r)
-{
-       u32 scratch, fsmvalue;
-       u32 ack_wait_timeout, state;
-
-       /* Workaround for Defect 7374 (U1/U2 erroneously rejected): */
-       scratch = get_idx_reg(dev->regs, SCRATCH);
-       fsmvalue = scratch & (0xf << DEFECT7374_FSM_FIELD);
-       scratch &= ~(0xf << DEFECT7374_FSM_FIELD);
-
-       if (!((fsmvalue == DEFECT7374_FSM_WAITING_FOR_CONTROL_READ) &&
-                               (r.bRequestType & USB_DIR_IN)))
-               return;
-
-       /* This is the first Control Read for this connection: */
-       if (!(readl(&dev->usb->usbstat) & BIT(SUPER_SPEED_MODE))) {
-               /*
-                * Connection is NOT SS:
-                * - Connection must be FS or HS.
-                * - This FSM state should allow workaround software to
-                * run after the next USB connection.
-                */
-               scratch |= DEFECT7374_FSM_NON_SS_CONTROL_READ;
-               goto restore_data_eps;
-       }
-
-       /* Connection is SS: */
-       for (ack_wait_timeout = 0;
-                       ack_wait_timeout < DEFECT_7374_NUMBEROF_MAX_WAIT_LOOPS;
-                       ack_wait_timeout++) {
-
-               state = readl(&dev->plregs->pl_ep_status_1)
-                       & (0xff << STATE);
-               if ((state >= (ACK_GOOD_NORMAL << STATE)) &&
-                       (state <= (ACK_GOOD_MORE_ACKS_TO_COME << STATE))) {
-                       scratch |= DEFECT7374_FSM_SS_CONTROL_READ;
-                       break;
-               }
-
-               /*
-                * We have not yet received host's Data Phase ACK
-                * - Wait and try again.
-                */
-               udelay(DEFECT_7374_PROCESSOR_WAIT_TIME);
-
-               continue;
-       }
-
-
-       if (ack_wait_timeout >= DEFECT_7374_NUMBEROF_MAX_WAIT_LOOPS) {
-               ep_err(dev, "FAIL: Defect 7374 workaround waited but failed "
-               "to detect SS host's data phase ACK.");
-               ep_err(dev, "PL_EP_STATUS_1(23:16):.Expected from 0x11 to 0x16"
-               "got 0x%2.2x.\n", state >> STATE);
-       } else {
-               ep_warn(dev, "INFO: Defect 7374 workaround waited about\n"
-               "%duSec for Control Read Data Phase ACK\n",
-                       DEFECT_7374_PROCESSOR_WAIT_TIME * ack_wait_timeout);
-       }
-
-restore_data_eps:
-       /*
-        * Restore data EPs to their pre-workaround settings (disabled,
-        * initialized, and other details).
-        */
-       defect7374_disable_data_eps(dev);
-
-       set_idx_reg(dev->regs, SCRATCH, scratch);
-
-       return;
-}
-
-static void ep_stall(struct net2280_ep *ep, int stall)
-{
-       struct net2280 *dev = ep->dev;
-       u32 val;
-       static const u32 ep_pl[9] = { 0, 3, 4, 7, 8, 2, 5, 6, 9 };
-
-       if (stall) {
-               writel(BIT(SET_ENDPOINT_HALT) |
-                      /* BIT(SET_NAK_PACKETS) | */
-                      BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE),
-                      &ep->regs->ep_rsp);
-               ep->is_halt = 1;
-       } else {
-               if (dev->gadget.speed == USB_SPEED_SUPER) {
-                       /*
-                        * Workaround for SS SeqNum not cleared via
-                        * Endpoint Halt (Clear) bit. select endpoint
-                        */
-                       val = readl(&dev->plregs->pl_ep_ctrl);
-                       val = (val & ~0x1f) | ep_pl[ep->num];
-                       writel(val, &dev->plregs->pl_ep_ctrl);
-
-                       val |= BIT(SEQUENCE_NUMBER_RESET);
-                       writel(val, &dev->plregs->pl_ep_ctrl);
-               }
-               val = readl(&ep->regs->ep_rsp);
-               val |= BIT(CLEAR_ENDPOINT_HALT) |
-                       BIT(CLEAR_ENDPOINT_TOGGLE);
-               writel(val,
-                      /* | BIT(CLEAR_NAK_PACKETS),*/
-                      &ep->regs->ep_rsp);
-               ep->is_halt = 0;
-               val = readl(&ep->regs->ep_rsp);
-       }
-}
-
-static void ep_stdrsp(struct net2280_ep *ep, int value, int wedged)
-{
-       /* set/clear, then synch memory views with the device */
-       if (value) {
-               ep->stopped = 1;
-               if (ep->num == 0)
-                       ep->dev->protocol_stall = 1;
-               else {
-                       if (ep->dma)
-                               ep_stop_dma(ep);
-                       ep_stall(ep, true);
-               }
-
-               if (wedged)
-                       ep->wedged = 1;
-       } else {
-               ep->stopped = 0;
-               ep->wedged = 0;
-
-               ep_stall(ep, false);
-
-               /* Flush the queue */
-               if (!list_empty(&ep->queue)) {
-                       struct net2280_request *req =
-                           list_entry(ep->queue.next, struct net2280_request,
-                                      queue);
-                       if (ep->dma)
-                               resume_dma(ep);
-                       else {
-                               if (ep->is_in)
-                                       write_fifo(ep, &req->req);
-                               else {
-                                       if (read_fifo(ep, req))
-                                               done(ep, req, 0);
-                               }
-                       }
-               }
-       }
-}
-
-static void handle_stat0_irqs_superspeed(struct net2280 *dev,
-               struct net2280_ep *ep, struct usb_ctrlrequest r)
-{
-       int tmp = 0;
-
-#define        w_value         le16_to_cpu(r.wValue)
-#define        w_index         le16_to_cpu(r.wIndex)
-#define        w_length        le16_to_cpu(r.wLength)
-
-       switch (r.bRequest) {
-               struct net2280_ep *e;
-               u16 status;
-
-       case USB_REQ_SET_CONFIGURATION:
-               dev->addressed_state = !w_value;
-               goto usb3_delegate;
-
-       case USB_REQ_GET_STATUS:
-               switch (r.bRequestType) {
-               case (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE):
-                       status = dev->wakeup_enable ? 0x02 : 0x00;
-                       if (dev->selfpowered)
-                               status |= BIT(0);
-                       status |= (dev->u1_enable << 2 | dev->u2_enable << 3 |
-                                                       dev->ltm_enable << 4);
-                       writel(0, &dev->epregs[0].ep_irqenb);
-                       set_fifo_bytecount(ep, sizeof(status));
-                       writel((__force u32) status, &dev->epregs[0].ep_data);
-                       allow_status_338x(ep);
-                       break;
-
-               case (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
-                       e = get_ep_by_addr(dev, w_index);
-                       if (!e)
-                               goto do_stall3;
-                       status = readl(&e->regs->ep_rsp) &
-                                               BIT(CLEAR_ENDPOINT_HALT);
-                       writel(0, &dev->epregs[0].ep_irqenb);
-                       set_fifo_bytecount(ep, sizeof(status));
-                       writel((__force u32) status, &dev->epregs[0].ep_data);
-                       allow_status_338x(ep);
-                       break;
-
-               default:
-                       goto usb3_delegate;
-               }
-               break;
-
-       case USB_REQ_CLEAR_FEATURE:
-               switch (r.bRequestType) {
-               case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE):
-                       if (!dev->addressed_state) {
-                               switch (w_value) {
-                               case USB_DEVICE_U1_ENABLE:
-                                       dev->u1_enable = 0;
-                                       writel(readl(&dev->usb_ext->usbctl2) &
-                                               ~BIT(U1_ENABLE),
-                                               &dev->usb_ext->usbctl2);
-                                       allow_status_338x(ep);
-                                       goto next_endpoints3;
-
-                               case USB_DEVICE_U2_ENABLE:
-                                       dev->u2_enable = 0;
-                                       writel(readl(&dev->usb_ext->usbctl2) &
-                                               ~BIT(U2_ENABLE),
-                                               &dev->usb_ext->usbctl2);
-                                       allow_status_338x(ep);
-                                       goto next_endpoints3;
-
-                               case USB_DEVICE_LTM_ENABLE:
-                                       dev->ltm_enable = 0;
-                                       writel(readl(&dev->usb_ext->usbctl2) &
-                                               ~BIT(LTM_ENABLE),
-                                               &dev->usb_ext->usbctl2);
-                                       allow_status_338x(ep);
-                                       goto next_endpoints3;
-
-                               default:
-                                       break;
-                               }
-                       }
-                       if (w_value == USB_DEVICE_REMOTE_WAKEUP) {
-                               dev->wakeup_enable = 0;
-                               writel(readl(&dev->usb->usbctl) &
-                                       ~BIT(DEVICE_REMOTE_WAKEUP_ENABLE),
-                                       &dev->usb->usbctl);
-                               allow_status_338x(ep);
-                               break;
-                       }
-                       goto usb3_delegate;
-
-               case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
-                       e = get_ep_by_addr(dev, w_index);
-                       if (!e)
-                               goto do_stall3;
-                       if (w_value != USB_ENDPOINT_HALT)
-                               goto do_stall3;
-                       ep_vdbg(dev, "%s clear halt\n", e->ep.name);
-                       ep_stall(e, false);
-                       if (!list_empty(&e->queue) && e->td_dma)
-                               restart_dma(e);
-                       allow_status(ep);
-                       ep->stopped = 1;
-                       break;
-
-               default:
-                       goto usb3_delegate;
-               }
-               break;
-       case USB_REQ_SET_FEATURE:
-               switch (r.bRequestType) {
-               case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE):
-                       if (!dev->addressed_state) {
-                               switch (w_value) {
-                               case USB_DEVICE_U1_ENABLE:
-                                       dev->u1_enable = 1;
-                                       writel(readl(&dev->usb_ext->usbctl2) |
-                                               BIT(U1_ENABLE),
-                                               &dev->usb_ext->usbctl2);
-                                       allow_status_338x(ep);
-                                       goto next_endpoints3;
-
-                               case USB_DEVICE_U2_ENABLE:
-                                       dev->u2_enable = 1;
-                                       writel(readl(&dev->usb_ext->usbctl2) |
-                                               BIT(U2_ENABLE),
-                                               &dev->usb_ext->usbctl2);
-                                       allow_status_338x(ep);
-                                       goto next_endpoints3;
-
-                               case USB_DEVICE_LTM_ENABLE:
-                                       dev->ltm_enable = 1;
-                                       writel(readl(&dev->usb_ext->usbctl2) |
-                                               BIT(LTM_ENABLE),
-                                               &dev->usb_ext->usbctl2);
-                                       allow_status_338x(ep);
-                                       goto next_endpoints3;
-                               default:
-                                       break;
-                               }
-                       }
-
-                       if (w_value == USB_DEVICE_REMOTE_WAKEUP) {
-                               dev->wakeup_enable = 1;
-                               writel(readl(&dev->usb->usbctl) |
-                                       BIT(DEVICE_REMOTE_WAKEUP_ENABLE),
-                                       &dev->usb->usbctl);
-                               allow_status_338x(ep);
-                               break;
-                       }
-                       goto usb3_delegate;
-
-               case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
-                       e = get_ep_by_addr(dev, w_index);
-                       if (!e || (w_value != USB_ENDPOINT_HALT))
-                               goto do_stall3;
-                       ep_stdrsp(e, true, false);
-                       allow_status_338x(ep);
-                       break;
-
-               default:
-                       goto usb3_delegate;
-               }
-
-               break;
-       default:
-
-usb3_delegate:
-               ep_vdbg(dev, "setup %02x.%02x v%04x i%04x l%04x ep_cfg %08x\n",
-                               r.bRequestType, r.bRequest,
-                               w_value, w_index, w_length,
-                               readl(&ep->cfg->ep_cfg));
-
-               ep->responded = 0;
-               spin_unlock(&dev->lock);
-               tmp = dev->driver->setup(&dev->gadget, &r);
-               spin_lock(&dev->lock);
-       }
-do_stall3:
-       if (tmp < 0) {
-               ep_vdbg(dev, "req %02x.%02x protocol STALL; stat %d\n",
-                               r.bRequestType, r.bRequest, tmp);
-               dev->protocol_stall = 1;
-               /* TD 9.9 Halt Endpoint test. TD 9.22 Set feature test */
-               ep_stall(ep, true);
-       }
-
-next_endpoints3:
-
-#undef w_value
-#undef w_index
-#undef w_length
-
-       return;
-}
-
-static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
-{
-       struct net2280_ep       *ep;
-       u32                     num, scratch;
-
-       /* most of these don't need individual acks */
-       stat &= ~BIT(INTA_ASSERTED);
-       if (!stat)
-               return;
-       /* ep_dbg(dev, "irqstat0 %04x\n", stat); */
-
-       /* starting a control request? */
-       if (unlikely(stat & BIT(SETUP_PACKET_INTERRUPT))) {
-               union {
-                       u32                     raw[2];
-                       struct usb_ctrlrequest  r;
-               } u;
-               int                             tmp;
-               struct net2280_request          *req;
-
-               if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
-                       u32 val = readl(&dev->usb->usbstat);
-                       if (val & BIT(SUPER_SPEED)) {
-                               dev->gadget.speed = USB_SPEED_SUPER;
-                               usb_ep_set_maxpacket_limit(&dev->ep[0].ep,
-                                               EP0_SS_MAX_PACKET_SIZE);
-                       } else if (val & BIT(HIGH_SPEED)) {
-                               dev->gadget.speed = USB_SPEED_HIGH;
-                               usb_ep_set_maxpacket_limit(&dev->ep[0].ep,
-                                               EP0_HS_MAX_PACKET_SIZE);
-                       } else {
-                               dev->gadget.speed = USB_SPEED_FULL;
-                               usb_ep_set_maxpacket_limit(&dev->ep[0].ep,
-                                               EP0_HS_MAX_PACKET_SIZE);
-                       }
-                       net2280_led_speed(dev, dev->gadget.speed);
-                       ep_dbg(dev, "%s\n",
-                                       usb_speed_string(dev->gadget.speed));
-               }
-
-               ep = &dev->ep[0];
-               ep->irqs++;
-
-               /* make sure any leftover request state is cleared */
-               stat &= ~BIT(ENDPOINT_0_INTERRUPT);
-               while (!list_empty(&ep->queue)) {
-                       req = list_entry(ep->queue.next,
-                                       struct net2280_request, queue);
-                       done(ep, req, (req->req.actual == req->req.length)
-                                               ? 0 : -EPROTO);
-               }
-               ep->stopped = 0;
-               dev->protocol_stall = 0;
-               if (dev->quirks & PLX_SUPERSPEED)
-                       ep->is_halt = 0;
-               else{
-                       if (ep->dev->quirks & PLX_2280)
-                               tmp = BIT(FIFO_OVERFLOW) |
-                                   BIT(FIFO_UNDERFLOW);
-                       else
-                               tmp = 0;
-
-                       writel(tmp | BIT(TIMEOUT) |
-                                  BIT(USB_STALL_SENT) |
-                                  BIT(USB_IN_NAK_SENT) |
-                                  BIT(USB_IN_ACK_RCVD) |
-                                  BIT(USB_OUT_PING_NAK_SENT) |
-                                  BIT(USB_OUT_ACK_SENT) |
-                                  BIT(SHORT_PACKET_OUT_DONE_INTERRUPT) |
-                                  BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT) |
-                                  BIT(DATA_PACKET_RECEIVED_INTERRUPT) |
-                                  BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
-                                  BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
-                                  BIT(DATA_IN_TOKEN_INTERRUPT),
-                                  &ep->regs->ep_stat);
-               }
-               u.raw[0] = readl(&dev->usb->setup0123);
-               u.raw[1] = readl(&dev->usb->setup4567);
-
-               cpu_to_le32s(&u.raw[0]);
-               cpu_to_le32s(&u.raw[1]);
-
-               if (dev->quirks & PLX_SUPERSPEED)
-                       defect7374_workaround(dev, u.r);
-
-               tmp = 0;
-
-#define        w_value         le16_to_cpu(u.r.wValue)
-#define        w_index         le16_to_cpu(u.r.wIndex)
-#define        w_length        le16_to_cpu(u.r.wLength)
-
-               /* ack the irq */
-               writel(BIT(SETUP_PACKET_INTERRUPT), &dev->regs->irqstat0);
-               stat ^= BIT(SETUP_PACKET_INTERRUPT);
-
-               /* watch control traffic at the token level, and force
-                * synchronization before letting the status stage happen.
-                * FIXME ignore tokens we'll NAK, until driver responds.
-                * that'll mean a lot less irqs for some drivers.
-                */
-               ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0;
-               if (ep->is_in) {
-                       scratch = BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
-                               BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
-                               BIT(DATA_IN_TOKEN_INTERRUPT);
-                       stop_out_naking(ep);
-               } else
-                       scratch = BIT(DATA_PACKET_RECEIVED_INTERRUPT) |
-                               BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
-                               BIT(DATA_IN_TOKEN_INTERRUPT);
-               writel(scratch, &dev->epregs[0].ep_irqenb);
-
-               /* we made the hardware handle most lowlevel requests;
-                * everything else goes uplevel to the gadget code.
-                */
-               ep->responded = 1;
-
-               if (dev->gadget.speed == USB_SPEED_SUPER) {
-                       handle_stat0_irqs_superspeed(dev, ep, u.r);
-                       goto next_endpoints;
-               }
-
-               switch (u.r.bRequest) {
-               case USB_REQ_GET_STATUS: {
-                       struct net2280_ep       *e;
-                       __le32                  status;
-
-                       /* hw handles device and interface status */
-                       if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
-                               goto delegate;
-                       e = get_ep_by_addr(dev, w_index);
-                       if (!e || w_length > 2)
-                               goto do_stall;
-
-                       if (readl(&e->regs->ep_rsp) & BIT(SET_ENDPOINT_HALT))
-                               status = cpu_to_le32(1);
-                       else
-                               status = cpu_to_le32(0);
-
-                       /* don't bother with a request object! */
-                       writel(0, &dev->epregs[0].ep_irqenb);
-                       set_fifo_bytecount(ep, w_length);
-                       writel((__force u32)status, &dev->epregs[0].ep_data);
-                       allow_status(ep);
-                       ep_vdbg(dev, "%s stat %02x\n", ep->ep.name, status);
-                       goto next_endpoints;
-                       }
-                       break;
-               case USB_REQ_CLEAR_FEATURE: {
-                       struct net2280_ep       *e;
-
-                       /* hw handles device features */
-                       if (u.r.bRequestType != USB_RECIP_ENDPOINT)
-                               goto delegate;
-                       if (w_value != USB_ENDPOINT_HALT || w_length != 0)
-                               goto do_stall;
-                       e = get_ep_by_addr(dev, w_index);
-                       if (!e)
-                               goto do_stall;
-                       if (e->wedged) {
-                               ep_vdbg(dev, "%s wedged, halt not cleared\n",
-                                               ep->ep.name);
-                       } else {
-                               ep_vdbg(dev, "%s clear halt\n", e->ep.name);
-                               clear_halt(e);
-                               if ((ep->dev->quirks & PLX_SUPERSPEED) &&
-                                       !list_empty(&e->queue) && e->td_dma)
-                                               restart_dma(e);
-                       }
-                       allow_status(ep);
-                       goto next_endpoints;
-                       }
-                       break;
-               case USB_REQ_SET_FEATURE: {
-                       struct net2280_ep       *e;
-
-                       /* hw handles device features */
-                       if (u.r.bRequestType != USB_RECIP_ENDPOINT)
-                               goto delegate;
-                       if (w_value != USB_ENDPOINT_HALT || w_length != 0)
-                               goto do_stall;
-                       e = get_ep_by_addr(dev, w_index);
-                       if (!e)
-                               goto do_stall;
-                       if (e->ep.name == ep0name)
-                               goto do_stall;
-                       set_halt(e);
-                       if ((dev->quirks & PLX_SUPERSPEED) && e->dma)
-                               abort_dma(e);
-                       allow_status(ep);
-                       ep_vdbg(dev, "%s set halt\n", ep->ep.name);
-                       goto next_endpoints;
-                       }
-                       break;
-               default:
-delegate:
-                       ep_vdbg(dev, "setup %02x.%02x v%04x i%04x l%04x "
-                               "ep_cfg %08x\n",
-                               u.r.bRequestType, u.r.bRequest,
-                               w_value, w_index, w_length,
-                               readl(&ep->cfg->ep_cfg));
-                       ep->responded = 0;
-                       spin_unlock(&dev->lock);
-                       tmp = dev->driver->setup(&dev->gadget, &u.r);
-                       spin_lock(&dev->lock);
-               }
-
-               /* stall ep0 on error */
-               if (tmp < 0) {
-do_stall:
-                       ep_vdbg(dev, "req %02x.%02x protocol STALL; stat %d\n",
-                                       u.r.bRequestType, u.r.bRequest, tmp);
-                       dev->protocol_stall = 1;
-               }
-
-               /* some in/out token irq should follow; maybe stall then.
-                * driver must queue a request (even zlp) or halt ep0
-                * before the host times out.
-                */
-       }
-
-#undef w_value
-#undef w_index
-#undef w_length
-
-next_endpoints:
-       /* endpoint data irq ? */
-       scratch = stat & 0x7f;
-       stat &= ~0x7f;
-       for (num = 0; scratch; num++) {
-               u32             t;
-
-               /* do this endpoint's FIFO and queue need tending? */
-               t = BIT(num);
-               if ((scratch & t) == 0)
-                       continue;
-               scratch ^= t;
-
-               ep = &dev->ep[num];
-               handle_ep_small(ep);
-       }
-
-       if (stat)
-               ep_dbg(dev, "unhandled irqstat0 %08x\n", stat);
-}
-
-#define DMA_INTERRUPTS (BIT(DMA_D_INTERRUPT) | \
-               BIT(DMA_C_INTERRUPT) | \
-               BIT(DMA_B_INTERRUPT) | \
-               BIT(DMA_A_INTERRUPT))
-#define        PCI_ERROR_INTERRUPTS ( \
-               BIT(PCI_MASTER_ABORT_RECEIVED_INTERRUPT) | \
-               BIT(PCI_TARGET_ABORT_RECEIVED_INTERRUPT) | \
-               BIT(PCI_RETRY_ABORT_INTERRUPT))
-
-static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
-{
-       struct net2280_ep       *ep;
-       u32                     tmp, num, mask, scratch;
-
-       /* after disconnect there's nothing else to do! */
-       tmp = BIT(VBUS_INTERRUPT) | BIT(ROOT_PORT_RESET_INTERRUPT);
-       mask = BIT(SUPER_SPEED) | BIT(HIGH_SPEED) | BIT(FULL_SPEED);
-
-       /* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
-        * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRUPT set and
-        * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT
-        * only indicates a change in the reset state).
-        */
-       if (stat & tmp) {
-               writel(tmp, &dev->regs->irqstat1);
-               if ((((stat & BIT(ROOT_PORT_RESET_INTERRUPT)) &&
-                               (readl(&dev->usb->usbstat) & mask)) ||
-                               ((readl(&dev->usb->usbctl) &
-                                       BIT(VBUS_PIN)) == 0)) &&
-                               (dev->gadget.speed != USB_SPEED_UNKNOWN)) {
-                       ep_dbg(dev, "disconnect %s\n",
-                                       dev->driver->driver.name);
-                       stop_activity(dev, dev->driver);
-                       ep0_start(dev);
-                       return;
-               }
-               stat &= ~tmp;
-
-               /* vBUS can bounce ... one of many reasons to ignore the
-                * notion of hotplug events on bus connect/disconnect!
-                */
-               if (!stat)
-                       return;
-       }
-
-       /* NOTE: chip stays in PCI D0 state for now, but it could
-        * enter D1 to save more power
-        */
-       tmp = BIT(SUSPEND_REQUEST_CHANGE_INTERRUPT);
-       if (stat & tmp) {
-               writel(tmp, &dev->regs->irqstat1);
-               if (stat & BIT(SUSPEND_REQUEST_INTERRUPT)) {
-                       if (dev->driver->suspend)
-                               dev->driver->suspend(&dev->gadget);
-                       if (!enable_suspend)
-                               stat &= ~BIT(SUSPEND_REQUEST_INTERRUPT);
-               } else {
-                       if (dev->driver->resume)
-                               dev->driver->resume(&dev->gadget);
-                       /* at high speed, note erratum 0133 */
-               }
-               stat &= ~tmp;
-       }
-
-       /* clear any other status/irqs */
-       if (stat)
-               writel(stat, &dev->regs->irqstat1);
-
-       /* some status we can just ignore */
-       if (dev->quirks & PLX_2280)
-               stat &= ~(BIT(CONTROL_STATUS_INTERRUPT) |
-                         BIT(SUSPEND_REQUEST_INTERRUPT) |
-                         BIT(RESUME_INTERRUPT) |
-                         BIT(SOF_INTERRUPT));
-       else
-               stat &= ~(BIT(CONTROL_STATUS_INTERRUPT) |
-                         BIT(RESUME_INTERRUPT) |
-                         BIT(SOF_DOWN_INTERRUPT) |
-                         BIT(SOF_INTERRUPT));
-
-       if (!stat)
-               return;
-       /* ep_dbg(dev, "irqstat1 %08x\n", stat);*/
-
-       /* DMA status, for ep-{a,b,c,d} */
-       scratch = stat & DMA_INTERRUPTS;
-       stat &= ~DMA_INTERRUPTS;
-       scratch >>= 9;
-       for (num = 0; scratch; num++) {
-               struct net2280_dma_regs __iomem *dma;
-
-               tmp = BIT(num);
-               if ((tmp & scratch) == 0)
-                       continue;
-               scratch ^= tmp;
-
-               ep = &dev->ep[num + 1];
-               dma = ep->dma;
-
-               if (!dma)
-                       continue;
-
-               /* clear ep's dma status */
-               tmp = readl(&dma->dmastat);
-               writel(tmp, &dma->dmastat);
-
-               /* dma sync*/
-               if (dev->quirks & PLX_SUPERSPEED) {
-                       u32 r_dmacount = readl(&dma->dmacount);
-                       if (!ep->is_in &&  (r_dmacount & 0x00FFFFFF) &&
-                           (tmp & BIT(DMA_TRANSACTION_DONE_INTERRUPT)))
-                               continue;
-               }
-
-               /* chaining should stop on abort, short OUT from fifo,
-                * or (stat0 codepath) short OUT transfer.
-                */
-               if (!use_dma_chaining) {
-                       if (!(tmp & BIT(DMA_TRANSACTION_DONE_INTERRUPT))) {
-                               ep_dbg(ep->dev, "%s no xact done? %08x\n",
-                                       ep->ep.name, tmp);
-                               continue;
-                       }
-                       stop_dma(ep->dma);
-               }
-
-               /* OUT transfers terminate when the data from the
-                * host is in our memory.  Process whatever's done.
-                * On this path, we know transfer's last packet wasn't
-                * less than req->length. NAK_OUT_PACKETS may be set,
-                * or the FIFO may already be holding new packets.
-                *
-                * IN transfers can linger in the FIFO for a very
-                * long time ... we ignore that for now, accounting
-                * precisely (like PIO does) needs per-packet irqs
-                */
-               scan_dma_completions(ep);
-
-               /* disable dma on inactive queues; else maybe restart */
-               if (list_empty(&ep->queue)) {
-                       if (use_dma_chaining)
-                               stop_dma(ep->dma);
-               } else {
-                       tmp = readl(&dma->dmactl);
-                       if (!use_dma_chaining || (tmp & BIT(DMA_ENABLE)) == 0)
-                               restart_dma(ep);
-                       else if (ep->is_in && use_dma_chaining) {
-                               struct net2280_request  *req;
-                               __le32                  dmacount;
-
-                               /* the descriptor at the head of the chain
-                                * may still have VALID_BIT clear; that's
-                                * used to trigger changing DMA_FIFO_VALIDATE
-                                * (affects automagic zlp writes).
-                                */
-                               req = list_entry(ep->queue.next,
-                                               struct net2280_request, queue);
-                               dmacount = req->td->dmacount;
-                               dmacount &= cpu_to_le32(BIT(VALID_BIT) |
-                                               DMA_BYTE_COUNT_MASK);
-                               if (dmacount && (dmacount & valid_bit) == 0)
-                                       restart_dma(ep);
-                       }
-               }
-               ep->irqs++;
-       }
-
-       /* NOTE:  there are other PCI errors we might usefully notice.
-        * if they appear very often, here's where to try recovering.
-        */
-       if (stat & PCI_ERROR_INTERRUPTS) {
-               ep_err(dev, "pci dma error; stat %08x\n", stat);
-               stat &= ~PCI_ERROR_INTERRUPTS;
-               /* these are fatal errors, but "maybe" they won't
-                * happen again ...
-                */
-               stop_activity(dev, dev->driver);
-               ep0_start(dev);
-               stat = 0;
-       }
-
-       if (stat)
-               ep_dbg(dev, "unhandled irqstat1 %08x\n", stat);
-}
-
-static irqreturn_t net2280_irq(int irq, void *_dev)
-{
-       struct net2280          *dev = _dev;
-
-       /* shared interrupt, not ours */
-       if ((dev->quirks & PLX_LEGACY) &&
-               (!(readl(&dev->regs->irqstat0) & BIT(INTA_ASSERTED))))
-               return IRQ_NONE;
-
-       spin_lock(&dev->lock);
-
-       /* handle disconnect, dma, and more */
-       handle_stat1_irqs(dev, readl(&dev->regs->irqstat1));
-
-       /* control requests and PIO */
-       handle_stat0_irqs(dev, readl(&dev->regs->irqstat0));
-
-       if (dev->quirks & PLX_SUPERSPEED) {
-               /* re-enable interrupt to trigger any possible new interrupt */
-               u32 pciirqenb1 = readl(&dev->regs->pciirqenb1);
-               writel(pciirqenb1 & 0x7FFFFFFF, &dev->regs->pciirqenb1);
-               writel(pciirqenb1, &dev->regs->pciirqenb1);
-       }
-
-       spin_unlock(&dev->lock);
-
-       return IRQ_HANDLED;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void gadget_release(struct device *_dev)
-{
-       struct net2280  *dev = dev_get_drvdata(_dev);
-
-       kfree(dev);
-}
-
-/* tear down the binding between this driver and the pci device */
-
-static void net2280_remove(struct pci_dev *pdev)
-{
-       struct net2280          *dev = pci_get_drvdata(pdev);
-
-       usb_del_gadget_udc(&dev->gadget);
-
-       BUG_ON(dev->driver);
-
-       /* then clean up the resources we allocated during probe() */
-       net2280_led_shutdown(dev);
-       if (dev->requests) {
-               int             i;
-               for (i = 1; i < 5; i++) {
-                       if (!dev->ep[i].dummy)
-                               continue;
-                       pci_pool_free(dev->requests, dev->ep[i].dummy,
-                                       dev->ep[i].td_dma);
-               }
-               pci_pool_destroy(dev->requests);
-       }
-       if (dev->got_irq)
-               free_irq(pdev->irq, dev);
-       if (use_msi && dev->quirks & PLX_SUPERSPEED)
-               pci_disable_msi(pdev);
-       if (dev->regs)
-               iounmap(dev->regs);
-       if (dev->region)
-               release_mem_region(pci_resource_start(pdev, 0),
-                               pci_resource_len(pdev, 0));
-       if (dev->enabled)
-               pci_disable_device(pdev);
-       device_remove_file(&pdev->dev, &dev_attr_registers);
-
-       ep_info(dev, "unbind\n");
-}
-
-/* wrap this driver around the specified device, but
- * don't respond over USB until a gadget driver binds to us.
- */
-
-static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-       struct net2280          *dev;
-       unsigned long           resource, len;
-       void                    __iomem *base = NULL;
-       int                     retval, i;
-
-       if (!use_dma)
-               use_dma_chaining = 0;
-
-       /* alloc, and start init */
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL) {
-               retval = -ENOMEM;
-               goto done;
-       }
-
-       pci_set_drvdata(pdev, dev);
-       spin_lock_init(&dev->lock);
-       dev->quirks = id->driver_data;
-       dev->pdev = pdev;
-       dev->gadget.ops = &net2280_ops;
-       dev->gadget.max_speed = (dev->quirks & PLX_SUPERSPEED) ?
-                               USB_SPEED_SUPER : USB_SPEED_HIGH;
-
-       /* the "gadget" abstracts/virtualizes the controller */
-       dev->gadget.name = driver_name;
-
-       /* now all the pci goodies ... */
-       if (pci_enable_device(pdev) < 0) {
-               retval = -ENODEV;
-               goto done;
-       }
-       dev->enabled = 1;
-
-       /* BAR 0 holds all the registers
-        * BAR 1 is 8051 memory; unused here (note erratum 0103)
-        * BAR 2 is fifo memory; unused here
-        */
-       resource = pci_resource_start(pdev, 0);
-       len = pci_resource_len(pdev, 0);
-       if (!request_mem_region(resource, len, driver_name)) {
-               ep_dbg(dev, "controller already in use\n");
-               retval = -EBUSY;
-               goto done;
-       }
-       dev->region = 1;
-
-       /* FIXME provide firmware download interface to put
-        * 8051 code into the chip, e.g. to turn on PCI PM.
-        */
-
-       base = ioremap_nocache(resource, len);
-       if (base == NULL) {
-               ep_dbg(dev, "can't map memory\n");
-               retval = -EFAULT;
-               goto done;
-       }
-       dev->regs = (struct net2280_regs __iomem *) base;
-       dev->usb = (struct net2280_usb_regs __iomem *) (base + 0x0080);
-       dev->pci = (struct net2280_pci_regs __iomem *) (base + 0x0100);
-       dev->dma = (struct net2280_dma_regs __iomem *) (base + 0x0180);
-       dev->dep = (struct net2280_dep_regs __iomem *) (base + 0x0200);
-       dev->epregs = (struct net2280_ep_regs __iomem *) (base + 0x0300);
-
-       if (dev->quirks & PLX_SUPERSPEED) {
-               u32 fsmvalue;
-               u32 usbstat;
-               dev->usb_ext = (struct usb338x_usb_ext_regs __iomem *)
-                                                       (base + 0x00b4);
-               dev->fiforegs = (struct usb338x_fifo_regs __iomem *)
-                                                       (base + 0x0500);
-               dev->llregs = (struct usb338x_ll_regs __iomem *)
-                                                       (base + 0x0700);
-               dev->ll_lfps_regs = (struct usb338x_ll_lfps_regs __iomem *)
-                                                       (base + 0x0748);
-               dev->ll_tsn_regs = (struct usb338x_ll_tsn_regs __iomem *)
-                                                       (base + 0x077c);
-               dev->ll_chicken_reg = (struct usb338x_ll_chi_regs __iomem *)
-                                                       (base + 0x079c);
-               dev->plregs = (struct usb338x_pl_regs __iomem *)
-                                                       (base + 0x0800);
-               usbstat = readl(&dev->usb->usbstat);
-               dev->enhanced_mode = !!(usbstat & BIT(11));
-               dev->n_ep = (dev->enhanced_mode) ? 9 : 5;
-               /* put into initial config, link up all endpoints */
-               fsmvalue = get_idx_reg(dev->regs, SCRATCH) &
-                                       (0xf << DEFECT7374_FSM_FIELD);
-               /* See if firmware needs to set up for workaround: */
-               if (fsmvalue == DEFECT7374_FSM_SS_CONTROL_READ)
-                       writel(0, &dev->usb->usbctl);
-       } else{
-               dev->enhanced_mode = 0;
-               dev->n_ep = 7;
-               /* put into initial config, link up all endpoints */
-               writel(0, &dev->usb->usbctl);
-       }
-
-       usb_reset(dev);
-       usb_reinit(dev);
-
-       /* irq setup after old hardware is cleaned up */
-       if (!pdev->irq) {
-               ep_err(dev, "No IRQ.  Check PCI setup!\n");
-               retval = -ENODEV;
-               goto done;
-       }
-
-       if (use_msi && (dev->quirks & PLX_SUPERSPEED))
-               if (pci_enable_msi(pdev))
-                       ep_err(dev, "Failed to enable MSI mode\n");
-
-       if (request_irq(pdev->irq, net2280_irq, IRQF_SHARED,
-                                                       driver_name, dev)) {
-               ep_err(dev, "request interrupt %d failed\n", pdev->irq);
-               retval = -EBUSY;
-               goto done;
-       }
-       dev->got_irq = 1;
-
-       /* DMA setup */
-       /* NOTE:  we know only the 32 LSBs of dma addresses may be nonzero */
-       dev->requests = pci_pool_create("requests", pdev,
-               sizeof(struct net2280_dma),
-               0 /* no alignment requirements */,
-               0 /* or page-crossing issues */);
-       if (!dev->requests) {
-               ep_dbg(dev, "can't get request pool\n");
-               retval = -ENOMEM;
-               goto done;
-       }
-       for (i = 1; i < 5; i++) {
-               struct net2280_dma      *td;
-
-               td = pci_pool_alloc(dev->requests, GFP_KERNEL,
-                               &dev->ep[i].td_dma);
-               if (!td) {
-                       ep_dbg(dev, "can't get dummy %d\n", i);
-                       retval = -ENOMEM;
-                       goto done;
-               }
-               td->dmacount = 0;       /* not VALID */
-               td->dmadesc = td->dmaaddr;
-               dev->ep[i].dummy = td;
-       }
-
-       /* enable lower-overhead pci memory bursts during DMA */
-       if (dev->quirks & PLX_LEGACY)
-               writel(BIT(DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE) |
-                       /*
-                        * 256 write retries may not be enough...
-                          BIT(PCI_RETRY_ABORT_ENABLE) |
-                       */
-                       BIT(DMA_READ_MULTIPLE_ENABLE) |
-                       BIT(DMA_READ_LINE_ENABLE),
-                       &dev->pci->pcimstctl);
-       /* erratum 0115 shouldn't appear: Linux inits PCI_LATENCY_TIMER */
-       pci_set_master(pdev);
-       pci_try_set_mwi(pdev);
-
-       /* ... also flushes any posted pci writes */
-       dev->chiprev = get_idx_reg(dev->regs, REG_CHIPREV) & 0xffff;
-
-       /* done */
-       ep_info(dev, "%s\n", driver_desc);
-       ep_info(dev, "irq %d, pci mem %p, chip rev %04x\n",
-                       pdev->irq, base, dev->chiprev);
-       ep_info(dev, "version: " DRIVER_VERSION "; dma %s %s\n",
-               use_dma ? (use_dma_chaining ? "chaining" : "enabled")
-                       : "disabled",
-               dev->enhanced_mode ? "enhanced mode" : "legacy mode");
-       retval = device_create_file(&pdev->dev, &dev_attr_registers);
-       if (retval)
-               goto done;
-
-       retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
-                       gadget_release);
-       if (retval)
-               goto done;
-       return 0;
-
-done:
-       if (dev)
-               net2280_remove(pdev);
-       return retval;
-}
-
-/* make sure the board is quiescent; otherwise it will continue
- * generating IRQs across the upcoming reboot.
- */
-
-static void net2280_shutdown(struct pci_dev *pdev)
-{
-       struct net2280          *dev = pci_get_drvdata(pdev);
-
-       /* disable IRQs */
-       writel(0, &dev->regs->pciirqenb0);
-       writel(0, &dev->regs->pciirqenb1);
-
-       /* disable the pullup so the host will think we're gone */
-       writel(0, &dev->usb->usbctl);
-
-       /* Disable full-speed test mode */
-       if (dev->quirks & PLX_LEGACY)
-               writel(0, &dev->usb->xcvrdiag);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static const struct pci_device_id pci_ids[] = { {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-       .class_mask =   ~0,
-       .vendor =       PCI_VENDOR_ID_PLX_LEGACY,
-       .device =       0x2280,
-       .subvendor =    PCI_ANY_ID,
-       .subdevice =    PCI_ANY_ID,
-       .driver_data =  PLX_LEGACY | PLX_2280,
-       }, {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-       .class_mask =   ~0,
-       .vendor =       PCI_VENDOR_ID_PLX_LEGACY,
-       .device =       0x2282,
-       .subvendor =    PCI_ANY_ID,
-       .subdevice =    PCI_ANY_ID,
-       .driver_data =  PLX_LEGACY,
-       },
-       {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-       .class_mask =   ~0,
-       .vendor =       PCI_VENDOR_ID_PLX,
-       .device =       0x3380,
-       .subvendor =    PCI_ANY_ID,
-       .subdevice =    PCI_ANY_ID,
-       .driver_data =  PLX_SUPERSPEED,
-        },
-       {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-       .class_mask =   ~0,
-       .vendor =       PCI_VENDOR_ID_PLX,
-       .device =       0x3382,
-       .subvendor =    PCI_ANY_ID,
-       .subdevice =    PCI_ANY_ID,
-       .driver_data =  PLX_SUPERSPEED,
-        },
-{ /* end: all zeroes */ }
-};
-MODULE_DEVICE_TABLE(pci, pci_ids);
-
-/* pci driver glue; this is a "new style" PCI driver module */
-static struct pci_driver net2280_pci_driver = {
-       .name =         (char *) driver_name,
-       .id_table =     pci_ids,
-
-       .probe =        net2280_probe,
-       .remove =       net2280_remove,
-       .shutdown =     net2280_shutdown,
-
-       /* FIXME add power management support */
-};
-
-module_pci_driver(net2280_pci_driver);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("David Brownell");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
deleted file mode 100644 (file)
index 03f1524..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * NetChip 2280 high/full speed USB device controller.
- * Unlike many such controllers, this one talks PCI.
- */
-
-/*
- * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
- * Copyright (C) 2003 David Brownell
- * Copyright (C) 2014 Ricardo Ribalda - Qtechnology/AS
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/usb/net2280.h>
-#include <linux/usb/usb338x.h>
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef __KERNEL__
-
-/* indexed registers [11.10] are accessed indirectly
- * caller must own the device lock.
- */
-
-static inline u32 get_idx_reg(struct net2280_regs __iomem *regs, u32 index)
-{
-       writel(index, &regs->idxaddr);
-       /* NOTE:  synchs device/cpu memory views */
-       return readl(&regs->idxdata);
-}
-
-static inline void
-set_idx_reg(struct net2280_regs __iomem *regs, u32 index, u32 value)
-{
-       writel(index, &regs->idxaddr);
-       writel(value, &regs->idxdata);
-       /* posted, may not be visible yet */
-}
-
-#endif /* __KERNEL__ */
-
-#define PCI_VENDOR_ID_PLX_LEGACY 0x17cc
-
-#define PLX_LEGACY             BIT(0)
-#define PLX_2280               BIT(1)
-#define PLX_SUPERSPEED         BIT(2)
-
-#define REG_DIAG               0x0
-#define     RETRY_COUNTER                                       16
-#define     FORCE_PCI_SERR                                      11
-#define     FORCE_PCI_INTERRUPT                                 10
-#define     FORCE_USB_INTERRUPT                                 9
-#define     FORCE_CPU_INTERRUPT                                 8
-#define     ILLEGAL_BYTE_ENABLES                                5
-#define     FAST_TIMES                                          4
-#define     FORCE_RECEIVE_ERROR                                 2
-#define     FORCE_TRANSMIT_CRC_ERROR                            0
-#define REG_FRAME              0x02    /* from last sof */
-#define REG_CHIPREV            0x03    /* in bcd */
-#define        REG_HS_NAK_RATE         0x0a    /* NAK per N uframes */
-
-#define        CHIPREV_1       0x0100
-#define        CHIPREV_1A      0x0110
-
-/* DEFECT 7374 */
-#define DEFECT_7374_NUMBEROF_MAX_WAIT_LOOPS         200
-#define DEFECT_7374_PROCESSOR_WAIT_TIME             10
-
-/* ep0 max packet size */
-#define EP0_SS_MAX_PACKET_SIZE  0x200
-#define EP0_HS_MAX_PACKET_SIZE  0x40
-#ifdef __KERNEL__
-
-/*-------------------------------------------------------------------------*/
-
-/* [8.3] for scatter/gather i/o
- * use struct net2280_dma_regs bitfields
- */
-struct net2280_dma {
-       __le32          dmacount;
-       __le32          dmaaddr;                /* the buffer */
-       __le32          dmadesc;                /* next dma descriptor */
-       __le32          _reserved;
-} __aligned(16);
-
-/*-------------------------------------------------------------------------*/
-
-/* DRIVER DATA STRUCTURES and UTILITIES */
-
-struct net2280_ep {
-       struct usb_ep                           ep;
-       struct net2280_ep_regs __iomem *cfg;
-       struct net2280_ep_regs                  __iomem *regs;
-       struct net2280_dma_regs                 __iomem *dma;
-       struct net2280_dma                      *dummy;
-       struct usb338x_fifo_regs __iomem *fiforegs;
-       dma_addr_t                              td_dma; /* of dummy */
-       struct net2280                          *dev;
-       unsigned long                           irqs;
-       unsigned is_halt:1, dma_started:1;
-
-       /* analogous to a host-side qh */
-       struct list_head                        queue;
-       const struct usb_endpoint_descriptor    *desc;
-       unsigned                                num : 8,
-                                               fifo_size : 12,
-                                               in_fifo_validate : 1,
-                                               out_overflow : 1,
-                                               stopped : 1,
-                                               wedged : 1,
-                                               is_in : 1,
-                                               is_iso : 1,
-                                               responded : 1;
-};
-
-static inline void allow_status(struct net2280_ep *ep)
-{
-       /* ep0 only */
-       writel(BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE) |
-               BIT(CLEAR_NAK_OUT_PACKETS) |
-               BIT(CLEAR_NAK_OUT_PACKETS_MODE),
-               &ep->regs->ep_rsp);
-       ep->stopped = 1;
-}
-
-static void allow_status_338x(struct net2280_ep *ep)
-{
-       /*
-        * Control Status Phase Handshake was set by the chip when the setup
-        * packet arrived. While set, the chip automatically NAKs the host's
-        * Status Phase tokens.
-        */
-       writel(BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE), &ep->regs->ep_rsp);
-
-       ep->stopped = 1;
-
-       /* TD 9.9 Halt Endpoint test.  TD 9.22 set feature test. */
-       ep->responded = 0;
-}
-
-struct net2280_request {
-       struct usb_request              req;
-       struct net2280_dma              *td;
-       dma_addr_t                      td_dma;
-       struct list_head                queue;
-       unsigned                        mapped : 1,
-                                       valid : 1;
-};
-
-struct net2280 {
-       /* each pci device provides one gadget, several endpoints */
-       struct usb_gadget               gadget;
-       spinlock_t                      lock;
-       struct net2280_ep               ep[9];
-       struct usb_gadget_driver        *driver;
-       unsigned                        enabled : 1,
-                                       protocol_stall : 1,
-                                       softconnect : 1,
-                                       got_irq : 1,
-                                       region:1,
-                                       u1_enable:1,
-                                       u2_enable:1,
-                                       ltm_enable:1,
-                                       wakeup_enable:1,
-                                       selfpowered:1,
-                                       addressed_state:1;
-       u16                             chiprev;
-       int enhanced_mode;
-       int n_ep;
-       kernel_ulong_t                  quirks;
-
-
-       /* pci state used to access those endpoints */
-       struct pci_dev                  *pdev;
-       struct net2280_regs             __iomem *regs;
-       struct net2280_usb_regs         __iomem *usb;
-       struct usb338x_usb_ext_regs     __iomem *usb_ext;
-       struct net2280_pci_regs         __iomem *pci;
-       struct net2280_dma_regs         __iomem *dma;
-       struct net2280_dep_regs         __iomem *dep;
-       struct net2280_ep_regs          __iomem *epregs;
-       struct usb338x_fifo_regs        __iomem *fiforegs;
-       struct usb338x_ll_regs          __iomem *llregs;
-       struct usb338x_ll_lfps_regs     __iomem *ll_lfps_regs;
-       struct usb338x_ll_tsn_regs      __iomem *ll_tsn_regs;
-       struct usb338x_ll_chi_regs      __iomem *ll_chicken_reg;
-       struct usb338x_pl_regs          __iomem *plregs;
-
-       struct pci_pool                 *requests;
-       /* statistics...*/
-};
-
-static inline void set_halt(struct net2280_ep *ep)
-{
-       /* ep0 and bulk/intr endpoints */
-       writel(BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE) |
-               /* set NAK_OUT for erratum 0114 */
-               ((ep->dev->chiprev == CHIPREV_1) << SET_NAK_OUT_PACKETS) |
-               BIT(SET_ENDPOINT_HALT),
-               &ep->regs->ep_rsp);
-}
-
-static inline void clear_halt(struct net2280_ep *ep)
-{
-       /* ep0 and bulk/intr endpoints */
-       writel(BIT(CLEAR_ENDPOINT_HALT) |
-               BIT(CLEAR_ENDPOINT_TOGGLE) |
-                   /*
-                    * unless the gadget driver left a short packet in the
-                    * fifo, this reverses the erratum 0114 workaround.
-                    */
-               ((ep->dev->chiprev == CHIPREV_1) << CLEAR_NAK_OUT_PACKETS),
-               &ep->regs->ep_rsp);
-}
-
-/*
- * FSM value for Defect 7374 (U1U2 Test) is managed in
- * chip's SCRATCH register:
- */
-#define DEFECT7374_FSM_FIELD    28
-
-/* Waiting for Control Read:
- *  - A transition to this state indicates a fresh USB connection,
- *    before the first Setup Packet. The connection speed is not
- *    known. Firmware is waiting for the first Control Read.
- *  - Starting state: This state can be thought of as the FSM's typical
- *    starting state.
- *  - Tip: Upon the first SS Control Read the FSM never
- *    returns to this state.
- */
-#define DEFECT7374_FSM_WAITING_FOR_CONTROL_READ BIT(DEFECT7374_FSM_FIELD)
-
-/* Non-SS Control Read:
- *  - A transition to this state indicates detection of the first HS
- *    or FS Control Read.
- *  - Tip: Upon the first SS Control Read the FSM never
- *    returns to this state.
- */
-#define        DEFECT7374_FSM_NON_SS_CONTROL_READ (2 << DEFECT7374_FSM_FIELD)
-
-/* SS Control Read:
- *  - A transition to this state indicates detection of the
- *    first SS Control Read.
- *  - This state indicates workaround completion. Workarounds no longer
- *    need to be applied (as long as the chip remains powered up).
- *  - Tip: Once in this state the FSM state does not change (until
- *    the chip's power is lost and restored).
- *  - This can be thought of as the final state of the FSM;
- *    the FSM 'locks-up' in this state until the chip loses power.
- */
-#define DEFECT7374_FSM_SS_CONTROL_READ (3 << DEFECT7374_FSM_FIELD)
-
-#ifdef USE_RDK_LEDS
-
-static inline void net2280_led_init(struct net2280 *dev)
-{
-       /* LED3 (green) is on during USB activity. note erratum 0113. */
-       writel(BIT(GPIO3_LED_SELECT) |
-               BIT(GPIO3_OUTPUT_ENABLE) |
-               BIT(GPIO2_OUTPUT_ENABLE) |
-               BIT(GPIO1_OUTPUT_ENABLE) |
-               BIT(GPIO0_OUTPUT_ENABLE),
-               &dev->regs->gpioctl);
-}
-
-/* indicate speed with bi-color LED 0/1 */
-static inline
-void net2280_led_speed(struct net2280 *dev, enum usb_device_speed speed)
-{
-       u32     val = readl(&dev->regs->gpioctl);
-       switch (speed) {
-       case USB_SPEED_SUPER:           /* green + red */
-               val |= BIT(GPIO0_DATA) | BIT(GPIO1_DATA);
-               break;
-       case USB_SPEED_HIGH:            /* green */
-               val &= ~BIT(GPIO0_DATA);
-               val |= BIT(GPIO1_DATA);
-               break;
-       case USB_SPEED_FULL:            /* red */
-               val &= ~BIT(GPIO1_DATA);
-               val |= BIT(GPIO0_DATA);
-               break;
-       default:                        /* (off/black) */
-               val &= ~(BIT(GPIO1_DATA) | BIT(GPIO0_DATA));
-               break;
-       }
-       writel(val, &dev->regs->gpioctl);
-}
-
-/* indicate power with LED 2 */
-static inline void net2280_led_active(struct net2280 *dev, int is_active)
-{
-       u32     val = readl(&dev->regs->gpioctl);
-
-       /* FIXME this LED never seems to turn on.*/
-       if (is_active)
-               val |= GPIO2_DATA;
-       else
-               val &= ~GPIO2_DATA;
-       writel(val, &dev->regs->gpioctl);
-}
-
-static inline void net2280_led_shutdown(struct net2280 *dev)
-{
-       /* turn off all four GPIO*_DATA bits */
-       writel(readl(&dev->regs->gpioctl) & ~0x0f,
-                       &dev->regs->gpioctl);
-}
-
-#else
-
-#define net2280_led_init(dev)          do { } while (0)
-#define net2280_led_speed(dev, speed)  do { } while (0)
-#define net2280_led_shutdown(dev)      do { } while (0)
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-#define ep_dbg(ndev, fmt, args...) \
-       dev_dbg((&((ndev)->pdev->dev)), fmt, ##args)
-
-#define ep_vdbg(ndev, fmt, args...) \
-       dev_vdbg((&((ndev)->pdev->dev)), fmt, ##args)
-
-#define ep_info(ndev, fmt, args...) \
-       dev_info((&((ndev)->pdev->dev)), fmt, ##args)
-
-#define ep_warn(ndev, fmt, args...) \
-       dev_warn((&((ndev)->pdev->dev)), fmt, ##args)
-
-#define ep_err(ndev, fmt, args...) \
-       dev_err((&((ndev)->pdev->dev)), fmt, ##args)
-
-/*-------------------------------------------------------------------------*/
-
-static inline void set_fifo_bytecount(struct net2280_ep *ep, unsigned count)
-{
-       if (ep->dev->pdev->vendor == 0x17cc)
-               writeb(count, 2 + (u8 __iomem *) &ep->regs->ep_cfg);
-       else{
-               u32 tmp = readl(&ep->cfg->ep_cfg) &
-                                       (~(0x07 << EP_FIFO_BYTE_COUNT));
-               writel(tmp | (count << EP_FIFO_BYTE_COUNT), &ep->cfg->ep_cfg);
-       }
-}
-
-static inline void start_out_naking(struct net2280_ep *ep)
-{
-       /* NOTE:  hardware races lurk here, and PING protocol issues */
-       writel(BIT(SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-       /* synch with device */
-       readl(&ep->regs->ep_rsp);
-}
-
-#ifdef DEBUG
-static inline void assert_out_naking(struct net2280_ep *ep, const char *where)
-{
-       u32     tmp = readl(&ep->regs->ep_stat);
-
-       if ((tmp & BIT(NAK_OUT_PACKETS)) == 0) {
-               ep_dbg(ep->dev, "%s %s %08x !NAK\n",
-                               ep->ep.name, where, tmp);
-               writel(BIT(SET_NAK_OUT_PACKETS),
-                       &ep->regs->ep_rsp);
-       }
-}
-#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep, __func__)
-#else
-#define ASSERT_OUT_NAKING(ep) do {} while (0)
-#endif
-
-static inline void stop_out_naking(struct net2280_ep *ep)
-{
-       u32     tmp;
-
-       tmp = readl(&ep->regs->ep_stat);
-       if ((tmp & BIT(NAK_OUT_PACKETS)) != 0)
-               writel(BIT(CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-}
-
-
-static inline void set_max_speed(struct net2280_ep *ep, u32 max)
-{
-       u32 reg;
-       static const u32 ep_enhanced[9] = { 0x10, 0x60, 0x30, 0x80,
-                                         0x50, 0x20, 0x70, 0x40, 0x90 };
-
-       if (ep->dev->enhanced_mode)
-               reg = ep_enhanced[ep->num];
-       else{
-               reg = (ep->num + 1) * 0x10;
-               if (ep->dev->gadget.speed != USB_SPEED_HIGH)
-                       reg += 1;
-       }
-
-       set_idx_reg(ep->dev->regs, reg, max);
-}
-
-#endif /* __KERNEL__ */
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
deleted file mode 100644 (file)
index e731373..0000000
+++ /dev/null
@@ -1,3038 +0,0 @@
-/*
- * omap_udc.c -- for OMAP full speed udc; most chips support OTG.
- *
- * Copyright (C) 2004 Texas Instruments, Inc.
- * Copyright (C) 2004-2005 David Brownell
- *
- * OMAP2 & DMA support by Kyungmin Park <kyungmin.park@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#undef DEBUG
-#undef VERBOSE
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/mm.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/otg.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/prefetch.h>
-#include <linux/io.h>
-
-#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/unaligned.h>
-#include <asm/mach-types.h>
-
-#include <linux/omap-dma.h>
-
-#include <mach/usb.h>
-
-#include "omap_udc.h"
-
-#undef USB_TRACE
-
-/* bulk DMA seems to be behaving for both IN and OUT */
-#define        USE_DMA
-
-/* ISO too */
-#define        USE_ISO
-
-#define        DRIVER_DESC     "OMAP UDC driver"
-#define        DRIVER_VERSION  "4 October 2004"
-
-#define OMAP_DMA_USB_W2FC_TX0          29
-#define OMAP_DMA_USB_W2FC_RX0          26
-
-/*
- * The OMAP UDC needs _very_ early endpoint setup:  before enabling the
- * D+ pullup to allow enumeration.  That's too early for the gadget
- * framework to use from usb_endpoint_enable(), which happens after
- * enumeration as part of activating an interface.  (But if we add an
- * optional new "UDC not yet running" state to the gadget driver model,
- * even just during driver binding, the endpoint autoconfig logic is the
- * natural spot to manufacture new endpoints.)
- *
- * So instead of using endpoint enable calls to control the hardware setup,
- * this driver defines a "fifo mode" parameter.  It's used during driver
- * initialization to choose among a set of pre-defined endpoint configs.
- * See omap_udc_setup() for available modes, or to add others.  That code
- * lives in an init section, so use this driver as a module if you need
- * to change the fifo mode after the kernel boots.
- *
- * Gadget drivers normally ignore endpoints they don't care about, and
- * won't include them in configuration descriptors.  That means only
- * misbehaving hosts would even notice they exist.
- */
-#ifdef USE_ISO
-static unsigned fifo_mode = 3;
-#else
-static unsigned fifo_mode;
-#endif
-
-/* "modprobe omap_udc fifo_mode=42", or else as a kernel
- * boot parameter "omap_udc:fifo_mode=42"
- */
-module_param(fifo_mode, uint, 0);
-MODULE_PARM_DESC(fifo_mode, "endpoint configuration");
-
-#ifdef USE_DMA
-static bool use_dma = 1;
-
-/* "modprobe omap_udc use_dma=y", or else as a kernel
- * boot parameter "omap_udc:use_dma=y"
- */
-module_param(use_dma, bool, 0);
-MODULE_PARM_DESC(use_dma, "enable/disable DMA");
-#else  /* !USE_DMA */
-
-/* save a bit of code */
-#define        use_dma         0
-#endif /* !USE_DMA */
-
-
-static const char driver_name[] = "omap_udc";
-static const char driver_desc[] = DRIVER_DESC;
-
-/*-------------------------------------------------------------------------*/
-
-/* there's a notion of "current endpoint" for modifying endpoint
- * state, and PIO access to its FIFO.
- */
-
-static void use_ep(struct omap_ep *ep, u16 select)
-{
-       u16     num = ep->bEndpointAddress & 0x0f;
-
-       if (ep->bEndpointAddress & USB_DIR_IN)
-               num |= UDC_EP_DIR;
-       omap_writew(num | select, UDC_EP_NUM);
-       /* when select, MUST deselect later !! */
-}
-
-static inline void deselect_ep(void)
-{
-       u16 w;
-
-       w = omap_readw(UDC_EP_NUM);
-       w &= ~UDC_EP_SEL;
-       omap_writew(w, UDC_EP_NUM);
-       /* 6 wait states before TX will happen */
-}
-
-static void dma_channel_claim(struct omap_ep *ep, unsigned preferred);
-
-/*-------------------------------------------------------------------------*/
-
-static int omap_ep_enable(struct usb_ep *_ep,
-               const struct usb_endpoint_descriptor *desc)
-{
-       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
-       struct omap_udc *udc;
-       unsigned long   flags;
-       u16             maxp;
-
-       /* catch various bogus parameters */
-       if (!_ep || !desc
-                       || desc->bDescriptorType != USB_DT_ENDPOINT
-                       || ep->bEndpointAddress != desc->bEndpointAddress
-                       || ep->maxpacket < usb_endpoint_maxp(desc)) {
-               DBG("%s, bad ep or descriptor\n", __func__);
-               return -EINVAL;
-       }
-       maxp = usb_endpoint_maxp(desc);
-       if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
-                               && maxp != ep->maxpacket)
-                       || usb_endpoint_maxp(desc) > ep->maxpacket
-                       || !desc->wMaxPacketSize) {
-               DBG("%s, bad %s maxpacket\n", __func__, _ep->name);
-               return -ERANGE;
-       }
-
-#ifdef USE_ISO
-       if ((desc->bmAttributes == USB_ENDPOINT_XFER_ISOC
-                               && desc->bInterval != 1)) {
-               /* hardware wants period = 1; USB allows 2^(Interval-1) */
-               DBG("%s, unsupported ISO period %dms\n", _ep->name,
-                               1 << (desc->bInterval - 1));
-               return -EDOM;
-       }
-#else
-       if (desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
-               DBG("%s, ISO nyet\n", _ep->name);
-               return -EDOM;
-       }
-#endif
-
-       /* xfer types must match, except that interrupt ~= bulk */
-       if (ep->bmAttributes != desc->bmAttributes
-                       && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
-                       && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
-               DBG("%s, %s type mismatch\n", __func__, _ep->name);
-               return -EINVAL;
-       }
-
-       udc = ep->udc;
-       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
-               DBG("%s, bogus device state\n", __func__);
-               return -ESHUTDOWN;
-       }
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       ep->ep.desc = desc;
-       ep->irqs = 0;
-       ep->stopped = 0;
-       ep->ep.maxpacket = maxp;
-
-       /* set endpoint to initial state */
-       ep->dma_channel = 0;
-       ep->has_dma = 0;
-       ep->lch = -1;
-       use_ep(ep, UDC_EP_SEL);
-       omap_writew(udc->clr_halt, UDC_CTRL);
-       ep->ackwait = 0;
-       deselect_ep();
-
-       if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
-               list_add(&ep->iso, &udc->iso);
-
-       /* maybe assign a DMA channel to this endpoint */
-       if (use_dma && desc->bmAttributes == USB_ENDPOINT_XFER_BULK)
-               /* FIXME ISO can dma, but prefers first channel */
-               dma_channel_claim(ep, 0);
-
-       /* PIO OUT may RX packets */
-       if (desc->bmAttributes != USB_ENDPOINT_XFER_ISOC
-                       && !ep->has_dma
-                       && !(ep->bEndpointAddress & USB_DIR_IN)) {
-               omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-               ep->ackwait = 1 + ep->double_buf;
-       }
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-       VDBG("%s enabled\n", _ep->name);
-       return 0;
-}
-
-static void nuke(struct omap_ep *, int status);
-
-static int omap_ep_disable(struct usb_ep *_ep)
-{
-       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
-       unsigned long   flags;
-
-       if (!_ep || !ep->ep.desc) {
-               DBG("%s, %s not enabled\n", __func__,
-                       _ep ? ep->ep.name : NULL);
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&ep->udc->lock, flags);
-       ep->ep.desc = NULL;
-       nuke(ep, -ESHUTDOWN);
-       ep->ep.maxpacket = ep->maxpacket;
-       ep->has_dma = 0;
-       omap_writew(UDC_SET_HALT, UDC_CTRL);
-       list_del_init(&ep->iso);
-       del_timer(&ep->timer);
-
-       spin_unlock_irqrestore(&ep->udc->lock, flags);
-
-       VDBG("%s disabled\n", _ep->name);
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_request *
-omap_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
-{
-       struct omap_req *req;
-
-       req = kzalloc(sizeof(*req), gfp_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD(&req->queue);
-
-       return &req->req;
-}
-
-static void
-omap_free_request(struct usb_ep *ep, struct usb_request *_req)
-{
-       struct omap_req *req = container_of(_req, struct omap_req, req);
-
-       kfree(req);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void
-done(struct omap_ep *ep, struct omap_req *req, int status)
-{
-       struct omap_udc         *udc = ep->udc;
-       unsigned                stopped = ep->stopped;
-
-       list_del_init(&req->queue);
-
-       if (req->req.status == -EINPROGRESS)
-               req->req.status = status;
-       else
-               status = req->req.status;
-
-       if (use_dma && ep->has_dma)
-               usb_gadget_unmap_request(&udc->gadget, &req->req,
-                               (ep->bEndpointAddress & USB_DIR_IN));
-
-#ifndef        USB_TRACE
-       if (status && status != -ESHUTDOWN)
-#endif
-               VDBG("complete %s req %p stat %d len %u/%u\n",
-                       ep->ep.name, &req->req, status,
-                       req->req.actual, req->req.length);
-
-       /* don't modify queue heads during completion callback */
-       ep->stopped = 1;
-       spin_unlock(&ep->udc->lock);
-       req->req.complete(&ep->ep, &req->req);
-       spin_lock(&ep->udc->lock);
-       ep->stopped = stopped;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#define UDC_FIFO_FULL          (UDC_NON_ISO_FIFO_FULL | UDC_ISO_FIFO_FULL)
-#define UDC_FIFO_UNWRITABLE    (UDC_EP_HALTED | UDC_FIFO_FULL)
-
-#define FIFO_EMPTY     (UDC_NON_ISO_FIFO_EMPTY | UDC_ISO_FIFO_EMPTY)
-#define FIFO_UNREADABLE (UDC_EP_HALTED | FIFO_EMPTY)
-
-static inline int
-write_packet(u8 *buf, struct omap_req *req, unsigned max)
-{
-       unsigned        len;
-       u16             *wp;
-
-       len = min(req->req.length - req->req.actual, max);
-       req->req.actual += len;
-
-       max = len;
-       if (likely((((int)buf) & 1) == 0)) {
-               wp = (u16 *)buf;
-               while (max >= 2) {
-                       omap_writew(*wp++, UDC_DATA);
-                       max -= 2;
-               }
-               buf = (u8 *)wp;
-       }
-       while (max--)
-               omap_writeb(*buf++, UDC_DATA);
-       return len;
-}
-
-/* FIXME change r/w fifo calling convention */
-
-
-/* return:  0 = still running, 1 = completed, negative = errno */
-static int write_fifo(struct omap_ep *ep, struct omap_req *req)
-{
-       u8              *buf;
-       unsigned        count;
-       int             is_last;
-       u16             ep_stat;
-
-       buf = req->req.buf + req->req.actual;
-       prefetch(buf);
-
-       /* PIO-IN isn't double buffered except for iso */
-       ep_stat = omap_readw(UDC_STAT_FLG);
-       if (ep_stat & UDC_FIFO_UNWRITABLE)
-               return 0;
-
-       count = ep->ep.maxpacket;
-       count = write_packet(buf, req, count);
-       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-       ep->ackwait = 1;
-
-       /* last packet is often short (sometimes a zlp) */
-       if (count != ep->ep.maxpacket)
-               is_last = 1;
-       else if (req->req.length == req->req.actual
-                       && !req->req.zero)
-               is_last = 1;
-       else
-               is_last = 0;
-
-       /* NOTE:  requests complete when all IN data is in a
-        * FIFO (or sometimes later, if a zlp was needed).
-        * Use usb_ep_fifo_status() where needed.
-        */
-       if (is_last)
-               done(ep, req, 0);
-       return is_last;
-}
-
-static inline int
-read_packet(u8 *buf, struct omap_req *req, unsigned avail)
-{
-       unsigned        len;
-       u16             *wp;
-
-       len = min(req->req.length - req->req.actual, avail);
-       req->req.actual += len;
-       avail = len;
-
-       if (likely((((int)buf) & 1) == 0)) {
-               wp = (u16 *)buf;
-               while (avail >= 2) {
-                       *wp++ = omap_readw(UDC_DATA);
-                       avail -= 2;
-               }
-               buf = (u8 *)wp;
-       }
-       while (avail--)
-               *buf++ = omap_readb(UDC_DATA);
-       return len;
-}
-
-/* return:  0 = still running, 1 = queue empty, negative = errno */
-static int read_fifo(struct omap_ep *ep, struct omap_req *req)
-{
-       u8              *buf;
-       unsigned        count, avail;
-       int             is_last;
-
-       buf = req->req.buf + req->req.actual;
-       prefetchw(buf);
-
-       for (;;) {
-               u16     ep_stat = omap_readw(UDC_STAT_FLG);
-
-               is_last = 0;
-               if (ep_stat & FIFO_EMPTY) {
-                       if (!ep->double_buf)
-                               break;
-                       ep->fnf = 1;
-               }
-               if (ep_stat & UDC_EP_HALTED)
-                       break;
-
-               if (ep_stat & UDC_FIFO_FULL)
-                       avail = ep->ep.maxpacket;
-               else  {
-                       avail = omap_readw(UDC_RXFSTAT);
-                       ep->fnf = ep->double_buf;
-               }
-               count = read_packet(buf, req, avail);
-
-               /* partial packet reads may not be errors */
-               if (count < ep->ep.maxpacket) {
-                       is_last = 1;
-                       /* overflowed this request?  flush extra data */
-                       if (count != avail) {
-                               req->req.status = -EOVERFLOW;
-                               avail -= count;
-                               while (avail--)
-                                       omap_readw(UDC_DATA);
-                       }
-               } else if (req->req.length == req->req.actual)
-                       is_last = 1;
-               else
-                       is_last = 0;
-
-               if (!ep->bEndpointAddress)
-                       break;
-               if (is_last)
-                       done(ep, req, 0);
-               break;
-       }
-       return is_last;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start)
-{
-       dma_addr_t      end;
-
-       /* IN-DMA needs this on fault/cancel paths, so 15xx misreports
-        * the last transfer's bytecount by more than a FIFO's worth.
-        */
-       if (cpu_is_omap15xx())
-               return 0;
-
-       end = omap_get_dma_src_pos(ep->lch);
-       if (end == ep->dma_counter)
-               return 0;
-
-       end |= start & (0xffff << 16);
-       if (end < start)
-               end += 0x10000;
-       return end - start;
-}
-
-static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start)
-{
-       dma_addr_t      end;
-
-       end = omap_get_dma_dst_pos(ep->lch);
-       if (end == ep->dma_counter)
-               return 0;
-
-       end |= start & (0xffff << 16);
-       if (cpu_is_omap15xx())
-               end++;
-       if (end < start)
-               end += 0x10000;
-       return end - start;
-}
-
-
-/* Each USB transfer request using DMA maps to one or more DMA transfers.
- * When DMA completion isn't request completion, the UDC continues with
- * the next DMA transfer for that USB transfer.
- */
-
-static void next_in_dma(struct omap_ep *ep, struct omap_req *req)
-{
-       u16             txdma_ctrl, w;
-       unsigned        length = req->req.length - req->req.actual;
-       const int       sync_mode = cpu_is_omap15xx()
-                               ? OMAP_DMA_SYNC_FRAME
-                               : OMAP_DMA_SYNC_ELEMENT;
-       int             dma_trigger = 0;
-
-       /* measure length in either bytes or packets */
-       if ((cpu_is_omap16xx() && length <= UDC_TXN_TSC)
-                       || (cpu_is_omap15xx() && length < ep->maxpacket)) {
-               txdma_ctrl = UDC_TXN_EOT | length;
-               omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
-                               length, 1, sync_mode, dma_trigger, 0);
-       } else {
-               length = min(length / ep->maxpacket,
-                               (unsigned) UDC_TXN_TSC + 1);
-               txdma_ctrl = length;
-               omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
-                               ep->ep.maxpacket >> 1, length, sync_mode,
-                               dma_trigger, 0);
-               length *= ep->maxpacket;
-       }
-       omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
-               OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
-               0, 0);
-
-       omap_start_dma(ep->lch);
-       ep->dma_counter = omap_get_dma_src_pos(ep->lch);
-       w = omap_readw(UDC_DMA_IRQ_EN);
-       w |= UDC_TX_DONE_IE(ep->dma_channel);
-       omap_writew(w, UDC_DMA_IRQ_EN);
-       omap_writew(UDC_TXN_START | txdma_ctrl, UDC_TXDMA(ep->dma_channel));
-       req->dma_bytes = length;
-}
-
-static void finish_in_dma(struct omap_ep *ep, struct omap_req *req, int status)
-{
-       u16 w;
-
-       if (status == 0) {
-               req->req.actual += req->dma_bytes;
-
-               /* return if this request needs to send data or zlp */
-               if (req->req.actual < req->req.length)
-                       return;
-               if (req->req.zero
-                               && req->dma_bytes != 0
-                               && (req->req.actual % ep->maxpacket) == 0)
-                       return;
-       } else
-               req->req.actual += dma_src_len(ep, req->req.dma
-                                                       + req->req.actual);
-
-       /* tx completion */
-       omap_stop_dma(ep->lch);
-       w = omap_readw(UDC_DMA_IRQ_EN);
-       w &= ~UDC_TX_DONE_IE(ep->dma_channel);
-       omap_writew(w, UDC_DMA_IRQ_EN);
-       done(ep, req, status);
-}
-
-static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
-{
-       unsigned packets = req->req.length - req->req.actual;
-       int dma_trigger = 0;
-       u16 w;
-
-       /* set up this DMA transfer, enable the fifo, start */
-       packets /= ep->ep.maxpacket;
-       packets = min(packets, (unsigned)UDC_RXN_TC + 1);
-       req->dma_bytes = packets * ep->ep.maxpacket;
-       omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
-                       ep->ep.maxpacket >> 1, packets,
-                       OMAP_DMA_SYNC_ELEMENT,
-                       dma_trigger, 0);
-       omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
-               OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
-               0, 0);
-       ep->dma_counter = omap_get_dma_dst_pos(ep->lch);
-
-       omap_writew(UDC_RXN_STOP | (packets - 1), UDC_RXDMA(ep->dma_channel));
-       w = omap_readw(UDC_DMA_IRQ_EN);
-       w |= UDC_RX_EOT_IE(ep->dma_channel);
-       omap_writew(w, UDC_DMA_IRQ_EN);
-       omap_writew(ep->bEndpointAddress & 0xf, UDC_EP_NUM);
-       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-
-       omap_start_dma(ep->lch);
-}
-
-static void
-finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status, int one)
-{
-       u16     count, w;
-
-       if (status == 0)
-               ep->dma_counter = (u16) (req->req.dma + req->req.actual);
-       count = dma_dest_len(ep, req->req.dma + req->req.actual);
-       count += req->req.actual;
-       if (one)
-               count--;
-       if (count <= req->req.length)
-               req->req.actual = count;
-
-       if (count != req->dma_bytes || status)
-               omap_stop_dma(ep->lch);
-
-       /* if this wasn't short, request may need another transfer */
-       else if (req->req.actual < req->req.length)
-               return;
-
-       /* rx completion */
-       w = omap_readw(UDC_DMA_IRQ_EN);
-       w &= ~UDC_RX_EOT_IE(ep->dma_channel);
-       omap_writew(w, UDC_DMA_IRQ_EN);
-       done(ep, req, status);
-}
-
-static void dma_irq(struct omap_udc *udc, u16 irq_src)
-{
-       u16             dman_stat = omap_readw(UDC_DMAN_STAT);
-       struct omap_ep  *ep;
-       struct omap_req *req;
-
-       /* IN dma: tx to host */
-       if (irq_src & UDC_TXN_DONE) {
-               ep = &udc->ep[16 + UDC_DMA_TX_SRC(dman_stat)];
-               ep->irqs++;
-               /* can see TXN_DONE after dma abort */
-               if (!list_empty(&ep->queue)) {
-                       req = container_of(ep->queue.next,
-                                               struct omap_req, queue);
-                       finish_in_dma(ep, req, 0);
-               }
-               omap_writew(UDC_TXN_DONE, UDC_IRQ_SRC);
-
-               if (!list_empty(&ep->queue)) {
-                       req = container_of(ep->queue.next,
-                                       struct omap_req, queue);
-                       next_in_dma(ep, req);
-               }
-       }
-
-       /* OUT dma: rx from host */
-       if (irq_src & UDC_RXN_EOT) {
-               ep = &udc->ep[UDC_DMA_RX_SRC(dman_stat)];
-               ep->irqs++;
-               /* can see RXN_EOT after dma abort */
-               if (!list_empty(&ep->queue)) {
-                       req = container_of(ep->queue.next,
-                                       struct omap_req, queue);
-                       finish_out_dma(ep, req, 0, dman_stat & UDC_DMA_RX_SB);
-               }
-               omap_writew(UDC_RXN_EOT, UDC_IRQ_SRC);
-
-               if (!list_empty(&ep->queue)) {
-                       req = container_of(ep->queue.next,
-                                       struct omap_req, queue);
-                       next_out_dma(ep, req);
-               }
-       }
-
-       if (irq_src & UDC_RXN_CNT) {
-               ep = &udc->ep[UDC_DMA_RX_SRC(dman_stat)];
-               ep->irqs++;
-               /* omap15xx does this unasked... */
-               VDBG("%s, RX_CNT irq?\n", ep->ep.name);
-               omap_writew(UDC_RXN_CNT, UDC_IRQ_SRC);
-       }
-}
-
-static void dma_error(int lch, u16 ch_status, void *data)
-{
-       struct omap_ep  *ep = data;
-
-       /* if ch_status & OMAP_DMA_DROP_IRQ ... */
-       /* if ch_status & OMAP1_DMA_TOUT_IRQ ... */
-       ERR("%s dma error, lch %d status %02x\n", ep->ep.name, lch, ch_status);
-
-       /* complete current transfer ... */
-}
-
-static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
-{
-       u16     reg;
-       int     status, restart, is_in;
-       int     dma_channel;
-
-       is_in = ep->bEndpointAddress & USB_DIR_IN;
-       if (is_in)
-               reg = omap_readw(UDC_TXDMA_CFG);
-       else
-               reg = omap_readw(UDC_RXDMA_CFG);
-       reg |= UDC_DMA_REQ;             /* "pulse" activated */
-
-       ep->dma_channel = 0;
-       ep->lch = -1;
-       if (channel == 0 || channel > 3) {
-               if ((reg & 0x0f00) == 0)
-                       channel = 3;
-               else if ((reg & 0x00f0) == 0)
-                       channel = 2;
-               else if ((reg & 0x000f) == 0)   /* preferred for ISO */
-                       channel = 1;
-               else {
-                       status = -EMLINK;
-                       goto just_restart;
-               }
-       }
-       reg |= (0x0f & ep->bEndpointAddress) << (4 * (channel - 1));
-       ep->dma_channel = channel;
-
-       if (is_in) {
-               dma_channel = OMAP_DMA_USB_W2FC_TX0 - 1 + channel;
-               status = omap_request_dma(dma_channel,
-                       ep->ep.name, dma_error, ep, &ep->lch);
-               if (status == 0) {
-                       omap_writew(reg, UDC_TXDMA_CFG);
-                       /* EMIFF or SDRC */
-                       omap_set_dma_src_burst_mode(ep->lch,
-                                               OMAP_DMA_DATA_BURST_4);
-                       omap_set_dma_src_data_pack(ep->lch, 1);
-                       /* TIPB */
-                       omap_set_dma_dest_params(ep->lch,
-                               OMAP_DMA_PORT_TIPB,
-                               OMAP_DMA_AMODE_CONSTANT,
-                               UDC_DATA_DMA,
-                               0, 0);
-               }
-       } else {
-               dma_channel = OMAP_DMA_USB_W2FC_RX0 - 1 + channel;
-               status = omap_request_dma(dma_channel,
-                       ep->ep.name, dma_error, ep, &ep->lch);
-               if (status == 0) {
-                       omap_writew(reg, UDC_RXDMA_CFG);
-                       /* TIPB */
-                       omap_set_dma_src_params(ep->lch,
-                               OMAP_DMA_PORT_TIPB,
-                               OMAP_DMA_AMODE_CONSTANT,
-                               UDC_DATA_DMA,
-                               0, 0);
-                       /* EMIFF or SDRC */
-                       omap_set_dma_dest_burst_mode(ep->lch,
-                                               OMAP_DMA_DATA_BURST_4);
-                       omap_set_dma_dest_data_pack(ep->lch, 1);
-               }
-       }
-       if (status)
-               ep->dma_channel = 0;
-       else {
-               ep->has_dma = 1;
-               omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ);
-
-               /* channel type P: hw synch (fifo) */
-               if (!cpu_is_omap15xx())
-                       omap_set_dma_channel_mode(ep->lch, OMAP_DMA_LCH_P);
-       }
-
-just_restart:
-       /* restart any queue, even if the claim failed  */
-       restart = !ep->stopped && !list_empty(&ep->queue);
-
-       if (status)
-               DBG("%s no dma channel: %d%s\n", ep->ep.name, status,
-                       restart ? " (restart)" : "");
-       else
-               DBG("%s claimed %cxdma%d lch %d%s\n", ep->ep.name,
-                       is_in ? 't' : 'r',
-                       ep->dma_channel - 1, ep->lch,
-                       restart ? " (restart)" : "");
-
-       if (restart) {
-               struct omap_req *req;
-               req = container_of(ep->queue.next, struct omap_req, queue);
-               if (ep->has_dma)
-                       (is_in ? next_in_dma : next_out_dma)(ep, req);
-               else {
-                       use_ep(ep, UDC_EP_SEL);
-                       (is_in ? write_fifo : read_fifo)(ep, req);
-                       deselect_ep();
-                       if (!is_in) {
-                               omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-                               ep->ackwait = 1 + ep->double_buf;
-                       }
-                       /* IN: 6 wait states before it'll tx */
-               }
-       }
-}
-
-static void dma_channel_release(struct omap_ep *ep)
-{
-       int             shift = 4 * (ep->dma_channel - 1);
-       u16             mask = 0x0f << shift;
-       struct omap_req *req;
-       int             active;
-
-       /* abort any active usb transfer request */
-       if (!list_empty(&ep->queue))
-               req = container_of(ep->queue.next, struct omap_req, queue);
-       else
-               req = NULL;
-
-       active = omap_get_dma_active_status(ep->lch);
-
-       DBG("%s release %s %cxdma%d %p\n", ep->ep.name,
-                       active ? "active" : "idle",
-                       (ep->bEndpointAddress & USB_DIR_IN) ? 't' : 'r',
-                       ep->dma_channel - 1, req);
-
-       /* NOTE: re-setting RX_REQ/TX_REQ because of a chip bug (before
-        * OMAP 1710 ES2.0) where reading the DMA_CFG can clear them.
-        */
-
-       /* wait till current packet DMA finishes, and fifo empties */
-       if (ep->bEndpointAddress & USB_DIR_IN) {
-               omap_writew((omap_readw(UDC_TXDMA_CFG) & ~mask) | UDC_DMA_REQ,
-                                       UDC_TXDMA_CFG);
-
-               if (req) {
-                       finish_in_dma(ep, req, -ECONNRESET);
-
-                       /* clear FIFO; hosts probably won't empty it */
-                       use_ep(ep, UDC_EP_SEL);
-                       omap_writew(UDC_CLR_EP, UDC_CTRL);
-                       deselect_ep();
-               }
-               while (omap_readw(UDC_TXDMA_CFG) & mask)
-                       udelay(10);
-       } else {
-               omap_writew((omap_readw(UDC_RXDMA_CFG) & ~mask) | UDC_DMA_REQ,
-                                       UDC_RXDMA_CFG);
-
-               /* dma empties the fifo */
-               while (omap_readw(UDC_RXDMA_CFG) & mask)
-                       udelay(10);
-               if (req)
-                       finish_out_dma(ep, req, -ECONNRESET, 0);
-       }
-       omap_free_dma(ep->lch);
-       ep->dma_channel = 0;
-       ep->lch = -1;
-       /* has_dma still set, till endpoint is fully quiesced */
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int
-omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
-{
-       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
-       struct omap_req *req = container_of(_req, struct omap_req, req);
-       struct omap_udc *udc;
-       unsigned long   flags;
-       int             is_iso = 0;
-
-       /* catch various bogus parameters */
-       if (!_req || !req->req.complete || !req->req.buf
-                       || !list_empty(&req->queue)) {
-               DBG("%s, bad params\n", __func__);
-               return -EINVAL;
-       }
-       if (!_ep || (!ep->ep.desc && ep->bEndpointAddress)) {
-               DBG("%s, bad ep\n", __func__);
-               return -EINVAL;
-       }
-       if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
-               if (req->req.length > ep->ep.maxpacket)
-                       return -EMSGSIZE;
-               is_iso = 1;
-       }
-
-       /* this isn't bogus, but OMAP DMA isn't the only hardware to
-        * have a hard time with partial packet reads...  reject it.
-        */
-       if (use_dma
-                       && ep->has_dma
-                       && ep->bEndpointAddress != 0
-                       && (ep->bEndpointAddress & USB_DIR_IN) == 0
-                       && (req->req.length % ep->ep.maxpacket) != 0) {
-               DBG("%s, no partial packet OUT reads\n", __func__);
-               return -EMSGSIZE;
-       }
-
-       udc = ep->udc;
-       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       if (use_dma && ep->has_dma)
-               usb_gadget_map_request(&udc->gadget, &req->req,
-                               (ep->bEndpointAddress & USB_DIR_IN));
-
-       VDBG("%s queue req %p, len %d buf %p\n",
-               ep->ep.name, _req, _req->length, _req->buf);
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       req->req.status = -EINPROGRESS;
-       req->req.actual = 0;
-
-       /* maybe kickstart non-iso i/o queues */
-       if (is_iso) {
-               u16 w;
-
-               w = omap_readw(UDC_IRQ_EN);
-               w |= UDC_SOF_IE;
-               omap_writew(w, UDC_IRQ_EN);
-       } else if (list_empty(&ep->queue) && !ep->stopped && !ep->ackwait) {
-               int     is_in;
-
-               if (ep->bEndpointAddress == 0) {
-                       if (!udc->ep0_pending || !list_empty(&ep->queue)) {
-                               spin_unlock_irqrestore(&udc->lock, flags);
-                               return -EL2HLT;
-                       }
-
-                       /* empty DATA stage? */
-                       is_in = udc->ep0_in;
-                       if (!req->req.length) {
-
-                               /* chip became CONFIGURED or ADDRESSED
-                                * earlier; drivers may already have queued
-                                * requests to non-control endpoints
-                                */
-                               if (udc->ep0_set_config) {
-                                       u16     irq_en = omap_readw(UDC_IRQ_EN);
-
-                                       irq_en |= UDC_DS_CHG_IE | UDC_EP0_IE;
-                                       if (!udc->ep0_reset_config)
-                                               irq_en |= UDC_EPN_RX_IE
-                                                       | UDC_EPN_TX_IE;
-                                       omap_writew(irq_en, UDC_IRQ_EN);
-                               }
-
-                               /* STATUS for zero length DATA stages is
-                                * always an IN ... even for IN transfers,
-                                * a weird case which seem to stall OMAP.
-                                */
-                               omap_writew(UDC_EP_SEL | UDC_EP_DIR,
-                                               UDC_EP_NUM);
-                               omap_writew(UDC_CLR_EP, UDC_CTRL);
-                               omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-                               omap_writew(UDC_EP_DIR, UDC_EP_NUM);
-
-                               /* cleanup */
-                               udc->ep0_pending = 0;
-                               done(ep, req, 0);
-                               req = NULL;
-
-                       /* non-empty DATA stage */
-                       } else if (is_in) {
-                               omap_writew(UDC_EP_SEL | UDC_EP_DIR,
-                                               UDC_EP_NUM);
-                       } else {
-                               if (udc->ep0_setup)
-                                       goto irq_wait;
-                               omap_writew(UDC_EP_SEL, UDC_EP_NUM);
-                       }
-               } else {
-                       is_in = ep->bEndpointAddress & USB_DIR_IN;
-                       if (!ep->has_dma)
-                               use_ep(ep, UDC_EP_SEL);
-                       /* if ISO: SOF IRQs must be enabled/disabled! */
-               }
-
-               if (ep->has_dma)
-                       (is_in ? next_in_dma : next_out_dma)(ep, req);
-               else if (req) {
-                       if ((is_in ? write_fifo : read_fifo)(ep, req) == 1)
-                               req = NULL;
-                       deselect_ep();
-                       if (!is_in) {
-                               omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-                               ep->ackwait = 1 + ep->double_buf;
-                       }
-                       /* IN: 6 wait states before it'll tx */
-               }
-       }
-
-irq_wait:
-       /* irq handler advances the queue */
-       if (req != NULL)
-               list_add_tail(&req->queue, &ep->queue);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-static int omap_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
-       struct omap_req *req;
-       unsigned long   flags;
-
-       if (!_ep || !_req)
-               return -EINVAL;
-
-       spin_lock_irqsave(&ep->udc->lock, flags);
-
-       /* make sure it's actually queued on this endpoint */
-       list_for_each_entry(req, &ep->queue, queue) {
-               if (&req->req == _req)
-                       break;
-       }
-       if (&req->req != _req) {
-               spin_unlock_irqrestore(&ep->udc->lock, flags);
-               return -EINVAL;
-       }
-
-       if (use_dma && ep->dma_channel && ep->queue.next == &req->queue) {
-               int channel = ep->dma_channel;
-
-               /* releasing the channel cancels the request,
-                * reclaiming the channel restarts the queue
-                */
-               dma_channel_release(ep);
-               dma_channel_claim(ep, channel);
-       } else
-               done(ep, req, -ECONNRESET);
-       spin_unlock_irqrestore(&ep->udc->lock, flags);
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int omap_ep_set_halt(struct usb_ep *_ep, int value)
-{
-       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
-       unsigned long   flags;
-       int             status = -EOPNOTSUPP;
-
-       spin_lock_irqsave(&ep->udc->lock, flags);
-
-       /* just use protocol stalls for ep0; real halts are annoying */
-       if (ep->bEndpointAddress == 0) {
-               if (!ep->udc->ep0_pending)
-                       status = -EINVAL;
-               else if (value) {
-                       if (ep->udc->ep0_set_config) {
-                               WARNING("error changing config?\n");
-                               omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
-                       }
-                       omap_writew(UDC_STALL_CMD, UDC_SYSCON2);
-                       ep->udc->ep0_pending = 0;
-                       status = 0;
-               } else /* NOP */
-                       status = 0;
-
-       /* otherwise, all active non-ISO endpoints can halt */
-       } else if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC && ep->ep.desc) {
-
-               /* IN endpoints must already be idle */
-               if ((ep->bEndpointAddress & USB_DIR_IN)
-                               && !list_empty(&ep->queue)) {
-                       status = -EAGAIN;
-                       goto done;
-               }
-
-               if (value) {
-                       int     channel;
-
-                       if (use_dma && ep->dma_channel
-                                       && !list_empty(&ep->queue)) {
-                               channel = ep->dma_channel;
-                               dma_channel_release(ep);
-                       } else
-                               channel = 0;
-
-                       use_ep(ep, UDC_EP_SEL);
-                       if (omap_readw(UDC_STAT_FLG) & UDC_NON_ISO_FIFO_EMPTY) {
-                               omap_writew(UDC_SET_HALT, UDC_CTRL);
-                               status = 0;
-                       } else
-                               status = -EAGAIN;
-                       deselect_ep();
-
-                       if (channel)
-                               dma_channel_claim(ep, channel);
-               } else {
-                       use_ep(ep, 0);
-                       omap_writew(ep->udc->clr_halt, UDC_CTRL);
-                       ep->ackwait = 0;
-                       if (!(ep->bEndpointAddress & USB_DIR_IN)) {
-                               omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-                               ep->ackwait = 1 + ep->double_buf;
-                       }
-               }
-       }
-done:
-       VDBG("%s %s halt stat %d\n", ep->ep.name,
-               value ? "set" : "clear", status);
-
-       spin_unlock_irqrestore(&ep->udc->lock, flags);
-       return status;
-}
-
-static struct usb_ep_ops omap_ep_ops = {
-       .enable         = omap_ep_enable,
-       .disable        = omap_ep_disable,
-
-       .alloc_request  = omap_alloc_request,
-       .free_request   = omap_free_request,
-
-       .queue          = omap_ep_queue,
-       .dequeue        = omap_ep_dequeue,
-
-       .set_halt       = omap_ep_set_halt,
-       /* fifo_status ... report bytes in fifo */
-       /* fifo_flush ... flush fifo */
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int omap_get_frame(struct usb_gadget *gadget)
-{
-       u16     sof = omap_readw(UDC_SOF);
-       return (sof & UDC_TS_OK) ? (sof & UDC_TS) : -EL2NSYNC;
-}
-
-static int omap_wakeup(struct usb_gadget *gadget)
-{
-       struct omap_udc *udc;
-       unsigned long   flags;
-       int             retval = -EHOSTUNREACH;
-
-       udc = container_of(gadget, struct omap_udc, gadget);
-
-       spin_lock_irqsave(&udc->lock, flags);
-       if (udc->devstat & UDC_SUS) {
-               /* NOTE:  OTG spec erratum says that OTG devices may
-                * issue wakeups without host enable.
-                */
-               if (udc->devstat & (UDC_B_HNP_ENABLE|UDC_R_WK_OK)) {
-                       DBG("remote wakeup...\n");
-                       omap_writew(UDC_RMT_WKP, UDC_SYSCON2);
-                       retval = 0;
-               }
-
-       /* NOTE:  non-OTG systems may use SRP TOO... */
-       } else if (!(udc->devstat & UDC_ATT)) {
-               if (!IS_ERR_OR_NULL(udc->transceiver))
-                       retval = otg_start_srp(udc->transceiver->otg);
-       }
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return retval;
-}
-
-static int
-omap_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
-{
-       struct omap_udc *udc;
-       unsigned long   flags;
-       u16             syscon1;
-
-       udc = container_of(gadget, struct omap_udc, gadget);
-       spin_lock_irqsave(&udc->lock, flags);
-       syscon1 = omap_readw(UDC_SYSCON1);
-       if (is_selfpowered)
-               syscon1 |= UDC_SELF_PWR;
-       else
-               syscon1 &= ~UDC_SELF_PWR;
-       omap_writew(syscon1, UDC_SYSCON1);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
-}
-
-static int can_pullup(struct omap_udc *udc)
-{
-       return udc->driver && udc->softconnect && udc->vbus_active;
-}
-
-static void pullup_enable(struct omap_udc *udc)
-{
-       u16 w;
-
-       w = omap_readw(UDC_SYSCON1);
-       w |= UDC_PULLUP_EN;
-       omap_writew(w, UDC_SYSCON1);
-       if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) {
-               u32 l;
-
-               l = omap_readl(OTG_CTRL);
-               l |= OTG_BSESSVLD;
-               omap_writel(l, OTG_CTRL);
-       }
-       omap_writew(UDC_DS_CHG_IE, UDC_IRQ_EN);
-}
-
-static void pullup_disable(struct omap_udc *udc)
-{
-       u16 w;
-
-       if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) {
-               u32 l;
-
-               l = omap_readl(OTG_CTRL);
-               l &= ~OTG_BSESSVLD;
-               omap_writel(l, OTG_CTRL);
-       }
-       omap_writew(UDC_DS_CHG_IE, UDC_IRQ_EN);
-       w = omap_readw(UDC_SYSCON1);
-       w &= ~UDC_PULLUP_EN;
-       omap_writew(w, UDC_SYSCON1);
-}
-
-static struct omap_udc *udc;
-
-static void omap_udc_enable_clock(int enable)
-{
-       if (udc == NULL || udc->dc_clk == NULL || udc->hhc_clk == NULL)
-               return;
-
-       if (enable) {
-               clk_enable(udc->dc_clk);
-               clk_enable(udc->hhc_clk);
-               udelay(100);
-       } else {
-               clk_disable(udc->hhc_clk);
-               clk_disable(udc->dc_clk);
-       }
-}
-
-/*
- * Called by whatever detects VBUS sessions:  external transceiver
- * driver, or maybe GPIO0 VBUS IRQ.  May request 48 MHz clock.
- */
-static int omap_vbus_session(struct usb_gadget *gadget, int is_active)
-{
-       struct omap_udc *udc;
-       unsigned long   flags;
-       u32 l;
-
-       udc = container_of(gadget, struct omap_udc, gadget);
-       spin_lock_irqsave(&udc->lock, flags);
-       VDBG("VBUS %s\n", is_active ? "on" : "off");
-       udc->vbus_active = (is_active != 0);
-       if (cpu_is_omap15xx()) {
-               /* "software" detect, ignored if !VBUS_MODE_1510 */
-               l = omap_readl(FUNC_MUX_CTRL_0);
-               if (is_active)
-                       l |= VBUS_CTRL_1510;
-               else
-                       l &= ~VBUS_CTRL_1510;
-               omap_writel(l, FUNC_MUX_CTRL_0);
-       }
-       if (udc->dc_clk != NULL && is_active) {
-               if (!udc->clk_requested) {
-                       omap_udc_enable_clock(1);
-                       udc->clk_requested = 1;
-               }
-       }
-       if (can_pullup(udc))
-               pullup_enable(udc);
-       else
-               pullup_disable(udc);
-       if (udc->dc_clk != NULL && !is_active) {
-               if (udc->clk_requested) {
-                       omap_udc_enable_clock(0);
-                       udc->clk_requested = 0;
-               }
-       }
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return 0;
-}
-
-static int omap_vbus_draw(struct usb_gadget *gadget, unsigned mA)
-{
-       struct omap_udc *udc;
-
-       udc = container_of(gadget, struct omap_udc, gadget);
-       if (!IS_ERR_OR_NULL(udc->transceiver))
-               return usb_phy_set_power(udc->transceiver, mA);
-       return -EOPNOTSUPP;
-}
-
-static int omap_pullup(struct usb_gadget *gadget, int is_on)
-{
-       struct omap_udc *udc;
-       unsigned long   flags;
-
-       udc = container_of(gadget, struct omap_udc, gadget);
-       spin_lock_irqsave(&udc->lock, flags);
-       udc->softconnect = (is_on != 0);
-       if (can_pullup(udc))
-               pullup_enable(udc);
-       else
-               pullup_disable(udc);
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return 0;
-}
-
-static int omap_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-static int omap_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-
-static const struct usb_gadget_ops omap_gadget_ops = {
-       .get_frame              = omap_get_frame,
-       .wakeup                 = omap_wakeup,
-       .set_selfpowered        = omap_set_selfpowered,
-       .vbus_session           = omap_vbus_session,
-       .vbus_draw              = omap_vbus_draw,
-       .pullup                 = omap_pullup,
-       .udc_start              = omap_udc_start,
-       .udc_stop               = omap_udc_stop,
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* dequeue ALL requests; caller holds udc->lock */
-static void nuke(struct omap_ep *ep, int status)
-{
-       struct omap_req *req;
-
-       ep->stopped = 1;
-
-       if (use_dma && ep->dma_channel)
-               dma_channel_release(ep);
-
-       use_ep(ep, 0);
-       omap_writew(UDC_CLR_EP, UDC_CTRL);
-       if (ep->bEndpointAddress && ep->bmAttributes != USB_ENDPOINT_XFER_ISOC)
-               omap_writew(UDC_SET_HALT, UDC_CTRL);
-
-       while (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next, struct omap_req, queue);
-               done(ep, req, status);
-       }
-}
-
-/* caller holds udc->lock */
-static void udc_quiesce(struct omap_udc *udc)
-{
-       struct omap_ep  *ep;
-
-       udc->gadget.speed = USB_SPEED_UNKNOWN;
-       nuke(&udc->ep[0], -ESHUTDOWN);
-       list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list)
-               nuke(ep, -ESHUTDOWN);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void update_otg(struct omap_udc *udc)
-{
-       u16     devstat;
-
-       if (!gadget_is_otg(&udc->gadget))
-               return;
-
-       if (omap_readl(OTG_CTRL) & OTG_ID)
-               devstat = omap_readw(UDC_DEVSTAT);
-       else
-               devstat = 0;
-
-       udc->gadget.b_hnp_enable = !!(devstat & UDC_B_HNP_ENABLE);
-       udc->gadget.a_hnp_support = !!(devstat & UDC_A_HNP_SUPPORT);
-       udc->gadget.a_alt_hnp_support = !!(devstat & UDC_A_ALT_HNP_SUPPORT);
-
-       /* Enable HNP early, avoiding races on suspend irq path.
-        * ASSUMES OTG state machine B_BUS_REQ input is true.
-        */
-       if (udc->gadget.b_hnp_enable) {
-               u32 l;
-
-               l = omap_readl(OTG_CTRL);
-               l |= OTG_B_HNPEN | OTG_B_BUSREQ;
-               l &= ~OTG_PULLUP;
-               omap_writel(l, OTG_CTRL);
-       }
-}
-
-static void ep0_irq(struct omap_udc *udc, u16 irq_src)
-{
-       struct omap_ep  *ep0 = &udc->ep[0];
-       struct omap_req *req = NULL;
-
-       ep0->irqs++;
-
-       /* Clear any pending requests and then scrub any rx/tx state
-        * before starting to handle the SETUP request.
-        */
-       if (irq_src & UDC_SETUP) {
-               u16     ack = irq_src & (UDC_EP0_TX|UDC_EP0_RX);
-
-               nuke(ep0, 0);
-               if (ack) {
-                       omap_writew(ack, UDC_IRQ_SRC);
-                       irq_src = UDC_SETUP;
-               }
-       }
-
-       /* IN/OUT packets mean we're in the DATA or STATUS stage.
-        * This driver uses only uses protocol stalls (ep0 never halts),
-        * and if we got this far the gadget driver already had a
-        * chance to stall.  Tries to be forgiving of host oddities.
-        *
-        * NOTE:  the last chance gadget drivers have to stall control
-        * requests is during their request completion callback.
-        */
-       if (!list_empty(&ep0->queue))
-               req = container_of(ep0->queue.next, struct omap_req, queue);
-
-       /* IN == TX to host */
-       if (irq_src & UDC_EP0_TX) {
-               int     stat;
-
-               omap_writew(UDC_EP0_TX, UDC_IRQ_SRC);
-               omap_writew(UDC_EP_SEL|UDC_EP_DIR, UDC_EP_NUM);
-               stat = omap_readw(UDC_STAT_FLG);
-               if (stat & UDC_ACK) {
-                       if (udc->ep0_in) {
-                               /* write next IN packet from response,
-                                * or set up the status stage.
-                                */
-                               if (req)
-                                       stat = write_fifo(ep0, req);
-                               omap_writew(UDC_EP_DIR, UDC_EP_NUM);
-                               if (!req && udc->ep0_pending) {
-                                       omap_writew(UDC_EP_SEL, UDC_EP_NUM);
-                                       omap_writew(UDC_CLR_EP, UDC_CTRL);
-                                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-                                       omap_writew(0, UDC_EP_NUM);
-                                       udc->ep0_pending = 0;
-                               } /* else:  6 wait states before it'll tx */
-                       } else {
-                               /* ack status stage of OUT transfer */
-                               omap_writew(UDC_EP_DIR, UDC_EP_NUM);
-                               if (req)
-                                       done(ep0, req, 0);
-                       }
-                       req = NULL;
-               } else if (stat & UDC_STALL) {
-                       omap_writew(UDC_CLR_HALT, UDC_CTRL);
-                       omap_writew(UDC_EP_DIR, UDC_EP_NUM);
-               } else {
-                       omap_writew(UDC_EP_DIR, UDC_EP_NUM);
-               }
-       }
-
-       /* OUT == RX from host */
-       if (irq_src & UDC_EP0_RX) {
-               int     stat;
-
-               omap_writew(UDC_EP0_RX, UDC_IRQ_SRC);
-               omap_writew(UDC_EP_SEL, UDC_EP_NUM);
-               stat = omap_readw(UDC_STAT_FLG);
-               if (stat & UDC_ACK) {
-                       if (!udc->ep0_in) {
-                               stat = 0;
-                               /* read next OUT packet of request, maybe
-                                * reactiviting the fifo; stall on errors.
-                                */
-                               stat = read_fifo(ep0, req);
-                               if (!req || stat < 0) {
-                                       omap_writew(UDC_STALL_CMD, UDC_SYSCON2);
-                                       udc->ep0_pending = 0;
-                                       stat = 0;
-                               } else if (stat == 0)
-                                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-                               omap_writew(0, UDC_EP_NUM);
-
-                               /* activate status stage */
-                               if (stat == 1) {
-                                       done(ep0, req, 0);
-                                       /* that may have STALLed ep0... */
-                                       omap_writew(UDC_EP_SEL | UDC_EP_DIR,
-                                                       UDC_EP_NUM);
-                                       omap_writew(UDC_CLR_EP, UDC_CTRL);
-                                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-                                       omap_writew(UDC_EP_DIR, UDC_EP_NUM);
-                                       udc->ep0_pending = 0;
-                               }
-                       } else {
-                               /* ack status stage of IN transfer */
-                               omap_writew(0, UDC_EP_NUM);
-                               if (req)
-                                       done(ep0, req, 0);
-                       }
-               } else if (stat & UDC_STALL) {
-                       omap_writew(UDC_CLR_HALT, UDC_CTRL);
-                       omap_writew(0, UDC_EP_NUM);
-               } else {
-                       omap_writew(0, UDC_EP_NUM);
-               }
-       }
-
-       /* SETUP starts all control transfers */
-       if (irq_src & UDC_SETUP) {
-               union u {
-                       u16                     word[4];
-                       struct usb_ctrlrequest  r;
-               } u;
-               int                     status = -EINVAL;
-               struct omap_ep          *ep;
-
-               /* read the (latest) SETUP message */
-               do {
-                       omap_writew(UDC_SETUP_SEL, UDC_EP_NUM);
-                       /* two bytes at a time */
-                       u.word[0] = omap_readw(UDC_DATA);
-                       u.word[1] = omap_readw(UDC_DATA);
-                       u.word[2] = omap_readw(UDC_DATA);
-                       u.word[3] = omap_readw(UDC_DATA);
-                       omap_writew(0, UDC_EP_NUM);
-               } while (omap_readw(UDC_IRQ_SRC) & UDC_SETUP);
-
-#define        w_value         le16_to_cpu(u.r.wValue)
-#define        w_index         le16_to_cpu(u.r.wIndex)
-#define        w_length        le16_to_cpu(u.r.wLength)
-
-               /* Delegate almost all control requests to the gadget driver,
-                * except for a handful of ch9 status/feature requests that
-                * hardware doesn't autodecode _and_ the gadget API hides.
-                */
-               udc->ep0_in = (u.r.bRequestType & USB_DIR_IN) != 0;
-               udc->ep0_set_config = 0;
-               udc->ep0_pending = 1;
-               ep0->stopped = 0;
-               ep0->ackwait = 0;
-               switch (u.r.bRequest) {
-               case USB_REQ_SET_CONFIGURATION:
-                       /* udc needs to know when ep != 0 is valid */
-                       if (u.r.bRequestType != USB_RECIP_DEVICE)
-                               goto delegate;
-                       if (w_length != 0)
-                               goto do_stall;
-                       udc->ep0_set_config = 1;
-                       udc->ep0_reset_config = (w_value == 0);
-                       VDBG("set config %d\n", w_value);
-
-                       /* update udc NOW since gadget driver may start
-                        * queueing requests immediately; clear config
-                        * later if it fails the request.
-                        */
-                       if (udc->ep0_reset_config)
-                               omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
-                       else
-                               omap_writew(UDC_DEV_CFG, UDC_SYSCON2);
-                       update_otg(udc);
-                       goto delegate;
-               case USB_REQ_CLEAR_FEATURE:
-                       /* clear endpoint halt */
-                       if (u.r.bRequestType != USB_RECIP_ENDPOINT)
-                               goto delegate;
-                       if (w_value != USB_ENDPOINT_HALT
-                                       || w_length != 0)
-                               goto do_stall;
-                       ep = &udc->ep[w_index & 0xf];
-                       if (ep != ep0) {
-                               if (w_index & USB_DIR_IN)
-                                       ep += 16;
-                               if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
-                                               || !ep->ep.desc)
-                                       goto do_stall;
-                               use_ep(ep, 0);
-                               omap_writew(udc->clr_halt, UDC_CTRL);
-                               ep->ackwait = 0;
-                               if (!(ep->bEndpointAddress & USB_DIR_IN)) {
-                                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-                                       ep->ackwait = 1 + ep->double_buf;
-                               }
-                               /* NOTE:  assumes the host behaves sanely,
-                                * only clearing real halts.  Else we may
-                                * need to kill pending transfers and then
-                                * restart the queue... very messy for DMA!
-                                */
-                       }
-                       VDBG("%s halt cleared by host\n", ep->name);
-                       goto ep0out_status_stage;
-               case USB_REQ_SET_FEATURE:
-                       /* set endpoint halt */
-                       if (u.r.bRequestType != USB_RECIP_ENDPOINT)
-                               goto delegate;
-                       if (w_value != USB_ENDPOINT_HALT
-                                       || w_length != 0)
-                               goto do_stall;
-                       ep = &udc->ep[w_index & 0xf];
-                       if (w_index & USB_DIR_IN)
-                               ep += 16;
-                       if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
-                                       || ep == ep0 || !ep->ep.desc)
-                               goto do_stall;
-                       if (use_dma && ep->has_dma) {
-                               /* this has rude side-effects (aborts) and
-                                * can't really work if DMA-IN is active
-                                */
-                               DBG("%s host set_halt, NYET\n", ep->name);
-                               goto do_stall;
-                       }
-                       use_ep(ep, 0);
-                       /* can't halt if fifo isn't empty... */
-                       omap_writew(UDC_CLR_EP, UDC_CTRL);
-                       omap_writew(UDC_SET_HALT, UDC_CTRL);
-                       VDBG("%s halted by host\n", ep->name);
-ep0out_status_stage:
-                       status = 0;
-                       omap_writew(UDC_EP_SEL|UDC_EP_DIR, UDC_EP_NUM);
-                       omap_writew(UDC_CLR_EP, UDC_CTRL);
-                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-                       omap_writew(UDC_EP_DIR, UDC_EP_NUM);
-                       udc->ep0_pending = 0;
-                       break;
-               case USB_REQ_GET_STATUS:
-                       /* USB_ENDPOINT_HALT status? */
-                       if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
-                               goto intf_status;
-
-                       /* ep0 never stalls */
-                       if (!(w_index & 0xf))
-                               goto zero_status;
-
-                       /* only active endpoints count */
-                       ep = &udc->ep[w_index & 0xf];
-                       if (w_index & USB_DIR_IN)
-                               ep += 16;
-                       if (!ep->ep.desc)
-                               goto do_stall;
-
-                       /* iso never stalls */
-                       if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
-                               goto zero_status;
-
-                       /* FIXME don't assume non-halted endpoints!! */
-                       ERR("%s status, can't report\n", ep->ep.name);
-                       goto do_stall;
-
-intf_status:
-                       /* return interface status.  if we were pedantic,
-                        * we'd detect non-existent interfaces, and stall.
-                        */
-                       if (u.r.bRequestType
-                                       != (USB_DIR_IN|USB_RECIP_INTERFACE))
-                               goto delegate;
-
-zero_status:
-                       /* return two zero bytes */
-                       omap_writew(UDC_EP_SEL|UDC_EP_DIR, UDC_EP_NUM);
-                       omap_writew(0, UDC_DATA);
-                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-                       omap_writew(UDC_EP_DIR, UDC_EP_NUM);
-                       status = 0;
-                       VDBG("GET_STATUS, interface %d\n", w_index);
-                       /* next, status stage */
-                       break;
-               default:
-delegate:
-                       /* activate the ep0out fifo right away */
-                       if (!udc->ep0_in && w_length) {
-                               omap_writew(0, UDC_EP_NUM);
-                               omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-                       }
-
-                       /* gadget drivers see class/vendor specific requests,
-                        * {SET,GET}_{INTERFACE,DESCRIPTOR,CONFIGURATION},
-                        * and more
-                        */
-                       VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n",
-                               u.r.bRequestType, u.r.bRequest,
-                               w_value, w_index, w_length);
-
-#undef w_value
-#undef w_index
-#undef w_length
-
-                       /* The gadget driver may return an error here,
-                        * causing an immediate protocol stall.
-                        *
-                        * Else it must issue a response, either queueing a
-                        * response buffer for the DATA stage, or halting ep0
-                        * (causing a protocol stall, not a real halt).  A
-                        * zero length buffer means no DATA stage.
-                        *
-                        * It's fine to issue that response after the setup()
-                        * call returns, and this IRQ was handled.
-                        */
-                       udc->ep0_setup = 1;
-                       spin_unlock(&udc->lock);
-                       status = udc->driver->setup(&udc->gadget, &u.r);
-                       spin_lock(&udc->lock);
-                       udc->ep0_setup = 0;
-               }
-
-               if (status < 0) {
-do_stall:
-                       VDBG("req %02x.%02x protocol STALL; stat %d\n",
-                                       u.r.bRequestType, u.r.bRequest, status);
-                       if (udc->ep0_set_config) {
-                               if (udc->ep0_reset_config)
-                                       WARNING("error resetting config?\n");
-                               else
-                                       omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
-                       }
-                       omap_writew(UDC_STALL_CMD, UDC_SYSCON2);
-                       udc->ep0_pending = 0;
-               }
-       }
-}
-
-/*-------------------------------------------------------------------------*/
-
-#define OTG_FLAGS (UDC_B_HNP_ENABLE|UDC_A_HNP_SUPPORT|UDC_A_ALT_HNP_SUPPORT)
-
-static void devstate_irq(struct omap_udc *udc, u16 irq_src)
-{
-       u16     devstat, change;
-
-       devstat = omap_readw(UDC_DEVSTAT);
-       change = devstat ^ udc->devstat;
-       udc->devstat = devstat;
-
-       if (change & (UDC_USB_RESET|UDC_ATT)) {
-               udc_quiesce(udc);
-
-               if (change & UDC_ATT) {
-                       /* driver for any external transceiver will
-                        * have called omap_vbus_session() already
-                        */
-                       if (devstat & UDC_ATT) {
-                               udc->gadget.speed = USB_SPEED_FULL;
-                               VDBG("connect\n");
-                               if (IS_ERR_OR_NULL(udc->transceiver))
-                                       pullup_enable(udc);
-                               /* if (driver->connect) call it */
-                       } else if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
-                               udc->gadget.speed = USB_SPEED_UNKNOWN;
-                               if (IS_ERR_OR_NULL(udc->transceiver))
-                                       pullup_disable(udc);
-                               DBG("disconnect, gadget %s\n",
-                                       udc->driver->driver.name);
-                               if (udc->driver->disconnect) {
-                                       spin_unlock(&udc->lock);
-                                       udc->driver->disconnect(&udc->gadget);
-                                       spin_lock(&udc->lock);
-                               }
-                       }
-                       change &= ~UDC_ATT;
-               }
-
-               if (change & UDC_USB_RESET) {
-                       if (devstat & UDC_USB_RESET) {
-                               VDBG("RESET=1\n");
-                       } else {
-                               udc->gadget.speed = USB_SPEED_FULL;
-                               INFO("USB reset done, gadget %s\n",
-                                       udc->driver->driver.name);
-                               /* ep0 traffic is legal from now on */
-                               omap_writew(UDC_DS_CHG_IE | UDC_EP0_IE,
-                                               UDC_IRQ_EN);
-                       }
-                       change &= ~UDC_USB_RESET;
-               }
-       }
-       if (change & UDC_SUS) {
-               if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
-                       /* FIXME tell isp1301 to suspend/resume (?) */
-                       if (devstat & UDC_SUS) {
-                               VDBG("suspend\n");
-                               update_otg(udc);
-                               /* HNP could be under way already */
-                               if (udc->gadget.speed == USB_SPEED_FULL
-                                               && udc->driver->suspend) {
-                                       spin_unlock(&udc->lock);
-                                       udc->driver->suspend(&udc->gadget);
-                                       spin_lock(&udc->lock);
-                               }
-                               if (!IS_ERR_OR_NULL(udc->transceiver))
-                                       usb_phy_set_suspend(
-                                                       udc->transceiver, 1);
-                       } else {
-                               VDBG("resume\n");
-                               if (!IS_ERR_OR_NULL(udc->transceiver))
-                                       usb_phy_set_suspend(
-                                                       udc->transceiver, 0);
-                               if (udc->gadget.speed == USB_SPEED_FULL
-                                               && udc->driver->resume) {
-                                       spin_unlock(&udc->lock);
-                                       udc->driver->resume(&udc->gadget);
-                                       spin_lock(&udc->lock);
-                               }
-                       }
-               }
-               change &= ~UDC_SUS;
-       }
-       if (!cpu_is_omap15xx() && (change & OTG_FLAGS)) {
-               update_otg(udc);
-               change &= ~OTG_FLAGS;
-       }
-
-       change &= ~(UDC_CFG|UDC_DEF|UDC_ADD);
-       if (change)
-               VDBG("devstat %03x, ignore change %03x\n",
-                       devstat,  change);
-
-       omap_writew(UDC_DS_CHG, UDC_IRQ_SRC);
-}
-
-static irqreturn_t omap_udc_irq(int irq, void *_udc)
-{
-       struct omap_udc *udc = _udc;
-       u16             irq_src;
-       irqreturn_t     status = IRQ_NONE;
-       unsigned long   flags;
-
-       spin_lock_irqsave(&udc->lock, flags);
-       irq_src = omap_readw(UDC_IRQ_SRC);
-
-       /* Device state change (usb ch9 stuff) */
-       if (irq_src & UDC_DS_CHG) {
-               devstate_irq(_udc, irq_src);
-               status = IRQ_HANDLED;
-               irq_src &= ~UDC_DS_CHG;
-       }
-
-       /* EP0 control transfers */
-       if (irq_src & (UDC_EP0_RX|UDC_SETUP|UDC_EP0_TX)) {
-               ep0_irq(_udc, irq_src);
-               status = IRQ_HANDLED;
-               irq_src &= ~(UDC_EP0_RX|UDC_SETUP|UDC_EP0_TX);
-       }
-
-       /* DMA transfer completion */
-       if (use_dma && (irq_src & (UDC_TXN_DONE|UDC_RXN_CNT|UDC_RXN_EOT))) {
-               dma_irq(_udc, irq_src);
-               status = IRQ_HANDLED;
-               irq_src &= ~(UDC_TXN_DONE|UDC_RXN_CNT|UDC_RXN_EOT);
-       }
-
-       irq_src &= ~(UDC_IRQ_SOF | UDC_EPN_TX|UDC_EPN_RX);
-       if (irq_src)
-               DBG("udc_irq, unhandled %03x\n", irq_src);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       return status;
-}
-
-/* workaround for seemingly-lost IRQs for RX ACKs... */
-#define PIO_OUT_TIMEOUT        (jiffies + HZ/3)
-#define HALF_FULL(f)   (!((f)&(UDC_NON_ISO_FIFO_FULL|UDC_NON_ISO_FIFO_EMPTY)))
-
-static void pio_out_timer(unsigned long _ep)
-{
-       struct omap_ep  *ep = (void *) _ep;
-       unsigned long   flags;
-       u16             stat_flg;
-
-       spin_lock_irqsave(&ep->udc->lock, flags);
-       if (!list_empty(&ep->queue) && ep->ackwait) {
-               use_ep(ep, UDC_EP_SEL);
-               stat_flg = omap_readw(UDC_STAT_FLG);
-
-               if ((stat_flg & UDC_ACK) && (!(stat_flg & UDC_FIFO_EN)
-                               || (ep->double_buf && HALF_FULL(stat_flg)))) {
-                       struct omap_req *req;
-
-                       VDBG("%s: lose, %04x\n", ep->ep.name, stat_flg);
-                       req = container_of(ep->queue.next,
-                                       struct omap_req, queue);
-                       (void) read_fifo(ep, req);
-                       omap_writew(ep->bEndpointAddress, UDC_EP_NUM);
-                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-                       ep->ackwait = 1 + ep->double_buf;
-               } else
-                       deselect_ep();
-       }
-       mod_timer(&ep->timer, PIO_OUT_TIMEOUT);
-       spin_unlock_irqrestore(&ep->udc->lock, flags);
-}
-
-static irqreturn_t omap_udc_pio_irq(int irq, void *_dev)
-{
-       u16             epn_stat, irq_src;
-       irqreturn_t     status = IRQ_NONE;
-       struct omap_ep  *ep;
-       int             epnum;
-       struct omap_udc *udc = _dev;
-       struct omap_req *req;
-       unsigned long   flags;
-
-       spin_lock_irqsave(&udc->lock, flags);
-       epn_stat = omap_readw(UDC_EPN_STAT);
-       irq_src = omap_readw(UDC_IRQ_SRC);
-
-       /* handle OUT first, to avoid some wasteful NAKs */
-       if (irq_src & UDC_EPN_RX) {
-               epnum = (epn_stat >> 8) & 0x0f;
-               omap_writew(UDC_EPN_RX, UDC_IRQ_SRC);
-               status = IRQ_HANDLED;
-               ep = &udc->ep[epnum];
-               ep->irqs++;
-
-               omap_writew(epnum | UDC_EP_SEL, UDC_EP_NUM);
-               ep->fnf = 0;
-               if (omap_readw(UDC_STAT_FLG) & UDC_ACK) {
-                       ep->ackwait--;
-                       if (!list_empty(&ep->queue)) {
-                               int stat;
-                               req = container_of(ep->queue.next,
-                                               struct omap_req, queue);
-                               stat = read_fifo(ep, req);
-                               if (!ep->double_buf)
-                                       ep->fnf = 1;
-                       }
-               }
-               /* min 6 clock delay before clearing EP_SEL ... */
-               epn_stat = omap_readw(UDC_EPN_STAT);
-               epn_stat = omap_readw(UDC_EPN_STAT);
-               omap_writew(epnum, UDC_EP_NUM);
-
-               /* enabling fifo _after_ clearing ACK, contrary to docs,
-                * reduces lossage; timer still needed though (sigh).
-                */
-               if (ep->fnf) {
-                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
-                       ep->ackwait = 1 + ep->double_buf;
-               }
-               mod_timer(&ep->timer, PIO_OUT_TIMEOUT);
-       }
-
-       /* then IN transfers */
-       else if (irq_src & UDC_EPN_TX) {
-               epnum = epn_stat & 0x0f;
-               omap_writew(UDC_EPN_TX, UDC_IRQ_SRC);
-               status = IRQ_HANDLED;
-               ep = &udc->ep[16 + epnum];
-               ep->irqs++;
-
-               omap_writew(epnum | UDC_EP_DIR | UDC_EP_SEL, UDC_EP_NUM);
-               if (omap_readw(UDC_STAT_FLG) & UDC_ACK) {
-                       ep->ackwait = 0;
-                       if (!list_empty(&ep->queue)) {
-                               req = container_of(ep->queue.next,
-                                               struct omap_req, queue);
-                               (void) write_fifo(ep, req);
-                       }
-               }
-               /* min 6 clock delay before clearing EP_SEL ... */
-               epn_stat = omap_readw(UDC_EPN_STAT);
-               epn_stat = omap_readw(UDC_EPN_STAT);
-               omap_writew(epnum | UDC_EP_DIR, UDC_EP_NUM);
-               /* then 6 clocks before it'd tx */
-       }
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return status;
-}
-
-#ifdef USE_ISO
-static irqreturn_t omap_udc_iso_irq(int irq, void *_dev)
-{
-       struct omap_udc *udc = _dev;
-       struct omap_ep  *ep;
-       int             pending = 0;
-       unsigned long   flags;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       /* handle all non-DMA ISO transfers */
-       list_for_each_entry(ep, &udc->iso, iso) {
-               u16             stat;
-               struct omap_req *req;
-
-               if (ep->has_dma || list_empty(&ep->queue))
-                       continue;
-               req = list_entry(ep->queue.next, struct omap_req, queue);
-
-               use_ep(ep, UDC_EP_SEL);
-               stat = omap_readw(UDC_STAT_FLG);
-
-               /* NOTE: like the other controller drivers, this isn't
-                * currently reporting lost or damaged frames.
-                */
-               if (ep->bEndpointAddress & USB_DIR_IN) {
-                       if (stat & UDC_MISS_IN)
-                               /* done(ep, req, -EPROTO) */;
-                       else
-                               write_fifo(ep, req);
-               } else {
-                       int     status = 0;
-
-                       if (stat & UDC_NO_RXPACKET)
-                               status = -EREMOTEIO;
-                       else if (stat & UDC_ISO_ERR)
-                               status = -EILSEQ;
-                       else if (stat & UDC_DATA_FLUSH)
-                               status = -ENOSR;
-
-                       if (status)
-                               /* done(ep, req, status) */;
-                       else
-                               read_fifo(ep, req);
-               }
-               deselect_ep();
-               /* 6 wait states before next EP */
-
-               ep->irqs++;
-               if (!list_empty(&ep->queue))
-                       pending = 1;
-       }
-       if (!pending) {
-               u16 w;
-
-               w = omap_readw(UDC_IRQ_EN);
-               w &= ~UDC_SOF_IE;
-               omap_writew(w, UDC_IRQ_EN);
-       }
-       omap_writew(UDC_IRQ_SOF, UDC_IRQ_SRC);
-
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return IRQ_HANDLED;
-}
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-static inline int machine_without_vbus_sense(void)
-{
-       return machine_is_omap_innovator()
-               || machine_is_omap_osk()
-               || machine_is_sx1()
-               /* No known omap7xx boards with vbus sense */
-               || cpu_is_omap7xx();
-}
-
-static int omap_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       int             status = -ENODEV;
-       struct omap_ep  *ep;
-       unsigned long   flags;
-
-
-       spin_lock_irqsave(&udc->lock, flags);
-       /* reset state */
-       list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
-               ep->irqs = 0;
-               if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
-                       continue;
-               use_ep(ep, 0);
-               omap_writew(UDC_SET_HALT, UDC_CTRL);
-       }
-       udc->ep0_pending = 0;
-       udc->ep[0].irqs = 0;
-       udc->softconnect = 1;
-
-       /* hook up the driver */
-       driver->driver.bus = NULL;
-       udc->driver = driver;
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       if (udc->dc_clk != NULL)
-               omap_udc_enable_clock(1);
-
-       omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
-
-       /* connect to bus through transceiver */
-       if (!IS_ERR_OR_NULL(udc->transceiver)) {
-               status = otg_set_peripheral(udc->transceiver->otg,
-                                               &udc->gadget);
-               if (status < 0) {
-                       ERR("can't bind to transceiver\n");
-                       udc->driver = NULL;
-                       goto done;
-               }
-       } else {
-               if (can_pullup(udc))
-                       pullup_enable(udc);
-               else
-                       pullup_disable(udc);
-       }
-
-       /* boards that don't have VBUS sensing can't autogate 48MHz;
-        * can't enter deep sleep while a gadget driver is active.
-        */
-       if (machine_without_vbus_sense())
-               omap_vbus_session(&udc->gadget, 1);
-
-done:
-       if (udc->dc_clk != NULL)
-               omap_udc_enable_clock(0);
-
-       return status;
-}
-
-static int omap_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       unsigned long   flags;
-       int             status = -ENODEV;
-
-       if (udc->dc_clk != NULL)
-               omap_udc_enable_clock(1);
-
-       if (machine_without_vbus_sense())
-               omap_vbus_session(&udc->gadget, 0);
-
-       if (!IS_ERR_OR_NULL(udc->transceiver))
-               (void) otg_set_peripheral(udc->transceiver->otg, NULL);
-       else
-               pullup_disable(udc);
-
-       spin_lock_irqsave(&udc->lock, flags);
-       udc_quiesce(udc);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       udc->driver = NULL;
-
-       if (udc->dc_clk != NULL)
-               omap_udc_enable_clock(0);
-
-       return status;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-
-#include <linux/seq_file.h>
-
-static const char proc_filename[] = "driver/udc";
-
-#define FOURBITS "%s%s%s%s"
-#define EIGHTBITS "%s%s%s%s%s%s%s%s"
-
-static void proc_ep_show(struct seq_file *s, struct omap_ep *ep)
-{
-       u16             stat_flg;
-       struct omap_req *req;
-       char            buf[20];
-
-       use_ep(ep, 0);
-
-       if (use_dma && ep->has_dma)
-               snprintf(buf, sizeof buf, "(%cxdma%d lch%d) ",
-                       (ep->bEndpointAddress & USB_DIR_IN) ? 't' : 'r',
-                       ep->dma_channel - 1, ep->lch);
-       else
-               buf[0] = 0;
-
-       stat_flg = omap_readw(UDC_STAT_FLG);
-       seq_printf(s,
-               "\n%s %s%s%sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n",
-               ep->name, buf,
-               ep->double_buf ? "dbuf " : "",
-               ({ char *s;
-               switch (ep->ackwait) {
-               case 0:
-                       s = "";
-                       break;
-               case 1:
-                       s = "(ackw) ";
-                       break;
-               case 2:
-                       s = "(ackw2) ";
-                       break;
-               default:
-                       s = "(?) ";
-                       break;
-               } s; }),
-               ep->irqs, stat_flg,
-               (stat_flg & UDC_NO_RXPACKET) ? "no_rxpacket " : "",
-               (stat_flg & UDC_MISS_IN) ? "miss_in " : "",
-               (stat_flg & UDC_DATA_FLUSH) ? "data_flush " : "",
-               (stat_flg & UDC_ISO_ERR) ? "iso_err " : "",
-               (stat_flg & UDC_ISO_FIFO_EMPTY) ? "iso_fifo_empty " : "",
-               (stat_flg & UDC_ISO_FIFO_FULL) ? "iso_fifo_full " : "",
-               (stat_flg & UDC_EP_HALTED) ? "HALT " : "",
-               (stat_flg & UDC_STALL) ? "STALL " : "",
-               (stat_flg & UDC_NAK) ? "NAK " : "",
-               (stat_flg & UDC_ACK) ? "ACK " : "",
-               (stat_flg & UDC_FIFO_EN) ? "fifo_en " : "",
-               (stat_flg & UDC_NON_ISO_FIFO_EMPTY) ? "fifo_empty " : "",
-               (stat_flg & UDC_NON_ISO_FIFO_FULL) ? "fifo_full " : "");
-
-       if (list_empty(&ep->queue))
-               seq_printf(s, "\t(queue empty)\n");
-       else
-               list_for_each_entry(req, &ep->queue, queue) {
-                       unsigned        length = req->req.actual;
-
-                       if (use_dma && buf[0]) {
-                               length += ((ep->bEndpointAddress & USB_DIR_IN)
-                                               ? dma_src_len : dma_dest_len)
-                                       (ep, req->req.dma + length);
-                               buf[0] = 0;
-                       }
-                       seq_printf(s, "\treq %p len %d/%d buf %p\n",
-                                       &req->req, length,
-                                       req->req.length, req->req.buf);
-               }
-}
-
-static char *trx_mode(unsigned m, int enabled)
-{
-       switch (m) {
-       case 0:
-               return enabled ? "*6wire" : "unused";
-       case 1:
-               return "4wire";
-       case 2:
-               return "3wire";
-       case 3:
-               return "6wire";
-       default:
-               return "unknown";
-       }
-}
-
-static int proc_otg_show(struct seq_file *s)
-{
-       u32             tmp;
-       u32             trans = 0;
-       char            *ctrl_name = "(UNKNOWN)";
-
-       tmp = omap_readl(OTG_REV);
-       ctrl_name = "tranceiver_ctrl";
-       trans = omap_readw(USB_TRANSCEIVER_CTRL);
-       seq_printf(s, "\nOTG rev %d.%d, %s %05x\n",
-               tmp >> 4, tmp & 0xf, ctrl_name, trans);
-       tmp = omap_readw(OTG_SYSCON_1);
-       seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s,"
-                       FOURBITS "\n", tmp,
-               trx_mode(USB2_TRX_MODE(tmp), trans & CONF_USB2_UNI_R),
-               trx_mode(USB1_TRX_MODE(tmp), trans & CONF_USB1_UNI_R),
-               (USB0_TRX_MODE(tmp) == 0 && !cpu_is_omap1710())
-                       ? "internal"
-                       : trx_mode(USB0_TRX_MODE(tmp), 1),
-               (tmp & OTG_IDLE_EN) ? " !otg" : "",
-               (tmp & HST_IDLE_EN) ? " !host" : "",
-               (tmp & DEV_IDLE_EN) ? " !dev" : "",
-               (tmp & OTG_RESET_DONE) ? " reset_done" : " reset_active");
-       tmp = omap_readl(OTG_SYSCON_2);
-       seq_printf(s, "otg_syscon2 %08x%s" EIGHTBITS
-                       " b_ase_brst=%d hmc=%d\n", tmp,
-               (tmp & OTG_EN) ? " otg_en" : "",
-               (tmp & USBX_SYNCHRO) ? " synchro" : "",
-               /* much more SRP stuff */
-               (tmp & SRP_DATA) ? " srp_data" : "",
-               (tmp & SRP_VBUS) ? " srp_vbus" : "",
-               (tmp & OTG_PADEN) ? " otg_paden" : "",
-               (tmp & HMC_PADEN) ? " hmc_paden" : "",
-               (tmp & UHOST_EN) ? " uhost_en" : "",
-               (tmp & HMC_TLLSPEED) ? " tllspeed" : "",
-               (tmp & HMC_TLLATTACH) ? " tllattach" : "",
-               B_ASE_BRST(tmp),
-               OTG_HMC(tmp));
-       tmp = omap_readl(OTG_CTRL);
-       seq_printf(s, "otg_ctrl    %06x" EIGHTBITS EIGHTBITS "%s\n", tmp,
-               (tmp & OTG_ASESSVLD) ? " asess" : "",
-               (tmp & OTG_BSESSEND) ? " bsess_end" : "",
-               (tmp & OTG_BSESSVLD) ? " bsess" : "",
-               (tmp & OTG_VBUSVLD) ? " vbus" : "",
-               (tmp & OTG_ID) ? " id" : "",
-               (tmp & OTG_DRIVER_SEL) ? " DEVICE" : " HOST",
-               (tmp & OTG_A_SETB_HNPEN) ? " a_setb_hnpen" : "",
-               (tmp & OTG_A_BUSREQ) ? " a_bus" : "",
-               (tmp & OTG_B_HNPEN) ? " b_hnpen" : "",
-               (tmp & OTG_B_BUSREQ) ? " b_bus" : "",
-               (tmp & OTG_BUSDROP) ? " busdrop" : "",
-               (tmp & OTG_PULLDOWN) ? " down" : "",
-               (tmp & OTG_PULLUP) ? " up" : "",
-               (tmp & OTG_DRV_VBUS) ? " drv" : "",
-               (tmp & OTG_PD_VBUS) ? " pd_vb" : "",
-               (tmp & OTG_PU_VBUS) ? " pu_vb" : "",
-               (tmp & OTG_PU_ID) ? " pu_id" : ""
-               );
-       tmp = omap_readw(OTG_IRQ_EN);
-       seq_printf(s, "otg_irq_en  %04x" "\n", tmp);
-       tmp = omap_readw(OTG_IRQ_SRC);
-       seq_printf(s, "otg_irq_src %04x" "\n", tmp);
-       tmp = omap_readw(OTG_OUTCTRL);
-       seq_printf(s, "otg_outctrl %04x" "\n", tmp);
-       tmp = omap_readw(OTG_TEST);
-       seq_printf(s, "otg_test    %04x" "\n", tmp);
-       return 0;
-}
-
-static int proc_udc_show(struct seq_file *s, void *_)
-{
-       u32             tmp;
-       struct omap_ep  *ep;
-       unsigned long   flags;
-
-       spin_lock_irqsave(&udc->lock, flags);
-
-       seq_printf(s, "%s, version: " DRIVER_VERSION
-#ifdef USE_ISO
-               " (iso)"
-#endif
-               "%s\n",
-               driver_desc,
-               use_dma ?  " (dma)" : "");
-
-       tmp = omap_readw(UDC_REV) & 0xff;
-       seq_printf(s,
-               "UDC rev %d.%d, fifo mode %d, gadget %s\n"
-               "hmc %d, transceiver %s\n",
-               tmp >> 4, tmp & 0xf,
-               fifo_mode,
-               udc->driver ? udc->driver->driver.name : "(none)",
-               HMC,
-               udc->transceiver
-                       ? udc->transceiver->label
-                       : (cpu_is_omap1710()
-                               ? "external" : "(none)"));
-       seq_printf(s, "ULPD control %04x req %04x status %04x\n",
-               omap_readw(ULPD_CLOCK_CTRL),
-               omap_readw(ULPD_SOFT_REQ),
-               omap_readw(ULPD_STATUS_REQ));
-
-       /* OTG controller registers */
-       if (!cpu_is_omap15xx())
-               proc_otg_show(s);
-
-       tmp = omap_readw(UDC_SYSCON1);
-       seq_printf(s, "\nsyscon1     %04x" EIGHTBITS "\n", tmp,
-               (tmp & UDC_CFG_LOCK) ? " cfg_lock" : "",
-               (tmp & UDC_DATA_ENDIAN) ? " data_endian" : "",
-               (tmp & UDC_DMA_ENDIAN) ? " dma_endian" : "",
-               (tmp & UDC_NAK_EN) ? " nak" : "",
-               (tmp & UDC_AUTODECODE_DIS) ? " autodecode_dis" : "",
-               (tmp & UDC_SELF_PWR) ? " self_pwr" : "",
-               (tmp & UDC_SOFF_DIS) ? " soff_dis" : "",
-               (tmp & UDC_PULLUP_EN) ? " PULLUP" : "");
-       /* syscon2 is write-only */
-
-       /* UDC controller registers */
-       if (!(tmp & UDC_PULLUP_EN)) {
-               seq_printf(s, "(suspended)\n");
-               spin_unlock_irqrestore(&udc->lock, flags);
-               return 0;
-       }
-
-       tmp = omap_readw(UDC_DEVSTAT);
-       seq_printf(s, "devstat     %04x" EIGHTBITS "%s%s\n", tmp,
-               (tmp & UDC_B_HNP_ENABLE) ? " b_hnp" : "",
-               (tmp & UDC_A_HNP_SUPPORT) ? " a_hnp" : "",
-               (tmp & UDC_A_ALT_HNP_SUPPORT) ? " a_alt_hnp" : "",
-               (tmp & UDC_R_WK_OK) ? " r_wk_ok" : "",
-               (tmp & UDC_USB_RESET) ? " usb_reset" : "",
-               (tmp & UDC_SUS) ? " SUS" : "",
-               (tmp & UDC_CFG) ? " CFG" : "",
-               (tmp & UDC_ADD) ? " ADD" : "",
-               (tmp & UDC_DEF) ? " DEF" : "",
-               (tmp & UDC_ATT) ? " ATT" : "");
-       seq_printf(s, "sof         %04x\n", omap_readw(UDC_SOF));
-       tmp = omap_readw(UDC_IRQ_EN);
-       seq_printf(s, "irq_en      %04x" FOURBITS "%s\n", tmp,
-               (tmp & UDC_SOF_IE) ? " sof" : "",
-               (tmp & UDC_EPN_RX_IE) ? " epn_rx" : "",
-               (tmp & UDC_EPN_TX_IE) ? " epn_tx" : "",
-               (tmp & UDC_DS_CHG_IE) ? " ds_chg" : "",
-               (tmp & UDC_EP0_IE) ? " ep0" : "");
-       tmp = omap_readw(UDC_IRQ_SRC);
-       seq_printf(s, "irq_src     %04x" EIGHTBITS "%s%s\n", tmp,
-               (tmp & UDC_TXN_DONE) ? " txn_done" : "",
-               (tmp & UDC_RXN_CNT) ? " rxn_cnt" : "",
-               (tmp & UDC_RXN_EOT) ? " rxn_eot" : "",
-               (tmp & UDC_IRQ_SOF) ? " sof" : "",
-               (tmp & UDC_EPN_RX) ? " epn_rx" : "",
-               (tmp & UDC_EPN_TX) ? " epn_tx" : "",
-               (tmp & UDC_DS_CHG) ? " ds_chg" : "",
-               (tmp & UDC_SETUP) ? " setup" : "",
-               (tmp & UDC_EP0_RX) ? " ep0out" : "",
-               (tmp & UDC_EP0_TX) ? " ep0in" : "");
-       if (use_dma) {
-               unsigned i;
-
-               tmp = omap_readw(UDC_DMA_IRQ_EN);
-               seq_printf(s, "dma_irq_en  %04x%s" EIGHTBITS "\n", tmp,
-                       (tmp & UDC_TX_DONE_IE(3)) ? " tx2_done" : "",
-                       (tmp & UDC_RX_CNT_IE(3)) ? " rx2_cnt" : "",
-                       (tmp & UDC_RX_EOT_IE(3)) ? " rx2_eot" : "",
-
-                       (tmp & UDC_TX_DONE_IE(2)) ? " tx1_done" : "",
-                       (tmp & UDC_RX_CNT_IE(2)) ? " rx1_cnt" : "",
-                       (tmp & UDC_RX_EOT_IE(2)) ? " rx1_eot" : "",
-
-                       (tmp & UDC_TX_DONE_IE(1)) ? " tx0_done" : "",
-                       (tmp & UDC_RX_CNT_IE(1)) ? " rx0_cnt" : "",
-                       (tmp & UDC_RX_EOT_IE(1)) ? " rx0_eot" : "");
-
-               tmp = omap_readw(UDC_RXDMA_CFG);
-               seq_printf(s, "rxdma_cfg   %04x\n", tmp);
-               if (tmp) {
-                       for (i = 0; i < 3; i++) {
-                               if ((tmp & (0x0f << (i * 4))) == 0)
-                                       continue;
-                               seq_printf(s, "rxdma[%d]    %04x\n", i,
-                                               omap_readw(UDC_RXDMA(i + 1)));
-                       }
-               }
-               tmp = omap_readw(UDC_TXDMA_CFG);
-               seq_printf(s, "txdma_cfg   %04x\n", tmp);
-               if (tmp) {
-                       for (i = 0; i < 3; i++) {
-                               if (!(tmp & (0x0f << (i * 4))))
-                                       continue;
-                               seq_printf(s, "txdma[%d]    %04x\n", i,
-                                               omap_readw(UDC_TXDMA(i + 1)));
-                       }
-               }
-       }
-
-       tmp = omap_readw(UDC_DEVSTAT);
-       if (tmp & UDC_ATT) {
-               proc_ep_show(s, &udc->ep[0]);
-               if (tmp & UDC_ADD) {
-                       list_for_each_entry(ep, &udc->gadget.ep_list,
-                                       ep.ep_list) {
-                               if (ep->ep.desc)
-                                       proc_ep_show(s, ep);
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&udc->lock, flags);
-       return 0;
-}
-
-static int proc_udc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, proc_udc_show, NULL);
-}
-
-static const struct file_operations proc_ops = {
-       .owner          = THIS_MODULE,
-       .open           = proc_udc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static void create_proc_file(void)
-{
-       proc_create(proc_filename, 0, NULL, &proc_ops);
-}
-
-static void remove_proc_file(void)
-{
-       remove_proc_entry(proc_filename, NULL);
-}
-
-#else
-
-static inline void create_proc_file(void) {}
-static inline void remove_proc_file(void) {}
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/* Before this controller can enumerate, we need to pick an endpoint
- * configuration, or "fifo_mode"  That involves allocating 2KB of packet
- * buffer space among the endpoints we'll be operating.
- *
- * NOTE: as of OMAP 1710 ES2.0, writing a new endpoint config when
- * UDC_SYSCON_1.CFG_LOCK is set can now work.  We won't use that
- * capability yet though.
- */
-static unsigned
-omap_ep_setup(char *name, u8 addr, u8 type,
-               unsigned buf, unsigned maxp, int dbuf)
-{
-       struct omap_ep  *ep;
-       u16             epn_rxtx = 0;
-
-       /* OUT endpoints first, then IN */
-       ep = &udc->ep[addr & 0xf];
-       if (addr & USB_DIR_IN)
-               ep += 16;
-
-       /* in case of ep init table bugs */
-       BUG_ON(ep->name[0]);
-
-       /* chip setup ... bit values are same for IN, OUT */
-       if (type == USB_ENDPOINT_XFER_ISOC) {
-               switch (maxp) {
-               case 8:
-                       epn_rxtx = 0 << 12;
-                       break;
-               case 16:
-                       epn_rxtx = 1 << 12;
-                       break;
-               case 32:
-                       epn_rxtx = 2 << 12;
-                       break;
-               case 64:
-                       epn_rxtx = 3 << 12;
-                       break;
-               case 128:
-                       epn_rxtx = 4 << 12;
-                       break;
-               case 256:
-                       epn_rxtx = 5 << 12;
-                       break;
-               case 512:
-                       epn_rxtx = 6 << 12;
-                       break;
-               default:
-                       BUG();
-               }
-               epn_rxtx |= UDC_EPN_RX_ISO;
-               dbuf = 1;
-       } else {
-               /* double-buffering "not supported" on 15xx,
-                * and ignored for PIO-IN on newer chips
-                * (for more reliable behavior)
-                */
-               if (!use_dma || cpu_is_omap15xx())
-                       dbuf = 0;
-
-               switch (maxp) {
-               case 8:
-                       epn_rxtx = 0 << 12;
-                       break;
-               case 16:
-                       epn_rxtx = 1 << 12;
-                       break;
-               case 32:
-                       epn_rxtx = 2 << 12;
-                       break;
-               case 64:
-                       epn_rxtx = 3 << 12;
-                       break;
-               default:
-                       BUG();
-               }
-               if (dbuf && addr)
-                       epn_rxtx |= UDC_EPN_RX_DB;
-               init_timer(&ep->timer);
-               ep->timer.function = pio_out_timer;
-               ep->timer.data = (unsigned long) ep;
-       }
-       if (addr)
-               epn_rxtx |= UDC_EPN_RX_VALID;
-       BUG_ON(buf & 0x07);
-       epn_rxtx |= buf >> 3;
-
-       DBG("%s addr %02x rxtx %04x maxp %d%s buf %d\n",
-               name, addr, epn_rxtx, maxp, dbuf ? "x2" : "", buf);
-
-       if (addr & USB_DIR_IN)
-               omap_writew(epn_rxtx, UDC_EP_TX(addr & 0xf));
-       else
-               omap_writew(epn_rxtx, UDC_EP_RX(addr));
-
-       /* next endpoint's buffer starts after this one's */
-       buf += maxp;
-       if (dbuf)
-               buf += maxp;
-       BUG_ON(buf > 2048);
-
-       /* set up driver data structures */
-       BUG_ON(strlen(name) >= sizeof ep->name);
-       strlcpy(ep->name, name, sizeof ep->name);
-       INIT_LIST_HEAD(&ep->queue);
-       INIT_LIST_HEAD(&ep->iso);
-       ep->bEndpointAddress = addr;
-       ep->bmAttributes = type;
-       ep->double_buf = dbuf;
-       ep->udc = udc;
-
-       ep->ep.name = ep->name;
-       ep->ep.ops = &omap_ep_ops;
-       ep->maxpacket = maxp;
-       usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
-       list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
-
-       return buf;
-}
-
-static void omap_udc_release(struct device *dev)
-{
-       complete(udc->done);
-       kfree(udc);
-       udc = NULL;
-}
-
-static int
-omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
-{
-       unsigned        tmp, buf;
-
-       /* abolish any previous hardware state */
-       omap_writew(0, UDC_SYSCON1);
-       omap_writew(0, UDC_IRQ_EN);
-       omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
-       omap_writew(0, UDC_DMA_IRQ_EN);
-       omap_writew(0, UDC_RXDMA_CFG);
-       omap_writew(0, UDC_TXDMA_CFG);
-
-       /* UDC_PULLUP_EN gates the chip clock */
-       /* OTG_SYSCON_1 |= DEV_IDLE_EN; */
-
-       udc = kzalloc(sizeof(*udc), GFP_KERNEL);
-       if (!udc)
-               return -ENOMEM;
-
-       spin_lock_init(&udc->lock);
-
-       udc->gadget.ops = &omap_gadget_ops;
-       udc->gadget.ep0 = &udc->ep[0].ep;
-       INIT_LIST_HEAD(&udc->gadget.ep_list);
-       INIT_LIST_HEAD(&udc->iso);
-       udc->gadget.speed = USB_SPEED_UNKNOWN;
-       udc->gadget.max_speed = USB_SPEED_FULL;
-       udc->gadget.name = driver_name;
-       udc->transceiver = xceiv;
-
-       /* ep0 is special; put it right after the SETUP buffer */
-       buf = omap_ep_setup("ep0", 0, USB_ENDPOINT_XFER_CONTROL,
-                       8 /* after SETUP */, 64 /* maxpacket */, 0);
-       list_del_init(&udc->ep[0].ep.ep_list);
-
-       /* initially disable all non-ep0 endpoints */
-       for (tmp = 1; tmp < 15; tmp++) {
-               omap_writew(0, UDC_EP_RX(tmp));
-               omap_writew(0, UDC_EP_TX(tmp));
-       }
-
-#define OMAP_BULK_EP(name, addr) \
-       buf = omap_ep_setup(name "-bulk", addr, \
-                       USB_ENDPOINT_XFER_BULK, buf, 64, 1);
-#define OMAP_INT_EP(name, addr, maxp) \
-       buf = omap_ep_setup(name "-int", addr, \
-                       USB_ENDPOINT_XFER_INT, buf, maxp, 0);
-#define OMAP_ISO_EP(name, addr, maxp) \
-       buf = omap_ep_setup(name "-iso", addr, \
-                       USB_ENDPOINT_XFER_ISOC, buf, maxp, 1);
-
-       switch (fifo_mode) {
-       case 0:
-               OMAP_BULK_EP("ep1in",  USB_DIR_IN  | 1);
-               OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2);
-               OMAP_INT_EP("ep3in",   USB_DIR_IN  | 3, 16);
-               break;
-       case 1:
-               OMAP_BULK_EP("ep1in",  USB_DIR_IN  | 1);
-               OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2);
-               OMAP_INT_EP("ep9in",   USB_DIR_IN  | 9, 16);
-
-               OMAP_BULK_EP("ep3in",  USB_DIR_IN  | 3);
-               OMAP_BULK_EP("ep4out", USB_DIR_OUT | 4);
-               OMAP_INT_EP("ep10in",  USB_DIR_IN  | 10, 16);
-
-               OMAP_BULK_EP("ep5in",  USB_DIR_IN  | 5);
-               OMAP_BULK_EP("ep5out", USB_DIR_OUT | 5);
-               OMAP_INT_EP("ep11in",  USB_DIR_IN  | 11, 16);
-
-               OMAP_BULK_EP("ep6in",  USB_DIR_IN  | 6);
-               OMAP_BULK_EP("ep6out", USB_DIR_OUT | 6);
-               OMAP_INT_EP("ep12in",  USB_DIR_IN  | 12, 16);
-
-               OMAP_BULK_EP("ep7in",  USB_DIR_IN  | 7);
-               OMAP_BULK_EP("ep7out", USB_DIR_OUT | 7);
-               OMAP_INT_EP("ep13in",  USB_DIR_IN  | 13, 16);
-               OMAP_INT_EP("ep13out", USB_DIR_OUT | 13, 16);
-
-               OMAP_BULK_EP("ep8in",  USB_DIR_IN  | 8);
-               OMAP_BULK_EP("ep8out", USB_DIR_OUT | 8);
-               OMAP_INT_EP("ep14in",  USB_DIR_IN  | 14, 16);
-               OMAP_INT_EP("ep14out", USB_DIR_OUT | 14, 16);
-
-               OMAP_BULK_EP("ep15in",  USB_DIR_IN  | 15);
-               OMAP_BULK_EP("ep15out", USB_DIR_OUT | 15);
-
-               break;
-
-#ifdef USE_ISO
-       case 2:                 /* mixed iso/bulk */
-               OMAP_ISO_EP("ep1in",   USB_DIR_IN  | 1, 256);
-               OMAP_ISO_EP("ep2out",  USB_DIR_OUT | 2, 256);
-               OMAP_ISO_EP("ep3in",   USB_DIR_IN  | 3, 128);
-               OMAP_ISO_EP("ep4out",  USB_DIR_OUT | 4, 128);
-
-               OMAP_INT_EP("ep5in",   USB_DIR_IN  | 5, 16);
-
-               OMAP_BULK_EP("ep6in",  USB_DIR_IN  | 6);
-               OMAP_BULK_EP("ep7out", USB_DIR_OUT | 7);
-               OMAP_INT_EP("ep8in",   USB_DIR_IN  | 8, 16);
-               break;
-       case 3:                 /* mixed bulk/iso */
-               OMAP_BULK_EP("ep1in",  USB_DIR_IN  | 1);
-               OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2);
-               OMAP_INT_EP("ep3in",   USB_DIR_IN  | 3, 16);
-
-               OMAP_BULK_EP("ep4in",  USB_DIR_IN  | 4);
-               OMAP_BULK_EP("ep5out", USB_DIR_OUT | 5);
-               OMAP_INT_EP("ep6in",   USB_DIR_IN  | 6, 16);
-
-               OMAP_ISO_EP("ep7in",   USB_DIR_IN  | 7, 256);
-               OMAP_ISO_EP("ep8out",  USB_DIR_OUT | 8, 256);
-               OMAP_INT_EP("ep9in",   USB_DIR_IN  | 9, 16);
-               break;
-#endif
-
-       /* add more modes as needed */
-
-       default:
-               ERR("unsupported fifo_mode #%d\n", fifo_mode);
-               return -ENODEV;
-       }
-       omap_writew(UDC_CFG_LOCK|UDC_SELF_PWR, UDC_SYSCON1);
-       INFO("fifo mode %d, %d bytes not used\n", fifo_mode, 2048 - buf);
-       return 0;
-}
-
-static int omap_udc_probe(struct platform_device *pdev)
-{
-       int                     status = -ENODEV;
-       int                     hmc;
-       struct usb_phy          *xceiv = NULL;
-       const char              *type = NULL;
-       struct omap_usb_config  *config = dev_get_platdata(&pdev->dev);
-       struct clk              *dc_clk = NULL;
-       struct clk              *hhc_clk = NULL;
-
-       if (cpu_is_omap7xx())
-               use_dma = 0;
-
-       /* NOTE:  "knows" the order of the resources! */
-       if (!request_mem_region(pdev->resource[0].start,
-                       pdev->resource[0].end - pdev->resource[0].start + 1,
-                       driver_name)) {
-               DBG("request_mem_region failed\n");
-               return -EBUSY;
-       }
-
-       if (cpu_is_omap16xx()) {
-               dc_clk = clk_get(&pdev->dev, "usb_dc_ck");
-               hhc_clk = clk_get(&pdev->dev, "usb_hhc_ck");
-               BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
-               /* can't use omap_udc_enable_clock yet */
-               clk_enable(dc_clk);
-               clk_enable(hhc_clk);
-               udelay(100);
-       }
-
-       if (cpu_is_omap7xx()) {
-               dc_clk = clk_get(&pdev->dev, "usb_dc_ck");
-               hhc_clk = clk_get(&pdev->dev, "l3_ocpi_ck");
-               BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
-               /* can't use omap_udc_enable_clock yet */
-               clk_enable(dc_clk);
-               clk_enable(hhc_clk);
-               udelay(100);
-       }
-
-       INFO("OMAP UDC rev %d.%d%s\n",
-               omap_readw(UDC_REV) >> 4, omap_readw(UDC_REV) & 0xf,
-               config->otg ? ", Mini-AB" : "");
-
-       /* use the mode given to us by board init code */
-       if (cpu_is_omap15xx()) {
-               hmc = HMC_1510;
-               type = "(unknown)";
-
-               if (machine_without_vbus_sense()) {
-                       /* just set up software VBUS detect, and then
-                        * later rig it so we always report VBUS.
-                        * FIXME without really sensing VBUS, we can't
-                        * know when to turn PULLUP_EN on/off; and that
-                        * means we always "need" the 48MHz clock.
-                        */
-                       u32 tmp = omap_readl(FUNC_MUX_CTRL_0);
-                       tmp &= ~VBUS_CTRL_1510;
-                       omap_writel(tmp, FUNC_MUX_CTRL_0);
-                       tmp |= VBUS_MODE_1510;
-                       tmp &= ~VBUS_CTRL_1510;
-                       omap_writel(tmp, FUNC_MUX_CTRL_0);
-               }
-       } else {
-               /* The transceiver may package some GPIO logic or handle
-                * loopback and/or transceiverless setup; if we find one,
-                * use it.  Except for OTG, we don't _need_ to talk to one;
-                * but not having one probably means no VBUS detection.
-                */
-               xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
-               if (!IS_ERR_OR_NULL(xceiv))
-                       type = xceiv->label;
-               else if (config->otg) {
-                       DBG("OTG requires external transceiver!\n");
-                       goto cleanup0;
-               }
-
-               hmc = HMC_1610;
-
-               switch (hmc) {
-               case 0:                 /* POWERUP DEFAULT == 0 */
-               case 4:
-               case 12:
-               case 20:
-                       if (!cpu_is_omap1710()) {
-                               type = "integrated";
-                               break;
-                       }
-                       /* FALL THROUGH */
-               case 3:
-               case 11:
-               case 16:
-               case 19:
-               case 25:
-                       if (IS_ERR_OR_NULL(xceiv)) {
-                               DBG("external transceiver not registered!\n");
-                               type = "unknown";
-                       }
-                       break;
-               case 21:                        /* internal loopback */
-                       type = "loopback";
-                       break;
-               case 14:                        /* transceiverless */
-                       if (cpu_is_omap1710())
-                               goto bad_on_1710;
-                       /* FALL THROUGH */
-               case 13:
-               case 15:
-                       type = "no";
-                       break;
-
-               default:
-bad_on_1710:
-                       ERR("unrecognized UDC HMC mode %d\n", hmc);
-                       goto cleanup0;
-               }
-       }
-
-       INFO("hmc mode %d, %s transceiver\n", hmc, type);
-
-       /* a "gadget" abstracts/virtualizes the controller */
-       status = omap_udc_setup(pdev, xceiv);
-       if (status)
-               goto cleanup0;
-
-       xceiv = NULL;
-       /* "udc" is now valid */
-       pullup_disable(udc);
-#if    defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-       udc->gadget.is_otg = (config->otg != 0);
-#endif
-
-       /* starting with omap1710 es2.0, clear toggle is a separate bit */
-       if (omap_readw(UDC_REV) >= 0x61)
-               udc->clr_halt = UDC_RESET_EP | UDC_CLRDATA_TOGGLE;
-       else
-               udc->clr_halt = UDC_RESET_EP;
-
-       /* USB general purpose IRQ:  ep0, state changes, dma, etc */
-       status = request_irq(pdev->resource[1].start, omap_udc_irq,
-                       0, driver_name, udc);
-       if (status != 0) {
-               ERR("can't get irq %d, err %d\n",
-                       (int) pdev->resource[1].start, status);
-               goto cleanup1;
-       }
-
-       /* USB "non-iso" IRQ (PIO for all but ep0) */
-       status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
-                       0, "omap_udc pio", udc);
-       if (status != 0) {
-               ERR("can't get irq %d, err %d\n",
-                       (int) pdev->resource[2].start, status);
-               goto cleanup2;
-       }
-#ifdef USE_ISO
-       status = request_irq(pdev->resource[3].start, omap_udc_iso_irq,
-                       0, "omap_udc iso", udc);
-       if (status != 0) {
-               ERR("can't get irq %d, err %d\n",
-                       (int) pdev->resource[3].start, status);
-               goto cleanup3;
-       }
-#endif
-       if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
-               udc->dc_clk = dc_clk;
-               udc->hhc_clk = hhc_clk;
-               clk_disable(hhc_clk);
-               clk_disable(dc_clk);
-       }
-
-       create_proc_file();
-       status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
-                       omap_udc_release);
-       if (status)
-               goto cleanup4;
-
-       return 0;
-
-cleanup4:
-       remove_proc_file();
-
-#ifdef USE_ISO
-cleanup3:
-       free_irq(pdev->resource[2].start, udc);
-#endif
-
-cleanup2:
-       free_irq(pdev->resource[1].start, udc);
-
-cleanup1:
-       kfree(udc);
-       udc = NULL;
-
-cleanup0:
-       if (!IS_ERR_OR_NULL(xceiv))
-               usb_put_phy(xceiv);
-
-       if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
-               clk_disable(hhc_clk);
-               clk_disable(dc_clk);
-               clk_put(hhc_clk);
-               clk_put(dc_clk);
-       }
-
-       release_mem_region(pdev->resource[0].start,
-                       pdev->resource[0].end - pdev->resource[0].start + 1);
-
-       return status;
-}
-
-static int omap_udc_remove(struct platform_device *pdev)
-{
-       DECLARE_COMPLETION_ONSTACK(done);
-
-       if (!udc)
-               return -ENODEV;
-
-       usb_del_gadget_udc(&udc->gadget);
-       if (udc->driver)
-               return -EBUSY;
-
-       udc->done = &done;
-
-       pullup_disable(udc);
-       if (!IS_ERR_OR_NULL(udc->transceiver)) {
-               usb_put_phy(udc->transceiver);
-               udc->transceiver = NULL;
-       }
-       omap_writew(0, UDC_SYSCON1);
-
-       remove_proc_file();
-
-#ifdef USE_ISO
-       free_irq(pdev->resource[3].start, udc);
-#endif
-       free_irq(pdev->resource[2].start, udc);
-       free_irq(pdev->resource[1].start, udc);
-
-       if (udc->dc_clk) {
-               if (udc->clk_requested)
-                       omap_udc_enable_clock(0);
-               clk_put(udc->hhc_clk);
-               clk_put(udc->dc_clk);
-       }
-
-       release_mem_region(pdev->resource[0].start,
-                       pdev->resource[0].end - pdev->resource[0].start + 1);
-
-       wait_for_completion(&done);
-
-       return 0;
-}
-
-/* suspend/resume/wakeup from sysfs (echo > power/state) or when the
- * system is forced into deep sleep
- *
- * REVISIT we should probably reject suspend requests when there's a host
- * session active, rather than disconnecting, at least on boards that can
- * report VBUS irqs (UDC_DEVSTAT.UDC_ATT).  And in any case, we need to
- * make host resumes and VBUS detection trigger OMAP wakeup events; that
- * may involve talking to an external transceiver (e.g. isp1301).
- */
-
-static int omap_udc_suspend(struct platform_device *dev, pm_message_t message)
-{
-       u32     devstat;
-
-       devstat = omap_readw(UDC_DEVSTAT);
-
-       /* we're requesting 48 MHz clock if the pullup is enabled
-        * (== we're attached to the host) and we're not suspended,
-        * which would prevent entry to deep sleep...
-        */
-       if ((devstat & UDC_ATT) != 0 && (devstat & UDC_SUS) == 0) {
-               WARNING("session active; suspend requires disconnect\n");
-               omap_pullup(&udc->gadget, 0);
-       }
-
-       return 0;
-}
-
-static int omap_udc_resume(struct platform_device *dev)
-{
-       DBG("resume + wakeup/SRP\n");
-       omap_pullup(&udc->gadget, 1);
-
-       /* maybe the host would enumerate us if we nudged it */
-       msleep(100);
-       return omap_wakeup(&udc->gadget);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct platform_driver udc_driver = {
-       .probe          = omap_udc_probe,
-       .remove         = omap_udc_remove,
-       .suspend        = omap_udc_suspend,
-       .resume         = omap_udc_resume,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = (char *) driver_name,
-       },
-};
-
-module_platform_driver(udc_driver);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:omap_udc");
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h
deleted file mode 100644 (file)
index cfadeb5..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * omap_udc.h -- for omap 3.2 udc, with OTG support
- *
- * 2004 (C) Texas Instruments, Inc.
- * 2004 (C) David Brownell
- */
-
-/*
- * USB device/endpoint management registers
- */
-
-#define        UDC_REV                         (UDC_BASE + 0x0)        /* Revision */
-#define        UDC_EP_NUM                      (UDC_BASE + 0x4)        /* Which endpoint */
-#      define  UDC_SETUP_SEL           (1 << 6)
-#      define  UDC_EP_SEL              (1 << 5)
-#      define  UDC_EP_DIR              (1 << 4)
-       /* low 4 bits for endpoint number */
-#define        UDC_DATA                        (UDC_BASE + 0x08)       /* Endpoint FIFO */
-#define        UDC_CTRL                        (UDC_BASE + 0x0C)       /* Endpoint control */
-#      define  UDC_CLR_HALT            (1 << 7)
-#      define  UDC_SET_HALT            (1 << 6)
-#      define  UDC_CLRDATA_TOGGLE      (1 << 3)
-#      define  UDC_SET_FIFO_EN         (1 << 2)
-#      define  UDC_CLR_EP              (1 << 1)
-#      define  UDC_RESET_EP            (1 << 0)
-#define        UDC_STAT_FLG                    (UDC_BASE + 0x10)       /* Endpoint status */
-#      define  UDC_NO_RXPACKET         (1 << 15)
-#      define  UDC_MISS_IN             (1 << 14)
-#      define  UDC_DATA_FLUSH          (1 << 13)
-#      define  UDC_ISO_ERR             (1 << 12)
-#      define  UDC_ISO_FIFO_EMPTY      (1 << 9)
-#      define  UDC_ISO_FIFO_FULL       (1 << 8)
-#      define  UDC_EP_HALTED           (1 << 6)
-#      define  UDC_STALL               (1 << 5)
-#      define  UDC_NAK                 (1 << 4)
-#      define  UDC_ACK                 (1 << 3)
-#      define  UDC_FIFO_EN             (1 << 2)
-#      define  UDC_NON_ISO_FIFO_EMPTY  (1 << 1)
-#      define  UDC_NON_ISO_FIFO_FULL   (1 << 0)
-#define        UDC_RXFSTAT                     (UDC_BASE + 0x14)       /* OUT bytecount */
-#define        UDC_SYSCON1                     (UDC_BASE + 0x18)       /* System config 1 */
-#      define  UDC_CFG_LOCK            (1 << 8)
-#      define  UDC_DATA_ENDIAN         (1 << 7)
-#      define  UDC_DMA_ENDIAN          (1 << 6)
-#      define  UDC_NAK_EN              (1 << 4)
-#      define  UDC_AUTODECODE_DIS      (1 << 3)
-#      define  UDC_SELF_PWR            (1 << 2)
-#      define  UDC_SOFF_DIS            (1 << 1)
-#      define  UDC_PULLUP_EN           (1 << 0)
-#define        UDC_SYSCON2                     (UDC_BASE + 0x1C)       /* System config 2 */
-#      define  UDC_RMT_WKP             (1 << 6)
-#      define  UDC_STALL_CMD           (1 << 5)
-#      define  UDC_DEV_CFG             (1 << 3)
-#      define  UDC_CLR_CFG             (1 << 2)
-#define        UDC_DEVSTAT                     (UDC_BASE + 0x20)       /* Device status */
-#      define  UDC_B_HNP_ENABLE        (1 << 9)
-#      define  UDC_A_HNP_SUPPORT       (1 << 8)
-#      define  UDC_A_ALT_HNP_SUPPORT   (1 << 7)
-#      define  UDC_R_WK_OK             (1 << 6)
-#      define  UDC_USB_RESET           (1 << 5)
-#      define  UDC_SUS                 (1 << 4)
-#      define  UDC_CFG                 (1 << 3)
-#      define  UDC_ADD                 (1 << 2)
-#      define  UDC_DEF                 (1 << 1)
-#      define  UDC_ATT                 (1 << 0)
-#define        UDC_SOF                         (UDC_BASE + 0x24)       /* Start of frame */
-#      define  UDC_FT_LOCK             (1 << 12)
-#      define  UDC_TS_OK               (1 << 11)
-#      define  UDC_TS                  0x03ff
-#define        UDC_IRQ_EN                      (UDC_BASE + 0x28)       /* Interrupt enable */
-#      define  UDC_SOF_IE              (1 << 7)
-#      define  UDC_EPN_RX_IE           (1 << 5)
-#      define  UDC_EPN_TX_IE           (1 << 4)
-#      define  UDC_DS_CHG_IE           (1 << 3)
-#      define  UDC_EP0_IE              (1 << 0)
-#define        UDC_DMA_IRQ_EN                  (UDC_BASE + 0x2C)       /* DMA irq enable */
-       /* rx/tx dma channels numbered 1-3 not 0-2 */
-#      define  UDC_TX_DONE_IE(n)       (1 << (4 * (n) - 2))
-#      define  UDC_RX_CNT_IE(n)        (1 << (4 * (n) - 3))
-#      define  UDC_RX_EOT_IE(n)        (1 << (4 * (n) - 4))
-#define        UDC_IRQ_SRC                     (UDC_BASE + 0x30)       /* Interrupt source */
-#      define  UDC_TXN_DONE            (1 << 10)
-#      define  UDC_RXN_CNT             (1 << 9)
-#      define  UDC_RXN_EOT             (1 << 8)
-#      define  UDC_IRQ_SOF             (1 << 7)
-#      define  UDC_EPN_RX              (1 << 5)
-#      define  UDC_EPN_TX              (1 << 4)
-#      define  UDC_DS_CHG              (1 << 3)
-#      define  UDC_SETUP               (1 << 2)
-#      define  UDC_EP0_RX              (1 << 1)
-#      define  UDC_EP0_TX              (1 << 0)
-#      define  UDC_IRQ_SRC_MASK        0x7bf
-#define        UDC_EPN_STAT                    (UDC_BASE + 0x34)       /* EP irq status */
-#define        UDC_DMAN_STAT                   (UDC_BASE + 0x38)       /* DMA irq status */
-#      define  UDC_DMA_RX_SB           (1 << 12)
-#      define  UDC_DMA_RX_SRC(x)       (((x)>>8) & 0xf)
-#      define  UDC_DMA_TX_SRC(x)       (((x)>>0) & 0xf)
-
-
-/* DMA configuration registers:  up to three channels in each direction.  */
-#define        UDC_RXDMA_CFG                   (UDC_BASE + 0x40)       /* 3 eps for RX DMA */
-#      define  UDC_DMA_REQ             (1 << 12)
-#define        UDC_TXDMA_CFG                   (UDC_BASE + 0x44)       /* 3 eps for TX DMA */
-#define        UDC_DATA_DMA                    (UDC_BASE + 0x48)       /* rx/tx fifo addr */
-
-/* rx/tx dma control, numbering channels 1-3 not 0-2 */
-#define        UDC_TXDMA(chan)                 (UDC_BASE + 0x50 - 4 + 4 * (chan))
-#      define UDC_TXN_EOT              (1 << 15)       /* bytes vs packets */
-#      define UDC_TXN_START            (1 << 14)       /* start transfer */
-#      define UDC_TXN_TSC              0x03ff          /* units in xfer */
-#define        UDC_RXDMA(chan)                 (UDC_BASE + 0x60 - 4 + 4 * (chan))
-#      define UDC_RXN_STOP             (1 << 15)       /* enable EOT irq */
-#      define UDC_RXN_TC               0x00ff          /* packets in xfer */
-
-
-/*
- * Endpoint configuration registers (used before CFG_LOCK is set)
- * UDC_EP_TX(0) is unused
- */
-#define        UDC_EP_RX(endpoint)             (UDC_BASE + 0x80 + (endpoint)*4)
-#      define  UDC_EPN_RX_VALID        (1 << 15)
-#      define  UDC_EPN_RX_DB           (1 << 14)
-       /* buffer size in bits 13, 12 */
-#      define  UDC_EPN_RX_ISO          (1 << 11)
-       /* buffer pointer in low 11 bits */
-#define        UDC_EP_TX(endpoint)             (UDC_BASE + 0xc0 + (endpoint)*4)
-       /* same bitfields as in RX */
-
-/*-------------------------------------------------------------------------*/
-
-struct omap_req {
-       struct usb_request              req;
-       struct list_head                queue;
-       unsigned                        dma_bytes;
-       unsigned                        mapped:1;
-};
-
-struct omap_ep {
-       struct usb_ep                   ep;
-       struct list_head                queue;
-       unsigned long                   irqs;
-       struct list_head                iso;
-       char                            name[14];
-       u16                             maxpacket;
-       u8                              bEndpointAddress;
-       u8                              bmAttributes;
-       unsigned                        double_buf:1;
-       unsigned                        stopped:1;
-       unsigned                        fnf:1;
-       unsigned                        has_dma:1;
-       u8                              ackwait;
-       u8                              dma_channel;
-       u16                             dma_counter;
-       int                             lch;
-       struct omap_udc                 *udc;
-       struct timer_list               timer;
-};
-
-struct omap_udc {
-       struct usb_gadget               gadget;
-       struct usb_gadget_driver        *driver;
-       spinlock_t                      lock;
-       struct omap_ep                  ep[32];
-       u16                             devstat;
-       u16                             clr_halt;
-       struct usb_phy                  *transceiver;
-       struct list_head                iso;
-       unsigned                        softconnect:1;
-       unsigned                        vbus_active:1;
-       unsigned                        ep0_pending:1;
-       unsigned                        ep0_in:1;
-       unsigned                        ep0_set_config:1;
-       unsigned                        ep0_reset_config:1;
-       unsigned                        ep0_setup:1;
-       struct completion               *done;
-       struct clk                      *dc_clk;
-       struct clk                      *hhc_clk;
-       unsigned                        clk_requested:1;
-};
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef VERBOSE
-#    define VDBG               DBG
-#else
-#    define VDBG(stuff...)     do{}while(0)
-#endif
-
-#define ERR(stuff...)          pr_err("udc: " stuff)
-#define WARNING(stuff...)      pr_warning("udc: " stuff)
-#define INFO(stuff...)         pr_info("udc: " stuff)
-#define DBG(stuff...)          pr_debug("udc: " stuff)
-
-/*-------------------------------------------------------------------------*/
-
-/* MOD_CONF_CTRL_0 */
-#define VBUS_W2FC_1510         (1 << 17)       /* 0 gpio0, 1 dvdd2 pin */
-
-/* FUNC_MUX_CTRL_0 */
-#define        VBUS_CTRL_1510          (1 << 19)       /* 1 connected (software) */
-#define        VBUS_MODE_1510          (1 << 18)       /* 0 hardware, 1 software */
-
-#define        HMC_1510        ((omap_readl(MOD_CONF_CTRL_0) >> 1) & 0x3f)
-#define        HMC_1610        (omap_readl(OTG_SYSCON_2) & 0x3f)
-#define        HMC             (cpu_is_omap15xx() ? HMC_1510 : HMC_1610)
-
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
deleted file mode 100644 (file)
index eb8c3be..0000000
+++ /dev/null
@@ -1,3248 +0,0 @@
-/*
- * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
- *
- * 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; version 2 of the License.
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-
-/* GPIO port for VBUS detecting */
-static int vbus_gpio_port = -1;                /* GPIO port number (-1:Not used) */
-
-#define PCH_VBUS_PERIOD                3000    /* VBUS polling period (msec) */
-#define PCH_VBUS_INTERVAL      10      /* VBUS polling interval (msec) */
-
-/* Address offset of Registers */
-#define UDC_EP_REG_SHIFT       0x20    /* Offset to next EP */
-
-#define UDC_EPCTL_ADDR         0x00    /* Endpoint control */
-#define UDC_EPSTS_ADDR         0x04    /* Endpoint status */
-#define UDC_BUFIN_FRAMENUM_ADDR        0x08    /* buffer size in / frame number out */
-#define UDC_BUFOUT_MAXPKT_ADDR 0x0C    /* buffer size out / maxpkt in */
-#define UDC_SUBPTR_ADDR                0x10    /* setup buffer pointer */
-#define UDC_DESPTR_ADDR                0x14    /* Data descriptor pointer */
-#define UDC_CONFIRM_ADDR       0x18    /* Write/Read confirmation */
-
-#define UDC_DEVCFG_ADDR                0x400   /* Device configuration */
-#define UDC_DEVCTL_ADDR                0x404   /* Device control */
-#define UDC_DEVSTS_ADDR                0x408   /* Device status */
-#define UDC_DEVIRQSTS_ADDR     0x40C   /* Device irq status */
-#define UDC_DEVIRQMSK_ADDR     0x410   /* Device irq mask */
-#define UDC_EPIRQSTS_ADDR      0x414   /* Endpoint irq status */
-#define UDC_EPIRQMSK_ADDR      0x418   /* Endpoint irq mask */
-#define UDC_DEVLPM_ADDR                0x41C   /* LPM control / status */
-#define UDC_CSR_BUSY_ADDR      0x4f0   /* UDC_CSR_BUSY Status register */
-#define UDC_SRST_ADDR          0x4fc   /* SOFT RESET register */
-#define UDC_CSR_ADDR           0x500   /* USB_DEVICE endpoint register */
-
-/* Endpoint control register */
-/* Bit position */
-#define UDC_EPCTL_MRXFLUSH             (1 << 12)
-#define UDC_EPCTL_RRDY                 (1 << 9)
-#define UDC_EPCTL_CNAK                 (1 << 8)
-#define UDC_EPCTL_SNAK                 (1 << 7)
-#define UDC_EPCTL_NAK                  (1 << 6)
-#define UDC_EPCTL_P                    (1 << 3)
-#define UDC_EPCTL_F                    (1 << 1)
-#define UDC_EPCTL_S                    (1 << 0)
-#define UDC_EPCTL_ET_SHIFT             4
-/* Mask patern */
-#define UDC_EPCTL_ET_MASK              0x00000030
-/* Value for ET field */
-#define UDC_EPCTL_ET_CONTROL           0
-#define UDC_EPCTL_ET_ISO               1
-#define UDC_EPCTL_ET_BULK              2
-#define UDC_EPCTL_ET_INTERRUPT         3
-
-/* Endpoint status register */
-/* Bit position */
-#define UDC_EPSTS_XFERDONE             (1 << 27)
-#define UDC_EPSTS_RSS                  (1 << 26)
-#define UDC_EPSTS_RCS                  (1 << 25)
-#define UDC_EPSTS_TXEMPTY              (1 << 24)
-#define UDC_EPSTS_TDC                  (1 << 10)
-#define UDC_EPSTS_HE                   (1 << 9)
-#define UDC_EPSTS_MRXFIFO_EMP          (1 << 8)
-#define UDC_EPSTS_BNA                  (1 << 7)
-#define UDC_EPSTS_IN                   (1 << 6)
-#define UDC_EPSTS_OUT_SHIFT            4
-/* Mask patern */
-#define UDC_EPSTS_OUT_MASK             0x00000030
-#define UDC_EPSTS_ALL_CLR_MASK         0x1F0006F0
-/* Value for OUT field */
-#define UDC_EPSTS_OUT_SETUP            2
-#define UDC_EPSTS_OUT_DATA             1
-
-/* Device configuration register */
-/* Bit position */
-#define UDC_DEVCFG_CSR_PRG             (1 << 17)
-#define UDC_DEVCFG_SP                  (1 << 3)
-/* SPD Valee */
-#define UDC_DEVCFG_SPD_HS              0x0
-#define UDC_DEVCFG_SPD_FS              0x1
-#define UDC_DEVCFG_SPD_LS              0x2
-
-/* Device control register */
-/* Bit position */
-#define UDC_DEVCTL_THLEN_SHIFT         24
-#define UDC_DEVCTL_BRLEN_SHIFT         16
-#define UDC_DEVCTL_CSR_DONE            (1 << 13)
-#define UDC_DEVCTL_SD                  (1 << 10)
-#define UDC_DEVCTL_MODE                        (1 << 9)
-#define UDC_DEVCTL_BREN                        (1 << 8)
-#define UDC_DEVCTL_THE                 (1 << 7)
-#define UDC_DEVCTL_DU                  (1 << 4)
-#define UDC_DEVCTL_TDE                 (1 << 3)
-#define UDC_DEVCTL_RDE                 (1 << 2)
-#define UDC_DEVCTL_RES                 (1 << 0)
-
-/* Device status register */
-/* Bit position */
-#define UDC_DEVSTS_TS_SHIFT            18
-#define UDC_DEVSTS_ENUM_SPEED_SHIFT    13
-#define UDC_DEVSTS_ALT_SHIFT           8
-#define UDC_DEVSTS_INTF_SHIFT          4
-#define UDC_DEVSTS_CFG_SHIFT           0
-/* Mask patern */
-#define UDC_DEVSTS_TS_MASK             0xfffc0000
-#define UDC_DEVSTS_ENUM_SPEED_MASK     0x00006000
-#define UDC_DEVSTS_ALT_MASK            0x00000f00
-#define UDC_DEVSTS_INTF_MASK           0x000000f0
-#define UDC_DEVSTS_CFG_MASK            0x0000000f
-/* value for maximum speed for SPEED field */
-#define UDC_DEVSTS_ENUM_SPEED_FULL     1
-#define UDC_DEVSTS_ENUM_SPEED_HIGH     0
-#define UDC_DEVSTS_ENUM_SPEED_LOW      2
-#define UDC_DEVSTS_ENUM_SPEED_FULLX    3
-
-/* Device irq register */
-/* Bit position */
-#define UDC_DEVINT_RWKP                        (1 << 7)
-#define UDC_DEVINT_ENUM                        (1 << 6)
-#define UDC_DEVINT_SOF                 (1 << 5)
-#define UDC_DEVINT_US                  (1 << 4)
-#define UDC_DEVINT_UR                  (1 << 3)
-#define UDC_DEVINT_ES                  (1 << 2)
-#define UDC_DEVINT_SI                  (1 << 1)
-#define UDC_DEVINT_SC                  (1 << 0)
-/* Mask patern */
-#define UDC_DEVINT_MSK                 0x7f
-
-/* Endpoint irq register */
-/* Bit position */
-#define UDC_EPINT_IN_SHIFT             0
-#define UDC_EPINT_OUT_SHIFT            16
-#define UDC_EPINT_IN_EP0               (1 << 0)
-#define UDC_EPINT_OUT_EP0              (1 << 16)
-/* Mask patern */
-#define UDC_EPINT_MSK_DISABLE_ALL      0xffffffff
-
-/* UDC_CSR_BUSY Status register */
-/* Bit position */
-#define UDC_CSR_BUSY                   (1 << 0)
-
-/* SOFT RESET register */
-/* Bit position */
-#define UDC_PSRST                      (1 << 1)
-#define UDC_SRST                       (1 << 0)
-
-/* USB_DEVICE endpoint register */
-/* Bit position */
-#define UDC_CSR_NE_NUM_SHIFT           0
-#define UDC_CSR_NE_DIR_SHIFT           4
-#define UDC_CSR_NE_TYPE_SHIFT          5
-#define UDC_CSR_NE_CFG_SHIFT           7
-#define UDC_CSR_NE_INTF_SHIFT          11
-#define UDC_CSR_NE_ALT_SHIFT           15
-#define UDC_CSR_NE_MAX_PKT_SHIFT       19
-/* Mask patern */
-#define UDC_CSR_NE_NUM_MASK            0x0000000f
-#define UDC_CSR_NE_DIR_MASK            0x00000010
-#define UDC_CSR_NE_TYPE_MASK           0x00000060
-#define UDC_CSR_NE_CFG_MASK            0x00000780
-#define UDC_CSR_NE_INTF_MASK           0x00007800
-#define UDC_CSR_NE_ALT_MASK            0x00078000
-#define UDC_CSR_NE_MAX_PKT_MASK                0x3ff80000
-
-#define PCH_UDC_CSR(ep)        (UDC_CSR_ADDR + ep*4)
-#define PCH_UDC_EPINT(in, num)\
-               (1 << (num + (in ? UDC_EPINT_IN_SHIFT : UDC_EPINT_OUT_SHIFT)))
-
-/* Index of endpoint */
-#define UDC_EP0IN_IDX          0
-#define UDC_EP0OUT_IDX         1
-#define UDC_EPIN_IDX(ep)       (ep * 2)
-#define UDC_EPOUT_IDX(ep)      (ep * 2 + 1)
-#define PCH_UDC_EP0            0
-#define PCH_UDC_EP1            1
-#define PCH_UDC_EP2            2
-#define PCH_UDC_EP3            3
-
-/* Number of endpoint */
-#define PCH_UDC_EP_NUM         32      /* Total number of EPs (16 IN,16 OUT) */
-#define PCH_UDC_USED_EP_NUM    4       /* EP number of EP's really used */
-/* Length Value */
-#define PCH_UDC_BRLEN          0x0F    /* Burst length */
-#define PCH_UDC_THLEN          0x1F    /* Threshold length */
-/* Value of EP Buffer Size */
-#define UDC_EP0IN_BUFF_SIZE    16
-#define UDC_EPIN_BUFF_SIZE     256
-#define UDC_EP0OUT_BUFF_SIZE   16
-#define UDC_EPOUT_BUFF_SIZE    256
-/* Value of EP maximum packet size */
-#define UDC_EP0IN_MAX_PKT_SIZE 64
-#define UDC_EP0OUT_MAX_PKT_SIZE        64
-#define UDC_BULK_MAX_PKT_SIZE  512
-
-/* DMA */
-#define DMA_DIR_RX             1       /* DMA for data receive */
-#define DMA_DIR_TX             2       /* DMA for data transmit */
-#define DMA_ADDR_INVALID       (~(dma_addr_t)0)
-#define UDC_DMA_MAXPACKET      65536   /* maximum packet size for DMA */
-
-/**
- * struct pch_udc_data_dma_desc - Structure to hold DMA descriptor information
- *                               for data
- * @status:            Status quadlet
- * @reserved:          Reserved
- * @dataptr:           Buffer descriptor
- * @next:              Next descriptor
- */
-struct pch_udc_data_dma_desc {
-       u32 status;
-       u32 reserved;
-       u32 dataptr;
-       u32 next;
-};
-
-/**
- * struct pch_udc_stp_dma_desc - Structure to hold DMA descriptor information
- *                              for control data
- * @status:    Status
- * @reserved:  Reserved
- * @data12:    First setup word
- * @data34:    Second setup word
- */
-struct pch_udc_stp_dma_desc {
-       u32 status;
-       u32 reserved;
-       struct usb_ctrlrequest request;
-} __attribute((packed));
-
-/* DMA status definitions */
-/* Buffer status */
-#define PCH_UDC_BUFF_STS       0xC0000000
-#define PCH_UDC_BS_HST_RDY     0x00000000
-#define PCH_UDC_BS_DMA_BSY     0x40000000
-#define PCH_UDC_BS_DMA_DONE    0x80000000
-#define PCH_UDC_BS_HST_BSY     0xC0000000
-/*  Rx/Tx Status */
-#define PCH_UDC_RXTX_STS       0x30000000
-#define PCH_UDC_RTS_SUCC       0x00000000
-#define PCH_UDC_RTS_DESERR     0x10000000
-#define PCH_UDC_RTS_BUFERR     0x30000000
-/* Last Descriptor Indication */
-#define PCH_UDC_DMA_LAST       0x08000000
-/* Number of Rx/Tx Bytes Mask */
-#define PCH_UDC_RXTX_BYTES     0x0000ffff
-
-/**
- * struct pch_udc_cfg_data - Structure to hold current configuration
- *                          and interface information
- * @cur_cfg:   current configuration in use
- * @cur_intf:  current interface in use
- * @cur_alt:   current alt interface in use
- */
-struct pch_udc_cfg_data {
-       u16 cur_cfg;
-       u16 cur_intf;
-       u16 cur_alt;
-};
-
-/**
- * struct pch_udc_ep - Structure holding a PCH USB device Endpoint information
- * @ep:                        embedded ep request
- * @td_stp_phys:       for setup request
- * @td_data_phys:      for data request
- * @td_stp:            for setup request
- * @td_data:           for data request
- * @dev:               reference to device struct
- * @offset_addr:       offset address of ep register
- * @desc:              for this ep
- * @queue:             queue for requests
- * @num:               endpoint number
- * @in:                        endpoint is IN
- * @halted:            endpoint halted?
- * @epsts:             Endpoint status
- */
-struct pch_udc_ep {
-       struct usb_ep                   ep;
-       dma_addr_t                      td_stp_phys;
-       dma_addr_t                      td_data_phys;
-       struct pch_udc_stp_dma_desc     *td_stp;
-       struct pch_udc_data_dma_desc    *td_data;
-       struct pch_udc_dev              *dev;
-       unsigned long                   offset_addr;
-       struct list_head                queue;
-       unsigned                        num:5,
-                                       in:1,
-                                       halted:1;
-       unsigned long                   epsts;
-};
-
-/**
- * struct pch_vbus_gpio_data - Structure holding GPIO informaton
- *                                     for detecting VBUS
- * @port:              gpio port number
- * @intr:              gpio interrupt number
- * @irq_work_fall      Structure for WorkQueue
- * @irq_work_rise      Structure for WorkQueue
- */
-struct pch_vbus_gpio_data {
-       int                     port;
-       int                     intr;
-       struct work_struct      irq_work_fall;
-       struct work_struct      irq_work_rise;
-};
-
-/**
- * struct pch_udc_dev - Structure holding complete information
- *                     of the PCH USB device
- * @gadget:            gadget driver data
- * @driver:            reference to gadget driver bound
- * @pdev:              reference to the PCI device
- * @ep:                        array of endpoints
- * @lock:              protects all state
- * @active:            enabled the PCI device
- * @stall:             stall requested
- * @prot_stall:                protcol stall requested
- * @irq_registered:    irq registered with system
- * @mem_region:                device memory mapped
- * @registered:                driver regsitered with system
- * @suspended:         driver in suspended state
- * @connected:         gadget driver associated
- * @vbus_session:      required vbus_session state
- * @set_cfg_not_acked: pending acknowledgement 4 setup
- * @waiting_zlp_ack:   pending acknowledgement 4 ZLP
- * @data_requests:     DMA pool for data requests
- * @stp_requests:      DMA pool for setup requests
- * @dma_addr:          DMA pool for received
- * @ep0out_buf:                Buffer for DMA
- * @setup_data:                Received setup data
- * @phys_addr:         of device memory
- * @base_addr:         for mapped device memory
- * @irq:               IRQ line for the device
- * @cfg_data:          current cfg, intf, and alt in use
- * @vbus_gpio:         GPIO informaton for detecting VBUS
- */
-struct pch_udc_dev {
-       struct usb_gadget               gadget;
-       struct usb_gadget_driver        *driver;
-       struct pci_dev                  *pdev;
-       struct pch_udc_ep               ep[PCH_UDC_EP_NUM];
-       spinlock_t                      lock; /* protects all state */
-       unsigned        active:1,
-                       stall:1,
-                       prot_stall:1,
-                       irq_registered:1,
-                       mem_region:1,
-                       suspended:1,
-                       connected:1,
-                       vbus_session:1,
-                       set_cfg_not_acked:1,
-                       waiting_zlp_ack:1;
-       struct pci_pool         *data_requests;
-       struct pci_pool         *stp_requests;
-       dma_addr_t                      dma_addr;
-       void                            *ep0out_buf;
-       struct usb_ctrlrequest          setup_data;
-       unsigned long                   phys_addr;
-       void __iomem                    *base_addr;
-       unsigned                        irq;
-       struct pch_udc_cfg_data         cfg_data;
-       struct pch_vbus_gpio_data       vbus_gpio;
-};
-#define to_pch_udc(g)  (container_of((g), struct pch_udc_dev, gadget))
-
-#define PCH_UDC_PCI_BAR                        1
-#define PCI_DEVICE_ID_INTEL_EG20T_UDC  0x8808
-#define PCI_VENDOR_ID_ROHM             0x10DB
-#define PCI_DEVICE_ID_ML7213_IOH_UDC   0x801D
-#define PCI_DEVICE_ID_ML7831_IOH_UDC   0x8808
-
-static const char      ep0_string[] = "ep0in";
-static DEFINE_SPINLOCK(udc_stall_spinlock);    /* stall spin lock */
-static bool speed_fs;
-module_param_named(speed_fs, speed_fs, bool, S_IRUGO);
-MODULE_PARM_DESC(speed_fs, "true for Full speed operation");
-
-/**
- * struct pch_udc_request - Structure holding a PCH USB device request packet
- * @req:               embedded ep request
- * @td_data_phys:      phys. address
- * @td_data:           first dma desc. of chain
- * @td_data_last:      last dma desc. of chain
- * @queue:             associated queue
- * @dma_going:         DMA in progress for request
- * @dma_mapped:                DMA memory mapped for request
- * @dma_done:          DMA completed for request
- * @chain_len:         chain length
- * @buf:               Buffer memory for align adjustment
- * @dma:               DMA memory for align adjustment
- */
-struct pch_udc_request {
-       struct usb_request              req;
-       dma_addr_t                      td_data_phys;
-       struct pch_udc_data_dma_desc    *td_data;
-       struct pch_udc_data_dma_desc    *td_data_last;
-       struct list_head                queue;
-       unsigned                        dma_going:1,
-                                       dma_mapped:1,
-                                       dma_done:1;
-       unsigned                        chain_len;
-       void                            *buf;
-       dma_addr_t                      dma;
-};
-
-static inline u32 pch_udc_readl(struct pch_udc_dev *dev, unsigned long reg)
-{
-       return ioread32(dev->base_addr + reg);
-}
-
-static inline void pch_udc_writel(struct pch_udc_dev *dev,
-                                   unsigned long val, unsigned long reg)
-{
-       iowrite32(val, dev->base_addr + reg);
-}
-
-static inline void pch_udc_bit_set(struct pch_udc_dev *dev,
-                                    unsigned long reg,
-                                    unsigned long bitmask)
-{
-       pch_udc_writel(dev, pch_udc_readl(dev, reg) | bitmask, reg);
-}
-
-static inline void pch_udc_bit_clr(struct pch_udc_dev *dev,
-                                    unsigned long reg,
-                                    unsigned long bitmask)
-{
-       pch_udc_writel(dev, pch_udc_readl(dev, reg) & ~(bitmask), reg);
-}
-
-static inline u32 pch_udc_ep_readl(struct pch_udc_ep *ep, unsigned long reg)
-{
-       return ioread32(ep->dev->base_addr + ep->offset_addr + reg);
-}
-
-static inline void pch_udc_ep_writel(struct pch_udc_ep *ep,
-                                   unsigned long val, unsigned long reg)
-{
-       iowrite32(val, ep->dev->base_addr + ep->offset_addr + reg);
-}
-
-static inline void pch_udc_ep_bit_set(struct pch_udc_ep *ep,
-                                    unsigned long reg,
-                                    unsigned long bitmask)
-{
-       pch_udc_ep_writel(ep, pch_udc_ep_readl(ep, reg) | bitmask, reg);
-}
-
-static inline void pch_udc_ep_bit_clr(struct pch_udc_ep *ep,
-                                    unsigned long reg,
-                                    unsigned long bitmask)
-{
-       pch_udc_ep_writel(ep, pch_udc_ep_readl(ep, reg) & ~(bitmask), reg);
-}
-
-/**
- * pch_udc_csr_busy() - Wait till idle.
- * @dev:       Reference to pch_udc_dev structure
- */
-static void pch_udc_csr_busy(struct pch_udc_dev *dev)
-{
-       unsigned int count = 200;
-
-       /* Wait till idle */
-       while ((pch_udc_readl(dev, UDC_CSR_BUSY_ADDR) & UDC_CSR_BUSY)
-               && --count)
-               cpu_relax();
-       if (!count)
-               dev_err(&dev->pdev->dev, "%s: wait error\n", __func__);
-}
-
-/**
- * pch_udc_write_csr() - Write the command and status registers.
- * @dev:       Reference to pch_udc_dev structure
- * @val:       value to be written to CSR register
- * @addr:      address of CSR register
- */
-static void pch_udc_write_csr(struct pch_udc_dev *dev, unsigned long val,
-                              unsigned int ep)
-{
-       unsigned long reg = PCH_UDC_CSR(ep);
-
-       pch_udc_csr_busy(dev);          /* Wait till idle */
-       pch_udc_writel(dev, val, reg);
-       pch_udc_csr_busy(dev);          /* Wait till idle */
-}
-
-/**
- * pch_udc_read_csr() - Read the command and status registers.
- * @dev:       Reference to pch_udc_dev structure
- * @addr:      address of CSR register
- *
- * Return codes:       content of CSR register
- */
-static u32 pch_udc_read_csr(struct pch_udc_dev *dev, unsigned int ep)
-{
-       unsigned long reg = PCH_UDC_CSR(ep);
-
-       pch_udc_csr_busy(dev);          /* Wait till idle */
-       pch_udc_readl(dev, reg);        /* Dummy read */
-       pch_udc_csr_busy(dev);          /* Wait till idle */
-       return pch_udc_readl(dev, reg);
-}
-
-/**
- * pch_udc_rmt_wakeup() - Initiate for remote wakeup
- * @dev:       Reference to pch_udc_dev structure
- */
-static inline void pch_udc_rmt_wakeup(struct pch_udc_dev *dev)
-{
-       pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
-       mdelay(1);
-       pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
-}
-
-/**
- * pch_udc_get_frame() - Get the current frame from device status register
- * @dev:       Reference to pch_udc_dev structure
- * Retern      current frame
- */
-static inline int pch_udc_get_frame(struct pch_udc_dev *dev)
-{
-       u32 frame = pch_udc_readl(dev, UDC_DEVSTS_ADDR);
-       return (frame & UDC_DEVSTS_TS_MASK) >> UDC_DEVSTS_TS_SHIFT;
-}
-
-/**
- * pch_udc_clear_selfpowered() - Clear the self power control
- * @dev:       Reference to pch_udc_regs structure
- */
-static inline void pch_udc_clear_selfpowered(struct pch_udc_dev *dev)
-{
-       pch_udc_bit_clr(dev, UDC_DEVCFG_ADDR, UDC_DEVCFG_SP);
-}
-
-/**
- * pch_udc_set_selfpowered() - Set the self power control
- * @dev:       Reference to pch_udc_regs structure
- */
-static inline void pch_udc_set_selfpowered(struct pch_udc_dev *dev)
-{
-       pch_udc_bit_set(dev, UDC_DEVCFG_ADDR, UDC_DEVCFG_SP);
-}
-
-/**
- * pch_udc_set_disconnect() - Set the disconnect status.
- * @dev:       Reference to pch_udc_regs structure
- */
-static inline void pch_udc_set_disconnect(struct pch_udc_dev *dev)
-{
-       pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD);
-}
-
-/**
- * pch_udc_clear_disconnect() - Clear the disconnect status.
- * @dev:       Reference to pch_udc_regs structure
- */
-static void pch_udc_clear_disconnect(struct pch_udc_dev *dev)
-{
-       /* Clear the disconnect */
-       pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
-       pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD);
-       mdelay(1);
-       /* Resume USB signalling */
-       pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
-}
-
-/**
- * pch_udc_reconnect() - This API initializes usb device controller,
- *                                             and clear the disconnect status.
- * @dev:               Reference to pch_udc_regs structure
- */
-static void pch_udc_init(struct pch_udc_dev *dev);
-static void pch_udc_reconnect(struct pch_udc_dev *dev)
-{
-       pch_udc_init(dev);
-
-       /* enable device interrupts */
-       /* pch_udc_enable_interrupts() */
-       pch_udc_bit_clr(dev, UDC_DEVIRQMSK_ADDR,
-                       UDC_DEVINT_UR | UDC_DEVINT_ENUM);
-
-       /* Clear the disconnect */
-       pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
-       pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD);
-       mdelay(1);
-       /* Resume USB signalling */
-       pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
-}
-
-/**
- * pch_udc_vbus_session() - set or clearr the disconnect status.
- * @dev:       Reference to pch_udc_regs structure
- * @is_active: Parameter specifying the action
- *               0:   indicating VBUS power is ending
- *               !0:  indicating VBUS power is starting
- */
-static inline void pch_udc_vbus_session(struct pch_udc_dev *dev,
-                                         int is_active)
-{
-       if (is_active) {
-               pch_udc_reconnect(dev);
-               dev->vbus_session = 1;
-       } else {
-               if (dev->driver && dev->driver->disconnect) {
-                       spin_unlock(&dev->lock);
-                       dev->driver->disconnect(&dev->gadget);
-                       spin_lock(&dev->lock);
-               }
-               pch_udc_set_disconnect(dev);
-               dev->vbus_session = 0;
-       }
-}
-
-/**
- * pch_udc_ep_set_stall() - Set the stall of endpoint
- * @ep:                Reference to structure of type pch_udc_ep_regs
- */
-static void pch_udc_ep_set_stall(struct pch_udc_ep *ep)
-{
-       if (ep->in) {
-               pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_F);
-               pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_S);
-       } else {
-               pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_S);
-       }
-}
-
-/**
- * pch_udc_ep_clear_stall() - Clear the stall of endpoint
- * @ep:                Reference to structure of type pch_udc_ep_regs
- */
-static inline void pch_udc_ep_clear_stall(struct pch_udc_ep *ep)
-{
-       /* Clear the stall */
-       pch_udc_ep_bit_clr(ep, UDC_EPCTL_ADDR, UDC_EPCTL_S);
-       /* Clear NAK by writing CNAK */
-       pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_CNAK);
-}
-
-/**
- * pch_udc_ep_set_trfr_type() - Set the transfer type of endpoint
- * @ep:                Reference to structure of type pch_udc_ep_regs
- * @type:      Type of endpoint
- */
-static inline void pch_udc_ep_set_trfr_type(struct pch_udc_ep *ep,
-                                       u8 type)
-{
-       pch_udc_ep_writel(ep, ((type << UDC_EPCTL_ET_SHIFT) &
-                               UDC_EPCTL_ET_MASK), UDC_EPCTL_ADDR);
-}
-
-/**
- * pch_udc_ep_set_bufsz() - Set the maximum packet size for the endpoint
- * @ep:                Reference to structure of type pch_udc_ep_regs
- * @buf_size:  The buffer word size
- */
-static void pch_udc_ep_set_bufsz(struct pch_udc_ep *ep,
-                                                u32 buf_size, u32 ep_in)
-{
-       u32 data;
-       if (ep_in) {
-               data = pch_udc_ep_readl(ep, UDC_BUFIN_FRAMENUM_ADDR);
-               data = (data & 0xffff0000) | (buf_size & 0xffff);
-               pch_udc_ep_writel(ep, data, UDC_BUFIN_FRAMENUM_ADDR);
-       } else {
-               data = pch_udc_ep_readl(ep, UDC_BUFOUT_MAXPKT_ADDR);
-               data = (buf_size << 16) | (data & 0xffff);
-               pch_udc_ep_writel(ep, data, UDC_BUFOUT_MAXPKT_ADDR);
-       }
-}
-
-/**
- * pch_udc_ep_set_maxpkt() - Set the Max packet size for the endpoint
- * @ep:                Reference to structure of type pch_udc_ep_regs
- * @pkt_size:  The packet byte size
- */
-static void pch_udc_ep_set_maxpkt(struct pch_udc_ep *ep, u32 pkt_size)
-{
-       u32 data = pch_udc_ep_readl(ep, UDC_BUFOUT_MAXPKT_ADDR);
-       data = (data & 0xffff0000) | (pkt_size & 0xffff);
-       pch_udc_ep_writel(ep, data, UDC_BUFOUT_MAXPKT_ADDR);
-}
-
-/**
- * pch_udc_ep_set_subptr() - Set the Setup buffer pointer for the endpoint
- * @ep:                Reference to structure of type pch_udc_ep_regs
- * @addr:      Address of the register
- */
-static inline void pch_udc_ep_set_subptr(struct pch_udc_ep *ep, u32 addr)
-{
-       pch_udc_ep_writel(ep, addr, UDC_SUBPTR_ADDR);
-}
-
-/**
- * pch_udc_ep_set_ddptr() - Set the Data descriptor pointer for the endpoint
- * @ep:                Reference to structure of type pch_udc_ep_regs
- * @addr:      Address of the register
- */
-static inline void pch_udc_ep_set_ddptr(struct pch_udc_ep *ep, u32 addr)
-{
-       pch_udc_ep_writel(ep, addr, UDC_DESPTR_ADDR);
-}
-
-/**
- * pch_udc_ep_set_pd() - Set the poll demand bit for the endpoint
- * @ep:                Reference to structure of type pch_udc_ep_regs
- */
-static inline void pch_udc_ep_set_pd(struct pch_udc_ep *ep)
-{
-       pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_P);
-}
-
-/**
- * pch_udc_ep_set_rrdy() - Set the receive ready bit for the endpoint
- * @ep:                Reference to structure of type pch_udc_ep_regs
- */
-static inline void pch_udc_ep_set_rrdy(struct pch_udc_ep *ep)
-{
-       pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_RRDY);
-}
-
-/**
- * pch_udc_ep_clear_rrdy() - Clear the receive ready bit for the endpoint
- * @ep:                Reference to structure of type pch_udc_ep_regs
- */
-static inline void pch_udc_ep_clear_rrdy(struct pch_udc_ep *ep)
-{
-       pch_udc_ep_bit_clr(ep, UDC_EPCTL_ADDR, UDC_EPCTL_RRDY);
-}
-
-/**
- * pch_udc_set_dma() - Set the 'TDE' or RDE bit of device control
- *                     register depending on the direction specified
- * @dev:       Reference to structure of type pch_udc_regs
- * @dir:       whether Tx or Rx
- *               DMA_DIR_RX: Receive
- *               DMA_DIR_TX: Transmit
- */
-static inline void pch_udc_set_dma(struct pch_udc_dev *dev, int dir)
-{
-       if (dir == DMA_DIR_RX)
-               pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RDE);
-       else if (dir == DMA_DIR_TX)
-               pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_TDE);
-}
-
-/**
- * pch_udc_clear_dma() - Clear the 'TDE' or RDE bit of device control
- *                              register depending on the direction specified
- * @dev:       Reference to structure of type pch_udc_regs
- * @dir:       Whether Tx or Rx
- *               DMA_DIR_RX: Receive
- *               DMA_DIR_TX: Transmit
- */
-static inline void pch_udc_clear_dma(struct pch_udc_dev *dev, int dir)
-{
-       if (dir == DMA_DIR_RX)
-               pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RDE);
-       else if (dir == DMA_DIR_TX)
-               pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_TDE);
-}
-
-/**
- * pch_udc_set_csr_done() - Set the device control register
- *                             CSR done field (bit 13)
- * @dev:       reference to structure of type pch_udc_regs
- */
-static inline void pch_udc_set_csr_done(struct pch_udc_dev *dev)
-{
-       pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_CSR_DONE);
-}
-
-/**
- * pch_udc_disable_interrupts() - Disables the specified interrupts
- * @dev:       Reference to structure of type pch_udc_regs
- * @mask:      Mask to disable interrupts
- */
-static inline void pch_udc_disable_interrupts(struct pch_udc_dev *dev,
-                                           u32 mask)
-{
-       pch_udc_bit_set(dev, UDC_DEVIRQMSK_ADDR, mask);
-}
-
-/**
- * pch_udc_enable_interrupts() - Enable the specified interrupts
- * @dev:       Reference to structure of type pch_udc_regs
- * @mask:      Mask to enable interrupts
- */
-static inline void pch_udc_enable_interrupts(struct pch_udc_dev *dev,
-                                          u32 mask)
-{
-       pch_udc_bit_clr(dev, UDC_DEVIRQMSK_ADDR, mask);
-}
-
-/**
- * pch_udc_disable_ep_interrupts() - Disable endpoint interrupts
- * @dev:       Reference to structure of type pch_udc_regs
- * @mask:      Mask to disable interrupts
- */
-static inline void pch_udc_disable_ep_interrupts(struct pch_udc_dev *dev,
-                                               u32 mask)
-{
-       pch_udc_bit_set(dev, UDC_EPIRQMSK_ADDR, mask);
-}
-
-/**
- * pch_udc_enable_ep_interrupts() - Enable endpoint interrupts
- * @dev:       Reference to structure of type pch_udc_regs
- * @mask:      Mask to enable interrupts
- */
-static inline void pch_udc_enable_ep_interrupts(struct pch_udc_dev *dev,
-                                             u32 mask)
-{
-       pch_udc_bit_clr(dev, UDC_EPIRQMSK_ADDR, mask);
-}
-
-/**
- * pch_udc_read_device_interrupts() - Read the device interrupts
- * @dev:       Reference to structure of type pch_udc_regs
- * Retern      The device interrupts
- */
-static inline u32 pch_udc_read_device_interrupts(struct pch_udc_dev *dev)
-{
-       return pch_udc_readl(dev, UDC_DEVIRQSTS_ADDR);
-}
-
-/**
- * pch_udc_write_device_interrupts() - Write device interrupts
- * @dev:       Reference to structure of type pch_udc_regs
- * @val:       The value to be written to interrupt register
- */
-static inline void pch_udc_write_device_interrupts(struct pch_udc_dev *dev,
-                                                    u32 val)
-{
-       pch_udc_writel(dev, val, UDC_DEVIRQSTS_ADDR);
-}
-
-/**
- * pch_udc_read_ep_interrupts() - Read the endpoint interrupts
- * @dev:       Reference to structure of type pch_udc_regs
- * Retern      The endpoint interrupt
- */
-static inline u32 pch_udc_read_ep_interrupts(struct pch_udc_dev *dev)
-{
-       return pch_udc_readl(dev, UDC_EPIRQSTS_ADDR);
-}
-
-/**
- * pch_udc_write_ep_interrupts() - Clear endpoint interupts
- * @dev:       Reference to structure of type pch_udc_regs
- * @val:       The value to be written to interrupt register
- */
-static inline void pch_udc_write_ep_interrupts(struct pch_udc_dev *dev,
-                                            u32 val)
-{
-       pch_udc_writel(dev, val, UDC_EPIRQSTS_ADDR);
-}
-
-/**
- * pch_udc_read_device_status() - Read the device status
- * @dev:       Reference to structure of type pch_udc_regs
- * Retern      The device status
- */
-static inline u32 pch_udc_read_device_status(struct pch_udc_dev *dev)
-{
-       return pch_udc_readl(dev, UDC_DEVSTS_ADDR);
-}
-
-/**
- * pch_udc_read_ep_control() - Read the endpoint control
- * @ep:                Reference to structure of type pch_udc_ep_regs
- * Retern      The endpoint control register value
- */
-static inline u32 pch_udc_read_ep_control(struct pch_udc_ep *ep)
-{
-       return pch_udc_ep_readl(ep, UDC_EPCTL_ADDR);
-}
-
-/**
- * pch_udc_clear_ep_control() - Clear the endpoint control register
- * @ep:                Reference to structure of type pch_udc_ep_regs
- * Retern      The endpoint control register value
- */
-static inline void pch_udc_clear_ep_control(struct pch_udc_ep *ep)
-{
-       return pch_udc_ep_writel(ep, 0, UDC_EPCTL_ADDR);
-}
-
-/**
- * pch_udc_read_ep_status() - Read the endpoint status
- * @ep:                Reference to structure of type pch_udc_ep_regs
- * Retern      The endpoint status
- */
-static inline u32 pch_udc_read_ep_status(struct pch_udc_ep *ep)
-{
-       return pch_udc_ep_readl(ep, UDC_EPSTS_ADDR);
-}
-
-/**
- * pch_udc_clear_ep_status() - Clear the endpoint status
- * @ep:                Reference to structure of type pch_udc_ep_regs
- * @stat:      Endpoint status
- */
-static inline void pch_udc_clear_ep_status(struct pch_udc_ep *ep,
-                                        u32 stat)
-{
-       return pch_udc_ep_writel(ep, stat, UDC_EPSTS_ADDR);
-}
-
-/**
- * pch_udc_ep_set_nak() - Set the bit 7 (SNAK field)
- *                             of the endpoint control register
- * @ep:                Reference to structure of type pch_udc_ep_regs
- */
-static inline void pch_udc_ep_set_nak(struct pch_udc_ep *ep)
-{
-       pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_SNAK);
-}
-
-/**
- * pch_udc_ep_clear_nak() - Set the bit 8 (CNAK field)
- *                             of the endpoint control register
- * @ep:                reference to structure of type pch_udc_ep_regs
- */
-static void pch_udc_ep_clear_nak(struct pch_udc_ep *ep)
-{
-       unsigned int loopcnt = 0;
-       struct pch_udc_dev *dev = ep->dev;
-
-       if (!(pch_udc_ep_readl(ep, UDC_EPCTL_ADDR) & UDC_EPCTL_NAK))
-               return;
-       if (!ep->in) {
-               loopcnt = 10000;
-               while (!(pch_udc_read_ep_status(ep) & UDC_EPSTS_MRXFIFO_EMP) &&
-                       --loopcnt)
-                       udelay(5);
-               if (!loopcnt)
-                       dev_err(&dev->pdev->dev, "%s: RxFIFO not Empty\n",
-                               __func__);
-       }
-       loopcnt = 10000;
-       while ((pch_udc_read_ep_control(ep) & UDC_EPCTL_NAK) && --loopcnt) {
-               pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_CNAK);
-               udelay(5);
-       }
-       if (!loopcnt)
-               dev_err(&dev->pdev->dev, "%s: Clear NAK not set for ep%d%s\n",
-                       __func__, ep->num, (ep->in ? "in" : "out"));
-}
-
-/**
- * pch_udc_ep_fifo_flush() - Flush the endpoint fifo
- * @ep:        reference to structure of type pch_udc_ep_regs
- * @dir:       direction of endpoint
- *               0:  endpoint is OUT
- *               !0: endpoint is IN
- */
-static void pch_udc_ep_fifo_flush(struct pch_udc_ep *ep, int dir)
-{
-       if (dir) {      /* IN ep */
-               pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_F);
-               return;
-       }
-}
-
-/**
- * pch_udc_ep_enable() - This api enables endpoint
- * @regs:      Reference to structure pch_udc_ep_regs
- * @desc:      endpoint descriptor
- */
-static void pch_udc_ep_enable(struct pch_udc_ep *ep,
-                              struct pch_udc_cfg_data *cfg,
-                              const struct usb_endpoint_descriptor *desc)
-{
-       u32 val = 0;
-       u32 buff_size = 0;
-
-       pch_udc_ep_set_trfr_type(ep, desc->bmAttributes);
-       if (ep->in)
-               buff_size = UDC_EPIN_BUFF_SIZE;
-       else
-               buff_size = UDC_EPOUT_BUFF_SIZE;
-       pch_udc_ep_set_bufsz(ep, buff_size, ep->in);
-       pch_udc_ep_set_maxpkt(ep, usb_endpoint_maxp(desc));
-       pch_udc_ep_set_nak(ep);
-       pch_udc_ep_fifo_flush(ep, ep->in);
-       /* Configure the endpoint */
-       val = ep->num << UDC_CSR_NE_NUM_SHIFT | ep->in << UDC_CSR_NE_DIR_SHIFT |
-             ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) <<
-               UDC_CSR_NE_TYPE_SHIFT) |
-             (cfg->cur_cfg << UDC_CSR_NE_CFG_SHIFT) |
-             (cfg->cur_intf << UDC_CSR_NE_INTF_SHIFT) |
-             (cfg->cur_alt << UDC_CSR_NE_ALT_SHIFT) |
-             usb_endpoint_maxp(desc) << UDC_CSR_NE_MAX_PKT_SHIFT;
-
-       if (ep->in)
-               pch_udc_write_csr(ep->dev, val, UDC_EPIN_IDX(ep->num));
-       else
-               pch_udc_write_csr(ep->dev, val, UDC_EPOUT_IDX(ep->num));
-}
-
-/**
- * pch_udc_ep_disable() - This api disables endpoint
- * @regs:      Reference to structure pch_udc_ep_regs
- */
-static void pch_udc_ep_disable(struct pch_udc_ep *ep)
-{
-       if (ep->in) {
-               /* flush the fifo */
-               pch_udc_ep_writel(ep, UDC_EPCTL_F, UDC_EPCTL_ADDR);
-               /* set NAK */
-               pch_udc_ep_writel(ep, UDC_EPCTL_SNAK, UDC_EPCTL_ADDR);
-               pch_udc_ep_bit_set(ep, UDC_EPSTS_ADDR, UDC_EPSTS_IN);
-       } else {
-               /* set NAK */
-               pch_udc_ep_writel(ep, UDC_EPCTL_SNAK, UDC_EPCTL_ADDR);
-       }
-       /* reset desc pointer */
-       pch_udc_ep_writel(ep, 0, UDC_DESPTR_ADDR);
-}
-
-/**
- * pch_udc_wait_ep_stall() - Wait EP stall.
- * @dev:       Reference to pch_udc_dev structure
- */
-static void pch_udc_wait_ep_stall(struct pch_udc_ep *ep)
-{
-       unsigned int count = 10000;
-
-       /* Wait till idle */
-       while ((pch_udc_read_ep_control(ep) & UDC_EPCTL_S) && --count)
-               udelay(5);
-       if (!count)
-               dev_err(&ep->dev->pdev->dev, "%s: wait error\n", __func__);
-}
-
-/**
- * pch_udc_init() - This API initializes usb device controller
- * @dev:       Rreference to pch_udc_regs structure
- */
-static void pch_udc_init(struct pch_udc_dev *dev)
-{
-       if (NULL == dev) {
-               pr_err("%s: Invalid address\n", __func__);
-               return;
-       }
-       /* Soft Reset and Reset PHY */
-       pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
-       pch_udc_writel(dev, UDC_SRST | UDC_PSRST, UDC_SRST_ADDR);
-       mdelay(1);
-       pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
-       pch_udc_writel(dev, 0x00, UDC_SRST_ADDR);
-       mdelay(1);
-       /* mask and clear all device interrupts */
-       pch_udc_bit_set(dev, UDC_DEVIRQMSK_ADDR, UDC_DEVINT_MSK);
-       pch_udc_bit_set(dev, UDC_DEVIRQSTS_ADDR, UDC_DEVINT_MSK);
-
-       /* mask and clear all ep interrupts */
-       pch_udc_bit_set(dev, UDC_EPIRQMSK_ADDR, UDC_EPINT_MSK_DISABLE_ALL);
-       pch_udc_bit_set(dev, UDC_EPIRQSTS_ADDR, UDC_EPINT_MSK_DISABLE_ALL);
-
-       /* enable dynamic CSR programmingi, self powered and device speed */
-       if (speed_fs)
-               pch_udc_bit_set(dev, UDC_DEVCFG_ADDR, UDC_DEVCFG_CSR_PRG |
-                               UDC_DEVCFG_SP | UDC_DEVCFG_SPD_FS);
-       else /* defaul high speed */
-               pch_udc_bit_set(dev, UDC_DEVCFG_ADDR, UDC_DEVCFG_CSR_PRG |
-                               UDC_DEVCFG_SP | UDC_DEVCFG_SPD_HS);
-       pch_udc_bit_set(dev, UDC_DEVCTL_ADDR,
-                       (PCH_UDC_THLEN << UDC_DEVCTL_THLEN_SHIFT) |
-                       (PCH_UDC_BRLEN << UDC_DEVCTL_BRLEN_SHIFT) |
-                       UDC_DEVCTL_MODE | UDC_DEVCTL_BREN |
-                       UDC_DEVCTL_THE);
-}
-
-/**
- * pch_udc_exit() - This API exit usb device controller
- * @dev:       Reference to pch_udc_regs structure
- */
-static void pch_udc_exit(struct pch_udc_dev *dev)
-{
-       /* mask all device interrupts */
-       pch_udc_bit_set(dev, UDC_DEVIRQMSK_ADDR, UDC_DEVINT_MSK);
-       /* mask all ep interrupts */
-       pch_udc_bit_set(dev, UDC_EPIRQMSK_ADDR, UDC_EPINT_MSK_DISABLE_ALL);
-       /* put device in disconnected state */
-       pch_udc_set_disconnect(dev);
-}
-
-/**
- * pch_udc_pcd_get_frame() - This API is invoked to get the current frame number
- * @gadget:    Reference to the gadget driver
- *
- * Return codes:
- *     0:              Success
- *     -EINVAL:        If the gadget passed is NULL
- */
-static int pch_udc_pcd_get_frame(struct usb_gadget *gadget)
-{
-       struct pch_udc_dev      *dev;
-
-       if (!gadget)
-               return -EINVAL;
-       dev = container_of(gadget, struct pch_udc_dev, gadget);
-       return pch_udc_get_frame(dev);
-}
-
-/**
- * pch_udc_pcd_wakeup() - This API is invoked to initiate a remote wakeup
- * @gadget:    Reference to the gadget driver
- *
- * Return codes:
- *     0:              Success
- *     -EINVAL:        If the gadget passed is NULL
- */
-static int pch_udc_pcd_wakeup(struct usb_gadget *gadget)
-{
-       struct pch_udc_dev      *dev;
-       unsigned long           flags;
-
-       if (!gadget)
-               return -EINVAL;
-       dev = container_of(gadget, struct pch_udc_dev, gadget);
-       spin_lock_irqsave(&dev->lock, flags);
-       pch_udc_rmt_wakeup(dev);
-       spin_unlock_irqrestore(&dev->lock, flags);
-       return 0;
-}
-
-/**
- * pch_udc_pcd_selfpowered() - This API is invoked to specify whether the device
- *                             is self powered or not
- * @gadget:    Reference to the gadget driver
- * @value:     Specifies self powered or not
- *
- * Return codes:
- *     0:              Success
- *     -EINVAL:        If the gadget passed is NULL
- */
-static int pch_udc_pcd_selfpowered(struct usb_gadget *gadget, int value)
-{
-       struct pch_udc_dev      *dev;
-
-       if (!gadget)
-               return -EINVAL;
-       dev = container_of(gadget, struct pch_udc_dev, gadget);
-       if (value)
-               pch_udc_set_selfpowered(dev);
-       else
-               pch_udc_clear_selfpowered(dev);
-       return 0;
-}
-
-/**
- * pch_udc_pcd_pullup() - This API is invoked to make the device
- *                             visible/invisible to the host
- * @gadget:    Reference to the gadget driver
- * @is_on:     Specifies whether the pull up is made active or inactive
- *
- * Return codes:
- *     0:              Success
- *     -EINVAL:        If the gadget passed is NULL
- */
-static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on)
-{
-       struct pch_udc_dev      *dev;
-
-       if (!gadget)
-               return -EINVAL;
-       dev = container_of(gadget, struct pch_udc_dev, gadget);
-       if (is_on) {
-               pch_udc_reconnect(dev);
-       } else {
-               if (dev->driver && dev->driver->disconnect) {
-                       spin_unlock(&dev->lock);
-                       dev->driver->disconnect(&dev->gadget);
-                       spin_lock(&dev->lock);
-               }
-               pch_udc_set_disconnect(dev);
-       }
-
-       return 0;
-}
-
-/**
- * pch_udc_pcd_vbus_session() - This API is used by a driver for an external
- *                             transceiver (or GPIO) that
- *                             detects a VBUS power session starting/ending
- * @gadget:    Reference to the gadget driver
- * @is_active: specifies whether the session is starting or ending
- *
- * Return codes:
- *     0:              Success
- *     -EINVAL:        If the gadget passed is NULL
- */
-static int pch_udc_pcd_vbus_session(struct usb_gadget *gadget, int is_active)
-{
-       struct pch_udc_dev      *dev;
-
-       if (!gadget)
-               return -EINVAL;
-       dev = container_of(gadget, struct pch_udc_dev, gadget);
-       pch_udc_vbus_session(dev, is_active);
-       return 0;
-}
-
-/**
- * pch_udc_pcd_vbus_draw() - This API is used by gadget drivers during
- *                             SET_CONFIGURATION calls to
- *                             specify how much power the device can consume
- * @gadget:    Reference to the gadget driver
- * @mA:                specifies the current limit in 2mA unit
- *
- * Return codes:
- *     -EINVAL:        If the gadget passed is NULL
- *     -EOPNOTSUPP:
- */
-static int pch_udc_pcd_vbus_draw(struct usb_gadget *gadget, unsigned int mA)
-{
-       return -EOPNOTSUPP;
-}
-
-static int pch_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-static int pch_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-static const struct usb_gadget_ops pch_udc_ops = {
-       .get_frame = pch_udc_pcd_get_frame,
-       .wakeup = pch_udc_pcd_wakeup,
-       .set_selfpowered = pch_udc_pcd_selfpowered,
-       .pullup = pch_udc_pcd_pullup,
-       .vbus_session = pch_udc_pcd_vbus_session,
-       .vbus_draw = pch_udc_pcd_vbus_draw,
-       .udc_start = pch_udc_start,
-       .udc_stop = pch_udc_stop,
-};
-
-/**
- * pch_vbus_gpio_get_value() - This API gets value of GPIO port as VBUS status.
- * @dev:       Reference to the driver structure
- *
- * Return value:
- *     1: VBUS is high
- *     0: VBUS is low
- *     -1: It is not enable to detect VBUS using GPIO
- */
-static int pch_vbus_gpio_get_value(struct pch_udc_dev *dev)
-{
-       int vbus = 0;
-
-       if (dev->vbus_gpio.port)
-               vbus = gpio_get_value(dev->vbus_gpio.port) ? 1 : 0;
-       else
-               vbus = -1;
-
-       return vbus;
-}
-
-/**
- * pch_vbus_gpio_work_fall() - This API keeps watch on VBUS becoming Low.
- *                             If VBUS is Low, disconnect is processed
- * @irq_work:  Structure for WorkQueue
- *
- */
-static void pch_vbus_gpio_work_fall(struct work_struct *irq_work)
-{
-       struct pch_vbus_gpio_data *vbus_gpio = container_of(irq_work,
-               struct pch_vbus_gpio_data, irq_work_fall);
-       struct pch_udc_dev *dev =
-               container_of(vbus_gpio, struct pch_udc_dev, vbus_gpio);
-       int vbus_saved = -1;
-       int vbus;
-       int count;
-
-       if (!dev->vbus_gpio.port)
-               return;
-
-       for (count = 0; count < (PCH_VBUS_PERIOD / PCH_VBUS_INTERVAL);
-               count++) {
-               vbus = pch_vbus_gpio_get_value(dev);
-
-               if ((vbus_saved == vbus) && (vbus == 0)) {
-                       dev_dbg(&dev->pdev->dev, "VBUS fell");
-                       if (dev->driver
-                               && dev->driver->disconnect) {
-                               dev->driver->disconnect(
-                                       &dev->gadget);
-                       }
-                       if (dev->vbus_gpio.intr)
-                               pch_udc_init(dev);
-                       else
-                               pch_udc_reconnect(dev);
-                       return;
-               }
-               vbus_saved = vbus;
-               mdelay(PCH_VBUS_INTERVAL);
-       }
-}
-
-/**
- * pch_vbus_gpio_work_rise() - This API checks VBUS is High.
- *                             If VBUS is High, connect is processed
- * @irq_work:  Structure for WorkQueue
- *
- */
-static void pch_vbus_gpio_work_rise(struct work_struct *irq_work)
-{
-       struct pch_vbus_gpio_data *vbus_gpio = container_of(irq_work,
-               struct pch_vbus_gpio_data, irq_work_rise);
-       struct pch_udc_dev *dev =
-               container_of(vbus_gpio, struct pch_udc_dev, vbus_gpio);
-       int vbus;
-
-       if (!dev->vbus_gpio.port)
-               return;
-
-       mdelay(PCH_VBUS_INTERVAL);
-       vbus = pch_vbus_gpio_get_value(dev);
-
-       if (vbus == 1) {
-               dev_dbg(&dev->pdev->dev, "VBUS rose");
-               pch_udc_reconnect(dev);
-               return;
-       }
-}
-
-/**
- * pch_vbus_gpio_irq() - IRQ handler for GPIO intrerrupt for changing VBUS
- * @irq:       Interrupt request number
- * @dev:       Reference to the device structure
- *
- * Return codes:
- *     0: Success
- *     -EINVAL: GPIO port is invalid or can't be initialized.
- */
-static irqreturn_t pch_vbus_gpio_irq(int irq, void *data)
-{
-       struct pch_udc_dev *dev = (struct pch_udc_dev *)data;
-
-       if (!dev->vbus_gpio.port || !dev->vbus_gpio.intr)
-               return IRQ_NONE;
-
-       if (pch_vbus_gpio_get_value(dev))
-               schedule_work(&dev->vbus_gpio.irq_work_rise);
-       else
-               schedule_work(&dev->vbus_gpio.irq_work_fall);
-
-       return IRQ_HANDLED;
-}
-
-/**
- * pch_vbus_gpio_init() - This API initializes GPIO port detecting VBUS.
- * @dev:       Reference to the driver structure
- * @vbus_gpio  Number of GPIO port to detect gpio
- *
- * Return codes:
- *     0: Success
- *     -EINVAL: GPIO port is invalid or can't be initialized.
- */
-static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port)
-{
-       int err;
-       int irq_num = 0;
-
-       dev->vbus_gpio.port = 0;
-       dev->vbus_gpio.intr = 0;
-
-       if (vbus_gpio_port <= -1)
-               return -EINVAL;
-
-       err = gpio_is_valid(vbus_gpio_port);
-       if (!err) {
-               pr_err("%s: gpio port %d is invalid\n",
-                       __func__, vbus_gpio_port);
-               return -EINVAL;
-       }
-
-       err = gpio_request(vbus_gpio_port, "pch_vbus");
-       if (err) {
-               pr_err("%s: can't request gpio port %d, err: %d\n",
-                       __func__, vbus_gpio_port, err);
-               return -EINVAL;
-       }
-
-       dev->vbus_gpio.port = vbus_gpio_port;
-       gpio_direction_input(vbus_gpio_port);
-       INIT_WORK(&dev->vbus_gpio.irq_work_fall, pch_vbus_gpio_work_fall);
-
-       irq_num = gpio_to_irq(vbus_gpio_port);
-       if (irq_num > 0) {
-               irq_set_irq_type(irq_num, IRQ_TYPE_EDGE_BOTH);
-               err = request_irq(irq_num, pch_vbus_gpio_irq, 0,
-                       "vbus_detect", dev);
-               if (!err) {
-                       dev->vbus_gpio.intr = irq_num;
-                       INIT_WORK(&dev->vbus_gpio.irq_work_rise,
-                               pch_vbus_gpio_work_rise);
-               } else {
-                       pr_err("%s: can't request irq %d, err: %d\n",
-                               __func__, irq_num, err);
-               }
-       }
-
-       return 0;
-}
-
-/**
- * pch_vbus_gpio_free() - This API frees resources of GPIO port
- * @dev:       Reference to the driver structure
- */
-static void pch_vbus_gpio_free(struct pch_udc_dev *dev)
-{
-       if (dev->vbus_gpio.intr)
-               free_irq(dev->vbus_gpio.intr, dev);
-
-       if (dev->vbus_gpio.port)
-               gpio_free(dev->vbus_gpio.port);
-}
-
-/**
- * complete_req() - This API is invoked from the driver when processing
- *                     of a request is complete
- * @ep:                Reference to the endpoint structure
- * @req:       Reference to the request structure
- * @status:    Indicates the success/failure of completion
- */
-static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
-                                                                int status)
-       __releases(&dev->lock)
-       __acquires(&dev->lock)
-{
-       struct pch_udc_dev      *dev;
-       unsigned halted = ep->halted;
-
-       list_del_init(&req->queue);
-
-       /* set new status if pending */
-       if (req->req.status == -EINPROGRESS)
-               req->req.status = status;
-       else
-               status = req->req.status;
-
-       dev = ep->dev;
-       if (req->dma_mapped) {
-               if (req->dma == DMA_ADDR_INVALID) {
-                       if (ep->in)
-                               dma_unmap_single(&dev->pdev->dev, req->req.dma,
-                                                req->req.length,
-                                                DMA_TO_DEVICE);
-                       else
-                               dma_unmap_single(&dev->pdev->dev, req->req.dma,
-                                                req->req.length,
-                                                DMA_FROM_DEVICE);
-                       req->req.dma = DMA_ADDR_INVALID;
-               } else {
-                       if (ep->in)
-                               dma_unmap_single(&dev->pdev->dev, req->dma,
-                                                req->req.length,
-                                                DMA_TO_DEVICE);
-                       else {
-                               dma_unmap_single(&dev->pdev->dev, req->dma,
-                                                req->req.length,
-                                                DMA_FROM_DEVICE);
-                               memcpy(req->req.buf, req->buf, req->req.length);
-                       }
-                       kfree(req->buf);
-                       req->dma = DMA_ADDR_INVALID;
-               }
-               req->dma_mapped = 0;
-       }
-       ep->halted = 1;
-       spin_unlock(&dev->lock);
-       if (!ep->in)
-               pch_udc_ep_clear_rrdy(ep);
-       req->req.complete(&ep->ep, &req->req);
-       spin_lock(&dev->lock);
-       ep->halted = halted;
-}
-
-/**
- * empty_req_queue() - This API empties the request queue of an endpoint
- * @ep:                Reference to the endpoint structure
- */
-static void empty_req_queue(struct pch_udc_ep *ep)
-{
-       struct pch_udc_request  *req;
-
-       ep->halted = 1;
-       while (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next, struct pch_udc_request, queue);
-               complete_req(ep, req, -ESHUTDOWN);      /* Remove from list */
-       }
-}
-
-/**
- * pch_udc_free_dma_chain() - This function frees the DMA chain created
- *                             for the request
- * @dev                Reference to the driver structure
- * @req                Reference to the request to be freed
- *
- * Return codes:
- *     0: Success
- */
-static void pch_udc_free_dma_chain(struct pch_udc_dev *dev,
-                                  struct pch_udc_request *req)
-{
-       struct pch_udc_data_dma_desc *td = req->td_data;
-       unsigned i = req->chain_len;
-
-       dma_addr_t addr2;
-       dma_addr_t addr = (dma_addr_t)td->next;
-       td->next = 0x00;
-       for (; i > 1; --i) {
-               /* do not free first desc., will be done by free for request */
-               td = phys_to_virt(addr);
-               addr2 = (dma_addr_t)td->next;
-               pci_pool_free(dev->data_requests, td, addr);
-               td->next = 0x00;
-               addr = addr2;
-       }
-       req->chain_len = 1;
-}
-
-/**
- * pch_udc_create_dma_chain() - This function creates or reinitializes
- *                             a DMA chain
- * @ep:                Reference to the endpoint structure
- * @req:       Reference to the request
- * @buf_len:   The buffer length
- * @gfp_flags: Flags to be used while mapping the data buffer
- *
- * Return codes:
- *     0:              success,
- *     -ENOMEM:        pci_pool_alloc invocation fails
- */
-static int pch_udc_create_dma_chain(struct pch_udc_ep *ep,
-                                   struct pch_udc_request *req,
-                                   unsigned long buf_len,
-                                   gfp_t gfp_flags)
-{
-       struct pch_udc_data_dma_desc *td = req->td_data, *last;
-       unsigned long bytes = req->req.length, i = 0;
-       dma_addr_t dma_addr;
-       unsigned len = 1;
-
-       if (req->chain_len > 1)
-               pch_udc_free_dma_chain(ep->dev, req);
-
-       if (req->dma == DMA_ADDR_INVALID)
-               td->dataptr = req->req.dma;
-       else
-               td->dataptr = req->dma;
-
-       td->status = PCH_UDC_BS_HST_BSY;
-       for (; ; bytes -= buf_len, ++len) {
-               td->status = PCH_UDC_BS_HST_BSY | min(buf_len, bytes);
-               if (bytes <= buf_len)
-                       break;
-               last = td;
-               td = pci_pool_alloc(ep->dev->data_requests, gfp_flags,
-                                   &dma_addr);
-               if (!td)
-                       goto nomem;
-               i += buf_len;
-               td->dataptr = req->td_data->dataptr + i;
-               last->next = dma_addr;
-       }
-
-       req->td_data_last = td;
-       td->status |= PCH_UDC_DMA_LAST;
-       td->next = req->td_data_phys;
-       req->chain_len = len;
-       return 0;
-
-nomem:
-       if (len > 1) {
-               req->chain_len = len;
-               pch_udc_free_dma_chain(ep->dev, req);
-       }
-       req->chain_len = 1;
-       return -ENOMEM;
-}
-
-/**
- * prepare_dma() - This function creates and initializes the DMA chain
- *                     for the request
- * @ep:                Reference to the endpoint structure
- * @req:       Reference to the request
- * @gfp:       Flag to be used while mapping the data buffer
- *
- * Return codes:
- *     0:              Success
- *     Other 0:        linux error number on failure
- */
-static int prepare_dma(struct pch_udc_ep *ep, struct pch_udc_request *req,
-                         gfp_t gfp)
-{
-       int     retval;
-
-       /* Allocate and create a DMA chain */
-       retval = pch_udc_create_dma_chain(ep, req, ep->ep.maxpacket, gfp);
-       if (retval) {
-               pr_err("%s: could not create DMA chain:%d\n", __func__, retval);
-               return retval;
-       }
-       if (ep->in)
-               req->td_data->status = (req->td_data->status &
-                               ~PCH_UDC_BUFF_STS) | PCH_UDC_BS_HST_RDY;
-       return 0;
-}
-
-/**
- * process_zlp() - This function process zero length packets
- *                     from the gadget driver
- * @ep:                Reference to the endpoint structure
- * @req:       Reference to the request
- */
-static void process_zlp(struct pch_udc_ep *ep, struct pch_udc_request *req)
-{
-       struct pch_udc_dev      *dev = ep->dev;
-
-       /* IN zlp's are handled by hardware */
-       complete_req(ep, req, 0);
-
-       /* if set_config or set_intf is waiting for ack by zlp
-        * then set CSR_DONE
-        */
-       if (dev->set_cfg_not_acked) {
-               pch_udc_set_csr_done(dev);
-               dev->set_cfg_not_acked = 0;
-       }
-       /* setup command is ACK'ed now by zlp */
-       if (!dev->stall && dev->waiting_zlp_ack) {
-               pch_udc_ep_clear_nak(&(dev->ep[UDC_EP0IN_IDX]));
-               dev->waiting_zlp_ack = 0;
-       }
-}
-
-/**
- * pch_udc_start_rxrequest() - This function starts the receive requirement.
- * @ep:                Reference to the endpoint structure
- * @req:       Reference to the request structure
- */
-static void pch_udc_start_rxrequest(struct pch_udc_ep *ep,
-                                        struct pch_udc_request *req)
-{
-       struct pch_udc_data_dma_desc *td_data;
-
-       pch_udc_clear_dma(ep->dev, DMA_DIR_RX);
-       td_data = req->td_data;
-       /* Set the status bits for all descriptors */
-       while (1) {
-               td_data->status = (td_data->status & ~PCH_UDC_BUFF_STS) |
-                                   PCH_UDC_BS_HST_RDY;
-               if ((td_data->status & PCH_UDC_DMA_LAST) ==  PCH_UDC_DMA_LAST)
-                       break;
-               td_data = phys_to_virt(td_data->next);
-       }
-       /* Write the descriptor pointer */
-       pch_udc_ep_set_ddptr(ep, req->td_data_phys);
-       req->dma_going = 1;
-       pch_udc_enable_ep_interrupts(ep->dev, UDC_EPINT_OUT_EP0 << ep->num);
-       pch_udc_set_dma(ep->dev, DMA_DIR_RX);
-       pch_udc_ep_clear_nak(ep);
-       pch_udc_ep_set_rrdy(ep);
-}
-
-/**
- * pch_udc_pcd_ep_enable() - This API enables the endpoint. It is called
- *                             from gadget driver
- * @usbep:     Reference to the USB endpoint structure
- * @desc:      Reference to the USB endpoint descriptor structure
- *
- * Return codes:
- *     0:              Success
- *     -EINVAL:
- *     -ESHUTDOWN:
- */
-static int pch_udc_pcd_ep_enable(struct usb_ep *usbep,
-                                   const struct usb_endpoint_descriptor *desc)
-{
-       struct pch_udc_ep       *ep;
-       struct pch_udc_dev      *dev;
-       unsigned long           iflags;
-
-       if (!usbep || (usbep->name == ep0_string) || !desc ||
-           (desc->bDescriptorType != USB_DT_ENDPOINT) || !desc->wMaxPacketSize)
-               return -EINVAL;
-
-       ep = container_of(usbep, struct pch_udc_ep, ep);
-       dev = ep->dev;
-       if (!dev->driver || (dev->gadget.speed == USB_SPEED_UNKNOWN))
-               return -ESHUTDOWN;
-       spin_lock_irqsave(&dev->lock, iflags);
-       ep->ep.desc = desc;
-       ep->halted = 0;
-       pch_udc_ep_enable(ep, &ep->dev->cfg_data, desc);
-       ep->ep.maxpacket = usb_endpoint_maxp(desc);
-       pch_udc_enable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
-       spin_unlock_irqrestore(&dev->lock, iflags);
-       return 0;
-}
-
-/**
- * pch_udc_pcd_ep_disable() - This API disables endpoint and is called
- *                             from gadget driver
- * @usbep      Reference to the USB endpoint structure
- *
- * Return codes:
- *     0:              Success
- *     -EINVAL:
- */
-static int pch_udc_pcd_ep_disable(struct usb_ep *usbep)
-{
-       struct pch_udc_ep       *ep;
-       struct pch_udc_dev      *dev;
-       unsigned long   iflags;
-
-       if (!usbep)
-               return -EINVAL;
-
-       ep = container_of(usbep, struct pch_udc_ep, ep);
-       dev = ep->dev;
-       if ((usbep->name == ep0_string) || !ep->ep.desc)
-               return -EINVAL;
-
-       spin_lock_irqsave(&ep->dev->lock, iflags);
-       empty_req_queue(ep);
-       ep->halted = 1;
-       pch_udc_ep_disable(ep);
-       pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
-       ep->ep.desc = NULL;
-       INIT_LIST_HEAD(&ep->queue);
-       spin_unlock_irqrestore(&ep->dev->lock, iflags);
-       return 0;
-}
-
-/**
- * pch_udc_alloc_request() - This function allocates request structure.
- *                             It is called by gadget driver
- * @usbep:     Reference to the USB endpoint structure
- * @gfp:       Flag to be used while allocating memory
- *
- * Return codes:
- *     NULL:                   Failure
- *     Allocated address:      Success
- */
-static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep,
-                                                 gfp_t gfp)
-{
-       struct pch_udc_request          *req;
-       struct pch_udc_ep               *ep;
-       struct pch_udc_data_dma_desc    *dma_desc;
-       struct pch_udc_dev              *dev;
-
-       if (!usbep)
-               return NULL;
-       ep = container_of(usbep, struct pch_udc_ep, ep);
-       dev = ep->dev;
-       req = kzalloc(sizeof *req, gfp);
-       if (!req)
-               return NULL;
-       req->req.dma = DMA_ADDR_INVALID;
-       req->dma = DMA_ADDR_INVALID;
-       INIT_LIST_HEAD(&req->queue);
-       if (!ep->dev->dma_addr)
-               return &req->req;
-       /* ep0 in requests are allocated from data pool here */
-       dma_desc = pci_pool_alloc(ep->dev->data_requests, gfp,
-                                 &req->td_data_phys);
-       if (NULL == dma_desc) {
-               kfree(req);
-               return NULL;
-       }
-       /* prevent from using desc. - set HOST BUSY */
-       dma_desc->status |= PCH_UDC_BS_HST_BSY;
-       dma_desc->dataptr = __constant_cpu_to_le32(DMA_ADDR_INVALID);
-       req->td_data = dma_desc;
-       req->td_data_last = dma_desc;
-       req->chain_len = 1;
-       return &req->req;
-}
-
-/**
- * pch_udc_free_request() - This function frees request structure.
- *                             It is called by gadget driver
- * @usbep:     Reference to the USB endpoint structure
- * @usbreq:    Reference to the USB request
- */
-static void pch_udc_free_request(struct usb_ep *usbep,
-                                 struct usb_request *usbreq)
-{
-       struct pch_udc_ep       *ep;
-       struct pch_udc_request  *req;
-       struct pch_udc_dev      *dev;
-
-       if (!usbep || !usbreq)
-               return;
-       ep = container_of(usbep, struct pch_udc_ep, ep);
-       req = container_of(usbreq, struct pch_udc_request, req);
-       dev = ep->dev;
-       if (!list_empty(&req->queue))
-               dev_err(&dev->pdev->dev, "%s: %s req=0x%p queue not empty\n",
-                       __func__, usbep->name, req);
-       if (req->td_data != NULL) {
-               if (req->chain_len > 1)
-                       pch_udc_free_dma_chain(ep->dev, req);
-               pci_pool_free(ep->dev->data_requests, req->td_data,
-                             req->td_data_phys);
-       }
-       kfree(req);
-}
-
-/**
- * pch_udc_pcd_queue() - This function queues a request packet. It is called
- *                     by gadget driver
- * @usbep:     Reference to the USB endpoint structure
- * @usbreq:    Reference to the USB request
- * @gfp:       Flag to be used while mapping the data buffer
- *
- * Return codes:
- *     0:                      Success
- *     linux error number:     Failure
- */
-static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq,
-                                                                gfp_t gfp)
-{
-       int retval = 0;
-       struct pch_udc_ep       *ep;
-       struct pch_udc_dev      *dev;
-       struct pch_udc_request  *req;
-       unsigned long   iflags;
-
-       if (!usbep || !usbreq || !usbreq->complete || !usbreq->buf)
-               return -EINVAL;
-       ep = container_of(usbep, struct pch_udc_ep, ep);
-       dev = ep->dev;
-       if (!ep->ep.desc && ep->num)
-               return -EINVAL;
-       req = container_of(usbreq, struct pch_udc_request, req);
-       if (!list_empty(&req->queue))
-               return -EINVAL;
-       if (!dev->driver || (dev->gadget.speed == USB_SPEED_UNKNOWN))
-               return -ESHUTDOWN;
-       spin_lock_irqsave(&dev->lock, iflags);
-       /* map the buffer for dma */
-       if (usbreq->length &&
-           ((usbreq->dma == DMA_ADDR_INVALID) || !usbreq->dma)) {
-               if (!((unsigned long)(usbreq->buf) & 0x03)) {
-                       if (ep->in)
-                               usbreq->dma = dma_map_single(&dev->pdev->dev,
-                                                            usbreq->buf,
-                                                            usbreq->length,
-                                                            DMA_TO_DEVICE);
-                       else
-                               usbreq->dma = dma_map_single(&dev->pdev->dev,
-                                                            usbreq->buf,
-                                                            usbreq->length,
-                                                            DMA_FROM_DEVICE);
-               } else {
-                       req->buf = kzalloc(usbreq->length, GFP_ATOMIC);
-                       if (!req->buf) {
-                               retval = -ENOMEM;
-                               goto probe_end;
-                       }
-                       if (ep->in) {
-                               memcpy(req->buf, usbreq->buf, usbreq->length);
-                               req->dma = dma_map_single(&dev->pdev->dev,
-                                                         req->buf,
-                                                         usbreq->length,
-                                                         DMA_TO_DEVICE);
-                       } else
-                               req->dma = dma_map_single(&dev->pdev->dev,
-                                                         req->buf,
-                                                         usbreq->length,
-                                                         DMA_FROM_DEVICE);
-               }
-               req->dma_mapped = 1;
-       }
-       if (usbreq->length > 0) {
-               retval = prepare_dma(ep, req, GFP_ATOMIC);
-               if (retval)
-                       goto probe_end;
-       }
-       usbreq->actual = 0;
-       usbreq->status = -EINPROGRESS;
-       req->dma_done = 0;
-       if (list_empty(&ep->queue) && !ep->halted) {
-               /* no pending transfer, so start this req */
-               if (!usbreq->length) {
-                       process_zlp(ep, req);
-                       retval = 0;
-                       goto probe_end;
-               }
-               if (!ep->in) {
-                       pch_udc_start_rxrequest(ep, req);
-               } else {
-                       /*
-                       * For IN trfr the descriptors will be programmed and
-                       * P bit will be set when
-                       * we get an IN token
-                       */
-                       pch_udc_wait_ep_stall(ep);
-                       pch_udc_ep_clear_nak(ep);
-                       pch_udc_enable_ep_interrupts(ep->dev, (1 << ep->num));
-               }
-       }
-       /* Now add this request to the ep's pending requests */
-       if (req != NULL)
-               list_add_tail(&req->queue, &ep->queue);
-
-probe_end:
-       spin_unlock_irqrestore(&dev->lock, iflags);
-       return retval;
-}
-
-/**
- * pch_udc_pcd_dequeue() - This function de-queues a request packet.
- *                             It is called by gadget driver
- * @usbep:     Reference to the USB endpoint structure
- * @usbreq:    Reference to the USB request
- *
- * Return codes:
- *     0:                      Success
- *     linux error number:     Failure
- */
-static int pch_udc_pcd_dequeue(struct usb_ep *usbep,
-                               struct usb_request *usbreq)
-{
-       struct pch_udc_ep       *ep;
-       struct pch_udc_request  *req;
-       struct pch_udc_dev      *dev;
-       unsigned long           flags;
-       int ret = -EINVAL;
-
-       ep = container_of(usbep, struct pch_udc_ep, ep);
-       dev = ep->dev;
-       if (!usbep || !usbreq || (!ep->ep.desc && ep->num))
-               return ret;
-       req = container_of(usbreq, struct pch_udc_request, req);
-       spin_lock_irqsave(&ep->dev->lock, flags);
-       /* make sure it's still queued on this endpoint */
-       list_for_each_entry(req, &ep->queue, queue) {
-               if (&req->req == usbreq) {
-                       pch_udc_ep_set_nak(ep);
-                       if (!list_empty(&req->queue))
-                               complete_req(ep, req, -ECONNRESET);
-                       ret = 0;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&ep->dev->lock, flags);
-       return ret;
-}
-
-/**
- * pch_udc_pcd_set_halt() - This function Sets or clear the endpoint halt
- *                         feature
- * @usbep:     Reference to the USB endpoint structure
- * @halt:      Specifies whether to set or clear the feature
- *
- * Return codes:
- *     0:                      Success
- *     linux error number:     Failure
- */
-static int pch_udc_pcd_set_halt(struct usb_ep *usbep, int halt)
-{
-       struct pch_udc_ep       *ep;
-       struct pch_udc_dev      *dev;
-       unsigned long iflags;
-       int ret;
-
-       if (!usbep)
-               return -EINVAL;
-       ep = container_of(usbep, struct pch_udc_ep, ep);
-       dev = ep->dev;
-       if (!ep->ep.desc && !ep->num)
-               return -EINVAL;
-       if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN))
-               return -ESHUTDOWN;
-       spin_lock_irqsave(&udc_stall_spinlock, iflags);
-       if (list_empty(&ep->queue)) {
-               if (halt) {
-                       if (ep->num == PCH_UDC_EP0)
-                               ep->dev->stall = 1;
-                       pch_udc_ep_set_stall(ep);
-                       pch_udc_enable_ep_interrupts(ep->dev,
-                                                    PCH_UDC_EPINT(ep->in,
-                                                                  ep->num));
-               } else {
-                       pch_udc_ep_clear_stall(ep);
-               }
-               ret = 0;
-       } else {
-               ret = -EAGAIN;
-       }
-       spin_unlock_irqrestore(&udc_stall_spinlock, iflags);
-       return ret;
-}
-
-/**
- * pch_udc_pcd_set_wedge() - This function Sets or clear the endpoint
- *                             halt feature
- * @usbep:     Reference to the USB endpoint structure
- * @halt:      Specifies whether to set or clear the feature
- *
- * Return codes:
- *     0:                      Success
- *     linux error number:     Failure
- */
-static int pch_udc_pcd_set_wedge(struct usb_ep *usbep)
-{
-       struct pch_udc_ep       *ep;
-       struct pch_udc_dev      *dev;
-       unsigned long iflags;
-       int ret;
-
-       if (!usbep)
-               return -EINVAL;
-       ep = container_of(usbep, struct pch_udc_ep, ep);
-       dev = ep->dev;
-       if (!ep->ep.desc && !ep->num)
-               return -EINVAL;
-       if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN))
-               return -ESHUTDOWN;
-       spin_lock_irqsave(&udc_stall_spinlock, iflags);
-       if (!list_empty(&ep->queue)) {
-               ret = -EAGAIN;
-       } else {
-               if (ep->num == PCH_UDC_EP0)
-                       ep->dev->stall = 1;
-               pch_udc_ep_set_stall(ep);
-               pch_udc_enable_ep_interrupts(ep->dev,
-                                            PCH_UDC_EPINT(ep->in, ep->num));
-               ep->dev->prot_stall = 1;
-               ret = 0;
-       }
-       spin_unlock_irqrestore(&udc_stall_spinlock, iflags);
-       return ret;
-}
-
-/**
- * pch_udc_pcd_fifo_flush() - This function Flush the FIFO of specified endpoint
- * @usbep:     Reference to the USB endpoint structure
- */
-static void pch_udc_pcd_fifo_flush(struct usb_ep *usbep)
-{
-       struct pch_udc_ep  *ep;
-
-       if (!usbep)
-               return;
-
-       ep = container_of(usbep, struct pch_udc_ep, ep);
-       if (ep->ep.desc || !ep->num)
-               pch_udc_ep_fifo_flush(ep, ep->in);
-}
-
-static const struct usb_ep_ops pch_udc_ep_ops = {
-       .enable         = pch_udc_pcd_ep_enable,
-       .disable        = pch_udc_pcd_ep_disable,
-       .alloc_request  = pch_udc_alloc_request,
-       .free_request   = pch_udc_free_request,
-       .queue          = pch_udc_pcd_queue,
-       .dequeue        = pch_udc_pcd_dequeue,
-       .set_halt       = pch_udc_pcd_set_halt,
-       .set_wedge      = pch_udc_pcd_set_wedge,
-       .fifo_status    = NULL,
-       .fifo_flush     = pch_udc_pcd_fifo_flush,
-};
-
-/**
- * pch_udc_init_setup_buff() - This function initializes the SETUP buffer
- * @td_stp:    Reference to the SETP buffer structure
- */
-static void pch_udc_init_setup_buff(struct pch_udc_stp_dma_desc *td_stp)
-{
-       static u32      pky_marker;
-
-       if (!td_stp)
-               return;
-       td_stp->reserved = ++pky_marker;
-       memset(&td_stp->request, 0xFF, sizeof td_stp->request);
-       td_stp->status = PCH_UDC_BS_HST_RDY;
-}
-
-/**
- * pch_udc_start_next_txrequest() - This function starts
- *                                     the next transmission requirement
- * @ep:        Reference to the endpoint structure
- */
-static void pch_udc_start_next_txrequest(struct pch_udc_ep *ep)
-{
-       struct pch_udc_request *req;
-       struct pch_udc_data_dma_desc *td_data;
-
-       if (pch_udc_read_ep_control(ep) & UDC_EPCTL_P)
-               return;
-
-       if (list_empty(&ep->queue))
-               return;
-
-       /* next request */
-       req = list_entry(ep->queue.next, struct pch_udc_request, queue);
-       if (req->dma_going)
-               return;
-       if (!req->td_data)
-               return;
-       pch_udc_wait_ep_stall(ep);
-       req->dma_going = 1;
-       pch_udc_ep_set_ddptr(ep, 0);
-       td_data = req->td_data;
-       while (1) {
-               td_data->status = (td_data->status & ~PCH_UDC_BUFF_STS) |
-                                  PCH_UDC_BS_HST_RDY;
-               if ((td_data->status & PCH_UDC_DMA_LAST) == PCH_UDC_DMA_LAST)
-                       break;
-               td_data = phys_to_virt(td_data->next);
-       }
-       pch_udc_ep_set_ddptr(ep, req->td_data_phys);
-       pch_udc_set_dma(ep->dev, DMA_DIR_TX);
-       pch_udc_ep_set_pd(ep);
-       pch_udc_enable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
-       pch_udc_ep_clear_nak(ep);
-}
-
-/**
- * pch_udc_complete_transfer() - This function completes a transfer
- * @ep:                Reference to the endpoint structure
- */
-static void pch_udc_complete_transfer(struct pch_udc_ep *ep)
-{
-       struct pch_udc_request *req;
-       struct pch_udc_dev *dev = ep->dev;
-
-       if (list_empty(&ep->queue))
-               return;
-       req = list_entry(ep->queue.next, struct pch_udc_request, queue);
-       if ((req->td_data_last->status & PCH_UDC_BUFF_STS) !=
-           PCH_UDC_BS_DMA_DONE)
-               return;
-       if ((req->td_data_last->status & PCH_UDC_RXTX_STS) !=
-            PCH_UDC_RTS_SUCC) {
-               dev_err(&dev->pdev->dev, "Invalid RXTX status (0x%08x) "
-                       "epstatus=0x%08x\n",
-                      (req->td_data_last->status & PCH_UDC_RXTX_STS),
-                      (int)(ep->epsts));
-               return;
-       }
-
-       req->req.actual = req->req.length;
-       req->td_data_last->status = PCH_UDC_BS_HST_BSY | PCH_UDC_DMA_LAST;
-       req->td_data->status = PCH_UDC_BS_HST_BSY | PCH_UDC_DMA_LAST;
-       complete_req(ep, req, 0);
-       req->dma_going = 0;
-       if (!list_empty(&ep->queue)) {
-               pch_udc_wait_ep_stall(ep);
-               pch_udc_ep_clear_nak(ep);
-               pch_udc_enable_ep_interrupts(ep->dev,
-                                            PCH_UDC_EPINT(ep->in, ep->num));
-       } else {
-               pch_udc_disable_ep_interrupts(ep->dev,
-                                             PCH_UDC_EPINT(ep->in, ep->num));
-       }
-}
-
-/**
- * pch_udc_complete_receiver() - This function completes a receiver
- * @ep:                Reference to the endpoint structure
- */
-static void pch_udc_complete_receiver(struct pch_udc_ep *ep)
-{
-       struct pch_udc_request *req;
-       struct pch_udc_dev *dev = ep->dev;
-       unsigned int count;
-       struct pch_udc_data_dma_desc *td;
-       dma_addr_t addr;
-
-       if (list_empty(&ep->queue))
-               return;
-       /* next request */
-       req = list_entry(ep->queue.next, struct pch_udc_request, queue);
-       pch_udc_clear_dma(ep->dev, DMA_DIR_RX);
-       pch_udc_ep_set_ddptr(ep, 0);
-       if ((req->td_data_last->status & PCH_UDC_BUFF_STS) ==
-           PCH_UDC_BS_DMA_DONE)
-               td = req->td_data_last;
-       else
-               td = req->td_data;
-
-       while (1) {
-               if ((td->status & PCH_UDC_RXTX_STS) != PCH_UDC_RTS_SUCC) {
-                       dev_err(&dev->pdev->dev, "Invalid RXTX status=0x%08x "
-                               "epstatus=0x%08x\n",
-                               (req->td_data->status & PCH_UDC_RXTX_STS),
-                               (int)(ep->epsts));
-                       return;
-               }
-               if ((td->status & PCH_UDC_BUFF_STS) == PCH_UDC_BS_DMA_DONE)
-                       if (td->status & PCH_UDC_DMA_LAST) {
-                               count = td->status & PCH_UDC_RXTX_BYTES;
-                               break;
-                       }
-               if (td == req->td_data_last) {
-                       dev_err(&dev->pdev->dev, "Not complete RX descriptor");
-                       return;
-               }
-               addr = (dma_addr_t)td->next;
-               td = phys_to_virt(addr);
-       }
-       /* on 64k packets the RXBYTES field is zero */
-       if (!count && (req->req.length == UDC_DMA_MAXPACKET))
-               count = UDC_DMA_MAXPACKET;
-       req->td_data->status |= PCH_UDC_DMA_LAST;
-       td->status |= PCH_UDC_BS_HST_BSY;
-
-       req->dma_going = 0;
-       req->req.actual = count;
-       complete_req(ep, req, 0);
-       /* If there is a new/failed requests try that now */
-       if (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next, struct pch_udc_request, queue);
-               pch_udc_start_rxrequest(ep, req);
-       }
-}
-
-/**
- * pch_udc_svc_data_in() - This function process endpoint interrupts
- *                             for IN endpoints
- * @dev:       Reference to the device structure
- * @ep_num:    Endpoint that generated the interrupt
- */
-static void pch_udc_svc_data_in(struct pch_udc_dev *dev, int ep_num)
-{
-       u32     epsts;
-       struct pch_udc_ep       *ep;
-
-       ep = &dev->ep[UDC_EPIN_IDX(ep_num)];
-       epsts = ep->epsts;
-       ep->epsts = 0;
-
-       if (!(epsts & (UDC_EPSTS_IN | UDC_EPSTS_BNA  | UDC_EPSTS_HE |
-                      UDC_EPSTS_TDC | UDC_EPSTS_RCS | UDC_EPSTS_TXEMPTY |
-                      UDC_EPSTS_RSS | UDC_EPSTS_XFERDONE)))
-               return;
-       if ((epsts & UDC_EPSTS_BNA))
-               return;
-       if (epsts & UDC_EPSTS_HE)
-               return;
-       if (epsts & UDC_EPSTS_RSS) {
-               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 (!dev->prot_stall) {
-                       pch_udc_ep_clear_stall(ep);
-               } else {
-                       pch_udc_ep_set_stall(ep);
-                       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 */
-       if ((epsts & UDC_EPSTS_IN) && !(epsts & UDC_EPSTS_RSS) &&
-           !(epsts & UDC_EPSTS_TDC) && !(epsts & UDC_EPSTS_TXEMPTY))
-               pch_udc_start_next_txrequest(ep);
-}
-
-/**
- * pch_udc_svc_data_out() - Handles interrupts from OUT endpoint
- * @dev:       Reference to the device structure
- * @ep_num:    Endpoint that generated the interrupt
- */
-static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num)
-{
-       u32                     epsts;
-       struct pch_udc_ep               *ep;
-       struct pch_udc_request          *req = NULL;
-
-       ep = &dev->ep[UDC_EPOUT_IDX(ep_num)];
-       epsts = ep->epsts;
-       ep->epsts = 0;
-
-       if ((epsts & UDC_EPSTS_BNA) && (!list_empty(&ep->queue))) {
-               /* next request */
-               req = list_entry(ep->queue.next, struct pch_udc_request,
-                                queue);
-               if ((req->td_data_last->status & PCH_UDC_BUFF_STS) !=
-                    PCH_UDC_BS_DMA_DONE) {
-                       if (!req->dma_going)
-                               pch_udc_start_rxrequest(ep, req);
-                       return;
-               }
-       }
-       if (epsts & UDC_EPSTS_HE)
-               return;
-       if (epsts & UDC_EPSTS_RSS) {
-               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 (!dev->prot_stall) {
-                       pch_udc_ep_clear_stall(ep);
-               } else {
-                       pch_udc_ep_set_stall(ep);
-                       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) {
-                       pch_udc_ep_set_stall(ep);
-                       pch_udc_enable_ep_interrupts(ep->dev,
-                                               PCH_UDC_EPINT(ep->in, ep->num));
-               } else {
-                       pch_udc_complete_receiver(ep);
-               }
-       }
-       if (list_empty(&ep->queue))
-               pch_udc_set_dma(dev, DMA_DIR_RX);
-}
-
-/**
- * pch_udc_svc_control_in() - Handle Control IN endpoint interrupts
- * @dev:       Reference to the device structure
- */
-static void pch_udc_svc_control_in(struct pch_udc_dev *dev)
-{
-       u32     epsts;
-       struct pch_udc_ep       *ep;
-       struct pch_udc_ep       *ep_out;
-
-       ep = &dev->ep[UDC_EP0IN_IDX];
-       ep_out = &dev->ep[UDC_EP0OUT_IDX];
-       epsts = ep->epsts;
-       ep->epsts = 0;
-
-       if (!(epsts & (UDC_EPSTS_IN | UDC_EPSTS_BNA | UDC_EPSTS_HE |
-                      UDC_EPSTS_TDC | UDC_EPSTS_RCS | UDC_EPSTS_TXEMPTY |
-                      UDC_EPSTS_XFERDONE)))
-               return;
-       if ((epsts & UDC_EPSTS_BNA))
-               return;
-       if (epsts & UDC_EPSTS_HE)
-               return;
-       if ((epsts & UDC_EPSTS_TDC) && (!dev->stall)) {
-               pch_udc_complete_transfer(ep);
-               pch_udc_clear_dma(dev, DMA_DIR_RX);
-               ep_out->td_data->status = (ep_out->td_data->status &
-                                       ~PCH_UDC_BUFF_STS) |
-                                       PCH_UDC_BS_HST_RDY;
-               pch_udc_ep_clear_nak(ep_out);
-               pch_udc_set_dma(dev, DMA_DIR_RX);
-               pch_udc_ep_set_rrdy(ep_out);
-       }
-       /* On IN interrupt, provide data if we have any */
-       if ((epsts & UDC_EPSTS_IN) && !(epsts & UDC_EPSTS_TDC) &&
-            !(epsts & UDC_EPSTS_TXEMPTY))
-               pch_udc_start_next_txrequest(ep);
-}
-
-/**
- * pch_udc_svc_control_out() - Routine that handle Control
- *                                     OUT endpoint interrupts
- * @dev:       Reference to the device structure
- */
-static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
-       __releases(&dev->lock)
-       __acquires(&dev->lock)
-{
-       u32     stat;
-       int setup_supported;
-       struct pch_udc_ep       *ep;
-
-       ep = &dev->ep[UDC_EP0OUT_IDX];
-       stat = ep->epsts;
-       ep->epsts = 0;
-
-       /* If setup data */
-       if (((stat & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_SHIFT) ==
-           UDC_EPSTS_OUT_SETUP) {
-               dev->stall = 0;
-               dev->ep[UDC_EP0IN_IDX].halted = 0;
-               dev->ep[UDC_EP0OUT_IDX].halted = 0;
-               dev->setup_data = ep->td_stp->request;
-               pch_udc_init_setup_buff(ep->td_stp);
-               pch_udc_clear_dma(dev, DMA_DIR_RX);
-               pch_udc_ep_fifo_flush(&(dev->ep[UDC_EP0IN_IDX]),
-                                     dev->ep[UDC_EP0IN_IDX].in);
-               if ((dev->setup_data.bRequestType & USB_DIR_IN))
-                       dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep;
-               else /* OUT */
-                       dev->gadget.ep0 = &ep->ep;
-               spin_unlock(&dev->lock);
-               /* If Mass storage Reset */
-               if ((dev->setup_data.bRequestType == 0x21) &&
-                   (dev->setup_data.bRequest == 0xFF))
-                       dev->prot_stall = 0;
-               /* call gadget with setup data received */
-               setup_supported = dev->driver->setup(&dev->gadget,
-                                                    &dev->setup_data);
-               spin_lock(&dev->lock);
-
-               if (dev->setup_data.bRequestType & USB_DIR_IN) {
-                       ep->td_data->status = (ep->td_data->status &
-                                               ~PCH_UDC_BUFF_STS) |
-                                               PCH_UDC_BS_HST_RDY;
-                       pch_udc_ep_set_ddptr(ep, ep->td_data_phys);
-               }
-               /* ep0 in returns data on IN phase */
-               if (setup_supported >= 0 && setup_supported <
-                                           UDC_EP0IN_MAX_PKT_SIZE) {
-                       pch_udc_ep_clear_nak(&(dev->ep[UDC_EP0IN_IDX]));
-                       /* Gadget would have queued a request when
-                        * we called the setup */
-                       if (!(dev->setup_data.bRequestType & USB_DIR_IN)) {
-                               pch_udc_set_dma(dev, DMA_DIR_RX);
-                               pch_udc_ep_clear_nak(ep);
-                       }
-               } else if (setup_supported < 0) {
-                       /* if unsupported request, then stall */
-                       pch_udc_ep_set_stall(&(dev->ep[UDC_EP0IN_IDX]));
-                       pch_udc_enable_ep_interrupts(ep->dev,
-                                               PCH_UDC_EPINT(ep->in, ep->num));
-                       dev->stall = 0;
-                       pch_udc_set_dma(dev, DMA_DIR_RX);
-               } else {
-                       dev->waiting_zlp_ack = 1;
-               }
-       } else if ((((stat & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_SHIFT) ==
-                    UDC_EPSTS_OUT_DATA) && !dev->stall) {
-               pch_udc_clear_dma(dev, DMA_DIR_RX);
-               pch_udc_ep_set_ddptr(ep, 0);
-               if (!list_empty(&ep->queue)) {
-                       ep->epsts = stat;
-                       pch_udc_svc_data_out(dev, PCH_UDC_EP0);
-               }
-               pch_udc_set_dma(dev, DMA_DIR_RX);
-       }
-       pch_udc_ep_set_rrdy(ep);
-}
-
-
-/**
- * pch_udc_postsvc_epinters() - This function enables end point interrupts
- *                             and clears NAK status
- * @dev:       Reference to the device structure
- * @ep_num:    End point number
- */
-static void pch_udc_postsvc_epinters(struct pch_udc_dev *dev, int ep_num)
-{
-       struct pch_udc_ep       *ep;
-       struct pch_udc_request *req;
-
-       ep = &dev->ep[UDC_EPIN_IDX(ep_num)];
-       if (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next, struct pch_udc_request, queue);
-               pch_udc_enable_ep_interrupts(ep->dev,
-                                            PCH_UDC_EPINT(ep->in, ep->num));
-               pch_udc_ep_clear_nak(ep);
-       }
-}
-
-/**
- * pch_udc_read_all_epstatus() - This function read all endpoint status
- * @dev:       Reference to the device structure
- * @ep_intr:   Status of endpoint interrupt
- */
-static void pch_udc_read_all_epstatus(struct pch_udc_dev *dev, u32 ep_intr)
-{
-       int i;
-       struct pch_udc_ep       *ep;
-
-       for (i = 0; i < PCH_UDC_USED_EP_NUM; i++) {
-               /* IN */
-               if (ep_intr & (0x1 << i)) {
-                       ep = &dev->ep[UDC_EPIN_IDX(i)];
-                       ep->epsts = pch_udc_read_ep_status(ep);
-                       pch_udc_clear_ep_status(ep, ep->epsts);
-               }
-               /* OUT */
-               if (ep_intr & (0x10000 << i)) {
-                       ep = &dev->ep[UDC_EPOUT_IDX(i)];
-                       ep->epsts = pch_udc_read_ep_status(ep);
-                       pch_udc_clear_ep_status(ep, ep->epsts);
-               }
-       }
-}
-
-/**
- * pch_udc_activate_control_ep() - This function enables the control endpoints
- *                                     for traffic after a reset
- * @dev:       Reference to the device structure
- */
-static void pch_udc_activate_control_ep(struct pch_udc_dev *dev)
-{
-       struct pch_udc_ep       *ep;
-       u32 val;
-
-       /* Setup the IN endpoint */
-       ep = &dev->ep[UDC_EP0IN_IDX];
-       pch_udc_clear_ep_control(ep);
-       pch_udc_ep_fifo_flush(ep, ep->in);
-       pch_udc_ep_set_bufsz(ep, UDC_EP0IN_BUFF_SIZE, ep->in);
-       pch_udc_ep_set_maxpkt(ep, UDC_EP0IN_MAX_PKT_SIZE);
-       /* Initialize the IN EP Descriptor */
-       ep->td_data      = NULL;
-       ep->td_stp       = NULL;
-       ep->td_data_phys = 0;
-       ep->td_stp_phys  = 0;
-
-       /* Setup the OUT endpoint */
-       ep = &dev->ep[UDC_EP0OUT_IDX];
-       pch_udc_clear_ep_control(ep);
-       pch_udc_ep_fifo_flush(ep, ep->in);
-       pch_udc_ep_set_bufsz(ep, UDC_EP0OUT_BUFF_SIZE, ep->in);
-       pch_udc_ep_set_maxpkt(ep, UDC_EP0OUT_MAX_PKT_SIZE);
-       val = UDC_EP0OUT_MAX_PKT_SIZE << UDC_CSR_NE_MAX_PKT_SHIFT;
-       pch_udc_write_csr(ep->dev, val, UDC_EP0OUT_IDX);
-
-       /* Initialize the SETUP buffer */
-       pch_udc_init_setup_buff(ep->td_stp);
-       /* Write the pointer address of dma descriptor */
-       pch_udc_ep_set_subptr(ep, ep->td_stp_phys);
-       /* Write the pointer address of Setup descriptor */
-       pch_udc_ep_set_ddptr(ep, ep->td_data_phys);
-
-       /* Initialize the dma descriptor */
-       ep->td_data->status  = PCH_UDC_DMA_LAST;
-       ep->td_data->dataptr = dev->dma_addr;
-       ep->td_data->next    = ep->td_data_phys;
-
-       pch_udc_ep_clear_nak(ep);
-}
-
-
-/**
- * pch_udc_svc_ur_interrupt() - This function handles a USB reset interrupt
- * @dev:       Reference to driver structure
- */
-static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev)
-{
-       struct pch_udc_ep       *ep;
-       int i;
-
-       pch_udc_clear_dma(dev, DMA_DIR_TX);
-       pch_udc_clear_dma(dev, DMA_DIR_RX);
-       /* Mask all endpoint interrupts */
-       pch_udc_disable_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL);
-       /* clear all endpoint interrupts */
-       pch_udc_write_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL);
-
-       for (i = 0; i < PCH_UDC_EP_NUM; i++) {
-               ep = &dev->ep[i];
-               pch_udc_clear_ep_status(ep, UDC_EPSTS_ALL_CLR_MASK);
-               pch_udc_clear_ep_control(ep);
-               pch_udc_ep_set_ddptr(ep, 0);
-               pch_udc_write_csr(ep->dev, 0x00, i);
-       }
-       dev->stall = 0;
-       dev->prot_stall = 0;
-       dev->waiting_zlp_ack = 0;
-       dev->set_cfg_not_acked = 0;
-
-       /* disable ep to empty req queue. Skip the control EP's */
-       for (i = 0; i < (PCH_UDC_USED_EP_NUM*2); i++) {
-               ep = &dev->ep[i];
-               pch_udc_ep_set_nak(ep);
-               pch_udc_ep_fifo_flush(ep, ep->in);
-               /* Complete request queue */
-               empty_req_queue(ep);
-       }
-       if (dev->driver && dev->driver->disconnect) {
-               spin_unlock(&dev->lock);
-               dev->driver->disconnect(&dev->gadget);
-               spin_lock(&dev->lock);
-       }
-}
-
-/**
- * pch_udc_svc_enum_interrupt() - This function handles a USB speed enumeration
- *                             done interrupt
- * @dev:       Reference to driver structure
- */
-static void pch_udc_svc_enum_interrupt(struct pch_udc_dev *dev)
-{
-       u32 dev_stat, dev_speed;
-       u32 speed = USB_SPEED_FULL;
-
-       dev_stat = pch_udc_read_device_status(dev);
-       dev_speed = (dev_stat & UDC_DEVSTS_ENUM_SPEED_MASK) >>
-                                                UDC_DEVSTS_ENUM_SPEED_SHIFT;
-       switch (dev_speed) {
-       case UDC_DEVSTS_ENUM_SPEED_HIGH:
-               speed = USB_SPEED_HIGH;
-               break;
-       case  UDC_DEVSTS_ENUM_SPEED_FULL:
-               speed = USB_SPEED_FULL;
-               break;
-       case  UDC_DEVSTS_ENUM_SPEED_LOW:
-               speed = USB_SPEED_LOW;
-               break;
-       default:
-               BUG();
-       }
-       dev->gadget.speed = speed;
-       pch_udc_activate_control_ep(dev);
-       pch_udc_enable_ep_interrupts(dev, UDC_EPINT_IN_EP0 | UDC_EPINT_OUT_EP0);
-       pch_udc_set_dma(dev, DMA_DIR_TX);
-       pch_udc_set_dma(dev, DMA_DIR_RX);
-       pch_udc_ep_set_rrdy(&(dev->ep[UDC_EP0OUT_IDX]));
-
-       /* enable device interrupts */
-       pch_udc_enable_interrupts(dev, UDC_DEVINT_UR | UDC_DEVINT_US |
-                                       UDC_DEVINT_ES | UDC_DEVINT_ENUM |
-                                       UDC_DEVINT_SI | UDC_DEVINT_SC);
-}
-
-/**
- * pch_udc_svc_intf_interrupt() - This function handles a set interface
- *                               interrupt
- * @dev:       Reference to driver structure
- */
-static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev)
-{
-       u32 reg, dev_stat = 0;
-       int i, ret;
-
-       dev_stat = pch_udc_read_device_status(dev);
-       dev->cfg_data.cur_intf = (dev_stat & UDC_DEVSTS_INTF_MASK) >>
-                                                        UDC_DEVSTS_INTF_SHIFT;
-       dev->cfg_data.cur_alt = (dev_stat & UDC_DEVSTS_ALT_MASK) >>
-                                                        UDC_DEVSTS_ALT_SHIFT;
-       dev->set_cfg_not_acked = 1;
-       /* Construct the usb request for gadget driver and inform it */
-       memset(&dev->setup_data, 0 , sizeof dev->setup_data);
-       dev->setup_data.bRequest = USB_REQ_SET_INTERFACE;
-       dev->setup_data.bRequestType = USB_RECIP_INTERFACE;
-       dev->setup_data.wValue = cpu_to_le16(dev->cfg_data.cur_alt);
-       dev->setup_data.wIndex = cpu_to_le16(dev->cfg_data.cur_intf);
-       /* programm the Endpoint Cfg registers */
-       /* Only one end point cfg register */
-       reg = pch_udc_read_csr(dev, UDC_EP0OUT_IDX);
-       reg = (reg & ~UDC_CSR_NE_INTF_MASK) |
-             (dev->cfg_data.cur_intf << UDC_CSR_NE_INTF_SHIFT);
-       reg = (reg & ~UDC_CSR_NE_ALT_MASK) |
-             (dev->cfg_data.cur_alt << UDC_CSR_NE_ALT_SHIFT);
-       pch_udc_write_csr(dev, reg, UDC_EP0OUT_IDX);
-       for (i = 0; i < PCH_UDC_USED_EP_NUM * 2; i++) {
-               /* clear stall bits */
-               pch_udc_ep_clear_stall(&(dev->ep[i]));
-               dev->ep[i].halted = 0;
-       }
-       dev->stall = 0;
-       spin_unlock(&dev->lock);
-       ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
-       spin_lock(&dev->lock);
-}
-
-/**
- * pch_udc_svc_cfg_interrupt() - This function handles a set configuration
- *                             interrupt
- * @dev:       Reference to driver structure
- */
-static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev)
-{
-       int i, ret;
-       u32 reg, dev_stat = 0;
-
-       dev_stat = pch_udc_read_device_status(dev);
-       dev->set_cfg_not_acked = 1;
-       dev->cfg_data.cur_cfg = (dev_stat & UDC_DEVSTS_CFG_MASK) >>
-                               UDC_DEVSTS_CFG_SHIFT;
-       /* make usb request for gadget driver */
-       memset(&dev->setup_data, 0 , sizeof dev->setup_data);
-       dev->setup_data.bRequest = USB_REQ_SET_CONFIGURATION;
-       dev->setup_data.wValue = cpu_to_le16(dev->cfg_data.cur_cfg);
-       /* program the NE registers */
-       /* Only one end point cfg register */
-       reg = pch_udc_read_csr(dev, UDC_EP0OUT_IDX);
-       reg = (reg & ~UDC_CSR_NE_CFG_MASK) |
-             (dev->cfg_data.cur_cfg << UDC_CSR_NE_CFG_SHIFT);
-       pch_udc_write_csr(dev, reg, UDC_EP0OUT_IDX);
-       for (i = 0; i < PCH_UDC_USED_EP_NUM * 2; i++) {
-               /* clear stall bits */
-               pch_udc_ep_clear_stall(&(dev->ep[i]));
-               dev->ep[i].halted = 0;
-       }
-       dev->stall = 0;
-
-       /* call gadget zero with setup data received */
-       spin_unlock(&dev->lock);
-       ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
-       spin_lock(&dev->lock);
-}
-
-/**
- * pch_udc_dev_isr() - This function services device interrupts
- *                     by invoking appropriate routines.
- * @dev:       Reference to the device structure
- * @dev_intr:  The Device interrupt status.
- */
-static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
-{
-       int vbus;
-
-       /* USB Reset Interrupt */
-       if (dev_intr & UDC_DEVINT_UR) {
-               pch_udc_svc_ur_interrupt(dev);
-               dev_dbg(&dev->pdev->dev, "USB_RESET\n");
-       }
-       /* Enumeration Done Interrupt */
-       if (dev_intr & UDC_DEVINT_ENUM) {
-               pch_udc_svc_enum_interrupt(dev);
-               dev_dbg(&dev->pdev->dev, "USB_ENUM\n");
-       }
-       /* Set Interface Interrupt */
-       if (dev_intr & UDC_DEVINT_SI)
-               pch_udc_svc_intf_interrupt(dev);
-       /* Set Config Interrupt */
-       if (dev_intr & UDC_DEVINT_SC)
-               pch_udc_svc_cfg_interrupt(dev);
-       /* USB Suspend interrupt */
-       if (dev_intr & UDC_DEVINT_US) {
-               if (dev->driver
-                       && dev->driver->suspend) {
-                       spin_unlock(&dev->lock);
-                       dev->driver->suspend(&dev->gadget);
-                       spin_lock(&dev->lock);
-               }
-
-               vbus = pch_vbus_gpio_get_value(dev);
-               if ((dev->vbus_session == 0)
-                       && (vbus != 1)) {
-                       if (dev->driver && dev->driver->disconnect) {
-                               spin_unlock(&dev->lock);
-                               dev->driver->disconnect(&dev->gadget);
-                               spin_lock(&dev->lock);
-                       }
-                       pch_udc_reconnect(dev);
-               } else if ((dev->vbus_session == 0)
-                       && (vbus == 1)
-                       && !dev->vbus_gpio.intr)
-                       schedule_work(&dev->vbus_gpio.irq_work_fall);
-
-               dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n");
-       }
-       /* Clear the SOF interrupt, if enabled */
-       if (dev_intr & UDC_DEVINT_SOF)
-               dev_dbg(&dev->pdev->dev, "SOF\n");
-       /* ES interrupt, IDLE > 3ms on the USB */
-       if (dev_intr & UDC_DEVINT_ES)
-               dev_dbg(&dev->pdev->dev, "ES\n");
-       /* RWKP interrupt */
-       if (dev_intr & UDC_DEVINT_RWKP)
-               dev_dbg(&dev->pdev->dev, "RWKP\n");
-}
-
-/**
- * pch_udc_isr() - This function handles interrupts from the PCH USB Device
- * @irq:       Interrupt request number
- * @dev:       Reference to the device structure
- */
-static irqreturn_t pch_udc_isr(int irq, void *pdev)
-{
-       struct pch_udc_dev *dev = (struct pch_udc_dev *) pdev;
-       u32 dev_intr, ep_intr;
-       int i;
-
-       dev_intr = pch_udc_read_device_interrupts(dev);
-       ep_intr = pch_udc_read_ep_interrupts(dev);
-
-       /* For a hot plug, this find that the controller is hung up. */
-       if (dev_intr == ep_intr)
-               if (dev_intr == pch_udc_readl(dev, UDC_DEVCFG_ADDR)) {
-                       dev_dbg(&dev->pdev->dev, "UDC: Hung up\n");
-                       /* The controller is reset */
-                       pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
-                       return IRQ_HANDLED;
-               }
-       if (dev_intr)
-               /* Clear device interrupts */
-               pch_udc_write_device_interrupts(dev, dev_intr);
-       if (ep_intr)
-               /* Clear ep interrupts */
-               pch_udc_write_ep_interrupts(dev, ep_intr);
-       if (!dev_intr && !ep_intr)
-               return IRQ_NONE;
-       spin_lock(&dev->lock);
-       if (dev_intr)
-               pch_udc_dev_isr(dev, dev_intr);
-       if (ep_intr) {
-               pch_udc_read_all_epstatus(dev, ep_intr);
-               /* Process Control In interrupts, if present */
-               if (ep_intr & UDC_EPINT_IN_EP0) {
-                       pch_udc_svc_control_in(dev);
-                       pch_udc_postsvc_epinters(dev, 0);
-               }
-               /* Process Control Out interrupts, if present */
-               if (ep_intr & UDC_EPINT_OUT_EP0)
-                       pch_udc_svc_control_out(dev);
-               /* Process data in end point interrupts */
-               for (i = 1; i < PCH_UDC_USED_EP_NUM; i++) {
-                       if (ep_intr & (1 <<  i)) {
-                               pch_udc_svc_data_in(dev, i);
-                               pch_udc_postsvc_epinters(dev, i);
-                       }
-               }
-               /* Process data out end point interrupts */
-               for (i = UDC_EPINT_OUT_SHIFT + 1; i < (UDC_EPINT_OUT_SHIFT +
-                                                PCH_UDC_USED_EP_NUM); i++)
-                       if (ep_intr & (1 <<  i))
-                               pch_udc_svc_data_out(dev, i -
-                                                        UDC_EPINT_OUT_SHIFT);
-       }
-       spin_unlock(&dev->lock);
-       return IRQ_HANDLED;
-}
-
-/**
- * pch_udc_setup_ep0() - This function enables control endpoint for traffic
- * @dev:       Reference to the device structure
- */
-static void pch_udc_setup_ep0(struct pch_udc_dev *dev)
-{
-       /* enable ep0 interrupts */
-       pch_udc_enable_ep_interrupts(dev, UDC_EPINT_IN_EP0 |
-                                               UDC_EPINT_OUT_EP0);
-       /* enable device interrupts */
-       pch_udc_enable_interrupts(dev, UDC_DEVINT_UR | UDC_DEVINT_US |
-                                      UDC_DEVINT_ES | UDC_DEVINT_ENUM |
-                                      UDC_DEVINT_SI | UDC_DEVINT_SC);
-}
-
-/**
- * gadget_release() - Free the gadget driver private data
- * @pdev       reference to struct pci_dev
- */
-static void gadget_release(struct device *pdev)
-{
-       struct pch_udc_dev *dev = dev_get_drvdata(pdev);
-
-       kfree(dev);
-}
-
-/**
- * pch_udc_pcd_reinit() - This API initializes the endpoint structures
- * @dev:       Reference to the driver structure
- */
-static void pch_udc_pcd_reinit(struct pch_udc_dev *dev)
-{
-       const char *const ep_string[] = {
-               ep0_string, "ep0out", "ep1in", "ep1out", "ep2in", "ep2out",
-               "ep3in", "ep3out", "ep4in", "ep4out", "ep5in", "ep5out",
-               "ep6in", "ep6out", "ep7in", "ep7out", "ep8in", "ep8out",
-               "ep9in", "ep9out", "ep10in", "ep10out", "ep11in", "ep11out",
-               "ep12in", "ep12out", "ep13in", "ep13out", "ep14in", "ep14out",
-               "ep15in", "ep15out",
-       };
-       int i;
-
-       dev->gadget.speed = USB_SPEED_UNKNOWN;
-       INIT_LIST_HEAD(&dev->gadget.ep_list);
-
-       /* Initialize the endpoints structures */
-       memset(dev->ep, 0, sizeof dev->ep);
-       for (i = 0; i < PCH_UDC_EP_NUM; i++) {
-               struct pch_udc_ep *ep = &dev->ep[i];
-               ep->dev = dev;
-               ep->halted = 1;
-               ep->num = i / 2;
-               ep->in = ~i & 1;
-               ep->ep.name = ep_string[i];
-               ep->ep.ops = &pch_udc_ep_ops;
-               if (ep->in)
-                       ep->offset_addr = ep->num * UDC_EP_REG_SHIFT;
-               else
-                       ep->offset_addr = (UDC_EPINT_OUT_SHIFT + ep->num) *
-                                         UDC_EP_REG_SHIFT;
-               /* need to set ep->ep.maxpacket and set Default Configuration?*/
-               usb_ep_set_maxpacket_limit(&ep->ep, UDC_BULK_MAX_PKT_SIZE);
-               list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
-               INIT_LIST_HEAD(&ep->queue);
-       }
-       usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0IN_IDX].ep, UDC_EP0IN_MAX_PKT_SIZE);
-       usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0OUT_IDX].ep, UDC_EP0OUT_MAX_PKT_SIZE);
-
-       /* remove ep0 in and out from the list.  They have own pointer */
-       list_del_init(&dev->ep[UDC_EP0IN_IDX].ep.ep_list);
-       list_del_init(&dev->ep[UDC_EP0OUT_IDX].ep.ep_list);
-
-       dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep;
-       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
-}
-
-/**
- * pch_udc_pcd_init() - This API initializes the driver structure
- * @dev:       Reference to the driver structure
- *
- * Return codes:
- *     0: Success
- */
-static int pch_udc_pcd_init(struct pch_udc_dev *dev)
-{
-       pch_udc_init(dev);
-       pch_udc_pcd_reinit(dev);
-       pch_vbus_gpio_init(dev, vbus_gpio_port);
-       return 0;
-}
-
-/**
- * init_dma_pools() - create dma pools during initialization
- * @pdev:      reference to struct pci_dev
- */
-static int init_dma_pools(struct pch_udc_dev *dev)
-{
-       struct pch_udc_stp_dma_desc     *td_stp;
-       struct pch_udc_data_dma_desc    *td_data;
-
-       /* DMA setup */
-       dev->data_requests = pci_pool_create("data_requests", dev->pdev,
-               sizeof(struct pch_udc_data_dma_desc), 0, 0);
-       if (!dev->data_requests) {
-               dev_err(&dev->pdev->dev, "%s: can't get request data pool\n",
-                       __func__);
-               return -ENOMEM;
-       }
-
-       /* dma desc for setup data */
-       dev->stp_requests = pci_pool_create("setup requests", dev->pdev,
-               sizeof(struct pch_udc_stp_dma_desc), 0, 0);
-       if (!dev->stp_requests) {
-               dev_err(&dev->pdev->dev, "%s: can't get setup request pool\n",
-                       __func__);
-               return -ENOMEM;
-       }
-       /* setup */
-       td_stp = pci_pool_alloc(dev->stp_requests, GFP_KERNEL,
-                               &dev->ep[UDC_EP0OUT_IDX].td_stp_phys);
-       if (!td_stp) {
-               dev_err(&dev->pdev->dev,
-                       "%s: can't allocate setup dma descriptor\n", __func__);
-               return -ENOMEM;
-       }
-       dev->ep[UDC_EP0OUT_IDX].td_stp = td_stp;
-
-       /* data: 0 packets !? */
-       td_data = pci_pool_alloc(dev->data_requests, GFP_KERNEL,
-                               &dev->ep[UDC_EP0OUT_IDX].td_data_phys);
-       if (!td_data) {
-               dev_err(&dev->pdev->dev,
-                       "%s: can't allocate data dma descriptor\n", __func__);
-               return -ENOMEM;
-       }
-       dev->ep[UDC_EP0OUT_IDX].td_data = td_data;
-       dev->ep[UDC_EP0IN_IDX].td_stp = NULL;
-       dev->ep[UDC_EP0IN_IDX].td_stp_phys = 0;
-       dev->ep[UDC_EP0IN_IDX].td_data = NULL;
-       dev->ep[UDC_EP0IN_IDX].td_data_phys = 0;
-
-       dev->ep0out_buf = kzalloc(UDC_EP0OUT_BUFF_SIZE * 4, GFP_KERNEL);
-       if (!dev->ep0out_buf)
-               return -ENOMEM;
-       dev->dma_addr = dma_map_single(&dev->pdev->dev, dev->ep0out_buf,
-                                      UDC_EP0OUT_BUFF_SIZE * 4,
-                                      DMA_FROM_DEVICE);
-       return 0;
-}
-
-static int pch_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct pch_udc_dev      *dev = to_pch_udc(g);
-
-       driver->driver.bus = NULL;
-       dev->driver = driver;
-
-       /* get ready for ep0 traffic */
-       pch_udc_setup_ep0(dev);
-
-       /* clear SD */
-       if ((pch_vbus_gpio_get_value(dev) != 0) || !dev->vbus_gpio.intr)
-               pch_udc_clear_disconnect(dev);
-
-       dev->connected = 1;
-       return 0;
-}
-
-static int pch_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct pch_udc_dev      *dev = to_pch_udc(g);
-
-       pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
-
-       /* Assures that there are no pending requests with this driver */
-       dev->driver = NULL;
-       dev->connected = 0;
-
-       /* set SD */
-       pch_udc_set_disconnect(dev);
-
-       return 0;
-}
-
-static void pch_udc_shutdown(struct pci_dev *pdev)
-{
-       struct pch_udc_dev *dev = pci_get_drvdata(pdev);
-
-       pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
-       pch_udc_disable_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL);
-
-       /* disable the pullup so the host will think we're gone */
-       pch_udc_set_disconnect(dev);
-}
-
-static void pch_udc_remove(struct pci_dev *pdev)
-{
-       struct pch_udc_dev      *dev = pci_get_drvdata(pdev);
-
-       usb_del_gadget_udc(&dev->gadget);
-
-       /* gadget driver must not be registered */
-       if (dev->driver)
-               dev_err(&pdev->dev,
-                       "%s: gadget driver still bound!!!\n", __func__);
-       /* dma pool cleanup */
-       if (dev->data_requests)
-               pci_pool_destroy(dev->data_requests);
-
-       if (dev->stp_requests) {
-               /* cleanup DMA desc's for ep0in */
-               if (dev->ep[UDC_EP0OUT_IDX].td_stp) {
-                       pci_pool_free(dev->stp_requests,
-                               dev->ep[UDC_EP0OUT_IDX].td_stp,
-                               dev->ep[UDC_EP0OUT_IDX].td_stp_phys);
-               }
-               if (dev->ep[UDC_EP0OUT_IDX].td_data) {
-                       pci_pool_free(dev->stp_requests,
-                               dev->ep[UDC_EP0OUT_IDX].td_data,
-                               dev->ep[UDC_EP0OUT_IDX].td_data_phys);
-               }
-               pci_pool_destroy(dev->stp_requests);
-       }
-
-       if (dev->dma_addr)
-               dma_unmap_single(&dev->pdev->dev, dev->dma_addr,
-                                UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE);
-       kfree(dev->ep0out_buf);
-
-       pch_vbus_gpio_free(dev);
-
-       pch_udc_exit(dev);
-
-       if (dev->irq_registered)
-               free_irq(pdev->irq, dev);
-       if (dev->base_addr)
-               iounmap(dev->base_addr);
-       if (dev->mem_region)
-               release_mem_region(dev->phys_addr,
-                                  pci_resource_len(pdev, PCH_UDC_PCI_BAR));
-       if (dev->active)
-               pci_disable_device(pdev);
-       kfree(dev);
-}
-
-#ifdef CONFIG_PM
-static int pch_udc_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       struct pch_udc_dev *dev = pci_get_drvdata(pdev);
-
-       pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
-       pch_udc_disable_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL);
-
-       pci_disable_device(pdev);
-       pci_enable_wake(pdev, PCI_D3hot, 0);
-
-       if (pci_save_state(pdev)) {
-               dev_err(&pdev->dev,
-                       "%s: could not save PCI config state\n", __func__);
-               return -ENOMEM;
-       }
-       pci_set_power_state(pdev, pci_choose_state(pdev, state));
-       return 0;
-}
-
-static int pch_udc_resume(struct pci_dev *pdev)
-{
-       int ret;
-
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-       ret = pci_enable_device(pdev);
-       if (ret) {
-               dev_err(&pdev->dev, "%s: pci_enable_device failed\n", __func__);
-               return ret;
-       }
-       pci_enable_wake(pdev, PCI_D3hot, 0);
-       return 0;
-}
-#else
-#define pch_udc_suspend        NULL
-#define pch_udc_resume NULL
-#endif /* CONFIG_PM */
-
-static int pch_udc_probe(struct pci_dev *pdev,
-                         const struct pci_device_id *id)
-{
-       unsigned long           resource;
-       unsigned long           len;
-       int                     retval;
-       struct pch_udc_dev      *dev;
-
-       /* init */
-       dev = kzalloc(sizeof *dev, GFP_KERNEL);
-       if (!dev) {
-               pr_err("%s: no memory for device structure\n", __func__);
-               return -ENOMEM;
-       }
-       /* pci setup */
-       if (pci_enable_device(pdev) < 0) {
-               kfree(dev);
-               pr_err("%s: pci_enable_device failed\n", __func__);
-               return -ENODEV;
-       }
-       dev->active = 1;
-       pci_set_drvdata(pdev, dev);
-
-       /* PCI resource allocation */
-       resource = pci_resource_start(pdev, 1);
-       len = pci_resource_len(pdev, 1);
-
-       if (!request_mem_region(resource, len, KBUILD_MODNAME)) {
-               dev_err(&pdev->dev, "%s: pci device used already\n", __func__);
-               retval = -EBUSY;
-               goto finished;
-       }
-       dev->phys_addr = resource;
-       dev->mem_region = 1;
-
-       dev->base_addr = ioremap_nocache(resource, len);
-       if (!dev->base_addr) {
-               pr_err("%s: device memory cannot be mapped\n", __func__);
-               retval = -ENOMEM;
-               goto finished;
-       }
-       if (!pdev->irq) {
-               dev_err(&pdev->dev, "%s: irq not set\n", __func__);
-               retval = -ENODEV;
-               goto finished;
-       }
-       /* initialize the hardware */
-       if (pch_udc_pcd_init(dev)) {
-               retval = -ENODEV;
-               goto finished;
-       }
-       if (request_irq(pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME,
-                       dev)) {
-               dev_err(&pdev->dev, "%s: request_irq(%d) fail\n", __func__,
-                       pdev->irq);
-               retval = -ENODEV;
-               goto finished;
-       }
-       dev->irq = pdev->irq;
-       dev->irq_registered = 1;
-
-       pci_set_master(pdev);
-       pci_try_set_mwi(pdev);
-
-       /* device struct setup */
-       spin_lock_init(&dev->lock);
-       dev->pdev = pdev;
-       dev->gadget.ops = &pch_udc_ops;
-
-       retval = init_dma_pools(dev);
-       if (retval)
-               goto finished;
-
-       dev->gadget.name = KBUILD_MODNAME;
-       dev->gadget.max_speed = USB_SPEED_HIGH;
-
-       /* Put the device in disconnected state till a driver is bound */
-       pch_udc_set_disconnect(dev);
-       retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
-                       gadget_release);
-       if (retval)
-               goto finished;
-       return 0;
-
-finished:
-       pch_udc_remove(pdev);
-       return retval;
-}
-
-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,
-               .class_mask = 0xffffffff,
-       },
-       {
-               PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7213_IOH_UDC),
-               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
-               .class_mask = 0xffffffff,
-       },
-       {
-               PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7831_IOH_UDC),
-               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
-               .class_mask = 0xffffffff,
-       },
-       { 0 },
-};
-
-MODULE_DEVICE_TABLE(pci, pch_udc_pcidev_id);
-
-static struct pci_driver pch_udc_driver = {
-       .name = KBUILD_MODNAME,
-       .id_table =     pch_udc_pcidev_id,
-       .probe =        pch_udc_probe,
-       .remove =       pch_udc_remove,
-       .suspend =      pch_udc_suspend,
-       .resume =       pch_udc_resume,
-       .shutdown =     pch_udc_shutdown,
-};
-
-module_pci_driver(pch_udc_driver);
-
-MODULE_DESCRIPTION("Intel EG20T USB Device Controller");
-MODULE_AUTHOR("LAPIS Semiconductor, <tomoya-linux@dsn.lapis-semi.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
deleted file mode 100644 (file)
index 251e4d5..0000000
+++ /dev/null
@@ -1,2284 +0,0 @@
-/*
- * Intel PXA25x and IXP4xx on-chip full speed USB device controllers
- *
- * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker)
- * Copyright (C) 2003 Robert Schwebel, Pengutronix
- * Copyright (C) 2003 Benedikt Spranger, Pengutronix
- * Copyright (C) 2003 David Brownell
- * Copyright (C) 2003 Joshua Wise
- *
- * 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.
- */
-
-/* #define VERBOSE_DEBUG */
-
-#include <linux/device.h>
-#include <linux/gpio.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/mm.h>
-#include <linux/platform_data/pxa2xx_udc.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/irq.h>
-#include <linux/clk.h>
-#include <linux/seq_file.h>
-#include <linux/debugfs.h>
-#include <linux/io.h>
-#include <linux/prefetch.h>
-
-#include <asm/byteorder.h>
-#include <asm/dma.h>
-#include <asm/mach-types.h>
-#include <asm/unaligned.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/otg.h>
-
-/*
- * This driver is PXA25x only.  Grab the right register definitions.
- */
-#ifdef CONFIG_ARCH_PXA
-#include <mach/pxa25x-udc.h>
-#include <mach/hardware.h>
-#endif
-
-#ifdef CONFIG_ARCH_LUBBOCK
-#include <mach/lubbock.h>
-#endif
-
-/*
- * This driver handles the USB Device Controller (UDC) in Intel's PXA 25x
- * series processors.  The UDC for the IXP 4xx series is very similar.
- * There are fifteen endpoints, in addition to ep0.
- *
- * Such controller drivers work with a gadget driver.  The gadget driver
- * returns descriptors, implements configuration and data protocols used
- * by the host to interact with this device, and allocates endpoints to
- * the different protocol interfaces.  The controller driver virtualizes
- * usb hardware so that the gadget drivers will be more portable.
- *
- * This UDC hardware wants to implement a bit too much USB protocol, so
- * it constrains the sorts of USB configuration change events that work.
- * The errata for these chips are misleading; some "fixed" bugs from
- * pxa250 a0/a1 b0/b1/b2 sure act like they're still there.
- *
- * Note that the UDC hardware supports DMA (except on IXP) but that's
- * not used here.  IN-DMA (to host) is simple enough, when the data is
- * suitably aligned (16 bytes) ... the network stack doesn't do that,
- * other software can.  OUT-DMA is buggy in most chip versions, as well
- * as poorly designed (data toggle not automatic).  So this driver won't
- * bother using DMA.  (Mostly-working IN-DMA support was available in
- * kernels before 2.6.23, but was never enabled or well tested.)
- */
-
-#define        DRIVER_VERSION  "30-June-2007"
-#define        DRIVER_DESC     "PXA 25x USB Device Controller driver"
-
-
-static const char driver_name [] = "pxa25x_udc";
-
-static const char ep0name [] = "ep0";
-
-
-#ifdef CONFIG_ARCH_IXP4XX
-
-/* cpu-specific register addresses are compiled in to this code */
-#ifdef CONFIG_ARCH_PXA
-#error "Can't configure both IXP and PXA"
-#endif
-
-/* IXP doesn't yet support <linux/clk.h> */
-#define clk_get(dev,name)      NULL
-#define clk_enable(clk)                do { } while (0)
-#define clk_disable(clk)       do { } while (0)
-#define clk_put(clk)           do { } while (0)
-
-#endif
-
-#include "pxa25x_udc.h"
-
-
-#ifdef CONFIG_USB_PXA25X_SMALL
-#define SIZE_STR       " (small)"
-#else
-#define SIZE_STR       ""
-#endif
-
-/* ---------------------------------------------------------------------------
- *     endpoint related parts of the api to the usb controller hardware,
- *     used by gadget driver; and the inner talker-to-hardware core.
- * ---------------------------------------------------------------------------
- */
-
-static void pxa25x_ep_fifo_flush (struct usb_ep *ep);
-static void nuke (struct pxa25x_ep *, int status);
-
-/* one GPIO should control a D+ pullup, so host sees this device (or not) */
-static void pullup_off(void)
-{
-       struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
-       int off_level = mach->gpio_pullup_inverted;
-
-       if (gpio_is_valid(mach->gpio_pullup))
-               gpio_set_value(mach->gpio_pullup, off_level);
-       else if (mach->udc_command)
-               mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
-}
-
-static void pullup_on(void)
-{
-       struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
-       int on_level = !mach->gpio_pullup_inverted;
-
-       if (gpio_is_valid(mach->gpio_pullup))
-               gpio_set_value(mach->gpio_pullup, on_level);
-       else if (mach->udc_command)
-               mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
-}
-
-static void pio_irq_enable(int bEndpointAddress)
-{
-        bEndpointAddress &= 0xf;
-        if (bEndpointAddress < 8)
-                UICR0 &= ~(1 << bEndpointAddress);
-        else {
-                bEndpointAddress -= 8;
-                UICR1 &= ~(1 << bEndpointAddress);
-       }
-}
-
-static void pio_irq_disable(int bEndpointAddress)
-{
-        bEndpointAddress &= 0xf;
-        if (bEndpointAddress < 8)
-                UICR0 |= 1 << bEndpointAddress;
-        else {
-                bEndpointAddress -= 8;
-                UICR1 |= 1 << bEndpointAddress;
-        }
-}
-
-/* The UDCCR reg contains mask and interrupt status bits,
- * so using '|=' isn't safe as it may ack an interrupt.
- */
-#define UDCCR_MASK_BITS         (UDCCR_REM | UDCCR_SRM | UDCCR_UDE)
-
-static inline void udc_set_mask_UDCCR(int mask)
-{
-       UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS);
-}
-
-static inline void udc_clear_mask_UDCCR(int mask)
-{
-       UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS);
-}
-
-static inline void udc_ack_int_UDCCR(int mask)
-{
-       /* udccr contains the bits we dont want to change */
-       __u32 udccr = UDCCR & UDCCR_MASK_BITS;
-
-       UDCCR = udccr | (mask & ~UDCCR_MASK_BITS);
-}
-
-/*
- * endpoint enable/disable
- *
- * we need to verify the descriptors used to enable endpoints.  since pxa25x
- * endpoint configurations are fixed, and are pretty much always enabled,
- * there's not a lot to manage here.
- *
- * because pxa25x can't selectively initialize bulk (or interrupt) endpoints,
- * (resetting endpoint halt and toggle), SET_INTERFACE is unusable except
- * for a single interface (with only the default altsetting) and for gadget
- * drivers that don't halt endpoints (not reset by set_interface).  that also
- * means that if you use ISO, you must violate the USB spec rule that all
- * iso endpoints must be in non-default altsettings.
- */
-static int pxa25x_ep_enable (struct usb_ep *_ep,
-               const struct usb_endpoint_descriptor *desc)
-{
-       struct pxa25x_ep        *ep;
-       struct pxa25x_udc       *dev;
-
-       ep = container_of (_ep, struct pxa25x_ep, ep);
-       if (!_ep || !desc || _ep->name == ep0name
-                       || desc->bDescriptorType != USB_DT_ENDPOINT
-                       || ep->bEndpointAddress != desc->bEndpointAddress
-                       || ep->fifo_size < usb_endpoint_maxp (desc)) {
-               DMSG("%s, bad ep or descriptor\n", __func__);
-               return -EINVAL;
-       }
-
-       /* xfer types must match, except that interrupt ~= bulk */
-       if (ep->bmAttributes != desc->bmAttributes
-                       && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
-                       && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
-               DMSG("%s, %s type mismatch\n", __func__, _ep->name);
-               return -EINVAL;
-       }
-
-       /* hardware _could_ do smaller, but driver doesn't */
-       if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
-                               && usb_endpoint_maxp (desc)
-                                               != BULK_FIFO_SIZE)
-                       || !desc->wMaxPacketSize) {
-               DMSG("%s, bad %s maxpacket\n", __func__, _ep->name);
-               return -ERANGE;
-       }
-
-       dev = ep->dev;
-       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
-               DMSG("%s, bogus device state\n", __func__);
-               return -ESHUTDOWN;
-       }
-
-       ep->ep.desc = desc;
-       ep->stopped = 0;
-       ep->pio_irqs = 0;
-       ep->ep.maxpacket = usb_endpoint_maxp (desc);
-
-       /* flush fifo (mostly for OUT buffers) */
-       pxa25x_ep_fifo_flush (_ep);
-
-       /* ... reset halt state too, if we could ... */
-
-       DBG(DBG_VERBOSE, "enabled %s\n", _ep->name);
-       return 0;
-}
-
-static int pxa25x_ep_disable (struct usb_ep *_ep)
-{
-       struct pxa25x_ep        *ep;
-       unsigned long           flags;
-
-       ep = container_of (_ep, struct pxa25x_ep, ep);
-       if (!_ep || !ep->ep.desc) {
-               DMSG("%s, %s not enabled\n", __func__,
-                       _ep ? ep->ep.name : NULL);
-               return -EINVAL;
-       }
-       local_irq_save(flags);
-
-       nuke (ep, -ESHUTDOWN);
-
-       /* flush fifo (mostly for IN buffers) */
-       pxa25x_ep_fifo_flush (_ep);
-
-       ep->ep.desc = NULL;
-       ep->stopped = 1;
-
-       local_irq_restore(flags);
-       DBG(DBG_VERBOSE, "%s disabled\n", _ep->name);
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* for the pxa25x, these can just wrap kmalloc/kfree.  gadget drivers
- * must still pass correctly initialized endpoints, since other controller
- * drivers may care about how it's currently set up (dma issues etc).
- */
-
-/*
- *     pxa25x_ep_alloc_request - allocate a request data structure
- */
-static struct usb_request *
-pxa25x_ep_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
-{
-       struct pxa25x_request *req;
-
-       req = kzalloc(sizeof(*req), gfp_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD (&req->queue);
-       return &req->req;
-}
-
-
-/*
- *     pxa25x_ep_free_request - deallocate a request data structure
- */
-static void
-pxa25x_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct pxa25x_request   *req;
-
-       req = container_of (_req, struct pxa25x_request, req);
-       WARN_ON(!list_empty (&req->queue));
-       kfree(req);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- *     done - retire a request; caller blocked irqs
- */
-static void done(struct pxa25x_ep *ep, struct pxa25x_request *req, int status)
-{
-       unsigned                stopped = ep->stopped;
-
-       list_del_init(&req->queue);
-
-       if (likely (req->req.status == -EINPROGRESS))
-               req->req.status = status;
-       else
-               status = req->req.status;
-
-       if (status && status != -ESHUTDOWN)
-               DBG(DBG_VERBOSE, "complete %s req %p stat %d len %u/%u\n",
-                       ep->ep.name, &req->req, status,
-                       req->req.actual, req->req.length);
-
-       /* don't modify queue heads during completion callback */
-       ep->stopped = 1;
-       req->req.complete(&ep->ep, &req->req);
-       ep->stopped = stopped;
-}
-
-
-static inline void ep0_idle (struct pxa25x_udc *dev)
-{
-       dev->ep0state = EP0_IDLE;
-}
-
-static int
-write_packet(volatile u32 *uddr, struct pxa25x_request *req, unsigned max)
-{
-       u8              *buf;
-       unsigned        length, count;
-
-       buf = req->req.buf + req->req.actual;
-       prefetch(buf);
-
-       /* how big will this packet be? */
-       length = min(req->req.length - req->req.actual, max);
-       req->req.actual += length;
-
-       count = length;
-       while (likely(count--))
-               *uddr = *buf++;
-
-       return length;
-}
-
-/*
- * write to an IN endpoint fifo, as many packets as possible.
- * irqs will use this to write the rest later.
- * caller guarantees at least one packet buffer is ready (or a zlp).
- */
-static int
-write_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
-{
-       unsigned                max;
-
-       max = usb_endpoint_maxp(ep->ep.desc);
-       do {
-               unsigned        count;
-               int             is_last, is_short;
-
-               count = write_packet(ep->reg_uddr, req, max);
-
-               /* last packet is usually short (or a zlp) */
-               if (unlikely (count != max))
-                       is_last = is_short = 1;
-               else {
-                       if (likely(req->req.length != req->req.actual)
-                                       || req->req.zero)
-                               is_last = 0;
-                       else
-                               is_last = 1;
-                       /* interrupt/iso maxpacket may not fill the fifo */
-                       is_short = unlikely (max < ep->fifo_size);
-               }
-
-               DBG(DBG_VERY_NOISY, "wrote %s %d bytes%s%s %d left %p\n",
-                       ep->ep.name, count,
-                       is_last ? "/L" : "", is_short ? "/S" : "",
-                       req->req.length - req->req.actual, req);
-
-               /* let loose that packet. maybe try writing another one,
-                * double buffering might work.  TSP, TPC, and TFS
-                * bit values are the same for all normal IN endpoints.
-                */
-               *ep->reg_udccs = UDCCS_BI_TPC;
-               if (is_short)
-                       *ep->reg_udccs = UDCCS_BI_TSP;
-
-               /* requests complete when all IN data is in the FIFO */
-               if (is_last) {
-                       done (ep, req, 0);
-                       if (list_empty(&ep->queue))
-                               pio_irq_disable (ep->bEndpointAddress);
-                       return 1;
-               }
-
-               // TODO experiment: how robust can fifo mode tweaking be?
-               // double buffering is off in the default fifo mode, which
-               // prevents TFS from being set here.
-
-       } while (*ep->reg_udccs & UDCCS_BI_TFS);
-       return 0;
-}
-
-/* caller asserts req->pending (ep0 irq status nyet cleared); starts
- * ep0 data stage.  these chips want very simple state transitions.
- */
-static inline
-void ep0start(struct pxa25x_udc *dev, u32 flags, const char *tag)
-{
-       UDCCS0 = flags|UDCCS0_SA|UDCCS0_OPR;
-       USIR0 = USIR0_IR0;
-       dev->req_pending = 0;
-       DBG(DBG_VERY_NOISY, "%s %s, %02x/%02x\n",
-               __func__, tag, UDCCS0, flags);
-}
-
-static int
-write_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
-{
-       unsigned        count;
-       int             is_short;
-
-       count = write_packet(&UDDR0, req, EP0_FIFO_SIZE);
-       ep->dev->stats.write.bytes += count;
-
-       /* last packet "must be" short (or a zlp) */
-       is_short = (count != EP0_FIFO_SIZE);
-
-       DBG(DBG_VERY_NOISY, "ep0in %d bytes %d left %p\n", count,
-               req->req.length - req->req.actual, req);
-
-       if (unlikely (is_short)) {
-               if (ep->dev->req_pending)
-                       ep0start(ep->dev, UDCCS0_IPR, "short IN");
-               else
-                       UDCCS0 = UDCCS0_IPR;
-
-               count = req->req.length;
-               done (ep, req, 0);
-               ep0_idle(ep->dev);
-#ifndef CONFIG_ARCH_IXP4XX
-#if 1
-               /* This seems to get rid of lost status irqs in some cases:
-                * host responds quickly, or next request involves config
-                * change automagic, or should have been hidden, or ...
-                *
-                * FIXME get rid of all udelays possible...
-                */
-               if (count >= EP0_FIFO_SIZE) {
-                       count = 100;
-                       do {
-                               if ((UDCCS0 & UDCCS0_OPR) != 0) {
-                                       /* clear OPR, generate ack */
-                                       UDCCS0 = UDCCS0_OPR;
-                                       break;
-                               }
-                               count--;
-                               udelay(1);
-                       } while (count);
-               }
-#endif
-#endif
-       } else if (ep->dev->req_pending)
-               ep0start(ep->dev, 0, "IN");
-       return is_short;
-}
-
-
-/*
- * read_fifo -  unload packet(s) from the fifo we use for usb OUT
- * transfers and put them into the request.  caller should have made
- * sure there's at least one packet ready.
- *
- * returns true if the request completed because of short packet or the
- * request buffer having filled (and maybe overran till end-of-packet).
- */
-static int
-read_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
-{
-       for (;;) {
-               u32             udccs;
-               u8              *buf;
-               unsigned        bufferspace, count, is_short;
-
-               /* make sure there's a packet in the FIFO.
-                * UDCCS_{BO,IO}_RPC are all the same bit value.
-                * UDCCS_{BO,IO}_RNE are all the same bit value.
-                */
-               udccs = *ep->reg_udccs;
-               if (unlikely ((udccs & UDCCS_BO_RPC) == 0))
-                       break;
-               buf = req->req.buf + req->req.actual;
-               prefetchw(buf);
-               bufferspace = req->req.length - req->req.actual;
-
-               /* read all bytes from this packet */
-               if (likely (udccs & UDCCS_BO_RNE)) {
-                       count = 1 + (0x0ff & *ep->reg_ubcr);
-                       req->req.actual += min (count, bufferspace);
-               } else /* zlp */
-                       count = 0;
-               is_short = (count < ep->ep.maxpacket);
-               DBG(DBG_VERY_NOISY, "read %s %02x, %d bytes%s req %p %d/%d\n",
-                       ep->ep.name, udccs, count,
-                       is_short ? "/S" : "",
-                       req, req->req.actual, req->req.length);
-               while (likely (count-- != 0)) {
-                       u8      byte = (u8) *ep->reg_uddr;
-
-                       if (unlikely (bufferspace == 0)) {
-                               /* this happens when the driver's buffer
-                                * is smaller than what the host sent.
-                                * discard the extra data.
-                                */
-                               if (req->req.status != -EOVERFLOW)
-                                       DMSG("%s overflow %d\n",
-                                               ep->ep.name, count);
-                               req->req.status = -EOVERFLOW;
-                       } else {
-                               *buf++ = byte;
-                               bufferspace--;
-                       }
-               }
-               *ep->reg_udccs =  UDCCS_BO_RPC;
-               /* RPC/RSP/RNE could now reflect the other packet buffer */
-
-               /* iso is one request per packet */
-               if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
-                       if (udccs & UDCCS_IO_ROF)
-                               req->req.status = -EHOSTUNREACH;
-                       /* more like "is_done" */
-                       is_short = 1;
-               }
-
-               /* completion */
-               if (is_short || req->req.actual == req->req.length) {
-                       done (ep, req, 0);
-                       if (list_empty(&ep->queue))
-                               pio_irq_disable (ep->bEndpointAddress);
-                       return 1;
-               }
-
-               /* finished that packet.  the next one may be waiting... */
-       }
-       return 0;
-}
-
-/*
- * special ep0 version of the above.  no UBCR0 or double buffering; status
- * handshaking is magic.  most device protocols don't need control-OUT.
- * CDC vendor commands (and RNDIS), mass storage CB/CBI, and some other
- * protocols do use them.
- */
-static int
-read_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
-{
-       u8              *buf, byte;
-       unsigned        bufferspace;
-
-       buf = req->req.buf + req->req.actual;
-       bufferspace = req->req.length - req->req.actual;
-
-       while (UDCCS0 & UDCCS0_RNE) {
-               byte = (u8) UDDR0;
-
-               if (unlikely (bufferspace == 0)) {
-                       /* this happens when the driver's buffer
-                        * is smaller than what the host sent.
-                        * discard the extra data.
-                        */
-                       if (req->req.status != -EOVERFLOW)
-                               DMSG("%s overflow\n", ep->ep.name);
-                       req->req.status = -EOVERFLOW;
-               } else {
-                       *buf++ = byte;
-                       req->req.actual++;
-                       bufferspace--;
-               }
-       }
-
-       UDCCS0 = UDCCS0_OPR | UDCCS0_IPR;
-
-       /* completion */
-       if (req->req.actual >= req->req.length)
-               return 1;
-
-       /* finished that packet.  the next one may be waiting... */
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
-{
-       struct pxa25x_request   *req;
-       struct pxa25x_ep        *ep;
-       struct pxa25x_udc       *dev;
-       unsigned long           flags;
-
-       req = container_of(_req, struct pxa25x_request, req);
-       if (unlikely (!_req || !_req->complete || !_req->buf
-                       || !list_empty(&req->queue))) {
-               DMSG("%s, bad params\n", __func__);
-               return -EINVAL;
-       }
-
-       ep = container_of(_ep, struct pxa25x_ep, ep);
-       if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) {
-               DMSG("%s, bad ep\n", __func__);
-               return -EINVAL;
-       }
-
-       dev = ep->dev;
-       if (unlikely (!dev->driver
-                       || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
-               DMSG("%s, bogus device state\n", __func__);
-               return -ESHUTDOWN;
-       }
-
-       /* iso is always one packet per request, that's the only way
-        * we can report per-packet status.  that also helps with dma.
-        */
-       if (unlikely (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
-                       && req->req.length > usb_endpoint_maxp(ep->ep.desc)))
-               return -EMSGSIZE;
-
-       DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n",
-               _ep->name, _req, _req->length, _req->buf);
-
-       local_irq_save(flags);
-
-       _req->status = -EINPROGRESS;
-       _req->actual = 0;
-
-       /* kickstart this i/o queue? */
-       if (list_empty(&ep->queue) && !ep->stopped) {
-               if (ep->ep.desc == NULL/* ep0 */) {
-                       unsigned        length = _req->length;
-
-                       switch (dev->ep0state) {
-                       case EP0_IN_DATA_PHASE:
-                               dev->stats.write.ops++;
-                               if (write_ep0_fifo(ep, req))
-                                       req = NULL;
-                               break;
-
-                       case EP0_OUT_DATA_PHASE:
-                               dev->stats.read.ops++;
-                               /* messy ... */
-                               if (dev->req_config) {
-                                       DBG(DBG_VERBOSE, "ep0 config ack%s\n",
-                                               dev->has_cfr ?  "" : " raced");
-                                       if (dev->has_cfr)
-                                               UDCCFR = UDCCFR_AREN|UDCCFR_ACM
-                                                       |UDCCFR_MB1;
-                                       done(ep, req, 0);
-                                       dev->ep0state = EP0_END_XFER;
-                                       local_irq_restore (flags);
-                                       return 0;
-                               }
-                               if (dev->req_pending)
-                                       ep0start(dev, UDCCS0_IPR, "OUT");
-                               if (length == 0 || ((UDCCS0 & UDCCS0_RNE) != 0
-                                               && read_ep0_fifo(ep, req))) {
-                                       ep0_idle(dev);
-                                       done(ep, req, 0);
-                                       req = NULL;
-                               }
-                               break;
-
-                       default:
-                               DMSG("ep0 i/o, odd state %d\n", dev->ep0state);
-                               local_irq_restore (flags);
-                               return -EL2HLT;
-                       }
-               /* can the FIFO can satisfy the request immediately? */
-               } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
-                       if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0
-                                       && write_fifo(ep, req))
-                               req = NULL;
-               } else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0
-                               && read_fifo(ep, req)) {
-                       req = NULL;
-               }
-
-               if (likely(req && ep->ep.desc))
-                       pio_irq_enable(ep->bEndpointAddress);
-       }
-
-       /* pio or dma irq handler advances the queue. */
-       if (likely(req != NULL))
-               list_add_tail(&req->queue, &ep->queue);
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-
-/*
- *     nuke - dequeue ALL requests
- */
-static void nuke(struct pxa25x_ep *ep, int status)
-{
-       struct pxa25x_request *req;
-
-       /* called with irqs blocked */
-       while (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next,
-                               struct pxa25x_request,
-                               queue);
-               done(ep, req, status);
-       }
-       if (ep->ep.desc)
-               pio_irq_disable (ep->bEndpointAddress);
-}
-
-
-/* dequeue JUST ONE request */
-static int pxa25x_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct pxa25x_ep        *ep;
-       struct pxa25x_request   *req;
-       unsigned long           flags;
-
-       ep = container_of(_ep, struct pxa25x_ep, ep);
-       if (!_ep || ep->ep.name == ep0name)
-               return -EINVAL;
-
-       local_irq_save(flags);
-
-       /* make sure it's actually queued on this endpoint */
-       list_for_each_entry (req, &ep->queue, queue) {
-               if (&req->req == _req)
-                       break;
-       }
-       if (&req->req != _req) {
-               local_irq_restore(flags);
-               return -EINVAL;
-       }
-
-       done(ep, req, -ECONNRESET);
-
-       local_irq_restore(flags);
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value)
-{
-       struct pxa25x_ep        *ep;
-       unsigned long           flags;
-
-       ep = container_of(_ep, struct pxa25x_ep, ep);
-       if (unlikely (!_ep
-                       || (!ep->ep.desc && ep->ep.name != ep0name))
-                       || ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
-               DMSG("%s, bad ep\n", __func__);
-               return -EINVAL;
-       }
-       if (value == 0) {
-               /* this path (reset toggle+halt) is needed to implement
-                * SET_INTERFACE on normal hardware.  but it can't be
-                * done from software on the PXA UDC, and the hardware
-                * forgets to do it as part of SET_INTERFACE automagic.
-                */
-               DMSG("only host can clear %s halt\n", _ep->name);
-               return -EROFS;
-       }
-
-       local_irq_save(flags);
-
-       if ((ep->bEndpointAddress & USB_DIR_IN) != 0
-                       && ((*ep->reg_udccs & UDCCS_BI_TFS) == 0
-                          || !list_empty(&ep->queue))) {
-               local_irq_restore(flags);
-               return -EAGAIN;
-       }
-
-       /* FST bit is the same for control, bulk in, bulk out, interrupt in */
-       *ep->reg_udccs = UDCCS_BI_FST|UDCCS_BI_FTF;
-
-       /* ep0 needs special care */
-       if (!ep->ep.desc) {
-               start_watchdog(ep->dev);
-               ep->dev->req_pending = 0;
-               ep->dev->ep0state = EP0_STALL;
-
-       /* and bulk/intr endpoints like dropping stalls too */
-       } else {
-               unsigned i;
-               for (i = 0; i < 1000; i += 20) {
-                       if (*ep->reg_udccs & UDCCS_BI_SST)
-                               break;
-                       udelay(20);
-               }
-       }
-       local_irq_restore(flags);
-
-       DBG(DBG_VERBOSE, "%s halt\n", _ep->name);
-       return 0;
-}
-
-static int pxa25x_ep_fifo_status(struct usb_ep *_ep)
-{
-       struct pxa25x_ep        *ep;
-
-       ep = container_of(_ep, struct pxa25x_ep, ep);
-       if (!_ep) {
-               DMSG("%s, bad ep\n", __func__);
-               return -ENODEV;
-       }
-       /* pxa can't report unclaimed bytes from IN fifos */
-       if ((ep->bEndpointAddress & USB_DIR_IN) != 0)
-               return -EOPNOTSUPP;
-       if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN
-                       || (*ep->reg_udccs & UDCCS_BO_RFS) == 0)
-               return 0;
-       else
-               return (*ep->reg_ubcr & 0xfff) + 1;
-}
-
-static void pxa25x_ep_fifo_flush(struct usb_ep *_ep)
-{
-       struct pxa25x_ep        *ep;
-
-       ep = container_of(_ep, struct pxa25x_ep, ep);
-       if (!_ep || ep->ep.name == ep0name || !list_empty(&ep->queue)) {
-               DMSG("%s, bad ep\n", __func__);
-               return;
-       }
-
-       /* toggle and halt bits stay unchanged */
-
-       /* for OUT, just read and discard the FIFO contents. */
-       if ((ep->bEndpointAddress & USB_DIR_IN) == 0) {
-               while (((*ep->reg_udccs) & UDCCS_BO_RNE) != 0)
-                       (void) *ep->reg_uddr;
-               return;
-       }
-
-       /* most IN status is the same, but ISO can't stall */
-       *ep->reg_udccs = UDCCS_BI_TPC|UDCCS_BI_FTF|UDCCS_BI_TUR
-               | (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
-                       ? 0 : UDCCS_BI_SST);
-}
-
-
-static struct usb_ep_ops pxa25x_ep_ops = {
-       .enable         = pxa25x_ep_enable,
-       .disable        = pxa25x_ep_disable,
-
-       .alloc_request  = pxa25x_ep_alloc_request,
-       .free_request   = pxa25x_ep_free_request,
-
-       .queue          = pxa25x_ep_queue,
-       .dequeue        = pxa25x_ep_dequeue,
-
-       .set_halt       = pxa25x_ep_set_halt,
-       .fifo_status    = pxa25x_ep_fifo_status,
-       .fifo_flush     = pxa25x_ep_fifo_flush,
-};
-
-
-/* ---------------------------------------------------------------------------
- *     device-scoped parts of the api to the usb controller hardware
- * ---------------------------------------------------------------------------
- */
-
-static int pxa25x_udc_get_frame(struct usb_gadget *_gadget)
-{
-       return ((UFNRH & 0x07) << 8) | (UFNRL & 0xff);
-}
-
-static int pxa25x_udc_wakeup(struct usb_gadget *_gadget)
-{
-       /* host may not have enabled remote wakeup */
-       if ((UDCCS0 & UDCCS0_DRWF) == 0)
-               return -EHOSTUNREACH;
-       udc_set_mask_UDCCR(UDCCR_RSM);
-       return 0;
-}
-
-static void stop_activity(struct pxa25x_udc *, struct usb_gadget_driver *);
-static void udc_enable (struct pxa25x_udc *);
-static void udc_disable(struct pxa25x_udc *);
-
-/* We disable the UDC -- and its 48 MHz clock -- whenever it's not
- * in active use.
- */
-static int pullup(struct pxa25x_udc *udc)
-{
-       int is_active = udc->vbus && udc->pullup && !udc->suspended;
-       DMSG("%s\n", is_active ? "active" : "inactive");
-       if (is_active) {
-               if (!udc->active) {
-                       udc->active = 1;
-                       /* Enable clock for USB device */
-                       clk_enable(udc->clk);
-                       udc_enable(udc);
-               }
-       } else {
-               if (udc->active) {
-                       if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
-                               DMSG("disconnect %s\n", udc->driver
-                                       ? udc->driver->driver.name
-                                       : "(no driver)");
-                               stop_activity(udc, udc->driver);
-                       }
-                       udc_disable(udc);
-                       /* Disable clock for USB device */
-                       clk_disable(udc->clk);
-                       udc->active = 0;
-               }
-
-       }
-       return 0;
-}
-
-/* VBUS reporting logically comes from a transceiver */
-static int pxa25x_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
-{
-       struct pxa25x_udc       *udc;
-
-       udc = container_of(_gadget, struct pxa25x_udc, gadget);
-       udc->vbus = is_active;
-       DMSG("vbus %s\n", is_active ? "supplied" : "inactive");
-       pullup(udc);
-       return 0;
-}
-
-/* drivers may have software control over D+ pullup */
-static int pxa25x_udc_pullup(struct usb_gadget *_gadget, int is_active)
-{
-       struct pxa25x_udc       *udc;
-
-       udc = container_of(_gadget, struct pxa25x_udc, gadget);
-
-       /* not all boards support pullup control */
-       if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
-               return -EOPNOTSUPP;
-
-       udc->pullup = (is_active != 0);
-       pullup(udc);
-       return 0;
-}
-
-/* boards may consume current from VBUS, up to 100-500mA based on config.
- * the 500uA suspend ceiling means that exclusively vbus-powered PXA designs
- * violate USB specs.
- */
-static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
-{
-       struct pxa25x_udc       *udc;
-
-       udc = container_of(_gadget, struct pxa25x_udc, gadget);
-
-       if (!IS_ERR_OR_NULL(udc->transceiver))
-               return usb_phy_set_power(udc->transceiver, mA);
-       return -EOPNOTSUPP;
-}
-
-static int pxa25x_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-static int pxa25x_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-
-static const struct usb_gadget_ops pxa25x_udc_ops = {
-       .get_frame      = pxa25x_udc_get_frame,
-       .wakeup         = pxa25x_udc_wakeup,
-       .vbus_session   = pxa25x_udc_vbus_session,
-       .pullup         = pxa25x_udc_pullup,
-       .vbus_draw      = pxa25x_udc_vbus_draw,
-       .udc_start      = pxa25x_udc_start,
-       .udc_stop       = pxa25x_udc_stop,
-};
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FS
-
-static int
-udc_seq_show(struct seq_file *m, void *_d)
-{
-       struct pxa25x_udc       *dev = m->private;
-       unsigned long           flags;
-       int                     i;
-       u32                     tmp;
-
-       local_irq_save(flags);
-
-       /* basic device status */
-       seq_printf(m, DRIVER_DESC "\n"
-               "%s version: %s\nGadget driver: %s\nHost %s\n\n",
-               driver_name, DRIVER_VERSION SIZE_STR "(pio)",
-               dev->driver ? dev->driver->driver.name : "(none)",
-               dev->gadget.speed == USB_SPEED_FULL ? "full speed" : "disconnected");
-
-       /* registers for device and ep0 */
-       seq_printf(m,
-               "uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
-               UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
-
-       tmp = UDCCR;
-       seq_printf(m,
-               "udccr %02X =%s%s%s%s%s%s%s%s\n", tmp,
-               (tmp & UDCCR_REM) ? " rem" : "",
-               (tmp & UDCCR_RSTIR) ? " rstir" : "",
-               (tmp & UDCCR_SRM) ? " srm" : "",
-               (tmp & UDCCR_SUSIR) ? " susir" : "",
-               (tmp & UDCCR_RESIR) ? " resir" : "",
-               (tmp & UDCCR_RSM) ? " rsm" : "",
-               (tmp & UDCCR_UDA) ? " uda" : "",
-               (tmp & UDCCR_UDE) ? " ude" : "");
-
-       tmp = UDCCS0;
-       seq_printf(m,
-               "udccs0 %02X =%s%s%s%s%s%s%s%s\n", tmp,
-               (tmp & UDCCS0_SA) ? " sa" : "",
-               (tmp & UDCCS0_RNE) ? " rne" : "",
-               (tmp & UDCCS0_FST) ? " fst" : "",
-               (tmp & UDCCS0_SST) ? " sst" : "",
-               (tmp & UDCCS0_DRWF) ? " dwrf" : "",
-               (tmp & UDCCS0_FTF) ? " ftf" : "",
-               (tmp & UDCCS0_IPR) ? " ipr" : "",
-               (tmp & UDCCS0_OPR) ? " opr" : "");
-
-       if (dev->has_cfr) {
-               tmp = UDCCFR;
-               seq_printf(m,
-                       "udccfr %02X =%s%s\n", tmp,
-                       (tmp & UDCCFR_AREN) ? " aren" : "",
-                       (tmp & UDCCFR_ACM) ? " acm" : "");
-       }
-
-       if (dev->gadget.speed != USB_SPEED_FULL || !dev->driver)
-               goto done;
-
-       seq_printf(m, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
-               dev->stats.write.bytes, dev->stats.write.ops,
-               dev->stats.read.bytes, dev->stats.read.ops,
-               dev->stats.irqs);
-
-       /* dump endpoint queues */
-       for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
-               struct pxa25x_ep        *ep = &dev->ep [i];
-               struct pxa25x_request   *req;
-
-               if (i != 0) {
-                       const struct usb_endpoint_descriptor    *desc;
-
-                       desc = ep->ep.desc;
-                       if (!desc)
-                               continue;
-                       tmp = *dev->ep [i].reg_udccs;
-                       seq_printf(m,
-                               "%s max %d %s udccs %02x irqs %lu\n",
-                               ep->ep.name, usb_endpoint_maxp(desc),
-                               "pio", tmp, ep->pio_irqs);
-                       /* TODO translate all five groups of udccs bits! */
-
-               } else /* ep0 should only have one transfer queued */
-                       seq_printf(m, "ep0 max 16 pio irqs %lu\n",
-                               ep->pio_irqs);
-
-               if (list_empty(&ep->queue)) {
-                       seq_printf(m, "\t(nothing queued)\n");
-                       continue;
-               }
-               list_for_each_entry(req, &ep->queue, queue) {
-                       seq_printf(m,
-                                       "\treq %p len %d/%d buf %p\n",
-                                       &req->req, req->req.actual,
-                                       req->req.length, req->req.buf);
-               }
-       }
-
-done:
-       local_irq_restore(flags);
-       return 0;
-}
-
-static int
-udc_debugfs_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, udc_seq_show, inode->i_private);
-}
-
-static const struct file_operations debug_fops = {
-       .open           = udc_debugfs_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .owner          = THIS_MODULE,
-};
-
-#define create_debug_files(dev) \
-       do { \
-               dev->debugfs_udc = debugfs_create_file(dev->gadget.name, \
-                       S_IRUGO, NULL, dev, &debug_fops); \
-       } while (0)
-#define remove_debug_files(dev) \
-       do { \
-               if (dev->debugfs_udc) \
-                       debugfs_remove(dev->debugfs_udc); \
-       } while (0)
-
-#else  /* !CONFIG_USB_GADGET_DEBUG_FILES */
-
-#define create_debug_files(dev) do {} while (0)
-#define remove_debug_files(dev) do {} while (0)
-
-#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
-
-/*-------------------------------------------------------------------------*/
-
-/*
- *     udc_disable - disable USB device controller
- */
-static void udc_disable(struct pxa25x_udc *dev)
-{
-       /* block all irqs */
-       udc_set_mask_UDCCR(UDCCR_SRM|UDCCR_REM);
-       UICR0 = UICR1 = 0xff;
-       UFNRH = UFNRH_SIM;
-
-       /* if hardware supports it, disconnect from usb */
-       pullup_off();
-
-       udc_clear_mask_UDCCR(UDCCR_UDE);
-
-       ep0_idle (dev);
-       dev->gadget.speed = USB_SPEED_UNKNOWN;
-}
-
-
-/*
- *     udc_reinit - initialize software state
- */
-static void udc_reinit(struct pxa25x_udc *dev)
-{
-       u32     i;
-
-       /* device/ep0 records init */
-       INIT_LIST_HEAD (&dev->gadget.ep_list);
-       INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
-       dev->ep0state = EP0_IDLE;
-
-       /* basic endpoint records init */
-       for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
-               struct pxa25x_ep *ep = &dev->ep[i];
-
-               if (i != 0)
-                       list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
-
-               ep->ep.desc = NULL;
-               ep->stopped = 0;
-               INIT_LIST_HEAD (&ep->queue);
-               ep->pio_irqs = 0;
-               usb_ep_set_maxpacket_limit(&ep->ep, ep->ep.maxpacket);
-       }
-
-       /* the rest was statically initialized, and is read-only */
-}
-
-/* until it's enabled, this UDC should be completely invisible
- * to any USB host.
- */
-static void udc_enable (struct pxa25x_udc *dev)
-{
-       udc_clear_mask_UDCCR(UDCCR_UDE);
-
-       /* try to clear these bits before we enable the udc */
-       udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR);
-
-       ep0_idle(dev);
-       dev->gadget.speed = USB_SPEED_UNKNOWN;
-       dev->stats.irqs = 0;
-
-       /*
-        * sequence taken from chapter 12.5.10, PXA250 AppProcDevManual:
-        * - enable UDC
-        * - if RESET is already in progress, ack interrupt
-        * - unmask reset interrupt
-        */
-       udc_set_mask_UDCCR(UDCCR_UDE);
-       if (!(UDCCR & UDCCR_UDA))
-               udc_ack_int_UDCCR(UDCCR_RSTIR);
-
-       if (dev->has_cfr /* UDC_RES2 is defined */) {
-               /* pxa255 (a0+) can avoid a set_config race that could
-                * prevent gadget drivers from configuring correctly
-                */
-               UDCCFR = UDCCFR_ACM | UDCCFR_MB1;
-       } else {
-               /* "USB test mode" for pxa250 errata 40-42 (stepping a0, a1)
-                * which could result in missing packets and interrupts.
-                * supposedly one bit per endpoint, controlling whether it
-                * double buffers or not; ACM/AREN bits fit into the holes.
-                * zero bits (like USIR0_IRx) disable double buffering.
-                */
-               UDC_RES1 = 0x00;
-               UDC_RES2 = 0x00;
-       }
-
-       /* enable suspend/resume and reset irqs */
-       udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
-
-       /* enable ep0 irqs */
-       UICR0 &= ~UICR0_IM0;
-
-       /* if hardware supports it, pullup D+ and wait for reset */
-       pullup_on();
-}
-
-
-/* when a driver is successfully registered, it will receive
- * control requests including set_configuration(), which enables
- * non-control requests.  then usb traffic follows until a
- * disconnect is reported.  then a host may connect again, or
- * the driver might get unbound.
- */
-static int pxa25x_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct pxa25x_udc       *dev = to_pxa25x(g);
-       int                     retval;
-
-       /* first hook up the driver ... */
-       dev->driver = driver;
-       dev->pullup = 1;
-
-       /* ... then enable host detection and ep0; and we're ready
-        * for set_configuration as well as eventual disconnect.
-        */
-       /* connect to bus through transceiver */
-       if (!IS_ERR_OR_NULL(dev->transceiver)) {
-               retval = otg_set_peripheral(dev->transceiver->otg,
-                                               &dev->gadget);
-               if (retval)
-                       goto bind_fail;
-       }
-
-       pullup(dev);
-       dump_state(dev);
-       return 0;
-bind_fail:
-       return retval;
-}
-
-static void
-stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
-{
-       int i;
-
-       /* don't disconnect drivers more than once */
-       if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-               driver = NULL;
-       dev->gadget.speed = USB_SPEED_UNKNOWN;
-
-       /* prevent new request submissions, kill any outstanding requests  */
-       for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
-               struct pxa25x_ep *ep = &dev->ep[i];
-
-               ep->stopped = 1;
-               nuke(ep, -ESHUTDOWN);
-       }
-       del_timer_sync(&dev->timer);
-
-       /* report disconnect; the driver is already quiesced */
-       if (driver)
-               driver->disconnect(&dev->gadget);
-
-       /* re-init driver-visible data structures */
-       udc_reinit(dev);
-}
-
-static int pxa25x_udc_stop(struct usb_gadget*g,
-               struct usb_gadget_driver *driver)
-{
-       struct pxa25x_udc       *dev = to_pxa25x(g);
-
-       local_irq_disable();
-       dev->pullup = 0;
-       pullup(dev);
-       stop_activity(dev, driver);
-       local_irq_enable();
-
-       if (!IS_ERR_OR_NULL(dev->transceiver))
-               (void) otg_set_peripheral(dev->transceiver->otg, NULL);
-
-       dev->driver = NULL;
-
-       dump_state(dev);
-
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_ARCH_LUBBOCK
-
-/* Lubbock has separate connect and disconnect irqs.  More typical designs
- * use one GPIO as the VBUS IRQ, and another to control the D+ pullup.
- */
-
-static irqreturn_t
-lubbock_vbus_irq(int irq, void *_dev)
-{
-       struct pxa25x_udc       *dev = _dev;
-       int                     vbus;
-
-       dev->stats.irqs++;
-       switch (irq) {
-       case LUBBOCK_USB_IRQ:
-               vbus = 1;
-               disable_irq(LUBBOCK_USB_IRQ);
-               enable_irq(LUBBOCK_USB_DISC_IRQ);
-               break;
-       case LUBBOCK_USB_DISC_IRQ:
-               vbus = 0;
-               disable_irq(LUBBOCK_USB_DISC_IRQ);
-               enable_irq(LUBBOCK_USB_IRQ);
-               break;
-       default:
-               return IRQ_NONE;
-       }
-
-       pxa25x_udc_vbus_session(&dev->gadget, vbus);
-       return IRQ_HANDLED;
-}
-
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-static inline void clear_ep_state (struct pxa25x_udc *dev)
-{
-       unsigned i;
-
-       /* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
-        * fifos, and pending transactions mustn't be continued in any case.
-        */
-       for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++)
-               nuke(&dev->ep[i], -ECONNABORTED);
-}
-
-static void udc_watchdog(unsigned long _dev)
-{
-       struct pxa25x_udc       *dev = (void *)_dev;
-
-       local_irq_disable();
-       if (dev->ep0state == EP0_STALL
-                       && (UDCCS0 & UDCCS0_FST) == 0
-                       && (UDCCS0 & UDCCS0_SST) == 0) {
-               UDCCS0 = UDCCS0_FST|UDCCS0_FTF;
-               DBG(DBG_VERBOSE, "ep0 re-stall\n");
-               start_watchdog(dev);
-       }
-       local_irq_enable();
-}
-
-static void handle_ep0 (struct pxa25x_udc *dev)
-{
-       u32                     udccs0 = UDCCS0;
-       struct pxa25x_ep        *ep = &dev->ep [0];
-       struct pxa25x_request   *req;
-       union {
-               struct usb_ctrlrequest  r;
-               u8                      raw [8];
-               u32                     word [2];
-       } u;
-
-       if (list_empty(&ep->queue))
-               req = NULL;
-       else
-               req = list_entry(ep->queue.next, struct pxa25x_request, queue);
-
-       /* clear stall status */
-       if (udccs0 & UDCCS0_SST) {
-               nuke(ep, -EPIPE);
-               UDCCS0 = UDCCS0_SST;
-               del_timer(&dev->timer);
-               ep0_idle(dev);
-       }
-
-       /* previous request unfinished?  non-error iff back-to-back ... */
-       if ((udccs0 & UDCCS0_SA) != 0 && dev->ep0state != EP0_IDLE) {
-               nuke(ep, 0);
-               del_timer(&dev->timer);
-               ep0_idle(dev);
-       }
-
-       switch (dev->ep0state) {
-       case EP0_IDLE:
-               /* late-breaking status? */
-               udccs0 = UDCCS0;
-
-               /* start control request? */
-               if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE))
-                               == (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE))) {
-                       int i;
-
-                       nuke (ep, -EPROTO);
-
-                       /* read SETUP packet */
-                       for (i = 0; i < 8; i++) {
-                               if (unlikely(!(UDCCS0 & UDCCS0_RNE))) {
-bad_setup:
-                                       DMSG("SETUP %d!\n", i);
-                                       goto stall;
-                               }
-                               u.raw [i] = (u8) UDDR0;
-                       }
-                       if (unlikely((UDCCS0 & UDCCS0_RNE) != 0))
-                               goto bad_setup;
-
-got_setup:
-                       DBG(DBG_VERBOSE, "SETUP %02x.%02x v%04x i%04x l%04x\n",
-                               u.r.bRequestType, u.r.bRequest,
-                               le16_to_cpu(u.r.wValue),
-                               le16_to_cpu(u.r.wIndex),
-                               le16_to_cpu(u.r.wLength));
-
-                       /* cope with automagic for some standard requests. */
-                       dev->req_std = (u.r.bRequestType & USB_TYPE_MASK)
-                                               == USB_TYPE_STANDARD;
-                       dev->req_config = 0;
-                       dev->req_pending = 1;
-                       switch (u.r.bRequest) {
-                       /* hardware restricts gadget drivers here! */
-                       case USB_REQ_SET_CONFIGURATION:
-                               if (u.r.bRequestType == USB_RECIP_DEVICE) {
-                                       /* reflect hardware's automagic
-                                        * up to the gadget driver.
-                                        */
-config_change:
-                                       dev->req_config = 1;
-                                       clear_ep_state(dev);
-                                       /* if !has_cfr, there's no synch
-                                        * else use AREN (later) not SA|OPR
-                                        * USIR0_IR0 acts edge sensitive
-                                        */
-                               }
-                               break;
-                       /* ... and here, even more ... */
-                       case USB_REQ_SET_INTERFACE:
-                               if (u.r.bRequestType == USB_RECIP_INTERFACE) {
-                                       /* udc hardware is broken by design:
-                                        *  - altsetting may only be zero;
-                                        *  - hw resets all interfaces' eps;
-                                        *  - ep reset doesn't include halt(?).
-                                        */
-                                       DMSG("broken set_interface (%d/%d)\n",
-                                               le16_to_cpu(u.r.wIndex),
-                                               le16_to_cpu(u.r.wValue));
-                                       goto config_change;
-                               }
-                               break;
-                       /* hardware was supposed to hide this */
-                       case USB_REQ_SET_ADDRESS:
-                               if (u.r.bRequestType == USB_RECIP_DEVICE) {
-                                       ep0start(dev, 0, "address");
-                                       return;
-                               }
-                               break;
-                       }
-
-                       if (u.r.bRequestType & USB_DIR_IN)
-                               dev->ep0state = EP0_IN_DATA_PHASE;
-                       else
-                               dev->ep0state = EP0_OUT_DATA_PHASE;
-
-                       i = dev->driver->setup(&dev->gadget, &u.r);
-                       if (i < 0) {
-                               /* hardware automagic preventing STALL... */
-                               if (dev->req_config) {
-                                       /* hardware sometimes neglects to tell
-                                        * tell us about config change events,
-                                        * so later ones may fail...
-                                        */
-                                       WARNING("config change %02x fail %d?\n",
-                                               u.r.bRequest, i);
-                                       return;
-                                       /* TODO experiment:  if has_cfr,
-                                        * hardware didn't ACK; maybe we
-                                        * could actually STALL!
-                                        */
-                               }
-                               DBG(DBG_VERBOSE, "protocol STALL, "
-                                       "%02x err %d\n", UDCCS0, i);
-stall:
-                               /* the watchdog timer helps deal with cases
-                                * where udc seems to clear FST wrongly, and
-                                * then NAKs instead of STALLing.
-                                */
-                               ep0start(dev, UDCCS0_FST|UDCCS0_FTF, "stall");
-                               start_watchdog(dev);
-                               dev->ep0state = EP0_STALL;
-
-                       /* deferred i/o == no response yet */
-                       } else if (dev->req_pending) {
-                               if (likely(dev->ep0state == EP0_IN_DATA_PHASE
-                                               || dev->req_std || u.r.wLength))
-                                       ep0start(dev, 0, "defer");
-                               else
-                                       ep0start(dev, UDCCS0_IPR, "defer/IPR");
-                       }
-
-                       /* expect at least one data or status stage irq */
-                       return;
-
-               } else if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA))
-                               == (UDCCS0_OPR|UDCCS0_SA))) {
-                       unsigned i;
-
-                       /* pxa210/250 erratum 131 for B0/B1 says RNE lies.
-                        * still observed on a pxa255 a0.
-                        */
-                       DBG(DBG_VERBOSE, "e131\n");
-                       nuke(ep, -EPROTO);
-
-                       /* read SETUP data, but don't trust it too much */
-                       for (i = 0; i < 8; i++)
-                               u.raw [i] = (u8) UDDR0;
-                       if ((u.r.bRequestType & USB_RECIP_MASK)
-                                       > USB_RECIP_OTHER)
-                               goto stall;
-                       if (u.word [0] == 0 && u.word [1] == 0)
-                               goto stall;
-                       goto got_setup;
-               } else {
-                       /* some random early IRQ:
-                        * - we acked FST
-                        * - IPR cleared
-                        * - OPR got set, without SA (likely status stage)
-                        */
-                       UDCCS0 = udccs0 & (UDCCS0_SA|UDCCS0_OPR);
-               }
-               break;
-       case EP0_IN_DATA_PHASE:                 /* GET_DESCRIPTOR etc */
-               if (udccs0 & UDCCS0_OPR) {
-                       UDCCS0 = UDCCS0_OPR|UDCCS0_FTF;
-                       DBG(DBG_VERBOSE, "ep0in premature status\n");
-                       if (req)
-                               done(ep, req, 0);
-                       ep0_idle(dev);
-               } else /* irq was IPR clearing */ {
-                       if (req) {
-                               /* this IN packet might finish the request */
-                               (void) write_ep0_fifo(ep, req);
-                       } /* else IN token before response was written */
-               }
-               break;
-       case EP0_OUT_DATA_PHASE:                /* SET_DESCRIPTOR etc */
-               if (udccs0 & UDCCS0_OPR) {
-                       if (req) {
-                               /* this OUT packet might finish the request */
-                               if (read_ep0_fifo(ep, req))
-                                       done(ep, req, 0);
-                               /* else more OUT packets expected */
-                       } /* else OUT token before read was issued */
-               } else /* irq was IPR clearing */ {
-                       DBG(DBG_VERBOSE, "ep0out premature status\n");
-                       if (req)
-                               done(ep, req, 0);
-                       ep0_idle(dev);
-               }
-               break;
-       case EP0_END_XFER:
-               if (req)
-                       done(ep, req, 0);
-               /* ack control-IN status (maybe in-zlp was skipped)
-                * also appears after some config change events.
-                */
-               if (udccs0 & UDCCS0_OPR)
-                       UDCCS0 = UDCCS0_OPR;
-               ep0_idle(dev);
-               break;
-       case EP0_STALL:
-               UDCCS0 = UDCCS0_FST;
-               break;
-       }
-       USIR0 = USIR0_IR0;
-}
-
-static void handle_ep(struct pxa25x_ep *ep)
-{
-       struct pxa25x_request   *req;
-       int                     is_in = ep->bEndpointAddress & USB_DIR_IN;
-       int                     completed;
-       u32                     udccs, tmp;
-
-       do {
-               completed = 0;
-               if (likely (!list_empty(&ep->queue)))
-                       req = list_entry(ep->queue.next,
-                                       struct pxa25x_request, queue);
-               else
-                       req = NULL;
-
-               // TODO check FST handling
-
-               udccs = *ep->reg_udccs;
-               if (unlikely(is_in)) {  /* irq from TPC, SST, or (ISO) TUR */
-                       tmp = UDCCS_BI_TUR;
-                       if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK))
-                               tmp |= UDCCS_BI_SST;
-                       tmp &= udccs;
-                       if (likely (tmp))
-                               *ep->reg_udccs = tmp;
-                       if (req && likely ((udccs & UDCCS_BI_TFS) != 0))
-                               completed = write_fifo(ep, req);
-
-               } else {        /* irq from RPC (or for ISO, ROF) */
-                       if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK))
-                               tmp = UDCCS_BO_SST | UDCCS_BO_DME;
-                       else
-                               tmp = UDCCS_IO_ROF | UDCCS_IO_DME;
-                       tmp &= udccs;
-                       if (likely(tmp))
-                               *ep->reg_udccs = tmp;
-
-                       /* fifos can hold packets, ready for reading... */
-                       if (likely(req)) {
-                               completed = read_fifo(ep, req);
-                       } else
-                               pio_irq_disable (ep->bEndpointAddress);
-               }
-               ep->pio_irqs++;
-       } while (completed);
-}
-
-/*
- *     pxa25x_udc_irq - interrupt handler
- *
- * avoid delays in ep0 processing. the control handshaking isn't always
- * under software control (pxa250c0 and the pxa255 are better), and delays
- * could cause usb protocol errors.
- */
-static irqreturn_t
-pxa25x_udc_irq(int irq, void *_dev)
-{
-       struct pxa25x_udc       *dev = _dev;
-       int                     handled;
-
-       dev->stats.irqs++;
-       do {
-               u32             udccr = UDCCR;
-
-               handled = 0;
-
-               /* SUSpend Interrupt Request */
-               if (unlikely(udccr & UDCCR_SUSIR)) {
-                       udc_ack_int_UDCCR(UDCCR_SUSIR);
-                       handled = 1;
-                       DBG(DBG_VERBOSE, "USB suspend\n");
-
-                       if (dev->gadget.speed != USB_SPEED_UNKNOWN
-                                       && dev->driver
-                                       && dev->driver->suspend)
-                               dev->driver->suspend(&dev->gadget);
-                       ep0_idle (dev);
-               }
-
-               /* RESume Interrupt Request */
-               if (unlikely(udccr & UDCCR_RESIR)) {
-                       udc_ack_int_UDCCR(UDCCR_RESIR);
-                       handled = 1;
-                       DBG(DBG_VERBOSE, "USB resume\n");
-
-                       if (dev->gadget.speed != USB_SPEED_UNKNOWN
-                                       && dev->driver
-                                       && dev->driver->resume)
-                               dev->driver->resume(&dev->gadget);
-               }
-
-               /* ReSeT Interrupt Request - USB reset */
-               if (unlikely(udccr & UDCCR_RSTIR)) {
-                       udc_ack_int_UDCCR(UDCCR_RSTIR);
-                       handled = 1;
-
-                       if ((UDCCR & UDCCR_UDA) == 0) {
-                               DBG(DBG_VERBOSE, "USB reset start\n");
-
-                               /* reset driver and endpoints,
-                                * in case that's not yet done
-                                */
-                               stop_activity (dev, dev->driver);
-
-                       } else {
-                               DBG(DBG_VERBOSE, "USB reset end\n");
-                               dev->gadget.speed = USB_SPEED_FULL;
-                               memset(&dev->stats, 0, sizeof dev->stats);
-                               /* driver and endpoints are still reset */
-                       }
-
-               } else {
-                       u32     usir0 = USIR0 & ~UICR0;
-                       u32     usir1 = USIR1 & ~UICR1;
-                       int     i;
-
-                       if (unlikely (!usir0 && !usir1))
-                               continue;
-
-                       DBG(DBG_VERY_NOISY, "irq %02x.%02x\n", usir1, usir0);
-
-                       /* control traffic */
-                       if (usir0 & USIR0_IR0) {
-                               dev->ep[0].pio_irqs++;
-                               handle_ep0(dev);
-                               handled = 1;
-                       }
-
-                       /* endpoint data transfers */
-                       for (i = 0; i < 8; i++) {
-                               u32     tmp = 1 << i;
-
-                               if (i && (usir0 & tmp)) {
-                                       handle_ep(&dev->ep[i]);
-                                       USIR0 |= tmp;
-                                       handled = 1;
-                               }
-#ifndef        CONFIG_USB_PXA25X_SMALL
-                               if (usir1 & tmp) {
-                                       handle_ep(&dev->ep[i+8]);
-                                       USIR1 |= tmp;
-                                       handled = 1;
-                               }
-#endif
-                       }
-               }
-
-               /* we could also ask for 1 msec SOF (SIR) interrupts */
-
-       } while (handled);
-       return IRQ_HANDLED;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void nop_release (struct device *dev)
-{
-       DMSG("%s %s\n", __func__, dev_name(dev));
-}
-
-/* this uses load-time allocation and initialization (instead of
- * doing it at run-time) to save code, eliminate fault paths, and
- * be more obviously correct.
- */
-static struct pxa25x_udc memory = {
-       .gadget = {
-               .ops            = &pxa25x_udc_ops,
-               .ep0            = &memory.ep[0].ep,
-               .name           = driver_name,
-               .dev = {
-                       .init_name      = "gadget",
-                       .release        = nop_release,
-               },
-       },
-
-       /* control endpoint */
-       .ep[0] = {
-               .ep = {
-                       .name           = ep0name,
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = EP0_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .reg_udccs      = &UDCCS0,
-               .reg_uddr       = &UDDR0,
-       },
-
-       /* first group of endpoints */
-       .ep[1] = {
-               .ep = {
-                       .name           = "ep1in-bulk",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = BULK_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = BULK_FIFO_SIZE,
-               .bEndpointAddress = USB_DIR_IN | 1,
-               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-               .reg_udccs      = &UDCCS1,
-               .reg_uddr       = &UDDR1,
-       },
-       .ep[2] = {
-               .ep = {
-                       .name           = "ep2out-bulk",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = BULK_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = BULK_FIFO_SIZE,
-               .bEndpointAddress = 2,
-               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-               .reg_udccs      = &UDCCS2,
-               .reg_ubcr       = &UBCR2,
-               .reg_uddr       = &UDDR2,
-       },
-#ifndef CONFIG_USB_PXA25X_SMALL
-       .ep[3] = {
-               .ep = {
-                       .name           = "ep3in-iso",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = ISO_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = ISO_FIFO_SIZE,
-               .bEndpointAddress = USB_DIR_IN | 3,
-               .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
-               .reg_udccs      = &UDCCS3,
-               .reg_uddr       = &UDDR3,
-       },
-       .ep[4] = {
-               .ep = {
-                       .name           = "ep4out-iso",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = ISO_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = ISO_FIFO_SIZE,
-               .bEndpointAddress = 4,
-               .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
-               .reg_udccs      = &UDCCS4,
-               .reg_ubcr       = &UBCR4,
-               .reg_uddr       = &UDDR4,
-       },
-       .ep[5] = {
-               .ep = {
-                       .name           = "ep5in-int",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = INT_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = INT_FIFO_SIZE,
-               .bEndpointAddress = USB_DIR_IN | 5,
-               .bmAttributes   = USB_ENDPOINT_XFER_INT,
-               .reg_udccs      = &UDCCS5,
-               .reg_uddr       = &UDDR5,
-       },
-
-       /* second group of endpoints */
-       .ep[6] = {
-               .ep = {
-                       .name           = "ep6in-bulk",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = BULK_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = BULK_FIFO_SIZE,
-               .bEndpointAddress = USB_DIR_IN | 6,
-               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-               .reg_udccs      = &UDCCS6,
-               .reg_uddr       = &UDDR6,
-       },
-       .ep[7] = {
-               .ep = {
-                       .name           = "ep7out-bulk",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = BULK_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = BULK_FIFO_SIZE,
-               .bEndpointAddress = 7,
-               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-               .reg_udccs      = &UDCCS7,
-               .reg_ubcr       = &UBCR7,
-               .reg_uddr       = &UDDR7,
-       },
-       .ep[8] = {
-               .ep = {
-                       .name           = "ep8in-iso",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = ISO_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = ISO_FIFO_SIZE,
-               .bEndpointAddress = USB_DIR_IN | 8,
-               .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
-               .reg_udccs      = &UDCCS8,
-               .reg_uddr       = &UDDR8,
-       },
-       .ep[9] = {
-               .ep = {
-                       .name           = "ep9out-iso",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = ISO_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = ISO_FIFO_SIZE,
-               .bEndpointAddress = 9,
-               .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
-               .reg_udccs      = &UDCCS9,
-               .reg_ubcr       = &UBCR9,
-               .reg_uddr       = &UDDR9,
-       },
-       .ep[10] = {
-               .ep = {
-                       .name           = "ep10in-int",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = INT_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = INT_FIFO_SIZE,
-               .bEndpointAddress = USB_DIR_IN | 10,
-               .bmAttributes   = USB_ENDPOINT_XFER_INT,
-               .reg_udccs      = &UDCCS10,
-               .reg_uddr       = &UDDR10,
-       },
-
-       /* third group of endpoints */
-       .ep[11] = {
-               .ep = {
-                       .name           = "ep11in-bulk",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = BULK_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = BULK_FIFO_SIZE,
-               .bEndpointAddress = USB_DIR_IN | 11,
-               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-               .reg_udccs      = &UDCCS11,
-               .reg_uddr       = &UDDR11,
-       },
-       .ep[12] = {
-               .ep = {
-                       .name           = "ep12out-bulk",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = BULK_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = BULK_FIFO_SIZE,
-               .bEndpointAddress = 12,
-               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-               .reg_udccs      = &UDCCS12,
-               .reg_ubcr       = &UBCR12,
-               .reg_uddr       = &UDDR12,
-       },
-       .ep[13] = {
-               .ep = {
-                       .name           = "ep13in-iso",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = ISO_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = ISO_FIFO_SIZE,
-               .bEndpointAddress = USB_DIR_IN | 13,
-               .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
-               .reg_udccs      = &UDCCS13,
-               .reg_uddr       = &UDDR13,
-       },
-       .ep[14] = {
-               .ep = {
-                       .name           = "ep14out-iso",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = ISO_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = ISO_FIFO_SIZE,
-               .bEndpointAddress = 14,
-               .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
-               .reg_udccs      = &UDCCS14,
-               .reg_ubcr       = &UBCR14,
-               .reg_uddr       = &UDDR14,
-       },
-       .ep[15] = {
-               .ep = {
-                       .name           = "ep15in-int",
-                       .ops            = &pxa25x_ep_ops,
-                       .maxpacket      = INT_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = INT_FIFO_SIZE,
-               .bEndpointAddress = USB_DIR_IN | 15,
-               .bmAttributes   = USB_ENDPOINT_XFER_INT,
-               .reg_udccs      = &UDCCS15,
-               .reg_uddr       = &UDDR15,
-       },
-#endif /* !CONFIG_USB_PXA25X_SMALL */
-};
-
-#define CP15R0_VENDOR_MASK     0xffffe000
-
-#if    defined(CONFIG_ARCH_PXA)
-#define CP15R0_XSCALE_VALUE    0x69052000      /* intel/arm/xscale */
-
-#elif  defined(CONFIG_ARCH_IXP4XX)
-#define CP15R0_XSCALE_VALUE    0x69054000      /* intel/arm/ixp4xx */
-
-#endif
-
-#define CP15R0_PROD_MASK       0x000003f0
-#define PXA25x                 0x00000100      /* and PXA26x */
-#define PXA210                 0x00000120
-
-#define CP15R0_REV_MASK                0x0000000f
-
-#define CP15R0_PRODREV_MASK    (CP15R0_PROD_MASK | CP15R0_REV_MASK)
-
-#define PXA255_A0              0x00000106      /* or PXA260_B1 */
-#define PXA250_C0              0x00000105      /* or PXA26x_B0 */
-#define PXA250_B2              0x00000104
-#define PXA250_B1              0x00000103      /* or PXA260_A0 */
-#define PXA250_B0              0x00000102
-#define PXA250_A1              0x00000101
-#define PXA250_A0              0x00000100
-
-#define PXA210_C0              0x00000125
-#define PXA210_B2              0x00000124
-#define PXA210_B1              0x00000123
-#define PXA210_B0              0x00000122
-#define IXP425_A0              0x000001c1
-#define IXP425_B0              0x000001f1
-#define IXP465_AD              0x00000200
-
-/*
- *     probe - binds to the platform device
- */
-static int pxa25x_udc_probe(struct platform_device *pdev)
-{
-       struct pxa25x_udc *dev = &memory;
-       int retval, irq;
-       u32 chiprev;
-
-       pr_info("%s: version %s\n", driver_name, DRIVER_VERSION);
-
-       /* insist on Intel/ARM/XScale */
-       asm("mrc%? p15, 0, %0, c0, c0" : "=r" (chiprev));
-       if ((chiprev & CP15R0_VENDOR_MASK) != CP15R0_XSCALE_VALUE) {
-               pr_err("%s: not XScale!\n", driver_name);
-               return -ENODEV;
-       }
-
-       /* trigger chiprev-specific logic */
-       switch (chiprev & CP15R0_PRODREV_MASK) {
-#if    defined(CONFIG_ARCH_PXA)
-       case PXA255_A0:
-               dev->has_cfr = 1;
-               break;
-       case PXA250_A0:
-       case PXA250_A1:
-               /* A0/A1 "not released"; ep 13, 15 unusable */
-               /* fall through */
-       case PXA250_B2: case PXA210_B2:
-       case PXA250_B1: case PXA210_B1:
-       case PXA250_B0: case PXA210_B0:
-               /* OUT-DMA is broken ... */
-               /* fall through */
-       case PXA250_C0: case PXA210_C0:
-               break;
-#elif  defined(CONFIG_ARCH_IXP4XX)
-       case IXP425_A0:
-       case IXP425_B0:
-       case IXP465_AD:
-               dev->has_cfr = 1;
-               break;
-#endif
-       default:
-               pr_err("%s: unrecognized processor: %08x\n",
-                       driver_name, chiprev);
-               /* iop3xx, ixp4xx, ... */
-               return -ENODEV;
-       }
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return -ENODEV;
-
-       dev->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(dev->clk))
-               return PTR_ERR(dev->clk);
-
-       pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
-               dev->has_cfr ? "" : " (!cfr)",
-               SIZE_STR "(pio)"
-               );
-
-       /* other non-static parts of init */
-       dev->dev = &pdev->dev;
-       dev->mach = dev_get_platdata(&pdev->dev);
-
-       dev->transceiver = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-
-       if (gpio_is_valid(dev->mach->gpio_pullup)) {
-               retval = devm_gpio_request(&pdev->dev, dev->mach->gpio_pullup,
-                                          "pca25x_udc GPIO PULLUP");
-               if (retval) {
-                       dev_dbg(&pdev->dev,
-                               "can't get pullup gpio %d, err: %d\n",
-                               dev->mach->gpio_pullup, retval);
-                       goto err;
-               }
-               gpio_direction_output(dev->mach->gpio_pullup, 0);
-       }
-
-       init_timer(&dev->timer);
-       dev->timer.function = udc_watchdog;
-       dev->timer.data = (unsigned long) dev;
-
-       the_controller = dev;
-       platform_set_drvdata(pdev, dev);
-
-       udc_disable(dev);
-       udc_reinit(dev);
-
-       dev->vbus = 0;
-
-       /* irq setup after old hardware state is cleaned up */
-       retval = devm_request_irq(&pdev->dev, irq, pxa25x_udc_irq, 0,
-                                 driver_name, dev);
-       if (retval != 0) {
-               pr_err("%s: can't get irq %d, err %d\n",
-                       driver_name, irq, retval);
-               goto err;
-       }
-       dev->got_irq = 1;
-
-#ifdef CONFIG_ARCH_LUBBOCK
-       if (machine_is_lubbock()) {
-               retval = devm_request_irq(&pdev->dev, LUBBOCK_USB_DISC_IRQ,
-                                         lubbock_vbus_irq, 0, driver_name,
-                                         dev);
-               if (retval != 0) {
-                       pr_err("%s: can't get irq %i, err %d\n",
-                               driver_name, LUBBOCK_USB_DISC_IRQ, retval);
-                       goto err;
-               }
-               retval = devm_request_irq(&pdev->dev, LUBBOCK_USB_IRQ,
-                                         lubbock_vbus_irq, 0, driver_name,
-                                         dev);
-               if (retval != 0) {
-                       pr_err("%s: can't get irq %i, err %d\n",
-                               driver_name, LUBBOCK_USB_IRQ, retval);
-                       goto err;
-               }
-       } else
-#endif
-       create_debug_files(dev);
-
-       retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
-       if (!retval)
-               return retval;
-
-       remove_debug_files(dev);
- err:
-       if (!IS_ERR_OR_NULL(dev->transceiver))
-               dev->transceiver = NULL;
-       return retval;
-}
-
-static void pxa25x_udc_shutdown(struct platform_device *_dev)
-{
-       pullup_off();
-}
-
-static int pxa25x_udc_remove(struct platform_device *pdev)
-{
-       struct pxa25x_udc *dev = platform_get_drvdata(pdev);
-
-       if (dev->driver)
-               return -EBUSY;
-
-       usb_del_gadget_udc(&dev->gadget);
-       dev->pullup = 0;
-       pullup(dev);
-
-       remove_debug_files(dev);
-
-       if (!IS_ERR_OR_NULL(dev->transceiver))
-               dev->transceiver = NULL;
-
-       the_controller = NULL;
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_PM
-
-/* USB suspend (controlled by the host) and system suspend (controlled
- * by the PXA) don't necessarily work well together.  If USB is active,
- * the 48 MHz clock is required; so the system can't enter 33 MHz idle
- * mode, or any deeper PM saving state.
- *
- * For now, we punt and forcibly disconnect from the USB host when PXA
- * enters any suspend state.  While we're disconnected, we always disable
- * the 48MHz USB clock ... allowing PXA sleep and/or 33 MHz idle states.
- * Boards without software pullup control shouldn't use those states.
- * VBUS IRQs should probably be ignored so that the PXA device just acts
- * "dead" to USB hosts until system resume.
- */
-static int pxa25x_udc_suspend(struct platform_device *dev, pm_message_t state)
-{
-       struct pxa25x_udc       *udc = platform_get_drvdata(dev);
-       unsigned long flags;
-
-       if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
-               WARNING("USB host won't detect disconnect!\n");
-       udc->suspended = 1;
-
-       local_irq_save(flags);
-       pullup(udc);
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-static int pxa25x_udc_resume(struct platform_device *dev)
-{
-       struct pxa25x_udc       *udc = platform_get_drvdata(dev);
-       unsigned long flags;
-
-       udc->suspended = 0;
-       local_irq_save(flags);
-       pullup(udc);
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-#else
-#define        pxa25x_udc_suspend      NULL
-#define        pxa25x_udc_resume       NULL
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-static struct platform_driver udc_driver = {
-       .shutdown       = pxa25x_udc_shutdown,
-       .probe          = pxa25x_udc_probe,
-       .remove         = pxa25x_udc_remove,
-       .suspend        = pxa25x_udc_suspend,
-       .resume         = pxa25x_udc_resume,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "pxa25x-udc",
-       },
-};
-
-module_platform_driver(udc_driver);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Frank Becker, Robert Schwebel, David Brownell");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa25x-udc");
diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h
deleted file mode 100644 (file)
index 3fe5931..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Intel PXA25x on-chip full speed USB device controller
- *
- * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
- * Copyright (C) 2003 David Brownell
- *
- *
- * 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.
- */
-
-#ifndef __LINUX_USB_GADGET_PXA25X_H
-#define __LINUX_USB_GADGET_PXA25X_H
-
-#include <linux/types.h>
-
-/*-------------------------------------------------------------------------*/
-
-/* pxa25x has this (move to include/asm-arm/arch-pxa/pxa-regs.h) */
-#define UFNRH_SIR      (1 << 7)        /* SOF interrupt request */
-#define UFNRH_SIM      (1 << 6)        /* SOF interrupt mask */
-#define UFNRH_IPE14    (1 << 5)        /* ISO packet error, ep14 */
-#define UFNRH_IPE9     (1 << 4)        /* ISO packet error, ep9 */
-#define UFNRH_IPE4     (1 << 3)        /* ISO packet error, ep4 */
-
-/* pxa255 has this (move to include/asm-arm/arch-pxa/pxa-regs.h) */
-#define        UDCCFR          UDC_RES2        /* UDC Control Function Register */
-#define UDCCFR_AREN    (1 << 7)        /* ACK response enable (now) */
-#define UDCCFR_ACM     (1 << 2)        /* ACK control mode (wait for AREN) */
-
-/* latest pxa255 errata define new "must be one" bits in UDCCFR */
-#define        UDCCFR_MB1      (0xff & ~(UDCCFR_AREN|UDCCFR_ACM))
-
-/*-------------------------------------------------------------------------*/
-
-struct pxa25x_udc;
-
-struct pxa25x_ep {
-       struct usb_ep                           ep;
-       struct pxa25x_udc                       *dev;
-
-       struct list_head                        queue;
-       unsigned long                           pio_irqs;
-
-       unsigned short                          fifo_size;
-       u8                                      bEndpointAddress;
-       u8                                      bmAttributes;
-
-       unsigned                                stopped : 1;
-       unsigned                                dma_fixup : 1;
-
-       /* UDCCS = UDC Control/Status for this EP
-        * UBCR = UDC Byte Count Remaining (contents of OUT fifo)
-        * UDDR = UDC Endpoint Data Register (the fifo)
-        * DRCM = DMA Request Channel Map
-        */
-       volatile u32                            *reg_udccs;
-       volatile u32                            *reg_ubcr;
-       volatile u32                            *reg_uddr;
-};
-
-struct pxa25x_request {
-       struct usb_request                      req;
-       struct list_head                        queue;
-};
-
-enum ep0_state {
-       EP0_IDLE,
-       EP0_IN_DATA_PHASE,
-       EP0_OUT_DATA_PHASE,
-       EP0_END_XFER,
-       EP0_STALL,
-};
-
-#define EP0_FIFO_SIZE  ((unsigned)16)
-#define BULK_FIFO_SIZE ((unsigned)64)
-#define ISO_FIFO_SIZE  ((unsigned)256)
-#define INT_FIFO_SIZE  ((unsigned)8)
-
-struct udc_stats {
-       struct ep0stats {
-               unsigned long           ops;
-               unsigned long           bytes;
-       } read, write;
-       unsigned long                   irqs;
-};
-
-#ifdef CONFIG_USB_PXA25X_SMALL
-/* when memory's tight, SMALL config saves code+data.  */
-#define        PXA_UDC_NUM_ENDPOINTS   3
-#endif
-
-#ifndef        PXA_UDC_NUM_ENDPOINTS
-#define        PXA_UDC_NUM_ENDPOINTS   16
-#endif
-
-struct pxa25x_udc {
-       struct usb_gadget                       gadget;
-       struct usb_gadget_driver                *driver;
-
-       enum ep0_state                          ep0state;
-       struct udc_stats                        stats;
-       unsigned                                got_irq : 1,
-                                               vbus : 1,
-                                               pullup : 1,
-                                               has_cfr : 1,
-                                               req_pending : 1,
-                                               req_std : 1,
-                                               req_config : 1,
-                                               suspended : 1,
-                                               active : 1;
-
-#define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200))
-       struct timer_list                       timer;
-
-       struct device                           *dev;
-       struct clk                              *clk;
-       struct pxa2xx_udc_mach_info             *mach;
-       struct usb_phy                          *transceiver;
-       u64                                     dma_mask;
-       struct pxa25x_ep                        ep [PXA_UDC_NUM_ENDPOINTS];
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FS
-       struct dentry                           *debugfs_udc;
-#endif
-};
-#define to_pxa25x(g)   (container_of((g), struct pxa25x_udc, gadget))
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_ARCH_LUBBOCK
-#include <mach/lubbock.h>
-/* lubbock can also report usb connect/disconnect irqs */
-#endif
-
-static struct pxa25x_udc *the_controller;
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Debugging support vanishes in non-debug builds.  DBG_NORMAL should be
- * mostly silent during normal use/testing, with no timing side-effects.
- */
-#define DBG_NORMAL     1       /* error paths, device state transitions */
-#define DBG_VERBOSE    2       /* add some success path trace info */
-#define DBG_NOISY      3       /* ... even more: request level */
-#define DBG_VERY_NOISY 4       /* ... even more: packet level */
-
-#define DMSG(stuff...) pr_debug("udc: " stuff)
-
-#ifdef DEBUG
-
-static const char *state_name[] = {
-       "EP0_IDLE",
-       "EP0_IN_DATA_PHASE", "EP0_OUT_DATA_PHASE",
-       "EP0_END_XFER", "EP0_STALL"
-};
-
-#ifdef VERBOSE_DEBUG
-#    define UDC_DEBUG DBG_VERBOSE
-#else
-#    define UDC_DEBUG DBG_NORMAL
-#endif
-
-static void __maybe_unused
-dump_udccr(const char *label)
-{
-       u32     udccr = UDCCR;
-       DMSG("%s %02X =%s%s%s%s%s%s%s%s\n",
-               label, udccr,
-               (udccr & UDCCR_REM) ? " rem" : "",
-               (udccr & UDCCR_RSTIR) ? " rstir" : "",
-               (udccr & UDCCR_SRM) ? " srm" : "",
-               (udccr & UDCCR_SUSIR) ? " susir" : "",
-               (udccr & UDCCR_RESIR) ? " resir" : "",
-               (udccr & UDCCR_RSM) ? " rsm" : "",
-               (udccr & UDCCR_UDA) ? " uda" : "",
-               (udccr & UDCCR_UDE) ? " ude" : "");
-}
-
-static void __maybe_unused
-dump_udccs0(const char *label)
-{
-       u32             udccs0 = UDCCS0;
-
-       DMSG("%s %s %02X =%s%s%s%s%s%s%s%s\n",
-               label, state_name[the_controller->ep0state], udccs0,
-               (udccs0 & UDCCS0_SA) ? " sa" : "",
-               (udccs0 & UDCCS0_RNE) ? " rne" : "",
-               (udccs0 & UDCCS0_FST) ? " fst" : "",
-               (udccs0 & UDCCS0_SST) ? " sst" : "",
-               (udccs0 & UDCCS0_DRWF) ? " dwrf" : "",
-               (udccs0 & UDCCS0_FTF) ? " ftf" : "",
-               (udccs0 & UDCCS0_IPR) ? " ipr" : "",
-               (udccs0 & UDCCS0_OPR) ? " opr" : "");
-}
-
-static void __maybe_unused
-dump_state(struct pxa25x_udc *dev)
-{
-       u32             tmp;
-       unsigned        i;
-
-       DMSG("%s, uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
-               state_name[dev->ep0state],
-               UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
-       dump_udccr("udccr");
-       if (dev->has_cfr) {
-               tmp = UDCCFR;
-               DMSG("udccfr %02X =%s%s\n", tmp,
-                       (tmp & UDCCFR_AREN) ? " aren" : "",
-                       (tmp & UDCCFR_ACM) ? " acm" : "");
-       }
-
-       if (!dev->driver) {
-               DMSG("no gadget driver bound\n");
-               return;
-       } else
-               DMSG("ep0 driver '%s'\n", dev->driver->driver.name);
-
-       dump_udccs0 ("udccs0");
-       DMSG("ep0 IN %lu/%lu, OUT %lu/%lu\n",
-               dev->stats.write.bytes, dev->stats.write.ops,
-               dev->stats.read.bytes, dev->stats.read.ops);
-
-       for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) {
-               if (dev->ep[i].ep.desc == NULL)
-                       continue;
-               DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccs);
-       }
-}
-
-#else
-
-#define        dump_udccr(x)   do{}while(0)
-#define        dump_udccs0(x)  do{}while(0)
-#define        dump_state(x)   do{}while(0)
-
-#define UDC_DEBUG ((unsigned)0)
-
-#endif
-
-#define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
-
-#define ERR(stuff...)          pr_err("udc: " stuff)
-#define WARNING(stuff...)      pr_warning("udc: " stuff)
-#define INFO(stuff...)         pr_info("udc: " stuff)
-
-
-#endif /* __LINUX_USB_GADGET_PXA25X_H */
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
deleted file mode 100644 (file)
index 597d39f..0000000
+++ /dev/null
@@ -1,2632 +0,0 @@
-/*
- * Handles the Intel 27x USB Device Controller (UDC)
- *
- * Inspired by original driver by Frank Becker, David Brownell, and others.
- * Copyright (C) 2008 Robert Jarzmik
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/clk.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/prefetch.h>
-#include <linux/byteorder/generic.h>
-#include <linux/platform_data/pxa2xx_udc.h>
-
-#include <linux/usb.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include "pxa27x_udc.h"
-
-/*
- * This driver handles the USB Device Controller (UDC) in Intel's PXA 27x
- * series processors.
- *
- * Such controller drivers work with a gadget driver.  The gadget driver
- * returns descriptors, implements configuration and data protocols used
- * by the host to interact with this device, and allocates endpoints to
- * the different protocol interfaces.  The controller driver virtualizes
- * usb hardware so that the gadget drivers will be more portable.
- *
- * This UDC hardware wants to implement a bit too much USB protocol. The
- * biggest issues are:  that the endpoints have to be set up before the
- * controller can be enabled (minor, and not uncommon); and each endpoint
- * can only have one configuration, interface and alternative interface
- * number (major, and very unusual). Once set up, these cannot be changed
- * without a controller reset.
- *
- * The workaround is to setup all combinations necessary for the gadgets which
- * will work with this driver. This is done in pxa_udc structure, statically.
- * See pxa_udc, udc_usb_ep versus pxa_ep, and matching function find_pxa_ep.
- * (You could modify this if needed.  Some drivers have a "fifo_mode" module
- * parameter to facilitate such changes.)
- *
- * The combinations have been tested with these gadgets :
- *  - zero gadget
- *  - file storage gadget
- *  - ether gadget
- *
- * The driver doesn't use DMA, only IO access and IRQ callbacks. No use is
- * made of UDC's double buffering either. USB "On-The-Go" is not implemented.
- *
- * All the requests are handled the same way :
- *  - the drivers tries to handle the request directly to the IO
- *  - if the IO fifo is not big enough, the remaining is send/received in
- *    interrupt handling.
- */
-
-#define        DRIVER_VERSION  "2008-04-18"
-#define        DRIVER_DESC     "PXA 27x USB Device Controller driver"
-
-static const char driver_name[] = "pxa27x_udc";
-static struct pxa_udc *the_controller;
-
-static void handle_ep(struct pxa_ep *ep);
-
-/*
- * Debug filesystem
- */
-#ifdef CONFIG_USB_GADGET_DEBUG_FS
-
-#include <linux/debugfs.h>
-#include <linux/uaccess.h>
-#include <linux/seq_file.h>
-
-static int state_dbg_show(struct seq_file *s, void *p)
-{
-       struct pxa_udc *udc = s->private;
-       int pos = 0, ret;
-       u32 tmp;
-
-       ret = -ENODEV;
-       if (!udc->driver)
-               goto out;
-
-       /* basic device status */
-       pos += seq_printf(s, DRIVER_DESC "\n"
-                        "%s version: %s\nGadget driver: %s\n",
-                        driver_name, DRIVER_VERSION,
-                        udc->driver ? udc->driver->driver.name : "(none)");
-
-       tmp = udc_readl(udc, UDCCR);
-       pos += seq_printf(s,
-                        "udccr=0x%0x(%s%s%s%s%s%s%s%s%s%s), "
-                        "con=%d,inter=%d,altinter=%d\n", tmp,
-                        (tmp & UDCCR_OEN) ? " oen":"",
-                        (tmp & UDCCR_AALTHNP) ? " aalthnp":"",
-                        (tmp & UDCCR_AHNP) ? " rem" : "",
-                        (tmp & UDCCR_BHNP) ? " rstir" : "",
-                        (tmp & UDCCR_DWRE) ? " dwre" : "",
-                        (tmp & UDCCR_SMAC) ? " smac" : "",
-                        (tmp & UDCCR_EMCE) ? " emce" : "",
-                        (tmp & UDCCR_UDR) ? " udr" : "",
-                        (tmp & UDCCR_UDA) ? " uda" : "",
-                        (tmp & UDCCR_UDE) ? " ude" : "",
-                        (tmp & UDCCR_ACN) >> UDCCR_ACN_S,
-                        (tmp & UDCCR_AIN) >> UDCCR_AIN_S,
-                        (tmp & UDCCR_AAISN) >> UDCCR_AAISN_S);
-       /* registers for device and ep0 */
-       pos += seq_printf(s, "udcicr0=0x%08x udcicr1=0x%08x\n",
-                       udc_readl(udc, UDCICR0), udc_readl(udc, UDCICR1));
-       pos += seq_printf(s, "udcisr0=0x%08x udcisr1=0x%08x\n",
-                       udc_readl(udc, UDCISR0), udc_readl(udc, UDCISR1));
-       pos += seq_printf(s, "udcfnr=%d\n", udc_readl(udc, UDCFNR));
-       pos += seq_printf(s, "irqs: reset=%lu, suspend=%lu, resume=%lu, "
-                       "reconfig=%lu\n",
-                       udc->stats.irqs_reset, udc->stats.irqs_suspend,
-                       udc->stats.irqs_resume, udc->stats.irqs_reconfig);
-
-       ret = 0;
-out:
-       return ret;
-}
-
-static int queues_dbg_show(struct seq_file *s, void *p)
-{
-       struct pxa_udc *udc = s->private;
-       struct pxa_ep *ep;
-       struct pxa27x_request *req;
-       int pos = 0, i, maxpkt, ret;
-
-       ret = -ENODEV;
-       if (!udc->driver)
-               goto out;
-
-       /* dump endpoint queues */
-       for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
-               ep = &udc->pxa_ep[i];
-               maxpkt = ep->fifo_size;
-               pos += seq_printf(s,  "%-12s max_pkt=%d %s\n",
-                               EPNAME(ep), maxpkt, "pio");
-
-               if (list_empty(&ep->queue)) {
-                       pos += seq_printf(s, "\t(nothing queued)\n");
-                       continue;
-               }
-
-               list_for_each_entry(req, &ep->queue, queue) {
-                       pos += seq_printf(s,  "\treq %p len %d/%d buf %p\n",
-                                       &req->req, req->req.actual,
-                                       req->req.length, req->req.buf);
-               }
-       }
-
-       ret = 0;
-out:
-       return ret;
-}
-
-static int eps_dbg_show(struct seq_file *s, void *p)
-{
-       struct pxa_udc *udc = s->private;
-       struct pxa_ep *ep;
-       int pos = 0, i, ret;
-       u32 tmp;
-
-       ret = -ENODEV;
-       if (!udc->driver)
-               goto out;
-
-       ep = &udc->pxa_ep[0];
-       tmp = udc_ep_readl(ep, UDCCSR);
-       pos += seq_printf(s, "udccsr0=0x%03x(%s%s%s%s%s%s%s)\n", tmp,
-                        (tmp & UDCCSR0_SA) ? " sa" : "",
-                        (tmp & UDCCSR0_RNE) ? " rne" : "",
-                        (tmp & UDCCSR0_FST) ? " fst" : "",
-                        (tmp & UDCCSR0_SST) ? " sst" : "",
-                        (tmp & UDCCSR0_DME) ? " dme" : "",
-                        (tmp & UDCCSR0_IPR) ? " ipr" : "",
-                        (tmp & UDCCSR0_OPC) ? " opc" : "");
-       for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
-               ep = &udc->pxa_ep[i];
-               tmp = i? udc_ep_readl(ep, UDCCR) : udc_readl(udc, UDCCR);
-               pos += seq_printf(s, "%-12s: "
-                               "IN %lu(%lu reqs), OUT %lu(%lu reqs), "
-                               "irqs=%lu, udccr=0x%08x, udccsr=0x%03x, "
-                               "udcbcr=%d\n",
-                               EPNAME(ep),
-                               ep->stats.in_bytes, ep->stats.in_ops,
-                               ep->stats.out_bytes, ep->stats.out_ops,
-                               ep->stats.irqs,
-                               tmp, udc_ep_readl(ep, UDCCSR),
-                               udc_ep_readl(ep, UDCBCR));
-       }
-
-       ret = 0;
-out:
-       return ret;
-}
-
-static int eps_dbg_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, eps_dbg_show, inode->i_private);
-}
-
-static int queues_dbg_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, queues_dbg_show, inode->i_private);
-}
-
-static int state_dbg_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, state_dbg_show, inode->i_private);
-}
-
-static const struct file_operations state_dbg_fops = {
-       .owner          = THIS_MODULE,
-       .open           = state_dbg_open,
-       .llseek         = seq_lseek,
-       .read           = seq_read,
-       .release        = single_release,
-};
-
-static const struct file_operations queues_dbg_fops = {
-       .owner          = THIS_MODULE,
-       .open           = queues_dbg_open,
-       .llseek         = seq_lseek,
-       .read           = seq_read,
-       .release        = single_release,
-};
-
-static const struct file_operations eps_dbg_fops = {
-       .owner          = THIS_MODULE,
-       .open           = eps_dbg_open,
-       .llseek         = seq_lseek,
-       .read           = seq_read,
-       .release        = single_release,
-};
-
-static void pxa_init_debugfs(struct pxa_udc *udc)
-{
-       struct dentry *root, *state, *queues, *eps;
-
-       root = debugfs_create_dir(udc->gadget.name, NULL);
-       if (IS_ERR(root) || !root)
-               goto err_root;
-
-       state = debugfs_create_file("udcstate", 0400, root, udc,
-                       &state_dbg_fops);
-       if (!state)
-               goto err_state;
-       queues = debugfs_create_file("queues", 0400, root, udc,
-                       &queues_dbg_fops);
-       if (!queues)
-               goto err_queues;
-       eps = debugfs_create_file("epstate", 0400, root, udc,
-                       &eps_dbg_fops);
-       if (!eps)
-               goto err_eps;
-
-       udc->debugfs_root = root;
-       udc->debugfs_state = state;
-       udc->debugfs_queues = queues;
-       udc->debugfs_eps = eps;
-       return;
-err_eps:
-       debugfs_remove(eps);
-err_queues:
-       debugfs_remove(queues);
-err_state:
-       debugfs_remove(root);
-err_root:
-       dev_err(udc->dev, "debugfs is not available\n");
-}
-
-static void pxa_cleanup_debugfs(struct pxa_udc *udc)
-{
-       debugfs_remove(udc->debugfs_eps);
-       debugfs_remove(udc->debugfs_queues);
-       debugfs_remove(udc->debugfs_state);
-       debugfs_remove(udc->debugfs_root);
-       udc->debugfs_eps = NULL;
-       udc->debugfs_queues = NULL;
-       udc->debugfs_state = NULL;
-       udc->debugfs_root = NULL;
-}
-
-#else
-static inline void pxa_init_debugfs(struct pxa_udc *udc)
-{
-}
-
-static inline void pxa_cleanup_debugfs(struct pxa_udc *udc)
-{
-}
-#endif
-
-/**
- * is_match_usb_pxa - check if usb_ep and pxa_ep match
- * @udc_usb_ep: usb endpoint
- * @ep: pxa endpoint
- * @config: configuration required in pxa_ep
- * @interface: interface required in pxa_ep
- * @altsetting: altsetting required in pxa_ep
- *
- * Returns 1 if all criteria match between pxa and usb endpoint, 0 otherwise
- */
-static int is_match_usb_pxa(struct udc_usb_ep *udc_usb_ep, struct pxa_ep *ep,
-               int config, int interface, int altsetting)
-{
-       if (usb_endpoint_num(&udc_usb_ep->desc) != ep->addr)
-               return 0;
-       if (usb_endpoint_dir_in(&udc_usb_ep->desc) != ep->dir_in)
-               return 0;
-       if (usb_endpoint_type(&udc_usb_ep->desc) != ep->type)
-               return 0;
-       if ((ep->config != config) || (ep->interface != interface)
-                       || (ep->alternate != altsetting))
-               return 0;
-       return 1;
-}
-
-/**
- * find_pxa_ep - find pxa_ep structure matching udc_usb_ep
- * @udc: pxa udc
- * @udc_usb_ep: udc_usb_ep structure
- *
- * Match udc_usb_ep and all pxa_ep available, to see if one matches.
- * This is necessary because of the strong pxa hardware restriction requiring
- * that once pxa endpoints are initialized, their configuration is freezed, and
- * no change can be made to their address, direction, or in which configuration,
- * interface or altsetting they are active ... which differs from more usual
- * models which have endpoints be roughly just addressable fifos, and leave
- * configuration events up to gadget drivers (like all control messages).
- *
- * Note that there is still a blurred point here :
- *   - we rely on UDCCR register "active interface" and "active altsetting".
- *     This is a nonsense in regard of USB spec, where multiple interfaces are
- *     active at the same time.
- *   - if we knew for sure that the pxa can handle multiple interface at the
- *     same time, assuming Intel's Developer Guide is wrong, this function
- *     should be reviewed, and a cache of couples (iface, altsetting) should
- *     be kept in the pxa_udc structure. In this case this function would match
- *     against the cache of couples instead of the "last altsetting" set up.
- *
- * Returns the matched pxa_ep structure or NULL if none found
- */
-static struct pxa_ep *find_pxa_ep(struct pxa_udc *udc,
-               struct udc_usb_ep *udc_usb_ep)
-{
-       int i;
-       struct pxa_ep *ep;
-       int cfg = udc->config;
-       int iface = udc->last_interface;
-       int alt = udc->last_alternate;
-
-       if (udc_usb_ep == &udc->udc_usb_ep[0])
-               return &udc->pxa_ep[0];
-
-       for (i = 1; i < NR_PXA_ENDPOINTS; i++) {
-               ep = &udc->pxa_ep[i];
-               if (is_match_usb_pxa(udc_usb_ep, ep, cfg, iface, alt))
-                       return ep;
-       }
-       return NULL;
-}
-
-/**
- * update_pxa_ep_matches - update pxa_ep cached values in all udc_usb_ep
- * @udc: pxa udc
- *
- * Context: in_interrupt()
- *
- * Updates all pxa_ep fields in udc_usb_ep structures, if this field was
- * previously set up (and is not NULL). The update is necessary is a
- * configuration change or altsetting change was issued by the USB host.
- */
-static void update_pxa_ep_matches(struct pxa_udc *udc)
-{
-       int i;
-       struct udc_usb_ep *udc_usb_ep;
-
-       for (i = 1; i < NR_USB_ENDPOINTS; i++) {
-               udc_usb_ep = &udc->udc_usb_ep[i];
-               if (udc_usb_ep->pxa_ep)
-                       udc_usb_ep->pxa_ep = find_pxa_ep(udc, udc_usb_ep);
-       }
-}
-
-/**
- * pio_irq_enable - Enables irq generation for one endpoint
- * @ep: udc endpoint
- */
-static void pio_irq_enable(struct pxa_ep *ep)
-{
-       struct pxa_udc *udc = ep->dev;
-       int index = EPIDX(ep);
-       u32 udcicr0 = udc_readl(udc, UDCICR0);
-       u32 udcicr1 = udc_readl(udc, UDCICR1);
-
-       if (index < 16)
-               udc_writel(udc, UDCICR0, udcicr0 | (3 << (index * 2)));
-       else
-               udc_writel(udc, UDCICR1, udcicr1 | (3 << ((index - 16) * 2)));
-}
-
-/**
- * pio_irq_disable - Disables irq generation for one endpoint
- * @ep: udc endpoint
- */
-static void pio_irq_disable(struct pxa_ep *ep)
-{
-       struct pxa_udc *udc = ep->dev;
-       int index = EPIDX(ep);
-       u32 udcicr0 = udc_readl(udc, UDCICR0);
-       u32 udcicr1 = udc_readl(udc, UDCICR1);
-
-       if (index < 16)
-               udc_writel(udc, UDCICR0, udcicr0 & ~(3 << (index * 2)));
-       else
-               udc_writel(udc, UDCICR1, udcicr1 & ~(3 << ((index - 16) * 2)));
-}
-
-/**
- * udc_set_mask_UDCCR - set bits in UDCCR
- * @udc: udc device
- * @mask: bits to set in UDCCR
- *
- * Sets bits in UDCCR, leaving DME and FST bits as they were.
- */
-static inline void udc_set_mask_UDCCR(struct pxa_udc *udc, int mask)
-{
-       u32 udccr = udc_readl(udc, UDCCR);
-       udc_writel(udc, UDCCR,
-                       (udccr & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS));
-}
-
-/**
- * udc_clear_mask_UDCCR - clears bits in UDCCR
- * @udc: udc device
- * @mask: bit to clear in UDCCR
- *
- * Clears bits in UDCCR, leaving DME and FST bits as they were.
- */
-static inline void udc_clear_mask_UDCCR(struct pxa_udc *udc, int mask)
-{
-       u32 udccr = udc_readl(udc, UDCCR);
-       udc_writel(udc, UDCCR,
-                       (udccr & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS));
-}
-
-/**
- * ep_write_UDCCSR - set bits in UDCCSR
- * @udc: udc device
- * @mask: bits to set in UDCCR
- *
- * Sets bits in UDCCSR (UDCCSR0 and UDCCSR*).
- *
- * A specific case is applied to ep0 : the ACM bit is always set to 1, for
- * SET_INTERFACE and SET_CONFIGURATION.
- */
-static inline void ep_write_UDCCSR(struct pxa_ep *ep, int mask)
-{
-       if (is_ep0(ep))
-               mask |= UDCCSR0_ACM;
-       udc_ep_writel(ep, UDCCSR, mask);
-}
-
-/**
- * ep_count_bytes_remain - get how many bytes in udc endpoint
- * @ep: udc endpoint
- *
- * Returns number of bytes in OUT fifos. Broken for IN fifos (-EOPNOTSUPP)
- */
-static int ep_count_bytes_remain(struct pxa_ep *ep)
-{
-       if (ep->dir_in)
-               return -EOPNOTSUPP;
-       return udc_ep_readl(ep, UDCBCR) & 0x3ff;
-}
-
-/**
- * ep_is_empty - checks if ep has byte ready for reading
- * @ep: udc endpoint
- *
- * If endpoint is the control endpoint, checks if there are bytes in the
- * control endpoint fifo. If endpoint is a data endpoint, checks if bytes
- * are ready for reading on OUT endpoint.
- *
- * Returns 0 if ep not empty, 1 if ep empty, -EOPNOTSUPP if IN endpoint
- */
-static int ep_is_empty(struct pxa_ep *ep)
-{
-       int ret;
-
-       if (!is_ep0(ep) && ep->dir_in)
-               return -EOPNOTSUPP;
-       if (is_ep0(ep))
-               ret = !(udc_ep_readl(ep, UDCCSR) & UDCCSR0_RNE);
-       else
-               ret = !(udc_ep_readl(ep, UDCCSR) & UDCCSR_BNE);
-       return ret;
-}
-
-/**
- * ep_is_full - checks if ep has place to write bytes
- * @ep: udc endpoint
- *
- * If endpoint is not the control endpoint and is an IN endpoint, checks if
- * there is place to write bytes into the endpoint.
- *
- * Returns 0 if ep not full, 1 if ep full, -EOPNOTSUPP if OUT endpoint
- */
-static int ep_is_full(struct pxa_ep *ep)
-{
-       if (is_ep0(ep))
-               return (udc_ep_readl(ep, UDCCSR) & UDCCSR0_IPR);
-       if (!ep->dir_in)
-               return -EOPNOTSUPP;
-       return (!(udc_ep_readl(ep, UDCCSR) & UDCCSR_BNF));
-}
-
-/**
- * epout_has_pkt - checks if OUT endpoint fifo has a packet available
- * @ep: pxa endpoint
- *
- * Returns 1 if a complete packet is available, 0 if not, -EOPNOTSUPP for IN ep.
- */
-static int epout_has_pkt(struct pxa_ep *ep)
-{
-       if (!is_ep0(ep) && ep->dir_in)
-               return -EOPNOTSUPP;
-       if (is_ep0(ep))
-               return (udc_ep_readl(ep, UDCCSR) & UDCCSR0_OPC);
-       return (udc_ep_readl(ep, UDCCSR) & UDCCSR_PC);
-}
-
-/**
- * set_ep0state - Set ep0 automata state
- * @dev: udc device
- * @state: state
- */
-static void set_ep0state(struct pxa_udc *udc, int state)
-{
-       struct pxa_ep *ep = &udc->pxa_ep[0];
-       char *old_stname = EP0_STNAME(udc);
-
-       udc->ep0state = state;
-       ep_dbg(ep, "state=%s->%s, udccsr0=0x%03x, udcbcr=%d\n", old_stname,
-               EP0_STNAME(udc), udc_ep_readl(ep, UDCCSR),
-               udc_ep_readl(ep, UDCBCR));
-}
-
-/**
- * ep0_idle - Put control endpoint into idle state
- * @dev: udc device
- */
-static void ep0_idle(struct pxa_udc *dev)
-{
-       set_ep0state(dev, WAIT_FOR_SETUP);
-}
-
-/**
- * inc_ep_stats_reqs - Update ep stats counts
- * @ep: physical endpoint
- * @req: usb request
- * @is_in: ep direction (USB_DIR_IN or 0)
- *
- */
-static void inc_ep_stats_reqs(struct pxa_ep *ep, int is_in)
-{
-       if (is_in)
-               ep->stats.in_ops++;
-       else
-               ep->stats.out_ops++;
-}
-
-/**
- * inc_ep_stats_bytes - Update ep stats counts
- * @ep: physical endpoint
- * @count: bytes transferred on endpoint
- * @is_in: ep direction (USB_DIR_IN or 0)
- */
-static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in)
-{
-       if (is_in)
-               ep->stats.in_bytes += count;
-       else
-               ep->stats.out_bytes += count;
-}
-
-/**
- * pxa_ep_setup - Sets up an usb physical endpoint
- * @ep: pxa27x physical endpoint
- *
- * Find the physical pxa27x ep, and setup its UDCCR
- */
-static void pxa_ep_setup(struct pxa_ep *ep)
-{
-       u32 new_udccr;
-
-       new_udccr = ((ep->config << UDCCONR_CN_S) & UDCCONR_CN)
-               | ((ep->interface << UDCCONR_IN_S) & UDCCONR_IN)
-               | ((ep->alternate << UDCCONR_AISN_S) & UDCCONR_AISN)
-               | ((EPADDR(ep) << UDCCONR_EN_S) & UDCCONR_EN)
-               | ((EPXFERTYPE(ep) << UDCCONR_ET_S) & UDCCONR_ET)
-               | ((ep->dir_in) ? UDCCONR_ED : 0)
-               | ((ep->fifo_size << UDCCONR_MPS_S) & UDCCONR_MPS)
-               | UDCCONR_EE;
-
-       udc_ep_writel(ep, UDCCR, new_udccr);
-}
-
-/**
- * pxa_eps_setup - Sets up all usb physical endpoints
- * @dev: udc device
- *
- * Setup all pxa physical endpoints, except ep0
- */
-static void pxa_eps_setup(struct pxa_udc *dev)
-{
-       unsigned int i;
-
-       dev_dbg(dev->dev, "%s: dev=%p\n", __func__, dev);
-
-       for (i = 1; i < NR_PXA_ENDPOINTS; i++)
-               pxa_ep_setup(&dev->pxa_ep[i]);
-}
-
-/**
- * pxa_ep_alloc_request - Allocate usb request
- * @_ep: usb endpoint
- * @gfp_flags:
- *
- * For the pxa27x, these can just wrap kmalloc/kfree.  gadget drivers
- * must still pass correctly initialized endpoints, since other controller
- * drivers may care about how it's currently set up (dma issues etc).
-  */
-static struct usb_request *
-pxa_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
-{
-       struct pxa27x_request *req;
-
-       req = kzalloc(sizeof *req, gfp_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD(&req->queue);
-       req->in_use = 0;
-       req->udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
-
-       return &req->req;
-}
-
-/**
- * pxa_ep_free_request - Free usb request
- * @_ep: usb endpoint
- * @_req: usb request
- *
- * Wrapper around kfree to free _req
- */
-static void pxa_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct pxa27x_request *req;
-
-       req = container_of(_req, struct pxa27x_request, req);
-       WARN_ON(!list_empty(&req->queue));
-       kfree(req);
-}
-
-/**
- * ep_add_request - add a request to the endpoint's queue
- * @ep: usb endpoint
- * @req: usb request
- *
- * Context: ep->lock held
- *
- * Queues the request in the endpoint's queue, and enables the interrupts
- * on the endpoint.
- */
-static void ep_add_request(struct pxa_ep *ep, struct pxa27x_request *req)
-{
-       if (unlikely(!req))
-               return;
-       ep_vdbg(ep, "req:%p, lg=%d, udccsr=0x%03x\n", req,
-               req->req.length, udc_ep_readl(ep, UDCCSR));
-
-       req->in_use = 1;
-       list_add_tail(&req->queue, &ep->queue);
-       pio_irq_enable(ep);
-}
-
-/**
- * ep_del_request - removes a request from the endpoint's queue
- * @ep: usb endpoint
- * @req: usb request
- *
- * Context: ep->lock held
- *
- * Unqueue the request from the endpoint's queue. If there are no more requests
- * on the endpoint, and if it's not the control endpoint, interrupts are
- * disabled on the endpoint.
- */
-static void ep_del_request(struct pxa_ep *ep, struct pxa27x_request *req)
-{
-       if (unlikely(!req))
-               return;
-       ep_vdbg(ep, "req:%p, lg=%d, udccsr=0x%03x\n", req,
-               req->req.length, udc_ep_readl(ep, UDCCSR));
-
-       list_del_init(&req->queue);
-       req->in_use = 0;
-       if (!is_ep0(ep) && list_empty(&ep->queue))
-               pio_irq_disable(ep);
-}
-
-/**
- * req_done - Complete an usb request
- * @ep: pxa physical endpoint
- * @req: pxa request
- * @status: usb request status sent to gadget API
- * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
- *
- * Context: ep->lock held if flags not NULL, else ep->lock released
- *
- * Retire a pxa27x usb request. Endpoint must be locked.
- */
-static void req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status,
-       unsigned long *pflags)
-{
-       unsigned long   flags;
-
-       ep_del_request(ep, req);
-       if (likely(req->req.status == -EINPROGRESS))
-               req->req.status = status;
-       else
-               status = req->req.status;
-
-       if (status && status != -ESHUTDOWN)
-               ep_dbg(ep, "complete req %p stat %d len %u/%u\n",
-                       &req->req, status,
-                       req->req.actual, req->req.length);
-
-       if (pflags)
-               spin_unlock_irqrestore(&ep->lock, *pflags);
-       local_irq_save(flags);
-       req->req.complete(&req->udc_usb_ep->usb_ep, &req->req);
-       local_irq_restore(flags);
-       if (pflags)
-               spin_lock_irqsave(&ep->lock, *pflags);
-}
-
-/**
- * ep_end_out_req - Ends endpoint OUT request
- * @ep: physical endpoint
- * @req: pxa request
- * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
- *
- * Context: ep->lock held or released (see req_done())
- *
- * Ends endpoint OUT request (completes usb request).
- */
-static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req,
-       unsigned long *pflags)
-{
-       inc_ep_stats_reqs(ep, !USB_DIR_IN);
-       req_done(ep, req, 0, pflags);
-}
-
-/**
- * ep0_end_out_req - Ends control endpoint OUT request (ends data stage)
- * @ep: physical endpoint
- * @req: pxa request
- * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
- *
- * Context: ep->lock held or released (see req_done())
- *
- * Ends control endpoint OUT request (completes usb request), and puts
- * control endpoint into idle state
- */
-static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req,
-       unsigned long *pflags)
-{
-       set_ep0state(ep->dev, OUT_STATUS_STAGE);
-       ep_end_out_req(ep, req, pflags);
-       ep0_idle(ep->dev);
-}
-
-/**
- * ep_end_in_req - Ends endpoint IN request
- * @ep: physical endpoint
- * @req: pxa request
- * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
- *
- * Context: ep->lock held or released (see req_done())
- *
- * Ends endpoint IN request (completes usb request).
- */
-static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req,
-       unsigned long *pflags)
-{
-       inc_ep_stats_reqs(ep, USB_DIR_IN);
-       req_done(ep, req, 0, pflags);
-}
-
-/**
- * ep0_end_in_req - Ends control endpoint IN request (ends data stage)
- * @ep: physical endpoint
- * @req: pxa request
- * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
- *
- * Context: ep->lock held or released (see req_done())
- *
- * Ends control endpoint IN request (completes usb request), and puts
- * control endpoint into status state
- */
-static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req,
-       unsigned long *pflags)
-{
-       set_ep0state(ep->dev, IN_STATUS_STAGE);
-       ep_end_in_req(ep, req, pflags);
-}
-
-/**
- * nuke - Dequeue all requests
- * @ep: pxa endpoint
- * @status: usb request status
- *
- * Context: ep->lock released
- *
- * Dequeues all requests on an endpoint. As a side effect, interrupts will be
- * disabled on that endpoint (because no more requests).
- */
-static void nuke(struct pxa_ep *ep, int status)
-{
-       struct pxa27x_request   *req;
-       unsigned long           flags;
-
-       spin_lock_irqsave(&ep->lock, flags);
-       while (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next, struct pxa27x_request, queue);
-               req_done(ep, req, status, &flags);
-       }
-       spin_unlock_irqrestore(&ep->lock, flags);
-}
-
-/**
- * read_packet - transfer 1 packet from an OUT endpoint into request
- * @ep: pxa physical endpoint
- * @req: usb request
- *
- * Takes bytes from OUT endpoint and transfers them info the usb request.
- * If there is less space in request than bytes received in OUT endpoint,
- * bytes are left in the OUT endpoint.
- *
- * Returns how many bytes were actually transferred
- */
-static int read_packet(struct pxa_ep *ep, struct pxa27x_request *req)
-{
-       u32 *buf;
-       int bytes_ep, bufferspace, count, i;
-
-       bytes_ep = ep_count_bytes_remain(ep);
-       bufferspace = req->req.length - req->req.actual;
-
-       buf = (u32 *)(req->req.buf + req->req.actual);
-       prefetchw(buf);
-
-       if (likely(!ep_is_empty(ep)))
-               count = min(bytes_ep, bufferspace);
-       else /* zlp */
-               count = 0;
-
-       for (i = count; i > 0; i -= 4)
-               *buf++ = udc_ep_readl(ep, UDCDR);
-       req->req.actual += count;
-
-       ep_write_UDCCSR(ep, UDCCSR_PC);
-
-       return count;
-}
-
-/**
- * write_packet - transfer 1 packet from request into an IN endpoint
- * @ep: pxa physical endpoint
- * @req: usb request
- * @max: max bytes that fit into endpoint
- *
- * Takes bytes from usb request, and transfers them into the physical
- * endpoint. If there are no bytes to transfer, doesn't write anything
- * to physical endpoint.
- *
- * Returns how many bytes were actually transferred.
- */
-static int write_packet(struct pxa_ep *ep, struct pxa27x_request *req,
-                       unsigned int max)
-{
-       int length, count, remain, i;
-       u32 *buf;
-       u8 *buf_8;
-
-       buf = (u32 *)(req->req.buf + req->req.actual);
-       prefetch(buf);
-
-       length = min(req->req.length - req->req.actual, max);
-       req->req.actual += length;
-
-       remain = length & 0x3;
-       count = length & ~(0x3);
-       for (i = count; i > 0 ; i -= 4)
-               udc_ep_writel(ep, UDCDR, *buf++);
-
-       buf_8 = (u8 *)buf;
-       for (i = remain; i > 0; i--)
-               udc_ep_writeb(ep, UDCDR, *buf_8++);
-
-       ep_vdbg(ep, "length=%d+%d, udccsr=0x%03x\n", count, remain,
-               udc_ep_readl(ep, UDCCSR));
-
-       return length;
-}
-
-/**
- * read_fifo - Transfer packets from OUT endpoint into usb request
- * @ep: pxa physical endpoint
- * @req: usb request
- *
- * Context: callable when in_interrupt()
- *
- * Unload as many packets as possible from the fifo we use for usb OUT
- * transfers and put them into the request. Caller should have made sure
- * there's at least one packet ready.
- * Doesn't complete the request, that's the caller's job
- *
- * Returns 1 if the request completed, 0 otherwise
- */
-static int read_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
-{
-       int count, is_short, completed = 0;
-
-       while (epout_has_pkt(ep)) {
-               count = read_packet(ep, req);
-               inc_ep_stats_bytes(ep, count, !USB_DIR_IN);
-
-               is_short = (count < ep->fifo_size);
-               ep_dbg(ep, "read udccsr:%03x, count:%d bytes%s req %p %d/%d\n",
-                       udc_ep_readl(ep, UDCCSR), count, is_short ? "/S" : "",
-                       &req->req, req->req.actual, req->req.length);
-
-               /* completion */
-               if (is_short || req->req.actual == req->req.length) {
-                       completed = 1;
-                       break;
-               }
-               /* finished that packet.  the next one may be waiting... */
-       }
-       return completed;
-}
-
-/**
- * write_fifo - transfer packets from usb request into an IN endpoint
- * @ep: pxa physical endpoint
- * @req: pxa usb request
- *
- * Write to an IN endpoint fifo, as many packets as possible.
- * irqs will use this to write the rest later.
- * caller guarantees at least one packet buffer is ready (or a zlp).
- * Doesn't complete the request, that's the caller's job
- *
- * Returns 1 if request fully transferred, 0 if partial transfer
- */
-static int write_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
-{
-       unsigned max;
-       int count, is_short, is_last = 0, completed = 0, totcount = 0;
-       u32 udccsr;
-
-       max = ep->fifo_size;
-       do {
-               is_short = 0;
-
-               udccsr = udc_ep_readl(ep, UDCCSR);
-               if (udccsr & UDCCSR_PC) {
-                       ep_vdbg(ep, "Clearing Transmit Complete, udccsr=%x\n",
-                               udccsr);
-                       ep_write_UDCCSR(ep, UDCCSR_PC);
-               }
-               if (udccsr & UDCCSR_TRN) {
-                       ep_vdbg(ep, "Clearing Underrun on, udccsr=%x\n",
-                               udccsr);
-                       ep_write_UDCCSR(ep, UDCCSR_TRN);
-               }
-
-               count = write_packet(ep, req, max);
-               inc_ep_stats_bytes(ep, count, USB_DIR_IN);
-               totcount += count;
-
-               /* last packet is usually short (or a zlp) */
-               if (unlikely(count < max)) {
-                       is_last = 1;
-                       is_short = 1;
-               } else {
-                       if (likely(req->req.length > req->req.actual)
-                                       || req->req.zero)
-                               is_last = 0;
-                       else
-                               is_last = 1;
-                       /* interrupt/iso maxpacket may not fill the fifo */
-                       is_short = unlikely(max < ep->fifo_size);
-               }
-
-               if (is_short)
-                       ep_write_UDCCSR(ep, UDCCSR_SP);
-
-               /* requests complete when all IN data is in the FIFO */
-               if (is_last) {
-                       completed = 1;
-                       break;
-               }
-       } while (!ep_is_full(ep));
-
-       ep_dbg(ep, "wrote count:%d bytes%s%s, left:%d req=%p\n",
-                       totcount, is_last ? "/L" : "", is_short ? "/S" : "",
-                       req->req.length - req->req.actual, &req->req);
-
-       return completed;
-}
-
-/**
- * read_ep0_fifo - Transfer packets from control endpoint into usb request
- * @ep: control endpoint
- * @req: pxa usb request
- *
- * Special ep0 version of the above read_fifo. Reads as many bytes from control
- * endpoint as can be read, and stores them into usb request (limited by request
- * maximum length).
- *
- * Returns 0 if usb request only partially filled, 1 if fully filled
- */
-static int read_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
-{
-       int count, is_short, completed = 0;
-
-       while (epout_has_pkt(ep)) {
-               count = read_packet(ep, req);
-               ep_write_UDCCSR(ep, UDCCSR0_OPC);
-               inc_ep_stats_bytes(ep, count, !USB_DIR_IN);
-
-               is_short = (count < ep->fifo_size);
-               ep_dbg(ep, "read udccsr:%03x, count:%d bytes%s req %p %d/%d\n",
-                       udc_ep_readl(ep, UDCCSR), count, is_short ? "/S" : "",
-                       &req->req, req->req.actual, req->req.length);
-
-               if (is_short || req->req.actual >= req->req.length) {
-                       completed = 1;
-                       break;
-               }
-       }
-
-       return completed;
-}
-
-/**
- * write_ep0_fifo - Send a request to control endpoint (ep0 in)
- * @ep: control endpoint
- * @req: request
- *
- * Context: callable when in_interrupt()
- *
- * Sends a request (or a part of the request) to the control endpoint (ep0 in).
- * If the request doesn't fit, the remaining part will be sent from irq.
- * The request is considered fully written only if either :
- *   - last write transferred all remaining bytes, but fifo was not fully filled
- *   - last write was a 0 length write
- *
- * Returns 1 if request fully written, 0 if request only partially sent
- */
-static int write_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
-{
-       unsigned        count;
-       int             is_last, is_short;
-
-       count = write_packet(ep, req, EP0_FIFO_SIZE);
-       inc_ep_stats_bytes(ep, count, USB_DIR_IN);
-
-       is_short = (count < EP0_FIFO_SIZE);
-       is_last = ((count == 0) || (count < EP0_FIFO_SIZE));
-
-       /* Sends either a short packet or a 0 length packet */
-       if (unlikely(is_short))
-               ep_write_UDCCSR(ep, UDCCSR0_IPR);
-
-       ep_dbg(ep, "in %d bytes%s%s, %d left, req=%p, udccsr0=0x%03x\n",
-               count, is_short ? "/S" : "", is_last ? "/L" : "",
-               req->req.length - req->req.actual,
-               &req->req, udc_ep_readl(ep, UDCCSR));
-
-       return is_last;
-}
-
-/**
- * pxa_ep_queue - Queue a request into an IN endpoint
- * @_ep: usb endpoint
- * @_req: usb request
- * @gfp_flags: flags
- *
- * Context: normally called when !in_interrupt, but callable when in_interrupt()
- * in the special case of ep0 setup :
- *   (irq->handle_ep0_ctrl_req->gadget_setup->pxa_ep_queue)
- *
- * Returns 0 if succedeed, error otherwise
- */
-static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
-                       gfp_t gfp_flags)
-{
-       struct udc_usb_ep       *udc_usb_ep;
-       struct pxa_ep           *ep;
-       struct pxa27x_request   *req;
-       struct pxa_udc          *dev;
-       unsigned long           flags;
-       int                     rc = 0;
-       int                     is_first_req;
-       unsigned                length;
-       int                     recursion_detected;
-
-       req = container_of(_req, struct pxa27x_request, req);
-       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
-
-       if (unlikely(!_req || !_req->complete || !_req->buf))
-               return -EINVAL;
-
-       if (unlikely(!_ep))
-               return -EINVAL;
-
-       dev = udc_usb_ep->dev;
-       ep = udc_usb_ep->pxa_ep;
-       if (unlikely(!ep))
-               return -EINVAL;
-
-       dev = ep->dev;
-       if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
-               ep_dbg(ep, "bogus device state\n");
-               return -ESHUTDOWN;
-       }
-
-       /* iso is always one packet per request, that's the only way
-        * we can report per-packet status.  that also helps with dma.
-        */
-       if (unlikely(EPXFERTYPE_is_ISO(ep)
-                       && req->req.length > ep->fifo_size))
-               return -EMSGSIZE;
-
-       spin_lock_irqsave(&ep->lock, flags);
-       recursion_detected = ep->in_handle_ep;
-
-       is_first_req = list_empty(&ep->queue);
-       ep_dbg(ep, "queue req %p(first=%s), len %d buf %p\n",
-                       _req, is_first_req ? "yes" : "no",
-                       _req->length, _req->buf);
-
-       if (!ep->enabled) {
-               _req->status = -ESHUTDOWN;
-               rc = -ESHUTDOWN;
-               goto out_locked;
-       }
-
-       if (req->in_use) {
-               ep_err(ep, "refusing to queue req %p (already queued)\n", req);
-               goto out_locked;
-       }
-
-       length = _req->length;
-       _req->status = -EINPROGRESS;
-       _req->actual = 0;
-
-       ep_add_request(ep, req);
-       spin_unlock_irqrestore(&ep->lock, flags);
-
-       if (is_ep0(ep)) {
-               switch (dev->ep0state) {
-               case WAIT_ACK_SET_CONF_INTERF:
-                       if (length == 0) {
-                               ep_end_in_req(ep, req, NULL);
-                       } else {
-                               ep_err(ep, "got a request of %d bytes while"
-                                       "in state WAIT_ACK_SET_CONF_INTERF\n",
-                                       length);
-                               ep_del_request(ep, req);
-                               rc = -EL2HLT;
-                       }
-                       ep0_idle(ep->dev);
-                       break;
-               case IN_DATA_STAGE:
-                       if (!ep_is_full(ep))
-                               if (write_ep0_fifo(ep, req))
-                                       ep0_end_in_req(ep, req, NULL);
-                       break;
-               case OUT_DATA_STAGE:
-                       if ((length == 0) || !epout_has_pkt(ep))
-                               if (read_ep0_fifo(ep, req))
-                                       ep0_end_out_req(ep, req, NULL);
-                       break;
-               default:
-                       ep_err(ep, "odd state %s to send me a request\n",
-                               EP0_STNAME(ep->dev));
-                       ep_del_request(ep, req);
-                       rc = -EL2HLT;
-                       break;
-               }
-       } else {
-               if (!recursion_detected)
-                       handle_ep(ep);
-       }
-
-out:
-       return rc;
-out_locked:
-       spin_unlock_irqrestore(&ep->lock, flags);
-       goto out;
-}
-
-/**
- * pxa_ep_dequeue - Dequeue one request
- * @_ep: usb endpoint
- * @_req: usb request
- *
- * Return 0 if no error, -EINVAL or -ECONNRESET otherwise
- */
-static int pxa_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct pxa_ep           *ep;
-       struct udc_usb_ep       *udc_usb_ep;
-       struct pxa27x_request   *req;
-       unsigned long           flags;
-       int                     rc = -EINVAL;
-
-       if (!_ep)
-               return rc;
-       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
-       ep = udc_usb_ep->pxa_ep;
-       if (!ep || is_ep0(ep))
-               return rc;
-
-       spin_lock_irqsave(&ep->lock, flags);
-
-       /* make sure it's actually queued on this endpoint */
-       list_for_each_entry(req, &ep->queue, queue) {
-               if (&req->req == _req) {
-                       rc = 0;
-                       break;
-               }
-       }
-
-       spin_unlock_irqrestore(&ep->lock, flags);
-       if (!rc)
-               req_done(ep, req, -ECONNRESET, NULL);
-       return rc;
-}
-
-/**
- * pxa_ep_set_halt - Halts operations on one endpoint
- * @_ep: usb endpoint
- * @value:
- *
- * Returns 0 if no error, -EINVAL, -EROFS, -EAGAIN otherwise
- */
-static int pxa_ep_set_halt(struct usb_ep *_ep, int value)
-{
-       struct pxa_ep           *ep;
-       struct udc_usb_ep       *udc_usb_ep;
-       unsigned long flags;
-       int rc;
-
-
-       if (!_ep)
-               return -EINVAL;
-       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
-       ep = udc_usb_ep->pxa_ep;
-       if (!ep || is_ep0(ep))
-               return -EINVAL;
-
-       if (value == 0) {
-               /*
-                * This path (reset toggle+halt) is needed to implement
-                * SET_INTERFACE on normal hardware.  but it can't be
-                * done from software on the PXA UDC, and the hardware
-                * forgets to do it as part of SET_INTERFACE automagic.
-                */
-               ep_dbg(ep, "only host can clear halt\n");
-               return -EROFS;
-       }
-
-       spin_lock_irqsave(&ep->lock, flags);
-
-       rc = -EAGAIN;
-       if (ep->dir_in  && (ep_is_full(ep) || !list_empty(&ep->queue)))
-               goto out;
-
-       /* FST, FEF bits are the same for control and non control endpoints */
-       rc = 0;
-       ep_write_UDCCSR(ep, UDCCSR_FST | UDCCSR_FEF);
-       if (is_ep0(ep))
-               set_ep0state(ep->dev, STALL);
-
-out:
-       spin_unlock_irqrestore(&ep->lock, flags);
-       return rc;
-}
-
-/**
- * pxa_ep_fifo_status - Get how many bytes in physical endpoint
- * @_ep: usb endpoint
- *
- * Returns number of bytes in OUT fifos. Broken for IN fifos.
- */
-static int pxa_ep_fifo_status(struct usb_ep *_ep)
-{
-       struct pxa_ep           *ep;
-       struct udc_usb_ep       *udc_usb_ep;
-
-       if (!_ep)
-               return -ENODEV;
-       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
-       ep = udc_usb_ep->pxa_ep;
-       if (!ep || is_ep0(ep))
-               return -ENODEV;
-
-       if (ep->dir_in)
-               return -EOPNOTSUPP;
-       if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN || ep_is_empty(ep))
-               return 0;
-       else
-               return ep_count_bytes_remain(ep) + 1;
-}
-
-/**
- * pxa_ep_fifo_flush - Flushes one endpoint
- * @_ep: usb endpoint
- *
- * Discards all data in one endpoint(IN or OUT), except control endpoint.
- */
-static void pxa_ep_fifo_flush(struct usb_ep *_ep)
-{
-       struct pxa_ep           *ep;
-       struct udc_usb_ep       *udc_usb_ep;
-       unsigned long           flags;
-
-       if (!_ep)
-               return;
-       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
-       ep = udc_usb_ep->pxa_ep;
-       if (!ep || is_ep0(ep))
-               return;
-
-       spin_lock_irqsave(&ep->lock, flags);
-
-       if (unlikely(!list_empty(&ep->queue)))
-               ep_dbg(ep, "called while queue list not empty\n");
-       ep_dbg(ep, "called\n");
-
-       /* for OUT, just read and discard the FIFO contents. */
-       if (!ep->dir_in) {
-               while (!ep_is_empty(ep))
-                       udc_ep_readl(ep, UDCDR);
-       } else {
-               /* most IN status is the same, but ISO can't stall */
-               ep_write_UDCCSR(ep,
-                               UDCCSR_PC | UDCCSR_FEF | UDCCSR_TRN
-                               | (EPXFERTYPE_is_ISO(ep) ? 0 : UDCCSR_SST));
-       }
-
-       spin_unlock_irqrestore(&ep->lock, flags);
-}
-
-/**
- * pxa_ep_enable - Enables usb endpoint
- * @_ep: usb endpoint
- * @desc: usb endpoint descriptor
- *
- * Nothing much to do here, as ep configuration is done once and for all
- * before udc is enabled. After udc enable, no physical endpoint configuration
- * can be changed.
- * Function makes sanity checks and flushes the endpoint.
- */
-static int pxa_ep_enable(struct usb_ep *_ep,
-       const struct usb_endpoint_descriptor *desc)
-{
-       struct pxa_ep           *ep;
-       struct udc_usb_ep       *udc_usb_ep;
-       struct pxa_udc          *udc;
-
-       if (!_ep || !desc)
-               return -EINVAL;
-
-       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
-       if (udc_usb_ep->pxa_ep) {
-               ep = udc_usb_ep->pxa_ep;
-               ep_warn(ep, "usb_ep %s already enabled, doing nothing\n",
-                       _ep->name);
-       } else {
-               ep = find_pxa_ep(udc_usb_ep->dev, udc_usb_ep);
-       }
-
-       if (!ep || is_ep0(ep)) {
-               dev_err(udc_usb_ep->dev->dev,
-                       "unable to match pxa_ep for ep %s\n",
-                       _ep->name);
-               return -EINVAL;
-       }
-
-       if ((desc->bDescriptorType != USB_DT_ENDPOINT)
-                       || (ep->type != usb_endpoint_type(desc))) {
-               ep_err(ep, "type mismatch\n");
-               return -EINVAL;
-       }
-
-       if (ep->fifo_size < usb_endpoint_maxp(desc)) {
-               ep_err(ep, "bad maxpacket\n");
-               return -ERANGE;
-       }
-
-       udc_usb_ep->pxa_ep = ep;
-       udc = ep->dev;
-
-       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
-               ep_err(ep, "bogus device state\n");
-               return -ESHUTDOWN;
-       }
-
-       ep->enabled = 1;
-
-       /* flush fifo (mostly for OUT buffers) */
-       pxa_ep_fifo_flush(_ep);
-
-       ep_dbg(ep, "enabled\n");
-       return 0;
-}
-
-/**
- * pxa_ep_disable - Disable usb endpoint
- * @_ep: usb endpoint
- *
- * Same as for pxa_ep_enable, no physical endpoint configuration can be
- * changed.
- * Function flushes the endpoint and related requests.
- */
-static int pxa_ep_disable(struct usb_ep *_ep)
-{
-       struct pxa_ep           *ep;
-       struct udc_usb_ep       *udc_usb_ep;
-
-       if (!_ep)
-               return -EINVAL;
-
-       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
-       ep = udc_usb_ep->pxa_ep;
-       if (!ep || is_ep0(ep) || !list_empty(&ep->queue))
-               return -EINVAL;
-
-       ep->enabled = 0;
-       nuke(ep, -ESHUTDOWN);
-
-       pxa_ep_fifo_flush(_ep);
-       udc_usb_ep->pxa_ep = NULL;
-
-       ep_dbg(ep, "disabled\n");
-       return 0;
-}
-
-static struct usb_ep_ops pxa_ep_ops = {
-       .enable         = pxa_ep_enable,
-       .disable        = pxa_ep_disable,
-
-       .alloc_request  = pxa_ep_alloc_request,
-       .free_request   = pxa_ep_free_request,
-
-       .queue          = pxa_ep_queue,
-       .dequeue        = pxa_ep_dequeue,
-
-       .set_halt       = pxa_ep_set_halt,
-       .fifo_status    = pxa_ep_fifo_status,
-       .fifo_flush     = pxa_ep_fifo_flush,
-};
-
-/**
- * dplus_pullup - Connect or disconnect pullup resistor to D+ pin
- * @udc: udc device
- * @on: 0 if disconnect pullup resistor, 1 otherwise
- * Context: any
- *
- * Handle D+ pullup resistor, make the device visible to the usb bus, and
- * declare it as a full speed usb device
- */
-static void dplus_pullup(struct pxa_udc *udc, int on)
-{
-       if (on) {
-               if (gpio_is_valid(udc->mach->gpio_pullup))
-                       gpio_set_value(udc->mach->gpio_pullup,
-                                      !udc->mach->gpio_pullup_inverted);
-               if (udc->mach->udc_command)
-                       udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
-       } else {
-               if (gpio_is_valid(udc->mach->gpio_pullup))
-                       gpio_set_value(udc->mach->gpio_pullup,
-                                      udc->mach->gpio_pullup_inverted);
-               if (udc->mach->udc_command)
-                       udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
-       }
-       udc->pullup_on = on;
-}
-
-/**
- * pxa_udc_get_frame - Returns usb frame number
- * @_gadget: usb gadget
- */
-static int pxa_udc_get_frame(struct usb_gadget *_gadget)
-{
-       struct pxa_udc *udc = to_gadget_udc(_gadget);
-
-       return (udc_readl(udc, UDCFNR) & 0x7ff);
-}
-
-/**
- * pxa_udc_wakeup - Force udc device out of suspend
- * @_gadget: usb gadget
- *
- * Returns 0 if successful, error code otherwise
- */
-static int pxa_udc_wakeup(struct usb_gadget *_gadget)
-{
-       struct pxa_udc *udc = to_gadget_udc(_gadget);
-
-       /* host may not have enabled remote wakeup */
-       if ((udc_readl(udc, UDCCR) & UDCCR_DWRE) == 0)
-               return -EHOSTUNREACH;
-       udc_set_mask_UDCCR(udc, UDCCR_UDR);
-       return 0;
-}
-
-static void udc_enable(struct pxa_udc *udc);
-static void udc_disable(struct pxa_udc *udc);
-
-/**
- * should_enable_udc - Tells if UDC should be enabled
- * @udc: udc device
- * Context: any
- *
- * The UDC should be enabled if :
-
- *  - the pullup resistor is connected
- *  - and a gadget driver is bound
- *  - and vbus is sensed (or no vbus sense is available)
- *
- * Returns 1 if UDC should be enabled, 0 otherwise
- */
-static int should_enable_udc(struct pxa_udc *udc)
-{
-       int put_on;
-
-       put_on = ((udc->pullup_on) && (udc->driver));
-       put_on &= ((udc->vbus_sensed) || (IS_ERR_OR_NULL(udc->transceiver)));
-       return put_on;
-}
-
-/**
- * should_disable_udc - Tells if UDC should be disabled
- * @udc: udc device
- * Context: any
- *
- * The UDC should be disabled if :
- *  - the pullup resistor is not connected
- *  - or no gadget driver is bound
- *  - or no vbus is sensed (when vbus sesing is available)
- *
- * Returns 1 if UDC should be disabled
- */
-static int should_disable_udc(struct pxa_udc *udc)
-{
-       int put_off;
-
-       put_off = ((!udc->pullup_on) || (!udc->driver));
-       put_off |= ((!udc->vbus_sensed) && (!IS_ERR_OR_NULL(udc->transceiver)));
-       return put_off;
-}
-
-/**
- * pxa_udc_pullup - Offer manual D+ pullup control
- * @_gadget: usb gadget using the control
- * @is_active: 0 if disconnect, else connect D+ pullup resistor
- * Context: !in_interrupt()
- *
- * Returns 0 if OK, -EOPNOTSUPP if udc driver doesn't handle D+ pullup
- */
-static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active)
-{
-       struct pxa_udc *udc = to_gadget_udc(_gadget);
-
-       if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
-               return -EOPNOTSUPP;
-
-       dplus_pullup(udc, is_active);
-
-       if (should_enable_udc(udc))
-               udc_enable(udc);
-       if (should_disable_udc(udc))
-               udc_disable(udc);
-       return 0;
-}
-
-static void udc_enable(struct pxa_udc *udc);
-static void udc_disable(struct pxa_udc *udc);
-
-/**
- * pxa_udc_vbus_session - Called by external transceiver to enable/disable udc
- * @_gadget: usb gadget
- * @is_active: 0 if should disable the udc, 1 if should enable
- *
- * Enables the udc, and optionnaly activates D+ pullup resistor. Or disables the
- * udc, and deactivates D+ pullup resistor.
- *
- * Returns 0
- */
-static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
-{
-       struct pxa_udc *udc = to_gadget_udc(_gadget);
-
-       udc->vbus_sensed = is_active;
-       if (should_enable_udc(udc))
-               udc_enable(udc);
-       if (should_disable_udc(udc))
-               udc_disable(udc);
-
-       return 0;
-}
-
-/**
- * pxa_udc_vbus_draw - Called by gadget driver after SET_CONFIGURATION completed
- * @_gadget: usb gadget
- * @mA: current drawn
- *
- * Context: !in_interrupt()
- *
- * Called after a configuration was chosen by a USB host, to inform how much
- * current can be drawn by the device from VBus line.
- *
- * Returns 0 or -EOPNOTSUPP if no transceiver is handling the udc
- */
-static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
-{
-       struct pxa_udc *udc;
-
-       udc = to_gadget_udc(_gadget);
-       if (!IS_ERR_OR_NULL(udc->transceiver))
-               return usb_phy_set_power(udc->transceiver, mA);
-       return -EOPNOTSUPP;
-}
-
-static int pxa27x_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-static int pxa27x_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-
-static const struct usb_gadget_ops pxa_udc_ops = {
-       .get_frame      = pxa_udc_get_frame,
-       .wakeup         = pxa_udc_wakeup,
-       .pullup         = pxa_udc_pullup,
-       .vbus_session   = pxa_udc_vbus_session,
-       .vbus_draw      = pxa_udc_vbus_draw,
-       .udc_start      = pxa27x_udc_start,
-       .udc_stop       = pxa27x_udc_stop,
-};
-
-/**
- * udc_disable - disable udc device controller
- * @udc: udc device
- * Context: any
- *
- * Disables the udc device : disables clocks, udc interrupts, control endpoint
- * interrupts.
- */
-static void udc_disable(struct pxa_udc *udc)
-{
-       if (!udc->enabled)
-               return;
-
-       udc_writel(udc, UDCICR0, 0);
-       udc_writel(udc, UDCICR1, 0);
-
-       udc_clear_mask_UDCCR(udc, UDCCR_UDE);
-       clk_disable(udc->clk);
-
-       ep0_idle(udc);
-       udc->gadget.speed = USB_SPEED_UNKNOWN;
-
-       udc->enabled = 0;
-}
-
-/**
- * udc_init_data - Initialize udc device data structures
- * @dev: udc device
- *
- * Initializes gadget endpoint list, endpoints locks. No action is taken
- * on the hardware.
- */
-static void udc_init_data(struct pxa_udc *dev)
-{
-       int i;
-       struct pxa_ep *ep;
-
-       /* device/ep0 records init */
-       INIT_LIST_HEAD(&dev->gadget.ep_list);
-       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
-       dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0];
-       ep0_idle(dev);
-
-       /* PXA endpoints init */
-       for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
-               ep = &dev->pxa_ep[i];
-
-               ep->enabled = is_ep0(ep);
-               INIT_LIST_HEAD(&ep->queue);
-               spin_lock_init(&ep->lock);
-       }
-
-       /* USB endpoints init */
-       for (i = 1; i < NR_USB_ENDPOINTS; i++) {
-               list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list,
-                               &dev->gadget.ep_list);
-               usb_ep_set_maxpacket_limit(&dev->udc_usb_ep[i].usb_ep,
-                                          dev->udc_usb_ep[i].usb_ep.maxpacket);
-       }
-}
-
-/**
- * udc_enable - Enables the udc device
- * @dev: udc device
- *
- * Enables the udc device : enables clocks, udc interrupts, control endpoint
- * interrupts, sets usb as UDC client and setups endpoints.
- */
-static void udc_enable(struct pxa_udc *udc)
-{
-       if (udc->enabled)
-               return;
-
-       udc_writel(udc, UDCICR0, 0);
-       udc_writel(udc, UDCICR1, 0);
-       udc_clear_mask_UDCCR(udc, UDCCR_UDE);
-
-       clk_enable(udc->clk);
-
-       ep0_idle(udc);
-       udc->gadget.speed = USB_SPEED_FULL;
-       memset(&udc->stats, 0, sizeof(udc->stats));
-
-       udc_set_mask_UDCCR(udc, UDCCR_UDE);
-       ep_write_UDCCSR(&udc->pxa_ep[0], UDCCSR0_ACM);
-       udelay(2);
-       if (udc_readl(udc, UDCCR) & UDCCR_EMCE)
-               dev_err(udc->dev, "Configuration errors, udc disabled\n");
-
-       /*
-        * Caller must be able to sleep in order to cope with startup transients
-        */
-       msleep(100);
-
-       /* enable suspend/resume and reset irqs */
-       udc_writel(udc, UDCICR1,
-                       UDCICR1_IECC | UDCICR1_IERU
-                       | UDCICR1_IESU | UDCICR1_IERS);
-
-       /* enable ep0 irqs */
-       pio_irq_enable(&udc->pxa_ep[0]);
-
-       udc->enabled = 1;
-}
-
-/**
- * pxa27x_start - Register gadget driver
- * @driver: gadget driver
- * @bind: bind function
- *
- * When a driver is successfully registered, it will receive control requests
- * including set_configuration(), which enables non-control requests.  Then
- * usb traffic follows until a disconnect is reported.  Then a host may connect
- * again, or the driver might get unbound.
- *
- * Note that the udc is not automatically enabled. Check function
- * should_enable_udc().
- *
- * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
- */
-static int pxa27x_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct pxa_udc *udc = to_pxa(g);
-       int retval;
-
-       /* first hook up the driver ... */
-       udc->driver = driver;
-       dplus_pullup(udc, 1);
-
-       if (!IS_ERR_OR_NULL(udc->transceiver)) {
-               retval = otg_set_peripheral(udc->transceiver->otg,
-                                               &udc->gadget);
-               if (retval) {
-                       dev_err(udc->dev, "can't bind to transceiver\n");
-                       goto fail;
-               }
-       }
-
-       if (should_enable_udc(udc))
-               udc_enable(udc);
-       return 0;
-
-fail:
-       udc->driver = NULL;
-       return retval;
-}
-
-/**
- * stop_activity - Stops udc endpoints
- * @udc: udc device
- * @driver: gadget driver
- *
- * Disables all udc endpoints (even control endpoint), report disconnect to
- * the gadget user.
- */
-static void stop_activity(struct pxa_udc *udc, struct usb_gadget_driver *driver)
-{
-       int i;
-
-       /* don't disconnect drivers more than once */
-       if (udc->gadget.speed == USB_SPEED_UNKNOWN)
-               driver = NULL;
-       udc->gadget.speed = USB_SPEED_UNKNOWN;
-
-       for (i = 0; i < NR_USB_ENDPOINTS; i++)
-               pxa_ep_disable(&udc->udc_usb_ep[i].usb_ep);
-}
-
-/**
- * pxa27x_udc_stop - Unregister the gadget driver
- * @driver: gadget driver
- *
- * Returns 0 if no error, -ENODEV, -EINVAL otherwise
- */
-static int pxa27x_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct pxa_udc *udc = to_pxa(g);
-
-       stop_activity(udc, driver);
-       udc_disable(udc);
-       dplus_pullup(udc, 0);
-
-       udc->driver = NULL;
-
-       if (!IS_ERR_OR_NULL(udc->transceiver))
-               return otg_set_peripheral(udc->transceiver->otg, NULL);
-       return 0;
-}
-
-/**
- * handle_ep0_ctrl_req - handle control endpoint control request
- * @udc: udc device
- * @req: control request
- */
-static void handle_ep0_ctrl_req(struct pxa_udc *udc,
-                               struct pxa27x_request *req)
-{
-       struct pxa_ep *ep = &udc->pxa_ep[0];
-       union {
-               struct usb_ctrlrequest  r;
-               u32                     word[2];
-       } u;
-       int i;
-       int have_extrabytes = 0;
-       unsigned long flags;
-
-       nuke(ep, -EPROTO);
-       spin_lock_irqsave(&ep->lock, flags);
-
-       /*
-        * In the PXA320 manual, in the section about Back-to-Back setup
-        * packets, it describes this situation.  The solution is to set OPC to
-        * get rid of the status packet, and then continue with the setup
-        * packet. Generalize to pxa27x CPUs.
-        */
-       if (epout_has_pkt(ep) && (ep_count_bytes_remain(ep) == 0))
-               ep_write_UDCCSR(ep, UDCCSR0_OPC);
-
-       /* read SETUP packet */
-       for (i = 0; i < 2; i++) {
-               if (unlikely(ep_is_empty(ep)))
-                       goto stall;
-               u.word[i] = udc_ep_readl(ep, UDCDR);
-       }
-
-       have_extrabytes = !ep_is_empty(ep);
-       while (!ep_is_empty(ep)) {
-               i = udc_ep_readl(ep, UDCDR);
-               ep_err(ep, "wrong to have extra bytes for setup : 0x%08x\n", i);
-       }
-
-       ep_dbg(ep, "SETUP %02x.%02x v%04x i%04x l%04x\n",
-               u.r.bRequestType, u.r.bRequest,
-               le16_to_cpu(u.r.wValue), le16_to_cpu(u.r.wIndex),
-               le16_to_cpu(u.r.wLength));
-       if (unlikely(have_extrabytes))
-               goto stall;
-
-       if (u.r.bRequestType & USB_DIR_IN)
-               set_ep0state(udc, IN_DATA_STAGE);
-       else
-               set_ep0state(udc, OUT_DATA_STAGE);
-
-       /* Tell UDC to enter Data Stage */
-       ep_write_UDCCSR(ep, UDCCSR0_SA | UDCCSR0_OPC);
-
-       spin_unlock_irqrestore(&ep->lock, flags);
-       i = udc->driver->setup(&udc->gadget, &u.r);
-       spin_lock_irqsave(&ep->lock, flags);
-       if (i < 0)
-               goto stall;
-out:
-       spin_unlock_irqrestore(&ep->lock, flags);
-       return;
-stall:
-       ep_dbg(ep, "protocol STALL, udccsr0=%03x err %d\n",
-               udc_ep_readl(ep, UDCCSR), i);
-       ep_write_UDCCSR(ep, UDCCSR0_FST | UDCCSR0_FTF);
-       set_ep0state(udc, STALL);
-       goto out;
-}
-
-/**
- * handle_ep0 - Handle control endpoint data transfers
- * @udc: udc device
- * @fifo_irq: 1 if triggered by fifo service type irq
- * @opc_irq: 1 if triggered by output packet complete type irq
- *
- * Context : when in_interrupt() or with ep->lock held
- *
- * Tries to transfer all pending request data into the endpoint and/or
- * transfer all pending data in the endpoint into usb requests.
- * Handles states of ep0 automata.
- *
- * PXA27x hardware handles several standard usb control requests without
- * driver notification.  The requests fully handled by hardware are :
- *  SET_ADDRESS, SET_FEATURE, CLEAR_FEATURE, GET_CONFIGURATION, GET_INTERFACE,
- *  GET_STATUS
- * The requests handled by hardware, but with irq notification are :
- *  SYNCH_FRAME, SET_CONFIGURATION, SET_INTERFACE
- * The remaining standard requests really handled by handle_ep0 are :
- *  GET_DESCRIPTOR, SET_DESCRIPTOR, specific requests.
- * Requests standardized outside of USB 2.0 chapter 9 are handled more
- * uniformly, by gadget drivers.
- *
- * The control endpoint state machine is _not_ USB spec compliant, it's even
- * hardly compliant with Intel PXA270 developers guide.
- * The key points which inferred this state machine are :
- *   - on every setup token, bit UDCCSR0_SA is raised and held until cleared by
- *     software.
- *   - on every OUT packet received, UDCCSR0_OPC is raised and held until
- *     cleared by software.
- *   - clearing UDCCSR0_OPC always flushes ep0. If in setup stage, never do it
- *     before reading ep0.
- *     This is true only for PXA27x. This is not true anymore for PXA3xx family
- *     (check Back-to-Back setup packet in developers guide).
- *   - irq can be called on a "packet complete" event (opc_irq=1), while
- *     UDCCSR0_OPC is not yet raised (delta can be as big as 100ms
- *     from experimentation).
- *   - as UDCCSR0_SA can be activated while in irq handling, and clearing
- *     UDCCSR0_OPC would flush the setup data, we almost never clear UDCCSR0_OPC
- *     => we never actually read the "status stage" packet of an IN data stage
- *     => this is not documented in Intel documentation
- *   - hardware as no idea of STATUS STAGE, it only handle SETUP STAGE and DATA
- *     STAGE. The driver add STATUS STAGE to send last zero length packet in
- *     OUT_STATUS_STAGE.
- *   - special attention was needed for IN_STATUS_STAGE. If a packet complete
- *     event is detected, we terminate the status stage without ackowledging the
- *     packet (not to risk to loose a potential SETUP packet)
- */
-static void handle_ep0(struct pxa_udc *udc, int fifo_irq, int opc_irq)
-{
-       u32                     udccsr0;
-       struct pxa_ep           *ep = &udc->pxa_ep[0];
-       struct pxa27x_request   *req = NULL;
-       int                     completed = 0;
-
-       if (!list_empty(&ep->queue))
-               req = list_entry(ep->queue.next, struct pxa27x_request, queue);
-
-       udccsr0 = udc_ep_readl(ep, UDCCSR);
-       ep_dbg(ep, "state=%s, req=%p, udccsr0=0x%03x, udcbcr=%d, irq_msk=%x\n",
-               EP0_STNAME(udc), req, udccsr0, udc_ep_readl(ep, UDCBCR),
-               (fifo_irq << 1 | opc_irq));
-
-       if (udccsr0 & UDCCSR0_SST) {
-               ep_dbg(ep, "clearing stall status\n");
-               nuke(ep, -EPIPE);
-               ep_write_UDCCSR(ep, UDCCSR0_SST);
-               ep0_idle(udc);
-       }
-
-       if (udccsr0 & UDCCSR0_SA) {
-               nuke(ep, 0);
-               set_ep0state(udc, SETUP_STAGE);
-       }
-
-       switch (udc->ep0state) {
-       case WAIT_FOR_SETUP:
-               /*
-                * Hardware bug : beware, we cannot clear OPC, since we would
-                * miss a potential OPC irq for a setup packet.
-                * So, we only do ... nothing, and hope for a next irq with
-                * UDCCSR0_SA set.
-                */
-               break;
-       case SETUP_STAGE:
-               udccsr0 &= UDCCSR0_CTRL_REQ_MASK;
-               if (likely(udccsr0 == UDCCSR0_CTRL_REQ_MASK))
-                       handle_ep0_ctrl_req(udc, req);
-               break;
-       case IN_DATA_STAGE:                     /* GET_DESCRIPTOR */
-               if (epout_has_pkt(ep))
-                       ep_write_UDCCSR(ep, UDCCSR0_OPC);
-               if (req && !ep_is_full(ep))
-                       completed = write_ep0_fifo(ep, req);
-               if (completed)
-                       ep0_end_in_req(ep, req, NULL);
-               break;
-       case OUT_DATA_STAGE:                    /* SET_DESCRIPTOR */
-               if (epout_has_pkt(ep) && req)
-                       completed = read_ep0_fifo(ep, req);
-               if (completed)
-                       ep0_end_out_req(ep, req, NULL);
-               break;
-       case STALL:
-               ep_write_UDCCSR(ep, UDCCSR0_FST);
-               break;
-       case IN_STATUS_STAGE:
-               /*
-                * Hardware bug : beware, we cannot clear OPC, since we would
-                * miss a potential PC irq for a setup packet.
-                * So, we only put the ep0 into WAIT_FOR_SETUP state.
-                */
-               if (opc_irq)
-                       ep0_idle(udc);
-               break;
-       case OUT_STATUS_STAGE:
-       case WAIT_ACK_SET_CONF_INTERF:
-               ep_warn(ep, "should never get in %s state here!!!\n",
-                               EP0_STNAME(ep->dev));
-               ep0_idle(udc);
-               break;
-       }
-}
-
-/**
- * handle_ep - Handle endpoint data tranfers
- * @ep: pxa physical endpoint
- *
- * Tries to transfer all pending request data into the endpoint and/or
- * transfer all pending data in the endpoint into usb requests.
- *
- * Is always called when in_interrupt() and with ep->lock released.
- */
-static void handle_ep(struct pxa_ep *ep)
-{
-       struct pxa27x_request   *req;
-       int completed;
-       u32 udccsr;
-       int is_in = ep->dir_in;
-       int loop = 0;
-       unsigned long           flags;
-
-       spin_lock_irqsave(&ep->lock, flags);
-       if (ep->in_handle_ep)
-               goto recursion_detected;
-       ep->in_handle_ep = 1;
-
-       do {
-               completed = 0;
-               udccsr = udc_ep_readl(ep, UDCCSR);
-
-               if (likely(!list_empty(&ep->queue)))
-                       req = list_entry(ep->queue.next,
-                                       struct pxa27x_request, queue);
-               else
-                       req = NULL;
-
-               ep_dbg(ep, "req:%p, udccsr 0x%03x loop=%d\n",
-                               req, udccsr, loop++);
-
-               if (unlikely(udccsr & (UDCCSR_SST | UDCCSR_TRN)))
-                       udc_ep_writel(ep, UDCCSR,
-                                       udccsr & (UDCCSR_SST | UDCCSR_TRN));
-               if (!req)
-                       break;
-
-               if (unlikely(is_in)) {
-                       if (likely(!ep_is_full(ep)))
-                               completed = write_fifo(ep, req);
-               } else {
-                       if (likely(epout_has_pkt(ep)))
-                               completed = read_fifo(ep, req);
-               }
-
-               if (completed) {
-                       if (is_in)
-                               ep_end_in_req(ep, req, &flags);
-                       else
-                               ep_end_out_req(ep, req, &flags);
-               }
-       } while (completed);
-
-       ep->in_handle_ep = 0;
-recursion_detected:
-       spin_unlock_irqrestore(&ep->lock, flags);
-}
-
-/**
- * pxa27x_change_configuration - Handle SET_CONF usb request notification
- * @udc: udc device
- * @config: usb configuration
- *
- * Post the request to upper level.
- * Don't use any pxa specific harware configuration capabilities
- */
-static void pxa27x_change_configuration(struct pxa_udc *udc, int config)
-{
-       struct usb_ctrlrequest req ;
-
-       dev_dbg(udc->dev, "config=%d\n", config);
-
-       udc->config = config;
-       udc->last_interface = 0;
-       udc->last_alternate = 0;
-
-       req.bRequestType = 0;
-       req.bRequest = USB_REQ_SET_CONFIGURATION;
-       req.wValue = config;
-       req.wIndex = 0;
-       req.wLength = 0;
-
-       set_ep0state(udc, WAIT_ACK_SET_CONF_INTERF);
-       udc->driver->setup(&udc->gadget, &req);
-       ep_write_UDCCSR(&udc->pxa_ep[0], UDCCSR0_AREN);
-}
-
-/**
- * pxa27x_change_interface - Handle SET_INTERF usb request notification
- * @udc: udc device
- * @iface: interface number
- * @alt: alternate setting number
- *
- * Post the request to upper level.
- * Don't use any pxa specific harware configuration capabilities
- */
-static void pxa27x_change_interface(struct pxa_udc *udc, int iface, int alt)
-{
-       struct usb_ctrlrequest  req;
-
-       dev_dbg(udc->dev, "interface=%d, alternate setting=%d\n", iface, alt);
-
-       udc->last_interface = iface;
-       udc->last_alternate = alt;
-
-       req.bRequestType = USB_RECIP_INTERFACE;
-       req.bRequest = USB_REQ_SET_INTERFACE;
-       req.wValue = alt;
-       req.wIndex = iface;
-       req.wLength = 0;
-
-       set_ep0state(udc, WAIT_ACK_SET_CONF_INTERF);
-       udc->driver->setup(&udc->gadget, &req);
-       ep_write_UDCCSR(&udc->pxa_ep[0], UDCCSR0_AREN);
-}
-
-/*
- * irq_handle_data - Handle data transfer
- * @irq: irq IRQ number
- * @udc: dev pxa_udc device structure
- *
- * Called from irq handler, transferts data to or from endpoint to queue
- */
-static void irq_handle_data(int irq, struct pxa_udc *udc)
-{
-       int i;
-       struct pxa_ep *ep;
-       u32 udcisr0 = udc_readl(udc, UDCISR0) & UDCCISR0_EP_MASK;
-       u32 udcisr1 = udc_readl(udc, UDCISR1) & UDCCISR1_EP_MASK;
-
-       if (udcisr0 & UDCISR_INT_MASK) {
-               udc->pxa_ep[0].stats.irqs++;
-               udc_writel(udc, UDCISR0, UDCISR_INT(0, UDCISR_INT_MASK));
-               handle_ep0(udc, !!(udcisr0 & UDCICR_FIFOERR),
-                               !!(udcisr0 & UDCICR_PKTCOMPL));
-       }
-
-       udcisr0 >>= 2;
-       for (i = 1; udcisr0 != 0 && i < 16; udcisr0 >>= 2, i++) {
-               if (!(udcisr0 & UDCISR_INT_MASK))
-                       continue;
-
-               udc_writel(udc, UDCISR0, UDCISR_INT(i, UDCISR_INT_MASK));
-
-               WARN_ON(i >= ARRAY_SIZE(udc->pxa_ep));
-               if (i < ARRAY_SIZE(udc->pxa_ep)) {
-                       ep = &udc->pxa_ep[i];
-                       ep->stats.irqs++;
-                       handle_ep(ep);
-               }
-       }
-
-       for (i = 16; udcisr1 != 0 && i < 24; udcisr1 >>= 2, i++) {
-               udc_writel(udc, UDCISR1, UDCISR_INT(i - 16, UDCISR_INT_MASK));
-               if (!(udcisr1 & UDCISR_INT_MASK))
-                       continue;
-
-               WARN_ON(i >= ARRAY_SIZE(udc->pxa_ep));
-               if (i < ARRAY_SIZE(udc->pxa_ep)) {
-                       ep = &udc->pxa_ep[i];
-                       ep->stats.irqs++;
-                       handle_ep(ep);
-               }
-       }
-
-}
-
-/**
- * irq_udc_suspend - Handle IRQ "UDC Suspend"
- * @udc: udc device
- */
-static void irq_udc_suspend(struct pxa_udc *udc)
-{
-       udc_writel(udc, UDCISR1, UDCISR1_IRSU);
-       udc->stats.irqs_suspend++;
-
-       if (udc->gadget.speed != USB_SPEED_UNKNOWN
-                       && udc->driver && udc->driver->suspend)
-               udc->driver->suspend(&udc->gadget);
-       ep0_idle(udc);
-}
-
-/**
-  * irq_udc_resume - Handle IRQ "UDC Resume"
-  * @udc: udc device
-  */
-static void irq_udc_resume(struct pxa_udc *udc)
-{
-       udc_writel(udc, UDCISR1, UDCISR1_IRRU);
-       udc->stats.irqs_resume++;
-
-       if (udc->gadget.speed != USB_SPEED_UNKNOWN
-                       && udc->driver && udc->driver->resume)
-               udc->driver->resume(&udc->gadget);
-}
-
-/**
- * irq_udc_reconfig - Handle IRQ "UDC Change Configuration"
- * @udc: udc device
- */
-static void irq_udc_reconfig(struct pxa_udc *udc)
-{
-       unsigned config, interface, alternate, config_change;
-       u32 udccr = udc_readl(udc, UDCCR);
-
-       udc_writel(udc, UDCISR1, UDCISR1_IRCC);
-       udc->stats.irqs_reconfig++;
-
-       config = (udccr & UDCCR_ACN) >> UDCCR_ACN_S;
-       config_change = (config != udc->config);
-       pxa27x_change_configuration(udc, config);
-
-       interface = (udccr & UDCCR_AIN) >> UDCCR_AIN_S;
-       alternate = (udccr & UDCCR_AAISN) >> UDCCR_AAISN_S;
-       pxa27x_change_interface(udc, interface, alternate);
-
-       if (config_change)
-               update_pxa_ep_matches(udc);
-       udc_set_mask_UDCCR(udc, UDCCR_SMAC);
-}
-
-/**
- * irq_udc_reset - Handle IRQ "UDC Reset"
- * @udc: udc device
- */
-static void irq_udc_reset(struct pxa_udc *udc)
-{
-       u32 udccr = udc_readl(udc, UDCCR);
-       struct pxa_ep *ep = &udc->pxa_ep[0];
-
-       dev_info(udc->dev, "USB reset\n");
-       udc_writel(udc, UDCISR1, UDCISR1_IRRS);
-       udc->stats.irqs_reset++;
-
-       if ((udccr & UDCCR_UDA) == 0) {
-               dev_dbg(udc->dev, "USB reset start\n");
-               stop_activity(udc, udc->driver);
-       }
-       udc->gadget.speed = USB_SPEED_FULL;
-       memset(&udc->stats, 0, sizeof udc->stats);
-
-       nuke(ep, -EPROTO);
-       ep_write_UDCCSR(ep, UDCCSR0_FTF | UDCCSR0_OPC);
-       ep0_idle(udc);
-}
-
-/**
- * pxa_udc_irq - Main irq handler
- * @irq: irq number
- * @_dev: udc device
- *
- * Handles all udc interrupts
- */
-static irqreturn_t pxa_udc_irq(int irq, void *_dev)
-{
-       struct pxa_udc *udc = _dev;
-       u32 udcisr0 = udc_readl(udc, UDCISR0);
-       u32 udcisr1 = udc_readl(udc, UDCISR1);
-       u32 udccr = udc_readl(udc, UDCCR);
-       u32 udcisr1_spec;
-
-       dev_vdbg(udc->dev, "Interrupt, UDCISR0:0x%08x, UDCISR1:0x%08x, "
-                "UDCCR:0x%08x\n", udcisr0, udcisr1, udccr);
-
-       udcisr1_spec = udcisr1 & 0xf8000000;
-       if (unlikely(udcisr1_spec & UDCISR1_IRSU))
-               irq_udc_suspend(udc);
-       if (unlikely(udcisr1_spec & UDCISR1_IRRU))
-               irq_udc_resume(udc);
-       if (unlikely(udcisr1_spec & UDCISR1_IRCC))
-               irq_udc_reconfig(udc);
-       if (unlikely(udcisr1_spec & UDCISR1_IRRS))
-               irq_udc_reset(udc);
-
-       if ((udcisr0 & UDCCISR0_EP_MASK) | (udcisr1 & UDCCISR1_EP_MASK))
-               irq_handle_data(irq, udc);
-
-       return IRQ_HANDLED;
-}
-
-static struct pxa_udc memory = {
-       .gadget = {
-               .ops            = &pxa_udc_ops,
-               .ep0            = &memory.udc_usb_ep[0].usb_ep,
-               .name           = driver_name,
-               .dev = {
-                       .init_name      = "gadget",
-               },
-       },
-
-       .udc_usb_ep = {
-               USB_EP_CTRL,
-               USB_EP_OUT_BULK(1),
-               USB_EP_IN_BULK(2),
-               USB_EP_IN_ISO(3),
-               USB_EP_OUT_ISO(4),
-               USB_EP_IN_INT(5),
-       },
-
-       .pxa_ep = {
-               PXA_EP_CTRL,
-               /* Endpoints for gadget zero */
-               PXA_EP_OUT_BULK(1, 1, 3, 0, 0),
-               PXA_EP_IN_BULK(2,  2, 3, 0, 0),
-               /* Endpoints for ether gadget, file storage gadget */
-               PXA_EP_OUT_BULK(3, 1, 1, 0, 0),
-               PXA_EP_IN_BULK(4,  2, 1, 0, 0),
-               PXA_EP_IN_ISO(5,   3, 1, 0, 0),
-               PXA_EP_OUT_ISO(6,  4, 1, 0, 0),
-               PXA_EP_IN_INT(7,   5, 1, 0, 0),
-               /* Endpoints for RNDIS, serial */
-               PXA_EP_OUT_BULK(8, 1, 2, 0, 0),
-               PXA_EP_IN_BULK(9,  2, 2, 0, 0),
-               PXA_EP_IN_INT(10,  5, 2, 0, 0),
-               /*
-                * All the following endpoints are only for completion.  They
-                * won't never work, as multiple interfaces are really broken on
-                * the pxa.
-               */
-               PXA_EP_OUT_BULK(11, 1, 2, 1, 0),
-               PXA_EP_IN_BULK(12,  2, 2, 1, 0),
-               /* Endpoint for CDC Ether */
-               PXA_EP_OUT_BULK(13, 1, 1, 1, 1),
-               PXA_EP_IN_BULK(14,  2, 1, 1, 1),
-       }
-};
-
-/**
- * pxa_udc_probe - probes the udc device
- * @_dev: platform device
- *
- * Perform basic init : allocates udc clock, creates sysfs files, requests
- * irq.
- */
-static int pxa_udc_probe(struct platform_device *pdev)
-{
-       struct resource *regs;
-       struct pxa_udc *udc = &memory;
-       int retval = 0, gpio;
-
-       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!regs)
-               return -ENXIO;
-       udc->irq = platform_get_irq(pdev, 0);
-       if (udc->irq < 0)
-               return udc->irq;
-
-       udc->dev = &pdev->dev;
-       udc->mach = dev_get_platdata(&pdev->dev);
-       udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
-
-       gpio = udc->mach->gpio_pullup;
-       if (gpio_is_valid(gpio)) {
-               retval = gpio_request(gpio, "USB D+ pullup");
-               if (retval == 0)
-                       gpio_direction_output(gpio,
-                                      udc->mach->gpio_pullup_inverted);
-       }
-       if (retval) {
-               dev_err(&pdev->dev, "Couldn't request gpio %d : %d\n",
-                       gpio, retval);
-               return retval;
-       }
-
-       udc->clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(udc->clk)) {
-               retval = PTR_ERR(udc->clk);
-               goto err_clk;
-       }
-       retval = clk_prepare(udc->clk);
-       if (retval)
-               goto err_clk_prepare;
-
-       retval = -ENOMEM;
-       udc->regs = ioremap(regs->start, resource_size(regs));
-       if (!udc->regs) {
-               dev_err(&pdev->dev, "Unable to map UDC I/O memory\n");
-               goto err_map;
-       }
-
-       udc->vbus_sensed = 0;
-
-       the_controller = udc;
-       platform_set_drvdata(pdev, udc);
-       udc_init_data(udc);
-       pxa_eps_setup(udc);
-
-       /* irq setup after old hardware state is cleaned up */
-       retval = request_irq(udc->irq, pxa_udc_irq,
-                       IRQF_SHARED, driver_name, udc);
-       if (retval != 0) {
-               dev_err(udc->dev, "%s: can't get irq %i, err %d\n",
-                       driver_name, udc->irq, retval);
-               goto err_irq;
-       }
-
-       retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
-       if (retval)
-               goto err_add_udc;
-
-       pxa_init_debugfs(udc);
-
-       return 0;
-
-err_add_udc:
-       free_irq(udc->irq, udc);
-err_irq:
-       iounmap(udc->regs);
-err_map:
-       clk_unprepare(udc->clk);
-err_clk_prepare:
-       clk_put(udc->clk);
-       udc->clk = NULL;
-err_clk:
-       return retval;
-}
-
-/**
- * pxa_udc_remove - removes the udc device driver
- * @_dev: platform device
- */
-static int pxa_udc_remove(struct platform_device *_dev)
-{
-       struct pxa_udc *udc = platform_get_drvdata(_dev);
-       int gpio = udc->mach->gpio_pullup;
-
-       usb_del_gadget_udc(&udc->gadget);
-       usb_gadget_unregister_driver(udc->driver);
-       free_irq(udc->irq, udc);
-       pxa_cleanup_debugfs(udc);
-       if (gpio_is_valid(gpio))
-               gpio_free(gpio);
-
-       usb_put_phy(udc->transceiver);
-
-       udc->transceiver = NULL;
-       the_controller = NULL;
-       clk_unprepare(udc->clk);
-       clk_put(udc->clk);
-       iounmap(udc->regs);
-
-       return 0;
-}
-
-static void pxa_udc_shutdown(struct platform_device *_dev)
-{
-       struct pxa_udc *udc = platform_get_drvdata(_dev);
-
-       if (udc_readl(udc, UDCCR) & UDCCR_UDE)
-               udc_disable(udc);
-}
-
-#ifdef CONFIG_PXA27x
-extern void pxa27x_clear_otgph(void);
-#else
-#define pxa27x_clear_otgph()   do {} while (0)
-#endif
-
-#ifdef CONFIG_PM
-/**
- * pxa_udc_suspend - Suspend udc device
- * @_dev: platform device
- * @state: suspend state
- *
- * Suspends udc : saves configuration registers (UDCCR*), then disables the udc
- * device.
- */
-static int pxa_udc_suspend(struct platform_device *_dev, pm_message_t state)
-{
-       int i;
-       struct pxa_udc *udc = platform_get_drvdata(_dev);
-       struct pxa_ep *ep;
-
-       ep = &udc->pxa_ep[0];
-       udc->udccsr0 = udc_ep_readl(ep, UDCCSR);
-       for (i = 1; i < NR_PXA_ENDPOINTS; i++) {
-               ep = &udc->pxa_ep[i];
-               ep->udccsr_value = udc_ep_readl(ep, UDCCSR);
-               ep->udccr_value  = udc_ep_readl(ep, UDCCR);
-               ep_dbg(ep, "udccsr:0x%03x, udccr:0x%x\n",
-                               ep->udccsr_value, ep->udccr_value);
-       }
-
-       udc_disable(udc);
-       udc->pullup_resume = udc->pullup_on;
-       dplus_pullup(udc, 0);
-
-       return 0;
-}
-
-/**
- * pxa_udc_resume - Resume udc device
- * @_dev: platform device
- *
- * Resumes udc : restores configuration registers (UDCCR*), then enables the udc
- * device.
- */
-static int pxa_udc_resume(struct platform_device *_dev)
-{
-       int i;
-       struct pxa_udc *udc = platform_get_drvdata(_dev);
-       struct pxa_ep *ep;
-
-       ep = &udc->pxa_ep[0];
-       udc_ep_writel(ep, UDCCSR, udc->udccsr0 & (UDCCSR0_FST | UDCCSR0_DME));
-       for (i = 1; i < NR_PXA_ENDPOINTS; i++) {
-               ep = &udc->pxa_ep[i];
-               udc_ep_writel(ep, UDCCSR, ep->udccsr_value);
-               udc_ep_writel(ep, UDCCR,  ep->udccr_value);
-               ep_dbg(ep, "udccsr:0x%03x, udccr:0x%x\n",
-                               ep->udccsr_value, ep->udccr_value);
-       }
-
-       dplus_pullup(udc, udc->pullup_resume);
-       if (should_enable_udc(udc))
-               udc_enable(udc);
-       /*
-        * We do not handle OTG yet.
-        *
-        * OTGPH bit is set when sleep mode is entered.
-        * it indicates that OTG pad is retaining its state.
-        * Upon exit from sleep mode and before clearing OTGPH,
-        * Software must configure the USB OTG pad, UDC, and UHC
-        * to the state they were in before entering sleep mode.
-        */
-       pxa27x_clear_otgph();
-
-       return 0;
-}
-#endif
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:pxa27x-udc");
-
-static struct platform_driver udc_driver = {
-       .driver         = {
-               .name   = "pxa27x-udc",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = pxa_udc_probe,
-       .remove         = pxa_udc_remove,
-       .shutdown       = pxa_udc_shutdown,
-#ifdef CONFIG_PM
-       .suspend        = pxa_udc_suspend,
-       .resume         = pxa_udc_resume
-#endif
-};
-
-module_platform_driver(udc_driver);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Robert Jarzmik");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h
deleted file mode 100644 (file)
index 28f2b53..0000000
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * linux/drivers/usb/gadget/pxa27x_udc.h
- * Intel PXA27x on-chip full speed USB device controller
- *
- * Inspired by original driver by Frank Becker, David Brownell, and others.
- * Copyright (C) 2008 Robert Jarzmik
- *
- * 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.
- */
-
-#ifndef __LINUX_USB_GADGET_PXA27X_H
-#define __LINUX_USB_GADGET_PXA27X_H
-
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/usb/otg.h>
-
-/*
- * Register definitions
- */
-/* Offsets */
-#define UDCCR          0x0000          /* UDC Control Register */
-#define UDCICR0                0x0004          /* UDC Interrupt Control Register0 */
-#define UDCICR1                0x0008          /* UDC Interrupt Control Register1 */
-#define UDCISR0                0x000C          /* UDC Interrupt Status Register 0 */
-#define UDCISR1                0x0010          /* UDC Interrupt Status Register 1 */
-#define UDCFNR         0x0014          /* UDC Frame Number Register */
-#define UDCOTGICR      0x0018          /* UDC On-The-Go interrupt control */
-#define UP2OCR         0x0020          /* USB Port 2 Output Control register */
-#define UP3OCR         0x0024          /* USB Port 3 Output Control register */
-#define UDCCSRn(x)     (0x0100 + ((x)<<2)) /* UDC Control/Status register */
-#define UDCBCRn(x)     (0x0200 + ((x)<<2)) /* UDC Byte Count Register */
-#define UDCDRn(x)      (0x0300 + ((x)<<2)) /* UDC Data Register  */
-#define UDCCRn(x)      (0x0400 + ((x)<<2)) /* UDC Control Register */
-
-#define UDCCR_OEN      (1 << 31)       /* On-the-Go Enable */
-#define UDCCR_AALTHNP  (1 << 30)       /* A-device Alternate Host Negotiation
-                                          Protocol Port Support */
-#define UDCCR_AHNP     (1 << 29)       /* A-device Host Negotiation Protocol
-                                          Support */
-#define UDCCR_BHNP     (1 << 28)       /* B-device Host Negotiation Protocol
-                                          Enable */
-#define UDCCR_DWRE     (1 << 16)       /* Device Remote Wake-up Enable */
-#define UDCCR_ACN      (0x03 << 11)    /* Active UDC configuration Number */
-#define UDCCR_ACN_S    11
-#define UDCCR_AIN      (0x07 << 8)     /* Active UDC interface Number */
-#define UDCCR_AIN_S    8
-#define UDCCR_AAISN    (0x07 << 5)     /* Active UDC Alternate Interface
-                                          Setting Number */
-#define UDCCR_AAISN_S  5
-#define UDCCR_SMAC     (1 << 4)        /* Switch Endpoint Memory to Active
-                                          Configuration */
-#define UDCCR_EMCE     (1 << 3)        /* Endpoint Memory Configuration
-                                          Error */
-#define UDCCR_UDR      (1 << 2)        /* UDC Resume */
-#define UDCCR_UDA      (1 << 1)        /* UDC Active */
-#define UDCCR_UDE      (1 << 0)        /* UDC Enable */
-
-#define UDCICR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
-#define UDCICR1_IECC   (1 << 31)       /* IntEn - Configuration Change */
-#define UDCICR1_IESOF  (1 << 30)       /* IntEn - Start of Frame */
-#define UDCICR1_IERU   (1 << 29)       /* IntEn - Resume */
-#define UDCICR1_IESU   (1 << 28)       /* IntEn - Suspend */
-#define UDCICR1_IERS   (1 << 27)       /* IntEn - Reset */
-#define UDCICR_FIFOERR (1 << 1)        /* FIFO Error interrupt for EP */
-#define UDCICR_PKTCOMPL        (1 << 0)        /* Packet Complete interrupt for EP */
-#define UDCICR_INT_MASK        (UDCICR_FIFOERR | UDCICR_PKTCOMPL)
-
-#define UDCISR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
-#define UDCISR1_IRCC   (1 << 31)       /* IntReq - Configuration Change */
-#define UDCISR1_IRSOF  (1 << 30)       /* IntReq - Start of Frame */
-#define UDCISR1_IRRU   (1 << 29)       /* IntReq - Resume */
-#define UDCISR1_IRSU   (1 << 28)       /* IntReq - Suspend */
-#define UDCISR1_IRRS   (1 << 27)       /* IntReq - Reset */
-#define UDCISR_INT_MASK        (UDCICR_FIFOERR | UDCICR_PKTCOMPL)
-
-#define UDCOTGICR_IESF (1 << 24)       /* OTG SET_FEATURE command recvd */
-#define UDCOTGICR_IEXR (1 << 17)       /* Extra Transceiver Interrupt
-                                          Rising Edge Interrupt Enable */
-#define UDCOTGICR_IEXF (1 << 16)       /* Extra Transceiver Interrupt
-                                          Falling Edge Interrupt Enable */
-#define UDCOTGICR_IEVV40R (1 << 9)     /* OTG Vbus Valid 4.0V Rising Edge
-                                          Interrupt Enable */
-#define UDCOTGICR_IEVV40F (1 << 8)     /* OTG Vbus Valid 4.0V Falling Edge
-                                          Interrupt Enable */
-#define UDCOTGICR_IEVV44R (1 << 7)     /* OTG Vbus Valid 4.4V Rising Edge
-                                          Interrupt Enable */
-#define UDCOTGICR_IEVV44F (1 << 6)     /* OTG Vbus Valid 4.4V Falling Edge
-                                          Interrupt Enable */
-#define UDCOTGICR_IESVR        (1 << 5)        /* OTG Session Valid Rising Edge
-                                          Interrupt Enable */
-#define UDCOTGICR_IESVF        (1 << 4)        /* OTG Session Valid Falling Edge
-                                          Interrupt Enable */
-#define UDCOTGICR_IESDR        (1 << 3)        /* OTG A-Device SRP Detect Rising
-                                          Edge Interrupt Enable */
-#define UDCOTGICR_IESDF        (1 << 2)        /* OTG A-Device SRP Detect Falling
-                                          Edge Interrupt Enable */
-#define UDCOTGICR_IEIDR        (1 << 1)        /* OTG ID Change Rising Edge
-                                          Interrupt Enable */
-#define UDCOTGICR_IEIDF        (1 << 0)        /* OTG ID Change Falling Edge
-                                          Interrupt Enable */
-
-/* Host Port 2 field bits */
-#define UP2OCR_CPVEN   (1 << 0)        /* Charge Pump Vbus Enable */
-#define UP2OCR_CPVPE   (1 << 1)        /* Charge Pump Vbus Pulse Enable */
-                                       /* Transceiver enablers */
-#define UP2OCR_DPPDE   (1 << 2)        /*   D+ Pull Down Enable */
-#define UP2OCR_DMPDE   (1 << 3)        /*   D- Pull Down Enable */
-#define UP2OCR_DPPUE   (1 << 4)        /*   D+ Pull Up Enable */
-#define UP2OCR_DMPUE   (1 << 5)        /*   D- Pull Up Enable */
-#define UP2OCR_DPPUBE  (1 << 6)        /*   D+ Pull Up Bypass Enable */
-#define UP2OCR_DMPUBE  (1 << 7)        /*   D- Pull Up Bypass Enable */
-#define UP2OCR_EXSP    (1 << 8)        /* External Transceiver Speed Control */
-#define UP2OCR_EXSUS   (1 << 9)        /* External Transceiver Speed Enable */
-#define UP2OCR_IDON    (1 << 10)       /* OTG ID Read Enable */
-#define UP2OCR_HXS     (1 << 16)       /* Transceiver Output Select */
-#define UP2OCR_HXOE    (1 << 17)       /* Transceiver Output Enable */
-#define UP2OCR_SEOS    (1 << 24)       /* Single-Ended Output Select */
-
-#define UDCCSR0_ACM    (1 << 9)        /* Ack Control Mode */
-#define UDCCSR0_AREN   (1 << 8)        /* Ack Response Enable */
-#define UDCCSR0_SA     (1 << 7)        /* Setup Active */
-#define UDCCSR0_RNE    (1 << 6)        /* Receive FIFO Not Empty */
-#define UDCCSR0_FST    (1 << 5)        /* Force Stall */
-#define UDCCSR0_SST    (1 << 4)        /* Sent Stall */
-#define UDCCSR0_DME    (1 << 3)        /* DMA Enable */
-#define UDCCSR0_FTF    (1 << 2)        /* Flush Transmit FIFO */
-#define UDCCSR0_IPR    (1 << 1)        /* IN Packet Ready */
-#define UDCCSR0_OPC    (1 << 0)        /* OUT Packet Complete */
-
-#define UDCCSR_DPE     (1 << 9)        /* Data Packet Error */
-#define UDCCSR_FEF     (1 << 8)        /* Flush Endpoint FIFO */
-#define UDCCSR_SP      (1 << 7)        /* Short Packet Control/Status */
-#define UDCCSR_BNE     (1 << 6)        /* Buffer Not Empty (IN endpoints) */
-#define UDCCSR_BNF     (1 << 6)        /* Buffer Not Full (OUT endpoints) */
-#define UDCCSR_FST     (1 << 5)        /* Force STALL */
-#define UDCCSR_SST     (1 << 4)        /* Sent STALL */
-#define UDCCSR_DME     (1 << 3)        /* DMA Enable */
-#define UDCCSR_TRN     (1 << 2)        /* Tx/Rx NAK */
-#define UDCCSR_PC      (1 << 1)        /* Packet Complete */
-#define UDCCSR_FS      (1 << 0)        /* FIFO needs service */
-
-#define UDCCONR_CN     (0x03 << 25)    /* Configuration Number */
-#define UDCCONR_CN_S   25
-#define UDCCONR_IN     (0x07 << 22)    /* Interface Number */
-#define UDCCONR_IN_S   22
-#define UDCCONR_AISN   (0x07 << 19)    /* Alternate Interface Number */
-#define UDCCONR_AISN_S 19
-#define UDCCONR_EN     (0x0f << 15)    /* Endpoint Number */
-#define UDCCONR_EN_S   15
-#define UDCCONR_ET     (0x03 << 13)    /* Endpoint Type: */
-#define UDCCONR_ET_S   13
-#define UDCCONR_ET_INT (0x03 << 13)    /*   Interrupt */
-#define UDCCONR_ET_BULK        (0x02 << 13)    /*   Bulk */
-#define UDCCONR_ET_ISO (0x01 << 13)    /*   Isochronous */
-#define UDCCONR_ET_NU  (0x00 << 13)    /*   Not used */
-#define UDCCONR_ED     (1 << 12)       /* Endpoint Direction */
-#define UDCCONR_MPS    (0x3ff << 2)    /* Maximum Packet Size */
-#define UDCCONR_MPS_S  2
-#define UDCCONR_DE     (1 << 1)        /* Double Buffering Enable */
-#define UDCCONR_EE     (1 << 0)        /* Endpoint Enable */
-
-#define UDCCR_MASK_BITS (UDCCR_OEN | UDCCR_SMAC | UDCCR_UDR | UDCCR_UDE)
-#define UDCCSR_WR_MASK (UDCCSR_DME | UDCCSR_FST)
-#define UDC_FNR_MASK   (0x7ff)
-#define UDC_BCR_MASK   (0x3ff)
-
-/*
- * UDCCR = UDC Endpoint Configuration Registers
- * UDCCSR = UDC Control/Status Register for this EP
- * UDCBCR = UDC Byte Count Remaining (contents of OUT fifo)
- * UDCDR = UDC Endpoint Data Register (the fifo)
- */
-#define ofs_UDCCR(ep)  (UDCCRn(ep->idx))
-#define ofs_UDCCSR(ep) (UDCCSRn(ep->idx))
-#define ofs_UDCBCR(ep) (UDCBCRn(ep->idx))
-#define ofs_UDCDR(ep)  (UDCDRn(ep->idx))
-
-/* Register access macros */
-#define udc_ep_readl(ep, reg)  \
-       __raw_readl((ep)->dev->regs + ofs_##reg(ep))
-#define udc_ep_writel(ep, reg, value)  \
-       __raw_writel((value), ep->dev->regs + ofs_##reg(ep))
-#define udc_ep_readb(ep, reg)  \
-       __raw_readb((ep)->dev->regs + ofs_##reg(ep))
-#define udc_ep_writeb(ep, reg, value)  \
-       __raw_writeb((value), ep->dev->regs + ofs_##reg(ep))
-#define udc_readl(dev, reg)    \
-       __raw_readl((dev)->regs + (reg))
-#define udc_writel(udc, reg, value)    \
-       __raw_writel((value), (udc)->regs + (reg))
-
-#define UDCCSR_MASK            (UDCCSR_FST | UDCCSR_DME)
-#define UDCCISR0_EP_MASK       ~0
-#define UDCCISR1_EP_MASK       0xffff
-#define UDCCSR0_CTRL_REQ_MASK  (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE)
-
-#define EPIDX(ep)      (ep->idx)
-#define EPADDR(ep)     (ep->addr)
-#define EPXFERTYPE(ep) (ep->type)
-#define EPNAME(ep)     (ep->name)
-#define is_ep0(ep)     (!ep->idx)
-#define EPXFERTYPE_is_ISO(ep) (EPXFERTYPE(ep) == USB_ENDPOINT_XFER_ISOC)
-
-/*
- * Endpoint definitions
- *
- * Once enabled, pxa endpoint configuration is freezed, and cannot change
- * unless a reset happens or the udc is disabled.
- * Therefore, we must define all pxa potential endpoint definitions needed for
- * all gadget and set them up before the udc is enabled.
- *
- * As the architecture chosen is fully static, meaning the pxa endpoint
- * configurations are set up once and for all, we must provide a way to match
- * one usb endpoint (usb_ep) to several pxa endpoints. The reason is that gadget
- * layer autoconf doesn't choose the usb_ep endpoint on (config, interface, alt)
- * criteria, while the pxa architecture requires that.
- *
- * The solution is to define several pxa endpoints matching one usb_ep. Ex:
- *   - "ep1-in" matches pxa endpoint EPA (which is an IN ep at addr 1, when
- *     the udc talks on (config=3, interface=0, alt=0)
- *   - "ep1-in" matches pxa endpoint EPB (which is an IN ep at addr 1, when
- *     the udc talks on (config=3, interface=0, alt=1)
- *   - "ep1-in" matches pxa endpoint EPC (which is an IN ep at addr 1, when
- *     the udc talks on (config=2, interface=0, alt=0)
- *
- * We'll define the pxa endpoint by its index (EPA => idx=1, EPB => idx=2, ...)
- */
-
-/*
- * Endpoint definition helpers
- */
-#define USB_EP_DEF(addr, bname, dir, type, maxpkt) \
-{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, }, \
-  .desc = {    .bEndpointAddress = addr | (dir ? USB_DIR_IN : 0), \
-               .bmAttributes = type, \
-               .wMaxPacketSize = maxpkt, }, \
-  .dev = &memory \
-}
-#define USB_EP_BULK(addr, bname, dir) \
-  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE)
-#define USB_EP_ISO(addr, bname, dir) \
-  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE)
-#define USB_EP_INT(addr, bname, dir) \
-  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE)
-#define USB_EP_IN_BULK(n)      USB_EP_BULK(n, "ep" #n "in-bulk", 1)
-#define USB_EP_OUT_BULK(n)     USB_EP_BULK(n, "ep" #n "out-bulk", 0)
-#define USB_EP_IN_ISO(n)       USB_EP_ISO(n,  "ep" #n "in-iso", 1)
-#define USB_EP_OUT_ISO(n)      USB_EP_ISO(n,  "ep" #n "out-iso", 0)
-#define USB_EP_IN_INT(n)       USB_EP_INT(n,  "ep" #n "in-int", 1)
-#define USB_EP_CTRL            USB_EP_DEF(0,  "ep0", 0, 0, EP0_FIFO_SIZE)
-
-#define PXA_EP_DEF(_idx, _addr, dir, _type, maxpkt, _config, iface, altset) \
-{ \
-       .dev = &memory, \
-       .name = "ep" #_idx, \
-       .idx = _idx, .enabled = 0, \
-       .dir_in = dir, .addr = _addr, \
-       .config = _config, .interface = iface, .alternate = altset, \
-       .type = _type, .fifo_size = maxpkt, \
-}
-#define PXA_EP_BULK(_idx, addr, dir, config, iface, alt) \
-  PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE, \
-               config, iface, alt)
-#define PXA_EP_ISO(_idx, addr, dir, config, iface, alt) \
-  PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE, \
-               config, iface, alt)
-#define PXA_EP_INT(_idx, addr, dir, config, iface, alt) \
-  PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE, \
-               config, iface, alt)
-#define PXA_EP_IN_BULK(i, adr, c, f, a)                PXA_EP_BULK(i, adr, 1, c, f, a)
-#define PXA_EP_OUT_BULK(i, adr, c, f, a)       PXA_EP_BULK(i, adr, 0, c, f, a)
-#define PXA_EP_IN_ISO(i, adr, c, f, a)         PXA_EP_ISO(i, adr, 1, c, f, a)
-#define PXA_EP_OUT_ISO(i, adr, c, f, a)                PXA_EP_ISO(i, adr, 0, c, f, a)
-#define PXA_EP_IN_INT(i, adr, c, f, a)         PXA_EP_INT(i, adr, 1, c, f, a)
-#define PXA_EP_CTRL    PXA_EP_DEF(0, 0, 0, 0, EP0_FIFO_SIZE, 0, 0, 0)
-
-struct pxa27x_udc;
-
-struct stats {
-       unsigned long in_ops;
-       unsigned long out_ops;
-       unsigned long in_bytes;
-       unsigned long out_bytes;
-       unsigned long irqs;
-};
-
-/**
- * struct udc_usb_ep - container of each usb_ep structure
- * @usb_ep: usb endpoint
- * @desc: usb descriptor, especially type and address
- * @dev: udc managing this endpoint
- * @pxa_ep: matching pxa_ep (cache of find_pxa_ep() call)
- */
-struct udc_usb_ep {
-       struct usb_ep usb_ep;
-       struct usb_endpoint_descriptor desc;
-       struct pxa_udc *dev;
-       struct pxa_ep *pxa_ep;
-};
-
-/**
- * struct pxa_ep - pxa endpoint
- * @dev: udc device
- * @queue: requests queue
- * @lock: lock to pxa_ep data (queues and stats)
- * @enabled: true when endpoint enabled (not stopped by gadget layer)
- * @in_handle_ep: number of recursions of handle_ep() function
- *     Prevents deadlocks or infinite recursions of types :
- *       irq->handle_ep()->req_done()->req.complete()->pxa_ep_queue()->handle_ep()
- *      or
- *        pxa_ep_queue()->handle_ep()->req_done()->req.complete()->pxa_ep_queue()
- * @idx: endpoint index (1 => epA, 2 => epB, ..., 24 => epX)
- * @name: endpoint name (for trace/debug purpose)
- * @dir_in: 1 if IN endpoint, 0 if OUT endpoint
- * @addr: usb endpoint number
- * @config: configuration in which this endpoint is active
- * @interface: interface in which this endpoint is active
- * @alternate: altsetting in which this endpoitn is active
- * @fifo_size: max packet size in the endpoint fifo
- * @type: endpoint type (bulk, iso, int, ...)
- * @udccsr_value: save register of UDCCSR0 for suspend/resume
- * @udccr_value: save register of UDCCR for suspend/resume
- * @stats: endpoint statistics
- *
- * The *PROBLEM* is that pxa's endpoint configuration scheme is both misdesigned
- * (cares about config/interface/altsetting, thus placing needless limits on
- * device capability) and full of implementation bugs forcing it to be set up
- * for use more or less like a pxa255.
- *
- * As we define the pxa_ep statically, we must guess all needed pxa_ep for all
- * gadget which may work with this udc driver.
- */
-struct pxa_ep {
-       struct pxa_udc          *dev;
-
-       struct list_head        queue;
-       spinlock_t              lock;           /* Protects this structure */
-                                               /* (queues, stats) */
-       unsigned                enabled:1;
-       unsigned                in_handle_ep:1;
-
-       unsigned                idx:5;
-       char                    *name;
-
-       /*
-        * Specific pxa endpoint data, needed for hardware initialization
-        */
-       unsigned                dir_in:1;
-       unsigned                addr:4;
-       unsigned                config:2;
-       unsigned                interface:3;
-       unsigned                alternate:3;
-       unsigned                fifo_size;
-       unsigned                type;
-
-#ifdef CONFIG_PM
-       u32                     udccsr_value;
-       u32                     udccr_value;
-#endif
-       struct stats            stats;
-};
-
-/**
- * struct pxa27x_request - container of each usb_request structure
- * @req: usb request
- * @udc_usb_ep: usb endpoint the request was submitted on
- * @in_use: sanity check if request already queued on an pxa_ep
- * @queue: linked list of requests, linked on pxa_ep->queue
- */
-struct pxa27x_request {
-       struct usb_request                      req;
-       struct udc_usb_ep                       *udc_usb_ep;
-       unsigned                                in_use:1;
-       struct list_head                        queue;
-};
-
-enum ep0_state {
-       WAIT_FOR_SETUP,
-       SETUP_STAGE,
-       IN_DATA_STAGE,
-       OUT_DATA_STAGE,
-       IN_STATUS_STAGE,
-       OUT_STATUS_STAGE,
-       STALL,
-       WAIT_ACK_SET_CONF_INTERF
-};
-
-static char *ep0_state_name[] = {
-       "WAIT_FOR_SETUP", "SETUP_STAGE", "IN_DATA_STAGE", "OUT_DATA_STAGE",
-       "IN_STATUS_STAGE", "OUT_STATUS_STAGE", "STALL",
-       "WAIT_ACK_SET_CONF_INTERF"
-};
-#define EP0_STNAME(udc) ep0_state_name[(udc)->ep0state]
-
-#define EP0_FIFO_SIZE  16U
-#define BULK_FIFO_SIZE 64U
-#define ISO_FIFO_SIZE  256U
-#define INT_FIFO_SIZE  16U
-
-struct udc_stats {
-       unsigned long   irqs_reset;
-       unsigned long   irqs_suspend;
-       unsigned long   irqs_resume;
-       unsigned long   irqs_reconfig;
-};
-
-#define NR_USB_ENDPOINTS (1 + 5)       /* ep0 + ep1in-bulk + .. + ep3in-iso */
-#define NR_PXA_ENDPOINTS (1 + 14)      /* ep0 + epA + epB + .. + epX */
-
-/**
- * struct pxa_udc - udc structure
- * @regs: mapped IO space
- * @irq: udc irq
- * @clk: udc clock
- * @usb_gadget: udc gadget structure
- * @driver: bound gadget (zero, g_ether, g_mass_storage, ...)
- * @dev: device
- * @mach: machine info, used to activate specific GPIO
- * @transceiver: external transceiver to handle vbus sense and D+ pullup
- * @ep0state: control endpoint state machine state
- * @stats: statistics on udc usage
- * @udc_usb_ep: array of usb endpoints offered by the gadget
- * @pxa_ep: array of pxa available endpoints
- * @enabled: UDC was enabled by a previous udc_enable()
- * @pullup_on: if pullup resistor connected to D+ pin
- * @pullup_resume: if pullup resistor should be connected to D+ pin on resume
- * @config: UDC active configuration
- * @last_interface: UDC interface of the last SET_INTERFACE host request
- * @last_alternate: UDC altsetting of the last SET_INTERFACE host request
- * @udccsr0: save of udccsr0 in case of suspend
- * @debugfs_root: root entry of debug filesystem
- * @debugfs_state: debugfs entry for "udcstate"
- * @debugfs_queues: debugfs entry for "queues"
- * @debugfs_eps: debugfs entry for "epstate"
- */
-struct pxa_udc {
-       void __iomem                            *regs;
-       int                                     irq;
-       struct clk                              *clk;
-
-       struct usb_gadget                       gadget;
-       struct usb_gadget_driver                *driver;
-       struct device                           *dev;
-       struct pxa2xx_udc_mach_info             *mach;
-       struct usb_phy                          *transceiver;
-
-       enum ep0_state                          ep0state;
-       struct udc_stats                        stats;
-
-       struct udc_usb_ep                       udc_usb_ep[NR_USB_ENDPOINTS];
-       struct pxa_ep                           pxa_ep[NR_PXA_ENDPOINTS];
-
-       unsigned                                enabled:1;
-       unsigned                                pullup_on:1;
-       unsigned                                pullup_resume:1;
-       unsigned                                vbus_sensed:1;
-       unsigned                                config:2;
-       unsigned                                last_interface:3;
-       unsigned                                last_alternate:3;
-
-#ifdef CONFIG_PM
-       unsigned                                udccsr0;
-#endif
-#ifdef CONFIG_USB_GADGET_DEBUG_FS
-       struct dentry                           *debugfs_root;
-       struct dentry                           *debugfs_state;
-       struct dentry                           *debugfs_queues;
-       struct dentry                           *debugfs_eps;
-#endif
-};
-#define to_pxa(g)      (container_of((g), struct pxa_udc, gadget))
-
-static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget)
-{
-       return container_of(gadget, struct pxa_udc, gadget);
-}
-
-/*
- * Debugging/message support
- */
-#define ep_dbg(ep, fmt, arg...) \
-       dev_dbg(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
-#define ep_vdbg(ep, fmt, arg...) \
-       dev_vdbg(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
-#define ep_err(ep, fmt, arg...) \
-       dev_err(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
-#define ep_info(ep, fmt, arg...) \
-       dev_info(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
-#define ep_warn(ep, fmt, arg...) \
-       dev_warn(ep->dev->dev, "%s:%s:" fmt, EPNAME(ep), __func__, ## arg)
-
-#endif /* __LINUX_USB_GADGET_PXA27X_H */
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
deleted file mode 100644 (file)
index 4600842..0000000
+++ /dev/null
@@ -1,1993 +0,0 @@
-/*
- * R8A66597 UDC (USB gadget)
- *
- * Copyright (C) 2006-2009 Renesas Solutions Corp.
- *
- * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include "r8a66597-udc.h"
-
-#define DRIVER_VERSION "2011-09-26"
-
-static const char udc_name[] = "r8a66597_udc";
-static const char *r8a66597_ep_name[] = {
-       "ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7",
-       "ep8", "ep9",
-};
-
-static void init_controller(struct r8a66597 *r8a66597);
-static void disable_controller(struct r8a66597 *r8a66597);
-static void irq_ep0_write(struct r8a66597_ep *ep, struct r8a66597_request *req);
-static void irq_packet_write(struct r8a66597_ep *ep,
-                               struct r8a66597_request *req);
-static int r8a66597_queue(struct usb_ep *_ep, struct usb_request *_req,
-                       gfp_t gfp_flags);
-
-static void transfer_complete(struct r8a66597_ep *ep,
-               struct r8a66597_request *req, int status);
-
-/*-------------------------------------------------------------------------*/
-static inline u16 get_usb_speed(struct r8a66597 *r8a66597)
-{
-       return r8a66597_read(r8a66597, DVSTCTR0) & RHST;
-}
-
-static void enable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum,
-               unsigned long reg)
-{
-       u16 tmp;
-
-       tmp = r8a66597_read(r8a66597, INTENB0);
-       r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE,
-                       INTENB0);
-       r8a66597_bset(r8a66597, (1 << pipenum), reg);
-       r8a66597_write(r8a66597, tmp, INTENB0);
-}
-
-static void disable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum,
-               unsigned long reg)
-{
-       u16 tmp;
-
-       tmp = r8a66597_read(r8a66597, INTENB0);
-       r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE,
-                       INTENB0);
-       r8a66597_bclr(r8a66597, (1 << pipenum), reg);
-       r8a66597_write(r8a66597, tmp, INTENB0);
-}
-
-static void r8a66597_usb_connect(struct r8a66597 *r8a66597)
-{
-       r8a66597_bset(r8a66597, CTRE, INTENB0);
-       r8a66597_bset(r8a66597, BEMPE | BRDYE, INTENB0);
-
-       r8a66597_bset(r8a66597, DPRPU, SYSCFG0);
-}
-
-static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597)
-__releases(r8a66597->lock)
-__acquires(r8a66597->lock)
-{
-       r8a66597_bclr(r8a66597, CTRE, INTENB0);
-       r8a66597_bclr(r8a66597, BEMPE | BRDYE, INTENB0);
-       r8a66597_bclr(r8a66597, DPRPU, SYSCFG0);
-
-       r8a66597->gadget.speed = USB_SPEED_UNKNOWN;
-       spin_unlock(&r8a66597->lock);
-       r8a66597->driver->disconnect(&r8a66597->gadget);
-       spin_lock(&r8a66597->lock);
-
-       disable_controller(r8a66597);
-       init_controller(r8a66597);
-       r8a66597_bset(r8a66597, VBSE, INTENB0);
-       INIT_LIST_HEAD(&r8a66597->ep[0].queue);
-}
-
-static inline u16 control_reg_get_pid(struct r8a66597 *r8a66597, u16 pipenum)
-{
-       u16 pid = 0;
-       unsigned long offset;
-
-       if (pipenum == 0) {
-               pid = r8a66597_read(r8a66597, DCPCTR) & PID;
-       } else if (pipenum < R8A66597_MAX_NUM_PIPE) {
-               offset = get_pipectr_addr(pipenum);
-               pid = r8a66597_read(r8a66597, offset) & PID;
-       } else {
-               dev_err(r8a66597_to_dev(r8a66597), "unexpect pipe num (%d)\n",
-                       pipenum);
-       }
-
-       return pid;
-}
-
-static inline void control_reg_set_pid(struct r8a66597 *r8a66597, u16 pipenum,
-               u16 pid)
-{
-       unsigned long offset;
-
-       if (pipenum == 0) {
-               r8a66597_mdfy(r8a66597, pid, PID, DCPCTR);
-       } else if (pipenum < R8A66597_MAX_NUM_PIPE) {
-               offset = get_pipectr_addr(pipenum);
-               r8a66597_mdfy(r8a66597, pid, PID, offset);
-       } else {
-               dev_err(r8a66597_to_dev(r8a66597), "unexpect pipe num (%d)\n",
-                       pipenum);
-       }
-}
-
-static inline void pipe_start(struct r8a66597 *r8a66597, u16 pipenum)
-{
-       control_reg_set_pid(r8a66597, pipenum, PID_BUF);
-}
-
-static inline void pipe_stop(struct r8a66597 *r8a66597, u16 pipenum)
-{
-       control_reg_set_pid(r8a66597, pipenum, PID_NAK);
-}
-
-static inline void pipe_stall(struct r8a66597 *r8a66597, u16 pipenum)
-{
-       control_reg_set_pid(r8a66597, pipenum, PID_STALL);
-}
-
-static inline u16 control_reg_get(struct r8a66597 *r8a66597, u16 pipenum)
-{
-       u16 ret = 0;
-       unsigned long offset;
-
-       if (pipenum == 0) {
-               ret = r8a66597_read(r8a66597, DCPCTR);
-       } else if (pipenum < R8A66597_MAX_NUM_PIPE) {
-               offset = get_pipectr_addr(pipenum);
-               ret = r8a66597_read(r8a66597, offset);
-       } else {
-               dev_err(r8a66597_to_dev(r8a66597), "unexpect pipe num (%d)\n",
-                       pipenum);
-       }
-
-       return ret;
-}
-
-static inline void control_reg_sqclr(struct r8a66597 *r8a66597, u16 pipenum)
-{
-       unsigned long offset;
-
-       pipe_stop(r8a66597, pipenum);
-
-       if (pipenum == 0) {
-               r8a66597_bset(r8a66597, SQCLR, DCPCTR);
-       } else if (pipenum < R8A66597_MAX_NUM_PIPE) {
-               offset = get_pipectr_addr(pipenum);
-               r8a66597_bset(r8a66597, SQCLR, offset);
-       } else {
-               dev_err(r8a66597_to_dev(r8a66597), "unexpect pipe num (%d)\n",
-                       pipenum);
-       }
-}
-
-static void control_reg_sqset(struct r8a66597 *r8a66597, u16 pipenum)
-{
-       unsigned long offset;
-
-       pipe_stop(r8a66597, pipenum);
-
-       if (pipenum == 0) {
-               r8a66597_bset(r8a66597, SQSET, DCPCTR);
-       } else if (pipenum < R8A66597_MAX_NUM_PIPE) {
-               offset = get_pipectr_addr(pipenum);
-               r8a66597_bset(r8a66597, SQSET, offset);
-       } else {
-               dev_err(r8a66597_to_dev(r8a66597),
-                       "unexpect pipe num(%d)\n", pipenum);
-       }
-}
-
-static u16 control_reg_sqmon(struct r8a66597 *r8a66597, u16 pipenum)
-{
-       unsigned long offset;
-
-       if (pipenum == 0) {
-               return r8a66597_read(r8a66597, DCPCTR) & SQMON;
-       } else if (pipenum < R8A66597_MAX_NUM_PIPE) {
-               offset = get_pipectr_addr(pipenum);
-               return r8a66597_read(r8a66597, offset) & SQMON;
-       } else {
-               dev_err(r8a66597_to_dev(r8a66597),
-                       "unexpect pipe num(%d)\n", pipenum);
-       }
-
-       return 0;
-}
-
-static u16 save_usb_toggle(struct r8a66597 *r8a66597, u16 pipenum)
-{
-       return control_reg_sqmon(r8a66597, pipenum);
-}
-
-static void restore_usb_toggle(struct r8a66597 *r8a66597, u16 pipenum,
-                              u16 toggle)
-{
-       if (toggle)
-               control_reg_sqset(r8a66597, pipenum);
-       else
-               control_reg_sqclr(r8a66597, pipenum);
-}
-
-static inline int get_buffer_size(struct r8a66597 *r8a66597, u16 pipenum)
-{
-       u16 tmp;
-       int size;
-
-       if (pipenum == 0) {
-               tmp = r8a66597_read(r8a66597, DCPCFG);
-               if ((tmp & R8A66597_CNTMD) != 0)
-                       size = 256;
-               else {
-                       tmp = r8a66597_read(r8a66597, DCPMAXP);
-                       size = tmp & MAXP;
-               }
-       } else {
-               r8a66597_write(r8a66597, pipenum, PIPESEL);
-               tmp = r8a66597_read(r8a66597, PIPECFG);
-               if ((tmp & R8A66597_CNTMD) != 0) {
-                       tmp = r8a66597_read(r8a66597, PIPEBUF);
-                       size = ((tmp >> 10) + 1) * 64;
-               } else {
-                       tmp = r8a66597_read(r8a66597, PIPEMAXP);
-                       size = tmp & MXPS;
-               }
-       }
-
-       return size;
-}
-
-static inline unsigned short mbw_value(struct r8a66597 *r8a66597)
-{
-       if (r8a66597->pdata->on_chip)
-               return MBW_32;
-       else
-               return MBW_16;
-}
-
-static void r8a66597_change_curpipe(struct r8a66597 *r8a66597, u16 pipenum,
-                                   u16 isel, u16 fifosel)
-{
-       u16 tmp, mask, loop;
-       int i = 0;
-
-       if (!pipenum) {
-               mask = ISEL | CURPIPE;
-               loop = isel;
-       } else {
-               mask = CURPIPE;
-               loop = pipenum;
-       }
-       r8a66597_mdfy(r8a66597, loop, mask, fifosel);
-
-       do {
-               tmp = r8a66597_read(r8a66597, fifosel);
-               if (i++ > 1000000) {
-                       dev_err(r8a66597_to_dev(r8a66597),
-                               "r8a66597: register%x, loop %x "
-                               "is timeout\n", fifosel, loop);
-                       break;
-               }
-               ndelay(1);
-       } while ((tmp & mask) != loop);
-}
-
-static inline void pipe_change(struct r8a66597 *r8a66597, u16 pipenum)
-{
-       struct r8a66597_ep *ep = r8a66597->pipenum2ep[pipenum];
-
-       if (ep->use_dma)
-               r8a66597_bclr(r8a66597, DREQE, ep->fifosel);
-
-       r8a66597_mdfy(r8a66597, pipenum, CURPIPE, ep->fifosel);
-
-       ndelay(450);
-
-       if (r8a66597_is_sudmac(r8a66597) && ep->use_dma)
-               r8a66597_bclr(r8a66597, mbw_value(r8a66597), ep->fifosel);
-       else
-               r8a66597_bset(r8a66597, mbw_value(r8a66597), ep->fifosel);
-
-       if (ep->use_dma)
-               r8a66597_bset(r8a66597, DREQE, ep->fifosel);
-}
-
-static int pipe_buffer_setting(struct r8a66597 *r8a66597,
-               struct r8a66597_pipe_info *info)
-{
-       u16 bufnum = 0, buf_bsize = 0;
-       u16 pipecfg = 0;
-
-       if (info->pipe == 0)
-               return -EINVAL;
-
-       r8a66597_write(r8a66597, info->pipe, PIPESEL);
-
-       if (info->dir_in)
-               pipecfg |= R8A66597_DIR;
-       pipecfg |= info->type;
-       pipecfg |= info->epnum;
-       switch (info->type) {
-       case R8A66597_INT:
-               bufnum = 4 + (info->pipe - R8A66597_BASE_PIPENUM_INT);
-               buf_bsize = 0;
-               break;
-       case R8A66597_BULK:
-               /* isochronous pipes may be used as bulk pipes */
-               if (info->pipe >= R8A66597_BASE_PIPENUM_BULK)
-                       bufnum = info->pipe - R8A66597_BASE_PIPENUM_BULK;
-               else
-                       bufnum = info->pipe - R8A66597_BASE_PIPENUM_ISOC;
-
-               bufnum = R8A66597_BASE_BUFNUM + (bufnum * 16);
-               buf_bsize = 7;
-               pipecfg |= R8A66597_DBLB;
-               if (!info->dir_in)
-                       pipecfg |= R8A66597_SHTNAK;
-               break;
-       case R8A66597_ISO:
-               bufnum = R8A66597_BASE_BUFNUM +
-                        (info->pipe - R8A66597_BASE_PIPENUM_ISOC) * 16;
-               buf_bsize = 7;
-               break;
-       }
-
-       if (buf_bsize && ((bufnum + 16) >= R8A66597_MAX_BUFNUM)) {
-               pr_err("r8a66597 pipe memory is insufficient\n");
-               return -ENOMEM;
-       }
-
-       r8a66597_write(r8a66597, pipecfg, PIPECFG);
-       r8a66597_write(r8a66597, (buf_bsize << 10) | (bufnum), PIPEBUF);
-       r8a66597_write(r8a66597, info->maxpacket, PIPEMAXP);
-       if (info->interval)
-               info->interval--;
-       r8a66597_write(r8a66597, info->interval, PIPEPERI);
-
-       return 0;
-}
-
-static void pipe_buffer_release(struct r8a66597 *r8a66597,
-                               struct r8a66597_pipe_info *info)
-{
-       if (info->pipe == 0)
-               return;
-
-       if (is_bulk_pipe(info->pipe)) {
-               r8a66597->bulk--;
-       } else if (is_interrupt_pipe(info->pipe)) {
-               r8a66597->interrupt--;
-       } else if (is_isoc_pipe(info->pipe)) {
-               r8a66597->isochronous--;
-               if (info->type == R8A66597_BULK)
-                       r8a66597->bulk--;
-       } else {
-               dev_err(r8a66597_to_dev(r8a66597),
-                       "ep_release: unexpect pipenum (%d)\n", info->pipe);
-       }
-}
-
-static void pipe_initialize(struct r8a66597_ep *ep)
-{
-       struct r8a66597 *r8a66597 = ep->r8a66597;
-
-       r8a66597_mdfy(r8a66597, 0, CURPIPE, ep->fifosel);
-
-       r8a66597_write(r8a66597, ACLRM, ep->pipectr);
-       r8a66597_write(r8a66597, 0, ep->pipectr);
-       r8a66597_write(r8a66597, SQCLR, ep->pipectr);
-       if (ep->use_dma) {
-               r8a66597_mdfy(r8a66597, ep->pipenum, CURPIPE, ep->fifosel);
-
-               ndelay(450);
-
-               r8a66597_bset(r8a66597, mbw_value(r8a66597), ep->fifosel);
-       }
-}
-
-static void r8a66597_ep_setting(struct r8a66597 *r8a66597,
-                               struct r8a66597_ep *ep,
-                               const struct usb_endpoint_descriptor *desc,
-                               u16 pipenum, int dma)
-{
-       ep->use_dma = 0;
-       ep->fifoaddr = CFIFO;
-       ep->fifosel = CFIFOSEL;
-       ep->fifoctr = CFIFOCTR;
-
-       ep->pipectr = get_pipectr_addr(pipenum);
-       if (is_bulk_pipe(pipenum) || is_isoc_pipe(pipenum)) {
-               ep->pipetre = get_pipetre_addr(pipenum);
-               ep->pipetrn = get_pipetrn_addr(pipenum);
-       } else {
-               ep->pipetre = 0;
-               ep->pipetrn = 0;
-       }
-       ep->pipenum = pipenum;
-       ep->ep.maxpacket = usb_endpoint_maxp(desc);
-       r8a66597->pipenum2ep[pipenum] = ep;
-       r8a66597->epaddr2ep[desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK]
-               = ep;
-       INIT_LIST_HEAD(&ep->queue);
-}
-
-static void r8a66597_ep_release(struct r8a66597_ep *ep)
-{
-       struct r8a66597 *r8a66597 = ep->r8a66597;
-       u16 pipenum = ep->pipenum;
-
-       if (pipenum == 0)
-               return;
-
-       if (ep->use_dma)
-               r8a66597->num_dma--;
-       ep->pipenum = 0;
-       ep->busy = 0;
-       ep->use_dma = 0;
-}
-
-static int alloc_pipe_config(struct r8a66597_ep *ep,
-               const struct usb_endpoint_descriptor *desc)
-{
-       struct r8a66597 *r8a66597 = ep->r8a66597;
-       struct r8a66597_pipe_info info;
-       int dma = 0;
-       unsigned char *counter;
-       int ret;
-
-       ep->ep.desc = desc;
-
-       if (ep->pipenum)        /* already allocated pipe  */
-               return 0;
-
-       switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
-       case USB_ENDPOINT_XFER_BULK:
-               if (r8a66597->bulk >= R8A66597_MAX_NUM_BULK) {
-                       if (r8a66597->isochronous >= R8A66597_MAX_NUM_ISOC) {
-                               dev_err(r8a66597_to_dev(r8a66597),
-                                       "bulk pipe is insufficient\n");
-                               return -ENODEV;
-                       } else {
-                               info.pipe = R8A66597_BASE_PIPENUM_ISOC
-                                               + r8a66597->isochronous;
-                               counter = &r8a66597->isochronous;
-                       }
-               } else {
-                       info.pipe = R8A66597_BASE_PIPENUM_BULK + r8a66597->bulk;
-                       counter = &r8a66597->bulk;
-               }
-               info.type = R8A66597_BULK;
-               dma = 1;
-               break;
-       case USB_ENDPOINT_XFER_INT:
-               if (r8a66597->interrupt >= R8A66597_MAX_NUM_INT) {
-                       dev_err(r8a66597_to_dev(r8a66597),
-                               "interrupt pipe is insufficient\n");
-                       return -ENODEV;
-               }
-               info.pipe = R8A66597_BASE_PIPENUM_INT + r8a66597->interrupt;
-               info.type = R8A66597_INT;
-               counter = &r8a66597->interrupt;
-               break;
-       case USB_ENDPOINT_XFER_ISOC:
-               if (r8a66597->isochronous >= R8A66597_MAX_NUM_ISOC) {
-                       dev_err(r8a66597_to_dev(r8a66597),
-                               "isochronous pipe is insufficient\n");
-                       return -ENODEV;
-               }
-               info.pipe = R8A66597_BASE_PIPENUM_ISOC + r8a66597->isochronous;
-               info.type = R8A66597_ISO;
-               counter = &r8a66597->isochronous;
-               break;
-       default:
-               dev_err(r8a66597_to_dev(r8a66597), "unexpect xfer type\n");
-               return -EINVAL;
-       }
-       ep->type = info.type;
-
-       info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-       info.maxpacket = usb_endpoint_maxp(desc);
-       info.interval = desc->bInterval;
-       if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-               info.dir_in = 1;
-       else
-               info.dir_in = 0;
-
-       ret = pipe_buffer_setting(r8a66597, &info);
-       if (ret < 0) {
-               dev_err(r8a66597_to_dev(r8a66597),
-                       "pipe_buffer_setting fail\n");
-               return ret;
-       }
-
-       (*counter)++;
-       if ((counter == &r8a66597->isochronous) && info.type == R8A66597_BULK)
-               r8a66597->bulk++;
-
-       r8a66597_ep_setting(r8a66597, ep, desc, info.pipe, dma);
-       pipe_initialize(ep);
-
-       return 0;
-}
-
-static int free_pipe_config(struct r8a66597_ep *ep)
-{
-       struct r8a66597 *r8a66597 = ep->r8a66597;
-       struct r8a66597_pipe_info info;
-
-       info.pipe = ep->pipenum;
-       info.type = ep->type;
-       pipe_buffer_release(r8a66597, &info);
-       r8a66597_ep_release(ep);
-
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-static void pipe_irq_enable(struct r8a66597 *r8a66597, u16 pipenum)
-{
-       enable_irq_ready(r8a66597, pipenum);
-       enable_irq_nrdy(r8a66597, pipenum);
-}
-
-static void pipe_irq_disable(struct r8a66597 *r8a66597, u16 pipenum)
-{
-       disable_irq_ready(r8a66597, pipenum);
-       disable_irq_nrdy(r8a66597, pipenum);
-}
-
-/* if complete is true, gadget driver complete function is not call */
-static void control_end(struct r8a66597 *r8a66597, unsigned ccpl)
-{
-       r8a66597->ep[0].internal_ccpl = ccpl;
-       pipe_start(r8a66597, 0);
-       r8a66597_bset(r8a66597, CCPL, DCPCTR);
-}
-
-static void start_ep0_write(struct r8a66597_ep *ep,
-                               struct r8a66597_request *req)
-{
-       struct r8a66597 *r8a66597 = ep->r8a66597;
-
-       pipe_change(r8a66597, ep->pipenum);
-       r8a66597_mdfy(r8a66597, ISEL, (ISEL | CURPIPE), CFIFOSEL);
-       r8a66597_write(r8a66597, BCLR, ep->fifoctr);
-       if (req->req.length == 0) {
-               r8a66597_bset(r8a66597, BVAL, ep->fifoctr);
-               pipe_start(r8a66597, 0);
-               transfer_complete(ep, req, 0);
-       } else {
-               r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
-               irq_ep0_write(ep, req);
-       }
-}
-
-static void disable_fifosel(struct r8a66597 *r8a66597, u16 pipenum,
-                           u16 fifosel)
-{
-       u16 tmp;
-
-       tmp = r8a66597_read(r8a66597, fifosel) & CURPIPE;
-       if (tmp == pipenum)
-               r8a66597_change_curpipe(r8a66597, 0, 0, fifosel);
-}
-
-static void change_bfre_mode(struct r8a66597 *r8a66597, u16 pipenum,
-                            int enable)
-{
-       struct r8a66597_ep *ep = r8a66597->pipenum2ep[pipenum];
-       u16 tmp, toggle;
-
-       /* check current BFRE bit */
-       r8a66597_write(r8a66597, pipenum, PIPESEL);
-       tmp = r8a66597_read(r8a66597, PIPECFG) & R8A66597_BFRE;
-       if ((enable && tmp) || (!enable && !tmp))
-               return;
-
-       /* change BFRE bit */
-       pipe_stop(r8a66597, pipenum);
-       disable_fifosel(r8a66597, pipenum, CFIFOSEL);
-       disable_fifosel(r8a66597, pipenum, D0FIFOSEL);
-       disable_fifosel(r8a66597, pipenum, D1FIFOSEL);
-
-       toggle = save_usb_toggle(r8a66597, pipenum);
-
-       r8a66597_write(r8a66597, pipenum, PIPESEL);
-       if (enable)
-               r8a66597_bset(r8a66597, R8A66597_BFRE, PIPECFG);
-       else
-               r8a66597_bclr(r8a66597, R8A66597_BFRE, PIPECFG);
-
-       /* initialize for internal BFRE flag */
-       r8a66597_bset(r8a66597, ACLRM, ep->pipectr);
-       r8a66597_bclr(r8a66597, ACLRM, ep->pipectr);
-
-       restore_usb_toggle(r8a66597, pipenum, toggle);
-}
-
-static int sudmac_alloc_channel(struct r8a66597 *r8a66597,
-                               struct r8a66597_ep *ep,
-                               struct r8a66597_request *req)
-{
-       struct r8a66597_dma *dma;
-
-       if (!r8a66597_is_sudmac(r8a66597))
-               return -ENODEV;
-
-       /* Check transfer type */
-       if (!is_bulk_pipe(ep->pipenum))
-               return -EIO;
-
-       if (r8a66597->dma.used)
-               return -EBUSY;
-
-       /* set SUDMAC parameters */
-       dma = &r8a66597->dma;
-       dma->used = 1;
-       if (ep->ep.desc->bEndpointAddress & USB_DIR_IN) {
-               dma->dir = 1;
-       } else {
-               dma->dir = 0;
-               change_bfre_mode(r8a66597, ep->pipenum, 1);
-       }
-
-       /* set r8a66597_ep paramters */
-       ep->use_dma = 1;
-       ep->dma = dma;
-       ep->fifoaddr = D0FIFO;
-       ep->fifosel = D0FIFOSEL;
-       ep->fifoctr = D0FIFOCTR;
-
-       /* dma mapping */
-       return usb_gadget_map_request(&r8a66597->gadget, &req->req, dma->dir);
-}
-
-static void sudmac_free_channel(struct r8a66597 *r8a66597,
-                               struct r8a66597_ep *ep,
-                               struct r8a66597_request *req)
-{
-       if (!r8a66597_is_sudmac(r8a66597))
-               return;
-
-       usb_gadget_unmap_request(&r8a66597->gadget, &req->req, ep->dma->dir);
-
-       r8a66597_bclr(r8a66597, DREQE, ep->fifosel);
-       r8a66597_change_curpipe(r8a66597, 0, 0, ep->fifosel);
-
-       ep->dma->used = 0;
-       ep->use_dma = 0;
-       ep->fifoaddr = CFIFO;
-       ep->fifosel = CFIFOSEL;
-       ep->fifoctr = CFIFOCTR;
-}
-
-static void sudmac_start(struct r8a66597 *r8a66597, struct r8a66597_ep *ep,
-                        struct r8a66597_request *req)
-{
-       BUG_ON(req->req.length == 0);
-
-       r8a66597_sudmac_write(r8a66597, LBA_WAIT, CH0CFG);
-       r8a66597_sudmac_write(r8a66597, req->req.dma, CH0BA);
-       r8a66597_sudmac_write(r8a66597, req->req.length, CH0BBC);
-       r8a66597_sudmac_write(r8a66597, CH0ENDE, DINTCTRL);
-
-       r8a66597_sudmac_write(r8a66597, DEN, CH0DEN);
-}
-
-static void start_packet_write(struct r8a66597_ep *ep,
-                               struct r8a66597_request *req)
-{
-       struct r8a66597 *r8a66597 = ep->r8a66597;
-       u16 tmp;
-
-       pipe_change(r8a66597, ep->pipenum);
-       disable_irq_empty(r8a66597, ep->pipenum);
-       pipe_start(r8a66597, ep->pipenum);
-
-       if (req->req.length == 0) {
-               transfer_complete(ep, req, 0);
-       } else {
-               r8a66597_write(r8a66597, ~(1 << ep->pipenum), BRDYSTS);
-               if (sudmac_alloc_channel(r8a66597, ep, req) < 0) {
-                       /* PIO mode */
-                       pipe_change(r8a66597, ep->pipenum);
-                       disable_irq_empty(r8a66597, ep->pipenum);
-                       pipe_start(r8a66597, ep->pipenum);
-                       tmp = r8a66597_read(r8a66597, ep->fifoctr);
-                       if (unlikely((tmp & FRDY) == 0))
-                               pipe_irq_enable(r8a66597, ep->pipenum);
-                       else
-                               irq_packet_write(ep, req);
-               } else {
-                       /* DMA mode */
-                       pipe_change(r8a66597, ep->pipenum);
-                       disable_irq_nrdy(r8a66597, ep->pipenum);
-                       pipe_start(r8a66597, ep->pipenum);
-                       enable_irq_nrdy(r8a66597, ep->pipenum);
-                       sudmac_start(r8a66597, ep, req);
-               }
-       }
-}
-
-static void start_packet_read(struct r8a66597_ep *ep,
-                               struct r8a66597_request *req)
-{
-       struct r8a66597 *r8a66597 = ep->r8a66597;
-       u16 pipenum = ep->pipenum;
-
-       if (ep->pipenum == 0) {
-               r8a66597_mdfy(r8a66597, 0, (ISEL | CURPIPE), CFIFOSEL);
-               r8a66597_write(r8a66597, BCLR, ep->fifoctr);
-               pipe_start(r8a66597, pipenum);
-               pipe_irq_enable(r8a66597, pipenum);
-       } else {
-               pipe_stop(r8a66597, pipenum);
-               if (ep->pipetre) {
-                       enable_irq_nrdy(r8a66597, pipenum);
-                       r8a66597_write(r8a66597, TRCLR, ep->pipetre);
-                       r8a66597_write(r8a66597,
-                               DIV_ROUND_UP(req->req.length, ep->ep.maxpacket),
-                               ep->pipetrn);
-                       r8a66597_bset(r8a66597, TRENB, ep->pipetre);
-               }
-
-               if (sudmac_alloc_channel(r8a66597, ep, req) < 0) {
-                       /* PIO mode */
-                       change_bfre_mode(r8a66597, ep->pipenum, 0);
-                       pipe_start(r8a66597, pipenum);  /* trigger once */
-                       pipe_irq_enable(r8a66597, pipenum);
-               } else {
-                       pipe_change(r8a66597, pipenum);
-                       sudmac_start(r8a66597, ep, req);
-                       pipe_start(r8a66597, pipenum);  /* trigger once */
-               }
-       }
-}
-
-static void start_packet(struct r8a66597_ep *ep, struct r8a66597_request *req)
-{
-       if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
-               start_packet_write(ep, req);
-       else
-               start_packet_read(ep, req);
-}
-
-static void start_ep0(struct r8a66597_ep *ep, struct r8a66597_request *req)
-{
-       u16 ctsq;
-
-       ctsq = r8a66597_read(ep->r8a66597, INTSTS0) & CTSQ;
-
-       switch (ctsq) {
-       case CS_RDDS:
-               start_ep0_write(ep, req);
-               break;
-       case CS_WRDS:
-               start_packet_read(ep, req);
-               break;
-
-       case CS_WRND:
-               control_end(ep->r8a66597, 0);
-               break;
-       default:
-               dev_err(r8a66597_to_dev(ep->r8a66597),
-                       "start_ep0: unexpect ctsq(%x)\n", ctsq);
-               break;
-       }
-}
-
-static void init_controller(struct r8a66597 *r8a66597)
-{
-       u16 vif = r8a66597->pdata->vif ? LDRV : 0;
-       u16 irq_sense = r8a66597->irq_sense_low ? INTL : 0;
-       u16 endian = r8a66597->pdata->endian ? BIGEND : 0;
-
-       if (r8a66597->pdata->on_chip) {
-               if (r8a66597->pdata->buswait)
-                       r8a66597_write(r8a66597, r8a66597->pdata->buswait,
-                                       SYSCFG1);
-               else
-                       r8a66597_write(r8a66597, 0x0f, SYSCFG1);
-               r8a66597_bset(r8a66597, HSE, SYSCFG0);
-
-               r8a66597_bclr(r8a66597, USBE, SYSCFG0);
-               r8a66597_bclr(r8a66597, DPRPU, SYSCFG0);
-               r8a66597_bset(r8a66597, USBE, SYSCFG0);
-
-               r8a66597_bset(r8a66597, SCKE, SYSCFG0);
-
-               r8a66597_bset(r8a66597, irq_sense, INTENB1);
-               r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR,
-                               DMA0CFG);
-       } else {
-               r8a66597_bset(r8a66597, vif | endian, PINCFG);
-               r8a66597_bset(r8a66597, HSE, SYSCFG0);          /* High spd */
-               r8a66597_mdfy(r8a66597, get_xtal_from_pdata(r8a66597->pdata),
-                               XTAL, SYSCFG0);
-
-               r8a66597_bclr(r8a66597, USBE, SYSCFG0);
-               r8a66597_bclr(r8a66597, DPRPU, SYSCFG0);
-               r8a66597_bset(r8a66597, USBE, SYSCFG0);
-
-               r8a66597_bset(r8a66597, XCKE, SYSCFG0);
-
-               msleep(3);
-
-               r8a66597_bset(r8a66597, PLLC, SYSCFG0);
-
-               msleep(1);
-
-               r8a66597_bset(r8a66597, SCKE, SYSCFG0);
-
-               r8a66597_bset(r8a66597, irq_sense, INTENB1);
-               r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR,
-                              DMA0CFG);
-       }
-}
-
-static void disable_controller(struct r8a66597 *r8a66597)
-{
-       if (r8a66597->pdata->on_chip) {
-               r8a66597_bset(r8a66597, SCKE, SYSCFG0);
-               r8a66597_bclr(r8a66597, UTST, TESTMODE);
-
-               /* disable interrupts */
-               r8a66597_write(r8a66597, 0, INTENB0);
-               r8a66597_write(r8a66597, 0, INTENB1);
-               r8a66597_write(r8a66597, 0, BRDYENB);
-               r8a66597_write(r8a66597, 0, BEMPENB);
-               r8a66597_write(r8a66597, 0, NRDYENB);
-
-               /* clear status */
-               r8a66597_write(r8a66597, 0, BRDYSTS);
-               r8a66597_write(r8a66597, 0, NRDYSTS);
-               r8a66597_write(r8a66597, 0, BEMPSTS);
-
-               r8a66597_bclr(r8a66597, USBE, SYSCFG0);
-               r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
-
-       } else {
-               r8a66597_bclr(r8a66597, UTST, TESTMODE);
-               r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
-               udelay(1);
-               r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
-               udelay(1);
-               udelay(1);
-               r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
-       }
-}
-
-static void r8a66597_start_xclock(struct r8a66597 *r8a66597)
-{
-       u16 tmp;
-
-       if (!r8a66597->pdata->on_chip) {
-               tmp = r8a66597_read(r8a66597, SYSCFG0);
-               if (!(tmp & XCKE))
-                       r8a66597_bset(r8a66597, XCKE, SYSCFG0);
-       }
-}
-
-static struct r8a66597_request *get_request_from_ep(struct r8a66597_ep *ep)
-{
-       return list_entry(ep->queue.next, struct r8a66597_request, queue);
-}
-
-/*-------------------------------------------------------------------------*/
-static void transfer_complete(struct r8a66597_ep *ep,
-               struct r8a66597_request *req, int status)
-__releases(r8a66597->lock)
-__acquires(r8a66597->lock)
-{
-       int restart = 0;
-
-       if (unlikely(ep->pipenum == 0)) {
-               if (ep->internal_ccpl) {
-                       ep->internal_ccpl = 0;
-                       return;
-               }
-       }
-
-       list_del_init(&req->queue);
-       if (ep->r8a66597->gadget.speed == USB_SPEED_UNKNOWN)
-               req->req.status = -ESHUTDOWN;
-       else
-               req->req.status = status;
-
-       if (!list_empty(&ep->queue))
-               restart = 1;
-
-       if (ep->use_dma)
-               sudmac_free_channel(ep->r8a66597, ep, req);
-
-       spin_unlock(&ep->r8a66597->lock);
-       req->req.complete(&ep->ep, &req->req);
-       spin_lock(&ep->r8a66597->lock);
-
-       if (restart) {
-               req = get_request_from_ep(ep);
-               if (ep->ep.desc)
-                       start_packet(ep, req);
-       }
-}
-
-static void irq_ep0_write(struct r8a66597_ep *ep, struct r8a66597_request *req)
-{
-       int i;
-       u16 tmp;
-       unsigned bufsize;
-       size_t size;
-       void *buf;
-       u16 pipenum = ep->pipenum;
-       struct r8a66597 *r8a66597 = ep->r8a66597;
-
-       pipe_change(r8a66597, pipenum);
-       r8a66597_bset(r8a66597, ISEL, ep->fifosel);
-
-       i = 0;
-       do {
-               tmp = r8a66597_read(r8a66597, ep->fifoctr);
-               if (i++ > 100000) {
-                       dev_err(r8a66597_to_dev(r8a66597),
-                               "pipe0 is busy. maybe cpu i/o bus "
-                               "conflict. please power off this controller.");
-                       return;
-               }
-               ndelay(1);
-       } while ((tmp & FRDY) == 0);
-
-       /* prepare parameters */
-       bufsize = get_buffer_size(r8a66597, pipenum);
-       buf = req->req.buf + req->req.actual;
-       size = min(bufsize, req->req.length - req->req.actual);
-
-       /* write fifo */
-       if (req->req.buf) {
-               if (size > 0)
-                       r8a66597_write_fifo(r8a66597, ep, buf, size);
-               if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
-                       r8a66597_bset(r8a66597, BVAL, ep->fifoctr);
-       }
-
-       /* update parameters */
-       req->req.actual += size;
-
-       /* check transfer finish */
-       if ((!req->req.zero && (req->req.actual == req->req.length))
-                       || (size % ep->ep.maxpacket)
-                       || (size == 0)) {
-               disable_irq_ready(r8a66597, pipenum);
-               disable_irq_empty(r8a66597, pipenum);
-       } else {
-               disable_irq_ready(r8a66597, pipenum);
-               enable_irq_empty(r8a66597, pipenum);
-       }
-       pipe_start(r8a66597, pipenum);
-}
-
-static void irq_packet_write(struct r8a66597_ep *ep,
-                               struct r8a66597_request *req)
-{
-       u16 tmp;
-       unsigned bufsize;
-       size_t size;
-       void *buf;
-       u16 pipenum = ep->pipenum;
-       struct r8a66597 *r8a66597 = ep->r8a66597;
-
-       pipe_change(r8a66597, pipenum);
-       tmp = r8a66597_read(r8a66597, ep->fifoctr);
-       if (unlikely((tmp & FRDY) == 0)) {
-               pipe_stop(r8a66597, pipenum);
-               pipe_irq_disable(r8a66597, pipenum);
-               dev_err(r8a66597_to_dev(r8a66597),
-                       "write fifo not ready. pipnum=%d\n", pipenum);
-               return;
-       }
-
-       /* prepare parameters */
-       bufsize = get_buffer_size(r8a66597, pipenum);
-       buf = req->req.buf + req->req.actual;
-       size = min(bufsize, req->req.length - req->req.actual);
-
-       /* write fifo */
-       if (req->req.buf) {
-               r8a66597_write_fifo(r8a66597, ep, buf, size);
-               if ((size == 0)
-                               || ((size % ep->ep.maxpacket) != 0)
-                               || ((bufsize != ep->ep.maxpacket)
-                                       && (bufsize > size)))
-                       r8a66597_bset(r8a66597, BVAL, ep->fifoctr);
-       }
-
-       /* update parameters */
-       req->req.actual += size;
-       /* check transfer finish */
-       if ((!req->req.zero && (req->req.actual == req->req.length))
-                       || (size % ep->ep.maxpacket)
-                       || (size == 0)) {
-               disable_irq_ready(r8a66597, pipenum);
-               enable_irq_empty(r8a66597, pipenum);
-       } else {
-               disable_irq_empty(r8a66597, pipenum);
-               pipe_irq_enable(r8a66597, pipenum);
-       }
-}
-
-static void irq_packet_read(struct r8a66597_ep *ep,
-                               struct r8a66597_request *req)
-{
-       u16 tmp;
-       int rcv_len, bufsize, req_len;
-       int size;
-       void *buf;
-       u16 pipenum = ep->pipenum;
-       struct r8a66597 *r8a66597 = ep->r8a66597;
-       int finish = 0;
-
-       pipe_change(r8a66597, pipenum);
-       tmp = r8a66597_read(r8a66597, ep->fifoctr);
-       if (unlikely((tmp & FRDY) == 0)) {
-               req->req.status = -EPIPE;
-               pipe_stop(r8a66597, pipenum);
-               pipe_irq_disable(r8a66597, pipenum);
-               dev_err(r8a66597_to_dev(r8a66597), "read fifo not ready");
-               return;
-       }
-
-       /* prepare parameters */
-       rcv_len = tmp & DTLN;
-       bufsize = get_buffer_size(r8a66597, pipenum);
-
-       buf = req->req.buf + req->req.actual;
-       req_len = req->req.length - req->req.actual;
-       if (rcv_len < bufsize)
-               size = min(rcv_len, req_len);
-       else
-               size = min(bufsize, req_len);
-
-       /* update parameters */
-       req->req.actual += size;
-
-       /* check transfer finish */
-       if ((!req->req.zero && (req->req.actual == req->req.length))
-                       || (size % ep->ep.maxpacket)
-                       || (size == 0)) {
-               pipe_stop(r8a66597, pipenum);
-               pipe_irq_disable(r8a66597, pipenum);
-               finish = 1;
-       }
-
-       /* read fifo */
-       if (req->req.buf) {
-               if (size == 0)
-                       r8a66597_write(r8a66597, BCLR, ep->fifoctr);
-               else
-                       r8a66597_read_fifo(r8a66597, ep->fifoaddr, buf, size);
-
-       }
-
-       if ((ep->pipenum != 0) && finish)
-               transfer_complete(ep, req, 0);
-}
-
-static void irq_pipe_ready(struct r8a66597 *r8a66597, u16 status, u16 enb)
-{
-       u16 check;
-       u16 pipenum;
-       struct r8a66597_ep *ep;
-       struct r8a66597_request *req;
-
-       if ((status & BRDY0) && (enb & BRDY0)) {
-               r8a66597_write(r8a66597, ~BRDY0, BRDYSTS);
-               r8a66597_mdfy(r8a66597, 0, CURPIPE, CFIFOSEL);
-
-               ep = &r8a66597->ep[0];
-               req = get_request_from_ep(ep);
-               irq_packet_read(ep, req);
-       } else {
-               for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
-                       check = 1 << pipenum;
-                       if ((status & check) && (enb & check)) {
-                               r8a66597_write(r8a66597, ~check, BRDYSTS);
-                               ep = r8a66597->pipenum2ep[pipenum];
-                               req = get_request_from_ep(ep);
-                               if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
-                                       irq_packet_write(ep, req);
-                               else
-                                       irq_packet_read(ep, req);
-                       }
-               }
-       }
-}
-
-static void irq_pipe_empty(struct r8a66597 *r8a66597, u16 status, u16 enb)
-{
-       u16 tmp;
-       u16 check;
-       u16 pipenum;
-       struct r8a66597_ep *ep;
-       struct r8a66597_request *req;
-
-       if ((status & BEMP0) && (enb & BEMP0)) {
-               r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
-
-               ep = &r8a66597->ep[0];
-               req = get_request_from_ep(ep);
-               irq_ep0_write(ep, req);
-       } else {
-               for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
-                       check = 1 << pipenum;
-                       if ((status & check) && (enb & check)) {
-                               r8a66597_write(r8a66597, ~check, BEMPSTS);
-                               tmp = control_reg_get(r8a66597, pipenum);
-                               if ((tmp & INBUFM) == 0) {
-                                       disable_irq_empty(r8a66597, pipenum);
-                                       pipe_irq_disable(r8a66597, pipenum);
-                                       pipe_stop(r8a66597, pipenum);
-                                       ep = r8a66597->pipenum2ep[pipenum];
-                                       req = get_request_from_ep(ep);
-                                       if (!list_empty(&ep->queue))
-                                               transfer_complete(ep, req, 0);
-                               }
-                       }
-               }
-       }
-}
-
-static void get_status(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl)
-__releases(r8a66597->lock)
-__acquires(r8a66597->lock)
-{
-       struct r8a66597_ep *ep;
-       u16 pid;
-       u16 status = 0;
-       u16 w_index = le16_to_cpu(ctrl->wIndex);
-
-       switch (ctrl->bRequestType & USB_RECIP_MASK) {
-       case USB_RECIP_DEVICE:
-               status = r8a66597->device_status;
-               break;
-       case USB_RECIP_INTERFACE:
-               status = 0;
-               break;
-       case USB_RECIP_ENDPOINT:
-               ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
-               pid = control_reg_get_pid(r8a66597, ep->pipenum);
-               if (pid == PID_STALL)
-                       status = 1 << USB_ENDPOINT_HALT;
-               else
-                       status = 0;
-               break;
-       default:
-               pipe_stall(r8a66597, 0);
-               return;         /* exit */
-       }
-
-       r8a66597->ep0_data = cpu_to_le16(status);
-       r8a66597->ep0_req->buf = &r8a66597->ep0_data;
-       r8a66597->ep0_req->length = 2;
-       /* AV: what happens if we get called again before that gets through? */
-       spin_unlock(&r8a66597->lock);
-       r8a66597_queue(r8a66597->gadget.ep0, r8a66597->ep0_req, GFP_KERNEL);
-       spin_lock(&r8a66597->lock);
-}
-
-static void clear_feature(struct r8a66597 *r8a66597,
-                               struct usb_ctrlrequest *ctrl)
-{
-       switch (ctrl->bRequestType & USB_RECIP_MASK) {
-       case USB_RECIP_DEVICE:
-               control_end(r8a66597, 1);
-               break;
-       case USB_RECIP_INTERFACE:
-               control_end(r8a66597, 1);
-               break;
-       case USB_RECIP_ENDPOINT: {
-               struct r8a66597_ep *ep;
-               struct r8a66597_request *req;
-               u16 w_index = le16_to_cpu(ctrl->wIndex);
-
-               ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
-               if (!ep->wedge) {
-                       pipe_stop(r8a66597, ep->pipenum);
-                       control_reg_sqclr(r8a66597, ep->pipenum);
-                       spin_unlock(&r8a66597->lock);
-                       usb_ep_clear_halt(&ep->ep);
-                       spin_lock(&r8a66597->lock);
-               }
-
-               control_end(r8a66597, 1);
-
-               req = get_request_from_ep(ep);
-               if (ep->busy) {
-                       ep->busy = 0;
-                       if (list_empty(&ep->queue))
-                               break;
-                       start_packet(ep, req);
-               } else if (!list_empty(&ep->queue))
-                       pipe_start(r8a66597, ep->pipenum);
-               }
-               break;
-       default:
-               pipe_stall(r8a66597, 0);
-               break;
-       }
-}
-
-static void set_feature(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl)
-{
-       u16 tmp;
-       int timeout = 3000;
-
-       switch (ctrl->bRequestType & USB_RECIP_MASK) {
-       case USB_RECIP_DEVICE:
-               switch (le16_to_cpu(ctrl->wValue)) {
-               case USB_DEVICE_TEST_MODE:
-                       control_end(r8a66597, 1);
-                       /* Wait for the completion of status stage */
-                       do {
-                               tmp = r8a66597_read(r8a66597, INTSTS0) & CTSQ;
-                               udelay(1);
-                       } while (tmp != CS_IDST || timeout-- > 0);
-
-                       if (tmp == CS_IDST)
-                               r8a66597_bset(r8a66597,
-                                             le16_to_cpu(ctrl->wIndex >> 8),
-                                             TESTMODE);
-                       break;
-               default:
-                       pipe_stall(r8a66597, 0);
-                       break;
-               }
-               break;
-       case USB_RECIP_INTERFACE:
-               control_end(r8a66597, 1);
-               break;
-       case USB_RECIP_ENDPOINT: {
-               struct r8a66597_ep *ep;
-               u16 w_index = le16_to_cpu(ctrl->wIndex);
-
-               ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
-               pipe_stall(r8a66597, ep->pipenum);
-
-               control_end(r8a66597, 1);
-               }
-               break;
-       default:
-               pipe_stall(r8a66597, 0);
-               break;
-       }
-}
-
-/* if return value is true, call class driver's setup() */
-static int setup_packet(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl)
-{
-       u16 *p = (u16 *)ctrl;
-       unsigned long offset = USBREQ;
-       int i, ret = 0;
-
-       /* read fifo */
-       r8a66597_write(r8a66597, ~VALID, INTSTS0);
-
-       for (i = 0; i < 4; i++)
-               p[i] = r8a66597_read(r8a66597, offset + i*2);
-
-       /* check request */
-       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
-               switch (ctrl->bRequest) {
-               case USB_REQ_GET_STATUS:
-                       get_status(r8a66597, ctrl);
-                       break;
-               case USB_REQ_CLEAR_FEATURE:
-                       clear_feature(r8a66597, ctrl);
-                       break;
-               case USB_REQ_SET_FEATURE:
-                       set_feature(r8a66597, ctrl);
-                       break;
-               default:
-                       ret = 1;
-                       break;
-               }
-       } else
-               ret = 1;
-       return ret;
-}
-
-static void r8a66597_update_usb_speed(struct r8a66597 *r8a66597)
-{
-       u16 speed = get_usb_speed(r8a66597);
-
-       switch (speed) {
-       case HSMODE:
-               r8a66597->gadget.speed = USB_SPEED_HIGH;
-               break;
-       case FSMODE:
-               r8a66597->gadget.speed = USB_SPEED_FULL;
-               break;
-       default:
-               r8a66597->gadget.speed = USB_SPEED_UNKNOWN;
-               dev_err(r8a66597_to_dev(r8a66597), "USB speed unknown\n");
-       }
-}
-
-static void irq_device_state(struct r8a66597 *r8a66597)
-{
-       u16 dvsq;
-
-       dvsq = r8a66597_read(r8a66597, INTSTS0) & DVSQ;
-       r8a66597_write(r8a66597, ~DVST, INTSTS0);
-
-       if (dvsq == DS_DFLT) {
-               /* bus reset */
-               spin_unlock(&r8a66597->lock);
-               r8a66597->driver->disconnect(&r8a66597->gadget);
-               spin_lock(&r8a66597->lock);
-               r8a66597_update_usb_speed(r8a66597);
-       }
-       if (r8a66597->old_dvsq == DS_CNFG && dvsq != DS_CNFG)
-               r8a66597_update_usb_speed(r8a66597);
-       if ((dvsq == DS_CNFG || dvsq == DS_ADDS)
-                       && r8a66597->gadget.speed == USB_SPEED_UNKNOWN)
-               r8a66597_update_usb_speed(r8a66597);
-
-       r8a66597->old_dvsq = dvsq;
-}
-
-static void irq_control_stage(struct r8a66597 *r8a66597)
-__releases(r8a66597->lock)
-__acquires(r8a66597->lock)
-{
-       struct usb_ctrlrequest ctrl;
-       u16 ctsq;
-
-       ctsq = r8a66597_read(r8a66597, INTSTS0) & CTSQ;
-       r8a66597_write(r8a66597, ~CTRT, INTSTS0);
-
-       switch (ctsq) {
-       case CS_IDST: {
-               struct r8a66597_ep *ep;
-               struct r8a66597_request *req;
-               ep = &r8a66597->ep[0];
-               req = get_request_from_ep(ep);
-               transfer_complete(ep, req, 0);
-               }
-               break;
-
-       case CS_RDDS:
-       case CS_WRDS:
-       case CS_WRND:
-               if (setup_packet(r8a66597, &ctrl)) {
-                       spin_unlock(&r8a66597->lock);
-                       if (r8a66597->driver->setup(&r8a66597->gadget, &ctrl)
-                               < 0)
-                               pipe_stall(r8a66597, 0);
-                       spin_lock(&r8a66597->lock);
-               }
-               break;
-       case CS_RDSS:
-       case CS_WRSS:
-               control_end(r8a66597, 0);
-               break;
-       default:
-               dev_err(r8a66597_to_dev(r8a66597),
-                       "ctrl_stage: unexpect ctsq(%x)\n", ctsq);
-               break;
-       }
-}
-
-static void sudmac_finish(struct r8a66597 *r8a66597, struct r8a66597_ep *ep)
-{
-       u16 pipenum;
-       struct r8a66597_request *req;
-       u32 len;
-       int i = 0;
-
-       pipenum = ep->pipenum;
-       pipe_change(r8a66597, pipenum);
-
-       while (!(r8a66597_read(r8a66597, ep->fifoctr) & FRDY)) {
-               udelay(1);
-               if (unlikely(i++ >= 10000)) {   /* timeout = 10 msec */
-                       dev_err(r8a66597_to_dev(r8a66597),
-                               "%s: FRDY was not set (%d)\n",
-                               __func__, pipenum);
-                       return;
-               }
-       }
-
-       r8a66597_bset(r8a66597, BCLR, ep->fifoctr);
-       req = get_request_from_ep(ep);
-
-       /* prepare parameters */
-       len = r8a66597_sudmac_read(r8a66597, CH0CBC);
-       req->req.actual += len;
-
-       /* clear */
-       r8a66597_sudmac_write(r8a66597, CH0STCLR, DSTSCLR);
-
-       /* check transfer finish */
-       if ((!req->req.zero && (req->req.actual == req->req.length))
-                       || (len % ep->ep.maxpacket)) {
-               if (ep->dma->dir) {
-                       disable_irq_ready(r8a66597, pipenum);
-                       enable_irq_empty(r8a66597, pipenum);
-               } else {
-                       /* Clear the interrupt flag for next transfer */
-                       r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS);
-                       transfer_complete(ep, req, 0);
-               }
-       }
-}
-
-static void r8a66597_sudmac_irq(struct r8a66597 *r8a66597)
-{
-       u32 irqsts;
-       struct r8a66597_ep *ep;
-       u16 pipenum;
-
-       irqsts = r8a66597_sudmac_read(r8a66597, DINTSTS);
-       if (irqsts & CH0ENDS) {
-               r8a66597_sudmac_write(r8a66597, CH0ENDC, DINTSTSCLR);
-               pipenum = (r8a66597_read(r8a66597, D0FIFOSEL) & CURPIPE);
-               ep = r8a66597->pipenum2ep[pipenum];
-               sudmac_finish(r8a66597, ep);
-       }
-}
-
-static irqreturn_t r8a66597_irq(int irq, void *_r8a66597)
-{
-       struct r8a66597 *r8a66597 = _r8a66597;
-       u16 intsts0;
-       u16 intenb0;
-       u16 brdysts, nrdysts, bempsts;
-       u16 brdyenb, nrdyenb, bempenb;
-       u16 savepipe;
-       u16 mask0;
-
-       spin_lock(&r8a66597->lock);
-
-       if (r8a66597_is_sudmac(r8a66597))
-               r8a66597_sudmac_irq(r8a66597);
-
-       intsts0 = r8a66597_read(r8a66597, INTSTS0);
-       intenb0 = r8a66597_read(r8a66597, INTENB0);
-
-       savepipe = r8a66597_read(r8a66597, CFIFOSEL);
-
-       mask0 = intsts0 & intenb0;
-       if (mask0) {
-               brdysts = r8a66597_read(r8a66597, BRDYSTS);
-               nrdysts = r8a66597_read(r8a66597, NRDYSTS);
-               bempsts = r8a66597_read(r8a66597, BEMPSTS);
-               brdyenb = r8a66597_read(r8a66597, BRDYENB);
-               nrdyenb = r8a66597_read(r8a66597, NRDYENB);
-               bempenb = r8a66597_read(r8a66597, BEMPENB);
-
-               if (mask0 & VBINT) {
-                       r8a66597_write(r8a66597,  0xffff & ~VBINT,
-                                       INTSTS0);
-                       r8a66597_start_xclock(r8a66597);
-
-                       /* start vbus sampling */
-                       r8a66597->old_vbus = r8a66597_read(r8a66597, INTSTS0)
-                                       & VBSTS;
-                       r8a66597->scount = R8A66597_MAX_SAMPLING;
-
-                       mod_timer(&r8a66597->timer,
-                                       jiffies + msecs_to_jiffies(50));
-               }
-               if (intsts0 & DVSQ)
-                       irq_device_state(r8a66597);
-
-               if ((intsts0 & BRDY) && (intenb0 & BRDYE)
-                               && (brdysts & brdyenb))
-                       irq_pipe_ready(r8a66597, brdysts, brdyenb);
-               if ((intsts0 & BEMP) && (intenb0 & BEMPE)
-                               && (bempsts & bempenb))
-                       irq_pipe_empty(r8a66597, bempsts, bempenb);
-
-               if (intsts0 & CTRT)
-                       irq_control_stage(r8a66597);
-       }
-
-       r8a66597_write(r8a66597, savepipe, CFIFOSEL);
-
-       spin_unlock(&r8a66597->lock);
-       return IRQ_HANDLED;
-}
-
-static void r8a66597_timer(unsigned long _r8a66597)
-{
-       struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
-       unsigned long flags;
-       u16 tmp;
-
-       spin_lock_irqsave(&r8a66597->lock, flags);
-       tmp = r8a66597_read(r8a66597, SYSCFG0);
-       if (r8a66597->scount > 0) {
-               tmp = r8a66597_read(r8a66597, INTSTS0) & VBSTS;
-               if (tmp == r8a66597->old_vbus) {
-                       r8a66597->scount--;
-                       if (r8a66597->scount == 0) {
-                               if (tmp == VBSTS)
-                                       r8a66597_usb_connect(r8a66597);
-                               else
-                                       r8a66597_usb_disconnect(r8a66597);
-                       } else {
-                               mod_timer(&r8a66597->timer,
-                                       jiffies + msecs_to_jiffies(50));
-                       }
-               } else {
-                       r8a66597->scount = R8A66597_MAX_SAMPLING;
-                       r8a66597->old_vbus = tmp;
-                       mod_timer(&r8a66597->timer,
-                                       jiffies + msecs_to_jiffies(50));
-               }
-       }
-       spin_unlock_irqrestore(&r8a66597->lock, flags);
-}
-
-/*-------------------------------------------------------------------------*/
-static int r8a66597_enable(struct usb_ep *_ep,
-                        const struct usb_endpoint_descriptor *desc)
-{
-       struct r8a66597_ep *ep;
-
-       ep = container_of(_ep, struct r8a66597_ep, ep);
-       return alloc_pipe_config(ep, desc);
-}
-
-static int r8a66597_disable(struct usb_ep *_ep)
-{
-       struct r8a66597_ep *ep;
-       struct r8a66597_request *req;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct r8a66597_ep, ep);
-       BUG_ON(!ep);
-
-       while (!list_empty(&ep->queue)) {
-               req = get_request_from_ep(ep);
-               spin_lock_irqsave(&ep->r8a66597->lock, flags);
-               transfer_complete(ep, req, -ECONNRESET);
-               spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
-       }
-
-       pipe_irq_disable(ep->r8a66597, ep->pipenum);
-       return free_pipe_config(ep);
-}
-
-static struct usb_request *r8a66597_alloc_request(struct usb_ep *_ep,
-                                               gfp_t gfp_flags)
-{
-       struct r8a66597_request *req;
-
-       req = kzalloc(sizeof(struct r8a66597_request), gfp_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD(&req->queue);
-
-       return &req->req;
-}
-
-static void r8a66597_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct r8a66597_request *req;
-
-       req = container_of(_req, struct r8a66597_request, req);
-       kfree(req);
-}
-
-static int r8a66597_queue(struct usb_ep *_ep, struct usb_request *_req,
-                       gfp_t gfp_flags)
-{
-       struct r8a66597_ep *ep;
-       struct r8a66597_request *req;
-       unsigned long flags;
-       int request = 0;
-
-       ep = container_of(_ep, struct r8a66597_ep, ep);
-       req = container_of(_req, struct r8a66597_request, req);
-
-       if (ep->r8a66597->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       spin_lock_irqsave(&ep->r8a66597->lock, flags);
-
-       if (list_empty(&ep->queue))
-               request = 1;
-
-       list_add_tail(&req->queue, &ep->queue);
-       req->req.actual = 0;
-       req->req.status = -EINPROGRESS;
-
-       if (ep->ep.desc == NULL)        /* control */
-               start_ep0(ep, req);
-       else {
-               if (request && !ep->busy)
-                       start_packet(ep, req);
-       }
-
-       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
-
-       return 0;
-}
-
-static int r8a66597_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct r8a66597_ep *ep;
-       struct r8a66597_request *req;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct r8a66597_ep, ep);
-       req = container_of(_req, struct r8a66597_request, req);
-
-       spin_lock_irqsave(&ep->r8a66597->lock, flags);
-       if (!list_empty(&ep->queue))
-               transfer_complete(ep, req, -ECONNRESET);
-       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
-
-       return 0;
-}
-
-static int r8a66597_set_halt(struct usb_ep *_ep, int value)
-{
-       struct r8a66597_ep *ep;
-       struct r8a66597_request *req;
-       unsigned long flags;
-       int ret = 0;
-
-       ep = container_of(_ep, struct r8a66597_ep, ep);
-       req = get_request_from_ep(ep);
-
-       spin_lock_irqsave(&ep->r8a66597->lock, flags);
-       if (!list_empty(&ep->queue)) {
-               ret = -EAGAIN;
-               goto out;
-       }
-       if (value) {
-               ep->busy = 1;
-               pipe_stall(ep->r8a66597, ep->pipenum);
-       } else {
-               ep->busy = 0;
-               ep->wedge = 0;
-               pipe_stop(ep->r8a66597, ep->pipenum);
-       }
-
-out:
-       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
-       return ret;
-}
-
-static int r8a66597_set_wedge(struct usb_ep *_ep)
-{
-       struct r8a66597_ep *ep;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct r8a66597_ep, ep);
-
-       if (!ep || !ep->ep.desc)
-               return -EINVAL;
-
-       spin_lock_irqsave(&ep->r8a66597->lock, flags);
-       ep->wedge = 1;
-       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
-
-       return usb_ep_set_halt(_ep);
-}
-
-static void r8a66597_fifo_flush(struct usb_ep *_ep)
-{
-       struct r8a66597_ep *ep;
-       unsigned long flags;
-
-       ep = container_of(_ep, struct r8a66597_ep, ep);
-       spin_lock_irqsave(&ep->r8a66597->lock, flags);
-       if (list_empty(&ep->queue) && !ep->busy) {
-               pipe_stop(ep->r8a66597, ep->pipenum);
-               r8a66597_bclr(ep->r8a66597, BCLR, ep->fifoctr);
-               r8a66597_write(ep->r8a66597, ACLRM, ep->pipectr);
-               r8a66597_write(ep->r8a66597, 0, ep->pipectr);
-       }
-       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
-}
-
-static struct usb_ep_ops r8a66597_ep_ops = {
-       .enable         = r8a66597_enable,
-       .disable        = r8a66597_disable,
-
-       .alloc_request  = r8a66597_alloc_request,
-       .free_request   = r8a66597_free_request,
-
-       .queue          = r8a66597_queue,
-       .dequeue        = r8a66597_dequeue,
-
-       .set_halt       = r8a66597_set_halt,
-       .set_wedge      = r8a66597_set_wedge,
-       .fifo_flush     = r8a66597_fifo_flush,
-};
-
-/*-------------------------------------------------------------------------*/
-static int r8a66597_start(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
-
-       if (!driver
-                       || driver->max_speed < USB_SPEED_HIGH
-                       || !driver->setup)
-               return -EINVAL;
-       if (!r8a66597)
-               return -ENODEV;
-
-       /* hook up the driver */
-       r8a66597->driver = driver;
-
-       init_controller(r8a66597);
-       r8a66597_bset(r8a66597, VBSE, INTENB0);
-       if (r8a66597_read(r8a66597, INTSTS0) & VBSTS) {
-               r8a66597_start_xclock(r8a66597);
-               /* start vbus sampling */
-               r8a66597->old_vbus = r8a66597_read(r8a66597,
-                                        INTSTS0) & VBSTS;
-               r8a66597->scount = R8A66597_MAX_SAMPLING;
-               mod_timer(&r8a66597->timer, jiffies + msecs_to_jiffies(50));
-       }
-
-       return 0;
-}
-
-static int r8a66597_stop(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
-       unsigned long flags;
-
-       spin_lock_irqsave(&r8a66597->lock, flags);
-       r8a66597_bclr(r8a66597, VBSE, INTENB0);
-       disable_controller(r8a66597);
-       spin_unlock_irqrestore(&r8a66597->lock, flags);
-
-       r8a66597->driver = NULL;
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-static int r8a66597_get_frame(struct usb_gadget *_gadget)
-{
-       struct r8a66597 *r8a66597 = gadget_to_r8a66597(_gadget);
-       return r8a66597_read(r8a66597, FRMNUM) & 0x03FF;
-}
-
-static int r8a66597_pullup(struct usb_gadget *gadget, int is_on)
-{
-       struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
-       unsigned long flags;
-
-       spin_lock_irqsave(&r8a66597->lock, flags);
-       if (is_on)
-               r8a66597_bset(r8a66597, DPRPU, SYSCFG0);
-       else
-               r8a66597_bclr(r8a66597, DPRPU, SYSCFG0);
-       spin_unlock_irqrestore(&r8a66597->lock, flags);
-
-       return 0;
-}
-
-static int r8a66597_set_selfpowered(struct usb_gadget *gadget, int is_self)
-{
-       struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
-
-       if (is_self)
-               r8a66597->device_status |= 1 << USB_DEVICE_SELF_POWERED;
-       else
-               r8a66597->device_status &= ~(1 << USB_DEVICE_SELF_POWERED);
-
-       return 0;
-}
-
-static const struct usb_gadget_ops r8a66597_gadget_ops = {
-       .get_frame              = r8a66597_get_frame,
-       .udc_start              = r8a66597_start,
-       .udc_stop               = r8a66597_stop,
-       .pullup                 = r8a66597_pullup,
-       .set_selfpowered        = r8a66597_set_selfpowered,
-};
-
-static int __exit r8a66597_remove(struct platform_device *pdev)
-{
-       struct r8a66597         *r8a66597 = platform_get_drvdata(pdev);
-
-       usb_del_gadget_udc(&r8a66597->gadget);
-       del_timer_sync(&r8a66597->timer);
-       r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
-
-       if (r8a66597->pdata->on_chip) {
-               clk_disable_unprepare(r8a66597->clk);
-       }
-
-       return 0;
-}
-
-static void nop_completion(struct usb_ep *ep, struct usb_request *r)
-{
-}
-
-static int r8a66597_sudmac_ioremap(struct r8a66597 *r8a66597,
-                                         struct platform_device *pdev)
-{
-       struct resource *res;
-
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sudmac");
-       r8a66597->sudmac_reg = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(r8a66597->sudmac_reg)) {
-               dev_err(&pdev->dev, "ioremap error(sudmac).\n");
-               return PTR_ERR(r8a66597->sudmac_reg);
-       }
-
-       return 0;
-}
-
-static int r8a66597_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       char clk_name[8];
-       struct resource *res, *ires;
-       int irq;
-       void __iomem *reg = NULL;
-       struct r8a66597 *r8a66597 = NULL;
-       int ret = 0;
-       int i;
-       unsigned long irq_trigger;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       reg = devm_ioremap_resource(&pdev->dev, res);
-       if (!reg)
-               return -ENODEV;
-
-       ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       irq = ires->start;
-       irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
-
-       if (irq < 0) {
-               dev_err(dev, "platform_get_irq error.\n");
-               return -ENODEV;
-       }
-
-       /* initialize ucd */
-       r8a66597 = devm_kzalloc(dev, sizeof(struct r8a66597), GFP_KERNEL);
-       if (r8a66597 == NULL)
-               return -ENOMEM;
-
-       spin_lock_init(&r8a66597->lock);
-       platform_set_drvdata(pdev, r8a66597);
-       r8a66597->pdata = dev_get_platdata(dev);
-       r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
-
-       r8a66597->gadget.ops = &r8a66597_gadget_ops;
-       r8a66597->gadget.max_speed = USB_SPEED_HIGH;
-       r8a66597->gadget.name = udc_name;
-
-       init_timer(&r8a66597->timer);
-       r8a66597->timer.function = r8a66597_timer;
-       r8a66597->timer.data = (unsigned long)r8a66597;
-       r8a66597->reg = reg;
-
-       if (r8a66597->pdata->on_chip) {
-               snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id);
-               r8a66597->clk = devm_clk_get(dev, clk_name);
-               if (IS_ERR(r8a66597->clk)) {
-                       dev_err(dev, "cannot get clock \"%s\"\n", clk_name);
-                       return PTR_ERR(r8a66597->clk);
-               }
-               clk_prepare_enable(r8a66597->clk);
-       }
-
-       if (r8a66597->pdata->sudmac) {
-               ret = r8a66597_sudmac_ioremap(r8a66597, pdev);
-               if (ret < 0)
-                       goto clean_up2;
-       }
-
-       disable_controller(r8a66597); /* make sure controller is disabled */
-
-       ret = devm_request_irq(dev, irq, r8a66597_irq, IRQF_SHARED,
-                              udc_name, r8a66597);
-       if (ret < 0) {
-               dev_err(dev, "request_irq error (%d)\n", ret);
-               goto clean_up2;
-       }
-
-       INIT_LIST_HEAD(&r8a66597->gadget.ep_list);
-       r8a66597->gadget.ep0 = &r8a66597->ep[0].ep;
-       INIT_LIST_HEAD(&r8a66597->gadget.ep0->ep_list);
-       for (i = 0; i < R8A66597_MAX_NUM_PIPE; i++) {
-               struct r8a66597_ep *ep = &r8a66597->ep[i];
-
-               if (i != 0) {
-                       INIT_LIST_HEAD(&r8a66597->ep[i].ep.ep_list);
-                       list_add_tail(&r8a66597->ep[i].ep.ep_list,
-                                       &r8a66597->gadget.ep_list);
-               }
-               ep->r8a66597 = r8a66597;
-               INIT_LIST_HEAD(&ep->queue);
-               ep->ep.name = r8a66597_ep_name[i];
-               ep->ep.ops = &r8a66597_ep_ops;
-               usb_ep_set_maxpacket_limit(&ep->ep, 512);
-       }
-       usb_ep_set_maxpacket_limit(&r8a66597->ep[0].ep, 64);
-       r8a66597->ep[0].pipenum = 0;
-       r8a66597->ep[0].fifoaddr = CFIFO;
-       r8a66597->ep[0].fifosel = CFIFOSEL;
-       r8a66597->ep[0].fifoctr = CFIFOCTR;
-       r8a66597->ep[0].pipectr = get_pipectr_addr(0);
-       r8a66597->pipenum2ep[0] = &r8a66597->ep[0];
-       r8a66597->epaddr2ep[0] = &r8a66597->ep[0];
-
-       r8a66597->ep0_req = r8a66597_alloc_request(&r8a66597->ep[0].ep,
-                                                       GFP_KERNEL);
-       if (r8a66597->ep0_req == NULL) {
-               ret = -ENOMEM;
-               goto clean_up2;
-       }
-       r8a66597->ep0_req->complete = nop_completion;
-
-       ret = usb_add_gadget_udc(dev, &r8a66597->gadget);
-       if (ret)
-               goto err_add_udc;
-
-       dev_info(dev, "version %s\n", DRIVER_VERSION);
-       return 0;
-
-err_add_udc:
-       r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
-clean_up2:
-       if (r8a66597->pdata->on_chip)
-               clk_disable_unprepare(r8a66597->clk);
-
-       if (r8a66597->ep0_req)
-               r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
-
-       return ret;
-}
-
-/*-------------------------------------------------------------------------*/
-static struct platform_driver r8a66597_driver = {
-       .remove =       __exit_p(r8a66597_remove),
-       .driver         = {
-               .name = (char *) udc_name,
-       },
-};
-
-module_platform_driver_probe(r8a66597_driver, r8a66597_probe);
-
-MODULE_DESCRIPTION("R8A66597 USB gadget driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Yoshihiro Shimoda");
-MODULE_ALIAS("platform:r8a66597_udc");
diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h
deleted file mode 100644 (file)
index 45c4b2d..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * R8A66597 UDC
- *
- * Copyright (C) 2007-2009 Renesas Solutions Corp.
- *
- * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- */
-
-#ifndef __R8A66597_H__
-#define __R8A66597_H__
-
-#include <linux/clk.h>
-#include <linux/usb/r8a66597.h>
-
-#define R8A66597_MAX_SAMPLING  10
-
-#define R8A66597_MAX_NUM_PIPE  8
-#define R8A66597_MAX_NUM_BULK  3
-#define R8A66597_MAX_NUM_ISOC  2
-#define R8A66597_MAX_NUM_INT   2
-
-#define R8A66597_BASE_PIPENUM_BULK     3
-#define R8A66597_BASE_PIPENUM_ISOC     1
-#define R8A66597_BASE_PIPENUM_INT      6
-
-#define R8A66597_BASE_BUFNUM   6
-#define R8A66597_MAX_BUFNUM    0x4F
-
-#define is_bulk_pipe(pipenum)  \
-       ((pipenum >= R8A66597_BASE_PIPENUM_BULK) && \
-        (pipenum < (R8A66597_BASE_PIPENUM_BULK + R8A66597_MAX_NUM_BULK)))
-#define is_interrupt_pipe(pipenum)     \
-       ((pipenum >= R8A66597_BASE_PIPENUM_INT) && \
-        (pipenum < (R8A66597_BASE_PIPENUM_INT + R8A66597_MAX_NUM_INT)))
-#define is_isoc_pipe(pipenum)  \
-       ((pipenum >= R8A66597_BASE_PIPENUM_ISOC) && \
-        (pipenum < (R8A66597_BASE_PIPENUM_ISOC + R8A66597_MAX_NUM_ISOC)))
-
-#define r8a66597_is_sudmac(r8a66597)   (r8a66597->pdata->sudmac)
-struct r8a66597_pipe_info {
-       u16     pipe;
-       u16     epnum;
-       u16     maxpacket;
-       u16     type;
-       u16     interval;
-       u16     dir_in;
-};
-
-struct r8a66597_request {
-       struct usb_request      req;
-       struct list_head        queue;
-};
-
-struct r8a66597_ep {
-       struct usb_ep           ep;
-       struct r8a66597         *r8a66597;
-       struct r8a66597_dma     *dma;
-
-       struct list_head        queue;
-       unsigned                busy:1;
-       unsigned                wedge:1;
-       unsigned                internal_ccpl:1;        /* use only control */
-
-       /* this member can able to after r8a66597_enable */
-       unsigned                use_dma:1;
-       u16                     pipenum;
-       u16                     type;
-
-       /* register address */
-       unsigned char           fifoaddr;
-       unsigned char           fifosel;
-       unsigned char           fifoctr;
-       unsigned char           pipectr;
-       unsigned char           pipetre;
-       unsigned char           pipetrn;
-};
-
-struct r8a66597_dma {
-       unsigned                used:1;
-       unsigned                dir:1;  /* 1 = IN(write), 0 = OUT(read) */
-};
-
-struct r8a66597 {
-       spinlock_t              lock;
-       void __iomem            *reg;
-       void __iomem            *sudmac_reg;
-
-       struct clk *clk;
-       struct r8a66597_platdata        *pdata;
-
-       struct usb_gadget               gadget;
-       struct usb_gadget_driver        *driver;
-
-       struct r8a66597_ep      ep[R8A66597_MAX_NUM_PIPE];
-       struct r8a66597_ep      *pipenum2ep[R8A66597_MAX_NUM_PIPE];
-       struct r8a66597_ep      *epaddr2ep[16];
-       struct r8a66597_dma     dma;
-
-       struct timer_list       timer;
-       struct usb_request      *ep0_req;       /* for internal request */
-       u16                     ep0_data;       /* for internal request */
-       u16                     old_vbus;
-       u16                     scount;
-       u16                     old_dvsq;
-       u16                     device_status;  /* for GET_STATUS */
-
-       /* pipe config */
-       unsigned char bulk;
-       unsigned char interrupt;
-       unsigned char isochronous;
-       unsigned char num_dma;
-
-       unsigned irq_sense_low:1;
-};
-
-#define gadget_to_r8a66597(_gadget)    \
-               container_of(_gadget, struct r8a66597, gadget)
-#define r8a66597_to_gadget(r8a66597) (&r8a66597->gadget)
-#define r8a66597_to_dev(r8a66597)      (r8a66597->gadget.dev.parent)
-
-static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
-{
-       return ioread16(r8a66597->reg + offset);
-}
-
-static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
-                                     unsigned long offset,
-                                     unsigned char *buf,
-                                     int len)
-{
-       void __iomem *fifoaddr = r8a66597->reg + offset;
-       unsigned int data = 0;
-       int i;
-
-       if (r8a66597->pdata->on_chip) {
-               /* 32-bit accesses for on_chip controllers */
-
-               /* aligned buf case */
-               if (len >= 4 && !((unsigned long)buf & 0x03)) {
-                       ioread32_rep(fifoaddr, buf, len / 4);
-                       buf += len & ~0x03;
-                       len &= 0x03;
-               }
-
-               /* unaligned buf case */
-               for (i = 0; i < len; i++) {
-                       if (!(i & 0x03))
-                               data = ioread32(fifoaddr);
-
-                       buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
-               }
-       } else {
-               /* 16-bit accesses for external controllers */
-
-               /* aligned buf case */
-               if (len >= 2 && !((unsigned long)buf & 0x01)) {
-                       ioread16_rep(fifoaddr, buf, len / 2);
-                       buf += len & ~0x01;
-                       len &= 0x01;
-               }
-
-               /* unaligned buf case */
-               for (i = 0; i < len; i++) {
-                       if (!(i & 0x01))
-                               data = ioread16(fifoaddr);
-
-                       buf[i] = (data >> ((i & 0x01) * 8)) & 0xff;
-               }
-       }
-}
-
-static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
-                                 unsigned long offset)
-{
-       iowrite16(val, r8a66597->reg + offset);
-}
-
-static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
-                                u16 val, u16 pat, unsigned long offset)
-{
-       u16 tmp;
-       tmp = r8a66597_read(r8a66597, offset);
-       tmp = tmp & (~pat);
-       tmp = tmp | val;
-       r8a66597_write(r8a66597, tmp, offset);
-}
-
-#define r8a66597_bclr(r8a66597, val, offset)   \
-                       r8a66597_mdfy(r8a66597, 0, val, offset)
-#define r8a66597_bset(r8a66597, val, offset)   \
-                       r8a66597_mdfy(r8a66597, val, 0, offset)
-
-static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
-                                      struct r8a66597_ep *ep,
-                                      unsigned char *buf,
-                                      int len)
-{
-       void __iomem *fifoaddr = r8a66597->reg + ep->fifoaddr;
-       int adj = 0;
-       int i;
-
-       if (r8a66597->pdata->on_chip) {
-               /* 32-bit access only if buf is 32-bit aligned */
-               if (len >= 4 && !((unsigned long)buf & 0x03)) {
-                       iowrite32_rep(fifoaddr, buf, len / 4);
-                       buf += len & ~0x03;
-                       len &= 0x03;
-               }
-       } else {
-               /* 16-bit access only if buf is 16-bit aligned */
-               if (len >= 2 && !((unsigned long)buf & 0x01)) {
-                       iowrite16_rep(fifoaddr, buf, len / 2);
-                       buf += len & ~0x01;
-                       len &= 0x01;
-               }
-       }
-
-       /* adjust fifo address in the little endian case */
-       if (!(r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)) {
-               if (r8a66597->pdata->on_chip)
-                       adj = 0x03; /* 32-bit wide */
-               else
-                       adj = 0x01; /* 16-bit wide */
-       }
-
-       if (r8a66597->pdata->wr0_shorted_to_wr1)
-               r8a66597_bclr(r8a66597, MBW_16, ep->fifosel);
-       for (i = 0; i < len; i++)
-               iowrite8(buf[i], fifoaddr + adj - (i & adj));
-       if (r8a66597->pdata->wr0_shorted_to_wr1)
-               r8a66597_bclr(r8a66597, MBW_16, ep->fifosel);
-}
-
-static inline u16 get_xtal_from_pdata(struct r8a66597_platdata *pdata)
-{
-       u16 clock = 0;
-
-       switch (pdata->xtal) {
-       case R8A66597_PLATDATA_XTAL_12MHZ:
-               clock = XTAL12;
-               break;
-       case R8A66597_PLATDATA_XTAL_24MHZ:
-               clock = XTAL24;
-               break;
-       case R8A66597_PLATDATA_XTAL_48MHZ:
-               clock = XTAL48;
-               break;
-       default:
-               printk(KERN_ERR "r8a66597: platdata clock is wrong.\n");
-               break;
-       }
-
-       return clock;
-}
-
-static inline u32 r8a66597_sudmac_read(struct r8a66597 *r8a66597,
-                                      unsigned long offset)
-{
-       return ioread32(r8a66597->sudmac_reg + offset);
-}
-
-static inline void r8a66597_sudmac_write(struct r8a66597 *r8a66597, u32 val,
-                                        unsigned long offset)
-{
-       iowrite32(val, r8a66597->sudmac_reg + offset);
-}
-
-#define get_pipectr_addr(pipenum)      (PIPE1CTR + (pipenum - 1) * 2)
-#define get_pipetre_addr(pipenum)      (PIPE1TRE + (pipenum - 1) * 4)
-#define get_pipetrn_addr(pipenum)      (PIPE1TRN + (pipenum - 1) * 4)
-
-#define enable_irq_ready(r8a66597, pipenum)    \
-       enable_pipe_irq(r8a66597, pipenum, BRDYENB)
-#define disable_irq_ready(r8a66597, pipenum)   \
-       disable_pipe_irq(r8a66597, pipenum, BRDYENB)
-#define enable_irq_empty(r8a66597, pipenum)    \
-       enable_pipe_irq(r8a66597, pipenum, BEMPENB)
-#define disable_irq_empty(r8a66597, pipenum)   \
-       disable_pipe_irq(r8a66597, pipenum, BEMPENB)
-#define enable_irq_nrdy(r8a66597, pipenum)     \
-       enable_pipe_irq(r8a66597, pipenum, NRDYENB)
-#define disable_irq_nrdy(r8a66597, pipenum)    \
-       disable_pipe_irq(r8a66597, pipenum, NRDYENB)
-
-#endif /* __R8A66597_H__ */
-
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
deleted file mode 100644 (file)
index 10c6a12..0000000
+++ /dev/null
@@ -1,1369 +0,0 @@
-/* linux/drivers/usb/gadget/s3c-hsudc.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * S3C24XX USB 2.0 High-speed USB controller gadget driver
- *
- * The S3C24XX USB 2.0 high-speed USB controller supports upto 9 endpoints.
- * Each endpoint can be configured as either in or out endpoint. Endpoints
- * can be configured for Bulk or Interrupt transfer mode.
- *
- * 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 <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/otg.h>
-#include <linux/prefetch.h>
-#include <linux/platform_data/s3c-hsudc.h>
-#include <linux/regulator/consumer.h>
-#include <linux/pm_runtime.h>
-
-#include <mach/regs-s3c2443-clock.h>
-
-#define S3C_HSUDC_REG(x)       (x)
-
-/* Non-Indexed Registers */
-#define S3C_IR                         S3C_HSUDC_REG(0x00) /* Index Register */
-#define S3C_EIR                                S3C_HSUDC_REG(0x04) /* EP Intr Status */
-#define S3C_EIR_EP0                    (1<<0)
-#define S3C_EIER                       S3C_HSUDC_REG(0x08) /* EP Intr Enable */
-#define S3C_FAR                                S3C_HSUDC_REG(0x0c) /* Gadget Address */
-#define S3C_FNR                                S3C_HSUDC_REG(0x10) /* Frame Number */
-#define S3C_EDR                                S3C_HSUDC_REG(0x14) /* EP Direction */
-#define S3C_TR                         S3C_HSUDC_REG(0x18) /* Test Register */
-#define S3C_SSR                                S3C_HSUDC_REG(0x1c) /* System Status */
-#define S3C_SSR_DTZIEN_EN              (0xff8f)
-#define S3C_SSR_ERR                    (0xff80)
-#define S3C_SSR_VBUSON                 (1 << 8)
-#define S3C_SSR_HSP                    (1 << 4)
-#define S3C_SSR_SDE                    (1 << 3)
-#define S3C_SSR_RESUME                 (1 << 2)
-#define S3C_SSR_SUSPEND                        (1 << 1)
-#define S3C_SSR_RESET                  (1 << 0)
-#define S3C_SCR                                S3C_HSUDC_REG(0x20) /* System Control */
-#define S3C_SCR_DTZIEN_EN              (1 << 14)
-#define S3C_SCR_RRD_EN                 (1 << 5)
-#define S3C_SCR_SUS_EN                 (1 << 1)
-#define S3C_SCR_RST_EN                 (1 << 0)
-#define S3C_EP0SR                      S3C_HSUDC_REG(0x24) /* EP0 Status */
-#define S3C_EP0SR_EP0_LWO              (1 << 6)
-#define S3C_EP0SR_STALL                        (1 << 4)
-#define S3C_EP0SR_TX_SUCCESS           (1 << 1)
-#define S3C_EP0SR_RX_SUCCESS           (1 << 0)
-#define S3C_EP0CR                      S3C_HSUDC_REG(0x28) /* EP0 Control */
-#define S3C_BR(_x)                     S3C_HSUDC_REG(0x60 + (_x * 4))
-
-/* Indexed Registers */
-#define S3C_ESR                                S3C_HSUDC_REG(0x2c) /* EPn Status */
-#define S3C_ESR_FLUSH                  (1 << 6)
-#define S3C_ESR_STALL                  (1 << 5)
-#define S3C_ESR_LWO                    (1 << 4)
-#define S3C_ESR_PSIF_ONE               (1 << 2)
-#define S3C_ESR_PSIF_TWO               (2 << 2)
-#define S3C_ESR_TX_SUCCESS             (1 << 1)
-#define S3C_ESR_RX_SUCCESS             (1 << 0)
-#define S3C_ECR                                S3C_HSUDC_REG(0x30) /* EPn Control */
-#define S3C_ECR_DUEN                   (1 << 7)
-#define S3C_ECR_FLUSH                  (1 << 6)
-#define S3C_ECR_STALL                  (1 << 1)
-#define S3C_ECR_IEMS                   (1 << 0)
-#define S3C_BRCR                       S3C_HSUDC_REG(0x34) /* Read Count */
-#define S3C_BWCR                       S3C_HSUDC_REG(0x38) /* Write Count */
-#define S3C_MPR                                S3C_HSUDC_REG(0x3c) /* Max Pkt Size */
-
-#define WAIT_FOR_SETUP                 (0)
-#define DATA_STATE_XMIT                        (1)
-#define DATA_STATE_RECV                        (2)
-
-static const char * const s3c_hsudc_supply_names[] = {
-       "vdda",         /* analog phy supply, 3.3V */
-       "vddi",         /* digital phy supply, 1.2V */
-       "vddosc",       /* oscillator supply, 1.8V - 3.3V */
-};
-
-/**
- * struct s3c_hsudc_ep - Endpoint representation used by driver.
- * @ep: USB gadget layer representation of device endpoint.
- * @name: Endpoint name (as required by ep autoconfiguration).
- * @dev: Reference to the device controller to which this EP belongs.
- * @desc: Endpoint descriptor obtained from the gadget driver.
- * @queue: Transfer request queue for the endpoint.
- * @stopped: Maintains state of endpoint, set if EP is halted.
- * @bEndpointAddress: EP address (including direction bit).
- * @fifo: Base address of EP FIFO.
- */
-struct s3c_hsudc_ep {
-       struct usb_ep ep;
-       char name[20];
-       struct s3c_hsudc *dev;
-       struct list_head queue;
-       u8 stopped;
-       u8 wedge;
-       u8 bEndpointAddress;
-       void __iomem *fifo;
-};
-
-/**
- * struct s3c_hsudc_req - Driver encapsulation of USB gadget transfer request.
- * @req: Reference to USB gadget transfer request.
- * @queue: Used for inserting this request to the endpoint request queue.
- */
-struct s3c_hsudc_req {
-       struct usb_request req;
-       struct list_head queue;
-};
-
-/**
- * struct s3c_hsudc - Driver's abstraction of the device controller.
- * @gadget: Instance of usb_gadget which is referenced by gadget driver.
- * @driver: Reference to currenty active gadget driver.
- * @dev: The device reference used by probe function.
- * @lock: Lock to synchronize the usage of Endpoints (EP's are indexed).
- * @regs: Remapped base address of controller's register space.
- * irq: IRQ number used by the controller.
- * uclk: Reference to the controller clock.
- * ep0state: Current state of EP0.
- * ep: List of endpoints supported by the controller.
- */
-struct s3c_hsudc {
-       struct usb_gadget gadget;
-       struct usb_gadget_driver *driver;
-       struct device *dev;
-       struct s3c24xx_hsudc_platdata *pd;
-       struct usb_phy *transceiver;
-       struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsudc_supply_names)];
-       spinlock_t lock;
-       void __iomem *regs;
-       int irq;
-       struct clk *uclk;
-       int ep0state;
-       struct s3c_hsudc_ep ep[];
-};
-
-#define ep_maxpacket(_ep)      ((_ep)->ep.maxpacket)
-#define ep_is_in(_ep)          ((_ep)->bEndpointAddress & USB_DIR_IN)
-#define ep_index(_ep)          ((_ep)->bEndpointAddress & \
-                                       USB_ENDPOINT_NUMBER_MASK)
-
-static const char driver_name[] = "s3c-udc";
-static const char ep0name[] = "ep0-control";
-
-static inline struct s3c_hsudc_req *our_req(struct usb_request *req)
-{
-       return container_of(req, struct s3c_hsudc_req, req);
-}
-
-static inline struct s3c_hsudc_ep *our_ep(struct usb_ep *ep)
-{
-       return container_of(ep, struct s3c_hsudc_ep, ep);
-}
-
-static inline struct s3c_hsudc *to_hsudc(struct usb_gadget *gadget)
-{
-       return container_of(gadget, struct s3c_hsudc, gadget);
-}
-
-static inline void set_index(struct s3c_hsudc *hsudc, int ep_addr)
-{
-       ep_addr &= USB_ENDPOINT_NUMBER_MASK;
-       writel(ep_addr, hsudc->regs + S3C_IR);
-}
-
-static inline void __orr32(void __iomem *ptr, u32 val)
-{
-       writel(readl(ptr) | val, ptr);
-}
-
-static void s3c_hsudc_init_phy(void)
-{
-       u32 cfg;
-
-       cfg = readl(S3C2443_PWRCFG) | S3C2443_PWRCFG_USBPHY;
-       writel(cfg, S3C2443_PWRCFG);
-
-       cfg = readl(S3C2443_URSTCON);
-       cfg |= (S3C2443_URSTCON_FUNCRST | S3C2443_URSTCON_PHYRST);
-       writel(cfg, S3C2443_URSTCON);
-       mdelay(1);
-
-       cfg = readl(S3C2443_URSTCON);
-       cfg &= ~(S3C2443_URSTCON_FUNCRST | S3C2443_URSTCON_PHYRST);
-       writel(cfg, S3C2443_URSTCON);
-
-       cfg = readl(S3C2443_PHYCTRL);
-       cfg &= ~(S3C2443_PHYCTRL_CLKSEL | S3C2443_PHYCTRL_DSPORT);
-       cfg |= (S3C2443_PHYCTRL_EXTCLK | S3C2443_PHYCTRL_PLLSEL);
-       writel(cfg, S3C2443_PHYCTRL);
-
-       cfg = readl(S3C2443_PHYPWR);
-       cfg &= ~(S3C2443_PHYPWR_FSUSPEND | S3C2443_PHYPWR_PLL_PWRDN |
-               S3C2443_PHYPWR_XO_ON | S3C2443_PHYPWR_PLL_REFCLK |
-               S3C2443_PHYPWR_ANALOG_PD);
-       cfg |= S3C2443_PHYPWR_COMMON_ON;
-       writel(cfg, S3C2443_PHYPWR);
-
-       cfg = readl(S3C2443_UCLKCON);
-       cfg |= (S3C2443_UCLKCON_DETECT_VBUS | S3C2443_UCLKCON_FUNC_CLKEN |
-               S3C2443_UCLKCON_TCLKEN);
-       writel(cfg, S3C2443_UCLKCON);
-}
-
-static void s3c_hsudc_uninit_phy(void)
-{
-       u32 cfg;
-
-       cfg = readl(S3C2443_PWRCFG) & ~S3C2443_PWRCFG_USBPHY;
-       writel(cfg, S3C2443_PWRCFG);
-
-       writel(S3C2443_PHYPWR_FSUSPEND, S3C2443_PHYPWR);
-
-       cfg = readl(S3C2443_UCLKCON) & ~S3C2443_UCLKCON_FUNC_CLKEN;
-       writel(cfg, S3C2443_UCLKCON);
-}
-
-/**
- * s3c_hsudc_complete_request - Complete a transfer request.
- * @hsep: Endpoint to which the request belongs.
- * @hsreq: Transfer request to be completed.
- * @status: Transfer completion status for the transfer request.
- */
-static void s3c_hsudc_complete_request(struct s3c_hsudc_ep *hsep,
-                               struct s3c_hsudc_req *hsreq, int status)
-{
-       unsigned int stopped = hsep->stopped;
-       struct s3c_hsudc *hsudc = hsep->dev;
-
-       list_del_init(&hsreq->queue);
-       hsreq->req.status = status;
-
-       if (!ep_index(hsep)) {
-               hsudc->ep0state = WAIT_FOR_SETUP;
-               hsep->bEndpointAddress &= ~USB_DIR_IN;
-       }
-
-       hsep->stopped = 1;
-       spin_unlock(&hsudc->lock);
-       if (hsreq->req.complete != NULL)
-               hsreq->req.complete(&hsep->ep, &hsreq->req);
-       spin_lock(&hsudc->lock);
-       hsep->stopped = stopped;
-}
-
-/**
- * s3c_hsudc_nuke_ep - Terminate all requests queued for a endpoint.
- * @hsep: Endpoint for which queued requests have to be terminated.
- * @status: Transfer completion status for the transfer request.
- */
-static void s3c_hsudc_nuke_ep(struct s3c_hsudc_ep *hsep, int status)
-{
-       struct s3c_hsudc_req *hsreq;
-
-       while (!list_empty(&hsep->queue)) {
-               hsreq = list_entry(hsep->queue.next,
-                               struct s3c_hsudc_req, queue);
-               s3c_hsudc_complete_request(hsep, hsreq, status);
-       }
-}
-
-/**
- * s3c_hsudc_stop_activity - Stop activity on all endpoints.
- * @hsudc: Device controller for which EP activity is to be stopped.
- *
- * All the endpoints are stopped and any pending transfer requests if any on
- * the endpoint are terminated.
- */
-static void s3c_hsudc_stop_activity(struct s3c_hsudc *hsudc)
-{
-       struct s3c_hsudc_ep *hsep;
-       int epnum;
-
-       hsudc->gadget.speed = USB_SPEED_UNKNOWN;
-
-       for (epnum = 0; epnum < hsudc->pd->epnum; epnum++) {
-               hsep = &hsudc->ep[epnum];
-               hsep->stopped = 1;
-               s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN);
-       }
-}
-
-/**
- * s3c_hsudc_read_setup_pkt - Read the received setup packet from EP0 fifo.
- * @hsudc: Device controller from which setup packet is to be read.
- * @buf: The buffer into which the setup packet is read.
- *
- * The setup packet received in the EP0 fifo is read and stored into a
- * given buffer address.
- */
-
-static void s3c_hsudc_read_setup_pkt(struct s3c_hsudc *hsudc, u16 *buf)
-{
-       int count;
-
-       count = readl(hsudc->regs + S3C_BRCR);
-       while (count--)
-               *buf++ = (u16)readl(hsudc->regs + S3C_BR(0));
-
-       writel(S3C_EP0SR_RX_SUCCESS, hsudc->regs + S3C_EP0SR);
-}
-
-/**
- * s3c_hsudc_write_fifo - Write next chunk of transfer data to EP fifo.
- * @hsep: Endpoint to which the data is to be written.
- * @hsreq: Transfer request from which the next chunk of data is written.
- *
- * Write the next chunk of data from a transfer request to the endpoint FIFO.
- * If the transfer request completes, 1 is returned, otherwise 0 is returned.
- */
-static int s3c_hsudc_write_fifo(struct s3c_hsudc_ep *hsep,
-                               struct s3c_hsudc_req *hsreq)
-{
-       u16 *buf;
-       u32 max = ep_maxpacket(hsep);
-       u32 count, length;
-       bool is_last;
-       void __iomem *fifo = hsep->fifo;
-
-       buf = hsreq->req.buf + hsreq->req.actual;
-       prefetch(buf);
-
-       length = hsreq->req.length - hsreq->req.actual;
-       length = min(length, max);
-       hsreq->req.actual += length;
-
-       writel(length, hsep->dev->regs + S3C_BWCR);
-       for (count = 0; count < length; count += 2)
-               writel(*buf++, fifo);
-
-       if (count != max) {
-               is_last = true;
-       } else {
-               if (hsreq->req.length != hsreq->req.actual || hsreq->req.zero)
-                       is_last = false;
-               else
-                       is_last = true;
-       }
-
-       if (is_last) {
-               s3c_hsudc_complete_request(hsep, hsreq, 0);
-               return 1;
-       }
-
-       return 0;
-}
-
-/**
- * s3c_hsudc_read_fifo - Read the next chunk of data from EP fifo.
- * @hsep: Endpoint from which the data is to be read.
- * @hsreq: Transfer request to which the next chunk of data read is written.
- *
- * Read the next chunk of data from the endpoint FIFO and a write it to the
- * transfer request buffer. If the transfer request completes, 1 is returned,
- * otherwise 0 is returned.
- */
-static int s3c_hsudc_read_fifo(struct s3c_hsudc_ep *hsep,
-                               struct s3c_hsudc_req *hsreq)
-{
-       struct s3c_hsudc *hsudc = hsep->dev;
-       u32 csr, offset;
-       u16 *buf, word;
-       u32 buflen, rcnt, rlen;
-       void __iomem *fifo = hsep->fifo;
-       u32 is_short = 0;
-
-       offset = (ep_index(hsep)) ? S3C_ESR : S3C_EP0SR;
-       csr = readl(hsudc->regs + offset);
-       if (!(csr & S3C_ESR_RX_SUCCESS))
-               return -EINVAL;
-
-       buf = hsreq->req.buf + hsreq->req.actual;
-       prefetchw(buf);
-       buflen = hsreq->req.length - hsreq->req.actual;
-
-       rcnt = readl(hsudc->regs + S3C_BRCR);
-       rlen = (csr & S3C_ESR_LWO) ? (rcnt * 2 - 1) : (rcnt * 2);
-
-       hsreq->req.actual += min(rlen, buflen);
-       is_short = (rlen < hsep->ep.maxpacket);
-
-       while (rcnt-- != 0) {
-               word = (u16)readl(fifo);
-               if (buflen) {
-                       *buf++ = word;
-                       buflen--;
-               } else {
-                       hsreq->req.status = -EOVERFLOW;
-               }
-       }
-
-       writel(S3C_ESR_RX_SUCCESS, hsudc->regs + offset);
-
-       if (is_short || hsreq->req.actual == hsreq->req.length) {
-               s3c_hsudc_complete_request(hsep, hsreq, 0);
-               return 1;
-       }
-
-       return 0;
-}
-
-/**
- * s3c_hsudc_epin_intr - Handle in-endpoint interrupt.
- * @hsudc - Device controller for which the interrupt is to be handled.
- * @ep_idx - Endpoint number on which an interrupt is pending.
- *
- * Handles interrupt for a in-endpoint. The interrupts that are handled are
- * stall and data transmit complete interrupt.
- */
-static void s3c_hsudc_epin_intr(struct s3c_hsudc *hsudc, u32 ep_idx)
-{
-       struct s3c_hsudc_ep *hsep = &hsudc->ep[ep_idx];
-       struct s3c_hsudc_req *hsreq;
-       u32 csr;
-
-       csr = readl(hsudc->regs + S3C_ESR);
-       if (csr & S3C_ESR_STALL) {
-               writel(S3C_ESR_STALL, hsudc->regs + S3C_ESR);
-               return;
-       }
-
-       if (csr & S3C_ESR_TX_SUCCESS) {
-               writel(S3C_ESR_TX_SUCCESS, hsudc->regs + S3C_ESR);
-               if (list_empty(&hsep->queue))
-                       return;
-
-               hsreq = list_entry(hsep->queue.next,
-                               struct s3c_hsudc_req, queue);
-               if ((s3c_hsudc_write_fifo(hsep, hsreq) == 0) &&
-                               (csr & S3C_ESR_PSIF_TWO))
-                       s3c_hsudc_write_fifo(hsep, hsreq);
-       }
-}
-
-/**
- * s3c_hsudc_epout_intr - Handle out-endpoint interrupt.
- * @hsudc - Device controller for which the interrupt is to be handled.
- * @ep_idx - Endpoint number on which an interrupt is pending.
- *
- * Handles interrupt for a out-endpoint. The interrupts that are handled are
- * stall, flush and data ready interrupt.
- */
-static void s3c_hsudc_epout_intr(struct s3c_hsudc *hsudc, u32 ep_idx)
-{
-       struct s3c_hsudc_ep *hsep = &hsudc->ep[ep_idx];
-       struct s3c_hsudc_req *hsreq;
-       u32 csr;
-
-       csr = readl(hsudc->regs + S3C_ESR);
-       if (csr & S3C_ESR_STALL) {
-               writel(S3C_ESR_STALL, hsudc->regs + S3C_ESR);
-               return;
-       }
-
-       if (csr & S3C_ESR_FLUSH) {
-               __orr32(hsudc->regs + S3C_ECR, S3C_ECR_FLUSH);
-               return;
-       }
-
-       if (csr & S3C_ESR_RX_SUCCESS) {
-               if (list_empty(&hsep->queue))
-                       return;
-
-               hsreq = list_entry(hsep->queue.next,
-                               struct s3c_hsudc_req, queue);
-               if (((s3c_hsudc_read_fifo(hsep, hsreq)) == 0) &&
-                               (csr & S3C_ESR_PSIF_TWO))
-                       s3c_hsudc_read_fifo(hsep, hsreq);
-       }
-}
-
-/** s3c_hsudc_set_halt - Set or clear a endpoint halt.
- * @_ep: Endpoint on which halt has to be set or cleared.
- * @value: 1 for setting halt on endpoint, 0 to clear halt.
- *
- * Set or clear endpoint halt. If halt is set, the endpoint is stopped.
- * If halt is cleared, for in-endpoints, if there are any pending
- * transfer requests, transfers are started.
- */
-static int s3c_hsudc_set_halt(struct usb_ep *_ep, int value)
-{
-       struct s3c_hsudc_ep *hsep = our_ep(_ep);
-       struct s3c_hsudc *hsudc = hsep->dev;
-       struct s3c_hsudc_req *hsreq;
-       unsigned long irqflags;
-       u32 ecr;
-       u32 offset;
-
-       if (value && ep_is_in(hsep) && !list_empty(&hsep->queue))
-               return -EAGAIN;
-
-       spin_lock_irqsave(&hsudc->lock, irqflags);
-       set_index(hsudc, ep_index(hsep));
-       offset = (ep_index(hsep)) ? S3C_ECR : S3C_EP0CR;
-       ecr = readl(hsudc->regs + offset);
-
-       if (value) {
-               ecr |= S3C_ECR_STALL;
-               if (ep_index(hsep))
-                       ecr |= S3C_ECR_FLUSH;
-               hsep->stopped = 1;
-       } else {
-               ecr &= ~S3C_ECR_STALL;
-               hsep->stopped = hsep->wedge = 0;
-       }
-       writel(ecr, hsudc->regs + offset);
-
-       if (ep_is_in(hsep) && !list_empty(&hsep->queue) && !value) {
-               hsreq = list_entry(hsep->queue.next,
-                       struct s3c_hsudc_req, queue);
-               if (hsreq)
-                       s3c_hsudc_write_fifo(hsep, hsreq);
-       }
-
-       spin_unlock_irqrestore(&hsudc->lock, irqflags);
-       return 0;
-}
-
-/** s3c_hsudc_set_wedge - Sets the halt feature with the clear requests ignored
- * @_ep: Endpoint on which wedge has to be set.
- *
- * Sets the halt feature with the clear requests ignored.
- */
-static int s3c_hsudc_set_wedge(struct usb_ep *_ep)
-{
-       struct s3c_hsudc_ep *hsep = our_ep(_ep);
-
-       if (!hsep)
-               return -EINVAL;
-
-       hsep->wedge = 1;
-       return usb_ep_set_halt(_ep);
-}
-
-/** s3c_hsudc_handle_reqfeat - Handle set feature or clear feature requests.
- * @_ep: Device controller on which the set/clear feature needs to be handled.
- * @ctrl: Control request as received on the endpoint 0.
- *
- * Handle set feature or clear feature control requests on the control endpoint.
- */
-static int s3c_hsudc_handle_reqfeat(struct s3c_hsudc *hsudc,
-                                       struct usb_ctrlrequest *ctrl)
-{
-       struct s3c_hsudc_ep *hsep;
-       bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE);
-       u8 ep_num = ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK;
-
-       if (ctrl->bRequestType == USB_RECIP_ENDPOINT) {
-               hsep = &hsudc->ep[ep_num];
-               switch (le16_to_cpu(ctrl->wValue)) {
-               case USB_ENDPOINT_HALT:
-                       if (set || (!set && !hsep->wedge))
-                               s3c_hsudc_set_halt(&hsep->ep, set);
-                       return 0;
-               }
-       }
-
-       return -ENOENT;
-}
-
-/**
- * s3c_hsudc_process_req_status - Handle get status control request.
- * @hsudc: Device controller on which get status request has be handled.
- * @ctrl: Control request as received on the endpoint 0.
- *
- * Handle get status control request received on control endpoint.
- */
-static void s3c_hsudc_process_req_status(struct s3c_hsudc *hsudc,
-                                       struct usb_ctrlrequest *ctrl)
-{
-       struct s3c_hsudc_ep *hsep0 = &hsudc->ep[0];
-       struct s3c_hsudc_req hsreq;
-       struct s3c_hsudc_ep *hsep;
-       __le16 reply;
-       u8 epnum;
-
-       switch (ctrl->bRequestType & USB_RECIP_MASK) {
-       case USB_RECIP_DEVICE:
-               reply = cpu_to_le16(0);
-               break;
-
-       case USB_RECIP_INTERFACE:
-               reply = cpu_to_le16(0);
-               break;
-
-       case USB_RECIP_ENDPOINT:
-               epnum = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
-               hsep = &hsudc->ep[epnum];
-               reply = cpu_to_le16(hsep->stopped ? 1 : 0);
-               break;
-       }
-
-       INIT_LIST_HEAD(&hsreq.queue);
-       hsreq.req.length = 2;
-       hsreq.req.buf = &reply;
-       hsreq.req.actual = 0;
-       hsreq.req.complete = NULL;
-       s3c_hsudc_write_fifo(hsep0, &hsreq);
-}
-
-/**
- * s3c_hsudc_process_setup - Process control request received on endpoint 0.
- * @hsudc: Device controller on which control request has been received.
- *
- * Read the control request received on endpoint 0, decode it and handle
- * the request.
- */
-static void s3c_hsudc_process_setup(struct s3c_hsudc *hsudc)
-{
-       struct s3c_hsudc_ep *hsep = &hsudc->ep[0];
-       struct usb_ctrlrequest ctrl = {0};
-       int ret;
-
-       s3c_hsudc_nuke_ep(hsep, -EPROTO);
-       s3c_hsudc_read_setup_pkt(hsudc, (u16 *)&ctrl);
-
-       if (ctrl.bRequestType & USB_DIR_IN) {
-               hsep->bEndpointAddress |= USB_DIR_IN;
-               hsudc->ep0state = DATA_STATE_XMIT;
-       } else {
-               hsep->bEndpointAddress &= ~USB_DIR_IN;
-               hsudc->ep0state = DATA_STATE_RECV;
-       }
-
-       switch (ctrl.bRequest) {
-       case USB_REQ_SET_ADDRESS:
-               if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE))
-                       break;
-               hsudc->ep0state = WAIT_FOR_SETUP;
-               return;
-
-       case USB_REQ_GET_STATUS:
-               if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD)
-                       break;
-               s3c_hsudc_process_req_status(hsudc, &ctrl);
-               return;
-
-       case USB_REQ_SET_FEATURE:
-       case USB_REQ_CLEAR_FEATURE:
-               if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD)
-                       break;
-               s3c_hsudc_handle_reqfeat(hsudc, &ctrl);
-               hsudc->ep0state = WAIT_FOR_SETUP;
-               return;
-       }
-
-       if (hsudc->driver) {
-               spin_unlock(&hsudc->lock);
-               ret = hsudc->driver->setup(&hsudc->gadget, &ctrl);
-               spin_lock(&hsudc->lock);
-
-               if (ctrl.bRequest == USB_REQ_SET_CONFIGURATION) {
-                       hsep->bEndpointAddress &= ~USB_DIR_IN;
-                       hsudc->ep0state = WAIT_FOR_SETUP;
-               }
-
-               if (ret < 0) {
-                       dev_err(hsudc->dev, "setup failed, returned %d\n",
-                                               ret);
-                       s3c_hsudc_set_halt(&hsep->ep, 1);
-                       hsudc->ep0state = WAIT_FOR_SETUP;
-                       hsep->bEndpointAddress &= ~USB_DIR_IN;
-               }
-       }
-}
-
-/** s3c_hsudc_handle_ep0_intr - Handle endpoint 0 interrupt.
- * @hsudc: Device controller on which endpoint 0 interrupt has occured.
- *
- * Handle endpoint 0 interrupt when it occurs. EP0 interrupt could occur
- * when a stall handshake is sent to host or data is sent/received on
- * endpoint 0.
- */
-static void s3c_hsudc_handle_ep0_intr(struct s3c_hsudc *hsudc)
-{
-       struct s3c_hsudc_ep *hsep = &hsudc->ep[0];
-       struct s3c_hsudc_req *hsreq;
-       u32 csr = readl(hsudc->regs + S3C_EP0SR);
-       u32 ecr;
-
-       if (csr & S3C_EP0SR_STALL) {
-               ecr = readl(hsudc->regs + S3C_EP0CR);
-               ecr &= ~(S3C_ECR_STALL | S3C_ECR_FLUSH);
-               writel(ecr, hsudc->regs + S3C_EP0CR);
-
-               writel(S3C_EP0SR_STALL, hsudc->regs + S3C_EP0SR);
-               hsep->stopped = 0;
-
-               s3c_hsudc_nuke_ep(hsep, -ECONNABORTED);
-               hsudc->ep0state = WAIT_FOR_SETUP;
-               hsep->bEndpointAddress &= ~USB_DIR_IN;
-               return;
-       }
-
-       if (csr & S3C_EP0SR_TX_SUCCESS) {
-               writel(S3C_EP0SR_TX_SUCCESS, hsudc->regs + S3C_EP0SR);
-               if (ep_is_in(hsep)) {
-                       if (list_empty(&hsep->queue))
-                               return;
-
-                       hsreq = list_entry(hsep->queue.next,
-                                       struct s3c_hsudc_req, queue);
-                       s3c_hsudc_write_fifo(hsep, hsreq);
-               }
-       }
-
-       if (csr & S3C_EP0SR_RX_SUCCESS) {
-               if (hsudc->ep0state == WAIT_FOR_SETUP)
-                       s3c_hsudc_process_setup(hsudc);
-               else {
-                       if (!ep_is_in(hsep)) {
-                               if (list_empty(&hsep->queue))
-                                       return;
-                               hsreq = list_entry(hsep->queue.next,
-                                       struct s3c_hsudc_req, queue);
-                               s3c_hsudc_read_fifo(hsep, hsreq);
-                       }
-               }
-       }
-}
-
-/**
- * s3c_hsudc_ep_enable - Enable a endpoint.
- * @_ep: The endpoint to be enabled.
- * @desc: Endpoint descriptor.
- *
- * Enables a endpoint when called from the gadget driver. Endpoint stall if
- * any is cleared, transfer type is configured and endpoint interrupt is
- * enabled.
- */
-static int s3c_hsudc_ep_enable(struct usb_ep *_ep,
-                               const struct usb_endpoint_descriptor *desc)
-{
-       struct s3c_hsudc_ep *hsep;
-       struct s3c_hsudc *hsudc;
-       unsigned long flags;
-       u32 ecr = 0;
-
-       hsep = our_ep(_ep);
-       if (!_ep || !desc || _ep->name == ep0name
-               || desc->bDescriptorType != USB_DT_ENDPOINT
-               || hsep->bEndpointAddress != desc->bEndpointAddress
-               || ep_maxpacket(hsep) < usb_endpoint_maxp(desc))
-               return -EINVAL;
-
-       if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
-               && usb_endpoint_maxp(desc) != ep_maxpacket(hsep))
-               || !desc->wMaxPacketSize)
-               return -ERANGE;
-
-       hsudc = hsep->dev;
-       if (!hsudc->driver || hsudc->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       spin_lock_irqsave(&hsudc->lock, flags);
-
-       set_index(hsudc, hsep->bEndpointAddress);
-       ecr |= ((usb_endpoint_xfer_int(desc)) ? S3C_ECR_IEMS : S3C_ECR_DUEN);
-       writel(ecr, hsudc->regs + S3C_ECR);
-
-       hsep->stopped = hsep->wedge = 0;
-       hsep->ep.desc = desc;
-       hsep->ep.maxpacket = usb_endpoint_maxp(desc);
-
-       s3c_hsudc_set_halt(_ep, 0);
-       __set_bit(ep_index(hsep), hsudc->regs + S3C_EIER);
-
-       spin_unlock_irqrestore(&hsudc->lock, flags);
-       return 0;
-}
-
-/**
- * s3c_hsudc_ep_disable - Disable a endpoint.
- * @_ep: The endpoint to be disabled.
- * @desc: Endpoint descriptor.
- *
- * Disables a endpoint when called from the gadget driver.
- */
-static int s3c_hsudc_ep_disable(struct usb_ep *_ep)
-{
-       struct s3c_hsudc_ep *hsep = our_ep(_ep);
-       struct s3c_hsudc *hsudc = hsep->dev;
-       unsigned long flags;
-
-       if (!_ep || !hsep->ep.desc)
-               return -EINVAL;
-
-       spin_lock_irqsave(&hsudc->lock, flags);
-
-       set_index(hsudc, hsep->bEndpointAddress);
-       __clear_bit(ep_index(hsep), hsudc->regs + S3C_EIER);
-
-       s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN);
-
-       hsep->ep.desc = NULL;
-       hsep->stopped = 1;
-
-       spin_unlock_irqrestore(&hsudc->lock, flags);
-       return 0;
-}
-
-/**
- * s3c_hsudc_alloc_request - Allocate a new request.
- * @_ep: Endpoint for which request is allocated (not used).
- * @gfp_flags: Flags used for the allocation.
- *
- * Allocates a single transfer request structure when called from gadget driver.
- */
-static struct usb_request *s3c_hsudc_alloc_request(struct usb_ep *_ep,
-                                               gfp_t gfp_flags)
-{
-       struct s3c_hsudc_req *hsreq;
-
-       hsreq = kzalloc(sizeof(*hsreq), gfp_flags);
-       if (!hsreq)
-               return NULL;
-
-       INIT_LIST_HEAD(&hsreq->queue);
-       return &hsreq->req;
-}
-
-/**
- * s3c_hsudc_free_request - Deallocate a request.
- * @ep: Endpoint for which request is deallocated (not used).
- * @_req: Request to be deallocated.
- *
- * Allocates a single transfer request structure when called from gadget driver.
- */
-static void s3c_hsudc_free_request(struct usb_ep *ep, struct usb_request *_req)
-{
-       struct s3c_hsudc_req *hsreq;
-
-       hsreq = our_req(_req);
-       WARN_ON(!list_empty(&hsreq->queue));
-       kfree(hsreq);
-}
-
-/**
- * s3c_hsudc_queue - Queue a transfer request for the endpoint.
- * @_ep: Endpoint for which the request is queued.
- * @_req: Request to be queued.
- * @gfp_flags: Not used.
- *
- * Start or enqueue a request for a endpoint when called from gadget driver.
- */
-static int s3c_hsudc_queue(struct usb_ep *_ep, struct usb_request *_req,
-                       gfp_t gfp_flags)
-{
-       struct s3c_hsudc_req *hsreq;
-       struct s3c_hsudc_ep *hsep;
-       struct s3c_hsudc *hsudc;
-       unsigned long flags;
-       u32 offset;
-       u32 csr;
-
-       hsreq = our_req(_req);
-       if ((!_req || !_req->complete || !_req->buf ||
-               !list_empty(&hsreq->queue)))
-               return -EINVAL;
-
-       hsep = our_ep(_ep);
-       hsudc = hsep->dev;
-       if (!hsudc->driver || hsudc->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       spin_lock_irqsave(&hsudc->lock, flags);
-       set_index(hsudc, hsep->bEndpointAddress);
-
-       _req->status = -EINPROGRESS;
-       _req->actual = 0;
-
-       if (!ep_index(hsep) && _req->length == 0) {
-               hsudc->ep0state = WAIT_FOR_SETUP;
-               s3c_hsudc_complete_request(hsep, hsreq, 0);
-               spin_unlock_irqrestore(&hsudc->lock, flags);
-               return 0;
-       }
-
-       if (list_empty(&hsep->queue) && !hsep->stopped) {
-               offset = (ep_index(hsep)) ? S3C_ESR : S3C_EP0SR;
-               if (ep_is_in(hsep)) {
-                       csr = readl(hsudc->regs + offset);
-                       if (!(csr & S3C_ESR_TX_SUCCESS) &&
-                               (s3c_hsudc_write_fifo(hsep, hsreq) == 1))
-                               hsreq = NULL;
-               } else {
-                       csr = readl(hsudc->regs + offset);
-                       if ((csr & S3C_ESR_RX_SUCCESS)
-                                  && (s3c_hsudc_read_fifo(hsep, hsreq) == 1))
-                               hsreq = NULL;
-               }
-       }
-
-       if (hsreq)
-               list_add_tail(&hsreq->queue, &hsep->queue);
-
-       spin_unlock_irqrestore(&hsudc->lock, flags);
-       return 0;
-}
-
-/**
- * s3c_hsudc_dequeue - Dequeue a transfer request from an endpoint.
- * @_ep: Endpoint from which the request is dequeued.
- * @_req: Request to be dequeued.
- *
- * Dequeue a request from a endpoint when called from gadget driver.
- */
-static int s3c_hsudc_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct s3c_hsudc_ep *hsep = our_ep(_ep);
-       struct s3c_hsudc *hsudc = hsep->dev;
-       struct s3c_hsudc_req *hsreq;
-       unsigned long flags;
-
-       hsep = our_ep(_ep);
-       if (!_ep || hsep->ep.name == ep0name)
-               return -EINVAL;
-
-       spin_lock_irqsave(&hsudc->lock, flags);
-
-       list_for_each_entry(hsreq, &hsep->queue, queue) {
-               if (&hsreq->req == _req)
-                       break;
-       }
-       if (&hsreq->req != _req) {
-               spin_unlock_irqrestore(&hsudc->lock, flags);
-               return -EINVAL;
-       }
-
-       set_index(hsudc, hsep->bEndpointAddress);
-       s3c_hsudc_complete_request(hsep, hsreq, -ECONNRESET);
-
-       spin_unlock_irqrestore(&hsudc->lock, flags);
-       return 0;
-}
-
-static struct usb_ep_ops s3c_hsudc_ep_ops = {
-       .enable = s3c_hsudc_ep_enable,
-       .disable = s3c_hsudc_ep_disable,
-       .alloc_request = s3c_hsudc_alloc_request,
-       .free_request = s3c_hsudc_free_request,
-       .queue = s3c_hsudc_queue,
-       .dequeue = s3c_hsudc_dequeue,
-       .set_halt = s3c_hsudc_set_halt,
-       .set_wedge = s3c_hsudc_set_wedge,
-};
-
-/**
- * s3c_hsudc_initep - Initialize a endpoint to default state.
- * @hsudc - Reference to the device controller.
- * @hsep - Endpoint to be initialized.
- * @epnum - Address to be assigned to the endpoint.
- *
- * Initialize a endpoint with default configuration.
- */
-static void s3c_hsudc_initep(struct s3c_hsudc *hsudc,
-                               struct s3c_hsudc_ep *hsep, int epnum)
-{
-       char *dir;
-
-       if ((epnum % 2) == 0) {
-               dir = "out";
-       } else {
-               dir = "in";
-               hsep->bEndpointAddress = USB_DIR_IN;
-       }
-
-       hsep->bEndpointAddress |= epnum;
-       if (epnum)
-               snprintf(hsep->name, sizeof(hsep->name), "ep%d%s", epnum, dir);
-       else
-               snprintf(hsep->name, sizeof(hsep->name), "%s", ep0name);
-
-       INIT_LIST_HEAD(&hsep->queue);
-       INIT_LIST_HEAD(&hsep->ep.ep_list);
-       if (epnum)
-               list_add_tail(&hsep->ep.ep_list, &hsudc->gadget.ep_list);
-
-       hsep->dev = hsudc;
-       hsep->ep.name = hsep->name;
-       usb_ep_set_maxpacket_limit(&hsep->ep, epnum ? 512 : 64);
-       hsep->ep.ops = &s3c_hsudc_ep_ops;
-       hsep->fifo = hsudc->regs + S3C_BR(epnum);
-       hsep->ep.desc = NULL;
-       hsep->stopped = 0;
-       hsep->wedge = 0;
-
-       set_index(hsudc, epnum);
-       writel(hsep->ep.maxpacket, hsudc->regs + S3C_MPR);
-}
-
-/**
- * s3c_hsudc_setup_ep - Configure all endpoints to default state.
- * @hsudc: Reference to device controller.
- *
- * Configures all endpoints to default state.
- */
-static void s3c_hsudc_setup_ep(struct s3c_hsudc *hsudc)
-{
-       int epnum;
-
-       hsudc->ep0state = WAIT_FOR_SETUP;
-       INIT_LIST_HEAD(&hsudc->gadget.ep_list);
-       for (epnum = 0; epnum < hsudc->pd->epnum; epnum++)
-               s3c_hsudc_initep(hsudc, &hsudc->ep[epnum], epnum);
-}
-
-/**
- * s3c_hsudc_reconfig - Reconfigure the device controller to default state.
- * @hsudc: Reference to device controller.
- *
- * Reconfigures the device controller registers to a default state.
- */
-static void s3c_hsudc_reconfig(struct s3c_hsudc *hsudc)
-{
-       writel(0xAA, hsudc->regs + S3C_EDR);
-       writel(1, hsudc->regs + S3C_EIER);
-       writel(0, hsudc->regs + S3C_TR);
-       writel(S3C_SCR_DTZIEN_EN | S3C_SCR_RRD_EN | S3C_SCR_SUS_EN |
-                       S3C_SCR_RST_EN, hsudc->regs + S3C_SCR);
-       writel(0, hsudc->regs + S3C_EP0CR);
-
-       s3c_hsudc_setup_ep(hsudc);
-}
-
-/**
- * s3c_hsudc_irq - Interrupt handler for device controller.
- * @irq: Not used.
- * @_dev: Reference to the device controller.
- *
- * Interrupt handler for the device controller. This handler handles controller
- * interrupts and endpoint interrupts.
- */
-static irqreturn_t s3c_hsudc_irq(int irq, void *_dev)
-{
-       struct s3c_hsudc *hsudc = _dev;
-       struct s3c_hsudc_ep *hsep;
-       u32 ep_intr;
-       u32 sys_status;
-       u32 ep_idx;
-
-       spin_lock(&hsudc->lock);
-
-       sys_status = readl(hsudc->regs + S3C_SSR);
-       ep_intr = readl(hsudc->regs + S3C_EIR) & 0x3FF;
-
-       if (!ep_intr && !(sys_status & S3C_SSR_DTZIEN_EN)) {
-               spin_unlock(&hsudc->lock);
-               return IRQ_HANDLED;
-       }
-
-       if (sys_status) {
-               if (sys_status & S3C_SSR_VBUSON)
-                       writel(S3C_SSR_VBUSON, hsudc->regs + S3C_SSR);
-
-               if (sys_status & S3C_SSR_ERR)
-                       writel(S3C_SSR_ERR, hsudc->regs + S3C_SSR);
-
-               if (sys_status & S3C_SSR_SDE) {
-                       writel(S3C_SSR_SDE, hsudc->regs + S3C_SSR);
-                       hsudc->gadget.speed = (sys_status & S3C_SSR_HSP) ?
-                               USB_SPEED_HIGH : USB_SPEED_FULL;
-               }
-
-               if (sys_status & S3C_SSR_SUSPEND) {
-                       writel(S3C_SSR_SUSPEND, hsudc->regs + S3C_SSR);
-                       if (hsudc->gadget.speed != USB_SPEED_UNKNOWN
-                               && hsudc->driver && hsudc->driver->suspend)
-                               hsudc->driver->suspend(&hsudc->gadget);
-               }
-
-               if (sys_status & S3C_SSR_RESUME) {
-                       writel(S3C_SSR_RESUME, hsudc->regs + S3C_SSR);
-                       if (hsudc->gadget.speed != USB_SPEED_UNKNOWN
-                               && hsudc->driver && hsudc->driver->resume)
-                               hsudc->driver->resume(&hsudc->gadget);
-               }
-
-               if (sys_status & S3C_SSR_RESET) {
-                       writel(S3C_SSR_RESET, hsudc->regs + S3C_SSR);
-                       for (ep_idx = 0; ep_idx < hsudc->pd->epnum; ep_idx++) {
-                               hsep = &hsudc->ep[ep_idx];
-                               hsep->stopped = 1;
-                               s3c_hsudc_nuke_ep(hsep, -ECONNRESET);
-                       }
-                       s3c_hsudc_reconfig(hsudc);
-                       hsudc->ep0state = WAIT_FOR_SETUP;
-               }
-       }
-
-       if (ep_intr & S3C_EIR_EP0) {
-               writel(S3C_EIR_EP0, hsudc->regs + S3C_EIR);
-               set_index(hsudc, 0);
-               s3c_hsudc_handle_ep0_intr(hsudc);
-       }
-
-       ep_intr >>= 1;
-       ep_idx = 1;
-       while (ep_intr) {
-               if (ep_intr & 1)  {
-                       hsep = &hsudc->ep[ep_idx];
-                       set_index(hsudc, ep_idx);
-                       writel(1 << ep_idx, hsudc->regs + S3C_EIR);
-                       if (ep_is_in(hsep))
-                               s3c_hsudc_epin_intr(hsudc, ep_idx);
-                       else
-                               s3c_hsudc_epout_intr(hsudc, ep_idx);
-               }
-               ep_intr >>= 1;
-               ep_idx++;
-       }
-
-       spin_unlock(&hsudc->lock);
-       return IRQ_HANDLED;
-}
-
-static int s3c_hsudc_start(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct s3c_hsudc *hsudc = to_hsudc(gadget);
-       int ret;
-
-       if (!driver
-               || driver->max_speed < USB_SPEED_FULL
-               || !driver->setup)
-               return -EINVAL;
-
-       if (!hsudc)
-               return -ENODEV;
-
-       if (hsudc->driver)
-               return -EBUSY;
-
-       hsudc->driver = driver;
-
-       ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies),
-                                   hsudc->supplies);
-       if (ret != 0) {
-               dev_err(hsudc->dev, "failed to enable supplies: %d\n", ret);
-               goto err_supplies;
-       }
-
-       /* connect to bus through transceiver */
-       if (!IS_ERR_OR_NULL(hsudc->transceiver)) {
-               ret = otg_set_peripheral(hsudc->transceiver->otg,
-                                       &hsudc->gadget);
-               if (ret) {
-                       dev_err(hsudc->dev, "%s: can't bind to transceiver\n",
-                                       hsudc->gadget.name);
-                       goto err_otg;
-               }
-       }
-
-       enable_irq(hsudc->irq);
-       dev_info(hsudc->dev, "bound driver %s\n", driver->driver.name);
-
-       s3c_hsudc_reconfig(hsudc);
-
-       pm_runtime_get_sync(hsudc->dev);
-
-       s3c_hsudc_init_phy();
-       if (hsudc->pd->gpio_init)
-               hsudc->pd->gpio_init();
-
-       return 0;
-err_otg:
-       regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
-err_supplies:
-       hsudc->driver = NULL;
-       return ret;
-}
-
-static int s3c_hsudc_stop(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct s3c_hsudc *hsudc = to_hsudc(gadget);
-       unsigned long flags;
-
-       if (!hsudc)
-               return -ENODEV;
-
-       if (!driver || driver != hsudc->driver)
-               return -EINVAL;
-
-       spin_lock_irqsave(&hsudc->lock, flags);
-       hsudc->driver = NULL;
-       hsudc->gadget.speed = USB_SPEED_UNKNOWN;
-       s3c_hsudc_uninit_phy();
-
-       pm_runtime_put(hsudc->dev);
-
-       if (hsudc->pd->gpio_uninit)
-               hsudc->pd->gpio_uninit();
-       s3c_hsudc_stop_activity(hsudc);
-       spin_unlock_irqrestore(&hsudc->lock, flags);
-
-       if (!IS_ERR_OR_NULL(hsudc->transceiver))
-               (void) otg_set_peripheral(hsudc->transceiver->otg, NULL);
-
-       disable_irq(hsudc->irq);
-
-       regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
-
-       dev_info(hsudc->dev, "unregistered gadget driver '%s'\n",
-                       driver->driver.name);
-       return 0;
-}
-
-static inline u32 s3c_hsudc_read_frameno(struct s3c_hsudc *hsudc)
-{
-       return readl(hsudc->regs + S3C_FNR) & 0x3FF;
-}
-
-static int s3c_hsudc_gadget_getframe(struct usb_gadget *gadget)
-{
-       return s3c_hsudc_read_frameno(to_hsudc(gadget));
-}
-
-static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA)
-{
-       struct s3c_hsudc *hsudc = to_hsudc(gadget);
-
-       if (!hsudc)
-               return -ENODEV;
-
-       if (!IS_ERR_OR_NULL(hsudc->transceiver))
-               return usb_phy_set_power(hsudc->transceiver, mA);
-
-       return -EOPNOTSUPP;
-}
-
-static const struct usb_gadget_ops s3c_hsudc_gadget_ops = {
-       .get_frame      = s3c_hsudc_gadget_getframe,
-       .udc_start      = s3c_hsudc_start,
-       .udc_stop       = s3c_hsudc_stop,
-       .vbus_draw      = s3c_hsudc_vbus_draw,
-};
-
-static int s3c_hsudc_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct resource *res;
-       struct s3c_hsudc *hsudc;
-       struct s3c24xx_hsudc_platdata *pd = dev_get_platdata(&pdev->dev);
-       int ret, i;
-
-       hsudc = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsudc) +
-                       sizeof(struct s3c_hsudc_ep) * pd->epnum,
-                       GFP_KERNEL);
-       if (!hsudc) {
-               dev_err(dev, "cannot allocate memory\n");
-               return -ENOMEM;
-       }
-
-       platform_set_drvdata(pdev, dev);
-       hsudc->dev = dev;
-       hsudc->pd = dev_get_platdata(&pdev->dev);
-
-       hsudc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
-
-       for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++)
-               hsudc->supplies[i].supply = s3c_hsudc_supply_names[i];
-
-       ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsudc->supplies),
-                                hsudc->supplies);
-       if (ret != 0) {
-               dev_err(dev, "failed to request supplies: %d\n", ret);
-               goto err_supplies;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-       hsudc->regs = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(hsudc->regs)) {
-               ret = PTR_ERR(hsudc->regs);
-               goto err_res;
-       }
-
-       spin_lock_init(&hsudc->lock);
-
-       hsudc->gadget.max_speed = USB_SPEED_HIGH;
-       hsudc->gadget.ops = &s3c_hsudc_gadget_ops;
-       hsudc->gadget.name = dev_name(dev);
-       hsudc->gadget.ep0 = &hsudc->ep[0].ep;
-       hsudc->gadget.is_otg = 0;
-       hsudc->gadget.is_a_peripheral = 0;
-       hsudc->gadget.speed = USB_SPEED_UNKNOWN;
-
-       s3c_hsudc_setup_ep(hsudc);
-
-       ret = platform_get_irq(pdev, 0);
-       if (ret < 0) {
-               dev_err(dev, "unable to obtain IRQ number\n");
-               goto err_res;
-       }
-       hsudc->irq = ret;
-
-       ret = devm_request_irq(&pdev->dev, hsudc->irq, s3c_hsudc_irq, 0,
-                               driver_name, hsudc);
-       if (ret < 0) {
-               dev_err(dev, "irq request failed\n");
-               goto err_res;
-       }
-
-       hsudc->uclk = devm_clk_get(&pdev->dev, "usb-device");
-       if (IS_ERR(hsudc->uclk)) {
-               dev_err(dev, "failed to find usb-device clock source\n");
-               ret = PTR_ERR(hsudc->uclk);
-               goto err_res;
-       }
-       clk_enable(hsudc->uclk);
-
-       local_irq_disable();
-
-       disable_irq(hsudc->irq);
-       local_irq_enable();
-
-       ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget);
-       if (ret)
-               goto err_add_udc;
-
-       pm_runtime_enable(dev);
-
-       return 0;
-err_add_udc:
-       clk_disable(hsudc->uclk);
-err_res:
-       if (!IS_ERR_OR_NULL(hsudc->transceiver))
-               usb_put_phy(hsudc->transceiver);
-
-err_supplies:
-       return ret;
-}
-
-static struct platform_driver s3c_hsudc_driver = {
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "s3c-hsudc",
-       },
-       .probe          = s3c_hsudc_probe,
-};
-
-module_platform_driver(s3c_hsudc_driver);
-
-MODULE_DESCRIPTION("Samsung S3C24XX USB high-speed controller driver");
-MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:s3c-hsudc");
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
deleted file mode 100644 (file)
index 357b58e..0000000
+++ /dev/null
@@ -1,2045 +0,0 @@
-/*
- * linux/drivers/usb/gadget/s3c2410_udc.c
- *
- * Samsung S3C24xx series on-chip full speed USB device controllers
- *
- * Copyright (C) 2004-2007 Herbert Pötzl - Arnaud Patard
- *     Additional cleanups by Ben Dooks <ben-linux@fluff.org>
- *
- * 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.
- */
-
-#define pr_fmt(fmt) "s3c2410_udc: " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/gpio.h>
-#include <linux/prefetch.h>
-#include <linux/io.h>
-
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-#include <linux/usb.h>
-#include <linux/usb/gadget.h>
-
-#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/unaligned.h>
-#include <mach/irqs.h>
-
-#include <mach/hardware.h>
-
-#include <plat/regs-udc.h>
-#include <linux/platform_data/usb-s3c2410_udc.h>
-
-
-#include "s3c2410_udc.h"
-
-#define DRIVER_DESC    "S3C2410 USB Device Controller Gadget"
-#define DRIVER_VERSION "29 Apr 2007"
-#define DRIVER_AUTHOR  "Herbert Pötzl <herbert@13thfloor.at>, " \
-                       "Arnaud Patard <arnaud.patard@rtp-net.org>"
-
-static const char              gadget_name[] = "s3c2410_udc";
-static const char              driver_desc[] = DRIVER_DESC;
-
-static struct s3c2410_udc      *the_controller;
-static struct clk              *udc_clock;
-static struct clk              *usb_bus_clock;
-static void __iomem            *base_addr;
-static u64                     rsrc_start;
-static u64                     rsrc_len;
-static struct dentry           *s3c2410_udc_debugfs_root;
-
-static inline u32 udc_read(u32 reg)
-{
-       return readb(base_addr + reg);
-}
-
-static inline void udc_write(u32 value, u32 reg)
-{
-       writeb(value, base_addr + reg);
-}
-
-static inline void udc_writeb(void __iomem *base, u32 value, u32 reg)
-{
-       writeb(value, base + reg);
-}
-
-static struct s3c2410_udc_mach_info *udc_info;
-
-/*************************** DEBUG FUNCTION ***************************/
-#define DEBUG_NORMAL   1
-#define DEBUG_VERBOSE  2
-
-#ifdef CONFIG_USB_S3C2410_DEBUG
-#define USB_S3C2410_DEBUG_LEVEL 0
-
-static uint32_t s3c2410_ticks = 0;
-
-static int dprintk(int level, const char *fmt, ...)
-{
-       static char printk_buf[1024];
-       static long prevticks;
-       static int invocation;
-       va_list args;
-       int len;
-
-       if (level > USB_S3C2410_DEBUG_LEVEL)
-               return 0;
-
-       if (s3c2410_ticks != prevticks) {
-               prevticks = s3c2410_ticks;
-               invocation = 0;
-       }
-
-       len = scnprintf(printk_buf,
-                       sizeof(printk_buf), "%1lu.%02d USB: ",
-                       prevticks, invocation++);
-
-       va_start(args, fmt);
-       len = vscnprintf(printk_buf+len,
-                       sizeof(printk_buf)-len, fmt, args);
-       va_end(args);
-
-       pr_debug("%s", printk_buf);
-       return len;
-}
-#else
-static int dprintk(int level, const char *fmt, ...)
-{
-       return 0;
-}
-#endif
-static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
-{
-       u32 addr_reg, pwr_reg, ep_int_reg, usb_int_reg;
-       u32 ep_int_en_reg, usb_int_en_reg, ep0_csr;
-       u32 ep1_i_csr1, ep1_i_csr2, ep1_o_csr1, ep1_o_csr2;
-       u32 ep2_i_csr1, ep2_i_csr2, ep2_o_csr1, ep2_o_csr2;
-
-       addr_reg       = udc_read(S3C2410_UDC_FUNC_ADDR_REG);
-       pwr_reg        = udc_read(S3C2410_UDC_PWR_REG);
-       ep_int_reg     = udc_read(S3C2410_UDC_EP_INT_REG);
-       usb_int_reg    = udc_read(S3C2410_UDC_USB_INT_REG);
-       ep_int_en_reg  = udc_read(S3C2410_UDC_EP_INT_EN_REG);
-       usb_int_en_reg = udc_read(S3C2410_UDC_USB_INT_EN_REG);
-       udc_write(0, S3C2410_UDC_INDEX_REG);
-       ep0_csr        = udc_read(S3C2410_UDC_IN_CSR1_REG);
-       udc_write(1, S3C2410_UDC_INDEX_REG);
-       ep1_i_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
-       ep1_i_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
-       ep1_o_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
-       ep1_o_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
-       udc_write(2, S3C2410_UDC_INDEX_REG);
-       ep2_i_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
-       ep2_i_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
-       ep2_o_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
-       ep2_o_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
-
-       seq_printf(m, "FUNC_ADDR_REG  : 0x%04X\n"
-                "PWR_REG        : 0x%04X\n"
-                "EP_INT_REG     : 0x%04X\n"
-                "USB_INT_REG    : 0x%04X\n"
-                "EP_INT_EN_REG  : 0x%04X\n"
-                "USB_INT_EN_REG : 0x%04X\n"
-                "EP0_CSR        : 0x%04X\n"
-                "EP1_I_CSR1     : 0x%04X\n"
-                "EP1_I_CSR2     : 0x%04X\n"
-                "EP1_O_CSR1     : 0x%04X\n"
-                "EP1_O_CSR2     : 0x%04X\n"
-                "EP2_I_CSR1     : 0x%04X\n"
-                "EP2_I_CSR2     : 0x%04X\n"
-                "EP2_O_CSR1     : 0x%04X\n"
-                "EP2_O_CSR2     : 0x%04X\n",
-                       addr_reg, pwr_reg, ep_int_reg, usb_int_reg,
-                       ep_int_en_reg, usb_int_en_reg, ep0_csr,
-                       ep1_i_csr1, ep1_i_csr2, ep1_o_csr1, ep1_o_csr2,
-                       ep2_i_csr1, ep2_i_csr2, ep2_o_csr1, ep2_o_csr2
-               );
-
-       return 0;
-}
-
-static int s3c2410_udc_debugfs_fops_open(struct inode *inode,
-                                        struct file *file)
-{
-       return single_open(file, s3c2410_udc_debugfs_seq_show, NULL);
-}
-
-static const struct file_operations s3c2410_udc_debugfs_fops = {
-       .open           = s3c2410_udc_debugfs_fops_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .owner          = THIS_MODULE,
-};
-
-/* io macros */
-
-static inline void s3c2410_udc_clear_ep0_opr(void __iomem *base)
-{
-       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-       udc_writeb(base, S3C2410_UDC_EP0_CSR_SOPKTRDY,
-                       S3C2410_UDC_EP0_CSR_REG);
-}
-
-static inline void s3c2410_udc_clear_ep0_sst(void __iomem *base)
-{
-       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-       writeb(0x00, base + S3C2410_UDC_EP0_CSR_REG);
-}
-
-static inline void s3c2410_udc_clear_ep0_se(void __iomem *base)
-{
-       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-       udc_writeb(base, S3C2410_UDC_EP0_CSR_SSE, S3C2410_UDC_EP0_CSR_REG);
-}
-
-static inline void s3c2410_udc_set_ep0_ipr(void __iomem *base)
-{
-       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-       udc_writeb(base, S3C2410_UDC_EP0_CSR_IPKRDY, S3C2410_UDC_EP0_CSR_REG);
-}
-
-static inline void s3c2410_udc_set_ep0_de(void __iomem *base)
-{
-       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-       udc_writeb(base, S3C2410_UDC_EP0_CSR_DE, S3C2410_UDC_EP0_CSR_REG);
-}
-
-inline void s3c2410_udc_set_ep0_ss(void __iomem *b)
-{
-       udc_writeb(b, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-       udc_writeb(b, S3C2410_UDC_EP0_CSR_SENDSTL, S3C2410_UDC_EP0_CSR_REG);
-}
-
-static inline void s3c2410_udc_set_ep0_de_out(void __iomem *base)
-{
-       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-
-       udc_writeb(base, (S3C2410_UDC_EP0_CSR_SOPKTRDY
-                               | S3C2410_UDC_EP0_CSR_DE),
-                       S3C2410_UDC_EP0_CSR_REG);
-}
-
-static inline void s3c2410_udc_set_ep0_sse_out(void __iomem *base)
-{
-       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-       udc_writeb(base, (S3C2410_UDC_EP0_CSR_SOPKTRDY
-                               | S3C2410_UDC_EP0_CSR_SSE),
-                       S3C2410_UDC_EP0_CSR_REG);
-}
-
-static inline void s3c2410_udc_set_ep0_de_in(void __iomem *base)
-{
-       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-       udc_writeb(base, (S3C2410_UDC_EP0_CSR_IPKRDY
-                       | S3C2410_UDC_EP0_CSR_DE),
-               S3C2410_UDC_EP0_CSR_REG);
-}
-
-/*------------------------- I/O ----------------------------------*/
-
-/*
- *     s3c2410_udc_done
- */
-static void s3c2410_udc_done(struct s3c2410_ep *ep,
-               struct s3c2410_request *req, int status)
-{
-       unsigned halted = ep->halted;
-
-       list_del_init(&req->queue);
-
-       if (likely(req->req.status == -EINPROGRESS))
-               req->req.status = status;
-       else
-               status = req->req.status;
-
-       ep->halted = 1;
-       req->req.complete(&ep->ep, &req->req);
-       ep->halted = halted;
-}
-
-static void s3c2410_udc_nuke(struct s3c2410_udc *udc,
-               struct s3c2410_ep *ep, int status)
-{
-       /* Sanity check */
-       if (&ep->queue == NULL)
-               return;
-
-       while (!list_empty(&ep->queue)) {
-               struct s3c2410_request *req;
-               req = list_entry(ep->queue.next, struct s3c2410_request,
-                               queue);
-               s3c2410_udc_done(ep, req, status);
-       }
-}
-
-static inline void s3c2410_udc_clear_ep_state(struct s3c2410_udc *dev)
-{
-       unsigned i;
-
-       /* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
-        * fifos, and pending transactions mustn't be continued in any case.
-        */
-
-       for (i = 1; i < S3C2410_ENDPOINTS; i++)
-               s3c2410_udc_nuke(dev, &dev->ep[i], -ECONNABORTED);
-}
-
-static inline int s3c2410_udc_fifo_count_out(void)
-{
-       int tmp;
-
-       tmp = udc_read(S3C2410_UDC_OUT_FIFO_CNT2_REG) << 8;
-       tmp |= udc_read(S3C2410_UDC_OUT_FIFO_CNT1_REG);
-       return tmp;
-}
-
-/*
- *     s3c2410_udc_write_packet
- */
-static inline int s3c2410_udc_write_packet(int fifo,
-               struct s3c2410_request *req,
-               unsigned max)
-{
-       unsigned len = min(req->req.length - req->req.actual, max);
-       u8 *buf = req->req.buf + req->req.actual;
-
-       prefetch(buf);
-
-       dprintk(DEBUG_VERBOSE, "%s %d %d %d %d\n", __func__,
-               req->req.actual, req->req.length, len, req->req.actual + len);
-
-       req->req.actual += len;
-
-       udelay(5);
-       writesb(base_addr + fifo, buf, len);
-       return len;
-}
-
-/*
- *     s3c2410_udc_write_fifo
- *
- * return:  0 = still running, 1 = completed, negative = errno
- */
-static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep,
-               struct s3c2410_request *req)
-{
-       unsigned        count;
-       int             is_last;
-       u32             idx;
-       int             fifo_reg;
-       u32             ep_csr;
-
-       idx = ep->bEndpointAddress & 0x7F;
-       switch (idx) {
-       default:
-               idx = 0;
-       case 0:
-               fifo_reg = S3C2410_UDC_EP0_FIFO_REG;
-               break;
-       case 1:
-               fifo_reg = S3C2410_UDC_EP1_FIFO_REG;
-               break;
-       case 2:
-               fifo_reg = S3C2410_UDC_EP2_FIFO_REG;
-               break;
-       case 3:
-               fifo_reg = S3C2410_UDC_EP3_FIFO_REG;
-               break;
-       case 4:
-               fifo_reg = S3C2410_UDC_EP4_FIFO_REG;
-               break;
-       }
-
-       count = s3c2410_udc_write_packet(fifo_reg, req, ep->ep.maxpacket);
-
-       /* last packet is often short (sometimes a zlp) */
-       if (count != ep->ep.maxpacket)
-               is_last = 1;
-       else if (req->req.length != req->req.actual || req->req.zero)
-               is_last = 0;
-       else
-               is_last = 2;
-
-       /* Only ep0 debug messages are interesting */
-       if (idx == 0)
-               dprintk(DEBUG_NORMAL,
-                       "Written ep%d %d.%d of %d b [last %d,z %d]\n",
-                       idx, count, req->req.actual, req->req.length,
-                       is_last, req->req.zero);
-
-       if (is_last) {
-               /* The order is important. It prevents sending 2 packets
-                * at the same time */
-
-               if (idx == 0) {
-                       /* Reset signal => no need to say 'data sent' */
-                       if (!(udc_read(S3C2410_UDC_USB_INT_REG)
-                                       & S3C2410_UDC_USBINT_RESET))
-                               s3c2410_udc_set_ep0_de_in(base_addr);
-                       ep->dev->ep0state = EP0_IDLE;
-               } else {
-                       udc_write(idx, S3C2410_UDC_INDEX_REG);
-                       ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
-                       udc_write(idx, S3C2410_UDC_INDEX_REG);
-                       udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY,
-                                       S3C2410_UDC_IN_CSR1_REG);
-               }
-
-               s3c2410_udc_done(ep, req, 0);
-               is_last = 1;
-       } else {
-               if (idx == 0) {
-                       /* Reset signal => no need to say 'data sent' */
-                       if (!(udc_read(S3C2410_UDC_USB_INT_REG)
-                                       & S3C2410_UDC_USBINT_RESET))
-                               s3c2410_udc_set_ep0_ipr(base_addr);
-               } else {
-                       udc_write(idx, S3C2410_UDC_INDEX_REG);
-                       ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
-                       udc_write(idx, S3C2410_UDC_INDEX_REG);
-                       udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY,
-                                       S3C2410_UDC_IN_CSR1_REG);
-               }
-       }
-
-       return is_last;
-}
-
-static inline int s3c2410_udc_read_packet(int fifo, u8 *buf,
-               struct s3c2410_request *req, unsigned avail)
-{
-       unsigned len;
-
-       len = min(req->req.length - req->req.actual, avail);
-       req->req.actual += len;
-
-       readsb(fifo + base_addr, buf, len);
-       return len;
-}
-
-/*
- * return:  0 = still running, 1 = queue empty, negative = errno
- */
-static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep,
-                                struct s3c2410_request *req)
-{
-       u8              *buf;
-       u32             ep_csr;
-       unsigned        bufferspace;
-       int             is_last = 1;
-       unsigned        avail;
-       int             fifo_count = 0;
-       u32             idx;
-       int             fifo_reg;
-
-       idx = ep->bEndpointAddress & 0x7F;
-
-       switch (idx) {
-       default:
-               idx = 0;
-       case 0:
-               fifo_reg = S3C2410_UDC_EP0_FIFO_REG;
-               break;
-       case 1:
-               fifo_reg = S3C2410_UDC_EP1_FIFO_REG;
-               break;
-       case 2:
-               fifo_reg = S3C2410_UDC_EP2_FIFO_REG;
-               break;
-       case 3:
-               fifo_reg = S3C2410_UDC_EP3_FIFO_REG;
-               break;
-       case 4:
-               fifo_reg = S3C2410_UDC_EP4_FIFO_REG;
-               break;
-       }
-
-       if (!req->req.length)
-               return 1;
-
-       buf = req->req.buf + req->req.actual;
-       bufferspace = req->req.length - req->req.actual;
-       if (!bufferspace) {
-               dprintk(DEBUG_NORMAL, "%s: buffer full!\n", __func__);
-               return -1;
-       }
-
-       udc_write(idx, S3C2410_UDC_INDEX_REG);
-
-       fifo_count = s3c2410_udc_fifo_count_out();
-       dprintk(DEBUG_NORMAL, "%s fifo count : %d\n", __func__, fifo_count);
-
-       if (fifo_count > ep->ep.maxpacket)
-               avail = ep->ep.maxpacket;
-       else
-               avail = fifo_count;
-
-       fifo_count = s3c2410_udc_read_packet(fifo_reg, buf, req, avail);
-
-       /* checking this with ep0 is not accurate as we already
-        * read a control request
-        **/
-       if (idx != 0 && fifo_count < ep->ep.maxpacket) {
-               is_last = 1;
-               /* overflowed this request?  flush extra data */
-               if (fifo_count != avail)
-                       req->req.status = -EOVERFLOW;
-       } else {
-               is_last = (req->req.length <= req->req.actual) ? 1 : 0;
-       }
-
-       udc_write(idx, S3C2410_UDC_INDEX_REG);
-       fifo_count = s3c2410_udc_fifo_count_out();
-
-       /* Only ep0 debug messages are interesting */
-       if (idx == 0)
-               dprintk(DEBUG_VERBOSE, "%s fifo count : %d [last %d]\n",
-                       __func__, fifo_count, is_last);
-
-       if (is_last) {
-               if (idx == 0) {
-                       s3c2410_udc_set_ep0_de_out(base_addr);
-                       ep->dev->ep0state = EP0_IDLE;
-               } else {
-                       udc_write(idx, S3C2410_UDC_INDEX_REG);
-                       ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG);
-                       udc_write(idx, S3C2410_UDC_INDEX_REG);
-                       udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY,
-                                       S3C2410_UDC_OUT_CSR1_REG);
-               }
-
-               s3c2410_udc_done(ep, req, 0);
-       } else {
-               if (idx == 0) {
-                       s3c2410_udc_clear_ep0_opr(base_addr);
-               } else {
-                       udc_write(idx, S3C2410_UDC_INDEX_REG);
-                       ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG);
-                       udc_write(idx, S3C2410_UDC_INDEX_REG);
-                       udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY,
-                                       S3C2410_UDC_OUT_CSR1_REG);
-               }
-       }
-
-       return is_last;
-}
-
-static int s3c2410_udc_read_fifo_crq(struct usb_ctrlrequest *crq)
-{
-       unsigned char *outbuf = (unsigned char *)crq;
-       int bytes_read = 0;
-
-       udc_write(0, S3C2410_UDC_INDEX_REG);
-
-       bytes_read = s3c2410_udc_fifo_count_out();
-
-       dprintk(DEBUG_NORMAL, "%s: fifo_count=%d\n", __func__, bytes_read);
-
-       if (bytes_read > sizeof(struct usb_ctrlrequest))
-               bytes_read = sizeof(struct usb_ctrlrequest);
-
-       readsb(S3C2410_UDC_EP0_FIFO_REG + base_addr, outbuf, bytes_read);
-
-       dprintk(DEBUG_VERBOSE, "%s: len=%d %02x:%02x {%x,%x,%x}\n", __func__,
-               bytes_read, crq->bRequest, crq->bRequestType,
-               crq->wValue, crq->wIndex, crq->wLength);
-
-       return bytes_read;
-}
-
-static int s3c2410_udc_get_status(struct s3c2410_udc *dev,
-               struct usb_ctrlrequest *crq)
-{
-       u16 status = 0;
-       u8 ep_num = crq->wIndex & 0x7F;
-       u8 is_in = crq->wIndex & USB_DIR_IN;
-
-       switch (crq->bRequestType & USB_RECIP_MASK) {
-       case USB_RECIP_INTERFACE:
-               break;
-
-       case USB_RECIP_DEVICE:
-               status = dev->devstatus;
-               break;
-
-       case USB_RECIP_ENDPOINT:
-               if (ep_num > 4 || crq->wLength > 2)
-                       return 1;
-
-               if (ep_num == 0) {
-                       udc_write(0, S3C2410_UDC_INDEX_REG);
-                       status = udc_read(S3C2410_UDC_IN_CSR1_REG);
-                       status = status & S3C2410_UDC_EP0_CSR_SENDSTL;
-               } else {
-                       udc_write(ep_num, S3C2410_UDC_INDEX_REG);
-                       if (is_in) {
-                               status = udc_read(S3C2410_UDC_IN_CSR1_REG);
-                               status = status & S3C2410_UDC_ICSR1_SENDSTL;
-                       } else {
-                               status = udc_read(S3C2410_UDC_OUT_CSR1_REG);
-                               status = status & S3C2410_UDC_OCSR1_SENDSTL;
-                       }
-               }
-
-               status = status ? 1 : 0;
-               break;
-
-       default:
-               return 1;
-       }
-
-       /* Seems to be needed to get it working. ouch :( */
-       udelay(5);
-       udc_write(status & 0xFF, S3C2410_UDC_EP0_FIFO_REG);
-       udc_write(status >> 8, S3C2410_UDC_EP0_FIFO_REG);
-       s3c2410_udc_set_ep0_de_in(base_addr);
-
-       return 0;
-}
-/*------------------------- usb state machine -------------------------------*/
-static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value);
-
-static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev,
-                                       struct s3c2410_ep *ep,
-                                       struct usb_ctrlrequest *crq,
-                                       u32 ep0csr)
-{
-       int len, ret, tmp;
-
-       /* start control request? */
-       if (!(ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY))
-               return;
-
-       s3c2410_udc_nuke(dev, ep, -EPROTO);
-
-       len = s3c2410_udc_read_fifo_crq(crq);
-       if (len != sizeof(*crq)) {
-               dprintk(DEBUG_NORMAL, "setup begin: fifo READ ERROR"
-                       " wanted %d bytes got %d. Stalling out...\n",
-                       sizeof(*crq), len);
-               s3c2410_udc_set_ep0_ss(base_addr);
-               return;
-       }
-
-       dprintk(DEBUG_NORMAL, "bRequest = %d bRequestType %d wLength = %d\n",
-               crq->bRequest, crq->bRequestType, crq->wLength);
-
-       /* cope with automagic for some standard requests. */
-       dev->req_std = (crq->bRequestType & USB_TYPE_MASK)
-               == USB_TYPE_STANDARD;
-       dev->req_config = 0;
-       dev->req_pending = 1;
-
-       switch (crq->bRequest) {
-       case USB_REQ_SET_CONFIGURATION:
-               dprintk(DEBUG_NORMAL, "USB_REQ_SET_CONFIGURATION ...\n");
-
-               if (crq->bRequestType == USB_RECIP_DEVICE) {
-                       dev->req_config = 1;
-                       s3c2410_udc_set_ep0_de_out(base_addr);
-               }
-               break;
-
-       case USB_REQ_SET_INTERFACE:
-               dprintk(DEBUG_NORMAL, "USB_REQ_SET_INTERFACE ...\n");
-
-               if (crq->bRequestType == USB_RECIP_INTERFACE) {
-                       dev->req_config = 1;
-                       s3c2410_udc_set_ep0_de_out(base_addr);
-               }
-               break;
-
-       case USB_REQ_SET_ADDRESS:
-               dprintk(DEBUG_NORMAL, "USB_REQ_SET_ADDRESS ...\n");
-
-               if (crq->bRequestType == USB_RECIP_DEVICE) {
-                       tmp = crq->wValue & 0x7F;
-                       dev->address = tmp;
-                       udc_write((tmp | S3C2410_UDC_FUNCADDR_UPDATE),
-                                       S3C2410_UDC_FUNC_ADDR_REG);
-                       s3c2410_udc_set_ep0_de_out(base_addr);
-                       return;
-               }
-               break;
-
-       case USB_REQ_GET_STATUS:
-               dprintk(DEBUG_NORMAL, "USB_REQ_GET_STATUS ...\n");
-               s3c2410_udc_clear_ep0_opr(base_addr);
-
-               if (dev->req_std) {
-                       if (!s3c2410_udc_get_status(dev, crq))
-                               return;
-               }
-               break;
-
-       case USB_REQ_CLEAR_FEATURE:
-               s3c2410_udc_clear_ep0_opr(base_addr);
-
-               if (crq->bRequestType != USB_RECIP_ENDPOINT)
-                       break;
-
-               if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0)
-                       break;
-
-               s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 0);
-               s3c2410_udc_set_ep0_de_out(base_addr);
-               return;
-
-       case USB_REQ_SET_FEATURE:
-               s3c2410_udc_clear_ep0_opr(base_addr);
-
-               if (crq->bRequestType != USB_RECIP_ENDPOINT)
-                       break;
-
-               if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0)
-                       break;
-
-               s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 1);
-               s3c2410_udc_set_ep0_de_out(base_addr);
-               return;
-
-       default:
-               s3c2410_udc_clear_ep0_opr(base_addr);
-               break;
-       }
-
-       if (crq->bRequestType & USB_DIR_IN)
-               dev->ep0state = EP0_IN_DATA_PHASE;
-       else
-               dev->ep0state = EP0_OUT_DATA_PHASE;
-
-       if (!dev->driver)
-               return;
-
-       /* deliver the request to the gadget driver */
-       ret = dev->driver->setup(&dev->gadget, crq);
-       if (ret < 0) {
-               if (dev->req_config) {
-                       dprintk(DEBUG_NORMAL, "config change %02x fail %d?\n",
-                               crq->bRequest, ret);
-                       return;
-               }
-
-               if (ret == -EOPNOTSUPP)
-                       dprintk(DEBUG_NORMAL, "Operation not supported\n");
-               else
-                       dprintk(DEBUG_NORMAL,
-                               "dev->driver->setup failed. (%d)\n", ret);
-
-               udelay(5);
-               s3c2410_udc_set_ep0_ss(base_addr);
-               s3c2410_udc_set_ep0_de_out(base_addr);
-               dev->ep0state = EP0_IDLE;
-               /* deferred i/o == no response yet */
-       } else if (dev->req_pending) {
-               dprintk(DEBUG_VERBOSE, "dev->req_pending... what now?\n");
-               dev->req_pending = 0;
-       }
-
-       dprintk(DEBUG_VERBOSE, "ep0state %s\n", ep0states[dev->ep0state]);
-}
-
-static void s3c2410_udc_handle_ep0(struct s3c2410_udc *dev)
-{
-       u32                     ep0csr;
-       struct s3c2410_ep       *ep = &dev->ep[0];
-       struct s3c2410_request  *req;
-       struct usb_ctrlrequest  crq;
-
-       if (list_empty(&ep->queue))
-               req = NULL;
-       else
-               req = list_entry(ep->queue.next, struct s3c2410_request, queue);
-
-       /* We make the assumption that S3C2410_UDC_IN_CSR1_REG equal to
-        * S3C2410_UDC_EP0_CSR_REG when index is zero */
-
-       udc_write(0, S3C2410_UDC_INDEX_REG);
-       ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
-
-       dprintk(DEBUG_NORMAL, "ep0csr %x ep0state %s\n",
-               ep0csr, ep0states[dev->ep0state]);
-
-       /* clear stall status */
-       if (ep0csr & S3C2410_UDC_EP0_CSR_SENTSTL) {
-               s3c2410_udc_nuke(dev, ep, -EPIPE);
-               dprintk(DEBUG_NORMAL, "... clear SENT_STALL ...\n");
-               s3c2410_udc_clear_ep0_sst(base_addr);
-               dev->ep0state = EP0_IDLE;
-               return;
-       }
-
-       /* clear setup end */
-       if (ep0csr & S3C2410_UDC_EP0_CSR_SE) {
-               dprintk(DEBUG_NORMAL, "... serviced SETUP_END ...\n");
-               s3c2410_udc_nuke(dev, ep, 0);
-               s3c2410_udc_clear_ep0_se(base_addr);
-               dev->ep0state = EP0_IDLE;
-       }
-
-       switch (dev->ep0state) {
-       case EP0_IDLE:
-               s3c2410_udc_handle_ep0_idle(dev, ep, &crq, ep0csr);
-               break;
-
-       case EP0_IN_DATA_PHASE:                 /* GET_DESCRIPTOR etc */
-               dprintk(DEBUG_NORMAL, "EP0_IN_DATA_PHASE ... what now?\n");
-               if (!(ep0csr & S3C2410_UDC_EP0_CSR_IPKRDY) && req)
-                       s3c2410_udc_write_fifo(ep, req);
-               break;
-
-       case EP0_OUT_DATA_PHASE:                /* SET_DESCRIPTOR etc */
-               dprintk(DEBUG_NORMAL, "EP0_OUT_DATA_PHASE ... what now?\n");
-               if ((ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY) && req)
-                       s3c2410_udc_read_fifo(ep, req);
-               break;
-
-       case EP0_END_XFER:
-               dprintk(DEBUG_NORMAL, "EP0_END_XFER ... what now?\n");
-               dev->ep0state = EP0_IDLE;
-               break;
-
-       case EP0_STALL:
-               dprintk(DEBUG_NORMAL, "EP0_STALL ... what now?\n");
-               dev->ep0state = EP0_IDLE;
-               break;
-       }
-}
-
-/*
- *     handle_ep - Manage I/O endpoints
- */
-
-static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
-{
-       struct s3c2410_request  *req;
-       int                     is_in = ep->bEndpointAddress & USB_DIR_IN;
-       u32                     ep_csr1;
-       u32                     idx;
-
-       if (likely(!list_empty(&ep->queue)))
-               req = list_entry(ep->queue.next,
-                               struct s3c2410_request, queue);
-       else
-               req = NULL;
-
-       idx = ep->bEndpointAddress & 0x7F;
-
-       if (is_in) {
-               udc_write(idx, S3C2410_UDC_INDEX_REG);
-               ep_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
-               dprintk(DEBUG_VERBOSE, "ep%01d write csr:%02x %d\n",
-                       idx, ep_csr1, req ? 1 : 0);
-
-               if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) {
-                       dprintk(DEBUG_VERBOSE, "st\n");
-                       udc_write(idx, S3C2410_UDC_INDEX_REG);
-                       udc_write(ep_csr1 & ~S3C2410_UDC_ICSR1_SENTSTL,
-                                       S3C2410_UDC_IN_CSR1_REG);
-                       return;
-               }
-
-               if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req)
-                       s3c2410_udc_write_fifo(ep, req);
-       } else {
-               udc_write(idx, S3C2410_UDC_INDEX_REG);
-               ep_csr1 = udc_read(S3C2410_UDC_OUT_CSR1_REG);
-               dprintk(DEBUG_VERBOSE, "ep%01d rd csr:%02x\n", idx, ep_csr1);
-
-               if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) {
-                       udc_write(idx, S3C2410_UDC_INDEX_REG);
-                       udc_write(ep_csr1 & ~S3C2410_UDC_OCSR1_SENTSTL,
-                                       S3C2410_UDC_OUT_CSR1_REG);
-                       return;
-               }
-
-               if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req)
-                       s3c2410_udc_read_fifo(ep, req);
-       }
-}
-
-#include <mach/regs-irq.h>
-
-/*
- *     s3c2410_udc_irq - interrupt handler
- */
-static irqreturn_t s3c2410_udc_irq(int dummy, void *_dev)
-{
-       struct s3c2410_udc *dev = _dev;
-       int usb_status;
-       int usbd_status;
-       int pwr_reg;
-       int ep0csr;
-       int i;
-       u32 idx, idx2;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       /* Driver connected ? */
-       if (!dev->driver) {
-               /* Clear interrupts */
-               udc_write(udc_read(S3C2410_UDC_USB_INT_REG),
-                               S3C2410_UDC_USB_INT_REG);
-               udc_write(udc_read(S3C2410_UDC_EP_INT_REG),
-                               S3C2410_UDC_EP_INT_REG);
-       }
-
-       /* Save index */
-       idx = udc_read(S3C2410_UDC_INDEX_REG);
-
-       /* Read status registers */
-       usb_status = udc_read(S3C2410_UDC_USB_INT_REG);
-       usbd_status = udc_read(S3C2410_UDC_EP_INT_REG);
-       pwr_reg = udc_read(S3C2410_UDC_PWR_REG);
-
-       udc_writeb(base_addr, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
-       ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
-
-       dprintk(DEBUG_NORMAL, "usbs=%02x, usbds=%02x, pwr=%02x ep0csr=%02x\n",
-               usb_status, usbd_status, pwr_reg, ep0csr);
-
-       /*
-        * Now, handle interrupts. There's two types :
-        * - Reset, Resume, Suspend coming -> usb_int_reg
-        * - EP -> ep_int_reg
-        */
-
-       /* RESET */
-       if (usb_status & S3C2410_UDC_USBINT_RESET) {
-               /* two kind of reset :
-                * - reset start -> pwr reg = 8
-                * - reset end   -> pwr reg = 0
-                **/
-               dprintk(DEBUG_NORMAL, "USB reset csr %x pwr %x\n",
-                       ep0csr, pwr_reg);
-
-               dev->gadget.speed = USB_SPEED_UNKNOWN;
-               udc_write(0x00, S3C2410_UDC_INDEX_REG);
-               udc_write((dev->ep[0].ep.maxpacket & 0x7ff) >> 3,
-                               S3C2410_UDC_MAXP_REG);
-               dev->address = 0;
-
-               dev->ep0state = EP0_IDLE;
-               dev->gadget.speed = USB_SPEED_FULL;
-
-               /* clear interrupt */
-               udc_write(S3C2410_UDC_USBINT_RESET,
-                               S3C2410_UDC_USB_INT_REG);
-
-               udc_write(idx, S3C2410_UDC_INDEX_REG);
-               spin_unlock_irqrestore(&dev->lock, flags);
-               return IRQ_HANDLED;
-       }
-
-       /* RESUME */
-       if (usb_status & S3C2410_UDC_USBINT_RESUME) {
-               dprintk(DEBUG_NORMAL, "USB resume\n");
-
-               /* clear interrupt */
-               udc_write(S3C2410_UDC_USBINT_RESUME,
-                               S3C2410_UDC_USB_INT_REG);
-
-               if (dev->gadget.speed != USB_SPEED_UNKNOWN
-                               && dev->driver
-                               && dev->driver->resume)
-                       dev->driver->resume(&dev->gadget);
-       }
-
-       /* SUSPEND */
-       if (usb_status & S3C2410_UDC_USBINT_SUSPEND) {
-               dprintk(DEBUG_NORMAL, "USB suspend\n");
-
-               /* clear interrupt */
-               udc_write(S3C2410_UDC_USBINT_SUSPEND,
-                               S3C2410_UDC_USB_INT_REG);
-
-               if (dev->gadget.speed != USB_SPEED_UNKNOWN
-                               && dev->driver
-                               && dev->driver->suspend)
-                       dev->driver->suspend(&dev->gadget);
-
-               dev->ep0state = EP0_IDLE;
-       }
-
-       /* EP */
-       /* control traffic */
-       /* check on ep0csr != 0 is not a good idea as clearing in_pkt_ready
-        * generate an interrupt
-        */
-       if (usbd_status & S3C2410_UDC_INT_EP0) {
-               dprintk(DEBUG_VERBOSE, "USB ep0 irq\n");
-               /* Clear the interrupt bit by setting it to 1 */
-               udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_REG);
-               s3c2410_udc_handle_ep0(dev);
-       }
-
-       /* endpoint data transfers */
-       for (i = 1; i < S3C2410_ENDPOINTS; i++) {
-               u32 tmp = 1 << i;
-               if (usbd_status & tmp) {
-                       dprintk(DEBUG_VERBOSE, "USB ep%d irq\n", i);
-
-                       /* Clear the interrupt bit by setting it to 1 */
-                       udc_write(tmp, S3C2410_UDC_EP_INT_REG);
-                       s3c2410_udc_handle_ep(&dev->ep[i]);
-               }
-       }
-
-       /* what else causes this interrupt? a receive! who is it? */
-       if (!usb_status && !usbd_status && !pwr_reg && !ep0csr) {
-               for (i = 1; i < S3C2410_ENDPOINTS; i++) {
-                       idx2 = udc_read(S3C2410_UDC_INDEX_REG);
-                       udc_write(i, S3C2410_UDC_INDEX_REG);
-
-                       if (udc_read(S3C2410_UDC_OUT_CSR1_REG) & 0x1)
-                               s3c2410_udc_handle_ep(&dev->ep[i]);
-
-                       /* restore index */
-                       udc_write(idx2, S3C2410_UDC_INDEX_REG);
-               }
-       }
-
-       dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", IRQ_USBD);
-
-       /* Restore old index */
-       udc_write(idx, S3C2410_UDC_INDEX_REG);
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return IRQ_HANDLED;
-}
-/*------------------------- s3c2410_ep_ops ----------------------------------*/
-
-static inline struct s3c2410_ep *to_s3c2410_ep(struct usb_ep *ep)
-{
-       return container_of(ep, struct s3c2410_ep, ep);
-}
-
-static inline struct s3c2410_udc *to_s3c2410_udc(struct usb_gadget *gadget)
-{
-       return container_of(gadget, struct s3c2410_udc, gadget);
-}
-
-static inline struct s3c2410_request *to_s3c2410_req(struct usb_request *req)
-{
-       return container_of(req, struct s3c2410_request, req);
-}
-
-/*
- *     s3c2410_udc_ep_enable
- */
-static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
-                                const struct usb_endpoint_descriptor *desc)
-{
-       struct s3c2410_udc      *dev;
-       struct s3c2410_ep       *ep;
-       u32                     max, tmp;
-       unsigned long           flags;
-       u32                     csr1, csr2;
-       u32                     int_en_reg;
-
-       ep = to_s3c2410_ep(_ep);
-
-       if (!_ep || !desc
-                       || _ep->name == ep0name
-                       || desc->bDescriptorType != USB_DT_ENDPOINT)
-               return -EINVAL;
-
-       dev = ep->dev;
-       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
-
-       max = usb_endpoint_maxp(desc) & 0x1fff;
-
-       local_irq_save(flags);
-       _ep->maxpacket = max & 0x7ff;
-       ep->ep.desc = desc;
-       ep->halted = 0;
-       ep->bEndpointAddress = desc->bEndpointAddress;
-
-       /* set max packet */
-       udc_write(ep->num, S3C2410_UDC_INDEX_REG);
-       udc_write(max >> 3, S3C2410_UDC_MAXP_REG);
-
-       /* set type, direction, address; reset fifo counters */
-       if (desc->bEndpointAddress & USB_DIR_IN) {
-               csr1 = S3C2410_UDC_ICSR1_FFLUSH|S3C2410_UDC_ICSR1_CLRDT;
-               csr2 = S3C2410_UDC_ICSR2_MODEIN|S3C2410_UDC_ICSR2_DMAIEN;
-
-               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
-               udc_write(csr1, S3C2410_UDC_IN_CSR1_REG);
-               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
-               udc_write(csr2, S3C2410_UDC_IN_CSR2_REG);
-       } else {
-               /* don't flush in fifo or it will cause endpoint interrupt */
-               csr1 = S3C2410_UDC_ICSR1_CLRDT;
-               csr2 = S3C2410_UDC_ICSR2_DMAIEN;
-
-               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
-               udc_write(csr1, S3C2410_UDC_IN_CSR1_REG);
-               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
-               udc_write(csr2, S3C2410_UDC_IN_CSR2_REG);
-
-               csr1 = S3C2410_UDC_OCSR1_FFLUSH | S3C2410_UDC_OCSR1_CLRDT;
-               csr2 = S3C2410_UDC_OCSR2_DMAIEN;
-
-               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
-               udc_write(csr1, S3C2410_UDC_OUT_CSR1_REG);
-               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
-               udc_write(csr2, S3C2410_UDC_OUT_CSR2_REG);
-       }
-
-       /* enable irqs */
-       int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
-       udc_write(int_en_reg | (1 << ep->num), S3C2410_UDC_EP_INT_EN_REG);
-
-       /* print some debug message */
-       tmp = desc->bEndpointAddress;
-       dprintk(DEBUG_NORMAL, "enable %s(%d) ep%x%s-blk max %02x\n",
-                _ep->name, ep->num, tmp,
-                desc->bEndpointAddress & USB_DIR_IN ? "in" : "out", max);
-
-       local_irq_restore(flags);
-       s3c2410_udc_set_halt(_ep, 0);
-
-       return 0;
-}
-
-/*
- * s3c2410_udc_ep_disable
- */
-static int s3c2410_udc_ep_disable(struct usb_ep *_ep)
-{
-       struct s3c2410_ep *ep = to_s3c2410_ep(_ep);
-       unsigned long flags;
-       u32 int_en_reg;
-
-       if (!_ep || !ep->ep.desc) {
-               dprintk(DEBUG_NORMAL, "%s not enabled\n",
-                       _ep ? ep->ep.name : NULL);
-               return -EINVAL;
-       }
-
-       local_irq_save(flags);
-
-       dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name);
-
-       ep->ep.desc = NULL;
-       ep->halted = 1;
-
-       s3c2410_udc_nuke(ep->dev, ep, -ESHUTDOWN);
-
-       /* disable irqs */
-       int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
-       udc_write(int_en_reg & ~(1<<ep->num), S3C2410_UDC_EP_INT_EN_REG);
-
-       local_irq_restore(flags);
-
-       dprintk(DEBUG_NORMAL, "%s disabled\n", _ep->name);
-
-       return 0;
-}
-
-/*
- * s3c2410_udc_alloc_request
- */
-static struct usb_request *
-s3c2410_udc_alloc_request(struct usb_ep *_ep, gfp_t mem_flags)
-{
-       struct s3c2410_request *req;
-
-       dprintk(DEBUG_VERBOSE, "%s(%p,%d)\n", __func__, _ep, mem_flags);
-
-       if (!_ep)
-               return NULL;
-
-       req = kzalloc(sizeof(struct s3c2410_request), mem_flags);
-       if (!req)
-               return NULL;
-
-       INIT_LIST_HEAD(&req->queue);
-       return &req->req;
-}
-
-/*
- * s3c2410_udc_free_request
- */
-static void
-s3c2410_udc_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct s3c2410_ep       *ep = to_s3c2410_ep(_ep);
-       struct s3c2410_request  *req = to_s3c2410_req(_req);
-
-       dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req);
-
-       if (!ep || !_req || (!ep->ep.desc && _ep->name != ep0name))
-               return;
-
-       WARN_ON(!list_empty(&req->queue));
-       kfree(req);
-}
-
-/*
- *     s3c2410_udc_queue
- */
-static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req,
-               gfp_t gfp_flags)
-{
-       struct s3c2410_request  *req = to_s3c2410_req(_req);
-       struct s3c2410_ep       *ep = to_s3c2410_ep(_ep);
-       struct s3c2410_udc      *dev;
-       u32                     ep_csr = 0;
-       int                     fifo_count = 0;
-       unsigned long           flags;
-
-       if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) {
-               dprintk(DEBUG_NORMAL, "%s: invalid args\n", __func__);
-               return -EINVAL;
-       }
-
-       dev = ep->dev;
-       if (unlikely(!dev->driver
-                       || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
-               return -ESHUTDOWN;
-       }
-
-       local_irq_save(flags);
-
-       if (unlikely(!_req || !_req->complete
-                       || !_req->buf || !list_empty(&req->queue))) {
-               if (!_req)
-                       dprintk(DEBUG_NORMAL, "%s: 1 X X X\n", __func__);
-               else {
-                       dprintk(DEBUG_NORMAL, "%s: 0 %01d %01d %01d\n",
-                               __func__, !_req->complete, !_req->buf,
-                               !list_empty(&req->queue));
-               }
-
-               local_irq_restore(flags);
-               return -EINVAL;
-       }
-
-       _req->status = -EINPROGRESS;
-       _req->actual = 0;
-
-       dprintk(DEBUG_VERBOSE, "%s: ep%x len %d\n",
-                __func__, ep->bEndpointAddress, _req->length);
-
-       if (ep->bEndpointAddress) {
-               udc_write(ep->bEndpointAddress & 0x7F, S3C2410_UDC_INDEX_REG);
-
-               ep_csr = udc_read((ep->bEndpointAddress & USB_DIR_IN)
-                               ? S3C2410_UDC_IN_CSR1_REG
-                               : S3C2410_UDC_OUT_CSR1_REG);
-               fifo_count = s3c2410_udc_fifo_count_out();
-       } else {
-               udc_write(0, S3C2410_UDC_INDEX_REG);
-               ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
-               fifo_count = s3c2410_udc_fifo_count_out();
-       }
-
-       /* kickstart this i/o queue? */
-       if (list_empty(&ep->queue) && !ep->halted) {
-               if (ep->bEndpointAddress == 0 /* ep0 */) {
-                       switch (dev->ep0state) {
-                       case EP0_IN_DATA_PHASE:
-                               if (!(ep_csr&S3C2410_UDC_EP0_CSR_IPKRDY)
-                                               && s3c2410_udc_write_fifo(ep,
-                                                       req)) {
-                                       dev->ep0state = EP0_IDLE;
-                                       req = NULL;
-                               }
-                               break;
-
-                       case EP0_OUT_DATA_PHASE:
-                               if ((!_req->length)
-                                       || ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY)
-                                               && s3c2410_udc_read_fifo(ep,
-                                                       req))) {
-                                       dev->ep0state = EP0_IDLE;
-                                       req = NULL;
-                               }
-                               break;
-
-                       default:
-                               local_irq_restore(flags);
-                               return -EL2HLT;
-                       }
-               } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0
-                               && (!(ep_csr&S3C2410_UDC_OCSR1_PKTRDY))
-                               && s3c2410_udc_write_fifo(ep, req)) {
-                       req = NULL;
-               } else if ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY)
-                               && fifo_count
-                               && s3c2410_udc_read_fifo(ep, req)) {
-                       req = NULL;
-               }
-       }
-
-       /* pio or dma irq handler advances the queue. */
-       if (likely(req))
-               list_add_tail(&req->queue, &ep->queue);
-
-       local_irq_restore(flags);
-
-       dprintk(DEBUG_VERBOSE, "%s ok\n", __func__);
-       return 0;
-}
-
-/*
- *     s3c2410_udc_dequeue
- */
-static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-       struct s3c2410_ep       *ep = to_s3c2410_ep(_ep);
-       struct s3c2410_udc      *udc;
-       int                     retval = -EINVAL;
-       unsigned long           flags;
-       struct s3c2410_request  *req = NULL;
-
-       dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req);
-
-       if (!the_controller->driver)
-               return -ESHUTDOWN;
-
-       if (!_ep || !_req)
-               return retval;
-
-       udc = to_s3c2410_udc(ep->gadget);
-
-       local_irq_save(flags);
-
-       list_for_each_entry(req, &ep->queue, queue) {
-               if (&req->req == _req) {
-                       list_del_init(&req->queue);
-                       _req->status = -ECONNRESET;
-                       retval = 0;
-                       break;
-               }
-       }
-
-       if (retval == 0) {
-               dprintk(DEBUG_VERBOSE,
-                       "dequeued req %p from %s, len %d buf %p\n",
-                       req, _ep->name, _req->length, _req->buf);
-
-               s3c2410_udc_done(ep, req, -ECONNRESET);
-       }
-
-       local_irq_restore(flags);
-       return retval;
-}
-
-/*
- * s3c2410_udc_set_halt
- */
-static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value)
-{
-       struct s3c2410_ep       *ep = to_s3c2410_ep(_ep);
-       u32                     ep_csr = 0;
-       unsigned long           flags;
-       u32                     idx;
-
-       if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) {
-               dprintk(DEBUG_NORMAL, "%s: inval 2\n", __func__);
-               return -EINVAL;
-       }
-
-       local_irq_save(flags);
-
-       idx = ep->bEndpointAddress & 0x7F;
-
-       if (idx == 0) {
-               s3c2410_udc_set_ep0_ss(base_addr);
-               s3c2410_udc_set_ep0_de_out(base_addr);
-       } else {
-               udc_write(idx, S3C2410_UDC_INDEX_REG);
-               ep_csr = udc_read((ep->bEndpointAddress & USB_DIR_IN)
-                               ? S3C2410_UDC_IN_CSR1_REG
-                               : S3C2410_UDC_OUT_CSR1_REG);
-
-               if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
-                       if (value)
-                               udc_write(ep_csr | S3C2410_UDC_ICSR1_SENDSTL,
-                                       S3C2410_UDC_IN_CSR1_REG);
-                       else {
-                               ep_csr &= ~S3C2410_UDC_ICSR1_SENDSTL;
-                               udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG);
-                               ep_csr |= S3C2410_UDC_ICSR1_CLRDT;
-                               udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG);
-                       }
-               } else {
-                       if (value)
-                               udc_write(ep_csr | S3C2410_UDC_OCSR1_SENDSTL,
-                                       S3C2410_UDC_OUT_CSR1_REG);
-                       else {
-                               ep_csr &= ~S3C2410_UDC_OCSR1_SENDSTL;
-                               udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG);
-                               ep_csr |= S3C2410_UDC_OCSR1_CLRDT;
-                               udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG);
-                       }
-               }
-       }
-
-       ep->halted = value ? 1 : 0;
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-static const struct usb_ep_ops s3c2410_ep_ops = {
-       .enable         = s3c2410_udc_ep_enable,
-       .disable        = s3c2410_udc_ep_disable,
-
-       .alloc_request  = s3c2410_udc_alloc_request,
-       .free_request   = s3c2410_udc_free_request,
-
-       .queue          = s3c2410_udc_queue,
-       .dequeue        = s3c2410_udc_dequeue,
-
-       .set_halt       = s3c2410_udc_set_halt,
-};
-
-/*------------------------- usb_gadget_ops ----------------------------------*/
-
-/*
- *     s3c2410_udc_get_frame
- */
-static int s3c2410_udc_get_frame(struct usb_gadget *_gadget)
-{
-       int tmp;
-
-       dprintk(DEBUG_VERBOSE, "%s()\n", __func__);
-
-       tmp = udc_read(S3C2410_UDC_FRAME_NUM2_REG) << 8;
-       tmp |= udc_read(S3C2410_UDC_FRAME_NUM1_REG);
-       return tmp;
-}
-
-/*
- *     s3c2410_udc_wakeup
- */
-static int s3c2410_udc_wakeup(struct usb_gadget *_gadget)
-{
-       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-       return 0;
-}
-
-/*
- *     s3c2410_udc_set_selfpowered
- */
-static int s3c2410_udc_set_selfpowered(struct usb_gadget *gadget, int value)
-{
-       struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
-
-       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-
-       if (value)
-               udc->devstatus |= (1 << USB_DEVICE_SELF_POWERED);
-       else
-               udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
-
-       return 0;
-}
-
-static void s3c2410_udc_disable(struct s3c2410_udc *dev);
-static void s3c2410_udc_enable(struct s3c2410_udc *dev);
-
-static int s3c2410_udc_set_pullup(struct s3c2410_udc *udc, int is_on)
-{
-       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-
-       if (udc_info && (udc_info->udc_command ||
-               gpio_is_valid(udc_info->pullup_pin))) {
-
-               if (is_on)
-                       s3c2410_udc_enable(udc);
-               else {
-                       if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
-                               if (udc->driver && udc->driver->disconnect)
-                                       udc->driver->disconnect(&udc->gadget);
-
-                       }
-                       s3c2410_udc_disable(udc);
-               }
-       } else {
-               return -EOPNOTSUPP;
-       }
-
-       return 0;
-}
-
-static int s3c2410_udc_vbus_session(struct usb_gadget *gadget, int is_active)
-{
-       struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
-
-       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-
-       udc->vbus = (is_active != 0);
-       s3c2410_udc_set_pullup(udc, is_active);
-       return 0;
-}
-
-static int s3c2410_udc_pullup(struct usb_gadget *gadget, int is_on)
-{
-       struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
-
-       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-
-       s3c2410_udc_set_pullup(udc, is_on ? 0 : 1);
-       return 0;
-}
-
-static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev)
-{
-       struct s3c2410_udc      *dev = _dev;
-       unsigned int            value;
-
-       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-
-       value = gpio_get_value(udc_info->vbus_pin) ? 1 : 0;
-       if (udc_info->vbus_pin_inverted)
-               value = !value;
-
-       if (value != dev->vbus)
-               s3c2410_udc_vbus_session(&dev->gadget, value);
-
-       return IRQ_HANDLED;
-}
-
-static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
-{
-       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-
-       if (udc_info && udc_info->vbus_draw) {
-               udc_info->vbus_draw(ma);
-               return 0;
-       }
-
-       return -ENOTSUPP;
-}
-
-static int s3c2410_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-static int s3c2410_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver);
-
-static const struct usb_gadget_ops s3c2410_ops = {
-       .get_frame              = s3c2410_udc_get_frame,
-       .wakeup                 = s3c2410_udc_wakeup,
-       .set_selfpowered        = s3c2410_udc_set_selfpowered,
-       .pullup                 = s3c2410_udc_pullup,
-       .vbus_session           = s3c2410_udc_vbus_session,
-       .vbus_draw              = s3c2410_vbus_draw,
-       .udc_start              = s3c2410_udc_start,
-       .udc_stop               = s3c2410_udc_stop,
-};
-
-static void s3c2410_udc_command(enum s3c2410_udc_cmd_e cmd)
-{
-       if (!udc_info)
-               return;
-
-       if (udc_info->udc_command) {
-               udc_info->udc_command(cmd);
-       } else if (gpio_is_valid(udc_info->pullup_pin)) {
-               int value;
-
-               switch (cmd) {
-               case S3C2410_UDC_P_ENABLE:
-                       value = 1;
-                       break;
-               case S3C2410_UDC_P_DISABLE:
-                       value = 0;
-                       break;
-               default:
-                       return;
-               }
-               value ^= udc_info->pullup_pin_inverted;
-
-               gpio_set_value(udc_info->pullup_pin, value);
-       }
-}
-
-/*------------------------- gadget driver handling---------------------------*/
-/*
- * s3c2410_udc_disable
- */
-static void s3c2410_udc_disable(struct s3c2410_udc *dev)
-{
-       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
-
-       /* Disable all interrupts */
-       udc_write(0x00, S3C2410_UDC_USB_INT_EN_REG);
-       udc_write(0x00, S3C2410_UDC_EP_INT_EN_REG);
-
-       /* Clear the interrupt registers */
-       udc_write(S3C2410_UDC_USBINT_RESET
-                               | S3C2410_UDC_USBINT_RESUME
-                               | S3C2410_UDC_USBINT_SUSPEND,
-                       S3C2410_UDC_USB_INT_REG);
-
-       udc_write(0x1F, S3C2410_UDC_EP_INT_REG);
-
-       /* Good bye, cruel world */
-       s3c2410_udc_command(S3C2410_UDC_P_DISABLE);
-
-       /* Set speed to unknown */
-       dev->gadget.speed = USB_SPEED_UNKNOWN;
-}
-
-/*
- * s3c2410_udc_reinit
- */
-static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
-{
-       u32 i;
-
-       /* device/ep0 records init */
-       INIT_LIST_HEAD(&dev->gadget.ep_list);
-       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
-       dev->ep0state = EP0_IDLE;
-
-       for (i = 0; i < S3C2410_ENDPOINTS; i++) {
-               struct s3c2410_ep *ep = &dev->ep[i];
-
-               if (i != 0)
-                       list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
-
-               ep->dev = dev;
-               ep->ep.desc = NULL;
-               ep->halted = 0;
-               INIT_LIST_HEAD(&ep->queue);
-               usb_ep_set_maxpacket_limit(&ep->ep, ep->ep.maxpacket);
-       }
-}
-
-/*
- * s3c2410_udc_enable
- */
-static void s3c2410_udc_enable(struct s3c2410_udc *dev)
-{
-       int i;
-
-       dprintk(DEBUG_NORMAL, "s3c2410_udc_enable called\n");
-
-       /* dev->gadget.speed = USB_SPEED_UNKNOWN; */
-       dev->gadget.speed = USB_SPEED_FULL;
-
-       /* Set MAXP for all endpoints */
-       for (i = 0; i < S3C2410_ENDPOINTS; i++) {
-               udc_write(i, S3C2410_UDC_INDEX_REG);
-               udc_write((dev->ep[i].ep.maxpacket & 0x7ff) >> 3,
-                               S3C2410_UDC_MAXP_REG);
-       }
-
-       /* Set default power state */
-       udc_write(DEFAULT_POWER_STATE, S3C2410_UDC_PWR_REG);
-
-       /* Enable reset and suspend interrupt interrupts */
-       udc_write(S3C2410_UDC_USBINT_RESET | S3C2410_UDC_USBINT_SUSPEND,
-                       S3C2410_UDC_USB_INT_EN_REG);
-
-       /* Enable ep0 interrupt */
-       udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_EN_REG);
-
-       /* time to say "hello, world" */
-       s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
-}
-
-static int s3c2410_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct s3c2410_udc *udc = to_s3c2410(g);
-
-       dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name);
-
-       /* Hook the driver */
-       udc->driver = driver;
-
-       /* Enable udc */
-       s3c2410_udc_enable(udc);
-
-       return 0;
-}
-
-static int s3c2410_udc_stop(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
-{
-       struct s3c2410_udc *udc = to_s3c2410(g);
-
-       udc->driver = NULL;
-
-       /* Disable udc */
-       s3c2410_udc_disable(udc);
-
-       return 0;
-}
-
-/*---------------------------------------------------------------------------*/
-static struct s3c2410_udc memory = {
-       .gadget = {
-               .ops            = &s3c2410_ops,
-               .ep0            = &memory.ep[0].ep,
-               .name           = gadget_name,
-               .dev = {
-                       .init_name      = "gadget",
-               },
-       },
-
-       /* control endpoint */
-       .ep[0] = {
-               .num            = 0,
-               .ep = {
-                       .name           = ep0name,
-                       .ops            = &s3c2410_ep_ops,
-                       .maxpacket      = EP0_FIFO_SIZE,
-               },
-               .dev            = &memory,
-       },
-
-       /* first group of endpoints */
-       .ep[1] = {
-               .num            = 1,
-               .ep = {
-                       .name           = "ep1-bulk",
-                       .ops            = &s3c2410_ep_ops,
-                       .maxpacket      = EP_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = EP_FIFO_SIZE,
-               .bEndpointAddress = 1,
-               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-       },
-       .ep[2] = {
-               .num            = 2,
-               .ep = {
-                       .name           = "ep2-bulk",
-                       .ops            = &s3c2410_ep_ops,
-                       .maxpacket      = EP_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = EP_FIFO_SIZE,
-               .bEndpointAddress = 2,
-               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-       },
-       .ep[3] = {
-               .num            = 3,
-               .ep = {
-                       .name           = "ep3-bulk",
-                       .ops            = &s3c2410_ep_ops,
-                       .maxpacket      = EP_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = EP_FIFO_SIZE,
-               .bEndpointAddress = 3,
-               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-       },
-       .ep[4] = {
-               .num            = 4,
-               .ep = {
-                       .name           = "ep4-bulk",
-                       .ops            = &s3c2410_ep_ops,
-                       .maxpacket      = EP_FIFO_SIZE,
-               },
-               .dev            = &memory,
-               .fifo_size      = EP_FIFO_SIZE,
-               .bEndpointAddress = 4,
-               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
-       }
-
-};
-
-/*
- *     probe - binds to the platform device
- */
-static int s3c2410_udc_probe(struct platform_device *pdev)
-{
-       struct s3c2410_udc *udc = &memory;
-       struct device *dev = &pdev->dev;
-       int retval;
-       int irq;
-
-       dev_dbg(dev, "%s()\n", __func__);
-
-       usb_bus_clock = clk_get(NULL, "usb-bus-gadget");
-       if (IS_ERR(usb_bus_clock)) {
-               dev_err(dev, "failed to get usb bus clock source\n");
-               return PTR_ERR(usb_bus_clock);
-       }
-
-       clk_prepare_enable(usb_bus_clock);
-
-       udc_clock = clk_get(NULL, "usb-device");
-       if (IS_ERR(udc_clock)) {
-               dev_err(dev, "failed to get udc clock source\n");
-               return PTR_ERR(udc_clock);
-       }
-
-       clk_prepare_enable(udc_clock);
-
-       mdelay(10);
-
-       dev_dbg(dev, "got and enabled clocks\n");
-
-       if (strncmp(pdev->name, "s3c2440", 7) == 0) {
-               dev_info(dev, "S3C2440: increasing FIFO to 128 bytes\n");
-               memory.ep[1].fifo_size = S3C2440_EP_FIFO_SIZE;
-               memory.ep[2].fifo_size = S3C2440_EP_FIFO_SIZE;
-               memory.ep[3].fifo_size = S3C2440_EP_FIFO_SIZE;
-               memory.ep[4].fifo_size = S3C2440_EP_FIFO_SIZE;
-       }
-
-       spin_lock_init(&udc->lock);
-       udc_info = dev_get_platdata(&pdev->dev);
-
-       rsrc_start = S3C2410_PA_USBDEV;
-       rsrc_len   = S3C24XX_SZ_USBDEV;
-
-       if (!request_mem_region(rsrc_start, rsrc_len, gadget_name))
-               return -EBUSY;
-
-       base_addr = ioremap(rsrc_start, rsrc_len);
-       if (!base_addr) {
-               retval = -ENOMEM;
-               goto err_mem;
-       }
-
-       the_controller = udc;
-       platform_set_drvdata(pdev, udc);
-
-       s3c2410_udc_disable(udc);
-       s3c2410_udc_reinit(udc);
-
-       /* irq setup after old hardware state is cleaned up */
-       retval = request_irq(IRQ_USBD, s3c2410_udc_irq,
-                            0, gadget_name, udc);
-
-       if (retval != 0) {
-               dev_err(dev, "cannot get irq %i, err %d\n", IRQ_USBD, retval);
-               retval = -EBUSY;
-               goto err_map;
-       }
-
-       dev_dbg(dev, "got irq %i\n", IRQ_USBD);
-
-       if (udc_info && udc_info->vbus_pin > 0) {
-               retval = gpio_request(udc_info->vbus_pin, "udc vbus");
-               if (retval < 0) {
-                       dev_err(dev, "cannot claim vbus pin\n");
-                       goto err_int;
-               }
-
-               irq = gpio_to_irq(udc_info->vbus_pin);
-               if (irq < 0) {
-                       dev_err(dev, "no irq for gpio vbus pin\n");
-                       retval = irq;
-                       goto err_gpio_claim;
-               }
-
-               retval = request_irq(irq, s3c2410_udc_vbus_irq,
-                                    IRQF_TRIGGER_RISING
-                                    | IRQF_TRIGGER_FALLING | IRQF_SHARED,
-                                    gadget_name, udc);
-
-               if (retval != 0) {
-                       dev_err(dev, "can't get vbus irq %d, err %d\n",
-                               irq, retval);
-                       retval = -EBUSY;
-                       goto err_gpio_claim;
-               }
-
-               dev_dbg(dev, "got irq %i\n", irq);
-       } else {
-               udc->vbus = 1;
-       }
-
-       if (udc_info && !udc_info->udc_command &&
-               gpio_is_valid(udc_info->pullup_pin)) {
-
-               retval = gpio_request_one(udc_info->pullup_pin,
-                               udc_info->vbus_pin_inverted ?
-                               GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
-                               "udc pullup");
-               if (retval)
-                       goto err_vbus_irq;
-       }
-
-       retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
-       if (retval)
-               goto err_add_udc;
-
-       if (s3c2410_udc_debugfs_root) {
-               udc->regs_info = debugfs_create_file("registers", S_IRUGO,
-                               s3c2410_udc_debugfs_root,
-                               udc, &s3c2410_udc_debugfs_fops);
-               if (!udc->regs_info)
-                       dev_warn(dev, "debugfs file creation failed\n");
-       }
-
-       dev_dbg(dev, "probe ok\n");
-
-       return 0;
-
-err_add_udc:
-       if (udc_info && !udc_info->udc_command &&
-                       gpio_is_valid(udc_info->pullup_pin))
-               gpio_free(udc_info->pullup_pin);
-err_vbus_irq:
-       if (udc_info && udc_info->vbus_pin > 0)
-               free_irq(gpio_to_irq(udc_info->vbus_pin), udc);
-err_gpio_claim:
-       if (udc_info && udc_info->vbus_pin > 0)
-               gpio_free(udc_info->vbus_pin);
-err_int:
-       free_irq(IRQ_USBD, udc);
-err_map:
-       iounmap(base_addr);
-err_mem:
-       release_mem_region(rsrc_start, rsrc_len);
-
-       return retval;
-}
-
-/*
- *     s3c2410_udc_remove
- */
-static int s3c2410_udc_remove(struct platform_device *pdev)
-{
-       struct s3c2410_udc *udc = platform_get_drvdata(pdev);
-       unsigned int irq;
-
-       dev_dbg(&pdev->dev, "%s()\n", __func__);
-
-       if (udc->driver)
-               return -EBUSY;
-
-       usb_del_gadget_udc(&udc->gadget);
-       debugfs_remove(udc->regs_info);
-
-       if (udc_info && !udc_info->udc_command &&
-               gpio_is_valid(udc_info->pullup_pin))
-               gpio_free(udc_info->pullup_pin);
-
-       if (udc_info && udc_info->vbus_pin > 0) {
-               irq = gpio_to_irq(udc_info->vbus_pin);
-               free_irq(irq, udc);
-       }
-
-       free_irq(IRQ_USBD, udc);
-
-       iounmap(base_addr);
-       release_mem_region(rsrc_start, rsrc_len);
-
-       if (!IS_ERR(udc_clock) && udc_clock != NULL) {
-               clk_disable_unprepare(udc_clock);
-               clk_put(udc_clock);
-               udc_clock = NULL;
-       }
-
-       if (!IS_ERR(usb_bus_clock) && usb_bus_clock != NULL) {
-               clk_disable_unprepare(usb_bus_clock);
-               clk_put(usb_bus_clock);
-               usb_bus_clock = NULL;
-       }
-
-       dev_dbg(&pdev->dev, "%s: remove ok\n", __func__);
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int
-s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message)
-{
-       s3c2410_udc_command(S3C2410_UDC_P_DISABLE);
-
-       return 0;
-}
-
-static int s3c2410_udc_resume(struct platform_device *pdev)
-{
-       s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
-
-       return 0;
-}
-#else
-#define s3c2410_udc_suspend    NULL
-#define s3c2410_udc_resume     NULL
-#endif
-
-static const struct platform_device_id s3c_udc_ids[] = {
-       { "s3c2410-usbgadget", },
-       { "s3c2440-usbgadget", },
-       { }
-};
-MODULE_DEVICE_TABLE(platform, s3c_udc_ids);
-
-static struct platform_driver udc_driver_24x0 = {
-       .driver         = {
-               .name   = "s3c24x0-usbgadget",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = s3c2410_udc_probe,
-       .remove         = s3c2410_udc_remove,
-       .suspend        = s3c2410_udc_suspend,
-       .resume         = s3c2410_udc_resume,
-       .id_table       = s3c_udc_ids,
-};
-
-static int __init udc_init(void)
-{
-       int retval;
-
-       dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);
-
-       s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
-       if (IS_ERR(s3c2410_udc_debugfs_root)) {
-               pr_err("%s: debugfs dir creation failed %ld\n",
-                       gadget_name, PTR_ERR(s3c2410_udc_debugfs_root));
-               s3c2410_udc_debugfs_root = NULL;
-       }
-
-       retval = platform_driver_register(&udc_driver_24x0);
-       if (retval)
-               goto err;
-
-       return 0;
-
-err:
-       debugfs_remove(s3c2410_udc_debugfs_root);
-       return retval;
-}
-
-static void __exit udc_exit(void)
-{
-       platform_driver_unregister(&udc_driver_24x0);
-       debugfs_remove(s3c2410_udc_debugfs_root);
-}
-
-module_init(udc_init);
-module_exit(udc_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/s3c2410_udc.h b/drivers/usb/gadget/s3c2410_udc.h
deleted file mode 100644 (file)
index 93bf225..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * linux/drivers/usb/gadget/s3c2410_udc.h
- * Samsung on-chip full speed USB device controllers
- *
- * Copyright (C) 2004-2007 Herbert Pötzl - Arnaud Patard
- *     Additional cleanups by Ben Dooks <ben-linux@fluff.org>
- *
- * 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.
- */
-
-#ifndef _S3C2410_UDC_H
-#define _S3C2410_UDC_H
-
-struct s3c2410_ep {
-       struct list_head                queue;
-       unsigned long                   last_io;        /* jiffies timestamp */
-       struct usb_gadget               *gadget;
-       struct s3c2410_udc              *dev;
-       struct usb_ep                   ep;
-       u8                              num;
-
-       unsigned short                  fifo_size;
-       u8                              bEndpointAddress;
-       u8                              bmAttributes;
-
-       unsigned                        halted : 1;
-       unsigned                        already_seen : 1;
-       unsigned                        setup_stage : 1;
-};
-
-
-/* Warning : ep0 has a fifo of 16 bytes */
-/* Don't try to set 32 or 64            */
-/* also testusb 14 fails  wit 16 but is */
-/* fine with 8                          */
-#define EP0_FIFO_SIZE           8
-#define EP_FIFO_SIZE           64
-#define DEFAULT_POWER_STATE    0x00
-
-#define S3C2440_EP_FIFO_SIZE   128
-
-static const char ep0name [] = "ep0";
-
-static const char *const ep_name[] = {
-       ep0name,                                /* everyone has ep0 */
-       /* s3c2410 four bidirectional bulk endpoints */
-       "ep1-bulk", "ep2-bulk", "ep3-bulk", "ep4-bulk",
-};
-
-#define S3C2410_ENDPOINTS       ARRAY_SIZE(ep_name)
-
-struct s3c2410_request {
-       struct list_head                queue;          /* ep's requests */
-       struct usb_request              req;
-};
-
-enum ep0_state {
-        EP0_IDLE,
-        EP0_IN_DATA_PHASE,
-        EP0_OUT_DATA_PHASE,
-        EP0_END_XFER,
-        EP0_STALL,
-};
-
-static const char *ep0states[]= {
-        "EP0_IDLE",
-        "EP0_IN_DATA_PHASE",
-        "EP0_OUT_DATA_PHASE",
-        "EP0_END_XFER",
-        "EP0_STALL",
-};
-
-struct s3c2410_udc {
-       spinlock_t                      lock;
-
-       struct s3c2410_ep               ep[S3C2410_ENDPOINTS];
-       int                             address;
-       struct usb_gadget               gadget;
-       struct usb_gadget_driver        *driver;
-       struct s3c2410_request          fifo_req;
-       u8                              fifo_buf[EP_FIFO_SIZE];
-       u16                             devstatus;
-
-       u32                             port_status;
-       int                             ep0state;
-
-       unsigned                        got_irq : 1;
-
-       unsigned                        req_std : 1;
-       unsigned                        req_config : 1;
-       unsigned                        req_pending : 1;
-       u8                              vbus;
-       struct dentry                   *regs_info;
-};
-#define to_s3c2410(g)  (container_of((g), struct s3c2410_udc, gadget))
-
-#endif
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
deleted file mode 100644 (file)
index b0d9817..0000000
+++ /dev/null
@@ -1,585 +0,0 @@
-/**
- * udc.c - Core UDC Framework
- *
- * Copyright (C) 2010 Texas Instruments
- * Author: Felipe Balbi <balbi@ti.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2  of
- * the License 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/err.h>
-#include <linux/dma-mapping.h>
-#include <linux/workqueue.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-/**
- * struct usb_udc - describes one usb device controller
- * @driver - the gadget driver pointer. For use by the class code
- * @dev - the child device to the actual controller
- * @gadget - the gadget. For use by the class code
- * @list - for use by the udc class driver
- *
- * This represents the internal data structure which is used by the UDC-class
- * to hold information about udc driver and gadget together.
- */
-struct usb_udc {
-       struct usb_gadget_driver        *driver;
-       struct usb_gadget               *gadget;
-       struct device                   dev;
-       struct list_head                list;
-};
-
-static struct class *udc_class;
-static LIST_HEAD(udc_list);
-static DEFINE_MUTEX(udc_lock);
-
-/* ------------------------------------------------------------------------- */
-
-#ifdef CONFIG_HAS_DMA
-
-int usb_gadget_map_request(struct usb_gadget *gadget,
-               struct usb_request *req, int is_in)
-{
-       if (req->length == 0)
-               return 0;
-
-       if (req->num_sgs) {
-               int     mapped;
-
-               mapped = dma_map_sg(&gadget->dev, req->sg, req->num_sgs,
-                               is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-               if (mapped == 0) {
-                       dev_err(&gadget->dev, "failed to map SGs\n");
-                       return -EFAULT;
-               }
-
-               req->num_mapped_sgs = mapped;
-       } else {
-               req->dma = dma_map_single(&gadget->dev, req->buf, req->length,
-                               is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-
-               if (dma_mapping_error(&gadget->dev, req->dma)) {
-                       dev_err(&gadget->dev, "failed to map buffer\n");
-                       return -EFAULT;
-               }
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(usb_gadget_map_request);
-
-void usb_gadget_unmap_request(struct usb_gadget *gadget,
-               struct usb_request *req, int is_in)
-{
-       if (req->length == 0)
-               return;
-
-       if (req->num_mapped_sgs) {
-               dma_unmap_sg(&gadget->dev, req->sg, req->num_mapped_sgs,
-                               is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-
-               req->num_mapped_sgs = 0;
-       } else {
-               dma_unmap_single(&gadget->dev, req->dma, req->length,
-                               is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-       }
-}
-EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
-
-#endif /* CONFIG_HAS_DMA */
-
-/* ------------------------------------------------------------------------- */
-
-static void usb_gadget_state_work(struct work_struct *work)
-{
-       struct usb_gadget       *gadget = work_to_gadget(work);
-
-       sysfs_notify(&gadget->dev.kobj, NULL, "state");
-}
-
-void usb_gadget_set_state(struct usb_gadget *gadget,
-               enum usb_device_state state)
-{
-       gadget->state = state;
-       schedule_work(&gadget->work);
-}
-EXPORT_SYMBOL_GPL(usb_gadget_set_state);
-
-/* ------------------------------------------------------------------------- */
-
-/**
- * usb_gadget_udc_start - tells usb device controller to start up
- * @gadget: The gadget we want to get started
- * @driver: The driver we want to bind to @gadget
- *
- * This call is issued by the UDC Class driver when it's about
- * to register a gadget driver to the device controller, before
- * calling gadget driver's bind() method.
- *
- * It allows the controller to be powered off until strictly
- * necessary to have it powered on.
- *
- * Returns zero on success, else negative errno.
- */
-static inline int usb_gadget_udc_start(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       return gadget->ops->udc_start(gadget, driver);
-}
-
-/**
- * usb_gadget_udc_stop - tells usb device controller we don't need it anymore
- * @gadget: The device we want to stop activity
- * @driver: The driver to unbind from @gadget
- *
- * This call is issued by the UDC Class driver after calling
- * gadget driver's unbind() method.
- *
- * The details are implementation specific, but it can go as
- * far as powering off UDC completely and disable its data
- * line pullups.
- */
-static inline void usb_gadget_udc_stop(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       gadget->ops->udc_stop(gadget, driver);
-}
-
-/**
- * usb_udc_release - release the usb_udc struct
- * @dev: the dev member within usb_udc
- *
- * This is called by driver's core in order to free memory once the last
- * reference is released.
- */
-static void usb_udc_release(struct device *dev)
-{
-       struct usb_udc *udc;
-
-       udc = container_of(dev, struct usb_udc, dev);
-       dev_dbg(dev, "releasing '%s'\n", dev_name(dev));
-       kfree(udc);
-}
-
-static const struct attribute_group *usb_udc_attr_groups[];
-
-static void usb_udc_nop_release(struct device *dev)
-{
-       dev_vdbg(dev, "%s\n", __func__);
-}
-
-/**
- * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
- * @parent: the parent device to this udc. Usually the controller driver's
- * device.
- * @gadget: the gadget to be added to the list.
- * @release: a gadget release function.
- *
- * Returns zero on success, negative errno otherwise.
- */
-int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
-               void (*release)(struct device *dev))
-{
-       struct usb_udc          *udc;
-       int                     ret = -ENOMEM;
-
-       udc = kzalloc(sizeof(*udc), GFP_KERNEL);
-       if (!udc)
-               goto err1;
-
-       dev_set_name(&gadget->dev, "gadget");
-       INIT_WORK(&gadget->work, usb_gadget_state_work);
-       gadget->dev.parent = parent;
-
-#ifdef CONFIG_HAS_DMA
-       dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask);
-       gadget->dev.dma_parms = parent->dma_parms;
-       gadget->dev.dma_mask = parent->dma_mask;
-#endif
-
-       if (release)
-               gadget->dev.release = release;
-       else
-               gadget->dev.release = usb_udc_nop_release;
-
-       ret = device_register(&gadget->dev);
-       if (ret)
-               goto err2;
-
-       device_initialize(&udc->dev);
-       udc->dev.release = usb_udc_release;
-       udc->dev.class = udc_class;
-       udc->dev.groups = usb_udc_attr_groups;
-       udc->dev.parent = parent;
-       ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
-       if (ret)
-               goto err3;
-
-       udc->gadget = gadget;
-
-       mutex_lock(&udc_lock);
-       list_add_tail(&udc->list, &udc_list);
-
-       ret = device_add(&udc->dev);
-       if (ret)
-               goto err4;
-
-       usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
-
-       mutex_unlock(&udc_lock);
-
-       return 0;
-
-err4:
-       list_del(&udc->list);
-       mutex_unlock(&udc_lock);
-
-err3:
-       put_device(&udc->dev);
-
-err2:
-       put_device(&gadget->dev);
-       kfree(udc);
-
-err1:
-       return ret;
-}
-EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);
-
-/**
- * usb_add_gadget_udc - adds a new gadget to the udc class driver list
- * @parent: the parent device to this udc. Usually the controller
- * driver's device.
- * @gadget: the gadget to be added to the list
- *
- * Returns zero on success, negative errno otherwise.
- */
-int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
-{
-       return usb_add_gadget_udc_release(parent, gadget, NULL);
-}
-EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
-
-static void usb_gadget_remove_driver(struct usb_udc *udc)
-{
-       dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
-                       udc->gadget->name);
-
-       kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
-
-       usb_gadget_disconnect(udc->gadget);
-       udc->driver->disconnect(udc->gadget);
-       udc->driver->unbind(udc->gadget);
-       usb_gadget_udc_stop(udc->gadget, NULL);
-
-       udc->driver = NULL;
-       udc->dev.driver = NULL;
-       udc->gadget->dev.driver = NULL;
-}
-
-/**
- * usb_del_gadget_udc - deletes @udc from udc_list
- * @gadget: the gadget to be removed.
- *
- * This, will call usb_gadget_unregister_driver() if
- * the @udc is still busy.
- */
-void usb_del_gadget_udc(struct usb_gadget *gadget)
-{
-       struct usb_udc          *udc = NULL;
-
-       mutex_lock(&udc_lock);
-       list_for_each_entry(udc, &udc_list, list)
-               if (udc->gadget == gadget)
-                       goto found;
-
-       dev_err(gadget->dev.parent, "gadget not registered.\n");
-       mutex_unlock(&udc_lock);
-
-       return;
-
-found:
-       dev_vdbg(gadget->dev.parent, "unregistering gadget\n");
-
-       list_del(&udc->list);
-       mutex_unlock(&udc_lock);
-
-       if (udc->driver)
-               usb_gadget_remove_driver(udc);
-
-       kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
-       flush_work(&gadget->work);
-       device_unregister(&udc->dev);
-       device_unregister(&gadget->dev);
-}
-EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
-
-/* ------------------------------------------------------------------------- */
-
-static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
-{
-       int ret;
-
-       dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
-                       driver->function);
-
-       udc->driver = driver;
-       udc->dev.driver = &driver->driver;
-       udc->gadget->dev.driver = &driver->driver;
-
-       ret = driver->bind(udc->gadget, driver);
-       if (ret)
-               goto err1;
-       ret = usb_gadget_udc_start(udc->gadget, driver);
-       if (ret) {
-               driver->unbind(udc->gadget);
-               goto err1;
-       }
-       usb_gadget_connect(udc->gadget);
-
-       kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
-       return 0;
-err1:
-       if (ret != -EISNAM)
-               dev_err(&udc->dev, "failed to start %s: %d\n",
-                       udc->driver->function, ret);
-       udc->driver = NULL;
-       udc->dev.driver = NULL;
-       udc->gadget->dev.driver = NULL;
-       return ret;
-}
-
-int udc_attach_driver(const char *name, struct usb_gadget_driver *driver)
-{
-       struct usb_udc *udc = NULL;
-       int ret = -ENODEV;
-
-       mutex_lock(&udc_lock);
-       list_for_each_entry(udc, &udc_list, list) {
-               ret = strcmp(name, dev_name(&udc->dev));
-               if (!ret)
-                       break;
-       }
-       if (ret) {
-               ret = -ENODEV;
-               goto out;
-       }
-       if (udc->driver) {
-               ret = -EBUSY;
-               goto out;
-       }
-       ret = udc_bind_to_driver(udc, driver);
-out:
-       mutex_unlock(&udc_lock);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(udc_attach_driver);
-
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
-{
-       struct usb_udc          *udc = NULL;
-       int                     ret;
-
-       if (!driver || !driver->bind || !driver->setup)
-               return -EINVAL;
-
-       mutex_lock(&udc_lock);
-       list_for_each_entry(udc, &udc_list, list) {
-               /* For now we take the first one */
-               if (!udc->driver)
-                       goto found;
-       }
-
-       pr_debug("couldn't find an available UDC\n");
-       mutex_unlock(&udc_lock);
-       return -ENODEV;
-found:
-       ret = udc_bind_to_driver(udc, driver);
-       mutex_unlock(&udc_lock);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(usb_gadget_probe_driver);
-
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
-{
-       struct usb_udc          *udc = NULL;
-       int                     ret = -ENODEV;
-
-       if (!driver || !driver->unbind)
-               return -EINVAL;
-
-       mutex_lock(&udc_lock);
-       list_for_each_entry(udc, &udc_list, list)
-               if (udc->driver == driver) {
-                       usb_gadget_remove_driver(udc);
-                       usb_gadget_set_state(udc->gadget,
-                                       USB_STATE_NOTATTACHED);
-                       ret = 0;
-                       break;
-               }
-
-       mutex_unlock(&udc_lock);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver);
-
-/* ------------------------------------------------------------------------- */
-
-static ssize_t usb_udc_srp_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t n)
-{
-       struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
-
-       if (sysfs_streq(buf, "1"))
-               usb_gadget_wakeup(udc->gadget);
-
-       return n;
-}
-static DEVICE_ATTR(srp, S_IWUSR, NULL, usb_udc_srp_store);
-
-static ssize_t usb_udc_softconn_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t n)
-{
-       struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
-
-       if (sysfs_streq(buf, "connect")) {
-               usb_gadget_udc_start(udc->gadget, udc->driver);
-               usb_gadget_connect(udc->gadget);
-       } else if (sysfs_streq(buf, "disconnect")) {
-               usb_gadget_disconnect(udc->gadget);
-               usb_gadget_udc_stop(udc->gadget, udc->driver);
-       } else {
-               dev_err(dev, "unsupported command '%s'\n", buf);
-               return -EINVAL;
-       }
-
-       return n;
-}
-static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
-
-static ssize_t state_show(struct device *dev, struct device_attribute *attr,
-                         char *buf)
-{
-       struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
-       struct usb_gadget       *gadget = udc->gadget;
-
-       return sprintf(buf, "%s\n", usb_state_string(gadget->state));
-}
-static DEVICE_ATTR_RO(state);
-
-#define USB_UDC_SPEED_ATTR(name, param)                                        \
-ssize_t name##_show(struct device *dev,                                        \
-               struct device_attribute *attr, char *buf)               \
-{                                                                      \
-       struct usb_udc *udc = container_of(dev, struct usb_udc, dev);   \
-       return snprintf(buf, PAGE_SIZE, "%s\n",                         \
-                       usb_speed_string(udc->gadget->param));          \
-}                                                                      \
-static DEVICE_ATTR_RO(name)
-
-static USB_UDC_SPEED_ATTR(current_speed, speed);
-static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
-
-#define USB_UDC_ATTR(name)                                     \
-ssize_t name##_show(struct device *dev,                                \
-               struct device_attribute *attr, char *buf)       \
-{                                                              \
-       struct usb_udc          *udc = container_of(dev, struct usb_udc, dev); \
-       struct usb_gadget       *gadget = udc->gadget;          \
-                                                               \
-       return snprintf(buf, PAGE_SIZE, "%d\n", gadget->name);  \
-}                                                              \
-static DEVICE_ATTR_RO(name)
-
-static USB_UDC_ATTR(is_otg);
-static USB_UDC_ATTR(is_a_peripheral);
-static USB_UDC_ATTR(b_hnp_enable);
-static USB_UDC_ATTR(a_hnp_support);
-static USB_UDC_ATTR(a_alt_hnp_support);
-
-static struct attribute *usb_udc_attrs[] = {
-       &dev_attr_srp.attr,
-       &dev_attr_soft_connect.attr,
-       &dev_attr_state.attr,
-       &dev_attr_current_speed.attr,
-       &dev_attr_maximum_speed.attr,
-
-       &dev_attr_is_otg.attr,
-       &dev_attr_is_a_peripheral.attr,
-       &dev_attr_b_hnp_enable.attr,
-       &dev_attr_a_hnp_support.attr,
-       &dev_attr_a_alt_hnp_support.attr,
-       NULL,
-};
-
-static const struct attribute_group usb_udc_attr_group = {
-       .attrs = usb_udc_attrs,
-};
-
-static const struct attribute_group *usb_udc_attr_groups[] = {
-       &usb_udc_attr_group,
-       NULL,
-};
-
-static int usb_udc_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-       struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
-       int                     ret;
-
-       ret = add_uevent_var(env, "USB_UDC_NAME=%s", udc->gadget->name);
-       if (ret) {
-               dev_err(dev, "failed to add uevent USB_UDC_NAME\n");
-               return ret;
-       }
-
-       if (udc->driver) {
-               ret = add_uevent_var(env, "USB_UDC_DRIVER=%s",
-                               udc->driver->function);
-               if (ret) {
-                       dev_err(dev, "failed to add uevent USB_UDC_DRIVER\n");
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-static int __init usb_udc_init(void)
-{
-       udc_class = class_create(THIS_MODULE, "udc");
-       if (IS_ERR(udc_class)) {
-               pr_err("failed to create udc class --> %ld\n",
-                               PTR_ERR(udc_class));
-               return PTR_ERR(udc_class);
-       }
-
-       udc_class->dev_uevent = usb_udc_uevent;
-       return 0;
-}
-subsys_initcall(usb_udc_init);
-
-static void __exit usb_udc_exit(void)
-{
-       class_destroy(udc_class);
-}
-module_exit(usb_udc_exit);
-
-MODULE_DESCRIPTION("UDC Framework");
-MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
new file mode 100644 (file)
index 0000000..5151f94
--- /dev/null
@@ -0,0 +1,385 @@
+#
+# USB Gadget support on a system involves
+#    (a) a peripheral controller, and
+#    (b) the gadget driver using it.
+#
+# NOTE:  Gadget support ** DOES NOT ** depend on host-side CONFIG_USB !!
+#
+#  - Host systems (like PCs) need CONFIG_USB (with "A" jacks).
+#  - Peripherals (like PDAs) need CONFIG_USB_GADGET (with "B" jacks).
+#  - Some systems have both kinds of controllers.
+#
+# With help from a special transceiver and a "Mini-AB" jack, systems with
+# both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
+#
+
+#
+# USB Peripheral Controller Support
+#
+# The order here is alphabetical, except that integrated controllers go
+# before discrete ones so they will be the initial/default value:
+#   - integrated/SOC controllers first
+#   - licensed IP used in both SOC and discrete versions
+#   - discrete ones (including all PCI-only controllers)
+#   - debug/dummy gadget+hcd is last.
+#
+menu "USB Peripheral Controller"
+
+#
+# Integrated controllers
+#
+
+config USB_AT91
+       tristate "Atmel AT91 USB Device Port"
+       depends on ARCH_AT91
+       help
+          Many Atmel AT91 processors (such as the AT91RM2000) have a
+          full speed USB Device Port with support for five configurable
+          endpoints (plus endpoint zero).
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "at91_udc" and force all
+          gadget drivers to also be dynamically linked.
+
+config USB_LPC32XX
+       tristate "LPC32XX USB Peripheral Controller"
+       depends on ARCH_LPC32XX && I2C
+       select USB_ISP1301
+       help
+          This option selects the USB device controller in the LPC32xx SoC.
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "lpc32xx_udc" and force all
+          gadget drivers to also be dynamically linked.
+
+config USB_ATMEL_USBA
+       tristate "Atmel USBA"
+       depends on AVR32 || ARCH_AT91
+       help
+         USBA is the integrated high-speed USB Device controller on
+         the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
+
+config USB_BCM63XX_UDC
+       tristate "Broadcom BCM63xx Peripheral Controller"
+       depends on BCM63XX
+       help
+          Many Broadcom BCM63xx chipsets (such as the BCM6328) have a
+          high speed USB Device Port with support for four fixed endpoints
+          (plus endpoint zero).
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "bcm63xx_udc".
+
+config USB_FSL_USB2
+       tristate "Freescale Highspeed USB DR Peripheral Controller"
+       depends on FSL_SOC || ARCH_MXC
+       select USB_FSL_MPH_DR_OF if OF
+       help
+          Some of Freescale PowerPC and i.MX processors have a High Speed
+          Dual-Role(DR) USB controller, which supports device mode.
+
+          The number of programmable endpoints is different through
+          SOC revisions.
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "fsl_usb2_udc" and force
+          all gadget drivers to also be dynamically linked.
+
+config USB_FUSB300
+       tristate "Faraday FUSB300 USB Peripheral Controller"
+       depends on !PHYS_ADDR_T_64BIT && HAS_DMA
+       help
+          Faraday usb device controller FUSB300 driver
+
+config USB_FOTG210_UDC
+       depends on HAS_DMA
+       tristate "Faraday FOTG210 USB Peripheral Controller"
+       help
+          Faraday USB2.0 OTG controller which can be configured as
+          high speed or full speed USB device. This driver supppors
+          Bulk Transfer so far.
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "fotg210_udc".
+
+config USB_GR_UDC
+       tristate "Aeroflex Gaisler GRUSBDC USB Peripheral Controller Driver"
+       depends on HAS_DMA
+       help
+          Select this to support Aeroflex Gaisler GRUSBDC cores from the GRLIB
+         VHDL IP core library.
+
+config USB_OMAP
+       tristate "OMAP USB Device Controller"
+       depends on ARCH_OMAP1
+       depends on ISP1301_OMAP || !(MACH_OMAP_H2 || MACH_OMAP_H3)
+       help
+          Many Texas Instruments OMAP processors have flexible full
+          speed USB device controllers, with support for up to 30
+          endpoints (plus endpoint zero).  This driver supports the
+          controller in the OMAP 1611, and should work with controllers
+          in other OMAP processors too, given minor tweaks.
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "omap_udc" and force all
+          gadget drivers to also be dynamically linked.
+
+config USB_PXA25X
+       tristate "PXA 25x or IXP 4xx"
+       depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
+       help
+          Intel's PXA 25x series XScale ARM-5TE processors include
+          an integrated full speed USB 1.1 device controller.  The
+          controller in the IXP 4xx series is register-compatible.
+
+          It has fifteen fixed-function endpoints, as well as endpoint
+          zero (for control transfers).
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "pxa25x_udc" and force all
+          gadget drivers to also be dynamically linked.
+
+# if there's only one gadget driver, using only two bulk endpoints,
+# don't waste memory for the other endpoints
+config USB_PXA25X_SMALL
+       depends on USB_PXA25X
+       bool
+       default n if USB_ETH_RNDIS
+       default y if USB_ZERO
+       default y if USB_ETH
+       default y if USB_G_SERIAL
+
+config USB_R8A66597
+       tristate "Renesas R8A66597 USB Peripheral Controller"
+       depends on HAS_DMA
+       help
+          R8A66597 is a discrete USB host and peripheral controller chip that
+          supports both full and high speed USB 2.0 data transfers.
+          It has nine configurable endpoints, and endpoint zero.
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "r8a66597_udc" and force all
+          gadget drivers to also be dynamically linked.
+
+config USB_RENESAS_USBHS_UDC
+       tristate 'Renesas USBHS controller'
+       depends on USB_RENESAS_USBHS
+       help
+          Renesas USBHS is a discrete USB host and peripheral controller chip
+          that supports both full and high speed USB 2.0 data transfers.
+          It has nine or more configurable endpoints, and endpoint zero.
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "renesas_usbhs" and force all
+          gadget drivers to also be dynamically linked.
+
+config USB_PXA27X
+       tristate "PXA 27x"
+       help
+          Intel's PXA 27x series XScale ARM v5TE processors include
+          an integrated full speed USB 1.1 device controller.
+
+          It has up to 23 endpoints, as well as endpoint zero (for
+          control transfers).
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "pxa27x_udc" and force all
+          gadget drivers to also be dynamically linked.
+
+config USB_S3C2410
+       tristate "S3C2410 USB Device Controller"
+       depends on ARCH_S3C24XX
+       help
+         Samsung's S3C2410 is an ARM-4 processor with an integrated
+         full speed USB 1.1 device controller.  It has 4 configurable
+         endpoints, as well as endpoint zero (for control transfers).
+
+         This driver has been tested on the S3C2410, S3C2412, and
+         S3C2440 processors.
+
+config USB_S3C2410_DEBUG
+       boolean "S3C2410 udc debug messages"
+       depends on USB_S3C2410
+
+config USB_S3C_HSUDC
+       tristate "S3C2416, S3C2443 and S3C2450 USB Device Controller"
+       depends on ARCH_S3C24XX
+       help
+         Samsung's S3C2416, S3C2443 and S3C2450 is an ARM9 based SoC
+         integrated with dual speed USB 2.0 device controller. It has
+         8 endpoints, as well as endpoint zero.
+
+         This driver has been tested on S3C2416 and S3C2450 processors.
+
+config USB_MV_UDC
+       tristate "Marvell USB2.0 Device Controller"
+       depends on HAS_DMA
+       help
+         Marvell Socs (including PXA and MMP series) include a high speed
+         USB2.0 OTG controller, which can be configured as high speed or
+         full speed USB peripheral.
+
+config USB_MV_U3D
+       depends on HAS_DMA
+       tristate "MARVELL PXA2128 USB 3.0 controller"
+       help
+         MARVELL PXA2128 Processor series include a super speed USB3.0 device
+         controller, which support super speed USB peripheral.
+
+#
+# Controllers available in both integrated and discrete versions
+#
+
+config USB_M66592
+       tristate "Renesas M66592 USB Peripheral Controller"
+       help
+          M66592 is a discrete USB peripheral controller chip that
+          supports both full and high speed USB 2.0 data transfers.
+          It has seven configurable endpoints, and endpoint zero.
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "m66592_udc" and force all
+          gadget drivers to also be dynamically linked.
+
+#
+# Controllers available only in discrete form (and all PCI controllers)
+#
+
+config USB_AMD5536UDC
+       tristate "AMD5536 UDC"
+       depends on PCI
+       help
+          The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
+          It is a USB Highspeed DMA capable USB device controller. Beside ep0
+          it provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
+          The UDC port supports OTG operation, and may be used as a host port
+          if it's not being used to implement peripheral or OTG roles.
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "amd5536udc" and force all
+          gadget drivers to also be dynamically linked.
+
+config USB_FSL_QE
+       tristate "Freescale QE/CPM USB Device Controller"
+       depends on FSL_SOC && (QUICC_ENGINE || CPM)
+       help
+          Some of Freescale PowerPC processors have a Full Speed
+          QE/CPM2 USB controller, which support device mode with 4
+          programmable endpoints. This driver supports the
+          controller in the MPC8360 and MPC8272, and should work with
+          controllers having QE or CPM2, given minor tweaks.
+
+          Set CONFIG_USB_GADGET to "m" to build this driver as a
+          dynamically linked module called "fsl_qe_udc".
+
+config USB_NET2272
+       tristate "PLX NET2272"
+       help
+         PLX NET2272 is a USB peripheral controller which supports
+         both full and high speed USB 2.0 data transfers.
+
+         It has three configurable endpoints, as well as endpoint zero
+         (for control transfer).
+         Say "y" to link the driver statically, or "m" to build a
+         dynamically linked module called "net2272" and force all
+         gadget drivers to also be dynamically linked.
+
+config USB_NET2272_DMA
+       boolean "Support external DMA controller"
+       depends on USB_NET2272 && HAS_DMA
+       help
+         The NET2272 part can optionally support an external DMA
+         controller, but your board has to have support in the
+         driver itself.
+
+         If unsure, say "N" here.  The driver works fine in PIO mode.
+
+config USB_NET2280
+       tristate "NetChip 228x / PLX USB338x"
+       depends on PCI
+       help
+          NetChip 2280 / 2282 is a PCI based USB peripheral controller which
+          supports both full and high speed USB 2.0 data transfers.
+
+          It has six configurable endpoints, as well as endpoint zero
+          (for control transfers) and several endpoints with dedicated
+          functions.
+
+          PLX 3380 / 3382 is a PCIe based USB peripheral controller which
+          supports full, high speed USB 2.0 and super speed USB 3.0
+          data transfers.
+
+          It has eight configurable endpoints, as well as endpoint zero
+          (for control transfers) and several endpoints with dedicated
+          functions.
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "net2280" and force all
+          gadget drivers to also be dynamically linked.
+
+config USB_GOKU
+       tristate "Toshiba TC86C001 'Goku-S'"
+       depends on PCI
+       help
+          The Toshiba TC86C001 is a PCI device which includes controllers
+          for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI).
+
+          The device controller has three configurable (bulk or interrupt)
+          endpoints, plus endpoint zero (for control transfers).
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "goku_udc" and to force all
+          gadget drivers to also be dynamically linked.
+
+config USB_EG20T
+       tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
+       depends on PCI
+       help
+         This is a USB device driver for EG20T PCH.
+         EG20T PCH is the platform controller hub that is used in Intel's
+         general embedded platform. EG20T PCH has USB device interface.
+         Using this interface, it is able to access system devices connected
+         to USB device.
+         This driver enables USB device function.
+         USB device is a USB peripheral controller which
+         supports both full and high speed USB 2.0 data transfers.
+         This driver supports both control transfer and bulk transfer modes.
+         This driver dose not support interrupt transfer or isochronous
+         transfer modes.
+
+         This driver also can be used for LAPIS Semiconductor's ML7213 which is
+         for IVI(In-Vehicle Infotainment) use.
+         ML7831 is for general purpose use.
+         ML7213/ML7831 is companion chip for Intel Atom E6xx series.
+         ML7213/ML7831 is completely compatible for Intel EG20T PCH.
+
+#
+# LAST -- dummy/emulated controller
+#
+
+config USB_DUMMY_HCD
+       tristate "Dummy HCD (DEVELOPMENT)"
+       depends on USB=y || (USB=m && USB_GADGET=m)
+       help
+         This host controller driver emulates USB, looping all data transfer
+         requests back to a USB "gadget driver" in the same host.  The host
+         side is the master; the gadget side is the slave.  Gadget drivers
+         can be high, full, or low speed; and they have access to endpoints
+         like those from NET2280, PXA2xx, or SA1100 hardware.
+
+         This may help in some stages of creating a driver to embed in a
+         Linux device, since it lets you debug several parts of the gadget
+         driver without its hardware or drivers being involved.
+
+         Since such a gadget side driver needs to interoperate with a host
+         side Linux-USB device driver, this may help to debug both sides
+         of a USB protocol stack.
+
+         Say "y" to link the driver statically, or "m" to build a
+         dynamically linked module called "dummy_hcd" and force all
+         gadget drivers to also be dynamically linked.
+
+# NOTE:  Please keep dummy_hcd LAST so that "real hardware" appears
+# first and will be selected by default.
+
+endmenu
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
new file mode 100644 (file)
index 0000000..4096122
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# USB peripheral controller drivers
+#
+obj-$(CONFIG_USB_GADGET)       += udc-core.o
+obj-$(CONFIG_USB_DUMMY_HCD)    += dummy_hcd.o
+obj-$(CONFIG_USB_NET2272)      += net2272.o
+obj-$(CONFIG_USB_NET2280)      += net2280.o
+obj-$(CONFIG_USB_AMD5536UDC)   += amd5536udc.o
+obj-$(CONFIG_USB_PXA25X)       += pxa25x_udc.o
+obj-$(CONFIG_USB_PXA27X)       += pxa27x_udc.o
+obj-$(CONFIG_USB_GOKU)         += goku_udc.o
+obj-$(CONFIG_USB_OMAP)         += omap_udc.o
+obj-$(CONFIG_USB_S3C2410)      += s3c2410_udc.o
+obj-$(CONFIG_USB_AT91)         += at91_udc.o
+obj-$(CONFIG_USB_ATMEL_USBA)   += atmel_usba_udc.o
+obj-$(CONFIG_USB_BCM63XX_UDC)  += bcm63xx_udc.o
+obj-$(CONFIG_USB_FSL_USB2)     += fsl_usb2_udc.o
+fsl_usb2_udc-y                 := fsl_udc_core.o
+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_S3C_HSUDC)    += s3c-hsudc.o
+obj-$(CONFIG_USB_LPC32XX)      += lpc32xx_udc.o
+obj-$(CONFIG_USB_EG20T)                += pch_udc.o
+obj-$(CONFIG_USB_MV_UDC)       += mv_udc.o
+mv_udc-y                       := mv_udc_core.o
+obj-$(CONFIG_USB_FUSB300)      += fusb300_udc.o
+obj-$(CONFIG_USB_FOTG210_UDC)  += fotg210-udc.o
+obj-$(CONFIG_USB_MV_U3D)       += mv_u3d_core.o
+obj-$(CONFIG_USB_GR_UDC)       += gr_udc.o
diff --git a/drivers/usb/gadget/udc/amd5536udc.c b/drivers/usb/gadget/udc/amd5536udc.c
new file mode 100644 (file)
index 0000000..41b062e
--- /dev/null
@@ -0,0 +1,3366 @@
+/*
+ * amd5536.c -- AMD 5536 UDC high/full speed USB device controller
+ *
+ * Copyright (C) 2005-2007 AMD (http://www.amd.com)
+ * Author: Thomas Dahlmann
+ *
+ * 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.
+ */
+
+/*
+ * The AMD5536 UDC is part of the x86 southbridge AMD Geode CS5536.
+ * It is a USB Highspeed DMA capable USB device controller. Beside ep0 it
+ * provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
+ *
+ * Make sure that UDC is assigned to port 4 by BIOS settings (port can also
+ * be used as host port) and UOC bits PAD_EN and APU are set (should be done
+ * by BIOS init).
+ *
+ * UDC DMA requires 32-bit aligned buffers so DMA with gadget ether does not
+ * work without updating NET_IP_ALIGN. Or PIO mode (module param "use_dma=0")
+ * can be used with gadget ether.
+ */
+
+/* debug control */
+/* #define UDC_VERBOSE */
+
+/* Driver strings */
+#define UDC_MOD_DESCRIPTION            "AMD 5536 UDC - USB Device Controller"
+#define UDC_DRIVER_VERSION_STRING      "01.00.0206"
+
+/* system */
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/dmapool.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/prefetch.h>
+
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+
+/* gadget stack */
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+/* udc specific */
+#include "amd5536udc.h"
+
+
+static void udc_tasklet_disconnect(unsigned long);
+static void empty_req_queue(struct udc_ep *);
+static int udc_probe(struct udc *dev);
+static void udc_basic_init(struct udc *dev);
+static void udc_setup_endpoints(struct udc *dev);
+static void udc_soft_reset(struct udc *dev);
+static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep);
+static void udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq);
+static int udc_free_dma_chain(struct udc *dev, struct udc_request *req);
+static int udc_create_dma_chain(struct udc_ep *ep, struct udc_request *req,
+                               unsigned long buf_len, gfp_t gfp_flags);
+static int udc_remote_wakeup(struct udc *dev);
+static int udc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id);
+static void udc_pci_remove(struct pci_dev *pdev);
+
+/* description */
+static const char mod_desc[] = UDC_MOD_DESCRIPTION;
+static const char name[] = "amd5536udc";
+
+/* structure to hold endpoint function pointers */
+static const struct usb_ep_ops udc_ep_ops;
+
+/* received setup data */
+static union udc_setup_data setup_data;
+
+/* pointer to device object */
+static struct udc *udc;
+
+/* irq spin lock for soft reset */
+static DEFINE_SPINLOCK(udc_irq_spinlock);
+/* stall spin lock */
+static DEFINE_SPINLOCK(udc_stall_spinlock);
+
+/*
+* slave mode: pending bytes in rx fifo after nyet,
+* used if EPIN irq came but no req was available
+*/
+static unsigned int udc_rxfifo_pending;
+
+/* count soft resets after suspend to avoid loop */
+static int soft_reset_occured;
+static int soft_reset_after_usbreset_occured;
+
+/* timer */
+static struct timer_list udc_timer;
+static int stop_timer;
+
+/* set_rde -- Is used to control enabling of RX DMA. Problem is
+ * that UDC has only one bit (RDE) to enable/disable RX DMA for
+ * all OUT endpoints. So we have to handle race conditions like
+ * when OUT data reaches the fifo but no request was queued yet.
+ * This cannot be solved by letting the RX DMA disabled until a
+ * request gets queued because there may be other OUT packets
+ * in the FIFO (important for not blocking control traffic).
+ * The value of set_rde controls the correspondig timer.
+ *
+ * set_rde -1 == not used, means it is alloed to be set to 0 or 1
+ * set_rde  0 == do not touch RDE, do no start the RDE timer
+ * set_rde  1 == timer function will look whether FIFO has data
+ * set_rde  2 == set by timer function to enable RX DMA on next call
+ */
+static int set_rde = -1;
+
+static DECLARE_COMPLETION(on_exit);
+static struct timer_list udc_pollstall_timer;
+static int stop_pollstall_timer;
+static DECLARE_COMPLETION(on_pollstall_exit);
+
+/* tasklet for usb disconnect */
+static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect,
+               (unsigned long) &udc);
+
+
+/* endpoint names used for print */
+static const char ep0_string[] = "ep0in";
+static const char *const ep_string[] = {
+       ep0_string,
+       "ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk",
+       "ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk",
+       "ep11in-bulk", "ep12in-bulk", "ep13in-bulk", "ep14in-bulk",
+       "ep15in-bulk", "ep0out", "ep1out-bulk", "ep2out-bulk", "ep3out-bulk",
+       "ep4out-bulk", "ep5out-bulk", "ep6out-bulk", "ep7out-bulk",
+       "ep8out-bulk", "ep9out-bulk", "ep10out-bulk", "ep11out-bulk",
+       "ep12out-bulk", "ep13out-bulk", "ep14out-bulk", "ep15out-bulk"
+};
+
+/* DMA usage flag */
+static bool use_dma = 1;
+/* packet per buffer dma */
+static bool use_dma_ppb = 1;
+/* with per descr. update */
+static bool use_dma_ppb_du;
+/* buffer fill mode */
+static int use_dma_bufferfill_mode;
+/* full speed only mode */
+static bool use_fullspeed;
+/* tx buffer size for high speed */
+static unsigned long hs_tx_buf = UDC_EPIN_BUFF_SIZE;
+
+/* module parameters */
+module_param(use_dma, bool, S_IRUGO);
+MODULE_PARM_DESC(use_dma, "true for DMA");
+module_param(use_dma_ppb, bool, S_IRUGO);
+MODULE_PARM_DESC(use_dma_ppb, "true for DMA in packet per buffer mode");
+module_param(use_dma_ppb_du, bool, S_IRUGO);
+MODULE_PARM_DESC(use_dma_ppb_du,
+       "true for DMA in packet per buffer mode with descriptor update");
+module_param(use_fullspeed, bool, S_IRUGO);
+MODULE_PARM_DESC(use_fullspeed, "true for fullspeed only");
+
+/*---------------------------------------------------------------------------*/
+/* Prints UDC device registers and endpoint irq registers */
+static void print_regs(struct udc *dev)
+{
+       DBG(dev, "------- Device registers -------\n");
+       DBG(dev, "dev config     = %08x\n", readl(&dev->regs->cfg));
+       DBG(dev, "dev control    = %08x\n", readl(&dev->regs->ctl));
+       DBG(dev, "dev status     = %08x\n", readl(&dev->regs->sts));
+       DBG(dev, "\n");
+       DBG(dev, "dev int's      = %08x\n", readl(&dev->regs->irqsts));
+       DBG(dev, "dev intmask    = %08x\n", readl(&dev->regs->irqmsk));
+       DBG(dev, "\n");
+       DBG(dev, "dev ep int's   = %08x\n", readl(&dev->regs->ep_irqsts));
+       DBG(dev, "dev ep intmask = %08x\n", readl(&dev->regs->ep_irqmsk));
+       DBG(dev, "\n");
+       DBG(dev, "USE DMA        = %d\n", use_dma);
+       if (use_dma && use_dma_ppb && !use_dma_ppb_du) {
+               DBG(dev, "DMA mode       = PPBNDU (packet per buffer "
+                       "WITHOUT desc. update)\n");
+               dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBNDU");
+       } else if (use_dma && use_dma_ppb && use_dma_ppb_du) {
+               DBG(dev, "DMA mode       = PPBDU (packet per buffer "
+                       "WITH desc. update)\n");
+               dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBDU");
+       }
+       if (use_dma && use_dma_bufferfill_mode) {
+               DBG(dev, "DMA mode       = BF (buffer fill mode)\n");
+               dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "BF");
+       }
+       if (!use_dma)
+               dev_info(&dev->pdev->dev, "FIFO mode\n");
+       DBG(dev, "-------------------------------------------------------\n");
+}
+
+/* Masks unused interrupts */
+static int udc_mask_unused_interrupts(struct udc *dev)
+{
+       u32 tmp;
+
+       /* mask all dev interrupts */
+       tmp =   AMD_BIT(UDC_DEVINT_SVC) |
+               AMD_BIT(UDC_DEVINT_ENUM) |
+               AMD_BIT(UDC_DEVINT_US) |
+               AMD_BIT(UDC_DEVINT_UR) |
+               AMD_BIT(UDC_DEVINT_ES) |
+               AMD_BIT(UDC_DEVINT_SI) |
+               AMD_BIT(UDC_DEVINT_SOF)|
+               AMD_BIT(UDC_DEVINT_SC);
+       writel(tmp, &dev->regs->irqmsk);
+
+       /* mask all ep interrupts */
+       writel(UDC_EPINT_MSK_DISABLE_ALL, &dev->regs->ep_irqmsk);
+
+       return 0;
+}
+
+/* Enables endpoint 0 interrupts */
+static int udc_enable_ep0_interrupts(struct udc *dev)
+{
+       u32 tmp;
+
+       DBG(dev, "udc_enable_ep0_interrupts()\n");
+
+       /* read irq mask */
+       tmp = readl(&dev->regs->ep_irqmsk);
+       /* enable ep0 irq's */
+       tmp &= AMD_UNMASK_BIT(UDC_EPINT_IN_EP0)
+               & AMD_UNMASK_BIT(UDC_EPINT_OUT_EP0);
+       writel(tmp, &dev->regs->ep_irqmsk);
+
+       return 0;
+}
+
+/* Enables device interrupts for SET_INTF and SET_CONFIG */
+static int udc_enable_dev_setup_interrupts(struct udc *dev)
+{
+       u32 tmp;
+
+       DBG(dev, "enable device interrupts for setup data\n");
+
+       /* read irq mask */
+       tmp = readl(&dev->regs->irqmsk);
+
+       /* enable SET_INTERFACE, SET_CONFIG and other needed irq's */
+       tmp &= AMD_UNMASK_BIT(UDC_DEVINT_SI)
+               & AMD_UNMASK_BIT(UDC_DEVINT_SC)
+               & AMD_UNMASK_BIT(UDC_DEVINT_UR)
+               & AMD_UNMASK_BIT(UDC_DEVINT_SVC)
+               & AMD_UNMASK_BIT(UDC_DEVINT_ENUM);
+       writel(tmp, &dev->regs->irqmsk);
+
+       return 0;
+}
+
+/* Calculates fifo start of endpoint based on preceding endpoints */
+static int udc_set_txfifo_addr(struct udc_ep *ep)
+{
+       struct udc      *dev;
+       u32 tmp;
+       int i;
+
+       if (!ep || !(ep->in))
+               return -EINVAL;
+
+       dev = ep->dev;
+       ep->txfifo = dev->txfifo;
+
+       /* traverse ep's */
+       for (i = 0; i < ep->num; i++) {
+               if (dev->ep[i].regs) {
+                       /* read fifo size */
+                       tmp = readl(&dev->ep[i].regs->bufin_framenum);
+                       tmp = AMD_GETBITS(tmp, UDC_EPIN_BUFF_SIZE);
+                       ep->txfifo += tmp;
+               }
+       }
+       return 0;
+}
+
+/* CNAK pending field: bit0 = ep0in, bit16 = ep0out */
+static u32 cnak_pending;
+
+static void UDC_QUEUE_CNAK(struct udc_ep *ep, unsigned num)
+{
+       if (readl(&ep->regs->ctl) & AMD_BIT(UDC_EPCTL_NAK)) {
+               DBG(ep->dev, "NAK could not be cleared for ep%d\n", num);
+               cnak_pending |= 1 << (num);
+               ep->naking = 1;
+       } else
+               cnak_pending = cnak_pending & (~(1 << (num)));
+}
+
+
+/* Enables endpoint, is called by gadget driver */
+static int
+udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc)
+{
+       struct udc_ep           *ep;
+       struct udc              *dev;
+       u32                     tmp;
+       unsigned long           iflags;
+       u8 udc_csr_epix;
+       unsigned                maxpacket;
+
+       if (!usbep
+                       || usbep->name == ep0_string
+                       || !desc
+                       || desc->bDescriptorType != USB_DT_ENDPOINT)
+               return -EINVAL;
+
+       ep = container_of(usbep, struct udc_ep, ep);
+       dev = ep->dev;
+
+       DBG(dev, "udc_ep_enable() ep %d\n", ep->num);
+
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       spin_lock_irqsave(&dev->lock, iflags);
+       ep->ep.desc = desc;
+
+       ep->halted = 0;
+
+       /* set traffic type */
+       tmp = readl(&dev->ep[ep->num].regs->ctl);
+       tmp = AMD_ADDBITS(tmp, desc->bmAttributes, UDC_EPCTL_ET);
+       writel(tmp, &dev->ep[ep->num].regs->ctl);
+
+       /* set max packet size */
+       maxpacket = usb_endpoint_maxp(desc);
+       tmp = readl(&dev->ep[ep->num].regs->bufout_maxpkt);
+       tmp = AMD_ADDBITS(tmp, maxpacket, UDC_EP_MAX_PKT_SIZE);
+       ep->ep.maxpacket = maxpacket;
+       writel(tmp, &dev->ep[ep->num].regs->bufout_maxpkt);
+
+       /* IN ep */
+       if (ep->in) {
+
+               /* ep ix in UDC CSR register space */
+               udc_csr_epix = ep->num;
+
+               /* set buffer size (tx fifo entries) */
+               tmp = readl(&dev->ep[ep->num].regs->bufin_framenum);
+               /* double buffering: fifo size = 2 x max packet size */
+               tmp = AMD_ADDBITS(
+                               tmp,
+                               maxpacket * UDC_EPIN_BUFF_SIZE_MULT
+                                         / UDC_DWORD_BYTES,
+                               UDC_EPIN_BUFF_SIZE);
+               writel(tmp, &dev->ep[ep->num].regs->bufin_framenum);
+
+               /* calc. tx fifo base addr */
+               udc_set_txfifo_addr(ep);
+
+               /* flush fifo */
+               tmp = readl(&ep->regs->ctl);
+               tmp |= AMD_BIT(UDC_EPCTL_F);
+               writel(tmp, &ep->regs->ctl);
+
+       /* OUT ep */
+       } else {
+               /* ep ix in UDC CSR register space */
+               udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS;
+
+               /* set max packet size UDC CSR  */
+               tmp = readl(&dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]);
+               tmp = AMD_ADDBITS(tmp, maxpacket,
+                                       UDC_CSR_NE_MAX_PKT);
+               writel(tmp, &dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]);
+
+               if (use_dma && !ep->in) {
+                       /* alloc and init BNA dummy request */
+                       ep->bna_dummy_req = udc_alloc_bna_dummy(ep);
+                       ep->bna_occurred = 0;
+               }
+
+               if (ep->num != UDC_EP0OUT_IX)
+                       dev->data_ep_enabled = 1;
+       }
+
+       /* set ep values */
+       tmp = readl(&dev->csr->ne[udc_csr_epix]);
+       /* max packet */
+       tmp = AMD_ADDBITS(tmp, maxpacket, UDC_CSR_NE_MAX_PKT);
+       /* ep number */
+       tmp = AMD_ADDBITS(tmp, desc->bEndpointAddress, UDC_CSR_NE_NUM);
+       /* ep direction */
+       tmp = AMD_ADDBITS(tmp, ep->in, UDC_CSR_NE_DIR);
+       /* ep type */
+       tmp = AMD_ADDBITS(tmp, desc->bmAttributes, UDC_CSR_NE_TYPE);
+       /* ep config */
+       tmp = AMD_ADDBITS(tmp, ep->dev->cur_config, UDC_CSR_NE_CFG);
+       /* ep interface */
+       tmp = AMD_ADDBITS(tmp, ep->dev->cur_intf, UDC_CSR_NE_INTF);
+       /* ep alt */
+       tmp = AMD_ADDBITS(tmp, ep->dev->cur_alt, UDC_CSR_NE_ALT);
+       /* write reg */
+       writel(tmp, &dev->csr->ne[udc_csr_epix]);
+
+       /* enable ep irq */
+       tmp = readl(&dev->regs->ep_irqmsk);
+       tmp &= AMD_UNMASK_BIT(ep->num);
+       writel(tmp, &dev->regs->ep_irqmsk);
+
+       /*
+        * clear NAK by writing CNAK
+        * avoid BNA for OUT DMA, don't clear NAK until DMA desc. written
+        */
+       if (!use_dma || ep->in) {
+               tmp = readl(&ep->regs->ctl);
+               tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+               writel(tmp, &ep->regs->ctl);
+               ep->naking = 0;
+               UDC_QUEUE_CNAK(ep, ep->num);
+       }
+       tmp = desc->bEndpointAddress;
+       DBG(dev, "%s enabled\n", usbep->name);
+
+       spin_unlock_irqrestore(&dev->lock, iflags);
+       return 0;
+}
+
+/* Resets endpoint */
+static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep)
+{
+       u32             tmp;
+
+       VDBG(ep->dev, "ep-%d reset\n", ep->num);
+       ep->ep.desc = NULL;
+       ep->ep.ops = &udc_ep_ops;
+       INIT_LIST_HEAD(&ep->queue);
+
+       usb_ep_set_maxpacket_limit(&ep->ep,(u16) ~0);
+       /* set NAK */
+       tmp = readl(&ep->regs->ctl);
+       tmp |= AMD_BIT(UDC_EPCTL_SNAK);
+       writel(tmp, &ep->regs->ctl);
+       ep->naking = 1;
+
+       /* disable interrupt */
+       tmp = readl(&regs->ep_irqmsk);
+       tmp |= AMD_BIT(ep->num);
+       writel(tmp, &regs->ep_irqmsk);
+
+       if (ep->in) {
+               /* unset P and IN bit of potential former DMA */
+               tmp = readl(&ep->regs->ctl);
+               tmp &= AMD_UNMASK_BIT(UDC_EPCTL_P);
+               writel(tmp, &ep->regs->ctl);
+
+               tmp = readl(&ep->regs->sts);
+               tmp |= AMD_BIT(UDC_EPSTS_IN);
+               writel(tmp, &ep->regs->sts);
+
+               /* flush the fifo */
+               tmp = readl(&ep->regs->ctl);
+               tmp |= AMD_BIT(UDC_EPCTL_F);
+               writel(tmp, &ep->regs->ctl);
+
+       }
+       /* reset desc pointer */
+       writel(0, &ep->regs->desptr);
+}
+
+/* Disables endpoint, is called by gadget driver */
+static int udc_ep_disable(struct usb_ep *usbep)
+{
+       struct udc_ep   *ep = NULL;
+       unsigned long   iflags;
+
+       if (!usbep)
+               return -EINVAL;
+
+       ep = container_of(usbep, struct udc_ep, ep);
+       if (usbep->name == ep0_string || !ep->ep.desc)
+               return -EINVAL;
+
+       DBG(ep->dev, "Disable ep-%d\n", ep->num);
+
+       spin_lock_irqsave(&ep->dev->lock, iflags);
+       udc_free_request(&ep->ep, &ep->bna_dummy_req->req);
+       empty_req_queue(ep);
+       ep_init(ep->dev->regs, ep);
+       spin_unlock_irqrestore(&ep->dev->lock, iflags);
+
+       return 0;
+}
+
+/* Allocates request packet, called by gadget driver */
+static struct usb_request *
+udc_alloc_request(struct usb_ep *usbep, gfp_t gfp)
+{
+       struct udc_request      *req;
+       struct udc_data_dma     *dma_desc;
+       struct udc_ep   *ep;
+
+       if (!usbep)
+               return NULL;
+
+       ep = container_of(usbep, struct udc_ep, ep);
+
+       VDBG(ep->dev, "udc_alloc_req(): ep%d\n", ep->num);
+       req = kzalloc(sizeof(struct udc_request), gfp);
+       if (!req)
+               return NULL;
+
+       req->req.dma = DMA_DONT_USE;
+       INIT_LIST_HEAD(&req->queue);
+
+       if (ep->dma) {
+               /* ep0 in requests are allocated from data pool here */
+               dma_desc = pci_pool_alloc(ep->dev->data_requests, gfp,
+                                               &req->td_phys);
+               if (!dma_desc) {
+                       kfree(req);
+                       return NULL;
+               }
+
+               VDBG(ep->dev, "udc_alloc_req: req = %p dma_desc = %p, "
+                               "td_phys = %lx\n",
+                               req, dma_desc,
+                               (unsigned long)req->td_phys);
+               /* prevent from using desc. - set HOST BUSY */
+               dma_desc->status = AMD_ADDBITS(dma_desc->status,
+                                               UDC_DMA_STP_STS_BS_HOST_BUSY,
+                                               UDC_DMA_STP_STS_BS);
+               dma_desc->bufptr = cpu_to_le32(DMA_DONT_USE);
+               req->td_data = dma_desc;
+               req->td_data_last = NULL;
+               req->chain_len = 1;
+       }
+
+       return &req->req;
+}
+
+/* Frees request packet, called by gadget driver */
+static void
+udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq)
+{
+       struct udc_ep   *ep;
+       struct udc_request      *req;
+
+       if (!usbep || !usbreq)
+               return;
+
+       ep = container_of(usbep, struct udc_ep, ep);
+       req = container_of(usbreq, struct udc_request, req);
+       VDBG(ep->dev, "free_req req=%p\n", req);
+       BUG_ON(!list_empty(&req->queue));
+       if (req->td_data) {
+               VDBG(ep->dev, "req->td_data=%p\n", req->td_data);
+
+               /* free dma chain if created */
+               if (req->chain_len > 1)
+                       udc_free_dma_chain(ep->dev, req);
+
+               pci_pool_free(ep->dev->data_requests, req->td_data,
+                                                       req->td_phys);
+       }
+       kfree(req);
+}
+
+/* Init BNA dummy descriptor for HOST BUSY and pointing to itself */
+static void udc_init_bna_dummy(struct udc_request *req)
+{
+       if (req) {
+               /* set last bit */
+               req->td_data->status |= AMD_BIT(UDC_DMA_IN_STS_L);
+               /* set next pointer to itself */
+               req->td_data->next = req->td_phys;
+               /* set HOST BUSY */
+               req->td_data->status
+                       = AMD_ADDBITS(req->td_data->status,
+                                       UDC_DMA_STP_STS_BS_DMA_DONE,
+                                       UDC_DMA_STP_STS_BS);
+#ifdef UDC_VERBOSE
+               pr_debug("bna desc = %p, sts = %08x\n",
+                       req->td_data, req->td_data->status);
+#endif
+       }
+}
+
+/* Allocate BNA dummy descriptor */
+static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep)
+{
+       struct udc_request *req = NULL;
+       struct usb_request *_req = NULL;
+
+       /* alloc the dummy request */
+       _req = udc_alloc_request(&ep->ep, GFP_ATOMIC);
+       if (_req) {
+               req = container_of(_req, struct udc_request, req);
+               ep->bna_dummy_req = req;
+               udc_init_bna_dummy(req);
+       }
+       return req;
+}
+
+/* Write data to TX fifo for IN packets */
+static void
+udc_txfifo_write(struct udc_ep *ep, struct usb_request *req)
+{
+       u8                      *req_buf;
+       u32                     *buf;
+       int                     i, j;
+       unsigned                bytes = 0;
+       unsigned                remaining = 0;
+
+       if (!req || !ep)
+               return;
+
+       req_buf = req->buf + req->actual;
+       prefetch(req_buf);
+       remaining = req->length - req->actual;
+
+       buf = (u32 *) req_buf;
+
+       bytes = ep->ep.maxpacket;
+       if (bytes > remaining)
+               bytes = remaining;
+
+       /* dwords first */
+       for (i = 0; i < bytes / UDC_DWORD_BYTES; i++)
+               writel(*(buf + i), ep->txfifo);
+
+       /* remaining bytes must be written by byte access */
+       for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) {
+               writeb((u8)(*(buf + i) >> (j << UDC_BITS_PER_BYTE_SHIFT)),
+                                                       ep->txfifo);
+       }
+
+       /* dummy write confirm */
+       writel(0, &ep->regs->confirm);
+}
+
+/* Read dwords from RX fifo for OUT transfers */
+static int udc_rxfifo_read_dwords(struct udc *dev, u32 *buf, int dwords)
+{
+       int i;
+
+       VDBG(dev, "udc_read_dwords(): %d dwords\n", dwords);
+
+       for (i = 0; i < dwords; i++)
+               *(buf + i) = readl(dev->rxfifo);
+       return 0;
+}
+
+/* Read bytes from RX fifo for OUT transfers */
+static int udc_rxfifo_read_bytes(struct udc *dev, u8 *buf, int bytes)
+{
+       int i, j;
+       u32 tmp;
+
+       VDBG(dev, "udc_read_bytes(): %d bytes\n", bytes);
+
+       /* dwords first */
+       for (i = 0; i < bytes / UDC_DWORD_BYTES; i++)
+               *((u32 *)(buf + (i<<2))) = readl(dev->rxfifo);
+
+       /* remaining bytes must be read by byte access */
+       if (bytes % UDC_DWORD_BYTES) {
+               tmp = readl(dev->rxfifo);
+               for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) {
+                       *(buf + (i<<2) + j) = (u8)(tmp & UDC_BYTE_MASK);
+                       tmp = tmp >> UDC_BITS_PER_BYTE;
+               }
+       }
+
+       return 0;
+}
+
+/* Read data from RX fifo for OUT transfers */
+static int
+udc_rxfifo_read(struct udc_ep *ep, struct udc_request *req)
+{
+       u8 *buf;
+       unsigned buf_space;
+       unsigned bytes = 0;
+       unsigned finished = 0;
+
+       /* received number bytes */
+       bytes = readl(&ep->regs->sts);
+       bytes = AMD_GETBITS(bytes, UDC_EPSTS_RX_PKT_SIZE);
+
+       buf_space = req->req.length - req->req.actual;
+       buf = req->req.buf + req->req.actual;
+       if (bytes > buf_space) {
+               if ((buf_space % ep->ep.maxpacket) != 0) {
+                       DBG(ep->dev,
+                               "%s: rx %d bytes, rx-buf space = %d bytesn\n",
+                               ep->ep.name, bytes, buf_space);
+                       req->req.status = -EOVERFLOW;
+               }
+               bytes = buf_space;
+       }
+       req->req.actual += bytes;
+
+       /* last packet ? */
+       if (((bytes % ep->ep.maxpacket) != 0) || (!bytes)
+               || ((req->req.actual == req->req.length) && !req->req.zero))
+               finished = 1;
+
+       /* read rx fifo bytes */
+       VDBG(ep->dev, "ep %s: rxfifo read %d bytes\n", ep->ep.name, bytes);
+       udc_rxfifo_read_bytes(ep->dev, buf, bytes);
+
+       return finished;
+}
+
+/* create/re-init a DMA descriptor or a DMA descriptor chain */
+static int prep_dma(struct udc_ep *ep, struct udc_request *req, gfp_t gfp)
+{
+       int     retval = 0;
+       u32     tmp;
+
+       VDBG(ep->dev, "prep_dma\n");
+       VDBG(ep->dev, "prep_dma ep%d req->td_data=%p\n",
+                       ep->num, req->td_data);
+
+       /* set buffer pointer */
+       req->td_data->bufptr = req->req.dma;
+
+       /* set last bit */
+       req->td_data->status |= AMD_BIT(UDC_DMA_IN_STS_L);
+
+       /* build/re-init dma chain if maxpkt scatter mode, not for EP0 */
+       if (use_dma_ppb) {
+
+               retval = udc_create_dma_chain(ep, req, ep->ep.maxpacket, gfp);
+               if (retval != 0) {
+                       if (retval == -ENOMEM)
+                               DBG(ep->dev, "Out of DMA memory\n");
+                       return retval;
+               }
+               if (ep->in) {
+                       if (req->req.length == ep->ep.maxpacket) {
+                               /* write tx bytes */
+                               req->td_data->status =
+                                       AMD_ADDBITS(req->td_data->status,
+                                               ep->ep.maxpacket,
+                                               UDC_DMA_IN_STS_TXBYTES);
+
+                       }
+               }
+
+       }
+
+       if (ep->in) {
+               VDBG(ep->dev, "IN: use_dma_ppb=%d req->req.len=%d "
+                               "maxpacket=%d ep%d\n",
+                               use_dma_ppb, req->req.length,
+                               ep->ep.maxpacket, ep->num);
+               /*
+                * if bytes < max packet then tx bytes must
+                * be written in packet per buffer mode
+                */
+               if (!use_dma_ppb || req->req.length < ep->ep.maxpacket
+                               || ep->num == UDC_EP0OUT_IX
+                               || ep->num == UDC_EP0IN_IX) {
+                       /* write tx bytes */
+                       req->td_data->status =
+                               AMD_ADDBITS(req->td_data->status,
+                                               req->req.length,
+                                               UDC_DMA_IN_STS_TXBYTES);
+                       /* reset frame num */
+                       req->td_data->status =
+                               AMD_ADDBITS(req->td_data->status,
+                                               0,
+                                               UDC_DMA_IN_STS_FRAMENUM);
+               }
+               /* set HOST BUSY */
+               req->td_data->status =
+                       AMD_ADDBITS(req->td_data->status,
+                               UDC_DMA_STP_STS_BS_HOST_BUSY,
+                               UDC_DMA_STP_STS_BS);
+       } else {
+               VDBG(ep->dev, "OUT set host ready\n");
+               /* set HOST READY */
+               req->td_data->status =
+                       AMD_ADDBITS(req->td_data->status,
+                               UDC_DMA_STP_STS_BS_HOST_READY,
+                               UDC_DMA_STP_STS_BS);
+
+
+                       /* clear NAK by writing CNAK */
+                       if (ep->naking) {
+                               tmp = readl(&ep->regs->ctl);
+                               tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+                               writel(tmp, &ep->regs->ctl);
+                               ep->naking = 0;
+                               UDC_QUEUE_CNAK(ep, ep->num);
+                       }
+
+       }
+
+       return retval;
+}
+
+/* Completes request packet ... caller MUST hold lock */
+static void
+complete_req(struct udc_ep *ep, struct udc_request *req, int sts)
+__releases(ep->dev->lock)
+__acquires(ep->dev->lock)
+{
+       struct udc              *dev;
+       unsigned                halted;
+
+       VDBG(ep->dev, "complete_req(): ep%d\n", ep->num);
+
+       dev = ep->dev;
+       /* unmap DMA */
+       if (ep->dma)
+               usb_gadget_unmap_request(&dev->gadget, &req->req, ep->in);
+
+       halted = ep->halted;
+       ep->halted = 1;
+
+       /* set new status if pending */
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = sts;
+
+       /* remove from ep queue */
+       list_del_init(&req->queue);
+
+       VDBG(ep->dev, "req %p => complete %d bytes at %s with sts %d\n",
+               &req->req, req->req.length, ep->ep.name, sts);
+
+       spin_unlock(&dev->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&dev->lock);
+       ep->halted = halted;
+}
+
+/* frees pci pool descriptors of a DMA chain */
+static int udc_free_dma_chain(struct udc *dev, struct udc_request *req)
+{
+
+       int ret_val = 0;
+       struct udc_data_dma     *td;
+       struct udc_data_dma     *td_last = NULL;
+       unsigned int i;
+
+       DBG(dev, "free chain req = %p\n", req);
+
+       /* do not free first desc., will be done by free for request */
+       td_last = req->td_data;
+       td = phys_to_virt(td_last->next);
+
+       for (i = 1; i < req->chain_len; i++) {
+
+               pci_pool_free(dev->data_requests, td,
+                               (dma_addr_t) td_last->next);
+               td_last = td;
+               td = phys_to_virt(td_last->next);
+       }
+
+       return ret_val;
+}
+
+/* Iterates to the end of a DMA chain and returns last descriptor */
+static struct udc_data_dma *udc_get_last_dma_desc(struct udc_request *req)
+{
+       struct udc_data_dma     *td;
+
+       td = req->td_data;
+       while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L)))
+               td = phys_to_virt(td->next);
+
+       return td;
+
+}
+
+/* Iterates to the end of a DMA chain and counts bytes received */
+static u32 udc_get_ppbdu_rxbytes(struct udc_request *req)
+{
+       struct udc_data_dma     *td;
+       u32 count;
+
+       td = req->td_data;
+       /* received number bytes */
+       count = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_RXBYTES);
+
+       while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) {
+               td = phys_to_virt(td->next);
+               /* received number bytes */
+               if (td) {
+                       count += AMD_GETBITS(td->status,
+                               UDC_DMA_OUT_STS_RXBYTES);
+               }
+       }
+
+       return count;
+
+}
+
+/* Creates or re-inits a DMA chain */
+static int udc_create_dma_chain(
+       struct udc_ep *ep,
+       struct udc_request *req,
+       unsigned long buf_len, gfp_t gfp_flags
+)
+{
+       unsigned long bytes = req->req.length;
+       unsigned int i;
+       dma_addr_t dma_addr;
+       struct udc_data_dma     *td = NULL;
+       struct udc_data_dma     *last = NULL;
+       unsigned long txbytes;
+       unsigned create_new_chain = 0;
+       unsigned len;
+
+       VDBG(ep->dev, "udc_create_dma_chain: bytes=%ld buf_len=%ld\n",
+                       bytes, buf_len);
+       dma_addr = DMA_DONT_USE;
+
+       /* unset L bit in first desc for OUT */
+       if (!ep->in)
+               req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
+
+       /* alloc only new desc's if not already available */
+       len = req->req.length / ep->ep.maxpacket;
+       if (req->req.length % ep->ep.maxpacket)
+               len++;
+
+       if (len > req->chain_len) {
+               /* shorter chain already allocated before */
+               if (req->chain_len > 1)
+                       udc_free_dma_chain(ep->dev, req);
+               req->chain_len = len;
+               create_new_chain = 1;
+       }
+
+       td = req->td_data;
+       /* gen. required number of descriptors and buffers */
+       for (i = buf_len; i < bytes; i += buf_len) {
+               /* create or determine next desc. */
+               if (create_new_chain) {
+
+                       td = pci_pool_alloc(ep->dev->data_requests,
+                                       gfp_flags, &dma_addr);
+                       if (!td)
+                               return -ENOMEM;
+
+                       td->status = 0;
+               } else if (i == buf_len) {
+                       /* first td */
+                       td = (struct udc_data_dma *) phys_to_virt(
+                                               req->td_data->next);
+                       td->status = 0;
+               } else {
+                       td = (struct udc_data_dma *) phys_to_virt(last->next);
+                       td->status = 0;
+               }
+
+
+               if (td)
+                       td->bufptr = req->req.dma + i; /* assign buffer */
+               else
+                       break;
+
+               /* short packet ? */
+               if ((bytes - i) >= buf_len) {
+                       txbytes = buf_len;
+               } else {
+                       /* short packet */
+                       txbytes = bytes - i;
+               }
+
+               /* link td and assign tx bytes */
+               if (i == buf_len) {
+                       if (create_new_chain)
+                               req->td_data->next = dma_addr;
+                       /*
+                       else
+                               req->td_data->next = virt_to_phys(td);
+                       */
+                       /* write tx bytes */
+                       if (ep->in) {
+                               /* first desc */
+                               req->td_data->status =
+                                       AMD_ADDBITS(req->td_data->status,
+                                                       ep->ep.maxpacket,
+                                                       UDC_DMA_IN_STS_TXBYTES);
+                               /* second desc */
+                               td->status = AMD_ADDBITS(td->status,
+                                                       txbytes,
+                                                       UDC_DMA_IN_STS_TXBYTES);
+                       }
+               } else {
+                       if (create_new_chain)
+                               last->next = dma_addr;
+                       /*
+                       else
+                               last->next = virt_to_phys(td);
+                       */
+                       if (ep->in) {
+                               /* write tx bytes */
+                               td->status = AMD_ADDBITS(td->status,
+                                                       txbytes,
+                                                       UDC_DMA_IN_STS_TXBYTES);
+                       }
+               }
+               last = td;
+       }
+       /* set last bit */
+       if (td) {
+               td->status |= AMD_BIT(UDC_DMA_IN_STS_L);
+               /* last desc. points to itself */
+               req->td_data_last = td;
+       }
+
+       return 0;
+}
+
+/* Enabling RX DMA */
+static void udc_set_rde(struct udc *dev)
+{
+       u32 tmp;
+
+       VDBG(dev, "udc_set_rde()\n");
+       /* stop RDE timer */
+       if (timer_pending(&udc_timer)) {
+               set_rde = 0;
+               mod_timer(&udc_timer, jiffies - 1);
+       }
+       /* set RDE */
+       tmp = readl(&dev->regs->ctl);
+       tmp |= AMD_BIT(UDC_DEVCTL_RDE);
+       writel(tmp, &dev->regs->ctl);
+}
+
+/* Queues a request packet, called by gadget driver */
+static int
+udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
+{
+       int                     retval = 0;
+       u8                      open_rxfifo = 0;
+       unsigned long           iflags;
+       struct udc_ep           *ep;
+       struct udc_request      *req;
+       struct udc              *dev;
+       u32                     tmp;
+
+       /* check the inputs */
+       req = container_of(usbreq, struct udc_request, req);
+
+       if (!usbep || !usbreq || !usbreq->complete || !usbreq->buf
+                       || !list_empty(&req->queue))
+               return -EINVAL;
+
+       ep = container_of(usbep, struct udc_ep, ep);
+       if (!ep->ep.desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
+               return -EINVAL;
+
+       VDBG(ep->dev, "udc_queue(): ep%d-in=%d\n", ep->num, ep->in);
+       dev = ep->dev;
+
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       /* map dma (usually done before) */
+       if (ep->dma) {
+               VDBG(dev, "DMA map req %p\n", req);
+               retval = usb_gadget_map_request(&udc->gadget, usbreq, ep->in);
+               if (retval)
+                       return retval;
+       }
+
+       VDBG(dev, "%s queue req %p, len %d req->td_data=%p buf %p\n",
+                       usbep->name, usbreq, usbreq->length,
+                       req->td_data, usbreq->buf);
+
+       spin_lock_irqsave(&dev->lock, iflags);
+       usbreq->actual = 0;
+       usbreq->status = -EINPROGRESS;
+       req->dma_done = 0;
+
+       /* on empty queue just do first transfer */
+       if (list_empty(&ep->queue)) {
+               /* zlp */
+               if (usbreq->length == 0) {
+                       /* IN zlp's are handled by hardware */
+                       complete_req(ep, req, 0);
+                       VDBG(dev, "%s: zlp\n", ep->ep.name);
+                       /*
+                        * if set_config or set_intf is waiting for ack by zlp
+                        * then set CSR_DONE
+                        */
+                       if (dev->set_cfg_not_acked) {
+                               tmp = readl(&dev->regs->ctl);
+                               tmp |= AMD_BIT(UDC_DEVCTL_CSR_DONE);
+                               writel(tmp, &dev->regs->ctl);
+                               dev->set_cfg_not_acked = 0;
+                       }
+                       /* setup command is ACK'ed now by zlp */
+                       if (dev->waiting_zlp_ack_ep0in) {
+                               /* clear NAK by writing CNAK in EP0_IN */
+                               tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
+                               tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+                               writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
+                               dev->ep[UDC_EP0IN_IX].naking = 0;
+                               UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX],
+                                                       UDC_EP0IN_IX);
+                               dev->waiting_zlp_ack_ep0in = 0;
+                       }
+                       goto finished;
+               }
+               if (ep->dma) {
+                       retval = prep_dma(ep, req, GFP_ATOMIC);
+                       if (retval != 0)
+                               goto finished;
+                       /* write desc pointer to enable DMA */
+                       if (ep->in) {
+                               /* set HOST READY */
+                               req->td_data->status =
+                                       AMD_ADDBITS(req->td_data->status,
+                                               UDC_DMA_IN_STS_BS_HOST_READY,
+                                               UDC_DMA_IN_STS_BS);
+                       }
+
+                       /* disabled rx dma while descriptor update */
+                       if (!ep->in) {
+                               /* stop RDE timer */
+                               if (timer_pending(&udc_timer)) {
+                                       set_rde = 0;
+                                       mod_timer(&udc_timer, jiffies - 1);
+                               }
+                               /* clear RDE */
+                               tmp = readl(&dev->regs->ctl);
+                               tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_RDE);
+                               writel(tmp, &dev->regs->ctl);
+                               open_rxfifo = 1;
+
+                               /*
+                                * if BNA occurred then let BNA dummy desc.
+                                * point to current desc.
+                                */
+                               if (ep->bna_occurred) {
+                                       VDBG(dev, "copy to BNA dummy desc.\n");
+                                       memcpy(ep->bna_dummy_req->td_data,
+                                               req->td_data,
+                                               sizeof(struct udc_data_dma));
+                               }
+                       }
+                       /* write desc pointer */
+                       writel(req->td_phys, &ep->regs->desptr);
+
+                       /* clear NAK by writing CNAK */
+                       if (ep->naking) {
+                               tmp = readl(&ep->regs->ctl);
+                               tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+                               writel(tmp, &ep->regs->ctl);
+                               ep->naking = 0;
+                               UDC_QUEUE_CNAK(ep, ep->num);
+                       }
+
+                       if (ep->in) {
+                               /* enable ep irq */
+                               tmp = readl(&dev->regs->ep_irqmsk);
+                               tmp &= AMD_UNMASK_BIT(ep->num);
+                               writel(tmp, &dev->regs->ep_irqmsk);
+                       }
+               } else if (ep->in) {
+                               /* enable ep irq */
+                               tmp = readl(&dev->regs->ep_irqmsk);
+                               tmp &= AMD_UNMASK_BIT(ep->num);
+                               writel(tmp, &dev->regs->ep_irqmsk);
+                       }
+
+       } else if (ep->dma) {
+
+               /*
+                * prep_dma not used for OUT ep's, this is not possible
+                * for PPB modes, because of chain creation reasons
+                */
+               if (ep->in) {
+                       retval = prep_dma(ep, req, GFP_ATOMIC);
+                       if (retval != 0)
+                               goto finished;
+               }
+       }
+       VDBG(dev, "list_add\n");
+       /* add request to ep queue */
+       if (req) {
+
+               list_add_tail(&req->queue, &ep->queue);
+
+               /* open rxfifo if out data queued */
+               if (open_rxfifo) {
+                       /* enable DMA */
+                       req->dma_going = 1;
+                       udc_set_rde(dev);
+                       if (ep->num != UDC_EP0OUT_IX)
+                               dev->data_ep_queued = 1;
+               }
+               /* stop OUT naking */
+               if (!ep->in) {
+                       if (!use_dma && udc_rxfifo_pending) {
+                               DBG(dev, "udc_queue(): pending bytes in "
+                                       "rxfifo after nyet\n");
+                               /*
+                                * read pending bytes afer nyet:
+                                * referring to isr
+                                */
+                               if (udc_rxfifo_read(ep, req)) {
+                                       /* finish */
+                                       complete_req(ep, req, 0);
+                               }
+                               udc_rxfifo_pending = 0;
+
+                       }
+               }
+       }
+
+finished:
+       spin_unlock_irqrestore(&dev->lock, iflags);
+       return retval;
+}
+
+/* Empty request queue of an endpoint; caller holds spinlock */
+static void empty_req_queue(struct udc_ep *ep)
+{
+       struct udc_request      *req;
+
+       ep->halted = 1;
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next,
+                       struct udc_request,
+                       queue);
+               complete_req(ep, req, -ESHUTDOWN);
+       }
+}
+
+/* Dequeues a request packet, called by gadget driver */
+static int udc_dequeue(struct usb_ep *usbep, struct usb_request *usbreq)
+{
+       struct udc_ep           *ep;
+       struct udc_request      *req;
+       unsigned                halted;
+       unsigned long           iflags;
+
+       ep = container_of(usbep, struct udc_ep, ep);
+       if (!usbep || !usbreq || (!ep->ep.desc && (ep->num != 0
+                               && ep->num != UDC_EP0OUT_IX)))
+               return -EINVAL;
+
+       req = container_of(usbreq, struct udc_request, req);
+
+       spin_lock_irqsave(&ep->dev->lock, iflags);
+       halted = ep->halted;
+       ep->halted = 1;
+       /* request in processing or next one */
+       if (ep->queue.next == &req->queue) {
+               if (ep->dma && req->dma_going) {
+                       if (ep->in)
+                               ep->cancel_transfer = 1;
+                       else {
+                               u32 tmp;
+                               u32 dma_sts;
+                               /* stop potential receive DMA */
+                               tmp = readl(&udc->regs->ctl);
+                               writel(tmp & AMD_UNMASK_BIT(UDC_DEVCTL_RDE),
+                                                       &udc->regs->ctl);
+                               /*
+                                * Cancel transfer later in ISR
+                                * if descriptor was touched.
+                                */
+                               dma_sts = AMD_GETBITS(req->td_data->status,
+                                                       UDC_DMA_OUT_STS_BS);
+                               if (dma_sts != UDC_DMA_OUT_STS_BS_HOST_READY)
+                                       ep->cancel_transfer = 1;
+                               else {
+                                       udc_init_bna_dummy(ep->req);
+                                       writel(ep->bna_dummy_req->td_phys,
+                                               &ep->regs->desptr);
+                               }
+                               writel(tmp, &udc->regs->ctl);
+                       }
+               }
+       }
+       complete_req(ep, req, -ECONNRESET);
+       ep->halted = halted;
+
+       spin_unlock_irqrestore(&ep->dev->lock, iflags);
+       return 0;
+}
+
+/* Halt or clear halt of endpoint */
+static int
+udc_set_halt(struct usb_ep *usbep, int halt)
+{
+       struct udc_ep   *ep;
+       u32 tmp;
+       unsigned long iflags;
+       int retval = 0;
+
+       if (!usbep)
+               return -EINVAL;
+
+       pr_debug("set_halt %s: halt=%d\n", usbep->name, halt);
+
+       ep = container_of(usbep, struct udc_ep, ep);
+       if (!ep->ep.desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
+               return -EINVAL;
+       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       spin_lock_irqsave(&udc_stall_spinlock, iflags);
+       /* halt or clear halt */
+       if (halt) {
+               if (ep->num == 0)
+                       ep->dev->stall_ep0in = 1;
+               else {
+                       /*
+                        * set STALL
+                        * rxfifo empty not taken into acount
+                        */
+                       tmp = readl(&ep->regs->ctl);
+                       tmp |= AMD_BIT(UDC_EPCTL_S);
+                       writel(tmp, &ep->regs->ctl);
+                       ep->halted = 1;
+
+                       /* setup poll timer */
+                       if (!timer_pending(&udc_pollstall_timer)) {
+                               udc_pollstall_timer.expires = jiffies +
+                                       HZ * UDC_POLLSTALL_TIMER_USECONDS
+                                       / (1000 * 1000);
+                               if (!stop_pollstall_timer) {
+                                       DBG(ep->dev, "start polltimer\n");
+                                       add_timer(&udc_pollstall_timer);
+                               }
+                       }
+               }
+       } else {
+               /* ep is halted by set_halt() before */
+               if (ep->halted) {
+                       tmp = readl(&ep->regs->ctl);
+                       /* clear stall bit */
+                       tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S);
+                       /* clear NAK by writing CNAK */
+                       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+                       writel(tmp, &ep->regs->ctl);
+                       ep->halted = 0;
+                       UDC_QUEUE_CNAK(ep, ep->num);
+               }
+       }
+       spin_unlock_irqrestore(&udc_stall_spinlock, iflags);
+       return retval;
+}
+
+/* gadget interface */
+static const struct usb_ep_ops udc_ep_ops = {
+       .enable         = udc_ep_enable,
+       .disable        = udc_ep_disable,
+
+       .alloc_request  = udc_alloc_request,
+       .free_request   = udc_free_request,
+
+       .queue          = udc_queue,
+       .dequeue        = udc_dequeue,
+
+       .set_halt       = udc_set_halt,
+       /* fifo ops not implemented */
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Get frame counter (not implemented) */
+static int udc_get_frame(struct usb_gadget *gadget)
+{
+       return -EOPNOTSUPP;
+}
+
+/* Remote wakeup gadget interface */
+static int udc_wakeup(struct usb_gadget *gadget)
+{
+       struct udc              *dev;
+
+       if (!gadget)
+               return -EINVAL;
+       dev = container_of(gadget, struct udc, gadget);
+       udc_remote_wakeup(dev);
+
+       return 0;
+}
+
+static int amd5536_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+static int amd5536_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+/* gadget operations */
+static const struct usb_gadget_ops udc_ops = {
+       .wakeup         = udc_wakeup,
+       .get_frame      = udc_get_frame,
+       .udc_start      = amd5536_udc_start,
+       .udc_stop       = amd5536_udc_stop,
+};
+
+/* Setups endpoint parameters, adds endpoints to linked list */
+static void make_ep_lists(struct udc *dev)
+{
+       /* make gadget ep lists */
+       INIT_LIST_HEAD(&dev->gadget.ep_list);
+       list_add_tail(&dev->ep[UDC_EPIN_STATUS_IX].ep.ep_list,
+                                               &dev->gadget.ep_list);
+       list_add_tail(&dev->ep[UDC_EPIN_IX].ep.ep_list,
+                                               &dev->gadget.ep_list);
+       list_add_tail(&dev->ep[UDC_EPOUT_IX].ep.ep_list,
+                                               &dev->gadget.ep_list);
+
+       /* fifo config */
+       dev->ep[UDC_EPIN_STATUS_IX].fifo_depth = UDC_EPIN_SMALLINT_BUFF_SIZE;
+       if (dev->gadget.speed == USB_SPEED_FULL)
+               dev->ep[UDC_EPIN_IX].fifo_depth = UDC_FS_EPIN_BUFF_SIZE;
+       else if (dev->gadget.speed == USB_SPEED_HIGH)
+               dev->ep[UDC_EPIN_IX].fifo_depth = hs_tx_buf;
+       dev->ep[UDC_EPOUT_IX].fifo_depth = UDC_RXFIFO_SIZE;
+}
+
+/* init registers at driver load time */
+static int startup_registers(struct udc *dev)
+{
+       u32 tmp;
+
+       /* init controller by soft reset */
+       udc_soft_reset(dev);
+
+       /* mask not needed interrupts */
+       udc_mask_unused_interrupts(dev);
+
+       /* put into initial config */
+       udc_basic_init(dev);
+       /* link up all endpoints */
+       udc_setup_endpoints(dev);
+
+       /* program speed */
+       tmp = readl(&dev->regs->cfg);
+       if (use_fullspeed)
+               tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
+       else
+               tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);
+       writel(tmp, &dev->regs->cfg);
+
+       return 0;
+}
+
+/* Inits UDC context */
+static void udc_basic_init(struct udc *dev)
+{
+       u32     tmp;
+
+       DBG(dev, "udc_basic_init()\n");
+
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+       /* stop RDE timer */
+       if (timer_pending(&udc_timer)) {
+               set_rde = 0;
+               mod_timer(&udc_timer, jiffies - 1);
+       }
+       /* stop poll stall timer */
+       if (timer_pending(&udc_pollstall_timer))
+               mod_timer(&udc_pollstall_timer, jiffies - 1);
+       /* disable DMA */
+       tmp = readl(&dev->regs->ctl);
+       tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_RDE);
+       tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_TDE);
+       writel(tmp, &dev->regs->ctl);
+
+       /* enable dynamic CSR programming */
+       tmp = readl(&dev->regs->cfg);
+       tmp |= AMD_BIT(UDC_DEVCFG_CSR_PRG);
+       /* set self powered */
+       tmp |= AMD_BIT(UDC_DEVCFG_SP);
+       /* set remote wakeupable */
+       tmp |= AMD_BIT(UDC_DEVCFG_RWKP);
+       writel(tmp, &dev->regs->cfg);
+
+       make_ep_lists(dev);
+
+       dev->data_ep_enabled = 0;
+       dev->data_ep_queued = 0;
+}
+
+/* Sets initial endpoint parameters */
+static void udc_setup_endpoints(struct udc *dev)
+{
+       struct udc_ep   *ep;
+       u32     tmp;
+       u32     reg;
+
+       DBG(dev, "udc_setup_endpoints()\n");
+
+       /* read enum speed */
+       tmp = readl(&dev->regs->sts);
+       tmp = AMD_GETBITS(tmp, UDC_DEVSTS_ENUM_SPEED);
+       if (tmp == UDC_DEVSTS_ENUM_SPEED_HIGH)
+               dev->gadget.speed = USB_SPEED_HIGH;
+       else if (tmp == UDC_DEVSTS_ENUM_SPEED_FULL)
+               dev->gadget.speed = USB_SPEED_FULL;
+
+       /* set basic ep parameters */
+       for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
+               ep = &dev->ep[tmp];
+               ep->dev = dev;
+               ep->ep.name = ep_string[tmp];
+               ep->num = tmp;
+               /* txfifo size is calculated at enable time */
+               ep->txfifo = dev->txfifo;
+
+               /* fifo size */
+               if (tmp < UDC_EPIN_NUM) {
+                       ep->fifo_depth = UDC_TXFIFO_SIZE;
+                       ep->in = 1;
+               } else {
+                       ep->fifo_depth = UDC_RXFIFO_SIZE;
+                       ep->in = 0;
+
+               }
+               ep->regs = &dev->ep_regs[tmp];
+               /*
+                * ep will be reset only if ep was not enabled before to avoid
+                * disabling ep interrupts when ENUM interrupt occurs but ep is
+                * not enabled by gadget driver
+                */
+               if (!ep->ep.desc)
+                       ep_init(dev->regs, ep);
+
+               if (use_dma) {
+                       /*
+                        * ep->dma is not really used, just to indicate that
+                        * DMA is active: remove this
+                        * dma regs = dev control regs
+                        */
+                       ep->dma = &dev->regs->ctl;
+
+                       /* nak OUT endpoints until enable - not for ep0 */
+                       if (tmp != UDC_EP0IN_IX && tmp != UDC_EP0OUT_IX
+                                               && tmp > UDC_EPIN_NUM) {
+                               /* set NAK */
+                               reg = readl(&dev->ep[tmp].regs->ctl);
+                               reg |= AMD_BIT(UDC_EPCTL_SNAK);
+                               writel(reg, &dev->ep[tmp].regs->ctl);
+                               dev->ep[tmp].naking = 1;
+
+                       }
+               }
+       }
+       /* EP0 max packet */
+       if (dev->gadget.speed == USB_SPEED_FULL) {
+               usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0IN_IX].ep,
+                                          UDC_FS_EP0IN_MAX_PKT_SIZE);
+               usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0OUT_IX].ep,
+                                          UDC_FS_EP0OUT_MAX_PKT_SIZE);
+       } else if (dev->gadget.speed == USB_SPEED_HIGH) {
+               usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0IN_IX].ep,
+                                          UDC_EP0IN_MAX_PKT_SIZE);
+               usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0OUT_IX].ep,
+                                          UDC_EP0OUT_MAX_PKT_SIZE);
+       }
+
+       /*
+        * with suspend bug workaround, ep0 params for gadget driver
+        * are set at gadget driver bind() call
+        */
+       dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IX].ep;
+       dev->ep[UDC_EP0IN_IX].halted = 0;
+       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+
+       /* init cfg/alt/int */
+       dev->cur_config = 0;
+       dev->cur_intf = 0;
+       dev->cur_alt = 0;
+}
+
+/* Bringup after Connect event, initial bringup to be ready for ep0 events */
+static void usb_connect(struct udc *dev)
+{
+
+       dev_info(&dev->pdev->dev, "USB Connect\n");
+
+       dev->connected = 1;
+
+       /* put into initial config */
+       udc_basic_init(dev);
+
+       /* enable device setup interrupts */
+       udc_enable_dev_setup_interrupts(dev);
+}
+
+/*
+ * Calls gadget with disconnect event and resets the UDC and makes
+ * initial bringup to be ready for ep0 events
+ */
+static void usb_disconnect(struct udc *dev)
+{
+
+       dev_info(&dev->pdev->dev, "USB Disconnect\n");
+
+       dev->connected = 0;
+
+       /* mask interrupts */
+       udc_mask_unused_interrupts(dev);
+
+       /* REVISIT there doesn't seem to be a point to having this
+        * talk to a tasklet ... do it directly, we already hold
+        * the spinlock needed to process the disconnect.
+        */
+
+       tasklet_schedule(&disconnect_tasklet);
+}
+
+/* Tasklet for disconnect to be outside of interrupt context */
+static void udc_tasklet_disconnect(unsigned long par)
+{
+       struct udc *dev = (struct udc *)(*((struct udc **) par));
+       u32 tmp;
+
+       DBG(dev, "Tasklet disconnect\n");
+       spin_lock_irq(&dev->lock);
+
+       if (dev->driver) {
+               spin_unlock(&dev->lock);
+               dev->driver->disconnect(&dev->gadget);
+               spin_lock(&dev->lock);
+
+               /* empty queues */
+               for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
+                       empty_req_queue(&dev->ep[tmp]);
+
+       }
+
+       /* disable ep0 */
+       ep_init(dev->regs,
+                       &dev->ep[UDC_EP0IN_IX]);
+
+
+       if (!soft_reset_occured) {
+               /* init controller by soft reset */
+               udc_soft_reset(dev);
+               soft_reset_occured++;
+       }
+
+       /* re-enable dev interrupts */
+       udc_enable_dev_setup_interrupts(dev);
+       /* back to full speed ? */
+       if (use_fullspeed) {
+               tmp = readl(&dev->regs->cfg);
+               tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
+               writel(tmp, &dev->regs->cfg);
+       }
+
+       spin_unlock_irq(&dev->lock);
+}
+
+/* Reset the UDC core */
+static void udc_soft_reset(struct udc *dev)
+{
+       unsigned long   flags;
+
+       DBG(dev, "Soft reset\n");
+       /*
+        * reset possible waiting interrupts, because int.
+        * status is lost after soft reset,
+        * ep int. status reset
+        */
+       writel(UDC_EPINT_MSK_DISABLE_ALL, &dev->regs->ep_irqsts);
+       /* device int. status reset */
+       writel(UDC_DEV_MSK_DISABLE, &dev->regs->irqsts);
+
+       spin_lock_irqsave(&udc_irq_spinlock, flags);
+       writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
+       readl(&dev->regs->cfg);
+       spin_unlock_irqrestore(&udc_irq_spinlock, flags);
+
+}
+
+/* RDE timer callback to set RDE bit */
+static void udc_timer_function(unsigned long v)
+{
+       u32 tmp;
+
+       spin_lock_irq(&udc_irq_spinlock);
+
+       if (set_rde > 0) {
+               /*
+                * open the fifo if fifo was filled on last timer call
+                * conditionally
+                */
+               if (set_rde > 1) {
+                       /* set RDE to receive setup data */
+                       tmp = readl(&udc->regs->ctl);
+                       tmp |= AMD_BIT(UDC_DEVCTL_RDE);
+                       writel(tmp, &udc->regs->ctl);
+                       set_rde = -1;
+               } else if (readl(&udc->regs->sts)
+                               & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {
+                       /*
+                        * if fifo empty setup polling, do not just
+                        * open the fifo
+                        */
+                       udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV;
+                       if (!stop_timer)
+                               add_timer(&udc_timer);
+               } else {
+                       /*
+                        * fifo contains data now, setup timer for opening
+                        * the fifo when timer expires to be able to receive
+                        * setup packets, when data packets gets queued by
+                        * gadget layer then timer will forced to expire with
+                        * set_rde=0 (RDE is set in udc_queue())
+                        */
+                       set_rde++;
+                       /* debug: lhadmot_timer_start = 221070 */
+                       udc_timer.expires = jiffies + HZ*UDC_RDE_TIMER_SECONDS;
+                       if (!stop_timer)
+                               add_timer(&udc_timer);
+               }
+
+       } else
+               set_rde = -1; /* RDE was set by udc_queue() */
+       spin_unlock_irq(&udc_irq_spinlock);
+       if (stop_timer)
+               complete(&on_exit);
+
+}
+
+/* Handle halt state, used in stall poll timer */
+static void udc_handle_halt_state(struct udc_ep *ep)
+{
+       u32 tmp;
+       /* set stall as long not halted */
+       if (ep->halted == 1) {
+               tmp = readl(&ep->regs->ctl);
+               /* STALL cleared ? */
+               if (!(tmp & AMD_BIT(UDC_EPCTL_S))) {
+                       /*
+                        * FIXME: MSC spec requires that stall remains
+                        * even on receivng of CLEAR_FEATURE HALT. So
+                        * we would set STALL again here to be compliant.
+                        * But with current mass storage drivers this does
+                        * not work (would produce endless host retries).
+                        * So we clear halt on CLEAR_FEATURE.
+                        *
+                       DBG(ep->dev, "ep %d: set STALL again\n", ep->num);
+                       tmp |= AMD_BIT(UDC_EPCTL_S);
+                       writel(tmp, &ep->regs->ctl);*/
+
+                       /* clear NAK by writing CNAK */
+                       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+                       writel(tmp, &ep->regs->ctl);
+                       ep->halted = 0;
+                       UDC_QUEUE_CNAK(ep, ep->num);
+               }
+       }
+}
+
+/* Stall timer callback to poll S bit and set it again after */
+static void udc_pollstall_timer_function(unsigned long v)
+{
+       struct udc_ep *ep;
+       int halted = 0;
+
+       spin_lock_irq(&udc_stall_spinlock);
+       /*
+        * only one IN and OUT endpoints are handled
+        * IN poll stall
+        */
+       ep = &udc->ep[UDC_EPIN_IX];
+       udc_handle_halt_state(ep);
+       if (ep->halted)
+               halted = 1;
+       /* OUT poll stall */
+       ep = &udc->ep[UDC_EPOUT_IX];
+       udc_handle_halt_state(ep);
+       if (ep->halted)
+               halted = 1;
+
+       /* setup timer again when still halted */
+       if (!stop_pollstall_timer && halted) {
+               udc_pollstall_timer.expires = jiffies +
+                                       HZ * UDC_POLLSTALL_TIMER_USECONDS
+                                       / (1000 * 1000);
+               add_timer(&udc_pollstall_timer);
+       }
+       spin_unlock_irq(&udc_stall_spinlock);
+
+       if (stop_pollstall_timer)
+               complete(&on_pollstall_exit);
+}
+
+/* Inits endpoint 0 so that SETUP packets are processed */
+static void activate_control_endpoints(struct udc *dev)
+{
+       u32 tmp;
+
+       DBG(dev, "activate_control_endpoints\n");
+
+       /* flush fifo */
+       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
+       tmp |= AMD_BIT(UDC_EPCTL_F);
+       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
+
+       /* set ep0 directions */
+       dev->ep[UDC_EP0IN_IX].in = 1;
+       dev->ep[UDC_EP0OUT_IX].in = 0;
+
+       /* set buffer size (tx fifo entries) of EP0_IN */
+       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufin_framenum);
+       if (dev->gadget.speed == USB_SPEED_FULL)
+               tmp = AMD_ADDBITS(tmp, UDC_FS_EPIN0_BUFF_SIZE,
+                                       UDC_EPIN_BUFF_SIZE);
+       else if (dev->gadget.speed == USB_SPEED_HIGH)
+               tmp = AMD_ADDBITS(tmp, UDC_EPIN0_BUFF_SIZE,
+                                       UDC_EPIN_BUFF_SIZE);
+       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufin_framenum);
+
+       /* set max packet size of EP0_IN */
+       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt);
+       if (dev->gadget.speed == USB_SPEED_FULL)
+               tmp = AMD_ADDBITS(tmp, UDC_FS_EP0IN_MAX_PKT_SIZE,
+                                       UDC_EP_MAX_PKT_SIZE);
+       else if (dev->gadget.speed == USB_SPEED_HIGH)
+               tmp = AMD_ADDBITS(tmp, UDC_EP0IN_MAX_PKT_SIZE,
+                               UDC_EP_MAX_PKT_SIZE);
+       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt);
+
+       /* set max packet size of EP0_OUT */
+       tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt);
+       if (dev->gadget.speed == USB_SPEED_FULL)
+               tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE,
+                                       UDC_EP_MAX_PKT_SIZE);
+       else if (dev->gadget.speed == USB_SPEED_HIGH)
+               tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE,
+                                       UDC_EP_MAX_PKT_SIZE);
+       writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt);
+
+       /* set max packet size of EP0 in UDC CSR */
+       tmp = readl(&dev->csr->ne[0]);
+       if (dev->gadget.speed == USB_SPEED_FULL)
+               tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE,
+                                       UDC_CSR_NE_MAX_PKT);
+       else if (dev->gadget.speed == USB_SPEED_HIGH)
+               tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE,
+                                       UDC_CSR_NE_MAX_PKT);
+       writel(tmp, &dev->csr->ne[0]);
+
+       if (use_dma) {
+               dev->ep[UDC_EP0OUT_IX].td->status |=
+                       AMD_BIT(UDC_DMA_OUT_STS_L);
+               /* write dma desc address */
+               writel(dev->ep[UDC_EP0OUT_IX].td_stp_dma,
+                       &dev->ep[UDC_EP0OUT_IX].regs->subptr);
+               writel(dev->ep[UDC_EP0OUT_IX].td_phys,
+                       &dev->ep[UDC_EP0OUT_IX].regs->desptr);
+               /* stop RDE timer */
+               if (timer_pending(&udc_timer)) {
+                       set_rde = 0;
+                       mod_timer(&udc_timer, jiffies - 1);
+               }
+               /* stop pollstall timer */
+               if (timer_pending(&udc_pollstall_timer))
+                       mod_timer(&udc_pollstall_timer, jiffies - 1);
+               /* enable DMA */
+               tmp = readl(&dev->regs->ctl);
+               tmp |= AMD_BIT(UDC_DEVCTL_MODE)
+                               | AMD_BIT(UDC_DEVCTL_RDE)
+                               | AMD_BIT(UDC_DEVCTL_TDE);
+               if (use_dma_bufferfill_mode)
+                       tmp |= AMD_BIT(UDC_DEVCTL_BF);
+               else if (use_dma_ppb_du)
+                       tmp |= AMD_BIT(UDC_DEVCTL_DU);
+               writel(tmp, &dev->regs->ctl);
+       }
+
+       /* clear NAK by writing CNAK for EP0IN */
+       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
+       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
+       dev->ep[UDC_EP0IN_IX].naking = 0;
+       UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX);
+
+       /* clear NAK by writing CNAK for EP0OUT */
+       tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);
+       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+       writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl);
+       dev->ep[UDC_EP0OUT_IX].naking = 0;
+       UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX);
+}
+
+/* Make endpoint 0 ready for control traffic */
+static int setup_ep0(struct udc *dev)
+{
+       activate_control_endpoints(dev);
+       /* enable ep0 interrupts */
+       udc_enable_ep0_interrupts(dev);
+       /* enable device setup interrupts */
+       udc_enable_dev_setup_interrupts(dev);
+
+       return 0;
+}
+
+/* Called by gadget driver to register itself */
+static int amd5536_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct udc *dev = to_amd5536_udc(g);
+       u32 tmp;
+
+       driver->driver.bus = NULL;
+       dev->driver = driver;
+
+       /* Some gadget drivers use both ep0 directions.
+        * NOTE: to gadget driver, ep0 is just one endpoint...
+        */
+       dev->ep[UDC_EP0OUT_IX].ep.driver_data =
+               dev->ep[UDC_EP0IN_IX].ep.driver_data;
+
+       /* get ready for ep0 traffic */
+       setup_ep0(dev);
+
+       /* clear SD */
+       tmp = readl(&dev->regs->ctl);
+       tmp = tmp & AMD_CLEAR_BIT(UDC_DEVCTL_SD);
+       writel(tmp, &dev->regs->ctl);
+
+       usb_connect(dev);
+
+       return 0;
+}
+
+/* shutdown requests and disconnect from gadget */
+static void
+shutdown(struct udc *dev, struct usb_gadget_driver *driver)
+__releases(dev->lock)
+__acquires(dev->lock)
+{
+       int tmp;
+
+       /* empty queues and init hardware */
+       udc_basic_init(dev);
+
+       for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
+               empty_req_queue(&dev->ep[tmp]);
+
+       udc_setup_endpoints(dev);
+}
+
+/* Called by gadget driver to unregister itself */
+static int amd5536_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct udc *dev = to_amd5536_udc(g);
+       unsigned long flags;
+       u32 tmp;
+
+       spin_lock_irqsave(&dev->lock, flags);
+       udc_mask_unused_interrupts(dev);
+       shutdown(dev, driver);
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       dev->driver = NULL;
+
+       /* set SD */
+       tmp = readl(&dev->regs->ctl);
+       tmp |= AMD_BIT(UDC_DEVCTL_SD);
+       writel(tmp, &dev->regs->ctl);
+
+       return 0;
+}
+
+/* Clear pending NAK bits */
+static void udc_process_cnak_queue(struct udc *dev)
+{
+       u32 tmp;
+       u32 reg;
+
+       /* check epin's */
+       DBG(dev, "CNAK pending queue processing\n");
+       for (tmp = 0; tmp < UDC_EPIN_NUM_USED; tmp++) {
+               if (cnak_pending & (1 << tmp)) {
+                       DBG(dev, "CNAK pending for ep%d\n", tmp);
+                       /* clear NAK by writing CNAK */
+                       reg = readl(&dev->ep[tmp].regs->ctl);
+                       reg |= AMD_BIT(UDC_EPCTL_CNAK);
+                       writel(reg, &dev->ep[tmp].regs->ctl);
+                       dev->ep[tmp].naking = 0;
+                       UDC_QUEUE_CNAK(&dev->ep[tmp], dev->ep[tmp].num);
+               }
+       }
+       /* ...  and ep0out */
+       if (cnak_pending & (1 << UDC_EP0OUT_IX)) {
+               DBG(dev, "CNAK pending for ep%d\n", UDC_EP0OUT_IX);
+               /* clear NAK by writing CNAK */
+               reg = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);
+               reg |= AMD_BIT(UDC_EPCTL_CNAK);
+               writel(reg, &dev->ep[UDC_EP0OUT_IX].regs->ctl);
+               dev->ep[UDC_EP0OUT_IX].naking = 0;
+               UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX],
+                               dev->ep[UDC_EP0OUT_IX].num);
+       }
+}
+
+/* Enabling RX DMA after setup packet */
+static void udc_ep0_set_rde(struct udc *dev)
+{
+       if (use_dma) {
+               /*
+                * only enable RXDMA when no data endpoint enabled
+                * or data is queued
+                */
+               if (!dev->data_ep_enabled || dev->data_ep_queued) {
+                       udc_set_rde(dev);
+               } else {
+                       /*
+                        * setup timer for enabling RDE (to not enable
+                        * RXFIFO DMA for data endpoints to early)
+                        */
+                       if (set_rde != 0 && !timer_pending(&udc_timer)) {
+                               udc_timer.expires =
+                                       jiffies + HZ/UDC_RDE_TIMER_DIV;
+                               set_rde = 1;
+                               if (!stop_timer)
+                                       add_timer(&udc_timer);
+                       }
+               }
+       }
+}
+
+
+/* Interrupt handler for data OUT traffic */
+static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
+{
+       irqreturn_t             ret_val = IRQ_NONE;
+       u32                     tmp;
+       struct udc_ep           *ep;
+       struct udc_request      *req;
+       unsigned int            count;
+       struct udc_data_dma     *td = NULL;
+       unsigned                dma_done;
+
+       VDBG(dev, "ep%d irq\n", ep_ix);
+       ep = &dev->ep[ep_ix];
+
+       tmp = readl(&ep->regs->sts);
+       if (use_dma) {
+               /* BNA event ? */
+               if (tmp & AMD_BIT(UDC_EPSTS_BNA)) {
+                       DBG(dev, "BNA ep%dout occurred - DESPTR = %x\n",
+                                       ep->num, readl(&ep->regs->desptr));
+                       /* clear BNA */
+                       writel(tmp | AMD_BIT(UDC_EPSTS_BNA), &ep->regs->sts);
+                       if (!ep->cancel_transfer)
+                               ep->bna_occurred = 1;
+                       else
+                               ep->cancel_transfer = 0;
+                       ret_val = IRQ_HANDLED;
+                       goto finished;
+               }
+       }
+       /* HE event ? */
+       if (tmp & AMD_BIT(UDC_EPSTS_HE)) {
+               dev_err(&dev->pdev->dev, "HE ep%dout occurred\n", ep->num);
+
+               /* clear HE */
+               writel(tmp | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts);
+               ret_val = IRQ_HANDLED;
+               goto finished;
+       }
+
+       if (!list_empty(&ep->queue)) {
+
+               /* next request */
+               req = list_entry(ep->queue.next,
+                       struct udc_request, queue);
+       } else {
+               req = NULL;
+               udc_rxfifo_pending = 1;
+       }
+       VDBG(dev, "req = %p\n", req);
+       /* fifo mode */
+       if (!use_dma) {
+
+               /* read fifo */
+               if (req && udc_rxfifo_read(ep, req)) {
+                       ret_val = IRQ_HANDLED;
+
+                       /* finish */
+                       complete_req(ep, req, 0);
+                       /* next request */
+                       if (!list_empty(&ep->queue) && !ep->halted) {
+                               req = list_entry(ep->queue.next,
+                                       struct udc_request, queue);
+                       } else
+                               req = NULL;
+               }
+
+       /* DMA */
+       } else if (!ep->cancel_transfer && req != NULL) {
+               ret_val = IRQ_HANDLED;
+
+               /* check for DMA done */
+               if (!use_dma_ppb) {
+                       dma_done = AMD_GETBITS(req->td_data->status,
+                                               UDC_DMA_OUT_STS_BS);
+               /* packet per buffer mode - rx bytes */
+               } else {
+                       /*
+                        * if BNA occurred then recover desc. from
+                        * BNA dummy desc.
+                        */
+                       if (ep->bna_occurred) {
+                               VDBG(dev, "Recover desc. from BNA dummy\n");
+                               memcpy(req->td_data, ep->bna_dummy_req->td_data,
+                                               sizeof(struct udc_data_dma));
+                               ep->bna_occurred = 0;
+                               udc_init_bna_dummy(ep->req);
+                       }
+                       td = udc_get_last_dma_desc(req);
+                       dma_done = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_BS);
+               }
+               if (dma_done == UDC_DMA_OUT_STS_BS_DMA_DONE) {
+                       /* buffer fill mode - rx bytes */
+                       if (!use_dma_ppb) {
+                               /* received number bytes */
+                               count = AMD_GETBITS(req->td_data->status,
+                                               UDC_DMA_OUT_STS_RXBYTES);
+                               VDBG(dev, "rx bytes=%u\n", count);
+                       /* packet per buffer mode - rx bytes */
+                       } else {
+                               VDBG(dev, "req->td_data=%p\n", req->td_data);
+                               VDBG(dev, "last desc = %p\n", td);
+                               /* received number bytes */
+                               if (use_dma_ppb_du) {
+                                       /* every desc. counts bytes */
+                                       count = udc_get_ppbdu_rxbytes(req);
+                               } else {
+                                       /* last desc. counts bytes */
+                                       count = AMD_GETBITS(td->status,
+                                               UDC_DMA_OUT_STS_RXBYTES);
+                                       if (!count && req->req.length
+                                               == UDC_DMA_MAXPACKET) {
+                                               /*
+                                                * on 64k packets the RXBYTES
+                                                * field is zero
+                                                */
+                                               count = UDC_DMA_MAXPACKET;
+                                       }
+                               }
+                               VDBG(dev, "last desc rx bytes=%u\n", count);
+                       }
+
+                       tmp = req->req.length - req->req.actual;
+                       if (count > tmp) {
+                               if ((tmp % ep->ep.maxpacket) != 0) {
+                                       DBG(dev, "%s: rx %db, space=%db\n",
+                                               ep->ep.name, count, tmp);
+                                       req->req.status = -EOVERFLOW;
+                               }
+                               count = tmp;
+                       }
+                       req->req.actual += count;
+                       req->dma_going = 0;
+                       /* complete request */
+                       complete_req(ep, req, 0);
+
+                       /* next request */
+                       if (!list_empty(&ep->queue) && !ep->halted) {
+                               req = list_entry(ep->queue.next,
+                                       struct udc_request,
+                                       queue);
+                               /*
+                                * DMA may be already started by udc_queue()
+                                * called by gadget drivers completion
+                                * routine. This happens when queue
+                                * holds one request only.
+                                */
+                               if (req->dma_going == 0) {
+                                       /* next dma */
+                                       if (prep_dma(ep, req, GFP_ATOMIC) != 0)
+                                               goto finished;
+                                       /* write desc pointer */
+                                       writel(req->td_phys,
+                                               &ep->regs->desptr);
+                                       req->dma_going = 1;
+                                       /* enable DMA */
+                                       udc_set_rde(dev);
+                               }
+                       } else {
+                               /*
+                                * implant BNA dummy descriptor to allow
+                                * RXFIFO opening by RDE
+                                */
+                               if (ep->bna_dummy_req) {
+                                       /* write desc pointer */
+                                       writel(ep->bna_dummy_req->td_phys,
+                                               &ep->regs->desptr);
+                                       ep->bna_occurred = 0;
+                               }
+
+                               /*
+                                * schedule timer for setting RDE if queue
+                                * remains empty to allow ep0 packets pass
+                                * through
+                                */
+                               if (set_rde != 0
+                                               && !timer_pending(&udc_timer)) {
+                                       udc_timer.expires =
+                                               jiffies
+                                               + HZ*UDC_RDE_TIMER_SECONDS;
+                                       set_rde = 1;
+                                       if (!stop_timer)
+                                               add_timer(&udc_timer);
+                               }
+                               if (ep->num != UDC_EP0OUT_IX)
+                                       dev->data_ep_queued = 0;
+                       }
+
+               } else {
+                       /*
+                       * RX DMA must be reenabled for each desc in PPBDU mode
+                       * and must be enabled for PPBNDU mode in case of BNA
+                       */
+                       udc_set_rde(dev);
+               }
+
+       } else if (ep->cancel_transfer) {
+               ret_val = IRQ_HANDLED;
+               ep->cancel_transfer = 0;
+       }
+
+       /* check pending CNAKS */
+       if (cnak_pending) {
+               /* CNAk processing when rxfifo empty only */
+               if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY))
+                       udc_process_cnak_queue(dev);
+       }
+
+       /* clear OUT bits in ep status */
+       writel(UDC_EPSTS_OUT_CLEAR, &ep->regs->sts);
+finished:
+       return ret_val;
+}
+
+/* Interrupt handler for data IN traffic */
+static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
+{
+       irqreturn_t ret_val = IRQ_NONE;
+       u32 tmp;
+       u32 epsts;
+       struct udc_ep *ep;
+       struct udc_request *req;
+       struct udc_data_dma *td;
+       unsigned dma_done;
+       unsigned len;
+
+       ep = &dev->ep[ep_ix];
+
+       epsts = readl(&ep->regs->sts);
+       if (use_dma) {
+               /* BNA ? */
+               if (epsts & AMD_BIT(UDC_EPSTS_BNA)) {
+                       dev_err(&dev->pdev->dev,
+                               "BNA ep%din occurred - DESPTR = %08lx\n",
+                               ep->num,
+                               (unsigned long) readl(&ep->regs->desptr));
+
+                       /* clear BNA */
+                       writel(epsts, &ep->regs->sts);
+                       ret_val = IRQ_HANDLED;
+                       goto finished;
+               }
+       }
+       /* HE event ? */
+       if (epsts & AMD_BIT(UDC_EPSTS_HE)) {
+               dev_err(&dev->pdev->dev,
+                       "HE ep%dn occurred - DESPTR = %08lx\n",
+                       ep->num, (unsigned long) readl(&ep->regs->desptr));
+
+               /* clear HE */
+               writel(epsts | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts);
+               ret_val = IRQ_HANDLED;
+               goto finished;
+       }
+
+       /* DMA completion */
+       if (epsts & AMD_BIT(UDC_EPSTS_TDC)) {
+               VDBG(dev, "TDC set- completion\n");
+               ret_val = IRQ_HANDLED;
+               if (!ep->cancel_transfer && !list_empty(&ep->queue)) {
+                       req = list_entry(ep->queue.next,
+                                       struct udc_request, queue);
+                       /*
+                        * length bytes transferred
+                        * check dma done of last desc. in PPBDU mode
+                        */
+                       if (use_dma_ppb_du) {
+                               td = udc_get_last_dma_desc(req);
+                               if (td) {
+                                       dma_done =
+                                               AMD_GETBITS(td->status,
+                                               UDC_DMA_IN_STS_BS);
+                                       /* don't care DMA done */
+                                       req->req.actual = req->req.length;
+                               }
+                       } else {
+                               /* assume all bytes transferred */
+                               req->req.actual = req->req.length;
+                       }
+
+                       if (req->req.actual == req->req.length) {
+                               /* complete req */
+                               complete_req(ep, req, 0);
+                               req->dma_going = 0;
+                               /* further request available ? */
+                               if (list_empty(&ep->queue)) {
+                                       /* disable interrupt */
+                                       tmp = readl(&dev->regs->ep_irqmsk);
+                                       tmp |= AMD_BIT(ep->num);
+                                       writel(tmp, &dev->regs->ep_irqmsk);
+                               }
+                       }
+               }
+               ep->cancel_transfer = 0;
+
+       }
+       /*
+        * status reg has IN bit set and TDC not set (if TDC was handled,
+        * IN must not be handled (UDC defect) ?
+        */
+       if ((epsts & AMD_BIT(UDC_EPSTS_IN))
+                       && !(epsts & AMD_BIT(UDC_EPSTS_TDC))) {
+               ret_val = IRQ_HANDLED;
+               if (!list_empty(&ep->queue)) {
+                       /* next request */
+                       req = list_entry(ep->queue.next,
+                                       struct udc_request, queue);
+                       /* FIFO mode */
+                       if (!use_dma) {
+                               /* write fifo */
+                               udc_txfifo_write(ep, &req->req);
+                               len = req->req.length - req->req.actual;
+                               if (len > ep->ep.maxpacket)
+                                       len = ep->ep.maxpacket;
+                               req->req.actual += len;
+                               if (req->req.actual == req->req.length
+                                       || (len != ep->ep.maxpacket)) {
+                                       /* complete req */
+                                       complete_req(ep, req, 0);
+                               }
+                       /* DMA */
+                       } else if (req && !req->dma_going) {
+                               VDBG(dev, "IN DMA : req=%p req->td_data=%p\n",
+                                       req, req->td_data);
+                               if (req->td_data) {
+
+                                       req->dma_going = 1;
+
+                                       /*
+                                        * unset L bit of first desc.
+                                        * for chain
+                                        */
+                                       if (use_dma_ppb && req->req.length >
+                                                       ep->ep.maxpacket) {
+                                               req->td_data->status &=
+                                                       AMD_CLEAR_BIT(
+                                                       UDC_DMA_IN_STS_L);
+                                       }
+
+                                       /* write desc pointer */
+                                       writel(req->td_phys, &ep->regs->desptr);
+
+                                       /* set HOST READY */
+                                       req->td_data->status =
+                                               AMD_ADDBITS(
+                                               req->td_data->status,
+                                               UDC_DMA_IN_STS_BS_HOST_READY,
+                                               UDC_DMA_IN_STS_BS);
+
+                                       /* set poll demand bit */
+                                       tmp = readl(&ep->regs->ctl);
+                                       tmp |= AMD_BIT(UDC_EPCTL_P);
+                                       writel(tmp, &ep->regs->ctl);
+                               }
+                       }
+
+               } else if (!use_dma && ep->in) {
+                       /* disable interrupt */
+                       tmp = readl(
+                               &dev->regs->ep_irqmsk);
+                       tmp |= AMD_BIT(ep->num);
+                       writel(tmp,
+                               &dev->regs->ep_irqmsk);
+               }
+       }
+       /* clear status bits */
+       writel(epsts, &ep->regs->sts);
+
+finished:
+       return ret_val;
+
+}
+
+/* Interrupt handler for Control OUT traffic */
+static irqreturn_t udc_control_out_isr(struct udc *dev)
+__releases(dev->lock)
+__acquires(dev->lock)
+{
+       irqreturn_t ret_val = IRQ_NONE;
+       u32 tmp;
+       int setup_supported;
+       u32 count;
+       int set = 0;
+       struct udc_ep   *ep;
+       struct udc_ep   *ep_tmp;
+
+       ep = &dev->ep[UDC_EP0OUT_IX];
+
+       /* clear irq */
+       writel(AMD_BIT(UDC_EPINT_OUT_EP0), &dev->regs->ep_irqsts);
+
+       tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->sts);
+       /* check BNA and clear if set */
+       if (tmp & AMD_BIT(UDC_EPSTS_BNA)) {
+               VDBG(dev, "ep0: BNA set\n");
+               writel(AMD_BIT(UDC_EPSTS_BNA),
+                       &dev->ep[UDC_EP0OUT_IX].regs->sts);
+               ep->bna_occurred = 1;
+               ret_val = IRQ_HANDLED;
+               goto finished;
+       }
+
+       /* type of data: SETUP or DATA 0 bytes */
+       tmp = AMD_GETBITS(tmp, UDC_EPSTS_OUT);
+       VDBG(dev, "data_typ = %x\n", tmp);
+
+       /* setup data */
+       if (tmp == UDC_EPSTS_OUT_SETUP) {
+               ret_val = IRQ_HANDLED;
+
+               ep->dev->stall_ep0in = 0;
+               dev->waiting_zlp_ack_ep0in = 0;
+
+               /* set NAK for EP0_IN */
+               tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
+               tmp |= AMD_BIT(UDC_EPCTL_SNAK);
+               writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
+               dev->ep[UDC_EP0IN_IX].naking = 1;
+               /* get setup data */
+               if (use_dma) {
+
+                       /* clear OUT bits in ep status */
+                       writel(UDC_EPSTS_OUT_CLEAR,
+                               &dev->ep[UDC_EP0OUT_IX].regs->sts);
+
+                       setup_data.data[0] =
+                               dev->ep[UDC_EP0OUT_IX].td_stp->data12;
+                       setup_data.data[1] =
+                               dev->ep[UDC_EP0OUT_IX].td_stp->data34;
+                       /* set HOST READY */
+                       dev->ep[UDC_EP0OUT_IX].td_stp->status =
+                                       UDC_DMA_STP_STS_BS_HOST_READY;
+               } else {
+                       /* read fifo */
+                       udc_rxfifo_read_dwords(dev, setup_data.data, 2);
+               }
+
+               /* determine direction of control data */
+               if ((setup_data.request.bRequestType & USB_DIR_IN) != 0) {
+                       dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IX].ep;
+                       /* enable RDE */
+                       udc_ep0_set_rde(dev);
+                       set = 0;
+               } else {
+                       dev->gadget.ep0 = &dev->ep[UDC_EP0OUT_IX].ep;
+                       /*
+                        * implant BNA dummy descriptor to allow RXFIFO opening
+                        * by RDE
+                        */
+                       if (ep->bna_dummy_req) {
+                               /* write desc pointer */
+                               writel(ep->bna_dummy_req->td_phys,
+                                       &dev->ep[UDC_EP0OUT_IX].regs->desptr);
+                               ep->bna_occurred = 0;
+                       }
+
+                       set = 1;
+                       dev->ep[UDC_EP0OUT_IX].naking = 1;
+                       /*
+                        * setup timer for enabling RDE (to not enable
+                        * RXFIFO DMA for data to early)
+                        */
+                       set_rde = 1;
+                       if (!timer_pending(&udc_timer)) {
+                               udc_timer.expires = jiffies +
+                                                       HZ/UDC_RDE_TIMER_DIV;
+                               if (!stop_timer)
+                                       add_timer(&udc_timer);
+                       }
+               }
+
+               /*
+                * mass storage reset must be processed here because
+                * next packet may be a CLEAR_FEATURE HALT which would not
+                * clear the stall bit when no STALL handshake was received
+                * before (autostall can cause this)
+                */
+               if (setup_data.data[0] == UDC_MSCRES_DWORD0
+                               && setup_data.data[1] == UDC_MSCRES_DWORD1) {
+                       DBG(dev, "MSC Reset\n");
+                       /*
+                        * clear stall bits
+                        * only one IN and OUT endpoints are handled
+                        */
+                       ep_tmp = &udc->ep[UDC_EPIN_IX];
+                       udc_set_halt(&ep_tmp->ep, 0);
+                       ep_tmp = &udc->ep[UDC_EPOUT_IX];
+                       udc_set_halt(&ep_tmp->ep, 0);
+               }
+
+               /* call gadget with setup data received */
+               spin_unlock(&dev->lock);
+               setup_supported = dev->driver->setup(&dev->gadget,
+                                               &setup_data.request);
+               spin_lock(&dev->lock);
+
+               tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
+               /* ep0 in returns data (not zlp) on IN phase */
+               if (setup_supported >= 0 && setup_supported <
+                               UDC_EP0IN_MAXPACKET) {
+                       /* clear NAK by writing CNAK in EP0_IN */
+                       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+                       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
+                       dev->ep[UDC_EP0IN_IX].naking = 0;
+                       UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX);
+
+               /* if unsupported request then stall */
+               } else if (setup_supported < 0) {
+                       tmp |= AMD_BIT(UDC_EPCTL_S);
+                       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
+               } else
+                       dev->waiting_zlp_ack_ep0in = 1;
+
+
+               /* clear NAK by writing CNAK in EP0_OUT */
+               if (!set) {
+                       tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);
+                       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+                       writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl);
+                       dev->ep[UDC_EP0OUT_IX].naking = 0;
+                       UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX);
+               }
+
+               if (!use_dma) {
+                       /* clear OUT bits in ep status */
+                       writel(UDC_EPSTS_OUT_CLEAR,
+                               &dev->ep[UDC_EP0OUT_IX].regs->sts);
+               }
+
+       /* data packet 0 bytes */
+       } else if (tmp == UDC_EPSTS_OUT_DATA) {
+               /* clear OUT bits in ep status */
+               writel(UDC_EPSTS_OUT_CLEAR, &dev->ep[UDC_EP0OUT_IX].regs->sts);
+
+               /* get setup data: only 0 packet */
+               if (use_dma) {
+                       /* no req if 0 packet, just reactivate */
+                       if (list_empty(&dev->ep[UDC_EP0OUT_IX].queue)) {
+                               VDBG(dev, "ZLP\n");
+
+                               /* set HOST READY */
+                               dev->ep[UDC_EP0OUT_IX].td->status =
+                                       AMD_ADDBITS(
+                                       dev->ep[UDC_EP0OUT_IX].td->status,
+                                       UDC_DMA_OUT_STS_BS_HOST_READY,
+                                       UDC_DMA_OUT_STS_BS);
+                               /* enable RDE */
+                               udc_ep0_set_rde(dev);
+                               ret_val = IRQ_HANDLED;
+
+                       } else {
+                               /* control write */
+                               ret_val |= udc_data_out_isr(dev, UDC_EP0OUT_IX);
+                               /* re-program desc. pointer for possible ZLPs */
+                               writel(dev->ep[UDC_EP0OUT_IX].td_phys,
+                                       &dev->ep[UDC_EP0OUT_IX].regs->desptr);
+                               /* enable RDE */
+                               udc_ep0_set_rde(dev);
+                       }
+               } else {
+
+                       /* received number bytes */
+                       count = readl(&dev->ep[UDC_EP0OUT_IX].regs->sts);
+                       count = AMD_GETBITS(count, UDC_EPSTS_RX_PKT_SIZE);
+                       /* out data for fifo mode not working */
+                       count = 0;
+
+                       /* 0 packet or real data ? */
+                       if (count != 0) {
+                               ret_val |= udc_data_out_isr(dev, UDC_EP0OUT_IX);
+                       } else {
+                               /* dummy read confirm */
+                               readl(&dev->ep[UDC_EP0OUT_IX].regs->confirm);
+                               ret_val = IRQ_HANDLED;
+                       }
+               }
+       }
+
+       /* check pending CNAKS */
+       if (cnak_pending) {
+               /* CNAk processing when rxfifo empty only */
+               if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY))
+                       udc_process_cnak_queue(dev);
+       }
+
+finished:
+       return ret_val;
+}
+
+/* Interrupt handler for Control IN traffic */
+static irqreturn_t udc_control_in_isr(struct udc *dev)
+{
+       irqreturn_t ret_val = IRQ_NONE;
+       u32 tmp;
+       struct udc_ep *ep;
+       struct udc_request *req;
+       unsigned len;
+
+       ep = &dev->ep[UDC_EP0IN_IX];
+
+       /* clear irq */
+       writel(AMD_BIT(UDC_EPINT_IN_EP0), &dev->regs->ep_irqsts);
+
+       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->sts);
+       /* DMA completion */
+       if (tmp & AMD_BIT(UDC_EPSTS_TDC)) {
+               VDBG(dev, "isr: TDC clear\n");
+               ret_val = IRQ_HANDLED;
+
+               /* clear TDC bit */
+               writel(AMD_BIT(UDC_EPSTS_TDC),
+                               &dev->ep[UDC_EP0IN_IX].regs->sts);
+
+       /* status reg has IN bit set ? */
+       } else if (tmp & AMD_BIT(UDC_EPSTS_IN)) {
+               ret_val = IRQ_HANDLED;
+
+               if (ep->dma) {
+                       /* clear IN bit */
+                       writel(AMD_BIT(UDC_EPSTS_IN),
+                               &dev->ep[UDC_EP0IN_IX].regs->sts);
+               }
+               if (dev->stall_ep0in) {
+                       DBG(dev, "stall ep0in\n");
+                       /* halt ep0in */
+                       tmp = readl(&ep->regs->ctl);
+                       tmp |= AMD_BIT(UDC_EPCTL_S);
+                       writel(tmp, &ep->regs->ctl);
+               } else {
+                       if (!list_empty(&ep->queue)) {
+                               /* next request */
+                               req = list_entry(ep->queue.next,
+                                               struct udc_request, queue);
+
+                               if (ep->dma) {
+                                       /* write desc pointer */
+                                       writel(req->td_phys, &ep->regs->desptr);
+                                       /* set HOST READY */
+                                       req->td_data->status =
+                                               AMD_ADDBITS(
+                                               req->td_data->status,
+                                               UDC_DMA_STP_STS_BS_HOST_READY,
+                                               UDC_DMA_STP_STS_BS);
+
+                                       /* set poll demand bit */
+                                       tmp =
+                                       readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
+                                       tmp |= AMD_BIT(UDC_EPCTL_P);
+                                       writel(tmp,
+                                       &dev->ep[UDC_EP0IN_IX].regs->ctl);
+
+                                       /* all bytes will be transferred */
+                                       req->req.actual = req->req.length;
+
+                                       /* complete req */
+                                       complete_req(ep, req, 0);
+
+                               } else {
+                                       /* write fifo */
+                                       udc_txfifo_write(ep, &req->req);
+
+                                       /* lengh bytes transferred */
+                                       len = req->req.length - req->req.actual;
+                                       if (len > ep->ep.maxpacket)
+                                               len = ep->ep.maxpacket;
+
+                                       req->req.actual += len;
+                                       if (req->req.actual == req->req.length
+                                               || (len != ep->ep.maxpacket)) {
+                                               /* complete req */
+                                               complete_req(ep, req, 0);
+                                       }
+                               }
+
+                       }
+               }
+               ep->halted = 0;
+               dev->stall_ep0in = 0;
+               if (!ep->dma) {
+                       /* clear IN bit */
+                       writel(AMD_BIT(UDC_EPSTS_IN),
+                               &dev->ep[UDC_EP0IN_IX].regs->sts);
+               }
+       }
+
+       return ret_val;
+}
+
+
+/* Interrupt handler for global device events */
+static irqreturn_t udc_dev_isr(struct udc *dev, u32 dev_irq)
+__releases(dev->lock)
+__acquires(dev->lock)
+{
+       irqreturn_t ret_val = IRQ_NONE;
+       u32 tmp;
+       u32 cfg;
+       struct udc_ep *ep;
+       u16 i;
+       u8 udc_csr_epix;
+
+       /* SET_CONFIG irq ? */
+       if (dev_irq & AMD_BIT(UDC_DEVINT_SC)) {
+               ret_val = IRQ_HANDLED;
+
+               /* read config value */
+               tmp = readl(&dev->regs->sts);
+               cfg = AMD_GETBITS(tmp, UDC_DEVSTS_CFG);
+               DBG(dev, "SET_CONFIG interrupt: config=%d\n", cfg);
+               dev->cur_config = cfg;
+               dev->set_cfg_not_acked = 1;
+
+               /* make usb request for gadget driver */
+               memset(&setup_data, 0 , sizeof(union udc_setup_data));
+               setup_data.request.bRequest = USB_REQ_SET_CONFIGURATION;
+               setup_data.request.wValue = cpu_to_le16(dev->cur_config);
+
+               /* programm the NE registers */
+               for (i = 0; i < UDC_EP_NUM; i++) {
+                       ep = &dev->ep[i];
+                       if (ep->in) {
+
+                               /* ep ix in UDC CSR register space */
+                               udc_csr_epix = ep->num;
+
+
+                       /* OUT ep */
+                       } else {
+                               /* ep ix in UDC CSR register space */
+                               udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS;
+                       }
+
+                       tmp = readl(&dev->csr->ne[udc_csr_epix]);
+                       /* ep cfg */
+                       tmp = AMD_ADDBITS(tmp, ep->dev->cur_config,
+                                               UDC_CSR_NE_CFG);
+                       /* write reg */
+                       writel(tmp, &dev->csr->ne[udc_csr_epix]);
+
+                       /* clear stall bits */
+                       ep->halted = 0;
+                       tmp = readl(&ep->regs->ctl);
+                       tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S);
+                       writel(tmp, &ep->regs->ctl);
+               }
+               /* call gadget zero with setup data received */
+               spin_unlock(&dev->lock);
+               tmp = dev->driver->setup(&dev->gadget, &setup_data.request);
+               spin_lock(&dev->lock);
+
+       } /* SET_INTERFACE ? */
+       if (dev_irq & AMD_BIT(UDC_DEVINT_SI)) {
+               ret_val = IRQ_HANDLED;
+
+               dev->set_cfg_not_acked = 1;
+               /* read interface and alt setting values */
+               tmp = readl(&dev->regs->sts);
+               dev->cur_alt = AMD_GETBITS(tmp, UDC_DEVSTS_ALT);
+               dev->cur_intf = AMD_GETBITS(tmp, UDC_DEVSTS_INTF);
+
+               /* make usb request for gadget driver */
+               memset(&setup_data, 0 , sizeof(union udc_setup_data));
+               setup_data.request.bRequest = USB_REQ_SET_INTERFACE;
+               setup_data.request.bRequestType = USB_RECIP_INTERFACE;
+               setup_data.request.wValue = cpu_to_le16(dev->cur_alt);
+               setup_data.request.wIndex = cpu_to_le16(dev->cur_intf);
+
+               DBG(dev, "SET_INTERFACE interrupt: alt=%d intf=%d\n",
+                               dev->cur_alt, dev->cur_intf);
+
+               /* programm the NE registers */
+               for (i = 0; i < UDC_EP_NUM; i++) {
+                       ep = &dev->ep[i];
+                       if (ep->in) {
+
+                               /* ep ix in UDC CSR register space */
+                               udc_csr_epix = ep->num;
+
+
+                       /* OUT ep */
+                       } else {
+                               /* ep ix in UDC CSR register space */
+                               udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS;
+                       }
+
+                       /* UDC CSR reg */
+                       /* set ep values */
+                       tmp = readl(&dev->csr->ne[udc_csr_epix]);
+                       /* ep interface */
+                       tmp = AMD_ADDBITS(tmp, ep->dev->cur_intf,
+                                               UDC_CSR_NE_INTF);
+                       /* tmp = AMD_ADDBITS(tmp, 2, UDC_CSR_NE_INTF); */
+                       /* ep alt */
+                       tmp = AMD_ADDBITS(tmp, ep->dev->cur_alt,
+                                               UDC_CSR_NE_ALT);
+                       /* write reg */
+                       writel(tmp, &dev->csr->ne[udc_csr_epix]);
+
+                       /* clear stall bits */
+                       ep->halted = 0;
+                       tmp = readl(&ep->regs->ctl);
+                       tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S);
+                       writel(tmp, &ep->regs->ctl);
+               }
+
+               /* call gadget zero with setup data received */
+               spin_unlock(&dev->lock);
+               tmp = dev->driver->setup(&dev->gadget, &setup_data.request);
+               spin_lock(&dev->lock);
+
+       } /* USB reset */
+       if (dev_irq & AMD_BIT(UDC_DEVINT_UR)) {
+               DBG(dev, "USB Reset interrupt\n");
+               ret_val = IRQ_HANDLED;
+
+               /* allow soft reset when suspend occurs */
+               soft_reset_occured = 0;
+
+               dev->waiting_zlp_ack_ep0in = 0;
+               dev->set_cfg_not_acked = 0;
+
+               /* mask not needed interrupts */
+               udc_mask_unused_interrupts(dev);
+
+               /* call gadget to resume and reset configs etc. */
+               spin_unlock(&dev->lock);
+               if (dev->sys_suspended && dev->driver->resume) {
+                       dev->driver->resume(&dev->gadget);
+                       dev->sys_suspended = 0;
+               }
+               dev->driver->disconnect(&dev->gadget);
+               spin_lock(&dev->lock);
+
+               /* disable ep0 to empty req queue */
+               empty_req_queue(&dev->ep[UDC_EP0IN_IX]);
+               ep_init(dev->regs, &dev->ep[UDC_EP0IN_IX]);
+
+               /* soft reset when rxfifo not empty */
+               tmp = readl(&dev->regs->sts);
+               if (!(tmp & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY))
+                               && !soft_reset_after_usbreset_occured) {
+                       udc_soft_reset(dev);
+                       soft_reset_after_usbreset_occured++;
+               }
+
+               /*
+                * DMA reset to kill potential old DMA hw hang,
+                * POLL bit is already reset by ep_init() through
+                * disconnect()
+                */
+               DBG(dev, "DMA machine reset\n");
+               tmp = readl(&dev->regs->cfg);
+               writel(tmp | AMD_BIT(UDC_DEVCFG_DMARST), &dev->regs->cfg);
+               writel(tmp, &dev->regs->cfg);
+
+               /* put into initial config */
+               udc_basic_init(dev);
+
+               /* enable device setup interrupts */
+               udc_enable_dev_setup_interrupts(dev);
+
+               /* enable suspend interrupt */
+               tmp = readl(&dev->regs->irqmsk);
+               tmp &= AMD_UNMASK_BIT(UDC_DEVINT_US);
+               writel(tmp, &dev->regs->irqmsk);
+
+       } /* USB suspend */
+       if (dev_irq & AMD_BIT(UDC_DEVINT_US)) {
+               DBG(dev, "USB Suspend interrupt\n");
+               ret_val = IRQ_HANDLED;
+               if (dev->driver->suspend) {
+                       spin_unlock(&dev->lock);
+                       dev->sys_suspended = 1;
+                       dev->driver->suspend(&dev->gadget);
+                       spin_lock(&dev->lock);
+               }
+       } /* new speed ? */
+       if (dev_irq & AMD_BIT(UDC_DEVINT_ENUM)) {
+               DBG(dev, "ENUM interrupt\n");
+               ret_val = IRQ_HANDLED;
+               soft_reset_after_usbreset_occured = 0;
+
+               /* disable ep0 to empty req queue */
+               empty_req_queue(&dev->ep[UDC_EP0IN_IX]);
+               ep_init(dev->regs, &dev->ep[UDC_EP0IN_IX]);
+
+               /* link up all endpoints */
+               udc_setup_endpoints(dev);
+               dev_info(&dev->pdev->dev, "Connect: %s\n",
+                        usb_speed_string(dev->gadget.speed));
+
+               /* init ep 0 */
+               activate_control_endpoints(dev);
+
+               /* enable ep0 interrupts */
+               udc_enable_ep0_interrupts(dev);
+       }
+       /* session valid change interrupt */
+       if (dev_irq & AMD_BIT(UDC_DEVINT_SVC)) {
+               DBG(dev, "USB SVC interrupt\n");
+               ret_val = IRQ_HANDLED;
+
+               /* check that session is not valid to detect disconnect */
+               tmp = readl(&dev->regs->sts);
+               if (!(tmp & AMD_BIT(UDC_DEVSTS_SESSVLD))) {
+                       /* disable suspend interrupt */
+                       tmp = readl(&dev->regs->irqmsk);
+                       tmp |= AMD_BIT(UDC_DEVINT_US);
+                       writel(tmp, &dev->regs->irqmsk);
+                       DBG(dev, "USB Disconnect (session valid low)\n");
+                       /* cleanup on disconnect */
+                       usb_disconnect(udc);
+               }
+
+       }
+
+       return ret_val;
+}
+
+/* Interrupt Service Routine, see Linux Kernel Doc for parameters */
+static irqreturn_t udc_irq(int irq, void *pdev)
+{
+       struct udc *dev = pdev;
+       u32 reg;
+       u16 i;
+       u32 ep_irq;
+       irqreturn_t ret_val = IRQ_NONE;
+
+       spin_lock(&dev->lock);
+
+       /* check for ep irq */
+       reg = readl(&dev->regs->ep_irqsts);
+       if (reg) {
+               if (reg & AMD_BIT(UDC_EPINT_OUT_EP0))
+                       ret_val |= udc_control_out_isr(dev);
+               if (reg & AMD_BIT(UDC_EPINT_IN_EP0))
+                       ret_val |= udc_control_in_isr(dev);
+
+               /*
+                * data endpoint
+                * iterate ep's
+                */
+               for (i = 1; i < UDC_EP_NUM; i++) {
+                       ep_irq = 1 << i;
+                       if (!(reg & ep_irq) || i == UDC_EPINT_OUT_EP0)
+                               continue;
+
+                       /* clear irq status */
+                       writel(ep_irq, &dev->regs->ep_irqsts);
+
+                       /* irq for out ep ? */
+                       if (i > UDC_EPIN_NUM)
+                               ret_val |= udc_data_out_isr(dev, i);
+                       else
+                               ret_val |= udc_data_in_isr(dev, i);
+               }
+
+       }
+
+
+       /* check for dev irq */
+       reg = readl(&dev->regs->irqsts);
+       if (reg) {
+               /* clear irq */
+               writel(reg, &dev->regs->irqsts);
+               ret_val |= udc_dev_isr(dev, reg);
+       }
+
+
+       spin_unlock(&dev->lock);
+       return ret_val;
+}
+
+/* Tears down device */
+static void gadget_release(struct device *pdev)
+{
+       struct amd5536udc *dev = dev_get_drvdata(pdev);
+       kfree(dev);
+}
+
+/* Cleanup on device remove */
+static void udc_remove(struct udc *dev)
+{
+       /* remove timer */
+       stop_timer++;
+       if (timer_pending(&udc_timer))
+               wait_for_completion(&on_exit);
+       if (udc_timer.data)
+               del_timer_sync(&udc_timer);
+       /* remove pollstall timer */
+       stop_pollstall_timer++;
+       if (timer_pending(&udc_pollstall_timer))
+               wait_for_completion(&on_pollstall_exit);
+       if (udc_pollstall_timer.data)
+               del_timer_sync(&udc_pollstall_timer);
+       udc = NULL;
+}
+
+/* Reset all pci context */
+static void udc_pci_remove(struct pci_dev *pdev)
+{
+       struct udc              *dev;
+
+       dev = pci_get_drvdata(pdev);
+
+       usb_del_gadget_udc(&udc->gadget);
+       /* gadget driver must not be registered */
+       BUG_ON(dev->driver != NULL);
+
+       /* dma pool cleanup */
+       if (dev->data_requests)
+               pci_pool_destroy(dev->data_requests);
+
+       if (dev->stp_requests) {
+               /* cleanup DMA desc's for ep0in */
+               pci_pool_free(dev->stp_requests,
+                       dev->ep[UDC_EP0OUT_IX].td_stp,
+                       dev->ep[UDC_EP0OUT_IX].td_stp_dma);
+               pci_pool_free(dev->stp_requests,
+                       dev->ep[UDC_EP0OUT_IX].td,
+                       dev->ep[UDC_EP0OUT_IX].td_phys);
+
+               pci_pool_destroy(dev->stp_requests);
+       }
+
+       /* reset controller */
+       writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
+       if (dev->irq_registered)
+               free_irq(pdev->irq, dev);
+       if (dev->regs)
+               iounmap(dev->regs);
+       if (dev->mem_region)
+               release_mem_region(pci_resource_start(pdev, 0),
+                               pci_resource_len(pdev, 0));
+       if (dev->active)
+               pci_disable_device(pdev);
+
+       udc_remove(dev);
+}
+
+/* create dma pools on init */
+static int init_dma_pools(struct udc *dev)
+{
+       struct udc_stp_dma      *td_stp;
+       struct udc_data_dma     *td_data;
+       int retval;
+
+       /* consistent DMA mode setting ? */
+       if (use_dma_ppb) {
+               use_dma_bufferfill_mode = 0;
+       } else {
+               use_dma_ppb_du = 0;
+               use_dma_bufferfill_mode = 1;
+       }
+
+       /* DMA setup */
+       dev->data_requests = dma_pool_create("data_requests", NULL,
+               sizeof(struct udc_data_dma), 0, 0);
+       if (!dev->data_requests) {
+               DBG(dev, "can't get request data pool\n");
+               retval = -ENOMEM;
+               goto finished;
+       }
+
+       /* EP0 in dma regs = dev control regs */
+       dev->ep[UDC_EP0IN_IX].dma = &dev->regs->ctl;
+
+       /* dma desc for setup data */
+       dev->stp_requests = dma_pool_create("setup requests", NULL,
+               sizeof(struct udc_stp_dma), 0, 0);
+       if (!dev->stp_requests) {
+               DBG(dev, "can't get stp request pool\n");
+               retval = -ENOMEM;
+               goto finished;
+       }
+       /* setup */
+       td_stp = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
+                               &dev->ep[UDC_EP0OUT_IX].td_stp_dma);
+       if (td_stp == NULL) {
+               retval = -ENOMEM;
+               goto finished;
+       }
+       dev->ep[UDC_EP0OUT_IX].td_stp = td_stp;
+
+       /* data: 0 packets !? */
+       td_data = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
+                               &dev->ep[UDC_EP0OUT_IX].td_phys);
+       if (td_data == NULL) {
+               retval = -ENOMEM;
+               goto finished;
+       }
+       dev->ep[UDC_EP0OUT_IX].td = td_data;
+       return 0;
+
+finished:
+       return retval;
+}
+
+/* Called by pci bus driver to init pci context */
+static int udc_pci_probe(
+       struct pci_dev *pdev,
+       const struct pci_device_id *id
+)
+{
+       struct udc              *dev;
+       unsigned long           resource;
+       unsigned long           len;
+       int                     retval = 0;
+
+       /* one udc only */
+       if (udc) {
+               dev_dbg(&pdev->dev, "already probed\n");
+               return -EBUSY;
+       }
+
+       /* init */
+       dev = kzalloc(sizeof(struct udc), GFP_KERNEL);
+       if (!dev) {
+               retval = -ENOMEM;
+               goto finished;
+       }
+
+       /* pci setup */
+       if (pci_enable_device(pdev) < 0) {
+               kfree(dev);
+               dev = NULL;
+               retval = -ENODEV;
+               goto finished;
+       }
+       dev->active = 1;
+
+       /* PCI resource allocation */
+       resource = pci_resource_start(pdev, 0);
+       len = pci_resource_len(pdev, 0);
+
+       if (!request_mem_region(resource, len, name)) {
+               dev_dbg(&pdev->dev, "pci device used already\n");
+               kfree(dev);
+               dev = NULL;
+               retval = -EBUSY;
+               goto finished;
+       }
+       dev->mem_region = 1;
+
+       dev->virt_addr = ioremap_nocache(resource, len);
+       if (dev->virt_addr == NULL) {
+               dev_dbg(&pdev->dev, "start address cannot be mapped\n");
+               kfree(dev);
+               dev = NULL;
+               retval = -EFAULT;
+               goto finished;
+       }
+
+       if (!pdev->irq) {
+               dev_err(&pdev->dev, "irq not set\n");
+               kfree(dev);
+               dev = NULL;
+               retval = -ENODEV;
+               goto finished;
+       }
+
+       spin_lock_init(&dev->lock);
+       /* udc csr registers base */
+       dev->csr = dev->virt_addr + UDC_CSR_ADDR;
+       /* dev registers base */
+       dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR;
+       /* ep registers base */
+       dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR;
+       /* fifo's base */
+       dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR);
+       dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR);
+
+       if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
+               dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq);
+               kfree(dev);
+               dev = NULL;
+               retval = -EBUSY;
+               goto finished;
+       }
+       dev->irq_registered = 1;
+
+       pci_set_drvdata(pdev, dev);
+
+       /* chip revision for Hs AMD5536 */
+       dev->chiprev = pdev->revision;
+
+       pci_set_master(pdev);
+       pci_try_set_mwi(pdev);
+
+       /* init dma pools */
+       if (use_dma) {
+               retval = init_dma_pools(dev);
+               if (retval != 0)
+                       goto finished;
+       }
+
+       dev->phys_addr = resource;
+       dev->irq = pdev->irq;
+       dev->pdev = pdev;
+
+       /* general probing */
+       if (udc_probe(dev) == 0)
+               return 0;
+
+finished:
+       if (dev)
+               udc_pci_remove(pdev);
+       return retval;
+}
+
+/* general probe */
+static int udc_probe(struct udc *dev)
+{
+       char            tmp[128];
+       u32             reg;
+       int             retval;
+
+       /* mark timer as not initialized */
+       udc_timer.data = 0;
+       udc_pollstall_timer.data = 0;
+
+       /* device struct setup */
+       dev->gadget.ops = &udc_ops;
+
+       dev_set_name(&dev->gadget.dev, "gadget");
+       dev->gadget.name = name;
+       dev->gadget.max_speed = USB_SPEED_HIGH;
+
+       /* init registers, interrupts, ... */
+       startup_registers(dev);
+
+       dev_info(&dev->pdev->dev, "%s\n", mod_desc);
+
+       snprintf(tmp, sizeof tmp, "%d", dev->irq);
+       dev_info(&dev->pdev->dev,
+               "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
+               tmp, dev->phys_addr, dev->chiprev,
+               (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1");
+       strcpy(tmp, UDC_DRIVER_VERSION_STRING);
+       if (dev->chiprev == UDC_HSA0_REV) {
+               dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
+               retval = -ENODEV;
+               goto finished;
+       }
+       dev_info(&dev->pdev->dev,
+               "driver version: %s(for Geode5536 B1)\n", tmp);
+       udc = dev;
+
+       retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
+                       gadget_release);
+       if (retval)
+               goto finished;
+
+       /* timer init */
+       init_timer(&udc_timer);
+       udc_timer.function = udc_timer_function;
+       udc_timer.data = 1;
+       /* timer pollstall init */
+       init_timer(&udc_pollstall_timer);
+       udc_pollstall_timer.function = udc_pollstall_timer_function;
+       udc_pollstall_timer.data = 1;
+
+       /* set SD */
+       reg = readl(&dev->regs->ctl);
+       reg |= AMD_BIT(UDC_DEVCTL_SD);
+       writel(reg, &dev->regs->ctl);
+
+       /* print dev register info */
+       print_regs(dev);
+
+       return 0;
+
+finished:
+       return retval;
+}
+
+/* Initiates a remote wakeup */
+static int udc_remote_wakeup(struct udc *dev)
+{
+       unsigned long flags;
+       u32 tmp;
+
+       DBG(dev, "UDC initiates remote wakeup\n");
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       tmp = readl(&dev->regs->ctl);
+       tmp |= AMD_BIT(UDC_DEVCTL_RES);
+       writel(tmp, &dev->regs->ctl);
+       tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES);
+       writel(tmp, &dev->regs->ctl);
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+       return 0;
+}
+
+/* PCI device parameters */
+static const struct pci_device_id pci_id[] = {
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096),
+               .class =        (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class_mask =   0xffffffff,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(pci, pci_id);
+
+/* PCI functions */
+static struct pci_driver udc_pci_driver = {
+       .name =         (char *) name,
+       .id_table =     pci_id,
+       .probe =        udc_pci_probe,
+       .remove =       udc_pci_remove,
+};
+
+module_pci_driver(udc_pci_driver);
+
+MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION);
+MODULE_AUTHOR("Thomas Dahlmann");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/gadget/udc/amd5536udc.h b/drivers/usb/gadget/udc/amd5536udc.h
new file mode 100644 (file)
index 0000000..6744d3b
--- /dev/null
@@ -0,0 +1,617 @@
+/*
+ * amd5536.h -- header for AMD 5536 UDC high/full speed USB device controller
+ *
+ * Copyright (C) 2007 AMD (http://www.amd.com)
+ * Author: Thomas Dahlmann
+ *
+ * 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.
+ */
+
+#ifndef AMD5536UDC_H
+#define AMD5536UDC_H
+
+/* various constants */
+#define UDC_RDE_TIMER_SECONDS          1
+#define UDC_RDE_TIMER_DIV              10
+#define UDC_POLLSTALL_TIMER_USECONDS   500
+
+/* Hs AMD5536 chip rev. */
+#define UDC_HSA0_REV 1
+#define UDC_HSB1_REV 2
+
+/*
+ * SETUP usb commands
+ * needed, because some SETUP's are handled in hw, but must be passed to
+ * gadget driver above
+ * SET_CONFIG
+ */
+#define UDC_SETCONFIG_DWORD0                   0x00000900
+#define UDC_SETCONFIG_DWORD0_VALUE_MASK                0xffff0000
+#define UDC_SETCONFIG_DWORD0_VALUE_OFS         16
+
+#define UDC_SETCONFIG_DWORD1                   0x00000000
+
+/* SET_INTERFACE */
+#define UDC_SETINTF_DWORD0                     0x00000b00
+#define UDC_SETINTF_DWORD0_ALT_MASK            0xffff0000
+#define UDC_SETINTF_DWORD0_ALT_OFS             16
+
+#define UDC_SETINTF_DWORD1                     0x00000000
+#define UDC_SETINTF_DWORD1_INTF_MASK           0x0000ffff
+#define UDC_SETINTF_DWORD1_INTF_OFS            0
+
+/* Mass storage reset */
+#define UDC_MSCRES_DWORD0                      0x0000ff21
+#define UDC_MSCRES_DWORD1                      0x00000000
+
+/* Global CSR's -------------------------------------------------------------*/
+#define UDC_CSR_ADDR                           0x500
+
+/* EP NE bits */
+/* EP number */
+#define UDC_CSR_NE_NUM_MASK                    0x0000000f
+#define UDC_CSR_NE_NUM_OFS                     0
+/* EP direction */
+#define UDC_CSR_NE_DIR_MASK                    0x00000010
+#define UDC_CSR_NE_DIR_OFS                     4
+/* EP type */
+#define UDC_CSR_NE_TYPE_MASK                   0x00000060
+#define UDC_CSR_NE_TYPE_OFS                    5
+/* EP config number */
+#define UDC_CSR_NE_CFG_MASK                    0x00000780
+#define UDC_CSR_NE_CFG_OFS                     7
+/* EP interface number */
+#define UDC_CSR_NE_INTF_MASK                   0x00007800
+#define UDC_CSR_NE_INTF_OFS                    11
+/* EP alt setting */
+#define UDC_CSR_NE_ALT_MASK                    0x00078000
+#define UDC_CSR_NE_ALT_OFS                     15
+
+/* max pkt */
+#define UDC_CSR_NE_MAX_PKT_MASK                        0x3ff80000
+#define UDC_CSR_NE_MAX_PKT_OFS                 19
+
+/* Device Config Register ---------------------------------------------------*/
+#define UDC_DEVCFG_ADDR                                0x400
+
+#define UDC_DEVCFG_SOFTRESET                   31
+#define UDC_DEVCFG_HNPSFEN                     30
+#define UDC_DEVCFG_DMARST                      29
+#define UDC_DEVCFG_SET_DESC                    18
+#define UDC_DEVCFG_CSR_PRG                     17
+#define UDC_DEVCFG_STATUS                      7
+#define UDC_DEVCFG_DIR                         6
+#define UDC_DEVCFG_PI                          5
+#define UDC_DEVCFG_SS                          4
+#define UDC_DEVCFG_SP                          3
+#define UDC_DEVCFG_RWKP                                2
+
+#define UDC_DEVCFG_SPD_MASK                    0x3
+#define UDC_DEVCFG_SPD_OFS                     0
+#define UDC_DEVCFG_SPD_HS                      0x0
+#define UDC_DEVCFG_SPD_FS                      0x1
+#define UDC_DEVCFG_SPD_LS                      0x2
+/*#define UDC_DEVCFG_SPD_FS                    0x3*/
+
+
+/* Device Control Register --------------------------------------------------*/
+#define UDC_DEVCTL_ADDR                                0x404
+
+#define UDC_DEVCTL_THLEN_MASK                  0xff000000
+#define UDC_DEVCTL_THLEN_OFS                   24
+
+#define UDC_DEVCTL_BRLEN_MASK                  0x00ff0000
+#define UDC_DEVCTL_BRLEN_OFS                   16
+
+#define UDC_DEVCTL_CSR_DONE                    13
+#define UDC_DEVCTL_DEVNAK                      12
+#define UDC_DEVCTL_SD                          10
+#define UDC_DEVCTL_MODE                                9
+#define UDC_DEVCTL_BREN                                8
+#define UDC_DEVCTL_THE                         7
+#define UDC_DEVCTL_BF                          6
+#define UDC_DEVCTL_BE                          5
+#define UDC_DEVCTL_DU                          4
+#define UDC_DEVCTL_TDE                         3
+#define UDC_DEVCTL_RDE                         2
+#define UDC_DEVCTL_RES                         0
+
+
+/* Device Status Register ---------------------------------------------------*/
+#define UDC_DEVSTS_ADDR                                0x408
+
+#define UDC_DEVSTS_TS_MASK                     0xfffc0000
+#define UDC_DEVSTS_TS_OFS                      18
+
+#define UDC_DEVSTS_SESSVLD                     17
+#define UDC_DEVSTS_PHY_ERROR                   16
+#define UDC_DEVSTS_RXFIFO_EMPTY                        15
+
+#define UDC_DEVSTS_ENUM_SPEED_MASK             0x00006000
+#define UDC_DEVSTS_ENUM_SPEED_OFS              13
+#define UDC_DEVSTS_ENUM_SPEED_FULL             1
+#define UDC_DEVSTS_ENUM_SPEED_HIGH             0
+
+#define UDC_DEVSTS_SUSP                                12
+
+#define UDC_DEVSTS_ALT_MASK                    0x00000f00
+#define UDC_DEVSTS_ALT_OFS                     8
+
+#define UDC_DEVSTS_INTF_MASK                   0x000000f0
+#define UDC_DEVSTS_INTF_OFS                    4
+
+#define UDC_DEVSTS_CFG_MASK                    0x0000000f
+#define UDC_DEVSTS_CFG_OFS                     0
+
+
+/* Device Interrupt Register ------------------------------------------------*/
+#define UDC_DEVINT_ADDR                                0x40c
+
+#define UDC_DEVINT_SVC                         7
+#define UDC_DEVINT_ENUM                                6
+#define UDC_DEVINT_SOF                         5
+#define UDC_DEVINT_US                          4
+#define UDC_DEVINT_UR                          3
+#define UDC_DEVINT_ES                          2
+#define UDC_DEVINT_SI                          1
+#define UDC_DEVINT_SC                          0
+
+/* Device Interrupt Mask Register -------------------------------------------*/
+#define UDC_DEVINT_MSK_ADDR                    0x410
+
+#define UDC_DEVINT_MSK                         0x7f
+
+/* Endpoint Interrupt Register ----------------------------------------------*/
+#define UDC_EPINT_ADDR                         0x414
+
+#define UDC_EPINT_OUT_MASK                     0xffff0000
+#define UDC_EPINT_OUT_OFS                      16
+#define UDC_EPINT_IN_MASK                      0x0000ffff
+#define UDC_EPINT_IN_OFS                       0
+
+#define UDC_EPINT_IN_EP0                       0
+#define UDC_EPINT_IN_EP1                       1
+#define UDC_EPINT_IN_EP2                       2
+#define UDC_EPINT_IN_EP3                       3
+#define UDC_EPINT_OUT_EP0                      16
+#define UDC_EPINT_OUT_EP1                      17
+#define UDC_EPINT_OUT_EP2                      18
+#define UDC_EPINT_OUT_EP3                      19
+
+#define UDC_EPINT_EP0_ENABLE_MSK               0x001e001e
+
+/* Endpoint Interrupt Mask Register -----------------------------------------*/
+#define UDC_EPINT_MSK_ADDR                     0x418
+
+#define UDC_EPINT_OUT_MSK_MASK                 0xffff0000
+#define UDC_EPINT_OUT_MSK_OFS                  16
+#define UDC_EPINT_IN_MSK_MASK                  0x0000ffff
+#define UDC_EPINT_IN_MSK_OFS                   0
+
+#define UDC_EPINT_MSK_DISABLE_ALL              0xffffffff
+/* mask non-EP0 endpoints */
+#define UDC_EPDATAINT_MSK_DISABLE              0xfffefffe
+/* mask all dev interrupts */
+#define UDC_DEV_MSK_DISABLE                    0x7f
+
+/* Endpoint-specific CSR's --------------------------------------------------*/
+#define UDC_EPREGS_ADDR                                0x0
+#define UDC_EPIN_REGS_ADDR                     0x0
+#define UDC_EPOUT_REGS_ADDR                    0x200
+
+#define UDC_EPCTL_ADDR                         0x0
+
+#define UDC_EPCTL_RRDY                         9
+#define UDC_EPCTL_CNAK                         8
+#define UDC_EPCTL_SNAK                         7
+#define UDC_EPCTL_NAK                          6
+
+#define UDC_EPCTL_ET_MASK                      0x00000030
+#define UDC_EPCTL_ET_OFS                       4
+#define UDC_EPCTL_ET_CONTROL                   0
+#define UDC_EPCTL_ET_ISO                       1
+#define UDC_EPCTL_ET_BULK                      2
+#define UDC_EPCTL_ET_INTERRUPT                 3
+
+#define UDC_EPCTL_P                            3
+#define UDC_EPCTL_SN                           2
+#define UDC_EPCTL_F                            1
+#define UDC_EPCTL_S                            0
+
+/* Endpoint Status Registers ------------------------------------------------*/
+#define UDC_EPSTS_ADDR                         0x4
+
+#define UDC_EPSTS_RX_PKT_SIZE_MASK             0x007ff800
+#define UDC_EPSTS_RX_PKT_SIZE_OFS              11
+
+#define UDC_EPSTS_TDC                          10
+#define UDC_EPSTS_HE                           9
+#define UDC_EPSTS_BNA                          7
+#define UDC_EPSTS_IN                           6
+
+#define UDC_EPSTS_OUT_MASK                     0x00000030
+#define UDC_EPSTS_OUT_OFS                      4
+#define UDC_EPSTS_OUT_DATA                     1
+#define UDC_EPSTS_OUT_DATA_CLEAR               0x10
+#define UDC_EPSTS_OUT_SETUP                    2
+#define UDC_EPSTS_OUT_SETUP_CLEAR              0x20
+#define UDC_EPSTS_OUT_CLEAR                    0x30
+
+/* Endpoint Buffer Size IN/ Receive Packet Frame Number OUT Registers ------*/
+#define UDC_EPIN_BUFF_SIZE_ADDR                        0x8
+#define UDC_EPOUT_FRAME_NUMBER_ADDR            0x8
+
+#define UDC_EPIN_BUFF_SIZE_MASK                        0x0000ffff
+#define UDC_EPIN_BUFF_SIZE_OFS                 0
+/* EP0in txfifo = 128 bytes*/
+#define UDC_EPIN0_BUFF_SIZE                    32
+/* EP0in fullspeed txfifo = 128 bytes*/
+#define UDC_FS_EPIN0_BUFF_SIZE                 32
+
+/* fifo size mult = fifo size / max packet */
+#define UDC_EPIN_BUFF_SIZE_MULT                        2
+
+/* EPin data fifo size = 1024 bytes DOUBLE BUFFERING */
+#define UDC_EPIN_BUFF_SIZE                     256
+/* EPin small INT data fifo size = 128 bytes */
+#define UDC_EPIN_SMALLINT_BUFF_SIZE            32
+
+/* EPin fullspeed data fifo size = 128 bytes DOUBLE BUFFERING */
+#define UDC_FS_EPIN_BUFF_SIZE                  32
+
+#define UDC_EPOUT_FRAME_NUMBER_MASK            0x0000ffff
+#define UDC_EPOUT_FRAME_NUMBER_OFS             0
+
+/* Endpoint Buffer Size OUT/Max Packet Size Registers -----------------------*/
+#define UDC_EPOUT_BUFF_SIZE_ADDR               0x0c
+#define UDC_EP_MAX_PKT_SIZE_ADDR               0x0c
+
+#define UDC_EPOUT_BUFF_SIZE_MASK               0xffff0000
+#define UDC_EPOUT_BUFF_SIZE_OFS                        16
+#define UDC_EP_MAX_PKT_SIZE_MASK               0x0000ffff
+#define UDC_EP_MAX_PKT_SIZE_OFS                        0
+/* EP0in max packet size = 64 bytes */
+#define UDC_EP0IN_MAX_PKT_SIZE                 64
+/* EP0out max packet size = 64 bytes */
+#define UDC_EP0OUT_MAX_PKT_SIZE                        64
+/* EP0in fullspeed max packet size = 64 bytes */
+#define UDC_FS_EP0IN_MAX_PKT_SIZE              64
+/* EP0out fullspeed max packet size = 64 bytes */
+#define UDC_FS_EP0OUT_MAX_PKT_SIZE             64
+
+/*
+ * Endpoint dma descriptors ------------------------------------------------
+ *
+ * Setup data, Status dword
+ */
+#define UDC_DMA_STP_STS_CFG_MASK               0x0fff0000
+#define UDC_DMA_STP_STS_CFG_OFS                        16
+#define UDC_DMA_STP_STS_CFG_ALT_MASK           0x000f0000
+#define UDC_DMA_STP_STS_CFG_ALT_OFS            16
+#define UDC_DMA_STP_STS_CFG_INTF_MASK          0x00f00000
+#define UDC_DMA_STP_STS_CFG_INTF_OFS           20
+#define UDC_DMA_STP_STS_CFG_NUM_MASK           0x0f000000
+#define UDC_DMA_STP_STS_CFG_NUM_OFS            24
+#define UDC_DMA_STP_STS_RX_MASK                        0x30000000
+#define UDC_DMA_STP_STS_RX_OFS                 28
+#define UDC_DMA_STP_STS_BS_MASK                        0xc0000000
+#define UDC_DMA_STP_STS_BS_OFS                 30
+#define UDC_DMA_STP_STS_BS_HOST_READY          0
+#define UDC_DMA_STP_STS_BS_DMA_BUSY            1
+#define UDC_DMA_STP_STS_BS_DMA_DONE            2
+#define UDC_DMA_STP_STS_BS_HOST_BUSY           3
+/* IN data, Status dword */
+#define UDC_DMA_IN_STS_TXBYTES_MASK            0x0000ffff
+#define UDC_DMA_IN_STS_TXBYTES_OFS             0
+#define        UDC_DMA_IN_STS_FRAMENUM_MASK            0x07ff0000
+#define UDC_DMA_IN_STS_FRAMENUM_OFS            0
+#define UDC_DMA_IN_STS_L                       27
+#define UDC_DMA_IN_STS_TX_MASK                 0x30000000
+#define UDC_DMA_IN_STS_TX_OFS                  28
+#define UDC_DMA_IN_STS_BS_MASK                 0xc0000000
+#define UDC_DMA_IN_STS_BS_OFS                  30
+#define UDC_DMA_IN_STS_BS_HOST_READY           0
+#define UDC_DMA_IN_STS_BS_DMA_BUSY             1
+#define UDC_DMA_IN_STS_BS_DMA_DONE             2
+#define UDC_DMA_IN_STS_BS_HOST_BUSY            3
+/* OUT data, Status dword */
+#define UDC_DMA_OUT_STS_RXBYTES_MASK           0x0000ffff
+#define UDC_DMA_OUT_STS_RXBYTES_OFS            0
+#define UDC_DMA_OUT_STS_FRAMENUM_MASK          0x07ff0000
+#define UDC_DMA_OUT_STS_FRAMENUM_OFS           0
+#define UDC_DMA_OUT_STS_L                      27
+#define UDC_DMA_OUT_STS_RX_MASK                        0x30000000
+#define UDC_DMA_OUT_STS_RX_OFS                 28
+#define UDC_DMA_OUT_STS_BS_MASK                        0xc0000000
+#define UDC_DMA_OUT_STS_BS_OFS                 30
+#define UDC_DMA_OUT_STS_BS_HOST_READY          0
+#define UDC_DMA_OUT_STS_BS_DMA_BUSY            1
+#define UDC_DMA_OUT_STS_BS_DMA_DONE            2
+#define UDC_DMA_OUT_STS_BS_HOST_BUSY           3
+/* max ep0in packet */
+#define UDC_EP0IN_MAXPACKET                    1000
+/* max dma packet */
+#define UDC_DMA_MAXPACKET                      65536
+
+/* un-usable DMA address */
+#define DMA_DONT_USE                           (~(dma_addr_t) 0 )
+
+/* other Endpoint register addresses and values-----------------------------*/
+#define UDC_EP_SUBPTR_ADDR                     0x10
+#define UDC_EP_DESPTR_ADDR                     0x14
+#define UDC_EP_WRITE_CONFIRM_ADDR              0x1c
+
+/* EP number as layouted in AHB space */
+#define UDC_EP_NUM                             32
+#define UDC_EPIN_NUM                           16
+#define UDC_EPIN_NUM_USED                      5
+#define UDC_EPOUT_NUM                          16
+/* EP number of EP's really used = EP0 + 8 data EP's */
+#define UDC_USED_EP_NUM                                9
+/* UDC CSR regs are aligned but AHB regs not - offset for OUT EP's */
+#define UDC_CSR_EP_OUT_IX_OFS                  12
+
+#define UDC_EP0OUT_IX                          16
+#define UDC_EP0IN_IX                           0
+
+/* Rx fifo address and size = 1k -------------------------------------------*/
+#define UDC_RXFIFO_ADDR                                0x800
+#define UDC_RXFIFO_SIZE                                0x400
+
+/* Tx fifo address and size = 1.5k -----------------------------------------*/
+#define UDC_TXFIFO_ADDR                                0xc00
+#define UDC_TXFIFO_SIZE                                0x600
+
+/* default data endpoints --------------------------------------------------*/
+#define UDC_EPIN_STATUS_IX                     1
+#define UDC_EPIN_IX                            2
+#define UDC_EPOUT_IX                           18
+
+/* general constants -------------------------------------------------------*/
+#define UDC_DWORD_BYTES                                4
+#define UDC_BITS_PER_BYTE_SHIFT                        3
+#define UDC_BYTE_MASK                          0xff
+#define UDC_BITS_PER_BYTE                      8
+
+/*---------------------------------------------------------------------------*/
+/* UDC CSR's */
+struct udc_csrs {
+
+       /* sca - setup command address */
+       u32 sca;
+
+       /* ep ne's */
+       u32 ne[UDC_USED_EP_NUM];
+} __attribute__ ((packed));
+
+/* AHB subsystem CSR registers */
+struct udc_regs {
+
+       /* device configuration */
+       u32 cfg;
+
+       /* device control */
+       u32 ctl;
+
+       /* device status */
+       u32 sts;
+
+       /* device interrupt */
+       u32 irqsts;
+
+       /* device interrupt mask */
+       u32 irqmsk;
+
+       /* endpoint interrupt */
+       u32 ep_irqsts;
+
+       /* endpoint interrupt mask */
+       u32 ep_irqmsk;
+} __attribute__ ((packed));
+
+/* endpoint specific registers */
+struct udc_ep_regs {
+
+       /* endpoint control */
+       u32 ctl;
+
+       /* endpoint status */
+       u32 sts;
+
+       /* endpoint buffer size in/ receive packet frame number out */
+       u32 bufin_framenum;
+
+       /* endpoint buffer size out/max packet size */
+       u32 bufout_maxpkt;
+
+       /* endpoint setup buffer pointer */
+       u32 subptr;
+
+       /* endpoint data descriptor pointer */
+       u32 desptr;
+
+       /* reserverd */
+       u32 reserved;
+
+       /* write/read confirmation */
+       u32 confirm;
+
+} __attribute__ ((packed));
+
+/* control data DMA desc */
+struct udc_stp_dma {
+       /* status quadlet */
+       u32     status;
+       /* reserved */
+       u32     _reserved;
+       /* first setup word */
+       u32     data12;
+       /* second setup word */
+       u32     data34;
+} __attribute__ ((aligned (16)));
+
+/* normal data DMA desc */
+struct udc_data_dma {
+       /* status quadlet */
+       u32     status;
+       /* reserved */
+       u32     _reserved;
+       /* buffer pointer */
+       u32     bufptr;
+       /* next descriptor pointer */
+       u32     next;
+} __attribute__ ((aligned (16)));
+
+/* request packet */
+struct udc_request {
+       /* embedded gadget ep */
+       struct usb_request              req;
+
+       /* flags */
+       unsigned                        dma_going : 1,
+                                       dma_done : 1;
+       /* phys. address */
+       dma_addr_t                      td_phys;
+       /* first dma desc. of chain */
+       struct udc_data_dma             *td_data;
+       /* last dma desc. of chain */
+       struct udc_data_dma             *td_data_last;
+       struct list_head                queue;
+
+       /* chain length */
+       unsigned                        chain_len;
+
+};
+
+/* UDC specific endpoint parameters */
+struct udc_ep {
+       struct usb_ep                   ep;
+       struct udc_ep_regs __iomem      *regs;
+       u32 __iomem                     *txfifo;
+       u32 __iomem                     *dma;
+       dma_addr_t                      td_phys;
+       dma_addr_t                      td_stp_dma;
+       struct udc_stp_dma              *td_stp;
+       struct udc_data_dma             *td;
+       /* temp request */
+       struct udc_request              *req;
+       unsigned                        req_used;
+       unsigned                        req_completed;
+       /* dummy DMA desc for BNA dummy */
+       struct udc_request              *bna_dummy_req;
+       unsigned                        bna_occurred;
+
+       /* NAK state */
+       unsigned                        naking;
+
+       struct udc                      *dev;
+
+       /* queue for requests */
+       struct list_head                queue;
+       unsigned                        halted;
+       unsigned                        cancel_transfer;
+       unsigned                        num : 5,
+                                       fifo_depth : 14,
+                                       in : 1;
+};
+
+/* device struct */
+struct udc {
+       struct usb_gadget               gadget;
+       spinlock_t                      lock;   /* protects all state */
+       /* all endpoints */
+       struct udc_ep                   ep[UDC_EP_NUM];
+       struct usb_gadget_driver        *driver;
+       /* operational flags */
+       unsigned                        active : 1,
+                                       stall_ep0in : 1,
+                                       waiting_zlp_ack_ep0in : 1,
+                                       set_cfg_not_acked : 1,
+                                       irq_registered : 1,
+                                       data_ep_enabled : 1,
+                                       data_ep_queued : 1,
+                                       mem_region : 1,
+                                       sys_suspended : 1,
+                                       connected;
+
+       u16                             chiprev;
+
+       /* registers */
+       struct pci_dev                  *pdev;
+       struct udc_csrs __iomem         *csr;
+       struct udc_regs __iomem         *regs;
+       struct udc_ep_regs __iomem      *ep_regs;
+       u32 __iomem                     *rxfifo;
+       u32 __iomem                     *txfifo;
+
+       /* DMA desc pools */
+       struct pci_pool                 *data_requests;
+       struct pci_pool                 *stp_requests;
+
+       /* device data */
+       unsigned long                   phys_addr;
+       void __iomem                    *virt_addr;
+       unsigned                        irq;
+
+       /* states */
+       u16                             cur_config;
+       u16                             cur_intf;
+       u16                             cur_alt;
+};
+
+#define to_amd5536_udc(g)      (container_of((g), struct udc, gadget))
+
+/* setup request data */
+union udc_setup_data {
+       u32                     data[2];
+       struct usb_ctrlrequest  request;
+};
+
+/*
+ *---------------------------------------------------------------------------
+ * SET and GET bitfields in u32 values
+ * via constants for mask/offset:
+ * <bit_field_stub_name> is the text between
+ * UDC_ and _MASK|_OFS of appropriate
+ * constant
+ *
+ * set bitfield value in u32 u32Val
+ */
+#define AMD_ADDBITS(u32Val, bitfield_val, bitfield_stub_name)          \
+       (((u32Val) & (((u32) ~((u32) bitfield_stub_name##_MASK))))      \
+       | (((bitfield_val) << ((u32) bitfield_stub_name##_OFS))         \
+               & ((u32) bitfield_stub_name##_MASK)))
+
+/*
+ * set bitfield value in zero-initialized u32 u32Val
+ * => bitfield bits in u32Val are all zero
+ */
+#define AMD_INIT_SETBITS(u32Val, bitfield_val, bitfield_stub_name)     \
+       ((u32Val)                                                       \
+       | (((bitfield_val) << ((u32) bitfield_stub_name##_OFS))         \
+               & ((u32) bitfield_stub_name##_MASK)))
+
+/* get bitfield value from u32 u32Val */
+#define AMD_GETBITS(u32Val, bitfield_stub_name)                                \
+       ((u32Val & ((u32) bitfield_stub_name##_MASK))                   \
+               >> ((u32) bitfield_stub_name##_OFS))
+
+/* SET and GET bits in u32 values ------------------------------------------*/
+#define AMD_BIT(bit_stub_name) (1 << bit_stub_name)
+#define AMD_UNMASK_BIT(bit_stub_name) (~AMD_BIT(bit_stub_name))
+#define AMD_CLEAR_BIT(bit_stub_name) (~AMD_BIT(bit_stub_name))
+
+/* debug macros ------------------------------------------------------------*/
+
+#define DBG(udc , args...)     dev_dbg(&(udc)->pdev->dev, args)
+
+#ifdef UDC_VERBOSE
+#define VDBG                   DBG
+#else
+#define VDBG(udc , args...)    do {} while (0)
+#endif
+
+#endif /* #ifdef AMD5536UDC_H */
diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c
new file mode 100644 (file)
index 0000000..cfd18bc
--- /dev/null
@@ -0,0 +1,1985 @@
+/*
+ * at91_udc -- driver for at91-series USB peripheral controller
+ *
+ * Copyright (C) 2004 by Thomas Rathbone
+ * Copyright (C) 2005 by HP Labs
+ * Copyright (C) 2005 by David Brownell
+ *
+ * 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.
+ */
+
+#undef VERBOSE_DEBUG
+#undef PACKET_TRACE
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/prefetch.h>
+#include <linux/clk.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_data/atmel.h>
+
+#include <asm/byteorder.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/gpio.h>
+
+#include <mach/cpu.h>
+#include <mach/at91sam9261_matrix.h>
+#include <mach/at91_matrix.h>
+
+#include "at91_udc.h"
+
+
+/*
+ * This controller is simple and PIO-only.  It's used in many AT91-series
+ * full speed USB controllers, including the at91rm9200 (arm920T, with MMU),
+ * at91sam926x (arm926ejs, with MMU), and several no-mmu versions.
+ *
+ * This driver expects the board has been wired with two GPIOs supporting
+ * a VBUS sensing IRQ, and a D+ pullup.  (They may be omitted, but the
+ * testing hasn't covered such cases.)
+ *
+ * The pullup is most important (so it's integrated on sam926x parts).  It
+ * provides software control over whether the host enumerates the device.
+ *
+ * The VBUS sensing helps during enumeration, and allows both USB clocks
+ * (and the transceiver) to stay gated off until they're necessary, saving
+ * power.  During USB suspend, the 48 MHz clock is gated off in hardware;
+ * it may also be gated off by software during some Linux sleep states.
+ */
+
+#define        DRIVER_VERSION  "3 May 2006"
+
+static const char driver_name [] = "at91_udc";
+static const char ep0name[] = "ep0";
+
+#define VBUS_POLL_TIMEOUT      msecs_to_jiffies(1000)
+
+#define at91_udp_read(udc, reg) \
+       __raw_readl((udc)->udp_baseaddr + (reg))
+#define at91_udp_write(udc, reg, val) \
+       __raw_writel((val), (udc)->udp_baseaddr + (reg))
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+#include <linux/seq_file.h>
+
+static const char debug_filename[] = "driver/udc";
+
+#define FOURBITS "%s%s%s%s"
+#define EIGHTBITS FOURBITS FOURBITS
+
+static void proc_ep_show(struct seq_file *s, struct at91_ep *ep)
+{
+       static char             *types[] = {
+               "control", "out-iso", "out-bulk", "out-int",
+               "BOGUS",   "in-iso",  "in-bulk",  "in-int"};
+
+       u32                     csr;
+       struct at91_request     *req;
+       unsigned long   flags;
+       struct at91_udc *udc = ep->udc;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       csr = __raw_readl(ep->creg);
+
+       /* NOTE:  not collecting per-endpoint irq statistics... */
+
+       seq_printf(s, "\n");
+       seq_printf(s, "%s, maxpacket %d %s%s %s%s\n",
+                       ep->ep.name, ep->ep.maxpacket,
+                       ep->is_in ? "in" : "out",
+                       ep->is_iso ? " iso" : "",
+                       ep->is_pingpong
+                               ? (ep->fifo_bank ? "pong" : "ping")
+                               : "",
+                       ep->stopped ? " stopped" : "");
+       seq_printf(s, "csr %08x rxbytes=%d %s %s %s" EIGHTBITS "\n",
+               csr,
+               (csr & 0x07ff0000) >> 16,
+               (csr & (1 << 15)) ? "enabled" : "disabled",
+               (csr & (1 << 11)) ? "DATA1" : "DATA0",
+               types[(csr & 0x700) >> 8],
+
+               /* iff type is control then print current direction */
+               (!(csr & 0x700))
+                       ? ((csr & (1 << 7)) ? " IN" : " OUT")
+                       : "",
+               (csr & (1 << 6)) ? " rxdatabk1" : "",
+               (csr & (1 << 5)) ? " forcestall" : "",
+               (csr & (1 << 4)) ? " txpktrdy" : "",
+
+               (csr & (1 << 3)) ? " stallsent" : "",
+               (csr & (1 << 2)) ? " rxsetup" : "",
+               (csr & (1 << 1)) ? " rxdatabk0" : "",
+               (csr & (1 << 0)) ? " txcomp" : "");
+       if (list_empty (&ep->queue))
+               seq_printf(s, "\t(queue empty)\n");
+
+       else list_for_each_entry (req, &ep->queue, queue) {
+               unsigned        length = req->req.actual;
+
+               seq_printf(s, "\treq %p len %d/%d buf %p\n",
+                               &req->req, length,
+                               req->req.length, req->req.buf);
+       }
+       spin_unlock_irqrestore(&udc->lock, flags);
+}
+
+static void proc_irq_show(struct seq_file *s, const char *label, u32 mask)
+{
+       int i;
+
+       seq_printf(s, "%s %04x:%s%s" FOURBITS, label, mask,
+               (mask & (1 << 13)) ? " wakeup" : "",
+               (mask & (1 << 12)) ? " endbusres" : "",
+
+               (mask & (1 << 11)) ? " sofint" : "",
+               (mask & (1 << 10)) ? " extrsm" : "",
+               (mask & (1 << 9)) ? " rxrsm" : "",
+               (mask & (1 << 8)) ? " rxsusp" : "");
+       for (i = 0; i < 8; i++) {
+               if (mask & (1 << i))
+                       seq_printf(s, " ep%d", i);
+       }
+       seq_printf(s, "\n");
+}
+
+static int proc_udc_show(struct seq_file *s, void *unused)
+{
+       struct at91_udc *udc = s->private;
+       struct at91_ep  *ep;
+       u32             tmp;
+
+       seq_printf(s, "%s: version %s\n", driver_name, DRIVER_VERSION);
+
+       seq_printf(s, "vbus %s, pullup %s, %s powered%s, gadget %s\n\n",
+               udc->vbus ? "present" : "off",
+               udc->enabled
+                       ? (udc->vbus ? "active" : "enabled")
+                       : "disabled",
+               udc->selfpowered ? "self" : "VBUS",
+               udc->suspended ? ", suspended" : "",
+               udc->driver ? udc->driver->driver.name : "(none)");
+
+       /* don't access registers when interface isn't clocked */
+       if (!udc->clocked) {
+               seq_printf(s, "(not clocked)\n");
+               return 0;
+       }
+
+       tmp = at91_udp_read(udc, AT91_UDP_FRM_NUM);
+       seq_printf(s, "frame %05x:%s%s frame=%d\n", tmp,
+               (tmp & AT91_UDP_FRM_OK) ? " ok" : "",
+               (tmp & AT91_UDP_FRM_ERR) ? " err" : "",
+               (tmp & AT91_UDP_NUM));
+
+       tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+       seq_printf(s, "glbstate %02x:%s" FOURBITS "\n", tmp,
+               (tmp & AT91_UDP_RMWUPE) ? " rmwupe" : "",
+               (tmp & AT91_UDP_RSMINPR) ? " rsminpr" : "",
+               (tmp & AT91_UDP_ESR) ? " esr" : "",
+               (tmp & AT91_UDP_CONFG) ? " confg" : "",
+               (tmp & AT91_UDP_FADDEN) ? " fadden" : "");
+
+       tmp = at91_udp_read(udc, AT91_UDP_FADDR);
+       seq_printf(s, "faddr   %03x:%s fadd=%d\n", tmp,
+               (tmp & AT91_UDP_FEN) ? " fen" : "",
+               (tmp & AT91_UDP_FADD));
+
+       proc_irq_show(s, "imr   ", at91_udp_read(udc, AT91_UDP_IMR));
+       proc_irq_show(s, "isr   ", at91_udp_read(udc, AT91_UDP_ISR));
+
+       if (udc->enabled && udc->vbus) {
+               proc_ep_show(s, &udc->ep[0]);
+               list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) {
+                       if (ep->ep.desc)
+                               proc_ep_show(s, ep);
+               }
+       }
+       return 0;
+}
+
+static int proc_udc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, proc_udc_show, PDE_DATA(inode));
+}
+
+static const struct file_operations proc_ops = {
+       .owner          = THIS_MODULE,
+       .open           = proc_udc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static void create_debug_file(struct at91_udc *udc)
+{
+       udc->pde = proc_create_data(debug_filename, 0, NULL, &proc_ops, udc);
+}
+
+static void remove_debug_file(struct at91_udc *udc)
+{
+       if (udc->pde)
+               remove_proc_entry(debug_filename, NULL);
+}
+
+#else
+
+static inline void create_debug_file(struct at91_udc *udc) {}
+static inline void remove_debug_file(struct at91_udc *udc) {}
+
+#endif
+
+
+/*-------------------------------------------------------------------------*/
+
+static void done(struct at91_ep *ep, struct at91_request *req, int status)
+{
+       unsigned        stopped = ep->stopped;
+       struct at91_udc *udc = ep->udc;
+
+       list_del_init(&req->queue);
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+       else
+               status = req->req.status;
+       if (status && status != -ESHUTDOWN)
+               VDBG("%s done %p, status %d\n", ep->ep.name, req, status);
+
+       ep->stopped = 1;
+       spin_unlock(&udc->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&udc->lock);
+       ep->stopped = stopped;
+
+       /* ep0 is always ready; other endpoints need a non-empty queue */
+       if (list_empty(&ep->queue) && ep->int_mask != (1 << 0))
+               at91_udp_write(udc, AT91_UDP_IDR, ep->int_mask);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* bits indicating OUT fifo has data ready */
+#define        RX_DATA_READY   (AT91_UDP_RX_DATA_BK0 | AT91_UDP_RX_DATA_BK1)
+
+/*
+ * Endpoint FIFO CSR bits have a mix of bits, making it unsafe to just write
+ * back most of the value you just read (because of side effects, including
+ * bits that may change after reading and before writing).
+ *
+ * Except when changing a specific bit, always write values which:
+ *  - clear SET_FX bits (setting them could change something)
+ *  - set CLR_FX bits (clearing them could change something)
+ *
+ * There are also state bits like FORCESTALL, EPEDS, DIR, and EPTYPE
+ * that shouldn't normally be changed.
+ *
+ * NOTE at91sam9260 docs mention synch between UDPCK and MCK clock domains,
+ * implying a need to wait for one write to complete (test relevant bits)
+ * before starting the next write.  This shouldn't be an issue given how
+ * infrequently we write, except maybe for write-then-read idioms.
+ */
+#define        SET_FX  (AT91_UDP_TXPKTRDY)
+#define        CLR_FX  (RX_DATA_READY | AT91_UDP_RXSETUP \
+               | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)
+
+/* pull OUT packet data from the endpoint's fifo */
+static int read_fifo (struct at91_ep *ep, struct at91_request *req)
+{
+       u32 __iomem     *creg = ep->creg;
+       u8 __iomem      *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
+       u32             csr;
+       u8              *buf;
+       unsigned int    count, bufferspace, is_done;
+
+       buf = req->req.buf + req->req.actual;
+       bufferspace = req->req.length - req->req.actual;
+
+       /*
+        * there might be nothing to read if ep_queue() calls us,
+        * or if we already emptied both pingpong buffers
+        */
+rescan:
+       csr = __raw_readl(creg);
+       if ((csr & RX_DATA_READY) == 0)
+               return 0;
+
+       count = (csr & AT91_UDP_RXBYTECNT) >> 16;
+       if (count > ep->ep.maxpacket)
+               count = ep->ep.maxpacket;
+       if (count > bufferspace) {
+               DBG("%s buffer overflow\n", ep->ep.name);
+               req->req.status = -EOVERFLOW;
+               count = bufferspace;
+       }
+       __raw_readsb(dreg, buf, count);
+
+       /* release and swap pingpong mem bank */
+       csr |= CLR_FX;
+       if (ep->is_pingpong) {
+               if (ep->fifo_bank == 0) {
+                       csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0);
+                       ep->fifo_bank = 1;
+               } else {
+                       csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK1);
+                       ep->fifo_bank = 0;
+               }
+       } else
+               csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0);
+       __raw_writel(csr, creg);
+
+       req->req.actual += count;
+       is_done = (count < ep->ep.maxpacket);
+       if (count == bufferspace)
+               is_done = 1;
+
+       PACKET("%s %p out/%d%s\n", ep->ep.name, &req->req, count,
+                       is_done ? " (done)" : "");
+
+       /*
+        * avoid extra trips through IRQ logic for packets already in
+        * the fifo ... maybe preventing an extra (expensive) OUT-NAK
+        */
+       if (is_done)
+               done(ep, req, 0);
+       else if (ep->is_pingpong) {
+               /*
+                * One dummy read to delay the code because of a HW glitch:
+                * CSR returns bad RXCOUNT when read too soon after updating
+                * RX_DATA_BK flags.
+                */
+               csr = __raw_readl(creg);
+
+               bufferspace -= count;
+               buf += count;
+               goto rescan;
+       }
+
+       return is_done;
+}
+
+/* load fifo for an IN packet */
+static int write_fifo(struct at91_ep *ep, struct at91_request *req)
+{
+       u32 __iomem     *creg = ep->creg;
+       u32             csr = __raw_readl(creg);
+       u8 __iomem      *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
+       unsigned        total, count, is_last;
+       u8              *buf;
+
+       /*
+        * TODO: allow for writing two packets to the fifo ... that'll
+        * reduce the amount of IN-NAKing, but probably won't affect
+        * throughput much.  (Unlike preventing OUT-NAKing!)
+        */
+
+       /*
+        * If ep_queue() calls us, the queue is empty and possibly in
+        * odd states like TXCOMP not yet cleared (we do it, saving at
+        * least one IRQ) or the fifo not yet being free.  Those aren't
+        * issues normally (IRQ handler fast path).
+        */
+       if (unlikely(csr & (AT91_UDP_TXCOMP | AT91_UDP_TXPKTRDY))) {
+               if (csr & AT91_UDP_TXCOMP) {
+                       csr |= CLR_FX;
+                       csr &= ~(SET_FX | AT91_UDP_TXCOMP);
+                       __raw_writel(csr, creg);
+                       csr = __raw_readl(creg);
+               }
+               if (csr & AT91_UDP_TXPKTRDY)
+                       return 0;
+       }
+
+       buf = req->req.buf + req->req.actual;
+       prefetch(buf);
+       total = req->req.length - req->req.actual;
+       if (ep->ep.maxpacket < total) {
+               count = ep->ep.maxpacket;
+               is_last = 0;
+       } else {
+               count = total;
+               is_last = (count < ep->ep.maxpacket) || !req->req.zero;
+       }
+
+       /*
+        * Write the packet, maybe it's a ZLP.
+        *
+        * NOTE:  incrementing req->actual before we receive the ACK means
+        * gadget driver IN bytecounts can be wrong in fault cases.  That's
+        * fixable with PIO drivers like this one (save "count" here, and
+        * do the increment later on TX irq), but not for most DMA hardware.
+        *
+        * So all gadget drivers must accept that potential error.  Some
+        * hardware supports precise fifo status reporting, letting them
+        * recover when the actual bytecount matters (e.g. for USB Test
+        * and Measurement Class devices).
+        */
+       __raw_writesb(dreg, buf, count);
+       csr &= ~SET_FX;
+       csr |= CLR_FX | AT91_UDP_TXPKTRDY;
+       __raw_writel(csr, creg);
+       req->req.actual += count;
+
+       PACKET("%s %p in/%d%s\n", ep->ep.name, &req->req, count,
+                       is_last ? " (done)" : "");
+       if (is_last)
+               done(ep, req, 0);
+       return is_last;
+}
+
+static void nuke(struct at91_ep *ep, int status)
+{
+       struct at91_request *req;
+
+       /* terminate any request in the queue */
+       ep->stopped = 1;
+       if (list_empty(&ep->queue))
+               return;
+
+       VDBG("%s %s\n", __func__, ep->ep.name);
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct at91_request, queue);
+               done(ep, req, status);
+       }
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int at91_ep_enable(struct usb_ep *_ep,
+                               const struct usb_endpoint_descriptor *desc)
+{
+       struct at91_ep  *ep = container_of(_ep, struct at91_ep, ep);
+       struct at91_udc *udc;
+       u16             maxpacket;
+       u32             tmp;
+       unsigned long   flags;
+
+       if (!_ep || !ep
+                       || !desc || _ep->name == ep0name
+                       || desc->bDescriptorType != USB_DT_ENDPOINT
+                       || (maxpacket = usb_endpoint_maxp(desc)) == 0
+                       || maxpacket > ep->maxpacket) {
+               DBG("bad ep or descriptor\n");
+               return -EINVAL;
+       }
+
+       udc = ep->udc;
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+               DBG("bogus device state\n");
+               return -ESHUTDOWN;
+       }
+
+       tmp = usb_endpoint_type(desc);
+       switch (tmp) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               DBG("only one control endpoint\n");
+               return -EINVAL;
+       case USB_ENDPOINT_XFER_INT:
+               if (maxpacket > 64)
+                       goto bogus_max;
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               switch (maxpacket) {
+               case 8:
+               case 16:
+               case 32:
+               case 64:
+                       goto ok;
+               }
+bogus_max:
+               DBG("bogus maxpacket %d\n", maxpacket);
+               return -EINVAL;
+       case USB_ENDPOINT_XFER_ISOC:
+               if (!ep->is_pingpong) {
+                       DBG("iso requires double buffering\n");
+                       return -EINVAL;
+               }
+               break;
+       }
+
+ok:
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /* initialize endpoint to match this descriptor */
+       ep->is_in = usb_endpoint_dir_in(desc);
+       ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC);
+       ep->stopped = 0;
+       if (ep->is_in)
+               tmp |= 0x04;
+       tmp <<= 8;
+       tmp |= AT91_UDP_EPEDS;
+       __raw_writel(tmp, ep->creg);
+
+       ep->ep.maxpacket = maxpacket;
+
+       /*
+        * reset/init endpoint fifo.  NOTE:  leaves fifo_bank alone,
+        * since endpoint resets don't reset hw pingpong state.
+        */
+       at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+       at91_udp_write(udc, AT91_UDP_RST_EP, 0);
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int at91_ep_disable (struct usb_ep * _ep)
+{
+       struct at91_ep  *ep = container_of(_ep, struct at91_ep, ep);
+       struct at91_udc *udc = ep->udc;
+       unsigned long   flags;
+
+       if (ep == &ep->udc->ep[0])
+               return -EINVAL;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       nuke(ep, -ESHUTDOWN);
+
+       /* restore the endpoint's pristine config */
+       ep->ep.desc = NULL;
+       ep->ep.maxpacket = ep->maxpacket;
+
+       /* reset fifos and endpoint */
+       if (ep->udc->clocked) {
+               at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+               at91_udp_write(udc, AT91_UDP_RST_EP, 0);
+               __raw_writel(0, ep->creg);
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+/*
+ * this is a PIO-only driver, so there's nothing
+ * interesting for request or buffer allocation.
+ */
+
+static struct usb_request *
+at91_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct at91_request *req;
+
+       req = kzalloc(sizeof (struct at91_request), gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+       return &req->req;
+}
+
+static void at91_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct at91_request *req;
+
+       req = container_of(_req, struct at91_request, req);
+       BUG_ON(!list_empty(&req->queue));
+       kfree(req);
+}
+
+static int at91_ep_queue(struct usb_ep *_ep,
+                       struct usb_request *_req, gfp_t gfp_flags)
+{
+       struct at91_request     *req;
+       struct at91_ep          *ep;
+       struct at91_udc         *udc;
+       int                     status;
+       unsigned long           flags;
+
+       req = container_of(_req, struct at91_request, req);
+       ep = container_of(_ep, struct at91_ep, ep);
+
+       if (!_req || !_req->complete
+                       || !_req->buf || !list_empty(&req->queue)) {
+               DBG("invalid request\n");
+               return -EINVAL;
+       }
+
+       if (!_ep || (!ep->ep.desc && ep->ep.name != ep0name)) {
+               DBG("invalid ep\n");
+               return -EINVAL;
+       }
+
+       udc = ep->udc;
+
+       if (!udc || !udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+               DBG("invalid device\n");
+               return -EINVAL;
+       }
+
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /* try to kickstart any empty and idle queue */
+       if (list_empty(&ep->queue) && !ep->stopped) {
+               int     is_ep0;
+
+               /*
+                * If this control request has a non-empty DATA stage, this
+                * will start that stage.  It works just like a non-control
+                * request (until the status stage starts, maybe early).
+                *
+                * If the data stage is empty, then this starts a successful
+                * IN/STATUS stage.  (Unsuccessful ones use set_halt.)
+                */
+               is_ep0 = (ep->ep.name == ep0name);
+               if (is_ep0) {
+                       u32     tmp;
+
+                       if (!udc->req_pending) {
+                               status = -EINVAL;
+                               goto done;
+                       }
+
+                       /*
+                        * defer changing CONFG until after the gadget driver
+                        * reconfigures the endpoints.
+                        */
+                       if (udc->wait_for_config_ack) {
+                               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+                               tmp ^= AT91_UDP_CONFG;
+                               VDBG("toggle config\n");
+                               at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
+                       }
+                       if (req->req.length == 0) {
+ep0_in_status:
+                               PACKET("ep0 in/status\n");
+                               status = 0;
+                               tmp = __raw_readl(ep->creg);
+                               tmp &= ~SET_FX;
+                               tmp |= CLR_FX | AT91_UDP_TXPKTRDY;
+                               __raw_writel(tmp, ep->creg);
+                               udc->req_pending = 0;
+                               goto done;
+                       }
+               }
+
+               if (ep->is_in)
+                       status = write_fifo(ep, req);
+               else {
+                       status = read_fifo(ep, req);
+
+                       /* IN/STATUS stage is otherwise triggered by irq */
+                       if (status && is_ep0)
+                               goto ep0_in_status;
+               }
+       } else
+               status = 0;
+
+       if (req && !status) {
+               list_add_tail (&req->queue, &ep->queue);
+               at91_udp_write(udc, AT91_UDP_IER, ep->int_mask);
+       }
+done:
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return (status < 0) ? status : 0;
+}
+
+static int at91_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct at91_ep          *ep;
+       struct at91_request     *req;
+       unsigned long           flags;
+       struct at91_udc         *udc;
+
+       ep = container_of(_ep, struct at91_ep, ep);
+       if (!_ep || ep->ep.name == ep0name)
+               return -EINVAL;
+
+       udc = ep->udc;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry (req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req) {
+               spin_unlock_irqrestore(&udc->lock, flags);
+               return -EINVAL;
+       }
+
+       done(ep, req, -ECONNRESET);
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int at91_ep_set_halt(struct usb_ep *_ep, int value)
+{
+       struct at91_ep  *ep = container_of(_ep, struct at91_ep, ep);
+       struct at91_udc *udc = ep->udc;
+       u32 __iomem     *creg;
+       u32             csr;
+       unsigned long   flags;
+       int             status = 0;
+
+       if (!_ep || ep->is_iso || !ep->udc->clocked)
+               return -EINVAL;
+
+       creg = ep->creg;
+       spin_lock_irqsave(&udc->lock, flags);
+
+       csr = __raw_readl(creg);
+
+       /*
+        * fail with still-busy IN endpoints, ensuring correct sequencing
+        * of data tx then stall.  note that the fifo rx bytecount isn't
+        * completely accurate as a tx bytecount.
+        */
+       if (ep->is_in && (!list_empty(&ep->queue) || (csr >> 16) != 0))
+               status = -EAGAIN;
+       else {
+               csr |= CLR_FX;
+               csr &= ~SET_FX;
+               if (value) {
+                       csr |= AT91_UDP_FORCESTALL;
+                       VDBG("halt %s\n", ep->ep.name);
+               } else {
+                       at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+                       at91_udp_write(udc, AT91_UDP_RST_EP, 0);
+                       csr &= ~AT91_UDP_FORCESTALL;
+               }
+               __raw_writel(csr, creg);
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return status;
+}
+
+static const struct usb_ep_ops at91_ep_ops = {
+       .enable         = at91_ep_enable,
+       .disable        = at91_ep_disable,
+       .alloc_request  = at91_ep_alloc_request,
+       .free_request   = at91_ep_free_request,
+       .queue          = at91_ep_queue,
+       .dequeue        = at91_ep_dequeue,
+       .set_halt       = at91_ep_set_halt,
+       /* there's only imprecise fifo status reporting */
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int at91_get_frame(struct usb_gadget *gadget)
+{
+       struct at91_udc *udc = to_udc(gadget);
+
+       if (!to_udc(gadget)->clocked)
+               return -EINVAL;
+       return at91_udp_read(udc, AT91_UDP_FRM_NUM) & AT91_UDP_NUM;
+}
+
+static int at91_wakeup(struct usb_gadget *gadget)
+{
+       struct at91_udc *udc = to_udc(gadget);
+       u32             glbstate;
+       int             status = -EINVAL;
+       unsigned long   flags;
+
+       DBG("%s\n", __func__ );
+       spin_lock_irqsave(&udc->lock, flags);
+
+       if (!udc->clocked || !udc->suspended)
+               goto done;
+
+       /* NOTE:  some "early versions" handle ESR differently ... */
+
+       glbstate = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+       if (!(glbstate & AT91_UDP_ESR))
+               goto done;
+       glbstate |= AT91_UDP_ESR;
+       at91_udp_write(udc, AT91_UDP_GLB_STAT, glbstate);
+
+done:
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return status;
+}
+
+/* reinit == restore initial software state */
+static void udc_reinit(struct at91_udc *udc)
+{
+       u32 i;
+
+       INIT_LIST_HEAD(&udc->gadget.ep_list);
+       INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
+
+       for (i = 0; i < NUM_ENDPOINTS; i++) {
+               struct at91_ep *ep = &udc->ep[i];
+
+               if (i != 0)
+                       list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+               ep->ep.desc = NULL;
+               ep->stopped = 0;
+               ep->fifo_bank = 0;
+               usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
+               ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i);
+               /* initialize one queue per endpoint */
+               INIT_LIST_HEAD(&ep->queue);
+       }
+}
+
+static void stop_activity(struct at91_udc *udc)
+{
+       struct usb_gadget_driver *driver = udc->driver;
+       int i;
+
+       if (udc->gadget.speed == USB_SPEED_UNKNOWN)
+               driver = NULL;
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       udc->suspended = 0;
+
+       for (i = 0; i < NUM_ENDPOINTS; i++) {
+               struct at91_ep *ep = &udc->ep[i];
+               ep->stopped = 1;
+               nuke(ep, -ESHUTDOWN);
+       }
+       if (driver) {
+               spin_unlock(&udc->lock);
+               driver->disconnect(&udc->gadget);
+               spin_lock(&udc->lock);
+       }
+
+       udc_reinit(udc);
+}
+
+static void clk_on(struct at91_udc *udc)
+{
+       if (udc->clocked)
+               return;
+       udc->clocked = 1;
+
+       if (IS_ENABLED(CONFIG_COMMON_CLK)) {
+               clk_set_rate(udc->uclk, 48000000);
+               clk_prepare_enable(udc->uclk);
+       }
+       clk_prepare_enable(udc->iclk);
+       clk_prepare_enable(udc->fclk);
+}
+
+static void clk_off(struct at91_udc *udc)
+{
+       if (!udc->clocked)
+               return;
+       udc->clocked = 0;
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       clk_disable_unprepare(udc->fclk);
+       clk_disable_unprepare(udc->iclk);
+       if (IS_ENABLED(CONFIG_COMMON_CLK))
+               clk_disable_unprepare(udc->uclk);
+}
+
+/*
+ * activate/deactivate link with host; minimize power usage for
+ * inactive links by cutting clocks and transceiver power.
+ */
+static void pullup(struct at91_udc *udc, int is_on)
+{
+       int     active = !udc->board.pullup_active_low;
+
+       if (!udc->enabled || !udc->vbus)
+               is_on = 0;
+       DBG("%sactive\n", is_on ? "" : "in");
+
+       if (is_on) {
+               clk_on(udc);
+               at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
+               at91_udp_write(udc, AT91_UDP_TXVC, 0);
+               if (cpu_is_at91rm9200())
+                       gpio_set_value(udc->board.pullup_pin, active);
+               else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
+                       u32     txvc = at91_udp_read(udc, AT91_UDP_TXVC);
+
+                       txvc |= AT91_UDP_TXVC_PUON;
+                       at91_udp_write(udc, AT91_UDP_TXVC, txvc);
+               } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
+                       u32     usbpucr;
+
+                       usbpucr = at91_matrix_read(AT91_MATRIX_USBPUCR);
+                       usbpucr |= AT91_MATRIX_USBPUCR_PUON;
+                       at91_matrix_write(AT91_MATRIX_USBPUCR, usbpucr);
+               }
+       } else {
+               stop_activity(udc);
+               at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
+               at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
+               if (cpu_is_at91rm9200())
+                       gpio_set_value(udc->board.pullup_pin, !active);
+               else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
+                       u32     txvc = at91_udp_read(udc, AT91_UDP_TXVC);
+
+                       txvc &= ~AT91_UDP_TXVC_PUON;
+                       at91_udp_write(udc, AT91_UDP_TXVC, txvc);
+               } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
+                       u32     usbpucr;
+
+                       usbpucr = at91_matrix_read(AT91_MATRIX_USBPUCR);
+                       usbpucr &= ~AT91_MATRIX_USBPUCR_PUON;
+                       at91_matrix_write(AT91_MATRIX_USBPUCR, usbpucr);
+               }
+               clk_off(udc);
+       }
+}
+
+/* vbus is here!  turn everything on that's ready */
+static int at91_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+       struct at91_udc *udc = to_udc(gadget);
+       unsigned long   flags;
+
+       /* VDBG("vbus %s\n", is_active ? "on" : "off"); */
+       spin_lock_irqsave(&udc->lock, flags);
+       udc->vbus = (is_active != 0);
+       if (udc->driver)
+               pullup(udc, is_active);
+       else
+               pullup(udc, 0);
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int at91_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct at91_udc *udc = to_udc(gadget);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       udc->enabled = is_on = !!is_on;
+       pullup(udc, is_on);
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on)
+{
+       struct at91_udc *udc = to_udc(gadget);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       udc->selfpowered = (is_on != 0);
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int at91_start(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver);
+static int at91_stop(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver);
+static const struct usb_gadget_ops at91_udc_ops = {
+       .get_frame              = at91_get_frame,
+       .wakeup                 = at91_wakeup,
+       .set_selfpowered        = at91_set_selfpowered,
+       .vbus_session           = at91_vbus_session,
+       .pullup                 = at91_pullup,
+       .udc_start              = at91_start,
+       .udc_stop               = at91_stop,
+
+       /*
+        * VBUS-powered devices may also also want to support bigger
+        * power budgets after an appropriate SET_CONFIGURATION.
+        */
+       /* .vbus_power          = at91_vbus_power, */
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int handle_ep(struct at91_ep *ep)
+{
+       struct at91_request     *req;
+       u32 __iomem             *creg = ep->creg;
+       u32                     csr = __raw_readl(creg);
+
+       if (!list_empty(&ep->queue))
+               req = list_entry(ep->queue.next,
+                       struct at91_request, queue);
+       else
+               req = NULL;
+
+       if (ep->is_in) {
+               if (csr & (AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)) {
+                       csr |= CLR_FX;
+                       csr &= ~(SET_FX | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP);
+                       __raw_writel(csr, creg);
+               }
+               if (req)
+                       return write_fifo(ep, req);
+
+       } else {
+               if (csr & AT91_UDP_STALLSENT) {
+                       /* STALLSENT bit == ISOERR */
+                       if (ep->is_iso && req)
+                               req->req.status = -EILSEQ;
+                       csr |= CLR_FX;
+                       csr &= ~(SET_FX | AT91_UDP_STALLSENT);
+                       __raw_writel(csr, creg);
+                       csr = __raw_readl(creg);
+               }
+               if (req && (csr & RX_DATA_READY))
+                       return read_fifo(ep, req);
+       }
+       return 0;
+}
+
+union setup {
+       u8                      raw[8];
+       struct usb_ctrlrequest  r;
+};
+
+static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
+{
+       u32 __iomem     *creg = ep->creg;
+       u8 __iomem      *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
+       unsigned        rxcount, i = 0;
+       u32             tmp;
+       union setup     pkt;
+       int             status = 0;
+
+       /* read and ack SETUP; hard-fail for bogus packets */
+       rxcount = (csr & AT91_UDP_RXBYTECNT) >> 16;
+       if (likely(rxcount == 8)) {
+               while (rxcount--)
+                       pkt.raw[i++] = __raw_readb(dreg);
+               if (pkt.r.bRequestType & USB_DIR_IN) {
+                       csr |= AT91_UDP_DIR;
+                       ep->is_in = 1;
+               } else {
+                       csr &= ~AT91_UDP_DIR;
+                       ep->is_in = 0;
+               }
+       } else {
+               /* REVISIT this happens sometimes under load; why?? */
+               ERR("SETUP len %d, csr %08x\n", rxcount, csr);
+               status = -EINVAL;
+       }
+       csr |= CLR_FX;
+       csr &= ~(SET_FX | AT91_UDP_RXSETUP);
+       __raw_writel(csr, creg);
+       udc->wait_for_addr_ack = 0;
+       udc->wait_for_config_ack = 0;
+       ep->stopped = 0;
+       if (unlikely(status != 0))
+               goto stall;
+
+#define w_index                le16_to_cpu(pkt.r.wIndex)
+#define w_value                le16_to_cpu(pkt.r.wValue)
+#define w_length       le16_to_cpu(pkt.r.wLength)
+
+       VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n",
+                       pkt.r.bRequestType, pkt.r.bRequest,
+                       w_value, w_index, w_length);
+
+       /*
+        * A few standard requests get handled here, ones that touch
+        * hardware ... notably for device and endpoint features.
+        */
+       udc->req_pending = 1;
+       csr = __raw_readl(creg);
+       csr |= CLR_FX;
+       csr &= ~SET_FX;
+       switch ((pkt.r.bRequestType << 8) | pkt.r.bRequest) {
+
+       case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+                       | USB_REQ_SET_ADDRESS:
+               __raw_writel(csr | AT91_UDP_TXPKTRDY, creg);
+               udc->addr = w_value;
+               udc->wait_for_addr_ack = 1;
+               udc->req_pending = 0;
+               /* FADDR is set later, when we ack host STATUS */
+               return;
+
+       case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+                       | USB_REQ_SET_CONFIGURATION:
+               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_CONFG;
+               if (pkt.r.wValue)
+                       udc->wait_for_config_ack = (tmp == 0);
+               else
+                       udc->wait_for_config_ack = (tmp != 0);
+               if (udc->wait_for_config_ack)
+                       VDBG("wait for config\n");
+               /* CONFG is toggled later, if gadget driver succeeds */
+               break;
+
+       /*
+        * Hosts may set or clear remote wakeup status, and
+        * devices may report they're VBUS powered.
+        */
+       case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+                       | USB_REQ_GET_STATUS:
+               tmp = (udc->selfpowered << USB_DEVICE_SELF_POWERED);
+               if (at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_ESR)
+                       tmp |= (1 << USB_DEVICE_REMOTE_WAKEUP);
+               PACKET("get device status\n");
+               __raw_writeb(tmp, dreg);
+               __raw_writeb(0, dreg);
+               goto write_in;
+               /* then STATUS starts later, automatically */
+       case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+                       | USB_REQ_SET_FEATURE:
+               if (w_value != USB_DEVICE_REMOTE_WAKEUP)
+                       goto stall;
+               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+               tmp |= AT91_UDP_ESR;
+               at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
+               goto succeed;
+       case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+                       | USB_REQ_CLEAR_FEATURE:
+               if (w_value != USB_DEVICE_REMOTE_WAKEUP)
+                       goto stall;
+               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+               tmp &= ~AT91_UDP_ESR;
+               at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
+               goto succeed;
+
+       /*
+        * Interfaces have no feature settings; this is pretty useless.
+        * we won't even insist the interface exists...
+        */
+       case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8)
+                       | USB_REQ_GET_STATUS:
+               PACKET("get interface status\n");
+               __raw_writeb(0, dreg);
+               __raw_writeb(0, dreg);
+               goto write_in;
+               /* then STATUS starts later, automatically */
+       case ((USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8)
+                       | USB_REQ_SET_FEATURE:
+       case ((USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8)
+                       | USB_REQ_CLEAR_FEATURE:
+               goto stall;
+
+       /*
+        * Hosts may clear bulk/intr endpoint halt after the gadget
+        * driver sets it (not widely used); or set it (for testing)
+        */
+       case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8)
+                       | USB_REQ_GET_STATUS:
+               tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
+               ep = &udc->ep[tmp];
+               if (tmp >= NUM_ENDPOINTS || (tmp && !ep->ep.desc))
+                       goto stall;
+
+               if (tmp) {
+                       if ((w_index & USB_DIR_IN)) {
+                               if (!ep->is_in)
+                                       goto stall;
+                       } else if (ep->is_in)
+                               goto stall;
+               }
+               PACKET("get %s status\n", ep->ep.name);
+               if (__raw_readl(ep->creg) & AT91_UDP_FORCESTALL)
+                       tmp = (1 << USB_ENDPOINT_HALT);
+               else
+                       tmp = 0;
+               __raw_writeb(tmp, dreg);
+               __raw_writeb(0, dreg);
+               goto write_in;
+               /* then STATUS starts later, automatically */
+       case ((USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8)
+                       | USB_REQ_SET_FEATURE:
+               tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
+               ep = &udc->ep[tmp];
+               if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
+                       goto stall;
+               if (!ep->ep.desc || ep->is_iso)
+                       goto stall;
+               if ((w_index & USB_DIR_IN)) {
+                       if (!ep->is_in)
+                               goto stall;
+               } else if (ep->is_in)
+                       goto stall;
+
+               tmp = __raw_readl(ep->creg);
+               tmp &= ~SET_FX;
+               tmp |= CLR_FX | AT91_UDP_FORCESTALL;
+               __raw_writel(tmp, ep->creg);
+               goto succeed;
+       case ((USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8)
+                       | USB_REQ_CLEAR_FEATURE:
+               tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
+               ep = &udc->ep[tmp];
+               if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
+                       goto stall;
+               if (tmp == 0)
+                       goto succeed;
+               if (!ep->ep.desc || ep->is_iso)
+                       goto stall;
+               if ((w_index & USB_DIR_IN)) {
+                       if (!ep->is_in)
+                               goto stall;
+               } else if (ep->is_in)
+                       goto stall;
+
+               at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+               at91_udp_write(udc, AT91_UDP_RST_EP, 0);
+               tmp = __raw_readl(ep->creg);
+               tmp |= CLR_FX;
+               tmp &= ~(SET_FX | AT91_UDP_FORCESTALL);
+               __raw_writel(tmp, ep->creg);
+               if (!list_empty(&ep->queue))
+                       handle_ep(ep);
+               goto succeed;
+       }
+
+#undef w_value
+#undef w_index
+#undef w_length
+
+       /* pass request up to the gadget driver */
+       if (udc->driver) {
+               spin_unlock(&udc->lock);
+               status = udc->driver->setup(&udc->gadget, &pkt.r);
+               spin_lock(&udc->lock);
+       }
+       else
+               status = -ENODEV;
+       if (status < 0) {
+stall:
+               VDBG("req %02x.%02x protocol STALL; stat %d\n",
+                               pkt.r.bRequestType, pkt.r.bRequest, status);
+               csr |= AT91_UDP_FORCESTALL;
+               __raw_writel(csr, creg);
+               udc->req_pending = 0;
+       }
+       return;
+
+succeed:
+       /* immediate successful (IN) STATUS after zero length DATA */
+       PACKET("ep0 in/status\n");
+write_in:
+       csr |= AT91_UDP_TXPKTRDY;
+       __raw_writel(csr, creg);
+       udc->req_pending = 0;
+}
+
+static void handle_ep0(struct at91_udc *udc)
+{
+       struct at91_ep          *ep0 = &udc->ep[0];
+       u32 __iomem             *creg = ep0->creg;
+       u32                     csr = __raw_readl(creg);
+       struct at91_request     *req;
+
+       if (unlikely(csr & AT91_UDP_STALLSENT)) {
+               nuke(ep0, -EPROTO);
+               udc->req_pending = 0;
+               csr |= CLR_FX;
+               csr &= ~(SET_FX | AT91_UDP_STALLSENT | AT91_UDP_FORCESTALL);
+               __raw_writel(csr, creg);
+               VDBG("ep0 stalled\n");
+               csr = __raw_readl(creg);
+       }
+       if (csr & AT91_UDP_RXSETUP) {
+               nuke(ep0, 0);
+               udc->req_pending = 0;
+               handle_setup(udc, ep0, csr);
+               return;
+       }
+
+       if (list_empty(&ep0->queue))
+               req = NULL;
+       else
+               req = list_entry(ep0->queue.next, struct at91_request, queue);
+
+       /* host ACKed an IN packet that we sent */
+       if (csr & AT91_UDP_TXCOMP) {
+               csr |= CLR_FX;
+               csr &= ~(SET_FX | AT91_UDP_TXCOMP);
+
+               /* write more IN DATA? */
+               if (req && ep0->is_in) {
+                       if (handle_ep(ep0))
+                               udc->req_pending = 0;
+
+               /*
+                * Ack after:
+                *  - last IN DATA packet (including GET_STATUS)
+                *  - IN/STATUS for OUT DATA
+                *  - IN/STATUS for any zero-length DATA stage
+                * except for the IN DATA case, the host should send
+                * an OUT status later, which we'll ack.
+                */
+               } else {
+                       udc->req_pending = 0;
+                       __raw_writel(csr, creg);
+
+                       /*
+                        * SET_ADDRESS takes effect only after the STATUS
+                        * (to the original address) gets acked.
+                        */
+                       if (udc->wait_for_addr_ack) {
+                               u32     tmp;
+
+                               at91_udp_write(udc, AT91_UDP_FADDR,
+                                               AT91_UDP_FEN | udc->addr);
+                               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+                               tmp &= ~AT91_UDP_FADDEN;
+                               if (udc->addr)
+                                       tmp |= AT91_UDP_FADDEN;
+                               at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
+
+                               udc->wait_for_addr_ack = 0;
+                               VDBG("address %d\n", udc->addr);
+                       }
+               }
+       }
+
+       /* OUT packet arrived ... */
+       else if (csr & AT91_UDP_RX_DATA_BK0) {
+               csr |= CLR_FX;
+               csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0);
+
+               /* OUT DATA stage */
+               if (!ep0->is_in) {
+                       if (req) {
+                               if (handle_ep(ep0)) {
+                                       /* send IN/STATUS */
+                                       PACKET("ep0 in/status\n");
+                                       csr = __raw_readl(creg);
+                                       csr &= ~SET_FX;
+                                       csr |= CLR_FX | AT91_UDP_TXPKTRDY;
+                                       __raw_writel(csr, creg);
+                                       udc->req_pending = 0;
+                               }
+                       } else if (udc->req_pending) {
+                               /*
+                                * AT91 hardware has a hard time with this
+                                * "deferred response" mode for control-OUT
+                                * transfers.  (For control-IN it's fine.)
+                                *
+                                * The normal solution leaves OUT data in the
+                                * fifo until the gadget driver is ready.
+                                * We couldn't do that here without disabling
+                                * the IRQ that tells about SETUP packets,
+                                * e.g. when the host gets impatient...
+                                *
+                                * Working around it by copying into a buffer
+                                * would almost be a non-deferred response,
+                                * except that it wouldn't permit reliable
+                                * stalling of the request.  Instead, demand
+                                * that gadget drivers not use this mode.
+                                */
+                               DBG("no control-OUT deferred responses!\n");
+                               __raw_writel(csr | AT91_UDP_FORCESTALL, creg);
+                               udc->req_pending = 0;
+                       }
+
+               /* STATUS stage for control-IN; ack.  */
+               } else {
+                       PACKET("ep0 out/status ACK\n");
+                       __raw_writel(csr, creg);
+
+                       /* "early" status stage */
+                       if (req)
+                               done(ep0, req, 0);
+               }
+       }
+}
+
+static irqreturn_t at91_udc_irq (int irq, void *_udc)
+{
+       struct at91_udc         *udc = _udc;
+       u32                     rescans = 5;
+       int                     disable_clock = 0;
+       unsigned long           flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       if (!udc->clocked) {
+               clk_on(udc);
+               disable_clock = 1;
+       }
+
+       while (rescans--) {
+               u32 status;
+
+               status = at91_udp_read(udc, AT91_UDP_ISR)
+                       & at91_udp_read(udc, AT91_UDP_IMR);
+               if (!status)
+                       break;
+
+               /* USB reset irq:  not maskable */
+               if (status & AT91_UDP_ENDBUSRES) {
+                       at91_udp_write(udc, AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS);
+                       at91_udp_write(udc, AT91_UDP_IER, MINIMUS_INTERRUPTUS);
+                       /* Atmel code clears this irq twice */
+                       at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
+                       at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
+                       VDBG("end bus reset\n");
+                       udc->addr = 0;
+                       stop_activity(udc);
+
+                       /* enable ep0 */
+                       at91_udp_write(udc, AT91_UDP_CSR(0),
+                                       AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL);
+                       udc->gadget.speed = USB_SPEED_FULL;
+                       udc->suspended = 0;
+                       at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_EP(0));
+
+                       /*
+                        * NOTE:  this driver keeps clocks off unless the
+                        * USB host is present.  That saves power, but for
+                        * boards that don't support VBUS detection, both
+                        * clocks need to be active most of the time.
+                        */
+
+               /* host initiated suspend (3+ms bus idle) */
+               } else if (status & AT91_UDP_RXSUSP) {
+                       at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXSUSP);
+                       at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXRSM);
+                       at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXSUSP);
+                       /* VDBG("bus suspend\n"); */
+                       if (udc->suspended)
+                               continue;
+                       udc->suspended = 1;
+
+                       /*
+                        * NOTE:  when suspending a VBUS-powered device, the
+                        * gadget driver should switch into slow clock mode
+                        * and then into standby to avoid drawing more than
+                        * 500uA power (2500uA for some high-power configs).
+                        */
+                       if (udc->driver && udc->driver->suspend) {
+                               spin_unlock(&udc->lock);
+                               udc->driver->suspend(&udc->gadget);
+                               spin_lock(&udc->lock);
+                       }
+
+               /* host initiated resume */
+               } else if (status & AT91_UDP_RXRSM) {
+                       at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
+                       at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXSUSP);
+                       at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
+                       /* VDBG("bus resume\n"); */
+                       if (!udc->suspended)
+                               continue;
+                       udc->suspended = 0;
+
+                       /*
+                        * NOTE:  for a VBUS-powered device, the gadget driver
+                        * would normally want to switch out of slow clock
+                        * mode into normal mode.
+                        */
+                       if (udc->driver && udc->driver->resume) {
+                               spin_unlock(&udc->lock);
+                               udc->driver->resume(&udc->gadget);
+                               spin_lock(&udc->lock);
+                       }
+
+               /* endpoint IRQs are cleared by handling them */
+               } else {
+                       int             i;
+                       unsigned        mask = 1;
+                       struct at91_ep  *ep = &udc->ep[1];
+
+                       if (status & mask)
+                               handle_ep0(udc);
+                       for (i = 1; i < NUM_ENDPOINTS; i++) {
+                               mask <<= 1;
+                               if (status & mask)
+                                       handle_ep(ep);
+                               ep++;
+                       }
+               }
+       }
+
+       if (disable_clock)
+               clk_off(udc);
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void nop_release(struct device *dev)
+{
+       /* nothing to free */
+}
+
+static struct at91_udc controller = {
+       .gadget = {
+               .ops    = &at91_udc_ops,
+               .ep0    = &controller.ep[0].ep,
+               .name   = driver_name,
+               .dev    = {
+                       .init_name = "gadget",
+                       .release = nop_release,
+               }
+       },
+       .ep[0] = {
+               .ep = {
+                       .name   = ep0name,
+                       .ops    = &at91_ep_ops,
+               },
+               .udc            = &controller,
+               .maxpacket      = 8,
+               .int_mask       = 1 << 0,
+       },
+       .ep[1] = {
+               .ep = {
+                       .name   = "ep1",
+                       .ops    = &at91_ep_ops,
+               },
+               .udc            = &controller,
+               .is_pingpong    = 1,
+               .maxpacket      = 64,
+               .int_mask       = 1 << 1,
+       },
+       .ep[2] = {
+               .ep = {
+                       .name   = "ep2",
+                       .ops    = &at91_ep_ops,
+               },
+               .udc            = &controller,
+               .is_pingpong    = 1,
+               .maxpacket      = 64,
+               .int_mask       = 1 << 2,
+       },
+       .ep[3] = {
+               .ep = {
+                       /* could actually do bulk too */
+                       .name   = "ep3-int",
+                       .ops    = &at91_ep_ops,
+               },
+               .udc            = &controller,
+               .maxpacket      = 8,
+               .int_mask       = 1 << 3,
+       },
+       .ep[4] = {
+               .ep = {
+                       .name   = "ep4",
+                       .ops    = &at91_ep_ops,
+               },
+               .udc            = &controller,
+               .is_pingpong    = 1,
+               .maxpacket      = 256,
+               .int_mask       = 1 << 4,
+       },
+       .ep[5] = {
+               .ep = {
+                       .name   = "ep5",
+                       .ops    = &at91_ep_ops,
+               },
+               .udc            = &controller,
+               .is_pingpong    = 1,
+               .maxpacket      = 256,
+               .int_mask       = 1 << 5,
+       },
+       /* ep6 and ep7 are also reserved (custom silicon might use them) */
+};
+
+static void at91_vbus_update(struct at91_udc *udc, unsigned value)
+{
+       value ^= udc->board.vbus_active_low;
+       if (value != udc->vbus)
+               at91_vbus_session(&udc->gadget, value);
+}
+
+static irqreturn_t at91_vbus_irq(int irq, void *_udc)
+{
+       struct at91_udc *udc = _udc;
+
+       /* vbus needs at least brief debouncing */
+       udelay(10);
+       at91_vbus_update(udc, gpio_get_value(udc->board.vbus_pin));
+
+       return IRQ_HANDLED;
+}
+
+static void at91_vbus_timer_work(struct work_struct *work)
+{
+       struct at91_udc *udc = container_of(work, struct at91_udc,
+                                           vbus_timer_work);
+
+       at91_vbus_update(udc, gpio_get_value_cansleep(udc->board.vbus_pin));
+
+       if (!timer_pending(&udc->vbus_timer))
+               mod_timer(&udc->vbus_timer, jiffies + VBUS_POLL_TIMEOUT);
+}
+
+static void at91_vbus_timer(unsigned long data)
+{
+       struct at91_udc *udc = (struct at91_udc *)data;
+
+       /*
+        * If we are polling vbus it is likely that the gpio is on an
+        * bus such as i2c or spi which may sleep, so schedule some work
+        * to read the vbus gpio
+        */
+       schedule_work(&udc->vbus_timer_work);
+}
+
+static int at91_start(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct at91_udc *udc;
+
+       udc = container_of(gadget, struct at91_udc, gadget);
+       udc->driver = driver;
+       udc->gadget.dev.of_node = udc->pdev->dev.of_node;
+       udc->enabled = 1;
+       udc->selfpowered = 1;
+
+       DBG("bound to %s\n", driver->driver.name);
+       return 0;
+}
+
+static int at91_stop(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct at91_udc *udc;
+       unsigned long   flags;
+
+       udc = container_of(gadget, struct at91_udc, gadget);
+       spin_lock_irqsave(&udc->lock, flags);
+       udc->enabled = 0;
+       at91_udp_write(udc, AT91_UDP_IDR, ~0);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       udc->driver = NULL;
+
+       DBG("unbound from %s\n", driver->driver.name);
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void at91udc_shutdown(struct platform_device *dev)
+{
+       struct at91_udc *udc = platform_get_drvdata(dev);
+       unsigned long   flags;
+
+       /* force disconnect on reboot */
+       spin_lock_irqsave(&udc->lock, flags);
+       pullup(platform_get_drvdata(dev), 0);
+       spin_unlock_irqrestore(&udc->lock, flags);
+}
+
+static void at91udc_of_init(struct at91_udc *udc,
+                                    struct device_node *np)
+{
+       struct at91_udc_data *board = &udc->board;
+       u32 val;
+       enum of_gpio_flags flags;
+
+       if (of_property_read_u32(np, "atmel,vbus-polled", &val) == 0)
+               board->vbus_polled = 1;
+
+       board->vbus_pin = of_get_named_gpio_flags(np, "atmel,vbus-gpio", 0,
+                                                 &flags);
+       board->vbus_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
+
+       board->pullup_pin = of_get_named_gpio_flags(np, "atmel,pullup-gpio", 0,
+                                                 &flags);
+
+       board->pullup_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
+}
+
+static int at91udc_probe(struct platform_device *pdev)
+{
+       struct device   *dev = &pdev->dev;
+       struct at91_udc *udc;
+       int             retval;
+       struct resource *res;
+
+       if (!dev_get_platdata(dev) && !pdev->dev.of_node) {
+               /* small (so we copy it) but critical! */
+               DBG("missing platform_data\n");
+               return -ENODEV;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENXIO;
+
+       if (!request_mem_region(res->start, resource_size(res), driver_name)) {
+               DBG("someone's using UDC memory\n");
+               return -EBUSY;
+       }
+
+       /* init software state */
+       udc = &controller;
+       udc->gadget.dev.parent = dev;
+       if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
+               at91udc_of_init(udc, pdev->dev.of_node);
+       else
+               memcpy(&udc->board, dev_get_platdata(dev),
+                      sizeof(struct at91_udc_data));
+       udc->pdev = pdev;
+       udc->enabled = 0;
+       spin_lock_init(&udc->lock);
+
+       /* rm9200 needs manual D+ pullup; off by default */
+       if (cpu_is_at91rm9200()) {
+               if (!gpio_is_valid(udc->board.pullup_pin)) {
+                       DBG("no D+ pullup?\n");
+                       retval = -ENODEV;
+                       goto fail0;
+               }
+               retval = gpio_request(udc->board.pullup_pin, "udc_pullup");
+               if (retval) {
+                       DBG("D+ pullup is busy\n");
+                       goto fail0;
+               }
+               gpio_direction_output(udc->board.pullup_pin,
+                               udc->board.pullup_active_low);
+       }
+
+       /* newer chips have more FIFO memory than rm9200 */
+       if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) {
+               udc->ep[0].maxpacket = 64;
+               udc->ep[3].maxpacket = 64;
+               udc->ep[4].maxpacket = 512;
+               udc->ep[5].maxpacket = 512;
+       } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
+               udc->ep[3].maxpacket = 64;
+       } else if (cpu_is_at91sam9263()) {
+               udc->ep[0].maxpacket = 64;
+               udc->ep[3].maxpacket = 64;
+       }
+
+       udc->udp_baseaddr = ioremap(res->start, resource_size(res));
+       if (!udc->udp_baseaddr) {
+               retval = -ENOMEM;
+               goto fail0a;
+       }
+
+       udc_reinit(udc);
+
+       /* get interface and function clocks */
+       udc->iclk = clk_get(dev, "udc_clk");
+       udc->fclk = clk_get(dev, "udpck");
+       if (IS_ENABLED(CONFIG_COMMON_CLK))
+               udc->uclk = clk_get(dev, "usb_clk");
+       if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk) ||
+           (IS_ENABLED(CONFIG_COMMON_CLK) && IS_ERR(udc->uclk))) {
+               DBG("clocks missing\n");
+               retval = -ENODEV;
+               goto fail1;
+       }
+
+       /* don't do anything until we have both gadget driver and VBUS */
+       retval = clk_prepare_enable(udc->iclk);
+       if (retval)
+               goto fail1;
+       at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
+       at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
+       /* Clear all pending interrupts - UDP may be used by bootloader. */
+       at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff);
+       clk_disable_unprepare(udc->iclk);
+
+       /* request UDC and maybe VBUS irqs */
+       udc->udp_irq = platform_get_irq(pdev, 0);
+       retval = request_irq(udc->udp_irq, at91_udc_irq,
+                       0, driver_name, udc);
+       if (retval < 0) {
+               DBG("request irq %d failed\n", udc->udp_irq);
+               goto fail1;
+       }
+       if (gpio_is_valid(udc->board.vbus_pin)) {
+               retval = gpio_request(udc->board.vbus_pin, "udc_vbus");
+               if (retval < 0) {
+                       DBG("request vbus pin failed\n");
+                       goto fail2;
+               }
+               gpio_direction_input(udc->board.vbus_pin);
+
+               /*
+                * Get the initial state of VBUS - we cannot expect
+                * a pending interrupt.
+                */
+               udc->vbus = gpio_get_value_cansleep(udc->board.vbus_pin) ^
+                       udc->board.vbus_active_low;
+
+               if (udc->board.vbus_polled) {
+                       INIT_WORK(&udc->vbus_timer_work, at91_vbus_timer_work);
+                       setup_timer(&udc->vbus_timer, at91_vbus_timer,
+                                   (unsigned long)udc);
+                       mod_timer(&udc->vbus_timer,
+                                 jiffies + VBUS_POLL_TIMEOUT);
+               } else {
+                       if (request_irq(gpio_to_irq(udc->board.vbus_pin),
+                                       at91_vbus_irq, 0, driver_name, udc)) {
+                               DBG("request vbus irq %d failed\n",
+                                   udc->board.vbus_pin);
+                               retval = -EBUSY;
+                               goto fail3;
+                       }
+               }
+       } else {
+               DBG("no VBUS detection, assuming always-on\n");
+               udc->vbus = 1;
+       }
+       retval = usb_add_gadget_udc(dev, &udc->gadget);
+       if (retval)
+               goto fail4;
+       dev_set_drvdata(dev, udc);
+       device_init_wakeup(dev, 1);
+       create_debug_file(udc);
+
+       INFO("%s version %s\n", driver_name, DRIVER_VERSION);
+       return 0;
+fail4:
+       if (gpio_is_valid(udc->board.vbus_pin) && !udc->board.vbus_polled)
+               free_irq(gpio_to_irq(udc->board.vbus_pin), udc);
+fail3:
+       if (gpio_is_valid(udc->board.vbus_pin))
+               gpio_free(udc->board.vbus_pin);
+fail2:
+       free_irq(udc->udp_irq, udc);
+fail1:
+       if (IS_ENABLED(CONFIG_COMMON_CLK) && !IS_ERR(udc->uclk))
+               clk_put(udc->uclk);
+       if (!IS_ERR(udc->fclk))
+               clk_put(udc->fclk);
+       if (!IS_ERR(udc->iclk))
+               clk_put(udc->iclk);
+       iounmap(udc->udp_baseaddr);
+fail0a:
+       if (cpu_is_at91rm9200())
+               gpio_free(udc->board.pullup_pin);
+fail0:
+       release_mem_region(res->start, resource_size(res));
+       DBG("%s probe failed, %d\n", driver_name, retval);
+       return retval;
+}
+
+static int __exit at91udc_remove(struct platform_device *pdev)
+{
+       struct at91_udc *udc = platform_get_drvdata(pdev);
+       struct resource *res;
+       unsigned long   flags;
+
+       DBG("remove\n");
+
+       usb_del_gadget_udc(&udc->gadget);
+       if (udc->driver)
+               return -EBUSY;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       pullup(udc, 0);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       device_init_wakeup(&pdev->dev, 0);
+       remove_debug_file(udc);
+       if (gpio_is_valid(udc->board.vbus_pin)) {
+               free_irq(gpio_to_irq(udc->board.vbus_pin), udc);
+               gpio_free(udc->board.vbus_pin);
+       }
+       free_irq(udc->udp_irq, udc);
+       iounmap(udc->udp_baseaddr);
+
+       if (cpu_is_at91rm9200())
+               gpio_free(udc->board.pullup_pin);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, resource_size(res));
+
+       clk_put(udc->iclk);
+       clk_put(udc->fclk);
+       if (IS_ENABLED(CONFIG_COMMON_CLK))
+               clk_put(udc->uclk);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+       struct at91_udc *udc = platform_get_drvdata(pdev);
+       int             wake = udc->driver && device_may_wakeup(&pdev->dev);
+       unsigned long   flags;
+
+       /* Unless we can act normally to the host (letting it wake us up
+        * whenever it has work for us) force disconnect.  Wakeup requires
+        * PLLB for USB events (signaling for reset, wakeup, or incoming
+        * tokens) and VBUS irqs (on systems which support them).
+        */
+       if ((!udc->suspended && udc->addr)
+                       || !wake
+                       || at91_suspend_entering_slow_clock()) {
+               spin_lock_irqsave(&udc->lock, flags);
+               pullup(udc, 0);
+               wake = 0;
+               spin_unlock_irqrestore(&udc->lock, flags);
+       } else
+               enable_irq_wake(udc->udp_irq);
+
+       udc->active_suspend = wake;
+       if (gpio_is_valid(udc->board.vbus_pin) && !udc->board.vbus_polled && wake)
+               enable_irq_wake(udc->board.vbus_pin);
+       return 0;
+}
+
+static int at91udc_resume(struct platform_device *pdev)
+{
+       struct at91_udc *udc = platform_get_drvdata(pdev);
+       unsigned long   flags;
+
+       if (gpio_is_valid(udc->board.vbus_pin) && !udc->board.vbus_polled &&
+           udc->active_suspend)
+               disable_irq_wake(udc->board.vbus_pin);
+
+       /* maybe reconnect to host; if so, clocks on */
+       if (udc->active_suspend)
+               disable_irq_wake(udc->udp_irq);
+       else {
+               spin_lock_irqsave(&udc->lock, flags);
+               pullup(udc, 1);
+               spin_unlock_irqrestore(&udc->lock, flags);
+       }
+       return 0;
+}
+#else
+#define        at91udc_suspend NULL
+#define        at91udc_resume  NULL
+#endif
+
+#if defined(CONFIG_OF)
+static const struct of_device_id at91_udc_dt_ids[] = {
+       { .compatible = "atmel,at91rm9200-udc" },
+       { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, at91_udc_dt_ids);
+#endif
+
+static struct platform_driver at91_udc_driver = {
+       .remove         = __exit_p(at91udc_remove),
+       .shutdown       = at91udc_shutdown,
+       .suspend        = at91udc_suspend,
+       .resume         = at91udc_resume,
+       .driver         = {
+               .name   = (char *) driver_name,
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(at91_udc_dt_ids),
+       },
+};
+
+module_platform_driver_probe(at91_udc_driver, at91udc_probe);
+
+MODULE_DESCRIPTION("AT91 udc driver");
+MODULE_AUTHOR("Thomas Rathbone, David Brownell");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:at91_udc");
diff --git a/drivers/usb/gadget/udc/at91_udc.h b/drivers/usb/gadget/udc/at91_udc.h
new file mode 100644 (file)
index 0000000..0175246
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2004 by Thomas Rathbone, HP Labs
+ * Copyright (C) 2005 by Ivan Kokshaysky
+ * Copyright (C) 2006 by SAN People
+ *
+ * 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.
+ */
+
+#ifndef AT91_UDC_H
+#define AT91_UDC_H
+
+/*
+ * USB Device Port (UDP) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ */
+
+#define AT91_UDP_FRM_NUM       0x00            /* Frame Number Register */
+#define     AT91_UDP_NUM       (0x7ff <<  0)   /* Frame Number */
+#define     AT91_UDP_FRM_ERR   (1     << 16)   /* Frame Error */
+#define     AT91_UDP_FRM_OK    (1     << 17)   /* Frame OK */
+
+#define AT91_UDP_GLB_STAT      0x04            /* Global State Register */
+#define     AT91_UDP_FADDEN    (1 <<  0)       /* Function Address Enable */
+#define     AT91_UDP_CONFG     (1 <<  1)       /* Configured */
+#define     AT91_UDP_ESR       (1 <<  2)       /* Enable Send Resume */
+#define     AT91_UDP_RSMINPR   (1 <<  3)       /* Resume has been sent */
+#define     AT91_UDP_RMWUPE    (1 <<  4)       /* Remote Wake Up Enable */
+
+#define AT91_UDP_FADDR         0x08            /* Function Address Register */
+#define     AT91_UDP_FADD      (0x7f << 0)     /* Function Address Value */
+#define     AT91_UDP_FEN       (1    << 8)     /* Function Enable */
+
+#define AT91_UDP_IER           0x10            /* Interrupt Enable Register */
+#define AT91_UDP_IDR           0x14            /* Interrupt Disable Register */
+#define AT91_UDP_IMR           0x18            /* Interrupt Mask Register */
+
+#define AT91_UDP_ISR           0x1c            /* Interrupt Status Register */
+#define     AT91_UDP_EP(n)     (1 << (n))      /* Endpoint Interrupt Status */
+#define     AT91_UDP_RXSUSP    (1 <<  8)       /* USB Suspend Interrupt Status */
+#define     AT91_UDP_RXRSM     (1 <<  9)       /* USB Resume Interrupt Status */
+#define     AT91_UDP_EXTRSM    (1 << 10)       /* External Resume Interrupt Status [AT91RM9200 only] */
+#define     AT91_UDP_SOFINT    (1 << 11)       /* Start of Frame Interrupt Status */
+#define     AT91_UDP_ENDBUSRES (1 << 12)       /* End of Bus Reset Interrupt Status */
+#define     AT91_UDP_WAKEUP    (1 << 13)       /* USB Wakeup Interrupt Status [AT91RM9200 only] */
+
+#define AT91_UDP_ICR           0x20            /* Interrupt Clear Register */
+#define AT91_UDP_RST_EP                0x28            /* Reset Endpoint Register */
+
+#define AT91_UDP_CSR(n)                (0x30+((n)*4))  /* Endpoint Control/Status Registers 0-7 */
+#define     AT91_UDP_TXCOMP    (1 <<  0)       /* Generates IN packet with data previously written in DPR */
+#define     AT91_UDP_RX_DATA_BK0 (1 <<  1)     /* Receive Data Bank 0 */
+#define     AT91_UDP_RXSETUP   (1 <<  2)       /* Send STALL to the host */
+#define     AT91_UDP_STALLSENT (1 <<  3)       /* Stall Sent / Isochronous error (Isochronous endpoints) */
+#define     AT91_UDP_TXPKTRDY  (1 <<  4)       /* Transmit Packet Ready */
+#define     AT91_UDP_FORCESTALL        (1 <<  5)       /* Force Stall */
+#define     AT91_UDP_RX_DATA_BK1 (1 <<  6)     /* Receive Data Bank 1 */
+#define     AT91_UDP_DIR       (1 <<  7)       /* Transfer Direction */
+#define     AT91_UDP_EPTYPE    (7 <<  8)       /* Endpoint Type */
+#define                AT91_UDP_EPTYPE_CTRL            (0 <<  8)
+#define                AT91_UDP_EPTYPE_ISO_OUT         (1 <<  8)
+#define                AT91_UDP_EPTYPE_BULK_OUT        (2 <<  8)
+#define                AT91_UDP_EPTYPE_INT_OUT         (3 <<  8)
+#define                AT91_UDP_EPTYPE_ISO_IN          (5 <<  8)
+#define                AT91_UDP_EPTYPE_BULK_IN         (6 <<  8)
+#define                AT91_UDP_EPTYPE_INT_IN          (7 <<  8)
+#define     AT91_UDP_DTGLE     (1 << 11)       /* Data Toggle */
+#define     AT91_UDP_EPEDS     (1 << 15)       /* Endpoint Enable/Disable */
+#define     AT91_UDP_RXBYTECNT (0x7ff << 16)   /* Number of bytes in FIFO */
+
+#define AT91_UDP_FDR(n)                (0x50+((n)*4))  /* Endpoint FIFO Data Registers 0-7 */
+
+#define AT91_UDP_TXVC          0x74            /* Transceiver Control Register */
+#define     AT91_UDP_TXVC_TXVDIS (1 << 8)      /* Transceiver Disable */
+#define     AT91_UDP_TXVC_PUON   (1 << 9)      /* PullUp On [AT91SAM9260 only] */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * controller driver data structures
+ */
+
+#define        NUM_ENDPOINTS   6
+
+/*
+ * hardware won't disable bus reset, or resume while the controller
+ * is suspended ... watching suspend helps keep the logic symmetric.
+ */
+#define        MINIMUS_INTERRUPTUS \
+       (AT91_UDP_ENDBUSRES | AT91_UDP_RXRSM | AT91_UDP_RXSUSP)
+
+struct at91_ep {
+       struct usb_ep                   ep;
+       struct list_head                queue;
+       struct at91_udc                 *udc;
+       void __iomem                    *creg;
+
+       unsigned                        maxpacket:16;
+       u8                              int_mask;
+       unsigned                        is_pingpong:1;
+
+       unsigned                        stopped:1;
+       unsigned                        is_in:1;
+       unsigned                        is_iso:1;
+       unsigned                        fifo_bank:1;
+};
+
+/*
+ * driver is non-SMP, and just blocks IRQs whenever it needs
+ * access protection for chip registers or driver state
+ */
+struct at91_udc {
+       struct usb_gadget               gadget;
+       struct at91_ep                  ep[NUM_ENDPOINTS];
+       struct usb_gadget_driver        *driver;
+       unsigned                        vbus:1;
+       unsigned                        enabled:1;
+       unsigned                        clocked:1;
+       unsigned                        suspended:1;
+       unsigned                        req_pending:1;
+       unsigned                        wait_for_addr_ack:1;
+       unsigned                        wait_for_config_ack:1;
+       unsigned                        selfpowered:1;
+       unsigned                        active_suspend:1;
+       u8                              addr;
+       struct at91_udc_data            board;
+       struct clk                      *iclk, *fclk, *uclk;
+       struct platform_device          *pdev;
+       struct proc_dir_entry           *pde;
+       void __iomem                    *udp_baseaddr;
+       int                             udp_irq;
+       spinlock_t                      lock;
+       struct timer_list               vbus_timer;
+       struct work_struct              vbus_timer_work;
+};
+
+static inline struct at91_udc *to_udc(struct usb_gadget *g)
+{
+       return container_of(g, struct at91_udc, gadget);
+}
+
+struct at91_request {
+       struct usb_request              req;
+       struct list_head                queue;
+};
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef VERBOSE_DEBUG
+#    define VDBG               DBG
+#else
+#    define VDBG(stuff...)     do{}while(0)
+#endif
+
+#ifdef PACKET_TRACE
+#    define PACKET             VDBG
+#else
+#    define PACKET(stuff...)   do{}while(0)
+#endif
+
+#define ERR(stuff...)          pr_err("udc: " stuff)
+#define WARNING(stuff...)      pr_warning("udc: " stuff)
+#define INFO(stuff...)         pr_info("udc: " stuff)
+#define DBG(stuff...)          pr_debug("udc: " stuff)
+
+#endif
+
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
new file mode 100644 (file)
index 0000000..906e65f
--- /dev/null
@@ -0,0 +1,2133 @@
+/*
+ * Driver for the Atmel USBA high speed USB device controller
+ *
+ * Copyright (C) 2005-2007 Atmel Corporation
+ *
+ * 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 <linux/clk.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/atmel_usba_udc.h>
+#include <linux/delay.h>
+#include <linux/platform_data/atmel.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+
+#include <asm/gpio.h>
+
+#include "atmel_usba_udc.h"
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+static int queue_dbg_open(struct inode *inode, struct file *file)
+{
+       struct usba_ep *ep = inode->i_private;
+       struct usba_request *req, *req_copy;
+       struct list_head *queue_data;
+
+       queue_data = kmalloc(sizeof(*queue_data), GFP_KERNEL);
+       if (!queue_data)
+               return -ENOMEM;
+       INIT_LIST_HEAD(queue_data);
+
+       spin_lock_irq(&ep->udc->lock);
+       list_for_each_entry(req, &ep->queue, queue) {
+               req_copy = kmemdup(req, sizeof(*req_copy), GFP_ATOMIC);
+               if (!req_copy)
+                       goto fail;
+               list_add_tail(&req_copy->queue, queue_data);
+       }
+       spin_unlock_irq(&ep->udc->lock);
+
+       file->private_data = queue_data;
+       return 0;
+
+fail:
+       spin_unlock_irq(&ep->udc->lock);
+       list_for_each_entry_safe(req, req_copy, queue_data, queue) {
+               list_del(&req->queue);
+               kfree(req);
+       }
+       kfree(queue_data);
+       return -ENOMEM;
+}
+
+/*
+ * bbbbbbbb llllllll IZS sssss nnnn FDL\n\0
+ *
+ * b: buffer address
+ * l: buffer length
+ * I/i: interrupt/no interrupt
+ * Z/z: zero/no zero
+ * S/s: short ok/short not ok
+ * s: status
+ * n: nr_packets
+ * F/f: submitted/not submitted to FIFO
+ * D/d: using/not using DMA
+ * L/l: last transaction/not last transaction
+ */
+static ssize_t queue_dbg_read(struct file *file, char __user *buf,
+               size_t nbytes, loff_t *ppos)
+{
+       struct list_head *queue = file->private_data;
+       struct usba_request *req, *tmp_req;
+       size_t len, remaining, actual = 0;
+       char tmpbuf[38];
+
+       if (!access_ok(VERIFY_WRITE, buf, nbytes))
+               return -EFAULT;
+
+       mutex_lock(&file_inode(file)->i_mutex);
+       list_for_each_entry_safe(req, tmp_req, queue, queue) {
+               len = snprintf(tmpbuf, sizeof(tmpbuf),
+                               "%8p %08x %c%c%c %5d %c%c%c\n",
+                               req->req.buf, req->req.length,
+                               req->req.no_interrupt ? 'i' : 'I',
+                               req->req.zero ? 'Z' : 'z',
+                               req->req.short_not_ok ? 's' : 'S',
+                               req->req.status,
+                               req->submitted ? 'F' : 'f',
+                               req->using_dma ? 'D' : 'd',
+                               req->last_transaction ? 'L' : 'l');
+               len = min(len, sizeof(tmpbuf));
+               if (len > nbytes)
+                       break;
+
+               list_del(&req->queue);
+               kfree(req);
+
+               remaining = __copy_to_user(buf, tmpbuf, len);
+               actual += len - remaining;
+               if (remaining)
+                       break;
+
+               nbytes -= len;
+               buf += len;
+       }
+       mutex_unlock(&file_inode(file)->i_mutex);
+
+       return actual;
+}
+
+static int queue_dbg_release(struct inode *inode, struct file *file)
+{
+       struct list_head *queue_data = file->private_data;
+       struct usba_request *req, *tmp_req;
+
+       list_for_each_entry_safe(req, tmp_req, queue_data, queue) {
+               list_del(&req->queue);
+               kfree(req);
+       }
+       kfree(queue_data);
+       return 0;
+}
+
+static int regs_dbg_open(struct inode *inode, struct file *file)
+{
+       struct usba_udc *udc;
+       unsigned int i;
+       u32 *data;
+       int ret = -ENOMEM;
+
+       mutex_lock(&inode->i_mutex);
+       udc = inode->i_private;
+       data = kmalloc(inode->i_size, GFP_KERNEL);
+       if (!data)
+               goto out;
+
+       spin_lock_irq(&udc->lock);
+       for (i = 0; i < inode->i_size / 4; i++)
+               data[i] = __raw_readl(udc->regs + i * 4);
+       spin_unlock_irq(&udc->lock);
+
+       file->private_data = data;
+       ret = 0;
+
+out:
+       mutex_unlock(&inode->i_mutex);
+
+       return ret;
+}
+
+static ssize_t regs_dbg_read(struct file *file, char __user *buf,
+               size_t nbytes, loff_t *ppos)
+{
+       struct inode *inode = file_inode(file);
+       int ret;
+
+       mutex_lock(&inode->i_mutex);
+       ret = simple_read_from_buffer(buf, nbytes, ppos,
+                       file->private_data,
+                       file_inode(file)->i_size);
+       mutex_unlock(&inode->i_mutex);
+
+       return ret;
+}
+
+static int regs_dbg_release(struct inode *inode, struct file *file)
+{
+       kfree(file->private_data);
+       return 0;
+}
+
+const struct file_operations queue_dbg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = queue_dbg_open,
+       .llseek         = no_llseek,
+       .read           = queue_dbg_read,
+       .release        = queue_dbg_release,
+};
+
+const struct file_operations regs_dbg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = regs_dbg_open,
+       .llseek         = generic_file_llseek,
+       .read           = regs_dbg_read,
+       .release        = regs_dbg_release,
+};
+
+static void usba_ep_init_debugfs(struct usba_udc *udc,
+               struct usba_ep *ep)
+{
+       struct dentry *ep_root;
+
+       ep_root = debugfs_create_dir(ep->ep.name, udc->debugfs_root);
+       if (!ep_root)
+               goto err_root;
+       ep->debugfs_dir = ep_root;
+
+       ep->debugfs_queue = debugfs_create_file("queue", 0400, ep_root,
+                                               ep, &queue_dbg_fops);
+       if (!ep->debugfs_queue)
+               goto err_queue;
+
+       if (ep->can_dma) {
+               ep->debugfs_dma_status
+                       = debugfs_create_u32("dma_status", 0400, ep_root,
+                                       &ep->last_dma_status);
+               if (!ep->debugfs_dma_status)
+                       goto err_dma_status;
+       }
+       if (ep_is_control(ep)) {
+               ep->debugfs_state
+                       = debugfs_create_u32("state", 0400, ep_root,
+                                       &ep->state);
+               if (!ep->debugfs_state)
+                       goto err_state;
+       }
+
+       return;
+
+err_state:
+       if (ep->can_dma)
+               debugfs_remove(ep->debugfs_dma_status);
+err_dma_status:
+       debugfs_remove(ep->debugfs_queue);
+err_queue:
+       debugfs_remove(ep_root);
+err_root:
+       dev_err(&ep->udc->pdev->dev,
+               "failed to create debugfs directory for %s\n", ep->ep.name);
+}
+
+static void usba_ep_cleanup_debugfs(struct usba_ep *ep)
+{
+       debugfs_remove(ep->debugfs_queue);
+       debugfs_remove(ep->debugfs_dma_status);
+       debugfs_remove(ep->debugfs_state);
+       debugfs_remove(ep->debugfs_dir);
+       ep->debugfs_dma_status = NULL;
+       ep->debugfs_dir = NULL;
+}
+
+static void usba_init_debugfs(struct usba_udc *udc)
+{
+       struct dentry *root, *regs;
+       struct resource *regs_resource;
+
+       root = debugfs_create_dir(udc->gadget.name, NULL);
+       if (IS_ERR(root) || !root)
+               goto err_root;
+       udc->debugfs_root = root;
+
+       regs = debugfs_create_file("regs", 0400, root, udc, &regs_dbg_fops);
+       if (!regs)
+               goto err_regs;
+
+       regs_resource = platform_get_resource(udc->pdev, IORESOURCE_MEM,
+                               CTRL_IOMEM_ID);
+       regs->d_inode->i_size = resource_size(regs_resource);
+       udc->debugfs_regs = regs;
+
+       usba_ep_init_debugfs(udc, to_usba_ep(udc->gadget.ep0));
+
+       return;
+
+err_regs:
+       debugfs_remove(root);
+err_root:
+       udc->debugfs_root = NULL;
+       dev_err(&udc->pdev->dev, "debugfs is not available\n");
+}
+
+static void usba_cleanup_debugfs(struct usba_udc *udc)
+{
+       usba_ep_cleanup_debugfs(to_usba_ep(udc->gadget.ep0));
+       debugfs_remove(udc->debugfs_regs);
+       debugfs_remove(udc->debugfs_root);
+       udc->debugfs_regs = NULL;
+       udc->debugfs_root = NULL;
+}
+#else
+static inline void usba_ep_init_debugfs(struct usba_udc *udc,
+                                        struct usba_ep *ep)
+{
+
+}
+
+static inline void usba_ep_cleanup_debugfs(struct usba_ep *ep)
+{
+
+}
+
+static inline void usba_init_debugfs(struct usba_udc *udc)
+{
+
+}
+
+static inline void usba_cleanup_debugfs(struct usba_udc *udc)
+{
+
+}
+#endif
+
+static int vbus_is_present(struct usba_udc *udc)
+{
+       if (gpio_is_valid(udc->vbus_pin))
+               return gpio_get_value(udc->vbus_pin) ^ udc->vbus_pin_inverted;
+
+       /* No Vbus detection: Assume always present */
+       return 1;
+}
+
+#if defined(CONFIG_ARCH_AT91SAM9RL)
+
+#include <linux/clk/at91_pmc.h>
+
+static void toggle_bias(int is_on)
+{
+       unsigned int uckr = at91_pmc_read(AT91_CKGR_UCKR);
+
+       if (is_on)
+               at91_pmc_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
+       else
+               at91_pmc_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN));
+}
+
+#else
+
+static void toggle_bias(int is_on)
+{
+}
+
+#endif /* CONFIG_ARCH_AT91SAM9RL */
+
+static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
+{
+       unsigned int transaction_len;
+
+       transaction_len = req->req.length - req->req.actual;
+       req->last_transaction = 1;
+       if (transaction_len > ep->ep.maxpacket) {
+               transaction_len = ep->ep.maxpacket;
+               req->last_transaction = 0;
+       } else if (transaction_len == ep->ep.maxpacket && req->req.zero)
+               req->last_transaction = 0;
+
+       DBG(DBG_QUEUE, "%s: submit_transaction, req %p (length %d)%s\n",
+               ep->ep.name, req, transaction_len,
+               req->last_transaction ? ", done" : "");
+
+       memcpy_toio(ep->fifo, req->req.buf + req->req.actual, transaction_len);
+       usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+       req->req.actual += transaction_len;
+}
+
+static void submit_request(struct usba_ep *ep, struct usba_request *req)
+{
+       DBG(DBG_QUEUE, "%s: submit_request: req %p (length %d)\n",
+               ep->ep.name, req, req->req.length);
+
+       req->req.actual = 0;
+       req->submitted = 1;
+
+       if (req->using_dma) {
+               if (req->req.length == 0) {
+                       usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
+                       return;
+               }
+
+               if (req->req.zero)
+                       usba_ep_writel(ep, CTL_ENB, USBA_SHORT_PACKET);
+               else
+                       usba_ep_writel(ep, CTL_DIS, USBA_SHORT_PACKET);
+
+               usba_dma_writel(ep, ADDRESS, req->req.dma);
+               usba_dma_writel(ep, CONTROL, req->ctrl);
+       } else {
+               next_fifo_transaction(ep, req);
+               if (req->last_transaction) {
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
+                       usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
+               } else {
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+                       usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
+               }
+       }
+}
+
+static void submit_next_request(struct usba_ep *ep)
+{
+       struct usba_request *req;
+
+       if (list_empty(&ep->queue)) {
+               usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY | USBA_RX_BK_RDY);
+               return;
+       }
+
+       req = list_entry(ep->queue.next, struct usba_request, queue);
+       if (!req->submitted)
+               submit_request(ep, req);
+}
+
+static void send_status(struct usba_udc *udc, struct usba_ep *ep)
+{
+       ep->state = STATUS_STAGE_IN;
+       usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+       usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
+}
+
+static void receive_data(struct usba_ep *ep)
+{
+       struct usba_udc *udc = ep->udc;
+       struct usba_request *req;
+       unsigned long status;
+       unsigned int bytecount, nr_busy;
+       int is_complete = 0;
+
+       status = usba_ep_readl(ep, STA);
+       nr_busy = USBA_BFEXT(BUSY_BANKS, status);
+
+       DBG(DBG_QUEUE, "receive data: nr_busy=%u\n", nr_busy);
+
+       while (nr_busy > 0) {
+               if (list_empty(&ep->queue)) {
+                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+                       break;
+               }
+               req = list_entry(ep->queue.next,
+                                struct usba_request, queue);
+
+               bytecount = USBA_BFEXT(BYTE_COUNT, status);
+
+               if (status & (1 << 31))
+                       is_complete = 1;
+               if (req->req.actual + bytecount >= req->req.length) {
+                       is_complete = 1;
+                       bytecount = req->req.length - req->req.actual;
+               }
+
+               memcpy_fromio(req->req.buf + req->req.actual,
+                               ep->fifo, bytecount);
+               req->req.actual += bytecount;
+
+               usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
+
+               if (is_complete) {
+                       DBG(DBG_QUEUE, "%s: request done\n", ep->ep.name);
+                       req->req.status = 0;
+                       list_del_init(&req->queue);
+                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+                       spin_unlock(&udc->lock);
+                       req->req.complete(&ep->ep, &req->req);
+                       spin_lock(&udc->lock);
+               }
+
+               status = usba_ep_readl(ep, STA);
+               nr_busy = USBA_BFEXT(BUSY_BANKS, status);
+
+               if (is_complete && ep_is_control(ep)) {
+                       send_status(udc, ep);
+                       break;
+               }
+       }
+}
+
+static void
+request_complete(struct usba_ep *ep, struct usba_request *req, int status)
+{
+       struct usba_udc *udc = ep->udc;
+
+       WARN_ON(!list_empty(&req->queue));
+
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+
+       if (req->using_dma)
+               usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
+
+       DBG(DBG_GADGET | DBG_REQ,
+               "%s: req %p complete: status %d, actual %u\n",
+               ep->ep.name, req, req->req.status, req->req.actual);
+
+       spin_unlock(&udc->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&udc->lock);
+}
+
+static void
+request_complete_list(struct usba_ep *ep, struct list_head *list, int status)
+{
+       struct usba_request *req, *tmp_req;
+
+       list_for_each_entry_safe(req, tmp_req, list, queue) {
+               list_del_init(&req->queue);
+               request_complete(ep, req, status);
+       }
+}
+
+static int
+usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+{
+       struct usba_ep *ep = to_usba_ep(_ep);
+       struct usba_udc *udc = ep->udc;
+       unsigned long flags, ept_cfg, maxpacket;
+       unsigned int nr_trans;
+
+       DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep->ep.name, desc);
+
+       maxpacket = usb_endpoint_maxp(desc) & 0x7ff;
+
+       if (((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) != ep->index)
+                       || ep->index == 0
+                       || desc->bDescriptorType != USB_DT_ENDPOINT
+                       || maxpacket == 0
+                       || maxpacket > ep->fifo_size) {
+               DBG(DBG_ERR, "ep_enable: Invalid argument");
+               return -EINVAL;
+       }
+
+       ep->is_isoc = 0;
+       ep->is_in = 0;
+
+       if (maxpacket <= 8)
+               ept_cfg = USBA_BF(EPT_SIZE, USBA_EPT_SIZE_8);
+       else
+               /* LSB is bit 1, not 0 */
+               ept_cfg = USBA_BF(EPT_SIZE, fls(maxpacket - 1) - 3);
+
+       DBG(DBG_HW, "%s: EPT_SIZE = %lu (maxpacket = %lu)\n",
+                       ep->ep.name, ept_cfg, maxpacket);
+
+       if (usb_endpoint_dir_in(desc)) {
+               ep->is_in = 1;
+               ept_cfg |= USBA_EPT_DIR_IN;
+       }
+
+       switch (usb_endpoint_type(desc)) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL);
+               ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE);
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               if (!ep->can_isoc) {
+                       DBG(DBG_ERR, "ep_enable: %s is not isoc capable\n",
+                                       ep->ep.name);
+                       return -EINVAL;
+               }
+
+               /*
+                * Bits 11:12 specify number of _additional_
+                * transactions per microframe.
+                */
+               nr_trans = ((usb_endpoint_maxp(desc) >> 11) & 3) + 1;
+               if (nr_trans > 3)
+                       return -EINVAL;
+
+               ep->is_isoc = 1;
+               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_ISO);
+
+               /*
+                * Do triple-buffering on high-bandwidth iso endpoints.
+                */
+               if (nr_trans > 1 && ep->nr_banks == 3)
+                       ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_TRIPLE);
+               else
+                       ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE);
+               ept_cfg |= USBA_BF(NB_TRANS, nr_trans);
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK);
+               ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE);
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_INT);
+               ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE);
+               break;
+       }
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+
+       ep->ep.desc = desc;
+       ep->ep.maxpacket = maxpacket;
+
+       usba_ep_writel(ep, CFG, ept_cfg);
+       usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
+
+       if (ep->can_dma) {
+               u32 ctrl;
+
+               usba_writel(udc, INT_ENB,
+                               (usba_readl(udc, INT_ENB)
+                                       | USBA_BF(EPT_INT, 1 << ep->index)
+                                       | USBA_BF(DMA_INT, 1 << ep->index)));
+               ctrl = USBA_AUTO_VALID | USBA_INTDIS_DMA;
+               usba_ep_writel(ep, CTL_ENB, ctrl);
+       } else {
+               usba_writel(udc, INT_ENB,
+                               (usba_readl(udc, INT_ENB)
+                                       | USBA_BF(EPT_INT, 1 << ep->index)));
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       DBG(DBG_HW, "EPT_CFG%d after init: %#08lx\n", ep->index,
+                       (unsigned long)usba_ep_readl(ep, CFG));
+       DBG(DBG_HW, "INT_ENB after init: %#08lx\n",
+                       (unsigned long)usba_readl(udc, INT_ENB));
+
+       return 0;
+}
+
+static int usba_ep_disable(struct usb_ep *_ep)
+{
+       struct usba_ep *ep = to_usba_ep(_ep);
+       struct usba_udc *udc = ep->udc;
+       LIST_HEAD(req_list);
+       unsigned long flags;
+
+       DBG(DBG_GADGET, "ep_disable: %s\n", ep->ep.name);
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       if (!ep->ep.desc) {
+               spin_unlock_irqrestore(&udc->lock, flags);
+               /* REVISIT because this driver disables endpoints in
+                * reset_all_endpoints() before calling disconnect(),
+                * most gadget drivers would trigger this non-error ...
+                */
+               if (udc->gadget.speed != USB_SPEED_UNKNOWN)
+                       DBG(DBG_ERR, "ep_disable: %s not enabled\n",
+                                       ep->ep.name);
+               return -EINVAL;
+       }
+       ep->ep.desc = NULL;
+
+       list_splice_init(&ep->queue, &req_list);
+       if (ep->can_dma) {
+               usba_dma_writel(ep, CONTROL, 0);
+               usba_dma_writel(ep, ADDRESS, 0);
+               usba_dma_readl(ep, STATUS);
+       }
+       usba_ep_writel(ep, CTL_DIS, USBA_EPT_ENABLE);
+       usba_writel(udc, INT_ENB,
+                       usba_readl(udc, INT_ENB)
+                       & ~USBA_BF(EPT_INT, 1 << ep->index));
+
+       request_complete_list(ep, &req_list, -ESHUTDOWN);
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static struct usb_request *
+usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct usba_request *req;
+
+       DBG(DBG_GADGET, "ep_alloc_request: %p, 0x%x\n", _ep, gfp_flags);
+
+       req = kzalloc(sizeof(*req), gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void
+usba_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct usba_request *req = to_usba_req(_req);
+
+       DBG(DBG_GADGET, "ep_free_request: %p, %p\n", _ep, _req);
+
+       kfree(req);
+}
+
+static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
+               struct usba_request *req, gfp_t gfp_flags)
+{
+       unsigned long flags;
+       int ret;
+
+       DBG(DBG_DMA, "%s: req l/%u d/%08x %c%c%c\n",
+               ep->ep.name, req->req.length, req->req.dma,
+               req->req.zero ? 'Z' : 'z',
+               req->req.short_not_ok ? 'S' : 's',
+               req->req.no_interrupt ? 'I' : 'i');
+
+       if (req->req.length > 0x10000) {
+               /* Lengths from 0 to 65536 (inclusive) are supported */
+               DBG(DBG_ERR, "invalid request length %u\n", req->req.length);
+               return -EINVAL;
+       }
+
+       ret = usb_gadget_map_request(&udc->gadget, &req->req, ep->is_in);
+       if (ret)
+               return ret;
+
+       req->using_dma = 1;
+       req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length)
+                       | USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE
+                       | USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE;
+
+       if (ep->is_in)
+               req->ctrl |= USBA_DMA_END_BUF_EN;
+
+       /*
+        * Add this request to the queue and submit for DMA if
+        * possible. Check if we're still alive first -- we may have
+        * received a reset since last time we checked.
+        */
+       ret = -ESHUTDOWN;
+       spin_lock_irqsave(&udc->lock, flags);
+       if (ep->ep.desc) {
+               if (list_empty(&ep->queue))
+                       submit_request(ep, req);
+
+               list_add_tail(&req->queue, &ep->queue);
+               ret = 0;
+       }
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return ret;
+}
+
+static int
+usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+       struct usba_request *req = to_usba_req(_req);
+       struct usba_ep *ep = to_usba_ep(_ep);
+       struct usba_udc *udc = ep->udc;
+       unsigned long flags;
+       int ret;
+
+       DBG(DBG_GADGET | DBG_QUEUE | DBG_REQ, "%s: queue req %p, len %u\n",
+                       ep->ep.name, req, _req->length);
+
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN ||
+           !ep->ep.desc)
+               return -ESHUTDOWN;
+
+       req->submitted = 0;
+       req->using_dma = 0;
+       req->last_transaction = 0;
+
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       if (ep->can_dma)
+               return queue_dma(udc, ep, req, gfp_flags);
+
+       /* May have received a reset since last time we checked */
+       ret = -ESHUTDOWN;
+       spin_lock_irqsave(&udc->lock, flags);
+       if (ep->ep.desc) {
+               list_add_tail(&req->queue, &ep->queue);
+
+               if ((!ep_is_control(ep) && ep->is_in) ||
+                       (ep_is_control(ep)
+                               && (ep->state == DATA_STAGE_IN
+                                       || ep->state == STATUS_STAGE_IN)))
+                       usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
+               else
+                       usba_ep_writel(ep, CTL_ENB, USBA_RX_BK_RDY);
+               ret = 0;
+       }
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return ret;
+}
+
+static void
+usba_update_req(struct usba_ep *ep, struct usba_request *req, u32 status)
+{
+       req->req.actual = req->req.length - USBA_BFEXT(DMA_BUF_LEN, status);
+}
+
+static int stop_dma(struct usba_ep *ep, u32 *pstatus)
+{
+       unsigned int timeout;
+       u32 status;
+
+       /*
+        * Stop the DMA controller. When writing both CH_EN
+        * and LINK to 0, the other bits are not affected.
+        */
+       usba_dma_writel(ep, CONTROL, 0);
+
+       /* Wait for the FIFO to empty */
+       for (timeout = 40; timeout; --timeout) {
+               status = usba_dma_readl(ep, STATUS);
+               if (!(status & USBA_DMA_CH_EN))
+                       break;
+               udelay(1);
+       }
+
+       if (pstatus)
+               *pstatus = status;
+
+       if (timeout == 0) {
+               dev_err(&ep->udc->pdev->dev,
+                       "%s: timed out waiting for DMA FIFO to empty\n",
+                       ep->ep.name);
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct usba_ep *ep = to_usba_ep(_ep);
+       struct usba_udc *udc = ep->udc;
+       struct usba_request *req = to_usba_req(_req);
+       unsigned long flags;
+       u32 status;
+
+       DBG(DBG_GADGET | DBG_QUEUE, "ep_dequeue: %s, req %p\n",
+                       ep->ep.name, req);
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       if (req->using_dma) {
+               /*
+                * If this request is currently being transferred,
+                * stop the DMA controller and reset the FIFO.
+                */
+               if (ep->queue.next == &req->queue) {
+                       status = usba_dma_readl(ep, STATUS);
+                       if (status & USBA_DMA_CH_EN)
+                               stop_dma(ep, &status);
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+                       ep->last_dma_status = status;
+#endif
+
+                       usba_writel(udc, EPT_RST, 1 << ep->index);
+
+                       usba_update_req(ep, req, status);
+               }
+       }
+
+       /*
+        * Errors should stop the queue from advancing until the
+        * completion function returns.
+        */
+       list_del_init(&req->queue);
+
+       request_complete(ep, req, -ECONNRESET);
+
+       /* Process the next request if any */
+       submit_next_request(ep);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static int usba_ep_set_halt(struct usb_ep *_ep, int value)
+{
+       struct usba_ep *ep = to_usba_ep(_ep);
+       struct usba_udc *udc = ep->udc;
+       unsigned long flags;
+       int ret = 0;
+
+       DBG(DBG_GADGET, "endpoint %s: %s HALT\n", ep->ep.name,
+                       value ? "set" : "clear");
+
+       if (!ep->ep.desc) {
+               DBG(DBG_ERR, "Attempted to halt uninitialized ep %s\n",
+                               ep->ep.name);
+               return -ENODEV;
+       }
+       if (ep->is_isoc) {
+               DBG(DBG_ERR, "Attempted to halt isochronous ep %s\n",
+                               ep->ep.name);
+               return -ENOTTY;
+       }
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /*
+        * We can't halt IN endpoints while there are still data to be
+        * transferred
+        */
+       if (!list_empty(&ep->queue)
+                       || ((value && ep->is_in && (usba_ep_readl(ep, STA)
+                                       & USBA_BF(BUSY_BANKS, -1L))))) {
+               ret = -EAGAIN;
+       } else {
+               if (value)
+                       usba_ep_writel(ep, SET_STA, USBA_FORCE_STALL);
+               else
+                       usba_ep_writel(ep, CLR_STA,
+                                       USBA_FORCE_STALL | USBA_TOGGLE_CLR);
+               usba_ep_readl(ep, STA);
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return ret;
+}
+
+static int usba_ep_fifo_status(struct usb_ep *_ep)
+{
+       struct usba_ep *ep = to_usba_ep(_ep);
+
+       return USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
+}
+
+static void usba_ep_fifo_flush(struct usb_ep *_ep)
+{
+       struct usba_ep *ep = to_usba_ep(_ep);
+       struct usba_udc *udc = ep->udc;
+
+       usba_writel(udc, EPT_RST, 1 << ep->index);
+}
+
+static const struct usb_ep_ops usba_ep_ops = {
+       .enable         = usba_ep_enable,
+       .disable        = usba_ep_disable,
+       .alloc_request  = usba_ep_alloc_request,
+       .free_request   = usba_ep_free_request,
+       .queue          = usba_ep_queue,
+       .dequeue        = usba_ep_dequeue,
+       .set_halt       = usba_ep_set_halt,
+       .fifo_status    = usba_ep_fifo_status,
+       .fifo_flush     = usba_ep_fifo_flush,
+};
+
+static int usba_udc_get_frame(struct usb_gadget *gadget)
+{
+       struct usba_udc *udc = to_usba_udc(gadget);
+
+       return USBA_BFEXT(FRAME_NUMBER, usba_readl(udc, FNUM));
+}
+
+static int usba_udc_wakeup(struct usb_gadget *gadget)
+{
+       struct usba_udc *udc = to_usba_udc(gadget);
+       unsigned long flags;
+       u32 ctrl;
+       int ret = -EINVAL;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       if (udc->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
+               ctrl = usba_readl(udc, CTRL);
+               usba_writel(udc, CTRL, ctrl | USBA_REMOTE_WAKE_UP);
+               ret = 0;
+       }
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return ret;
+}
+
+static int
+usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
+{
+       struct usba_udc *udc = to_usba_udc(gadget);
+       unsigned long flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       if (is_selfpowered)
+               udc->devstatus |= 1 << USB_DEVICE_SELF_POWERED;
+       else
+               udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static int atmel_usba_start(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver);
+static int atmel_usba_stop(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver);
+static const struct usb_gadget_ops usba_udc_ops = {
+       .get_frame              = usba_udc_get_frame,
+       .wakeup                 = usba_udc_wakeup,
+       .set_selfpowered        = usba_udc_set_selfpowered,
+       .udc_start              = atmel_usba_start,
+       .udc_stop               = atmel_usba_stop,
+};
+
+static struct usb_endpoint_descriptor usba_ep0_desc = {
+       .bLength = USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType = USB_DT_ENDPOINT,
+       .bEndpointAddress = 0,
+       .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
+       .wMaxPacketSize = cpu_to_le16(64),
+       /* FIXME: I have no idea what to put here */
+       .bInterval = 1,
+};
+
+static void nop_release(struct device *dev)
+{
+
+}
+
+static struct usb_gadget usba_gadget_template = {
+       .ops            = &usba_udc_ops,
+       .max_speed      = USB_SPEED_HIGH,
+       .name           = "atmel_usba_udc",
+       .dev    = {
+               .init_name      = "gadget",
+               .release        = nop_release,
+       },
+};
+
+/*
+ * Called with interrupts disabled and udc->lock held.
+ */
+static void reset_all_endpoints(struct usba_udc *udc)
+{
+       struct usba_ep *ep;
+       struct usba_request *req, *tmp_req;
+
+       usba_writel(udc, EPT_RST, ~0UL);
+
+       ep = to_usba_ep(udc->gadget.ep0);
+       list_for_each_entry_safe(req, tmp_req, &ep->queue, queue) {
+               list_del_init(&req->queue);
+               request_complete(ep, req, -ECONNRESET);
+       }
+
+       /* NOTE:  normally, the next call to the gadget driver is in
+        * charge of disabling endpoints... usually disconnect().
+        * The exception would be entering a high speed test mode.
+        *
+        * FIXME remove this code ... and retest thoroughly.
+        */
+       list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
+               if (ep->ep.desc) {
+                       spin_unlock(&udc->lock);
+                       usba_ep_disable(&ep->ep);
+                       spin_lock(&udc->lock);
+               }
+       }
+}
+
+static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex)
+{
+       struct usba_ep *ep;
+
+       if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
+               return to_usba_ep(udc->gadget.ep0);
+
+       list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) {
+               u8 bEndpointAddress;
+
+               if (!ep->ep.desc)
+                       continue;
+               bEndpointAddress = ep->ep.desc->bEndpointAddress;
+               if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
+                       continue;
+               if ((bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)
+                               == (wIndex & USB_ENDPOINT_NUMBER_MASK))
+                       return ep;
+       }
+
+       return NULL;
+}
+
+/* Called with interrupts disabled and udc->lock held */
+static inline void set_protocol_stall(struct usba_udc *udc, struct usba_ep *ep)
+{
+       usba_ep_writel(ep, SET_STA, USBA_FORCE_STALL);
+       ep->state = WAIT_FOR_SETUP;
+}
+
+static inline int is_stalled(struct usba_udc *udc, struct usba_ep *ep)
+{
+       if (usba_ep_readl(ep, STA) & USBA_FORCE_STALL)
+               return 1;
+       return 0;
+}
+
+static inline void set_address(struct usba_udc *udc, unsigned int addr)
+{
+       u32 regval;
+
+       DBG(DBG_BUS, "setting address %u...\n", addr);
+       regval = usba_readl(udc, CTRL);
+       regval = USBA_BFINS(DEV_ADDR, addr, regval);
+       usba_writel(udc, CTRL, regval);
+}
+
+static int do_test_mode(struct usba_udc *udc)
+{
+       static const char test_packet_buffer[] = {
+               /* JKJKJKJK * 9 */
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               /* JJKKJJKK * 8 */
+               0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+               /* JJKKJJKK * 8 */
+               0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+               /* JJJJJJJKKKKKKK * 8 */
+               0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+               /* JJJJJJJK * 8 */
+               0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD,
+               /* {JKKKKKKK * 10}, JK */
+               0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0x7E
+       };
+       struct usba_ep *ep;
+       struct device *dev = &udc->pdev->dev;
+       int test_mode;
+
+       test_mode = udc->test_mode;
+
+       /* Start from a clean slate */
+       reset_all_endpoints(udc);
+
+       switch (test_mode) {
+       case 0x0100:
+               /* Test_J */
+               usba_writel(udc, TST, USBA_TST_J_MODE);
+               dev_info(dev, "Entering Test_J mode...\n");
+               break;
+       case 0x0200:
+               /* Test_K */
+               usba_writel(udc, TST, USBA_TST_K_MODE);
+               dev_info(dev, "Entering Test_K mode...\n");
+               break;
+       case 0x0300:
+               /*
+                * Test_SE0_NAK: Force high-speed mode and set up ep0
+                * for Bulk IN transfers
+                */
+               ep = &udc->usba_ep[0];
+               usba_writel(udc, TST,
+                               USBA_BF(SPEED_CFG, USBA_SPEED_CFG_FORCE_HIGH));
+               usba_ep_writel(ep, CFG,
+                               USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64)
+                               | USBA_EPT_DIR_IN
+                               | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK)
+                               | USBA_BF(BK_NUMBER, 1));
+               if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) {
+                       set_protocol_stall(udc, ep);
+                       dev_err(dev, "Test_SE0_NAK: ep0 not mapped\n");
+               } else {
+                       usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
+                       dev_info(dev, "Entering Test_SE0_NAK mode...\n");
+               }
+               break;
+       case 0x0400:
+               /* Test_Packet */
+               ep = &udc->usba_ep[0];
+               usba_ep_writel(ep, CFG,
+                               USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64)
+                               | USBA_EPT_DIR_IN
+                               | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK)
+                               | USBA_BF(BK_NUMBER, 1));
+               if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) {
+                       set_protocol_stall(udc, ep);
+                       dev_err(dev, "Test_Packet: ep0 not mapped\n");
+               } else {
+                       usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
+                       usba_writel(udc, TST, USBA_TST_PKT_MODE);
+                       memcpy_toio(ep->fifo, test_packet_buffer,
+                                       sizeof(test_packet_buffer));
+                       usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+                       dev_info(dev, "Entering Test_Packet mode...\n");
+               }
+               break;
+       default:
+               dev_err(dev, "Invalid test mode: 0x%04x\n", test_mode);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* Avoid overly long expressions */
+static inline bool feature_is_dev_remote_wakeup(struct usb_ctrlrequest *crq)
+{
+       if (crq->wValue == cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP))
+               return true;
+       return false;
+}
+
+static inline bool feature_is_dev_test_mode(struct usb_ctrlrequest *crq)
+{
+       if (crq->wValue == cpu_to_le16(USB_DEVICE_TEST_MODE))
+               return true;
+       return false;
+}
+
+static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq)
+{
+       if (crq->wValue == cpu_to_le16(USB_ENDPOINT_HALT))
+               return true;
+       return false;
+}
+
+static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep,
+               struct usb_ctrlrequest *crq)
+{
+       int retval = 0;
+
+       switch (crq->bRequest) {
+       case USB_REQ_GET_STATUS: {
+               u16 status;
+
+               if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_DEVICE)) {
+                       status = cpu_to_le16(udc->devstatus);
+               } else if (crq->bRequestType
+                               == (USB_DIR_IN | USB_RECIP_INTERFACE)) {
+                       status = cpu_to_le16(0);
+               } else if (crq->bRequestType
+                               == (USB_DIR_IN | USB_RECIP_ENDPOINT)) {
+                       struct usba_ep *target;
+
+                       target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
+                       if (!target)
+                               goto stall;
+
+                       status = 0;
+                       if (is_stalled(udc, target))
+                               status |= cpu_to_le16(1);
+               } else
+                       goto delegate;
+
+               /* Write directly to the FIFO. No queueing is done. */
+               if (crq->wLength != cpu_to_le16(sizeof(status)))
+                       goto stall;
+               ep->state = DATA_STAGE_IN;
+               __raw_writew(status, ep->fifo);
+               usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+               break;
+       }
+
+       case USB_REQ_CLEAR_FEATURE: {
+               if (crq->bRequestType == USB_RECIP_DEVICE) {
+                       if (feature_is_dev_remote_wakeup(crq))
+                               udc->devstatus
+                                       &= ~(1 << USB_DEVICE_REMOTE_WAKEUP);
+                       else
+                               /* Can't CLEAR_FEATURE TEST_MODE */
+                               goto stall;
+               } else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
+                       struct usba_ep *target;
+
+                       if (crq->wLength != cpu_to_le16(0)
+                                       || !feature_is_ep_halt(crq))
+                               goto stall;
+                       target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
+                       if (!target)
+                               goto stall;
+
+                       usba_ep_writel(target, CLR_STA, USBA_FORCE_STALL);
+                       if (target->index != 0)
+                               usba_ep_writel(target, CLR_STA,
+                                               USBA_TOGGLE_CLR);
+               } else {
+                       goto delegate;
+               }
+
+               send_status(udc, ep);
+               break;
+       }
+
+       case USB_REQ_SET_FEATURE: {
+               if (crq->bRequestType == USB_RECIP_DEVICE) {
+                       if (feature_is_dev_test_mode(crq)) {
+                               send_status(udc, ep);
+                               ep->state = STATUS_STAGE_TEST;
+                               udc->test_mode = le16_to_cpu(crq->wIndex);
+                               return 0;
+                       } else if (feature_is_dev_remote_wakeup(crq)) {
+                               udc->devstatus |= 1 << USB_DEVICE_REMOTE_WAKEUP;
+                       } else {
+                               goto stall;
+                       }
+               } else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
+                       struct usba_ep *target;
+
+                       if (crq->wLength != cpu_to_le16(0)
+                                       || !feature_is_ep_halt(crq))
+                               goto stall;
+
+                       target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
+                       if (!target)
+                               goto stall;
+
+                       usba_ep_writel(target, SET_STA, USBA_FORCE_STALL);
+               } else
+                       goto delegate;
+
+               send_status(udc, ep);
+               break;
+       }
+
+       case USB_REQ_SET_ADDRESS:
+               if (crq->bRequestType != (USB_DIR_OUT | USB_RECIP_DEVICE))
+                       goto delegate;
+
+               set_address(udc, le16_to_cpu(crq->wValue));
+               send_status(udc, ep);
+               ep->state = STATUS_STAGE_ADDR;
+               break;
+
+       default:
+delegate:
+               spin_unlock(&udc->lock);
+               retval = udc->driver->setup(&udc->gadget, crq);
+               spin_lock(&udc->lock);
+       }
+
+       return retval;
+
+stall:
+       pr_err("udc: %s: Invalid setup request: %02x.%02x v%04x i%04x l%d, "
+               "halting endpoint...\n",
+               ep->ep.name, crq->bRequestType, crq->bRequest,
+               le16_to_cpu(crq->wValue), le16_to_cpu(crq->wIndex),
+               le16_to_cpu(crq->wLength));
+       set_protocol_stall(udc, ep);
+       return -1;
+}
+
+static void usba_control_irq(struct usba_udc *udc, struct usba_ep *ep)
+{
+       struct usba_request *req;
+       u32 epstatus;
+       u32 epctrl;
+
+restart:
+       epstatus = usba_ep_readl(ep, STA);
+       epctrl = usba_ep_readl(ep, CTL);
+
+       DBG(DBG_INT, "%s [%d]: s/%08x c/%08x\n",
+                       ep->ep.name, ep->state, epstatus, epctrl);
+
+       req = NULL;
+       if (!list_empty(&ep->queue))
+               req = list_entry(ep->queue.next,
+                                struct usba_request, queue);
+
+       if ((epctrl & USBA_TX_PK_RDY) && !(epstatus & USBA_TX_PK_RDY)) {
+               if (req->submitted)
+                       next_fifo_transaction(ep, req);
+               else
+                       submit_request(ep, req);
+
+               if (req->last_transaction) {
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
+                       usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
+               }
+               goto restart;
+       }
+       if ((epstatus & epctrl) & USBA_TX_COMPLETE) {
+               usba_ep_writel(ep, CLR_STA, USBA_TX_COMPLETE);
+
+               switch (ep->state) {
+               case DATA_STAGE_IN:
+                       usba_ep_writel(ep, CTL_ENB, USBA_RX_BK_RDY);
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+                       ep->state = STATUS_STAGE_OUT;
+                       break;
+               case STATUS_STAGE_ADDR:
+                       /* Activate our new address */
+                       usba_writel(udc, CTRL, (usba_readl(udc, CTRL)
+                                               | USBA_FADDR_EN));
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+                       ep->state = WAIT_FOR_SETUP;
+                       break;
+               case STATUS_STAGE_IN:
+                       if (req) {
+                               list_del_init(&req->queue);
+                               request_complete(ep, req, 0);
+                               submit_next_request(ep);
+                       }
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+                       ep->state = WAIT_FOR_SETUP;
+                       break;
+               case STATUS_STAGE_TEST:
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+                       ep->state = WAIT_FOR_SETUP;
+                       if (do_test_mode(udc))
+                               set_protocol_stall(udc, ep);
+                       break;
+               default:
+                       pr_err("udc: %s: TXCOMP: Invalid endpoint state %d, "
+                               "halting endpoint...\n",
+                               ep->ep.name, ep->state);
+                       set_protocol_stall(udc, ep);
+                       break;
+               }
+
+               goto restart;
+       }
+       if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
+               switch (ep->state) {
+               case STATUS_STAGE_OUT:
+                       usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
+                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+
+                       if (req) {
+                               list_del_init(&req->queue);
+                               request_complete(ep, req, 0);
+                       }
+                       ep->state = WAIT_FOR_SETUP;
+                       break;
+
+               case DATA_STAGE_OUT:
+                       receive_data(ep);
+                       break;
+
+               default:
+                       usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
+                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+                       pr_err("udc: %s: RXRDY: Invalid endpoint state %d, "
+                               "halting endpoint...\n",
+                               ep->ep.name, ep->state);
+                       set_protocol_stall(udc, ep);
+                       break;
+               }
+
+               goto restart;
+       }
+       if (epstatus & USBA_RX_SETUP) {
+               union {
+                       struct usb_ctrlrequest crq;
+                       unsigned long data[2];
+               } crq;
+               unsigned int pkt_len;
+               int ret;
+
+               if (ep->state != WAIT_FOR_SETUP) {
+                       /*
+                        * Didn't expect a SETUP packet at this
+                        * point. Clean up any pending requests (which
+                        * may be successful).
+                        */
+                       int status = -EPROTO;
+
+                       /*
+                        * RXRDY and TXCOMP are dropped when SETUP
+                        * packets arrive.  Just pretend we received
+                        * the status packet.
+                        */
+                       if (ep->state == STATUS_STAGE_OUT
+                                       || ep->state == STATUS_STAGE_IN) {
+                               usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+                               status = 0;
+                       }
+
+                       if (req) {
+                               list_del_init(&req->queue);
+                               request_complete(ep, req, status);
+                       }
+               }
+
+               pkt_len = USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
+               DBG(DBG_HW, "Packet length: %u\n", pkt_len);
+               if (pkt_len != sizeof(crq)) {
+                       pr_warning("udc: Invalid packet length %u "
+                               "(expected %zu)\n", pkt_len, sizeof(crq));
+                       set_protocol_stall(udc, ep);
+                       return;
+               }
+
+               DBG(DBG_FIFO, "Copying ctrl request from 0x%p:\n", ep->fifo);
+               memcpy_fromio(crq.data, ep->fifo, sizeof(crq));
+
+               /* Free up one bank in the FIFO so that we can
+                * generate or receive a reply right away. */
+               usba_ep_writel(ep, CLR_STA, USBA_RX_SETUP);
+
+               /* printk(KERN_DEBUG "setup: %d: %02x.%02x\n",
+                       ep->state, crq.crq.bRequestType,
+                       crq.crq.bRequest); */
+
+               if (crq.crq.bRequestType & USB_DIR_IN) {
+                       /*
+                        * The USB 2.0 spec states that "if wLength is
+                        * zero, there is no data transfer phase."
+                        * However, testusb #14 seems to actually
+                        * expect a data phase even if wLength = 0...
+                        */
+                       ep->state = DATA_STAGE_IN;
+               } else {
+                       if (crq.crq.wLength != cpu_to_le16(0))
+                               ep->state = DATA_STAGE_OUT;
+                       else
+                               ep->state = STATUS_STAGE_IN;
+               }
+
+               ret = -1;
+               if (ep->index == 0)
+                       ret = handle_ep0_setup(udc, ep, &crq.crq);
+               else {
+                       spin_unlock(&udc->lock);
+                       ret = udc->driver->setup(&udc->gadget, &crq.crq);
+                       spin_lock(&udc->lock);
+               }
+
+               DBG(DBG_BUS, "req %02x.%02x, length %d, state %d, ret %d\n",
+                       crq.crq.bRequestType, crq.crq.bRequest,
+                       le16_to_cpu(crq.crq.wLength), ep->state, ret);
+
+               if (ret < 0) {
+                       /* Let the host know that we failed */
+                       set_protocol_stall(udc, ep);
+               }
+       }
+}
+
+static void usba_ep_irq(struct usba_udc *udc, struct usba_ep *ep)
+{
+       struct usba_request *req;
+       u32 epstatus;
+       u32 epctrl;
+
+       epstatus = usba_ep_readl(ep, STA);
+       epctrl = usba_ep_readl(ep, CTL);
+
+       DBG(DBG_INT, "%s: interrupt, status: 0x%08x\n", ep->ep.name, epstatus);
+
+       while ((epctrl & USBA_TX_PK_RDY) && !(epstatus & USBA_TX_PK_RDY)) {
+               DBG(DBG_BUS, "%s: TX PK ready\n", ep->ep.name);
+
+               if (list_empty(&ep->queue)) {
+                       dev_warn(&udc->pdev->dev, "ep_irq: queue empty\n");
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
+                       return;
+               }
+
+               req = list_entry(ep->queue.next, struct usba_request, queue);
+
+               if (req->using_dma) {
+                       /* Send a zero-length packet */
+                       usba_ep_writel(ep, SET_STA,
+                                       USBA_TX_PK_RDY);
+                       usba_ep_writel(ep, CTL_DIS,
+                                       USBA_TX_PK_RDY);
+                       list_del_init(&req->queue);
+                       submit_next_request(ep);
+                       request_complete(ep, req, 0);
+               } else {
+                       if (req->submitted)
+                               next_fifo_transaction(ep, req);
+                       else
+                               submit_request(ep, req);
+
+                       if (req->last_transaction) {
+                               list_del_init(&req->queue);
+                               submit_next_request(ep);
+                               request_complete(ep, req, 0);
+                       }
+               }
+
+               epstatus = usba_ep_readl(ep, STA);
+               epctrl = usba_ep_readl(ep, CTL);
+       }
+       if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
+               DBG(DBG_BUS, "%s: RX data ready\n", ep->ep.name);
+               receive_data(ep);
+               usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
+       }
+}
+
+static void usba_dma_irq(struct usba_udc *udc, struct usba_ep *ep)
+{
+       struct usba_request *req;
+       u32 status, control, pending;
+
+       status = usba_dma_readl(ep, STATUS);
+       control = usba_dma_readl(ep, CONTROL);
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+       ep->last_dma_status = status;
+#endif
+       pending = status & control;
+       DBG(DBG_INT | DBG_DMA, "dma irq, s/%#08x, c/%#08x\n", status, control);
+
+       if (status & USBA_DMA_CH_EN) {
+               dev_err(&udc->pdev->dev,
+                       "DMA_CH_EN is set after transfer is finished!\n");
+               dev_err(&udc->pdev->dev,
+                       "status=%#08x, pending=%#08x, control=%#08x\n",
+                       status, pending, control);
+
+               /*
+                * try to pretend nothing happened. We might have to
+                * do something here...
+                */
+       }
+
+       if (list_empty(&ep->queue))
+               /* Might happen if a reset comes along at the right moment */
+               return;
+
+       if (pending & (USBA_DMA_END_TR_ST | USBA_DMA_END_BUF_ST)) {
+               req = list_entry(ep->queue.next, struct usba_request, queue);
+               usba_update_req(ep, req, status);
+
+               list_del_init(&req->queue);
+               submit_next_request(ep);
+               request_complete(ep, req, 0);
+       }
+}
+
+static irqreturn_t usba_udc_irq(int irq, void *devid)
+{
+       struct usba_udc *udc = devid;
+       u32 status;
+       u32 dma_status;
+       u32 ep_status;
+
+       spin_lock(&udc->lock);
+
+       status = usba_readl(udc, INT_STA);
+       DBG(DBG_INT, "irq, status=%#08x\n", status);
+
+       if (status & USBA_DET_SUSPEND) {
+               toggle_bias(0);
+               usba_writel(udc, INT_CLR, USBA_DET_SUSPEND);
+               DBG(DBG_BUS, "Suspend detected\n");
+               if (udc->gadget.speed != USB_SPEED_UNKNOWN
+                               && udc->driver && udc->driver->suspend) {
+                       spin_unlock(&udc->lock);
+                       udc->driver->suspend(&udc->gadget);
+                       spin_lock(&udc->lock);
+               }
+       }
+
+       if (status & USBA_WAKE_UP) {
+               toggle_bias(1);
+               usba_writel(udc, INT_CLR, USBA_WAKE_UP);
+               DBG(DBG_BUS, "Wake Up CPU detected\n");
+       }
+
+       if (status & USBA_END_OF_RESUME) {
+               usba_writel(udc, INT_CLR, USBA_END_OF_RESUME);
+               DBG(DBG_BUS, "Resume detected\n");
+               if (udc->gadget.speed != USB_SPEED_UNKNOWN
+                               && udc->driver && udc->driver->resume) {
+                       spin_unlock(&udc->lock);
+                       udc->driver->resume(&udc->gadget);
+                       spin_lock(&udc->lock);
+               }
+       }
+
+       dma_status = USBA_BFEXT(DMA_INT, status);
+       if (dma_status) {
+               int i;
+
+               for (i = 1; i < USBA_NR_DMAS; i++)
+                       if (dma_status & (1 << i))
+                               usba_dma_irq(udc, &udc->usba_ep[i]);
+       }
+
+       ep_status = USBA_BFEXT(EPT_INT, status);
+       if (ep_status) {
+               int i;
+
+               for (i = 0; i < udc->num_ep; i++)
+                       if (ep_status & (1 << i)) {
+                               if (ep_is_control(&udc->usba_ep[i]))
+                                       usba_control_irq(udc, &udc->usba_ep[i]);
+                               else
+                                       usba_ep_irq(udc, &udc->usba_ep[i]);
+                       }
+       }
+
+       if (status & USBA_END_OF_RESET) {
+               struct usba_ep *ep0;
+
+               usba_writel(udc, INT_CLR, USBA_END_OF_RESET);
+               reset_all_endpoints(udc);
+
+               if (udc->gadget.speed != USB_SPEED_UNKNOWN
+                               && udc->driver && udc->driver->disconnect) {
+                       udc->gadget.speed = USB_SPEED_UNKNOWN;
+                       spin_unlock(&udc->lock);
+                       udc->driver->disconnect(&udc->gadget);
+                       spin_lock(&udc->lock);
+               }
+
+               if (status & USBA_HIGH_SPEED)
+                       udc->gadget.speed = USB_SPEED_HIGH;
+               else
+                       udc->gadget.speed = USB_SPEED_FULL;
+               DBG(DBG_BUS, "%s bus reset detected\n",
+                   usb_speed_string(udc->gadget.speed));
+
+               ep0 = &udc->usba_ep[0];
+               ep0->ep.desc = &usba_ep0_desc;
+               ep0->state = WAIT_FOR_SETUP;
+               usba_ep_writel(ep0, CFG,
+                               (USBA_BF(EPT_SIZE, EP0_EPT_SIZE)
+                               | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL)
+                               | USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE)));
+               usba_ep_writel(ep0, CTL_ENB,
+                               USBA_EPT_ENABLE | USBA_RX_SETUP);
+               usba_writel(udc, INT_ENB,
+                               (usba_readl(udc, INT_ENB)
+                               | USBA_BF(EPT_INT, 1)
+                               | USBA_DET_SUSPEND
+                               | USBA_END_OF_RESUME));
+
+               /*
+                * Unclear why we hit this irregularly, e.g. in usbtest,
+                * but it's clearly harmless...
+                */
+               if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED))
+                       dev_dbg(&udc->pdev->dev,
+                                "ODD: EP0 configuration is invalid!\n");
+       }
+
+       spin_unlock(&udc->lock);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t usba_vbus_irq(int irq, void *devid)
+{
+       struct usba_udc *udc = devid;
+       int vbus;
+
+       /* debounce */
+       udelay(10);
+
+       spin_lock(&udc->lock);
+
+       /* May happen if Vbus pin toggles during probe() */
+       if (!udc->driver)
+               goto out;
+
+       vbus = vbus_is_present(udc);
+       if (vbus != udc->vbus_prev) {
+               if (vbus) {
+                       toggle_bias(1);
+                       usba_writel(udc, CTRL, USBA_ENABLE_MASK);
+                       usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
+               } else {
+                       udc->gadget.speed = USB_SPEED_UNKNOWN;
+                       reset_all_endpoints(udc);
+                       toggle_bias(0);
+                       usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+                       if (udc->driver->disconnect) {
+                               spin_unlock(&udc->lock);
+                               udc->driver->disconnect(&udc->gadget);
+                               spin_lock(&udc->lock);
+                       }
+               }
+               udc->vbus_prev = vbus;
+       }
+
+out:
+       spin_unlock(&udc->lock);
+
+       return IRQ_HANDLED;
+}
+
+static int atmel_usba_start(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       int ret;
+       struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
+       unsigned long flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
+       udc->driver = driver;
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       ret = clk_prepare_enable(udc->pclk);
+       if (ret)
+               return ret;
+       ret = clk_prepare_enable(udc->hclk);
+       if (ret) {
+               clk_disable_unprepare(udc->pclk);
+               return ret;
+       }
+
+       DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name);
+
+       udc->vbus_prev = 0;
+       if (gpio_is_valid(udc->vbus_pin))
+               enable_irq(gpio_to_irq(udc->vbus_pin));
+
+       /* If Vbus is present, enable the controller and wait for reset */
+       spin_lock_irqsave(&udc->lock, flags);
+       if (vbus_is_present(udc) && udc->vbus_prev == 0) {
+               toggle_bias(1);
+               usba_writel(udc, CTRL, USBA_ENABLE_MASK);
+               usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
+       }
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static int atmel_usba_stop(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
+       unsigned long flags;
+
+       if (gpio_is_valid(udc->vbus_pin))
+               disable_irq(gpio_to_irq(udc->vbus_pin));
+
+       spin_lock_irqsave(&udc->lock, flags);
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       reset_all_endpoints(udc);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       /* This will also disable the DP pullup */
+       toggle_bias(0);
+       usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+
+       clk_disable_unprepare(udc->hclk);
+       clk_disable_unprepare(udc->pclk);
+
+       DBG(DBG_GADGET, "unregistered driver `%s'\n", udc->driver->driver.name);
+
+       udc->driver = NULL;
+
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
+                                                   struct usba_udc *udc)
+{
+       u32 val;
+       const char *name;
+       enum of_gpio_flags flags;
+       struct device_node *np = pdev->dev.of_node;
+       struct device_node *pp;
+       int i, ret;
+       struct usba_ep *eps, *ep;
+
+       udc->num_ep = 0;
+
+       udc->vbus_pin = of_get_named_gpio_flags(np, "atmel,vbus-gpio", 0,
+                                               &flags);
+       udc->vbus_pin_inverted = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
+
+       pp = NULL;
+       while ((pp = of_get_next_child(np, pp)))
+               udc->num_ep++;
+
+       eps = devm_kzalloc(&pdev->dev, sizeof(struct usba_ep) * udc->num_ep,
+                          GFP_KERNEL);
+       if (!eps)
+               return ERR_PTR(-ENOMEM);
+
+       udc->gadget.ep0 = &eps[0].ep;
+
+       INIT_LIST_HEAD(&eps[0].ep.ep_list);
+
+       pp = NULL;
+       i = 0;
+       while ((pp = of_get_next_child(np, pp))) {
+               ep = &eps[i];
+
+               ret = of_property_read_u32(pp, "reg", &val);
+               if (ret) {
+                       dev_err(&pdev->dev, "of_probe: reg error(%d)\n", ret);
+                       goto err;
+               }
+               ep->index = val;
+
+               ret = of_property_read_u32(pp, "atmel,fifo-size", &val);
+               if (ret) {
+                       dev_err(&pdev->dev, "of_probe: fifo-size error(%d)\n", ret);
+                       goto err;
+               }
+               ep->fifo_size = val;
+
+               ret = of_property_read_u32(pp, "atmel,nb-banks", &val);
+               if (ret) {
+                       dev_err(&pdev->dev, "of_probe: nb-banks error(%d)\n", ret);
+                       goto err;
+               }
+               ep->nr_banks = val;
+
+               ep->can_dma = of_property_read_bool(pp, "atmel,can-dma");
+               ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc");
+
+               ret = of_property_read_string(pp, "name", &name);
+               ep->ep.name = name;
+
+               ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
+               ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
+               ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
+               ep->ep.ops = &usba_ep_ops;
+               usb_ep_set_maxpacket_limit(&ep->ep, ep->fifo_size);
+               ep->udc = udc;
+               INIT_LIST_HEAD(&ep->queue);
+
+               if (i)
+                       list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+
+               i++;
+       }
+
+       if (i == 0) {
+               dev_err(&pdev->dev, "of_probe: no endpoint specified\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       return eps;
+err:
+       return ERR_PTR(ret);
+}
+#else
+static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
+                                                   struct usba_udc *udc)
+{
+       return ERR_PTR(-ENOSYS);
+}
+#endif
+
+static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
+                                                struct usba_udc *udc)
+{
+       struct usba_platform_data *pdata = dev_get_platdata(&pdev->dev);
+       struct usba_ep *eps;
+       int i;
+
+       if (!pdata)
+               return ERR_PTR(-ENXIO);
+
+       eps = devm_kzalloc(&pdev->dev, sizeof(struct usba_ep) * pdata->num_ep,
+                          GFP_KERNEL);
+       if (!eps)
+               return ERR_PTR(-ENOMEM);
+
+       udc->gadget.ep0 = &eps[0].ep;
+
+       udc->vbus_pin = pdata->vbus_pin;
+       udc->vbus_pin_inverted = pdata->vbus_pin_inverted;
+       udc->num_ep = pdata->num_ep;
+
+       INIT_LIST_HEAD(&eps[0].ep.ep_list);
+
+       for (i = 0; i < pdata->num_ep; i++) {
+               struct usba_ep *ep = &eps[i];
+
+               ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
+               ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
+               ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
+               ep->ep.ops = &usba_ep_ops;
+               ep->ep.name = pdata->ep[i].name;
+               ep->fifo_size = pdata->ep[i].fifo_size;
+               usb_ep_set_maxpacket_limit(&ep->ep, ep->fifo_size);
+               ep->udc = udc;
+               INIT_LIST_HEAD(&ep->queue);
+               ep->nr_banks = pdata->ep[i].nr_banks;
+               ep->index = pdata->ep[i].index;
+               ep->can_dma = pdata->ep[i].can_dma;
+               ep->can_isoc = pdata->ep[i].can_isoc;
+
+               if (i)
+                       list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+       }
+
+       return eps;
+}
+
+static int usba_udc_probe(struct platform_device *pdev)
+{
+       struct resource *regs, *fifo;
+       struct clk *pclk, *hclk;
+       struct usba_udc *udc;
+       int irq, ret, i;
+
+       udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL);
+       if (!udc)
+               return -ENOMEM;
+
+       udc->gadget = usba_gadget_template;
+       INIT_LIST_HEAD(&udc->gadget.ep_list);
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID);
+       fifo = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID);
+       if (!regs || !fifo)
+               return -ENXIO;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+
+       pclk = devm_clk_get(&pdev->dev, "pclk");
+       if (IS_ERR(pclk))
+               return PTR_ERR(pclk);
+       hclk = devm_clk_get(&pdev->dev, "hclk");
+       if (IS_ERR(hclk))
+               return PTR_ERR(hclk);
+
+       spin_lock_init(&udc->lock);
+       udc->pdev = pdev;
+       udc->pclk = pclk;
+       udc->hclk = hclk;
+       udc->vbus_pin = -ENODEV;
+
+       ret = -ENOMEM;
+       udc->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
+       if (!udc->regs) {
+               dev_err(&pdev->dev, "Unable to map I/O memory, aborting.\n");
+               return ret;
+       }
+       dev_info(&pdev->dev, "MMIO registers at 0x%08lx mapped at %p\n",
+                (unsigned long)regs->start, udc->regs);
+       udc->fifo = devm_ioremap(&pdev->dev, fifo->start, resource_size(fifo));
+       if (!udc->fifo) {
+               dev_err(&pdev->dev, "Unable to map FIFO, aborting.\n");
+               return ret;
+       }
+       dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
+                (unsigned long)fifo->start, udc->fifo);
+
+       platform_set_drvdata(pdev, udc);
+
+       /* Make sure we start from a clean slate */
+       ret = clk_prepare_enable(pclk);
+       if (ret) {
+               dev_err(&pdev->dev, "Unable to enable pclk, aborting.\n");
+               return ret;
+       }
+       toggle_bias(0);
+       usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+       clk_disable_unprepare(pclk);
+
+       if (pdev->dev.of_node)
+               udc->usba_ep = atmel_udc_of_init(pdev, udc);
+       else
+               udc->usba_ep = usba_udc_pdata(pdev, udc);
+
+       if (IS_ERR(udc->usba_ep))
+               return PTR_ERR(udc->usba_ep);
+
+       ret = devm_request_irq(&pdev->dev, irq, usba_udc_irq, 0,
+                               "atmel_usba_udc", udc);
+       if (ret) {
+               dev_err(&pdev->dev, "Cannot request irq %d (error %d)\n",
+                       irq, ret);
+               return ret;
+       }
+       udc->irq = irq;
+
+       if (gpio_is_valid(udc->vbus_pin)) {
+               if (!devm_gpio_request(&pdev->dev, udc->vbus_pin, "atmel_usba_udc")) {
+                       ret = devm_request_irq(&pdev->dev,
+                                       gpio_to_irq(udc->vbus_pin),
+                                       usba_vbus_irq, 0,
+                                       "atmel_usba_udc", udc);
+                       if (ret) {
+                               udc->vbus_pin = -ENODEV;
+                               dev_warn(&udc->pdev->dev,
+                                        "failed to request vbus irq; "
+                                        "assuming always on\n");
+                       } else {
+                               disable_irq(gpio_to_irq(udc->vbus_pin));
+                       }
+               } else {
+                       /* gpio_request fail so use -EINVAL for gpio_is_valid */
+                       udc->vbus_pin = -EINVAL;
+               }
+       }
+
+       ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
+       if (ret)
+               return ret;
+
+       usba_init_debugfs(udc);
+       for (i = 1; i < udc->num_ep; i++)
+               usba_ep_init_debugfs(udc, &udc->usba_ep[i]);
+
+       return 0;
+}
+
+static int __exit usba_udc_remove(struct platform_device *pdev)
+{
+       struct usba_udc *udc;
+       int i;
+
+       udc = platform_get_drvdata(pdev);
+
+       usb_del_gadget_udc(&udc->gadget);
+
+       for (i = 1; i < udc->num_ep; i++)
+               usba_ep_cleanup_debugfs(&udc->usba_ep[i]);
+       usba_cleanup_debugfs(udc);
+
+       return 0;
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id atmel_udc_dt_ids[] = {
+       { .compatible = "atmel,at91sam9rl-udc" },
+       { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, atmel_udc_dt_ids);
+#endif
+
+static struct platform_driver udc_driver = {
+       .remove         = __exit_p(usba_udc_remove),
+       .driver         = {
+               .name           = "atmel_usba_udc",
+               .owner          = THIS_MODULE,
+               .of_match_table = of_match_ptr(atmel_udc_dt_ids),
+       },
+};
+
+module_platform_driver_probe(udc_driver, usba_udc_probe);
+
+MODULE_DESCRIPTION("Atmel USBA UDC driver");
+MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:atmel_usba_udc");
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.h b/drivers/usb/gadget/udc/atmel_usba_udc.h
new file mode 100644 (file)
index 0000000..a70706e
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * Driver for the Atmel USBA high speed USB device controller
+ *
+ * Copyright (C) 2005-2007 Atmel Corporation
+ *
+ * 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.
+ */
+#ifndef __LINUX_USB_GADGET_USBA_UDC_H__
+#define __LINUX_USB_GADGET_USBA_UDC_H__
+
+/* USB register offsets */
+#define USBA_CTRL                              0x0000
+#define USBA_FNUM                              0x0004
+#define USBA_INT_ENB                           0x0010
+#define USBA_INT_STA                           0x0014
+#define USBA_INT_CLR                           0x0018
+#define USBA_EPT_RST                           0x001c
+#define USBA_TST                               0x00e0
+
+/* USB endpoint register offsets */
+#define USBA_EPT_CFG                           0x0000
+#define USBA_EPT_CTL_ENB                       0x0004
+#define USBA_EPT_CTL_DIS                       0x0008
+#define USBA_EPT_CTL                           0x000c
+#define USBA_EPT_SET_STA                       0x0014
+#define USBA_EPT_CLR_STA                       0x0018
+#define USBA_EPT_STA                           0x001c
+
+/* USB DMA register offsets */
+#define USBA_DMA_NXT_DSC                       0x0000
+#define USBA_DMA_ADDRESS                       0x0004
+#define USBA_DMA_CONTROL                       0x0008
+#define USBA_DMA_STATUS                                0x000c
+
+/* Bitfields in CTRL */
+#define USBA_DEV_ADDR_OFFSET                   0
+#define USBA_DEV_ADDR_SIZE                     7
+#define USBA_FADDR_EN                          (1 <<  7)
+#define USBA_EN_USBA                           (1 <<  8)
+#define USBA_DETACH                            (1 <<  9)
+#define USBA_REMOTE_WAKE_UP                    (1 << 10)
+#define USBA_PULLD_DIS                         (1 << 11)
+
+#if defined(CONFIG_AVR32)
+#define USBA_ENABLE_MASK                       USBA_EN_USBA
+#define USBA_DISABLE_MASK                      0
+#elif defined(CONFIG_ARCH_AT91)
+#define USBA_ENABLE_MASK                       (USBA_EN_USBA | USBA_PULLD_DIS)
+#define USBA_DISABLE_MASK                      USBA_DETACH
+#endif /* CONFIG_ARCH_AT91 */
+
+/* Bitfields in FNUM */
+#define USBA_MICRO_FRAME_NUM_OFFSET            0
+#define USBA_MICRO_FRAME_NUM_SIZE              3
+#define USBA_FRAME_NUMBER_OFFSET               3
+#define USBA_FRAME_NUMBER_SIZE                 11
+#define USBA_FRAME_NUM_ERROR                   (1 << 31)
+
+/* Bitfields in INT_ENB/INT_STA/INT_CLR */
+#define USBA_HIGH_SPEED                                (1 <<  0)
+#define USBA_DET_SUSPEND                       (1 <<  1)
+#define USBA_MICRO_SOF                         (1 <<  2)
+#define USBA_SOF                               (1 <<  3)
+#define USBA_END_OF_RESET                      (1 <<  4)
+#define USBA_WAKE_UP                           (1 <<  5)
+#define USBA_END_OF_RESUME                     (1 <<  6)
+#define USBA_UPSTREAM_RESUME                   (1 <<  7)
+#define USBA_EPT_INT_OFFSET                    8
+#define USBA_EPT_INT_SIZE                      16
+#define USBA_DMA_INT_OFFSET                    24
+#define USBA_DMA_INT_SIZE                      8
+
+/* Bitfields in EPT_RST */
+#define USBA_RST_OFFSET                                0
+#define USBA_RST_SIZE                          16
+
+/* Bitfields in USBA_TST */
+#define USBA_SPEED_CFG_OFFSET                  0
+#define USBA_SPEED_CFG_SIZE                    2
+#define USBA_TST_J_MODE                                (1 <<  2)
+#define USBA_TST_K_MODE                                (1 <<  3)
+#define USBA_TST_PKT_MODE                      (1 <<  4)
+#define USBA_OPMODE2                           (1 <<  5)
+
+/* Bitfields in EPT_CFG */
+#define USBA_EPT_SIZE_OFFSET                   0
+#define USBA_EPT_SIZE_SIZE                     3
+#define USBA_EPT_DIR_IN                                (1 <<  3)
+#define USBA_EPT_TYPE_OFFSET                   4
+#define USBA_EPT_TYPE_SIZE                     2
+#define USBA_BK_NUMBER_OFFSET                  6
+#define USBA_BK_NUMBER_SIZE                    2
+#define USBA_NB_TRANS_OFFSET                   8
+#define USBA_NB_TRANS_SIZE                     2
+#define USBA_EPT_MAPPED                                (1 << 31)
+
+/* Bitfields in EPT_CTL/EPT_CTL_ENB/EPT_CTL_DIS */
+#define USBA_EPT_ENABLE                                (1 <<  0)
+#define USBA_AUTO_VALID                                (1 <<  1)
+#define USBA_INTDIS_DMA                                (1 <<  3)
+#define USBA_NYET_DIS                          (1 <<  4)
+#define USBA_DATAX_RX                          (1 <<  6)
+#define USBA_MDATA_RX                          (1 <<  7)
+/* Bits 8-15 and 31 enable interrupts for respective bits in EPT_STA */
+#define USBA_BUSY_BANK_IE                      (1 << 18)
+
+/* Bitfields in EPT_SET_STA/EPT_CLR_STA/EPT_STA */
+#define USBA_FORCE_STALL                       (1 <<  5)
+#define USBA_TOGGLE_CLR                                (1 <<  6)
+#define USBA_TOGGLE_SEQ_OFFSET                 6
+#define USBA_TOGGLE_SEQ_SIZE                   2
+#define USBA_ERR_OVFLW                         (1 <<  8)
+#define USBA_RX_BK_RDY                         (1 <<  9)
+#define USBA_KILL_BANK                         (1 <<  9)
+#define USBA_TX_COMPLETE                       (1 << 10)
+#define USBA_TX_PK_RDY                         (1 << 11)
+#define USBA_ISO_ERR_TRANS                     (1 << 11)
+#define USBA_RX_SETUP                          (1 << 12)
+#define USBA_ISO_ERR_FLOW                      (1 << 12)
+#define USBA_STALL_SENT                                (1 << 13)
+#define USBA_ISO_ERR_CRC                       (1 << 13)
+#define USBA_ISO_ERR_NBTRANS                   (1 << 13)
+#define USBA_NAK_IN                            (1 << 14)
+#define USBA_ISO_ERR_FLUSH                     (1 << 14)
+#define USBA_NAK_OUT                           (1 << 15)
+#define USBA_CURRENT_BANK_OFFSET               16
+#define USBA_CURRENT_BANK_SIZE                 2
+#define USBA_BUSY_BANKS_OFFSET                 18
+#define USBA_BUSY_BANKS_SIZE                   2
+#define USBA_BYTE_COUNT_OFFSET                 20
+#define USBA_BYTE_COUNT_SIZE                   11
+#define USBA_SHORT_PACKET                      (1 << 31)
+
+/* Bitfields in DMA_CONTROL */
+#define USBA_DMA_CH_EN                         (1 <<  0)
+#define USBA_DMA_LINK                          (1 <<  1)
+#define USBA_DMA_END_TR_EN                     (1 <<  2)
+#define USBA_DMA_END_BUF_EN                    (1 <<  3)
+#define USBA_DMA_END_TR_IE                     (1 <<  4)
+#define USBA_DMA_END_BUF_IE                    (1 <<  5)
+#define USBA_DMA_DESC_LOAD_IE                  (1 <<  6)
+#define USBA_DMA_BURST_LOCK                    (1 <<  7)
+#define USBA_DMA_BUF_LEN_OFFSET                        16
+#define USBA_DMA_BUF_LEN_SIZE                  16
+
+/* Bitfields in DMA_STATUS */
+#define USBA_DMA_CH_ACTIVE                     (1 <<  1)
+#define USBA_DMA_END_TR_ST                     (1 <<  4)
+#define USBA_DMA_END_BUF_ST                    (1 <<  5)
+#define USBA_DMA_DESC_LOAD_ST                  (1 <<  6)
+
+/* Constants for SPEED_CFG */
+#define USBA_SPEED_CFG_NORMAL                  0
+#define USBA_SPEED_CFG_FORCE_HIGH              2
+#define USBA_SPEED_CFG_FORCE_FULL              3
+
+/* Constants for EPT_SIZE */
+#define USBA_EPT_SIZE_8                                0
+#define USBA_EPT_SIZE_16                       1
+#define USBA_EPT_SIZE_32                       2
+#define USBA_EPT_SIZE_64                       3
+#define USBA_EPT_SIZE_128                      4
+#define USBA_EPT_SIZE_256                      5
+#define USBA_EPT_SIZE_512                      6
+#define USBA_EPT_SIZE_1024                     7
+
+/* Constants for EPT_TYPE */
+#define USBA_EPT_TYPE_CONTROL                  0
+#define USBA_EPT_TYPE_ISO                      1
+#define USBA_EPT_TYPE_BULK                     2
+#define USBA_EPT_TYPE_INT                      3
+
+/* Constants for BK_NUMBER */
+#define USBA_BK_NUMBER_ZERO                    0
+#define USBA_BK_NUMBER_ONE                     1
+#define USBA_BK_NUMBER_DOUBLE                  2
+#define USBA_BK_NUMBER_TRIPLE                  3
+
+/* Bit manipulation macros */
+#define USBA_BF(name, value)                                   \
+       (((value) & ((1 << USBA_##name##_SIZE) - 1))            \
+        << USBA_##name##_OFFSET)
+#define USBA_BFEXT(name, value)                                        \
+       (((value) >> USBA_##name##_OFFSET)                      \
+        & ((1 << USBA_##name##_SIZE) - 1))
+#define USBA_BFINS(name, value, old)                           \
+       (((old) & ~(((1 << USBA_##name##_SIZE) - 1)             \
+                   << USBA_##name##_OFFSET))                   \
+        | USBA_BF(name, value))
+
+/* Register access macros */
+#define usba_readl(udc, reg)                                   \
+       __raw_readl((udc)->regs + USBA_##reg)
+#define usba_writel(udc, reg, value)                           \
+       __raw_writel((value), (udc)->regs + USBA_##reg)
+#define usba_ep_readl(ep, reg)                                 \
+       __raw_readl((ep)->ep_regs + USBA_EPT_##reg)
+#define usba_ep_writel(ep, reg, value)                         \
+       __raw_writel((value), (ep)->ep_regs + USBA_EPT_##reg)
+#define usba_dma_readl(ep, reg)                                        \
+       __raw_readl((ep)->dma_regs + USBA_DMA_##reg)
+#define usba_dma_writel(ep, reg, value)                                \
+       __raw_writel((value), (ep)->dma_regs + USBA_DMA_##reg)
+
+/* Calculate base address for a given endpoint or DMA controller */
+#define USBA_EPT_BASE(x)       (0x100 + (x) * 0x20)
+#define USBA_DMA_BASE(x)       (0x300 + (x) * 0x10)
+#define USBA_FIFO_BASE(x)      ((x) << 16)
+
+/* Synth parameters */
+#define USBA_NR_DMAS           7
+
+#define EP0_FIFO_SIZE          64
+#define EP0_EPT_SIZE           USBA_EPT_SIZE_64
+#define EP0_NR_BANKS           1
+
+#define FIFO_IOMEM_ID  0
+#define CTRL_IOMEM_ID  1
+
+#define DBG_ERR                0x0001  /* report all error returns */
+#define DBG_HW         0x0002  /* debug hardware initialization */
+#define DBG_GADGET     0x0004  /* calls to/from gadget driver */
+#define DBG_INT                0x0008  /* interrupts */
+#define DBG_BUS                0x0010  /* report changes in bus state */
+#define DBG_QUEUE      0x0020  /* debug request queue processing */
+#define DBG_FIFO       0x0040  /* debug FIFO contents */
+#define DBG_DMA                0x0080  /* debug DMA handling */
+#define DBG_REQ                0x0100  /* print out queued request length */
+#define DBG_ALL                0xffff
+#define DBG_NONE       0x0000
+
+#define DEBUG_LEVEL    (DBG_ERR)
+
+#define DBG(level, fmt, ...)                                   \
+       do {                                                    \
+               if ((level) & DEBUG_LEVEL)                      \
+                       pr_debug("udc: " fmt, ## __VA_ARGS__);  \
+       } while (0)
+
+enum usba_ctrl_state {
+       WAIT_FOR_SETUP,
+       DATA_STAGE_IN,
+       DATA_STAGE_OUT,
+       STATUS_STAGE_IN,
+       STATUS_STAGE_OUT,
+       STATUS_STAGE_ADDR,
+       STATUS_STAGE_TEST,
+};
+/*
+  EP_STATE_IDLE,
+  EP_STATE_SETUP,
+  EP_STATE_IN_DATA,
+  EP_STATE_OUT_DATA,
+  EP_STATE_SET_ADDR_STATUS,
+  EP_STATE_RX_STATUS,
+  EP_STATE_TX_STATUS,
+  EP_STATE_HALT,
+*/
+
+struct usba_dma_desc {
+       dma_addr_t next;
+       dma_addr_t addr;
+       u32 ctrl;
+};
+
+struct usba_ep {
+       int                                     state;
+       void __iomem                            *ep_regs;
+       void __iomem                            *dma_regs;
+       void __iomem                            *fifo;
+       struct usb_ep                           ep;
+       struct usba_udc                         *udc;
+
+       struct list_head                        queue;
+
+       u16                                     fifo_size;
+       u8                                      nr_banks;
+       u8                                      index;
+       unsigned int                            can_dma:1;
+       unsigned int                            can_isoc:1;
+       unsigned int                            is_isoc:1;
+       unsigned int                            is_in:1;
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+       u32                                     last_dma_status;
+       struct dentry                           *debugfs_dir;
+       struct dentry                           *debugfs_queue;
+       struct dentry                           *debugfs_dma_status;
+       struct dentry                           *debugfs_state;
+#endif
+};
+
+struct usba_request {
+       struct usb_request                      req;
+       struct list_head                        queue;
+
+       u32                                     ctrl;
+
+       unsigned int                            submitted:1;
+       unsigned int                            last_transaction:1;
+       unsigned int                            using_dma:1;
+       unsigned int                            mapped:1;
+};
+
+struct usba_udc {
+       /* Protect hw registers from concurrent modifications */
+       spinlock_t lock;
+
+       void __iomem *regs;
+       void __iomem *fifo;
+
+       struct usb_gadget gadget;
+       struct usb_gadget_driver *driver;
+       struct platform_device *pdev;
+       int irq;
+       int vbus_pin;
+       int vbus_pin_inverted;
+       int num_ep;
+       struct clk *pclk;
+       struct clk *hclk;
+       struct usba_ep *usba_ep;
+
+       u16 devstatus;
+
+       u16 test_mode;
+       int vbus_prev;
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+       struct dentry *debugfs_root;
+       struct dentry *debugfs_regs;
+#endif
+};
+
+static inline struct usba_ep *to_usba_ep(struct usb_ep *ep)
+{
+       return container_of(ep, struct usba_ep, ep);
+}
+
+static inline struct usba_request *to_usba_req(struct usb_request *req)
+{
+       return container_of(req, struct usba_request, req);
+}
+
+static inline struct usba_udc *to_usba_udc(struct usb_gadget *gadget)
+{
+       return container_of(gadget, struct usba_udc, gadget);
+}
+
+#define ep_is_control(ep)      ((ep)->index == 0)
+#define ep_is_idle(ep)         ((ep)->state == EP_STATE_IDLE)
+
+#endif /* __LINUX_USB_GADGET_USBA_UDC_H */
diff --git a/drivers/usb/gadget/udc/bcm63xx_udc.c b/drivers/usb/gadget/udc/bcm63xx_udc.c
new file mode 100644 (file)
index 0000000..e969eb8
--- /dev/null
@@ -0,0 +1,2436 @@
+/*
+ * bcm63xx_udc.c -- BCM63xx UDC high/full speed USB device controller
+ *
+ * Copyright (C) 2012 Kevin Cernekee <cernekee@gmail.com>
+ * Copyright (C) 2012 Broadcom 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.
+ */
+
+#include <linux/bitops.h>
+#include <linux/bug.h>
+#include <linux/clk.h>
+#include <linux/compiler.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kconfig.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/workqueue.h>
+
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_iudma.h>
+#include <bcm63xx_dev_usb_usbd.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_regs.h>
+
+#define DRV_MODULE_NAME                "bcm63xx_udc"
+
+static const char bcm63xx_ep0name[] = "ep0";
+static const char *const bcm63xx_ep_name[] = {
+       bcm63xx_ep0name,
+       "ep1in-bulk", "ep2out-bulk", "ep3in-int", "ep4out-int",
+};
+
+static bool use_fullspeed;
+module_param(use_fullspeed, bool, S_IRUGO);
+MODULE_PARM_DESC(use_fullspeed, "true for fullspeed only");
+
+/*
+ * RX IRQ coalescing options:
+ *
+ * false (default) - one IRQ per DATAx packet.  Slow but reliable.  The
+ * driver is able to pass the "testusb" suite and recover from conditions like:
+ *
+ *   1) Device queues up a 2048-byte RX IUDMA transaction on an OUT bulk ep
+ *   2) Host sends 512 bytes of data
+ *   3) Host decides to reconfigure the device and sends SET_INTERFACE
+ *   4) Device shuts down the endpoint and cancels the RX transaction
+ *
+ * true - one IRQ per transfer, for transfers <= 2048B.  Generates
+ * considerably fewer IRQs, but error recovery is less robust.  Does not
+ * reliably pass "testusb".
+ *
+ * TX always uses coalescing, because we can cancel partially complete TX
+ * transfers by repeatedly flushing the FIFO.  The hardware doesn't allow
+ * this on RX.
+ */
+static bool irq_coalesce;
+module_param(irq_coalesce, bool, S_IRUGO);
+MODULE_PARM_DESC(irq_coalesce, "take one IRQ per RX transfer");
+
+#define BCM63XX_NUM_EP                 5
+#define BCM63XX_NUM_IUDMA              6
+#define BCM63XX_NUM_FIFO_PAIRS         3
+
+#define IUDMA_RESET_TIMEOUT_US         10000
+
+#define IUDMA_EP0_RXCHAN               0
+#define IUDMA_EP0_TXCHAN               1
+
+#define IUDMA_MAX_FRAGMENT             2048
+#define BCM63XX_MAX_CTRL_PKT           64
+
+#define BCMEP_CTRL                     0x00
+#define BCMEP_ISOC                     0x01
+#define BCMEP_BULK                     0x02
+#define BCMEP_INTR                     0x03
+
+#define BCMEP_OUT                      0x00
+#define BCMEP_IN                       0x01
+
+#define BCM63XX_SPD_FULL               1
+#define BCM63XX_SPD_HIGH               0
+
+#define IUDMA_DMAC_OFFSET              0x200
+#define IUDMA_DMAS_OFFSET              0x400
+
+enum bcm63xx_ep0_state {
+       EP0_REQUEUE,
+       EP0_IDLE,
+       EP0_IN_DATA_PHASE_SETUP,
+       EP0_IN_DATA_PHASE_COMPLETE,
+       EP0_OUT_DATA_PHASE_SETUP,
+       EP0_OUT_DATA_PHASE_COMPLETE,
+       EP0_OUT_STATUS_PHASE,
+       EP0_IN_FAKE_STATUS_PHASE,
+       EP0_SHUTDOWN,
+};
+
+static const char __maybe_unused bcm63xx_ep0_state_names[][32] = {
+       "REQUEUE",
+       "IDLE",
+       "IN_DATA_PHASE_SETUP",
+       "IN_DATA_PHASE_COMPLETE",
+       "OUT_DATA_PHASE_SETUP",
+       "OUT_DATA_PHASE_COMPLETE",
+       "OUT_STATUS_PHASE",
+       "IN_FAKE_STATUS_PHASE",
+       "SHUTDOWN",
+};
+
+/**
+ * struct iudma_ch_cfg - Static configuration for an IUDMA channel.
+ * @ep_num: USB endpoint number.
+ * @n_bds: Number of buffer descriptors in the ring.
+ * @ep_type: Endpoint type (control, bulk, interrupt).
+ * @dir: Direction (in, out).
+ * @n_fifo_slots: Number of FIFO entries to allocate for this channel.
+ * @max_pkt_hs: Maximum packet size in high speed mode.
+ * @max_pkt_fs: Maximum packet size in full speed mode.
+ */
+struct iudma_ch_cfg {
+       int                             ep_num;
+       int                             n_bds;
+       int                             ep_type;
+       int                             dir;
+       int                             n_fifo_slots;
+       int                             max_pkt_hs;
+       int                             max_pkt_fs;
+};
+
+static const struct iudma_ch_cfg iudma_defaults[] = {
+
+       /* This controller was designed to support a CDC/RNDIS application.
+          It may be possible to reconfigure some of the endpoints, but
+          the hardware limitations (FIFO sizing and number of DMA channels)
+          may significantly impact flexibility and/or stability.  Change
+          these values at your own risk.
+
+             ep_num       ep_type           n_fifo_slots    max_pkt_fs
+       idx      |  n_bds     |         dir       |  max_pkt_hs  |
+        |       |    |       |          |        |      |       |       */
+       [0] = { -1,   4, BCMEP_CTRL, BCMEP_OUT,  32,    64,     64 },
+       [1] = {  0,   4, BCMEP_CTRL, BCMEP_OUT,  32,    64,     64 },
+       [2] = {  2,  16, BCMEP_BULK, BCMEP_OUT, 128,   512,     64 },
+       [3] = {  1,  16, BCMEP_BULK, BCMEP_IN,  128,   512,     64 },
+       [4] = {  4,   4, BCMEP_INTR, BCMEP_OUT,  32,    64,     64 },
+       [5] = {  3,   4, BCMEP_INTR, BCMEP_IN,   32,    64,     64 },
+};
+
+struct bcm63xx_udc;
+
+/**
+ * struct iudma_ch - Represents the current state of a single IUDMA channel.
+ * @ch_idx: IUDMA channel index (0 to BCM63XX_NUM_IUDMA-1).
+ * @ep_num: USB endpoint number.  -1 for ep0 RX.
+ * @enabled: Whether bcm63xx_ep_enable() has been called.
+ * @max_pkt: "Chunk size" on the USB interface.  Based on interface speed.
+ * @is_tx: true for TX, false for RX.
+ * @bep: Pointer to the associated endpoint.  NULL for ep0 RX.
+ * @udc: Reference to the device controller.
+ * @read_bd: Next buffer descriptor to reap from the hardware.
+ * @write_bd: Next BD available for a new packet.
+ * @end_bd: Points to the final BD in the ring.
+ * @n_bds_used: Number of BD entries currently occupied.
+ * @bd_ring: Base pointer to the BD ring.
+ * @bd_ring_dma: Physical (DMA) address of bd_ring.
+ * @n_bds: Total number of BDs in the ring.
+ *
+ * ep0 has two IUDMA channels (IUDMA_EP0_RXCHAN and IUDMA_EP0_TXCHAN), as it is
+ * bidirectional.  The "struct usb_ep" associated with ep0 is for TX (IN)
+ * only.
+ *
+ * Each bulk/intr endpoint has a single IUDMA channel and a single
+ * struct usb_ep.
+ */
+struct iudma_ch {
+       unsigned int                    ch_idx;
+       int                             ep_num;
+       bool                            enabled;
+       int                             max_pkt;
+       bool                            is_tx;
+       struct bcm63xx_ep               *bep;
+       struct bcm63xx_udc              *udc;
+
+       struct bcm_enet_desc            *read_bd;
+       struct bcm_enet_desc            *write_bd;
+       struct bcm_enet_desc            *end_bd;
+       int                             n_bds_used;
+
+       struct bcm_enet_desc            *bd_ring;
+       dma_addr_t                      bd_ring_dma;
+       unsigned int                    n_bds;
+};
+
+/**
+ * struct bcm63xx_ep - Internal (driver) state of a single endpoint.
+ * @ep_num: USB endpoint number.
+ * @iudma: Pointer to IUDMA channel state.
+ * @ep: USB gadget layer representation of the EP.
+ * @udc: Reference to the device controller.
+ * @queue: Linked list of outstanding requests for this EP.
+ * @halted: 1 if the EP is stalled; 0 otherwise.
+ */
+struct bcm63xx_ep {
+       unsigned int                    ep_num;
+       struct iudma_ch                 *iudma;
+       struct usb_ep                   ep;
+       struct bcm63xx_udc              *udc;
+       struct list_head                queue;
+       unsigned                        halted:1;
+};
+
+/**
+ * struct bcm63xx_req - Internal (driver) state of a single request.
+ * @queue: Links back to the EP's request list.
+ * @req: USB gadget layer representation of the request.
+ * @offset: Current byte offset into the data buffer (next byte to queue).
+ * @bd_bytes: Number of data bytes in outstanding BD entries.
+ * @iudma: IUDMA channel used for the request.
+ */
+struct bcm63xx_req {
+       struct list_head                queue;          /* ep's requests */
+       struct usb_request              req;
+       unsigned int                    offset;
+       unsigned int                    bd_bytes;
+       struct iudma_ch                 *iudma;
+};
+
+/**
+ * struct bcm63xx_udc - Driver/hardware private context.
+ * @lock: Spinlock to mediate access to this struct, and (most) HW regs.
+ * @dev: Generic Linux device structure.
+ * @pd: Platform data (board/port info).
+ * @usbd_clk: Clock descriptor for the USB device block.
+ * @usbh_clk: Clock descriptor for the USB host block.
+ * @gadget: USB slave device.
+ * @driver: Driver for USB slave devices.
+ * @usbd_regs: Base address of the USBD/USB20D block.
+ * @iudma_regs: Base address of the USBD's associated IUDMA block.
+ * @bep: Array of endpoints, including ep0.
+ * @iudma: Array of all IUDMA channels used by this controller.
+ * @cfg: USB configuration number, from SET_CONFIGURATION wValue.
+ * @iface: USB interface number, from SET_INTERFACE wIndex.
+ * @alt_iface: USB alt interface number, from SET_INTERFACE wValue.
+ * @ep0_ctrl_req: Request object for bcm63xx_udc-initiated ep0 transactions.
+ * @ep0_ctrl_buf: Data buffer for ep0_ctrl_req.
+ * @ep0state: Current state of the ep0 state machine.
+ * @ep0_wq: Workqueue struct used to wake up the ep0 state machine.
+ * @wedgemap: Bitmap of wedged endpoints.
+ * @ep0_req_reset: USB reset is pending.
+ * @ep0_req_set_cfg: Need to spoof a SET_CONFIGURATION packet.
+ * @ep0_req_set_iface: Need to spoof a SET_INTERFACE packet.
+ * @ep0_req_shutdown: Driver is shutting down; requesting ep0 to halt activity.
+ * @ep0_req_completed: ep0 request has completed; worker has not seen it yet.
+ * @ep0_reply: Pending reply from gadget driver.
+ * @ep0_request: Outstanding ep0 request.
+ * @debugfs_root: debugfs directory: /sys/kernel/debug/<DRV_MODULE_NAME>.
+ * @debugfs_usbd: debugfs file "usbd" for controller state.
+ * @debugfs_iudma: debugfs file "usbd" for IUDMA state.
+ */
+struct bcm63xx_udc {
+       spinlock_t                      lock;
+
+       struct device                   *dev;
+       struct bcm63xx_usbd_platform_data *pd;
+       struct clk                      *usbd_clk;
+       struct clk                      *usbh_clk;
+
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+
+       void __iomem                    *usbd_regs;
+       void __iomem                    *iudma_regs;
+
+       struct bcm63xx_ep               bep[BCM63XX_NUM_EP];
+       struct iudma_ch                 iudma[BCM63XX_NUM_IUDMA];
+
+       int                             cfg;
+       int                             iface;
+       int                             alt_iface;
+
+       struct bcm63xx_req              ep0_ctrl_req;
+       u8                              *ep0_ctrl_buf;
+
+       int                             ep0state;
+       struct work_struct              ep0_wq;
+
+       unsigned long                   wedgemap;
+
+       unsigned                        ep0_req_reset:1;
+       unsigned                        ep0_req_set_cfg:1;
+       unsigned                        ep0_req_set_iface:1;
+       unsigned                        ep0_req_shutdown:1;
+
+       unsigned                        ep0_req_completed:1;
+       struct usb_request              *ep0_reply;
+       struct usb_request              *ep0_request;
+
+       struct dentry                   *debugfs_root;
+       struct dentry                   *debugfs_usbd;
+       struct dentry                   *debugfs_iudma;
+};
+
+static const struct usb_ep_ops bcm63xx_udc_ep_ops;
+
+/***********************************************************************
+ * Convenience functions
+ ***********************************************************************/
+
+static inline struct bcm63xx_udc *gadget_to_udc(struct usb_gadget *g)
+{
+       return container_of(g, struct bcm63xx_udc, gadget);
+}
+
+static inline struct bcm63xx_ep *our_ep(struct usb_ep *ep)
+{
+       return container_of(ep, struct bcm63xx_ep, ep);
+}
+
+static inline struct bcm63xx_req *our_req(struct usb_request *req)
+{
+       return container_of(req, struct bcm63xx_req, req);
+}
+
+static inline u32 usbd_readl(struct bcm63xx_udc *udc, u32 off)
+{
+       return bcm_readl(udc->usbd_regs + off);
+}
+
+static inline void usbd_writel(struct bcm63xx_udc *udc, u32 val, u32 off)
+{
+       bcm_writel(val, udc->usbd_regs + off);
+}
+
+static inline u32 usb_dma_readl(struct bcm63xx_udc *udc, u32 off)
+{
+       return bcm_readl(udc->iudma_regs + off);
+}
+
+static inline void usb_dma_writel(struct bcm63xx_udc *udc, u32 val, u32 off)
+{
+       bcm_writel(val, udc->iudma_regs + off);
+}
+
+static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off, int chan)
+{
+       return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off +
+                       (ENETDMA_CHAN_WIDTH * chan));
+}
+
+static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off,
+                                       int chan)
+{
+       bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off +
+                       (ENETDMA_CHAN_WIDTH * chan));
+}
+
+static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off, int chan)
+{
+       return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off +
+                       (ENETDMA_CHAN_WIDTH * chan));
+}
+
+static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off,
+                                       int chan)
+{
+       bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off +
+                       (ENETDMA_CHAN_WIDTH * chan));
+}
+
+static inline void set_clocks(struct bcm63xx_udc *udc, bool is_enabled)
+{
+       if (is_enabled) {
+               clk_enable(udc->usbh_clk);
+               clk_enable(udc->usbd_clk);
+               udelay(10);
+       } else {
+               clk_disable(udc->usbd_clk);
+               clk_disable(udc->usbh_clk);
+       }
+}
+
+/***********************************************************************
+ * Low-level IUDMA / FIFO operations
+ ***********************************************************************/
+
+/**
+ * bcm63xx_ep_dma_select - Helper function to set up the init_sel signal.
+ * @udc: Reference to the device controller.
+ * @idx: Desired init_sel value.
+ *
+ * The "init_sel" signal is used as a selection index for both endpoints
+ * and IUDMA channels.  Since these do not map 1:1, the use of this signal
+ * depends on the context.
+ */
+static void bcm63xx_ep_dma_select(struct bcm63xx_udc *udc, int idx)
+{
+       u32 val = usbd_readl(udc, USBD_CONTROL_REG);
+
+       val &= ~USBD_CONTROL_INIT_SEL_MASK;
+       val |= idx << USBD_CONTROL_INIT_SEL_SHIFT;
+       usbd_writel(udc, val, USBD_CONTROL_REG);
+}
+
+/**
+ * bcm63xx_set_stall - Enable/disable stall on one endpoint.
+ * @udc: Reference to the device controller.
+ * @bep: Endpoint on which to operate.
+ * @is_stalled: true to enable stall, false to disable.
+ *
+ * See notes in bcm63xx_update_wedge() regarding automatic clearing of
+ * halt/stall conditions.
+ */
+static void bcm63xx_set_stall(struct bcm63xx_udc *udc, struct bcm63xx_ep *bep,
+       bool is_stalled)
+{
+       u32 val;
+
+       val = USBD_STALL_UPDATE_MASK |
+               (is_stalled ? USBD_STALL_ENABLE_MASK : 0) |
+               (bep->ep_num << USBD_STALL_EPNUM_SHIFT);
+       usbd_writel(udc, val, USBD_STALL_REG);
+}
+
+/**
+ * bcm63xx_fifo_setup - (Re)initialize FIFO boundaries and settings.
+ * @udc: Reference to the device controller.
+ *
+ * These parameters depend on the USB link speed.  Settings are
+ * per-IUDMA-channel-pair.
+ */
+static void bcm63xx_fifo_setup(struct bcm63xx_udc *udc)
+{
+       int is_hs = udc->gadget.speed == USB_SPEED_HIGH;
+       u32 i, val, rx_fifo_slot, tx_fifo_slot;
+
+       /* set up FIFO boundaries and packet sizes; this is done in pairs */
+       rx_fifo_slot = tx_fifo_slot = 0;
+       for (i = 0; i < BCM63XX_NUM_IUDMA; i += 2) {
+               const struct iudma_ch_cfg *rx_cfg = &iudma_defaults[i];
+               const struct iudma_ch_cfg *tx_cfg = &iudma_defaults[i + 1];
+
+               bcm63xx_ep_dma_select(udc, i >> 1);
+
+               val = (rx_fifo_slot << USBD_RXFIFO_CONFIG_START_SHIFT) |
+                       ((rx_fifo_slot + rx_cfg->n_fifo_slots - 1) <<
+                        USBD_RXFIFO_CONFIG_END_SHIFT);
+               rx_fifo_slot += rx_cfg->n_fifo_slots;
+               usbd_writel(udc, val, USBD_RXFIFO_CONFIG_REG);
+               usbd_writel(udc,
+                           is_hs ? rx_cfg->max_pkt_hs : rx_cfg->max_pkt_fs,
+                           USBD_RXFIFO_EPSIZE_REG);
+
+               val = (tx_fifo_slot << USBD_TXFIFO_CONFIG_START_SHIFT) |
+                       ((tx_fifo_slot + tx_cfg->n_fifo_slots - 1) <<
+                        USBD_TXFIFO_CONFIG_END_SHIFT);
+               tx_fifo_slot += tx_cfg->n_fifo_slots;
+               usbd_writel(udc, val, USBD_TXFIFO_CONFIG_REG);
+               usbd_writel(udc,
+                           is_hs ? tx_cfg->max_pkt_hs : tx_cfg->max_pkt_fs,
+                           USBD_TXFIFO_EPSIZE_REG);
+
+               usbd_readl(udc, USBD_TXFIFO_EPSIZE_REG);
+       }
+}
+
+/**
+ * bcm63xx_fifo_reset_ep - Flush a single endpoint's FIFO.
+ * @udc: Reference to the device controller.
+ * @ep_num: Endpoint number.
+ */
+static void bcm63xx_fifo_reset_ep(struct bcm63xx_udc *udc, int ep_num)
+{
+       u32 val;
+
+       bcm63xx_ep_dma_select(udc, ep_num);
+
+       val = usbd_readl(udc, USBD_CONTROL_REG);
+       val |= USBD_CONTROL_FIFO_RESET_MASK;
+       usbd_writel(udc, val, USBD_CONTROL_REG);
+       usbd_readl(udc, USBD_CONTROL_REG);
+}
+
+/**
+ * bcm63xx_fifo_reset - Flush all hardware FIFOs.
+ * @udc: Reference to the device controller.
+ */
+static void bcm63xx_fifo_reset(struct bcm63xx_udc *udc)
+{
+       int i;
+
+       for (i = 0; i < BCM63XX_NUM_FIFO_PAIRS; i++)
+               bcm63xx_fifo_reset_ep(udc, i);
+}
+
+/**
+ * bcm63xx_ep_init - Initial (one-time) endpoint initialization.
+ * @udc: Reference to the device controller.
+ */
+static void bcm63xx_ep_init(struct bcm63xx_udc *udc)
+{
+       u32 i, val;
+
+       for (i = 0; i < BCM63XX_NUM_IUDMA; i++) {
+               const struct iudma_ch_cfg *cfg = &iudma_defaults[i];
+
+               if (cfg->ep_num < 0)
+                       continue;
+
+               bcm63xx_ep_dma_select(udc, cfg->ep_num);
+               val = (cfg->ep_type << USBD_EPNUM_TYPEMAP_TYPE_SHIFT) |
+                       ((i >> 1) << USBD_EPNUM_TYPEMAP_DMA_CH_SHIFT);
+               usbd_writel(udc, val, USBD_EPNUM_TYPEMAP_REG);
+       }
+}
+
+/**
+ * bcm63xx_ep_setup - Configure per-endpoint settings.
+ * @udc: Reference to the device controller.
+ *
+ * This needs to be rerun if the speed/cfg/intf/altintf changes.
+ */
+static void bcm63xx_ep_setup(struct bcm63xx_udc *udc)
+{
+       u32 val, i;
+
+       usbd_writel(udc, USBD_CSR_SETUPADDR_DEF, USBD_CSR_SETUPADDR_REG);
+
+       for (i = 0; i < BCM63XX_NUM_IUDMA; i++) {
+               const struct iudma_ch_cfg *cfg = &iudma_defaults[i];
+               int max_pkt = udc->gadget.speed == USB_SPEED_HIGH ?
+                             cfg->max_pkt_hs : cfg->max_pkt_fs;
+               int idx = cfg->ep_num;
+
+               udc->iudma[i].max_pkt = max_pkt;
+
+               if (idx < 0)
+                       continue;
+               usb_ep_set_maxpacket_limit(&udc->bep[idx].ep, max_pkt);
+
+               val = (idx << USBD_CSR_EP_LOG_SHIFT) |
+                     (cfg->dir << USBD_CSR_EP_DIR_SHIFT) |
+                     (cfg->ep_type << USBD_CSR_EP_TYPE_SHIFT) |
+                     (udc->cfg << USBD_CSR_EP_CFG_SHIFT) |
+                     (udc->iface << USBD_CSR_EP_IFACE_SHIFT) |
+                     (udc->alt_iface << USBD_CSR_EP_ALTIFACE_SHIFT) |
+                     (max_pkt << USBD_CSR_EP_MAXPKT_SHIFT);
+               usbd_writel(udc, val, USBD_CSR_EP_REG(idx));
+       }
+}
+
+/**
+ * iudma_write - Queue a single IUDMA transaction.
+ * @udc: Reference to the device controller.
+ * @iudma: IUDMA channel to use.
+ * @breq: Request containing the transaction data.
+ *
+ * For RX IUDMA, this will queue a single buffer descriptor, as RX IUDMA
+ * does not honor SOP/EOP so the handling of multiple buffers is ambiguous.
+ * So iudma_write() may be called several times to fulfill a single
+ * usb_request.
+ *
+ * For TX IUDMA, this can queue multiple buffer descriptors if needed.
+ */
+static void iudma_write(struct bcm63xx_udc *udc, struct iudma_ch *iudma,
+       struct bcm63xx_req *breq)
+{
+       int first_bd = 1, last_bd = 0, extra_zero_pkt = 0;
+       unsigned int bytes_left = breq->req.length - breq->offset;
+       const int max_bd_bytes = !irq_coalesce && !iudma->is_tx ?
+               iudma->max_pkt : IUDMA_MAX_FRAGMENT;
+
+       iudma->n_bds_used = 0;
+       breq->bd_bytes = 0;
+       breq->iudma = iudma;
+
+       if ((bytes_left % iudma->max_pkt == 0) && bytes_left && breq->req.zero)
+               extra_zero_pkt = 1;
+
+       do {
+               struct bcm_enet_desc *d = iudma->write_bd;
+               u32 dmaflags = 0;
+               unsigned int n_bytes;
+
+               if (d == iudma->end_bd) {
+                       dmaflags |= DMADESC_WRAP_MASK;
+                       iudma->write_bd = iudma->bd_ring;
+               } else {
+                       iudma->write_bd++;
+               }
+               iudma->n_bds_used++;
+
+               n_bytes = min_t(int, bytes_left, max_bd_bytes);
+               if (n_bytes)
+                       dmaflags |= n_bytes << DMADESC_LENGTH_SHIFT;
+               else
+                       dmaflags |= (1 << DMADESC_LENGTH_SHIFT) |
+                                   DMADESC_USB_ZERO_MASK;
+
+               dmaflags |= DMADESC_OWNER_MASK;
+               if (first_bd) {
+                       dmaflags |= DMADESC_SOP_MASK;
+                       first_bd = 0;
+               }
+
+               /*
+                * extra_zero_pkt forces one more iteration through the loop
+                * after all data is queued up, to send the zero packet
+                */
+               if (extra_zero_pkt && !bytes_left)
+                       extra_zero_pkt = 0;
+
+               if (!iudma->is_tx || iudma->n_bds_used == iudma->n_bds ||
+                   (n_bytes == bytes_left && !extra_zero_pkt)) {
+                       last_bd = 1;
+                       dmaflags |= DMADESC_EOP_MASK;
+               }
+
+               d->address = breq->req.dma + breq->offset;
+               mb();
+               d->len_stat = dmaflags;
+
+               breq->offset += n_bytes;
+               breq->bd_bytes += n_bytes;
+               bytes_left -= n_bytes;
+       } while (!last_bd);
+
+       usb_dmac_writel(udc, ENETDMAC_CHANCFG_EN_MASK,
+                       ENETDMAC_CHANCFG_REG, iudma->ch_idx);
+}
+
+/**
+ * iudma_read - Check for IUDMA buffer completion.
+ * @udc: Reference to the device controller.
+ * @iudma: IUDMA channel to use.
+ *
+ * This checks to see if ALL of the outstanding BDs on the DMA channel
+ * have been filled.  If so, it returns the actual transfer length;
+ * otherwise it returns -EBUSY.
+ */
+static int iudma_read(struct bcm63xx_udc *udc, struct iudma_ch *iudma)
+{
+       int i, actual_len = 0;
+       struct bcm_enet_desc *d = iudma->read_bd;
+
+       if (!iudma->n_bds_used)
+               return -EINVAL;
+
+       for (i = 0; i < iudma->n_bds_used; i++) {
+               u32 dmaflags;
+
+               dmaflags = d->len_stat;
+
+               if (dmaflags & DMADESC_OWNER_MASK)
+                       return -EBUSY;
+
+               actual_len += (dmaflags & DMADESC_LENGTH_MASK) >>
+                             DMADESC_LENGTH_SHIFT;
+               if (d == iudma->end_bd)
+                       d = iudma->bd_ring;
+               else
+                       d++;
+       }
+
+       iudma->read_bd = d;
+       iudma->n_bds_used = 0;
+       return actual_len;
+}
+
+/**
+ * iudma_reset_channel - Stop DMA on a single channel.
+ * @udc: Reference to the device controller.
+ * @iudma: IUDMA channel to reset.
+ */
+static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma)
+{
+       int timeout = IUDMA_RESET_TIMEOUT_US;
+       struct bcm_enet_desc *d;
+       int ch_idx = iudma->ch_idx;
+
+       if (!iudma->is_tx)
+               bcm63xx_fifo_reset_ep(udc, max(0, iudma->ep_num));
+
+       /* stop DMA, then wait for the hardware to wrap up */
+       usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG, ch_idx);
+
+       while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx) &
+                                  ENETDMAC_CHANCFG_EN_MASK) {
+               udelay(1);
+
+               /* repeatedly flush the FIFO data until the BD completes */
+               if (iudma->is_tx && iudma->ep_num >= 0)
+                       bcm63xx_fifo_reset_ep(udc, iudma->ep_num);
+
+               if (!timeout--) {
+                       dev_err(udc->dev, "can't reset IUDMA channel %d\n",
+                               ch_idx);
+                       break;
+               }
+               if (timeout == IUDMA_RESET_TIMEOUT_US / 2) {
+                       dev_warn(udc->dev, "forcibly halting IUDMA channel %d\n",
+                                ch_idx);
+                       usb_dmac_writel(udc, ENETDMAC_CHANCFG_BUFHALT_MASK,
+                                       ENETDMAC_CHANCFG_REG, ch_idx);
+               }
+       }
+       usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG, ch_idx);
+
+       /* don't leave "live" HW-owned entries for the next guy to step on */
+       for (d = iudma->bd_ring; d <= iudma->end_bd; d++)
+               d->len_stat = 0;
+       mb();
+
+       iudma->read_bd = iudma->write_bd = iudma->bd_ring;
+       iudma->n_bds_used = 0;
+
+       /* set up IRQs, UBUS burst size, and BD base for this channel */
+       usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK,
+                       ENETDMAC_IRMASK_REG, ch_idx);
+       usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG, ch_idx);
+
+       usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG, ch_idx);
+       usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG, ch_idx);
+}
+
+/**
+ * iudma_init_channel - One-time IUDMA channel initialization.
+ * @udc: Reference to the device controller.
+ * @ch_idx: Channel to initialize.
+ */
+static int iudma_init_channel(struct bcm63xx_udc *udc, unsigned int ch_idx)
+{
+       struct iudma_ch *iudma = &udc->iudma[ch_idx];
+       const struct iudma_ch_cfg *cfg = &iudma_defaults[ch_idx];
+       unsigned int n_bds = cfg->n_bds;
+       struct bcm63xx_ep *bep = NULL;
+
+       iudma->ep_num = cfg->ep_num;
+       iudma->ch_idx = ch_idx;
+       iudma->is_tx = !!(ch_idx & 0x01);
+       if (iudma->ep_num >= 0) {
+               bep = &udc->bep[iudma->ep_num];
+               bep->iudma = iudma;
+               INIT_LIST_HEAD(&bep->queue);
+       }
+
+       iudma->bep = bep;
+       iudma->udc = udc;
+
+       /* ep0 is always active; others are controlled by the gadget driver */
+       if (iudma->ep_num <= 0)
+               iudma->enabled = true;
+
+       iudma->n_bds = n_bds;
+       iudma->bd_ring = dmam_alloc_coherent(udc->dev,
+               n_bds * sizeof(struct bcm_enet_desc),
+               &iudma->bd_ring_dma, GFP_KERNEL);
+       if (!iudma->bd_ring)
+               return -ENOMEM;
+       iudma->end_bd = &iudma->bd_ring[n_bds - 1];
+
+       return 0;
+}
+
+/**
+ * iudma_init - One-time initialization of all IUDMA channels.
+ * @udc: Reference to the device controller.
+ *
+ * Enable DMA, flush channels, and enable global IUDMA IRQs.
+ */
+static int iudma_init(struct bcm63xx_udc *udc)
+{
+       int i, rc;
+
+       usb_dma_writel(udc, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG);
+
+       for (i = 0; i < BCM63XX_NUM_IUDMA; i++) {
+               rc = iudma_init_channel(udc, i);
+               if (rc)
+                       return rc;
+               iudma_reset_channel(udc, &udc->iudma[i]);
+       }
+
+       usb_dma_writel(udc, BIT(BCM63XX_NUM_IUDMA)-1, ENETDMA_GLB_IRQMASK_REG);
+       return 0;
+}
+
+/**
+ * iudma_uninit - Uninitialize IUDMA channels.
+ * @udc: Reference to the device controller.
+ *
+ * Kill global IUDMA IRQs, flush channels, and kill DMA.
+ */
+static void iudma_uninit(struct bcm63xx_udc *udc)
+{
+       int i;
+
+       usb_dma_writel(udc, 0, ENETDMA_GLB_IRQMASK_REG);
+
+       for (i = 0; i < BCM63XX_NUM_IUDMA; i++)
+               iudma_reset_channel(udc, &udc->iudma[i]);
+
+       usb_dma_writel(udc, 0, ENETDMA_CFG_REG);
+}
+
+/***********************************************************************
+ * Other low-level USBD operations
+ ***********************************************************************/
+
+/**
+ * bcm63xx_set_ctrl_irqs - Mask/unmask control path interrupts.
+ * @udc: Reference to the device controller.
+ * @enable_irqs: true to enable, false to disable.
+ */
+static void bcm63xx_set_ctrl_irqs(struct bcm63xx_udc *udc, bool enable_irqs)
+{
+       u32 val;
+
+       usbd_writel(udc, 0, USBD_STATUS_REG);
+
+       val = BIT(USBD_EVENT_IRQ_USB_RESET) |
+             BIT(USBD_EVENT_IRQ_SETUP) |
+             BIT(USBD_EVENT_IRQ_SETCFG) |
+             BIT(USBD_EVENT_IRQ_SETINTF) |
+             BIT(USBD_EVENT_IRQ_USB_LINK);
+       usbd_writel(udc, enable_irqs ? val : 0, USBD_EVENT_IRQ_MASK_REG);
+       usbd_writel(udc, val, USBD_EVENT_IRQ_STATUS_REG);
+}
+
+/**
+ * bcm63xx_select_phy_mode - Select between USB device and host mode.
+ * @udc: Reference to the device controller.
+ * @is_device: true for device, false for host.
+ *
+ * This should probably be reworked to use the drivers/usb/otg
+ * infrastructure.
+ *
+ * By default, the AFE/pullups are disabled in device mode, until
+ * bcm63xx_select_pullup() is called.
+ */
+static void bcm63xx_select_phy_mode(struct bcm63xx_udc *udc, bool is_device)
+{
+       u32 val, portmask = BIT(udc->pd->port_no);
+
+       if (BCMCPU_IS_6328()) {
+               /* configure pinmux to sense VBUS signal */
+               val = bcm_gpio_readl(GPIO_PINMUX_OTHR_REG);
+               val &= ~GPIO_PINMUX_OTHR_6328_USB_MASK;
+               val |= is_device ? GPIO_PINMUX_OTHR_6328_USB_DEV :
+                              GPIO_PINMUX_OTHR_6328_USB_HOST;
+               bcm_gpio_writel(val, GPIO_PINMUX_OTHR_REG);
+       }
+
+       val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
+       if (is_device) {
+               val |= (portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
+               val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+       } else {
+               val &= ~(portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT);
+               val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+       }
+       bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
+
+       val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
+       if (is_device)
+               val |= USBH_PRIV_SWAP_USBD_MASK;
+       else
+               val &= ~USBH_PRIV_SWAP_USBD_MASK;
+       bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG);
+}
+
+/**
+ * bcm63xx_select_pullup - Enable/disable the pullup on D+
+ * @udc: Reference to the device controller.
+ * @is_on: true to enable the pullup, false to disable.
+ *
+ * If the pullup is active, the host will sense a FS/HS device connected to
+ * the port.  If the pullup is inactive, the host will think the USB
+ * device has been disconnected.
+ */
+static void bcm63xx_select_pullup(struct bcm63xx_udc *udc, bool is_on)
+{
+       u32 val, portmask = BIT(udc->pd->port_no);
+
+       val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
+       if (is_on)
+               val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+       else
+               val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
+       bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
+}
+
+/**
+ * bcm63xx_uninit_udc_hw - Shut down the hardware prior to driver removal.
+ * @udc: Reference to the device controller.
+ *
+ * This just masks the IUDMA IRQs and releases the clocks.  It is assumed
+ * that bcm63xx_udc_stop() has already run, and the clocks are stopped.
+ */
+static void bcm63xx_uninit_udc_hw(struct bcm63xx_udc *udc)
+{
+       set_clocks(udc, true);
+       iudma_uninit(udc);
+       set_clocks(udc, false);
+
+       clk_put(udc->usbd_clk);
+       clk_put(udc->usbh_clk);
+}
+
+/**
+ * bcm63xx_init_udc_hw - Initialize the controller hardware and data structures.
+ * @udc: Reference to the device controller.
+ */
+static int bcm63xx_init_udc_hw(struct bcm63xx_udc *udc)
+{
+       int i, rc = 0;
+       u32 val;
+
+       udc->ep0_ctrl_buf = devm_kzalloc(udc->dev, BCM63XX_MAX_CTRL_PKT,
+                                        GFP_KERNEL);
+       if (!udc->ep0_ctrl_buf)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&udc->gadget.ep_list);
+       for (i = 0; i < BCM63XX_NUM_EP; i++) {
+               struct bcm63xx_ep *bep = &udc->bep[i];
+
+               bep->ep.name = bcm63xx_ep_name[i];
+               bep->ep_num = i;
+               bep->ep.ops = &bcm63xx_udc_ep_ops;
+               list_add_tail(&bep->ep.ep_list, &udc->gadget.ep_list);
+               bep->halted = 0;
+               usb_ep_set_maxpacket_limit(&bep->ep, BCM63XX_MAX_CTRL_PKT);
+               bep->udc = udc;
+               bep->ep.desc = NULL;
+               INIT_LIST_HEAD(&bep->queue);
+       }
+
+       udc->gadget.ep0 = &udc->bep[0].ep;
+       list_del(&udc->bep[0].ep.ep_list);
+
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       udc->ep0state = EP0_SHUTDOWN;
+
+       udc->usbh_clk = clk_get(udc->dev, "usbh");
+       if (IS_ERR(udc->usbh_clk))
+               return -EIO;
+
+       udc->usbd_clk = clk_get(udc->dev, "usbd");
+       if (IS_ERR(udc->usbd_clk)) {
+               clk_put(udc->usbh_clk);
+               return -EIO;
+       }
+
+       set_clocks(udc, true);
+
+       val = USBD_CONTROL_AUTO_CSRS_MASK |
+             USBD_CONTROL_DONE_CSRS_MASK |
+             (irq_coalesce ? USBD_CONTROL_RXZSCFG_MASK : 0);
+       usbd_writel(udc, val, USBD_CONTROL_REG);
+
+       val = USBD_STRAPS_APP_SELF_PWR_MASK |
+             USBD_STRAPS_APP_RAM_IF_MASK |
+             USBD_STRAPS_APP_CSRPRGSUP_MASK |
+             USBD_STRAPS_APP_8BITPHY_MASK |
+             USBD_STRAPS_APP_RMTWKUP_MASK;
+
+       if (udc->gadget.max_speed == USB_SPEED_HIGH)
+               val |= (BCM63XX_SPD_HIGH << USBD_STRAPS_SPEED_SHIFT);
+       else
+               val |= (BCM63XX_SPD_FULL << USBD_STRAPS_SPEED_SHIFT);
+       usbd_writel(udc, val, USBD_STRAPS_REG);
+
+       bcm63xx_set_ctrl_irqs(udc, false);
+
+       usbd_writel(udc, 0, USBD_EVENT_IRQ_CFG_LO_REG);
+
+       val = USBD_EVENT_IRQ_CFG_FALLING(USBD_EVENT_IRQ_ENUM_ON) |
+             USBD_EVENT_IRQ_CFG_FALLING(USBD_EVENT_IRQ_SET_CSRS);
+       usbd_writel(udc, val, USBD_EVENT_IRQ_CFG_HI_REG);
+
+       rc = iudma_init(udc);
+       set_clocks(udc, false);
+       if (rc)
+               bcm63xx_uninit_udc_hw(udc);
+
+       return 0;
+}
+
+/***********************************************************************
+ * Standard EP gadget operations
+ ***********************************************************************/
+
+/**
+ * bcm63xx_ep_enable - Enable one endpoint.
+ * @ep: Endpoint to enable.
+ * @desc: Contains max packet, direction, etc.
+ *
+ * Most of the endpoint parameters are fixed in this controller, so there
+ * isn't much for this function to do.
+ */
+static int bcm63xx_ep_enable(struct usb_ep *ep,
+       const struct usb_endpoint_descriptor *desc)
+{
+       struct bcm63xx_ep *bep = our_ep(ep);
+       struct bcm63xx_udc *udc = bep->udc;
+       struct iudma_ch *iudma = bep->iudma;
+       unsigned long flags;
+
+       if (!ep || !desc || ep->name == bcm63xx_ep0name)
+               return -EINVAL;
+
+       if (!udc->driver)
+               return -ESHUTDOWN;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       if (iudma->enabled) {
+               spin_unlock_irqrestore(&udc->lock, flags);
+               return -EINVAL;
+       }
+
+       iudma->enabled = true;
+       BUG_ON(!list_empty(&bep->queue));
+
+       iudma_reset_channel(udc, iudma);
+
+       bep->halted = 0;
+       bcm63xx_set_stall(udc, bep, false);
+       clear_bit(bep->ep_num, &udc->wedgemap);
+
+       ep->desc = desc;
+       ep->maxpacket = usb_endpoint_maxp(desc);
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+/**
+ * bcm63xx_ep_disable - Disable one endpoint.
+ * @ep: Endpoint to disable.
+ */
+static int bcm63xx_ep_disable(struct usb_ep *ep)
+{
+       struct bcm63xx_ep *bep = our_ep(ep);
+       struct bcm63xx_udc *udc = bep->udc;
+       struct iudma_ch *iudma = bep->iudma;
+       struct list_head *pos, *n;
+       unsigned long flags;
+
+       if (!ep || !ep->desc)
+               return -EINVAL;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       if (!iudma->enabled) {
+               spin_unlock_irqrestore(&udc->lock, flags);
+               return -EINVAL;
+       }
+       iudma->enabled = false;
+
+       iudma_reset_channel(udc, iudma);
+
+       if (!list_empty(&bep->queue)) {
+               list_for_each_safe(pos, n, &bep->queue) {
+                       struct bcm63xx_req *breq =
+                               list_entry(pos, struct bcm63xx_req, queue);
+
+                       usb_gadget_unmap_request(&udc->gadget, &breq->req,
+                                                iudma->is_tx);
+                       list_del(&breq->queue);
+                       breq->req.status = -ESHUTDOWN;
+
+                       spin_unlock_irqrestore(&udc->lock, flags);
+                       breq->req.complete(&iudma->bep->ep, &breq->req);
+                       spin_lock_irqsave(&udc->lock, flags);
+               }
+       }
+       ep->desc = NULL;
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+/**
+ * bcm63xx_udc_alloc_request - Allocate a new request.
+ * @ep: Endpoint associated with the request.
+ * @mem_flags: Flags to pass to kzalloc().
+ */
+static struct usb_request *bcm63xx_udc_alloc_request(struct usb_ep *ep,
+       gfp_t mem_flags)
+{
+       struct bcm63xx_req *breq;
+
+       breq = kzalloc(sizeof(*breq), mem_flags);
+       if (!breq)
+               return NULL;
+       return &breq->req;
+}
+
+/**
+ * bcm63xx_udc_free_request - Free a request.
+ * @ep: Endpoint associated with the request.
+ * @req: Request to free.
+ */
+static void bcm63xx_udc_free_request(struct usb_ep *ep,
+       struct usb_request *req)
+{
+       struct bcm63xx_req *breq = our_req(req);
+       kfree(breq);
+}
+
+/**
+ * bcm63xx_udc_queue - Queue up a new request.
+ * @ep: Endpoint associated with the request.
+ * @req: Request to add.
+ * @mem_flags: Unused.
+ *
+ * If the queue is empty, start this request immediately.  Otherwise, add
+ * it to the list.
+ *
+ * ep0 replies are sent through this function from the gadget driver, but
+ * they are treated differently because they need to be handled by the ep0
+ * state machine.  (Sometimes they are replies to control requests that
+ * were spoofed by this driver, and so they shouldn't be transmitted at all.)
+ */
+static int bcm63xx_udc_queue(struct usb_ep *ep, struct usb_request *req,
+       gfp_t mem_flags)
+{
+       struct bcm63xx_ep *bep = our_ep(ep);
+       struct bcm63xx_udc *udc = bep->udc;
+       struct bcm63xx_req *breq = our_req(req);
+       unsigned long flags;
+       int rc = 0;
+
+       if (unlikely(!req || !req->complete || !req->buf || !ep))
+               return -EINVAL;
+
+       req->actual = 0;
+       req->status = 0;
+       breq->offset = 0;
+
+       if (bep == &udc->bep[0]) {
+               /* only one reply per request, please */
+               if (udc->ep0_reply)
+                       return -EINVAL;
+
+               udc->ep0_reply = req;
+               schedule_work(&udc->ep0_wq);
+               return 0;
+       }
+
+       spin_lock_irqsave(&udc->lock, flags);
+       if (!bep->iudma->enabled) {
+               rc = -ESHUTDOWN;
+               goto out;
+       }
+
+       rc = usb_gadget_map_request(&udc->gadget, req, bep->iudma->is_tx);
+       if (rc == 0) {
+               list_add_tail(&breq->queue, &bep->queue);
+               if (list_is_singular(&bep->queue))
+                       iudma_write(udc, bep->iudma, breq);
+       }
+
+out:
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return rc;
+}
+
+/**
+ * bcm63xx_udc_dequeue - Remove a pending request from the queue.
+ * @ep: Endpoint associated with the request.
+ * @req: Request to remove.
+ *
+ * If the request is not at the head of the queue, this is easy - just nuke
+ * it.  If the request is at the head of the queue, we'll need to stop the
+ * DMA transaction and then queue up the successor.
+ */
+static int bcm63xx_udc_dequeue(struct usb_ep *ep, struct usb_request *req)
+{
+       struct bcm63xx_ep *bep = our_ep(ep);
+       struct bcm63xx_udc *udc = bep->udc;
+       struct bcm63xx_req *breq = our_req(req), *cur;
+       unsigned long flags;
+       int rc = 0;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       if (list_empty(&bep->queue)) {
+               rc = -EINVAL;
+               goto out;
+       }
+
+       cur = list_first_entry(&bep->queue, struct bcm63xx_req, queue);
+       usb_gadget_unmap_request(&udc->gadget, &breq->req, bep->iudma->is_tx);
+
+       if (breq == cur) {
+               iudma_reset_channel(udc, bep->iudma);
+               list_del(&breq->queue);
+
+               if (!list_empty(&bep->queue)) {
+                       struct bcm63xx_req *next;
+
+                       next = list_first_entry(&bep->queue,
+                               struct bcm63xx_req, queue);
+                       iudma_write(udc, bep->iudma, next);
+               }
+       } else {
+               list_del(&breq->queue);
+       }
+
+out:
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       req->status = -ESHUTDOWN;
+       req->complete(ep, req);
+
+       return rc;
+}
+
+/**
+ * bcm63xx_udc_set_halt - Enable/disable STALL flag in the hardware.
+ * @ep: Endpoint to halt.
+ * @value: Zero to clear halt; nonzero to set halt.
+ *
+ * See comments in bcm63xx_update_wedge().
+ */
+static int bcm63xx_udc_set_halt(struct usb_ep *ep, int value)
+{
+       struct bcm63xx_ep *bep = our_ep(ep);
+       struct bcm63xx_udc *udc = bep->udc;
+       unsigned long flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       bcm63xx_set_stall(udc, bep, !!value);
+       bep->halted = value;
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+/**
+ * bcm63xx_udc_set_wedge - Stall the endpoint until the next reset.
+ * @ep: Endpoint to wedge.
+ *
+ * See comments in bcm63xx_update_wedge().
+ */
+static int bcm63xx_udc_set_wedge(struct usb_ep *ep)
+{
+       struct bcm63xx_ep *bep = our_ep(ep);
+       struct bcm63xx_udc *udc = bep->udc;
+       unsigned long flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       set_bit(bep->ep_num, &udc->wedgemap);
+       bcm63xx_set_stall(udc, bep, true);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static const struct usb_ep_ops bcm63xx_udc_ep_ops = {
+       .enable         = bcm63xx_ep_enable,
+       .disable        = bcm63xx_ep_disable,
+
+       .alloc_request  = bcm63xx_udc_alloc_request,
+       .free_request   = bcm63xx_udc_free_request,
+
+       .queue          = bcm63xx_udc_queue,
+       .dequeue        = bcm63xx_udc_dequeue,
+
+       .set_halt       = bcm63xx_udc_set_halt,
+       .set_wedge      = bcm63xx_udc_set_wedge,
+};
+
+/***********************************************************************
+ * EP0 handling
+ ***********************************************************************/
+
+/**
+ * bcm63xx_ep0_setup_callback - Drop spinlock to invoke ->setup callback.
+ * @udc: Reference to the device controller.
+ * @ctrl: 8-byte SETUP request.
+ */
+static int bcm63xx_ep0_setup_callback(struct bcm63xx_udc *udc,
+       struct usb_ctrlrequest *ctrl)
+{
+       int rc;
+
+       spin_unlock_irq(&udc->lock);
+       rc = udc->driver->setup(&udc->gadget, ctrl);
+       spin_lock_irq(&udc->lock);
+       return rc;
+}
+
+/**
+ * bcm63xx_ep0_spoof_set_cfg - Synthesize a SET_CONFIGURATION request.
+ * @udc: Reference to the device controller.
+ *
+ * Many standard requests are handled automatically in the hardware, but
+ * we still need to pass them to the gadget driver so that it can
+ * reconfigure the interfaces/endpoints if necessary.
+ *
+ * Unfortunately we are not able to send a STALL response if the host
+ * requests an invalid configuration.  If this happens, we'll have to be
+ * content with printing a warning.
+ */
+static int bcm63xx_ep0_spoof_set_cfg(struct bcm63xx_udc *udc)
+{
+       struct usb_ctrlrequest ctrl;
+       int rc;
+
+       ctrl.bRequestType = USB_DIR_OUT | USB_RECIP_DEVICE;
+       ctrl.bRequest = USB_REQ_SET_CONFIGURATION;
+       ctrl.wValue = cpu_to_le16(udc->cfg);
+       ctrl.wIndex = 0;
+       ctrl.wLength = 0;
+
+       rc = bcm63xx_ep0_setup_callback(udc, &ctrl);
+       if (rc < 0) {
+               dev_warn_ratelimited(udc->dev,
+                       "hardware auto-acked bad SET_CONFIGURATION(%d) request\n",
+                       udc->cfg);
+       }
+       return rc;
+}
+
+/**
+ * bcm63xx_ep0_spoof_set_iface - Synthesize a SET_INTERFACE request.
+ * @udc: Reference to the device controller.
+ */
+static int bcm63xx_ep0_spoof_set_iface(struct bcm63xx_udc *udc)
+{
+       struct usb_ctrlrequest ctrl;
+       int rc;
+
+       ctrl.bRequestType = USB_DIR_OUT | USB_RECIP_INTERFACE;
+       ctrl.bRequest = USB_REQ_SET_INTERFACE;
+       ctrl.wValue = cpu_to_le16(udc->alt_iface);
+       ctrl.wIndex = cpu_to_le16(udc->iface);
+       ctrl.wLength = 0;
+
+       rc = bcm63xx_ep0_setup_callback(udc, &ctrl);
+       if (rc < 0) {
+               dev_warn_ratelimited(udc->dev,
+                       "hardware auto-acked bad SET_INTERFACE(%d,%d) request\n",
+                       udc->iface, udc->alt_iface);
+       }
+       return rc;
+}
+
+/**
+ * bcm63xx_ep0_map_write - dma_map and iudma_write a single request.
+ * @udc: Reference to the device controller.
+ * @ch_idx: IUDMA channel number.
+ * @req: USB gadget layer representation of the request.
+ */
+static void bcm63xx_ep0_map_write(struct bcm63xx_udc *udc, int ch_idx,
+       struct usb_request *req)
+{
+       struct bcm63xx_req *breq = our_req(req);
+       struct iudma_ch *iudma = &udc->iudma[ch_idx];
+
+       BUG_ON(udc->ep0_request);
+       udc->ep0_request = req;
+
+       req->actual = 0;
+       breq->offset = 0;
+       usb_gadget_map_request(&udc->gadget, req, iudma->is_tx);
+       iudma_write(udc, iudma, breq);
+}
+
+/**
+ * bcm63xx_ep0_complete - Set completion status and "stage" the callback.
+ * @udc: Reference to the device controller.
+ * @req: USB gadget layer representation of the request.
+ * @status: Status to return to the gadget driver.
+ */
+static void bcm63xx_ep0_complete(struct bcm63xx_udc *udc,
+       struct usb_request *req, int status)
+{
+       req->status = status;
+       if (status)
+               req->actual = 0;
+       if (req->complete) {
+               spin_unlock_irq(&udc->lock);
+               req->complete(&udc->bep[0].ep, req);
+               spin_lock_irq(&udc->lock);
+       }
+}
+
+/**
+ * bcm63xx_ep0_nuke_reply - Abort request from the gadget driver due to
+ *   reset/shutdown.
+ * @udc: Reference to the device controller.
+ * @is_tx: Nonzero for TX (IN), zero for RX (OUT).
+ */
+static void bcm63xx_ep0_nuke_reply(struct bcm63xx_udc *udc, int is_tx)
+{
+       struct usb_request *req = udc->ep0_reply;
+
+       udc->ep0_reply = NULL;
+       usb_gadget_unmap_request(&udc->gadget, req, is_tx);
+       if (udc->ep0_request == req) {
+               udc->ep0_req_completed = 0;
+               udc->ep0_request = NULL;
+       }
+       bcm63xx_ep0_complete(udc, req, -ESHUTDOWN);
+}
+
+/**
+ * bcm63xx_ep0_read_complete - Close out the pending ep0 request; return
+ *   transfer len.
+ * @udc: Reference to the device controller.
+ */
+static int bcm63xx_ep0_read_complete(struct bcm63xx_udc *udc)
+{
+       struct usb_request *req = udc->ep0_request;
+
+       udc->ep0_req_completed = 0;
+       udc->ep0_request = NULL;
+
+       return req->actual;
+}
+
+/**
+ * bcm63xx_ep0_internal_request - Helper function to submit an ep0 request.
+ * @udc: Reference to the device controller.
+ * @ch_idx: IUDMA channel number.
+ * @length: Number of bytes to TX/RX.
+ *
+ * Used for simple transfers performed by the ep0 worker.  This will always
+ * use ep0_ctrl_req / ep0_ctrl_buf.
+ */
+static void bcm63xx_ep0_internal_request(struct bcm63xx_udc *udc, int ch_idx,
+       int length)
+{
+       struct usb_request *req = &udc->ep0_ctrl_req.req;
+
+       req->buf = udc->ep0_ctrl_buf;
+       req->length = length;
+       req->complete = NULL;
+
+       bcm63xx_ep0_map_write(udc, ch_idx, req);
+}
+
+/**
+ * bcm63xx_ep0_do_setup - Parse new SETUP packet and decide how to handle it.
+ * @udc: Reference to the device controller.
+ *
+ * EP0_IDLE probably shouldn't ever happen.  EP0_REQUEUE means we're ready
+ * for the next packet.  Anything else means the transaction requires multiple
+ * stages of handling.
+ */
+static enum bcm63xx_ep0_state bcm63xx_ep0_do_setup(struct bcm63xx_udc *udc)
+{
+       int rc;
+       struct usb_ctrlrequest *ctrl = (void *)udc->ep0_ctrl_buf;
+
+       rc = bcm63xx_ep0_read_complete(udc);
+
+       if (rc < 0) {
+               dev_err(udc->dev, "missing SETUP packet\n");
+               return EP0_IDLE;
+       }
+
+       /*
+        * Handle 0-byte IN STATUS acknowledgement.  The hardware doesn't
+        * ALWAYS deliver these 100% of the time, so if we happen to see one,
+        * just throw it away.
+        */
+       if (rc == 0)
+               return EP0_REQUEUE;
+
+       /* Drop malformed SETUP packets */
+       if (rc != sizeof(*ctrl)) {
+               dev_warn_ratelimited(udc->dev,
+                       "malformed SETUP packet (%d bytes)\n", rc);
+               return EP0_REQUEUE;
+       }
+
+       /* Process new SETUP packet arriving on ep0 */
+       rc = bcm63xx_ep0_setup_callback(udc, ctrl);
+       if (rc < 0) {
+               bcm63xx_set_stall(udc, &udc->bep[0], true);
+               return EP0_REQUEUE;
+       }
+
+       if (!ctrl->wLength)
+               return EP0_REQUEUE;
+       else if (ctrl->bRequestType & USB_DIR_IN)
+               return EP0_IN_DATA_PHASE_SETUP;
+       else
+               return EP0_OUT_DATA_PHASE_SETUP;
+}
+
+/**
+ * bcm63xx_ep0_do_idle - Check for outstanding requests if ep0 is idle.
+ * @udc: Reference to the device controller.
+ *
+ * In state EP0_IDLE, the RX descriptor is either pending, or has been
+ * filled with a SETUP packet from the host.  This function handles new
+ * SETUP packets, control IRQ events (which can generate fake SETUP packets),
+ * and reset/shutdown events.
+ *
+ * Returns 0 if work was done; -EAGAIN if nothing to do.
+ */
+static int bcm63xx_ep0_do_idle(struct bcm63xx_udc *udc)
+{
+       if (udc->ep0_req_reset) {
+               udc->ep0_req_reset = 0;
+       } else if (udc->ep0_req_set_cfg) {
+               udc->ep0_req_set_cfg = 0;
+               if (bcm63xx_ep0_spoof_set_cfg(udc) >= 0)
+                       udc->ep0state = EP0_IN_FAKE_STATUS_PHASE;
+       } else if (udc->ep0_req_set_iface) {
+               udc->ep0_req_set_iface = 0;
+               if (bcm63xx_ep0_spoof_set_iface(udc) >= 0)
+                       udc->ep0state = EP0_IN_FAKE_STATUS_PHASE;
+       } else if (udc->ep0_req_completed) {
+               udc->ep0state = bcm63xx_ep0_do_setup(udc);
+               return udc->ep0state == EP0_IDLE ? -EAGAIN : 0;
+       } else if (udc->ep0_req_shutdown) {
+               udc->ep0_req_shutdown = 0;
+               udc->ep0_req_completed = 0;
+               udc->ep0_request = NULL;
+               iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_RXCHAN]);
+               usb_gadget_unmap_request(&udc->gadget,
+                       &udc->ep0_ctrl_req.req, 0);
+
+               /* bcm63xx_udc_pullup() is waiting for this */
+               mb();
+               udc->ep0state = EP0_SHUTDOWN;
+       } else if (udc->ep0_reply) {
+               /*
+                * This could happen if a USB RESET shows up during an ep0
+                * transaction (especially if a laggy driver like gadgetfs
+                * is in use).
+                */
+               dev_warn(udc->dev, "nuking unexpected reply\n");
+               bcm63xx_ep0_nuke_reply(udc, 0);
+       } else {
+               return -EAGAIN;
+       }
+
+       return 0;
+}
+
+/**
+ * bcm63xx_ep0_one_round - Handle the current ep0 state.
+ * @udc: Reference to the device controller.
+ *
+ * Returns 0 if work was done; -EAGAIN if nothing to do.
+ */
+static int bcm63xx_ep0_one_round(struct bcm63xx_udc *udc)
+{
+       enum bcm63xx_ep0_state ep0state = udc->ep0state;
+       bool shutdown = udc->ep0_req_reset || udc->ep0_req_shutdown;
+
+       switch (udc->ep0state) {
+       case EP0_REQUEUE:
+               /* set up descriptor to receive SETUP packet */
+               bcm63xx_ep0_internal_request(udc, IUDMA_EP0_RXCHAN,
+                                            BCM63XX_MAX_CTRL_PKT);
+               ep0state = EP0_IDLE;
+               break;
+       case EP0_IDLE:
+               return bcm63xx_ep0_do_idle(udc);
+       case EP0_IN_DATA_PHASE_SETUP:
+               /*
+                * Normal case: TX request is in ep0_reply (queued by the
+                * callback), or will be queued shortly.  When it's here,
+                * send it to the HW and go to EP0_IN_DATA_PHASE_COMPLETE.
+                *
+                * Shutdown case: Stop waiting for the reply.  Just
+                * REQUEUE->IDLE.  The gadget driver is NOT expected to
+                * queue anything else now.
+                */
+               if (udc->ep0_reply) {
+                       bcm63xx_ep0_map_write(udc, IUDMA_EP0_TXCHAN,
+                                             udc->ep0_reply);
+                       ep0state = EP0_IN_DATA_PHASE_COMPLETE;
+               } else if (shutdown) {
+                       ep0state = EP0_REQUEUE;
+               }
+               break;
+       case EP0_IN_DATA_PHASE_COMPLETE: {
+               /*
+                * Normal case: TX packet (ep0_reply) is in flight; wait for
+                * it to finish, then go back to REQUEUE->IDLE.
+                *
+                * Shutdown case: Reset the TX channel, send -ESHUTDOWN
+                * completion to the gadget driver, then REQUEUE->IDLE.
+                */
+               if (udc->ep0_req_completed) {
+                       udc->ep0_reply = NULL;
+                       bcm63xx_ep0_read_complete(udc);
+                       /*
+                        * the "ack" sometimes gets eaten (see
+                        * bcm63xx_ep0_do_idle)
+                        */
+                       ep0state = EP0_REQUEUE;
+               } else if (shutdown) {
+                       iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_TXCHAN]);
+                       bcm63xx_ep0_nuke_reply(udc, 1);
+                       ep0state = EP0_REQUEUE;
+               }
+               break;
+       }
+       case EP0_OUT_DATA_PHASE_SETUP:
+               /* Similar behavior to EP0_IN_DATA_PHASE_SETUP */
+               if (udc->ep0_reply) {
+                       bcm63xx_ep0_map_write(udc, IUDMA_EP0_RXCHAN,
+                                             udc->ep0_reply);
+                       ep0state = EP0_OUT_DATA_PHASE_COMPLETE;
+               } else if (shutdown) {
+                       ep0state = EP0_REQUEUE;
+               }
+               break;
+       case EP0_OUT_DATA_PHASE_COMPLETE: {
+               /* Similar behavior to EP0_IN_DATA_PHASE_COMPLETE */
+               if (udc->ep0_req_completed) {
+                       udc->ep0_reply = NULL;
+                       bcm63xx_ep0_read_complete(udc);
+
+                       /* send 0-byte ack to host */
+                       bcm63xx_ep0_internal_request(udc, IUDMA_EP0_TXCHAN, 0);
+                       ep0state = EP0_OUT_STATUS_PHASE;
+               } else if (shutdown) {
+                       iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_RXCHAN]);
+                       bcm63xx_ep0_nuke_reply(udc, 0);
+                       ep0state = EP0_REQUEUE;
+               }
+               break;
+       }
+       case EP0_OUT_STATUS_PHASE:
+               /*
+                * Normal case: 0-byte OUT ack packet is in flight; wait
+                * for it to finish, then go back to REQUEUE->IDLE.
+                *
+                * Shutdown case: just cancel the transmission.  Don't bother
+                * calling the completion, because it originated from this
+                * function anyway.  Then go back to REQUEUE->IDLE.
+                */
+               if (udc->ep0_req_completed) {
+                       bcm63xx_ep0_read_complete(udc);
+                       ep0state = EP0_REQUEUE;
+               } else if (shutdown) {
+                       iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_TXCHAN]);
+                       udc->ep0_request = NULL;
+                       ep0state = EP0_REQUEUE;
+               }
+               break;
+       case EP0_IN_FAKE_STATUS_PHASE: {
+               /*
+                * Normal case: we spoofed a SETUP packet and are now
+                * waiting for the gadget driver to send a 0-byte reply.
+                * This doesn't actually get sent to the HW because the
+                * HW has already sent its own reply.  Once we get the
+                * response, return to IDLE.
+                *
+                * Shutdown case: return to IDLE immediately.
+                *
+                * Note that the ep0 RX descriptor has remained queued
+                * (and possibly unfilled) during this entire transaction.
+                * The HW datapath (IUDMA) never even sees SET_CONFIGURATION
+                * or SET_INTERFACE transactions.
+                */
+               struct usb_request *r = udc->ep0_reply;
+
+               if (!r) {
+                       if (shutdown)
+                               ep0state = EP0_IDLE;
+                       break;
+               }
+
+               bcm63xx_ep0_complete(udc, r, 0);
+               udc->ep0_reply = NULL;
+               ep0state = EP0_IDLE;
+               break;
+       }
+       case EP0_SHUTDOWN:
+               break;
+       }
+
+       if (udc->ep0state == ep0state)
+               return -EAGAIN;
+
+       udc->ep0state = ep0state;
+       return 0;
+}
+
+/**
+ * bcm63xx_ep0_process - ep0 worker thread / state machine.
+ * @w: Workqueue struct.
+ *
+ * bcm63xx_ep0_process is triggered any time an event occurs on ep0.  It
+ * is used to synchronize ep0 events and ensure that both HW and SW events
+ * occur in a well-defined order.  When the ep0 IUDMA queues are idle, it may
+ * synthesize SET_CONFIGURATION / SET_INTERFACE requests that were consumed
+ * by the USBD hardware.
+ *
+ * The worker function will continue iterating around the state machine
+ * until there is nothing left to do.  Usually "nothing left to do" means
+ * that we're waiting for a new event from the hardware.
+ */
+static void bcm63xx_ep0_process(struct work_struct *w)
+{
+       struct bcm63xx_udc *udc = container_of(w, struct bcm63xx_udc, ep0_wq);
+       spin_lock_irq(&udc->lock);
+       while (bcm63xx_ep0_one_round(udc) == 0)
+               ;
+       spin_unlock_irq(&udc->lock);
+}
+
+/***********************************************************************
+ * Standard UDC gadget operations
+ ***********************************************************************/
+
+/**
+ * bcm63xx_udc_get_frame - Read current SOF frame number from the HW.
+ * @gadget: USB slave device.
+ */
+static int bcm63xx_udc_get_frame(struct usb_gadget *gadget)
+{
+       struct bcm63xx_udc *udc = gadget_to_udc(gadget);
+
+       return (usbd_readl(udc, USBD_STATUS_REG) &
+               USBD_STATUS_SOF_MASK) >> USBD_STATUS_SOF_SHIFT;
+}
+
+/**
+ * bcm63xx_udc_pullup - Enable/disable pullup on D+ line.
+ * @gadget: USB slave device.
+ * @is_on: 0 to disable pullup, 1 to enable.
+ *
+ * See notes in bcm63xx_select_pullup().
+ */
+static int bcm63xx_udc_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct bcm63xx_udc *udc = gadget_to_udc(gadget);
+       unsigned long flags;
+       int i, rc = -EINVAL;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       if (is_on && udc->ep0state == EP0_SHUTDOWN) {
+               udc->gadget.speed = USB_SPEED_UNKNOWN;
+               udc->ep0state = EP0_REQUEUE;
+               bcm63xx_fifo_setup(udc);
+               bcm63xx_fifo_reset(udc);
+               bcm63xx_ep_setup(udc);
+
+               bitmap_zero(&udc->wedgemap, BCM63XX_NUM_EP);
+               for (i = 0; i < BCM63XX_NUM_EP; i++)
+                       bcm63xx_set_stall(udc, &udc->bep[i], false);
+
+               bcm63xx_set_ctrl_irqs(udc, true);
+               bcm63xx_select_pullup(gadget_to_udc(gadget), true);
+               rc = 0;
+       } else if (!is_on && udc->ep0state != EP0_SHUTDOWN) {
+               bcm63xx_select_pullup(gadget_to_udc(gadget), false);
+
+               udc->ep0_req_shutdown = 1;
+               spin_unlock_irqrestore(&udc->lock, flags);
+
+               while (1) {
+                       schedule_work(&udc->ep0_wq);
+                       if (udc->ep0state == EP0_SHUTDOWN)
+                               break;
+                       msleep(50);
+               }
+               bcm63xx_set_ctrl_irqs(udc, false);
+               cancel_work_sync(&udc->ep0_wq);
+               return 0;
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return rc;
+}
+
+/**
+ * bcm63xx_udc_start - Start the controller.
+ * @gadget: USB slave device.
+ * @driver: Driver for USB slave devices.
+ */
+static int bcm63xx_udc_start(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct bcm63xx_udc *udc = gadget_to_udc(gadget);
+       unsigned long flags;
+
+       if (!driver || driver->max_speed < USB_SPEED_HIGH ||
+           !driver->setup)
+               return -EINVAL;
+       if (!udc)
+               return -ENODEV;
+       if (udc->driver)
+               return -EBUSY;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       set_clocks(udc, true);
+       bcm63xx_fifo_setup(udc);
+       bcm63xx_ep_init(udc);
+       bcm63xx_ep_setup(udc);
+       bcm63xx_fifo_reset(udc);
+       bcm63xx_select_phy_mode(udc, true);
+
+       udc->driver = driver;
+       driver->driver.bus = NULL;
+       udc->gadget.dev.of_node = udc->dev->of_node;
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+/**
+ * bcm63xx_udc_stop - Shut down the controller.
+ * @gadget: USB slave device.
+ * @driver: Driver for USB slave devices.
+ */
+static int bcm63xx_udc_stop(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct bcm63xx_udc *udc = gadget_to_udc(gadget);
+       unsigned long flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       udc->driver = NULL;
+
+       /*
+        * If we switch the PHY too abruptly after dropping D+, the host
+        * will often complain:
+        *
+        *     hub 1-0:1.0: port 1 disabled by hub (EMI?), re-enabling...
+        */
+       msleep(100);
+
+       bcm63xx_select_phy_mode(udc, false);
+       set_clocks(udc, false);
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static const struct usb_gadget_ops bcm63xx_udc_ops = {
+       .get_frame      = bcm63xx_udc_get_frame,
+       .pullup         = bcm63xx_udc_pullup,
+       .udc_start      = bcm63xx_udc_start,
+       .udc_stop       = bcm63xx_udc_stop,
+};
+
+/***********************************************************************
+ * IRQ handling
+ ***********************************************************************/
+
+/**
+ * bcm63xx_update_cfg_iface - Read current configuration/interface settings.
+ * @udc: Reference to the device controller.
+ *
+ * This controller intercepts SET_CONFIGURATION and SET_INTERFACE messages.
+ * The driver never sees the raw control packets coming in on the ep0
+ * IUDMA channel, but at least we get an interrupt event to tell us that
+ * new values are waiting in the USBD_STATUS register.
+ */
+static void bcm63xx_update_cfg_iface(struct bcm63xx_udc *udc)
+{
+       u32 reg = usbd_readl(udc, USBD_STATUS_REG);
+
+       udc->cfg = (reg & USBD_STATUS_CFG_MASK) >> USBD_STATUS_CFG_SHIFT;
+       udc->iface = (reg & USBD_STATUS_INTF_MASK) >> USBD_STATUS_INTF_SHIFT;
+       udc->alt_iface = (reg & USBD_STATUS_ALTINTF_MASK) >>
+                        USBD_STATUS_ALTINTF_SHIFT;
+       bcm63xx_ep_setup(udc);
+}
+
+/**
+ * bcm63xx_update_link_speed - Check to see if the link speed has changed.
+ * @udc: Reference to the device controller.
+ *
+ * The link speed update coincides with a SETUP IRQ.  Returns 1 if the
+ * speed has changed, so that the caller can update the endpoint settings.
+ */
+static int bcm63xx_update_link_speed(struct bcm63xx_udc *udc)
+{
+       u32 reg = usbd_readl(udc, USBD_STATUS_REG);
+       enum usb_device_speed oldspeed = udc->gadget.speed;
+
+       switch ((reg & USBD_STATUS_SPD_MASK) >> USBD_STATUS_SPD_SHIFT) {
+       case BCM63XX_SPD_HIGH:
+               udc->gadget.speed = USB_SPEED_HIGH;
+               break;
+       case BCM63XX_SPD_FULL:
+               udc->gadget.speed = USB_SPEED_FULL;
+               break;
+       default:
+               /* this should never happen */
+               udc->gadget.speed = USB_SPEED_UNKNOWN;
+               dev_err(udc->dev,
+                       "received SETUP packet with invalid link speed\n");
+               return 0;
+       }
+
+       if (udc->gadget.speed != oldspeed) {
+               dev_info(udc->dev, "link up, %s-speed mode\n",
+                        udc->gadget.speed == USB_SPEED_HIGH ? "high" : "full");
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * bcm63xx_update_wedge - Iterate through wedged endpoints.
+ * @udc: Reference to the device controller.
+ * @new_status: true to "refresh" wedge status; false to clear it.
+ *
+ * On a SETUP interrupt, we need to manually "refresh" the wedge status
+ * because the controller hardware is designed to automatically clear
+ * stalls in response to a CLEAR_FEATURE request from the host.
+ *
+ * On a RESET interrupt, we do want to restore all wedged endpoints.
+ */
+static void bcm63xx_update_wedge(struct bcm63xx_udc *udc, bool new_status)
+{
+       int i;
+
+       for_each_set_bit(i, &udc->wedgemap, BCM63XX_NUM_EP) {
+               bcm63xx_set_stall(udc, &udc->bep[i], new_status);
+               if (!new_status)
+                       clear_bit(i, &udc->wedgemap);
+       }
+}
+
+/**
+ * bcm63xx_udc_ctrl_isr - ISR for control path events (USBD).
+ * @irq: IRQ number (unused).
+ * @dev_id: Reference to the device controller.
+ *
+ * This is where we handle link (VBUS) down, USB reset, speed changes,
+ * SET_CONFIGURATION, and SET_INTERFACE events.
+ */
+static irqreturn_t bcm63xx_udc_ctrl_isr(int irq, void *dev_id)
+{
+       struct bcm63xx_udc *udc = dev_id;
+       u32 stat;
+       bool disconnected = false;
+
+       stat = usbd_readl(udc, USBD_EVENT_IRQ_STATUS_REG) &
+              usbd_readl(udc, USBD_EVENT_IRQ_MASK_REG);
+
+       usbd_writel(udc, stat, USBD_EVENT_IRQ_STATUS_REG);
+
+       spin_lock(&udc->lock);
+       if (stat & BIT(USBD_EVENT_IRQ_USB_LINK)) {
+               /* VBUS toggled */
+
+               if (!(usbd_readl(udc, USBD_EVENTS_REG) &
+                     USBD_EVENTS_USB_LINK_MASK) &&
+                     udc->gadget.speed != USB_SPEED_UNKNOWN)
+                       dev_info(udc->dev, "link down\n");
+
+               udc->gadget.speed = USB_SPEED_UNKNOWN;
+               disconnected = true;
+       }
+       if (stat & BIT(USBD_EVENT_IRQ_USB_RESET)) {
+               bcm63xx_fifo_setup(udc);
+               bcm63xx_fifo_reset(udc);
+               bcm63xx_ep_setup(udc);
+
+               bcm63xx_update_wedge(udc, false);
+
+               udc->ep0_req_reset = 1;
+               schedule_work(&udc->ep0_wq);
+               disconnected = true;
+       }
+       if (stat & BIT(USBD_EVENT_IRQ_SETUP)) {
+               if (bcm63xx_update_link_speed(udc)) {
+                       bcm63xx_fifo_setup(udc);
+                       bcm63xx_ep_setup(udc);
+               }
+               bcm63xx_update_wedge(udc, true);
+       }
+       if (stat & BIT(USBD_EVENT_IRQ_SETCFG)) {
+               bcm63xx_update_cfg_iface(udc);
+               udc->ep0_req_set_cfg = 1;
+               schedule_work(&udc->ep0_wq);
+       }
+       if (stat & BIT(USBD_EVENT_IRQ_SETINTF)) {
+               bcm63xx_update_cfg_iface(udc);
+               udc->ep0_req_set_iface = 1;
+               schedule_work(&udc->ep0_wq);
+       }
+       spin_unlock(&udc->lock);
+
+       if (disconnected && udc->driver)
+               udc->driver->disconnect(&udc->gadget);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * bcm63xx_udc_data_isr - ISR for data path events (IUDMA).
+ * @irq: IRQ number (unused).
+ * @dev_id: Reference to the IUDMA channel that generated the interrupt.
+ *
+ * For the two ep0 channels, we have special handling that triggers the
+ * ep0 worker thread.  For normal bulk/intr channels, either queue up
+ * the next buffer descriptor for the transaction (incomplete transaction),
+ * or invoke the completion callback (complete transactions).
+ */
+static irqreturn_t bcm63xx_udc_data_isr(int irq, void *dev_id)
+{
+       struct iudma_ch *iudma = dev_id;
+       struct bcm63xx_udc *udc = iudma->udc;
+       struct bcm63xx_ep *bep;
+       struct usb_request *req = NULL;
+       struct bcm63xx_req *breq = NULL;
+       int rc;
+       bool is_done = false;
+
+       spin_lock(&udc->lock);
+
+       usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK,
+                       ENETDMAC_IR_REG, iudma->ch_idx);
+       bep = iudma->bep;
+       rc = iudma_read(udc, iudma);
+
+       /* special handling for EP0 RX (0) and TX (1) */
+       if (iudma->ch_idx == IUDMA_EP0_RXCHAN ||
+           iudma->ch_idx == IUDMA_EP0_TXCHAN) {
+               req = udc->ep0_request;
+               breq = our_req(req);
+
+               /* a single request could require multiple submissions */
+               if (rc >= 0) {
+                       req->actual += rc;
+
+                       if (req->actual >= req->length || breq->bd_bytes > rc) {
+                               udc->ep0_req_completed = 1;
+                               is_done = true;
+                               schedule_work(&udc->ep0_wq);
+
+                               /* "actual" on a ZLP is 1 byte */
+                               req->actual = min(req->actual, req->length);
+                       } else {
+                               /* queue up the next BD (same request) */
+                               iudma_write(udc, iudma, breq);
+                       }
+               }
+       } else if (!list_empty(&bep->queue)) {
+               breq = list_first_entry(&bep->queue, struct bcm63xx_req, queue);
+               req = &breq->req;
+
+               if (rc >= 0) {
+                       req->actual += rc;
+
+                       if (req->actual >= req->length || breq->bd_bytes > rc) {
+                               is_done = true;
+                               list_del(&breq->queue);
+
+                               req->actual = min(req->actual, req->length);
+
+                               if (!list_empty(&bep->queue)) {
+                                       struct bcm63xx_req *next;
+
+                                       next = list_first_entry(&bep->queue,
+                                               struct bcm63xx_req, queue);
+                                       iudma_write(udc, iudma, next);
+                               }
+                       } else {
+                               iudma_write(udc, iudma, breq);
+                       }
+               }
+       }
+       spin_unlock(&udc->lock);
+
+       if (is_done) {
+               usb_gadget_unmap_request(&udc->gadget, req, iudma->is_tx);
+               if (req->complete)
+                       req->complete(&bep->ep, req);
+       }
+
+       return IRQ_HANDLED;
+}
+
+/***********************************************************************
+ * Debug filesystem
+ ***********************************************************************/
+
+/*
+ * bcm63xx_usbd_dbg_show - Show USBD controller state.
+ * @s: seq_file to which the information will be written.
+ * @p: Unused.
+ *
+ * This file nominally shows up as /sys/kernel/debug/bcm63xx_udc/usbd
+ */
+static int bcm63xx_usbd_dbg_show(struct seq_file *s, void *p)
+{
+       struct bcm63xx_udc *udc = s->private;
+
+       if (!udc->driver)
+               return -ENODEV;
+
+       seq_printf(s, "ep0 state: %s\n",
+                  bcm63xx_ep0_state_names[udc->ep0state]);
+       seq_printf(s, "  pending requests: %s%s%s%s%s%s%s\n",
+                  udc->ep0_req_reset ? "reset " : "",
+                  udc->ep0_req_set_cfg ? "set_cfg " : "",
+                  udc->ep0_req_set_iface ? "set_iface " : "",
+                  udc->ep0_req_shutdown ? "shutdown " : "",
+                  udc->ep0_request ? "pending " : "",
+                  udc->ep0_req_completed ? "completed " : "",
+                  udc->ep0_reply ? "reply " : "");
+       seq_printf(s, "cfg: %d; iface: %d; alt_iface: %d\n",
+                  udc->cfg, udc->iface, udc->alt_iface);
+       seq_printf(s, "regs:\n");
+       seq_printf(s, "  control: %08x; straps: %08x; status: %08x\n",
+                  usbd_readl(udc, USBD_CONTROL_REG),
+                  usbd_readl(udc, USBD_STRAPS_REG),
+                  usbd_readl(udc, USBD_STATUS_REG));
+       seq_printf(s, "  events:  %08x; stall:  %08x\n",
+                  usbd_readl(udc, USBD_EVENTS_REG),
+                  usbd_readl(udc, USBD_STALL_REG));
+
+       return 0;
+}
+
+/*
+ * bcm63xx_iudma_dbg_show - Show IUDMA status and descriptors.
+ * @s: seq_file to which the information will be written.
+ * @p: Unused.
+ *
+ * This file nominally shows up as /sys/kernel/debug/bcm63xx_udc/iudma
+ */
+static int bcm63xx_iudma_dbg_show(struct seq_file *s, void *p)
+{
+       struct bcm63xx_udc *udc = s->private;
+       int ch_idx, i;
+       u32 sram2, sram3;
+
+       if (!udc->driver)
+               return -ENODEV;
+
+       for (ch_idx = 0; ch_idx < BCM63XX_NUM_IUDMA; ch_idx++) {
+               struct iudma_ch *iudma = &udc->iudma[ch_idx];
+               struct list_head *pos;
+
+               seq_printf(s, "IUDMA channel %d -- ", ch_idx);
+               switch (iudma_defaults[ch_idx].ep_type) {
+               case BCMEP_CTRL:
+                       seq_printf(s, "control");
+                       break;
+               case BCMEP_BULK:
+                       seq_printf(s, "bulk");
+                       break;
+               case BCMEP_INTR:
+                       seq_printf(s, "interrupt");
+                       break;
+               }
+               seq_printf(s, ch_idx & 0x01 ? " tx" : " rx");
+               seq_printf(s, " [ep%d]:\n",
+                          max_t(int, iudma_defaults[ch_idx].ep_num, 0));
+               seq_printf(s, "  cfg: %08x; irqstat: %08x; irqmask: %08x; maxburst: %08x\n",
+                          usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx),
+                          usb_dmac_readl(udc, ENETDMAC_IR_REG, ch_idx),
+                          usb_dmac_readl(udc, ENETDMAC_IRMASK_REG, ch_idx),
+                          usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG, ch_idx));
+
+               sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG, ch_idx);
+               sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG, ch_idx);
+               seq_printf(s, "  base: %08x; index: %04x_%04x; desc: %04x_%04x %08x\n",
+                          usb_dmas_readl(udc, ENETDMAS_RSTART_REG, ch_idx),
+                          sram2 >> 16, sram2 & 0xffff,
+                          sram3 >> 16, sram3 & 0xffff,
+                          usb_dmas_readl(udc, ENETDMAS_SRAM4_REG, ch_idx));
+               seq_printf(s, "  desc: %d/%d used", iudma->n_bds_used,
+                          iudma->n_bds);
+
+               if (iudma->bep) {
+                       i = 0;
+                       list_for_each(pos, &iudma->bep->queue)
+                               i++;
+                       seq_printf(s, "; %d queued\n", i);
+               } else {
+                       seq_printf(s, "\n");
+               }
+
+               for (i = 0; i < iudma->n_bds; i++) {
+                       struct bcm_enet_desc *d = &iudma->bd_ring[i];
+
+                       seq_printf(s, "  %03x (%02x): len_stat: %04x_%04x; pa %08x",
+                                  i * sizeof(*d), i,
+                                  d->len_stat >> 16, d->len_stat & 0xffff,
+                                  d->address);
+                       if (d == iudma->read_bd)
+                               seq_printf(s, "   <<RD");
+                       if (d == iudma->write_bd)
+                               seq_printf(s, "   <<WR");
+                       seq_printf(s, "\n");
+               }
+
+               seq_printf(s, "\n");
+       }
+
+       return 0;
+}
+
+static int bcm63xx_usbd_dbg_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, bcm63xx_usbd_dbg_show, inode->i_private);
+}
+
+static int bcm63xx_iudma_dbg_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, bcm63xx_iudma_dbg_show, inode->i_private);
+}
+
+static const struct file_operations usbd_dbg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = bcm63xx_usbd_dbg_open,
+       .llseek         = seq_lseek,
+       .read           = seq_read,
+       .release        = single_release,
+};
+
+static const struct file_operations iudma_dbg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = bcm63xx_iudma_dbg_open,
+       .llseek         = seq_lseek,
+       .read           = seq_read,
+       .release        = single_release,
+};
+
+
+/**
+ * bcm63xx_udc_init_debugfs - Create debugfs entries.
+ * @udc: Reference to the device controller.
+ */
+static void bcm63xx_udc_init_debugfs(struct bcm63xx_udc *udc)
+{
+       struct dentry *root, *usbd, *iudma;
+
+       if (!IS_ENABLED(CONFIG_USB_GADGET_DEBUG_FS))
+               return;
+
+       root = debugfs_create_dir(udc->gadget.name, NULL);
+       if (IS_ERR(root) || !root)
+               goto err_root;
+
+       usbd = debugfs_create_file("usbd", 0400, root, udc,
+                       &usbd_dbg_fops);
+       if (!usbd)
+               goto err_usbd;
+       iudma = debugfs_create_file("iudma", 0400, root, udc,
+                       &iudma_dbg_fops);
+       if (!iudma)
+               goto err_iudma;
+
+       udc->debugfs_root = root;
+       udc->debugfs_usbd = usbd;
+       udc->debugfs_iudma = iudma;
+       return;
+err_iudma:
+       debugfs_remove(usbd);
+err_usbd:
+       debugfs_remove(root);
+err_root:
+       dev_err(udc->dev, "debugfs is not available\n");
+}
+
+/**
+ * bcm63xx_udc_cleanup_debugfs - Remove debugfs entries.
+ * @udc: Reference to the device controller.
+ *
+ * debugfs_remove() is safe to call with a NULL argument.
+ */
+static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc)
+{
+       debugfs_remove(udc->debugfs_iudma);
+       debugfs_remove(udc->debugfs_usbd);
+       debugfs_remove(udc->debugfs_root);
+       udc->debugfs_iudma = NULL;
+       udc->debugfs_usbd = NULL;
+       udc->debugfs_root = NULL;
+}
+
+/***********************************************************************
+ * Driver init/exit
+ ***********************************************************************/
+
+/**
+ * bcm63xx_udc_probe - Initialize a new instance of the UDC.
+ * @pdev: Platform device struct from the bcm63xx BSP code.
+ *
+ * Note that platform data is required, because pd.port_no varies from chip
+ * to chip and is used to switch the correct USB port to device mode.
+ */
+static int bcm63xx_udc_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct bcm63xx_usbd_platform_data *pd = dev_get_platdata(dev);
+       struct bcm63xx_udc *udc;
+       struct resource *res;
+       int rc = -ENOMEM, i, irq;
+
+       udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL);
+       if (!udc) {
+               dev_err(dev, "cannot allocate memory\n");
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(pdev, udc);
+       udc->dev = dev;
+       udc->pd = pd;
+
+       if (!pd) {
+               dev_err(dev, "missing platform data\n");
+               return -EINVAL;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       udc->usbd_regs = devm_ioremap_resource(dev, res);
+       if (IS_ERR(udc->usbd_regs))
+               return PTR_ERR(udc->usbd_regs);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       udc->iudma_regs = devm_ioremap_resource(dev, res);
+       if (IS_ERR(udc->iudma_regs))
+               return PTR_ERR(udc->iudma_regs);
+
+       spin_lock_init(&udc->lock);
+       INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process);
+
+       udc->gadget.ops = &bcm63xx_udc_ops;
+       udc->gadget.name = dev_name(dev);
+
+       if (!pd->use_fullspeed && !use_fullspeed)
+               udc->gadget.max_speed = USB_SPEED_HIGH;
+       else
+               udc->gadget.max_speed = USB_SPEED_FULL;
+
+       /* request clocks, allocate buffers, and clear any pending IRQs */
+       rc = bcm63xx_init_udc_hw(udc);
+       if (rc)
+               return rc;
+
+       rc = -ENXIO;
+
+       /* IRQ resource #0: control interrupt (VBUS, speed, etc.) */
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(dev, "missing IRQ resource #0\n");
+               goto out_uninit;
+       }
+       if (devm_request_irq(dev, irq, &bcm63xx_udc_ctrl_isr, 0,
+                            dev_name(dev), udc) < 0) {
+               dev_err(dev, "error requesting IRQ #%d\n", irq);
+               goto out_uninit;
+       }
+
+       /* IRQ resources #1-6: data interrupts for IUDMA channels 0-5 */
+       for (i = 0; i < BCM63XX_NUM_IUDMA; i++) {
+               irq = platform_get_irq(pdev, i + 1);
+               if (irq < 0) {
+                       dev_err(dev, "missing IRQ resource #%d\n", i + 1);
+                       goto out_uninit;
+               }
+               if (devm_request_irq(dev, irq, &bcm63xx_udc_data_isr, 0,
+                                    dev_name(dev), &udc->iudma[i]) < 0) {
+                       dev_err(dev, "error requesting IRQ #%d\n", irq);
+                       goto out_uninit;
+               }
+       }
+
+       bcm63xx_udc_init_debugfs(udc);
+       rc = usb_add_gadget_udc(dev, &udc->gadget);
+       if (!rc)
+               return 0;
+
+       bcm63xx_udc_cleanup_debugfs(udc);
+out_uninit:
+       bcm63xx_uninit_udc_hw(udc);
+       return rc;
+}
+
+/**
+ * bcm63xx_udc_remove - Remove the device from the system.
+ * @pdev: Platform device struct from the bcm63xx BSP code.
+ */
+static int bcm63xx_udc_remove(struct platform_device *pdev)
+{
+       struct bcm63xx_udc *udc = platform_get_drvdata(pdev);
+
+       bcm63xx_udc_cleanup_debugfs(udc);
+       usb_del_gadget_udc(&udc->gadget);
+       BUG_ON(udc->driver);
+
+       bcm63xx_uninit_udc_hw(udc);
+
+       return 0;
+}
+
+static struct platform_driver bcm63xx_udc_driver = {
+       .probe          = bcm63xx_udc_probe,
+       .remove         = bcm63xx_udc_remove,
+       .driver         = {
+               .name   = DRV_MODULE_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+module_platform_driver(bcm63xx_udc_driver);
+
+MODULE_DESCRIPTION("BCM63xx USB Peripheral Controller");
+MODULE_AUTHOR("Kevin Cernekee <cernekee@gmail.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_MODULE_NAME);
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
new file mode 100644 (file)
index 0000000..2b54955
--- /dev/null
@@ -0,0 +1,2764 @@
+/*
+ * dummy_hcd.c -- Dummy/Loopback USB host and device emulator driver.
+ *
+ * Maintainer: Alan Stern <stern@rowland.harvard.edu>
+ *
+ * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2003-2005 Alan Stern
+ *
+ * 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 exposes a device side "USB gadget" API, driven by requests to a
+ * Linux-USB host controller driver.  USB traffic is simulated; there's
+ * no need for USB hardware.  Use this with two other drivers:
+ *
+ *  - Gadget driver, responding to requests (slave);
+ *  - Host-side device driver, as already familiar in Linux.
+ *
+ * Having this all in one kernel can help some stages of development,
+ * bypassing some hardware (and driver) issues.  UML could help too.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/hcd.h>
+#include <linux/scatterlist.h>
+
+#include <asm/byteorder.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <asm/unaligned.h>
+
+#define DRIVER_DESC    "USB Host+Gadget Emulator"
+#define DRIVER_VERSION "02 May 2005"
+
+#define POWER_BUDGET   500     /* in mA; use 8 for low-power port testing */
+
+static const char      driver_name[] = "dummy_hcd";
+static const char      driver_desc[] = "USB Host+Gadget Emulator";
+
+static const char      gadget_name[] = "dummy_udc";
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
+
+struct dummy_hcd_module_parameters {
+       bool is_super_speed;
+       bool is_high_speed;
+       unsigned int num;
+};
+
+static struct dummy_hcd_module_parameters mod_data = {
+       .is_super_speed = false,
+       .is_high_speed = true,
+       .num = 1,
+};
+module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO);
+MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection");
+module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO);
+MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection");
+module_param_named(num, mod_data.num, uint, S_IRUGO);
+MODULE_PARM_DESC(num, "number of emulated controllers");
+/*-------------------------------------------------------------------------*/
+
+/* gadget side driver data structres */
+struct dummy_ep {
+       struct list_head                queue;
+       unsigned long                   last_io;        /* jiffies timestamp */
+       struct usb_gadget               *gadget;
+       const struct usb_endpoint_descriptor *desc;
+       struct usb_ep                   ep;
+       unsigned                        halted:1;
+       unsigned                        wedged:1;
+       unsigned                        already_seen:1;
+       unsigned                        setup_stage:1;
+       unsigned                        stream_en:1;
+};
+
+struct dummy_request {
+       struct list_head                queue;          /* ep's requests */
+       struct usb_request              req;
+};
+
+static inline struct dummy_ep *usb_ep_to_dummy_ep(struct usb_ep *_ep)
+{
+       return container_of(_ep, struct dummy_ep, ep);
+}
+
+static inline struct dummy_request *usb_request_to_dummy_request
+               (struct usb_request *_req)
+{
+       return container_of(_req, struct dummy_request, req);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Every device has ep0 for control requests, plus up to 30 more endpoints,
+ * in one of two types:
+ *
+ *   - Configurable:  direction (in/out), type (bulk, iso, etc), and endpoint
+ *     number can be changed.  Names like "ep-a" are used for this type.
+ *
+ *   - Fixed Function:  in other cases.  some characteristics may be mutable;
+ *     that'd be hardware-specific.  Names like "ep12out-bulk" are used.
+ *
+ * Gadget drivers are responsible for not setting up conflicting endpoint
+ * configurations, illegal or unsupported packet lengths, and so on.
+ */
+
+static const char ep0name[] = "ep0";
+
+static const char *const ep_name[] = {
+       ep0name,                                /* everyone has ep0 */
+
+       /* act like a pxa250: fifteen fixed function endpoints */
+       "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int",
+       "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int",
+       "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso",
+               "ep15in-int",
+
+       /* or like sa1100: two fixed function endpoints */
+       "ep1out-bulk", "ep2in-bulk",
+
+       /* and now some generic EPs so we have enough in multi config */
+       "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in",
+       "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out",
+};
+#define DUMMY_ENDPOINTS        ARRAY_SIZE(ep_name)
+
+/*-------------------------------------------------------------------------*/
+
+#define FIFO_SIZE              64
+
+struct urbp {
+       struct urb              *urb;
+       struct list_head        urbp_list;
+       struct sg_mapping_iter  miter;
+       u32                     miter_started;
+};
+
+
+enum dummy_rh_state {
+       DUMMY_RH_RESET,
+       DUMMY_RH_SUSPENDED,
+       DUMMY_RH_RUNNING
+};
+
+struct dummy_hcd {
+       struct dummy                    *dum;
+       enum dummy_rh_state             rh_state;
+       struct timer_list               timer;
+       u32                             port_status;
+       u32                             old_status;
+       unsigned long                   re_timeout;
+
+       struct usb_device               *udev;
+       struct list_head                urbp_list;
+       u32                             stream_en_ep;
+       u8                              num_stream[30 / 2];
+
+       unsigned                        active:1;
+       unsigned                        old_active:1;
+       unsigned                        resuming:1;
+};
+
+struct dummy {
+       spinlock_t                      lock;
+
+       /*
+        * SLAVE/GADGET side support
+        */
+       struct dummy_ep                 ep[DUMMY_ENDPOINTS];
+       int                             address;
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+       struct dummy_request            fifo_req;
+       u8                              fifo_buf[FIFO_SIZE];
+       u16                             devstatus;
+       unsigned                        udc_suspended:1;
+       unsigned                        pullup:1;
+
+       /*
+        * MASTER/HOST side support
+        */
+       struct dummy_hcd                *hs_hcd;
+       struct dummy_hcd                *ss_hcd;
+};
+
+static inline struct dummy_hcd *hcd_to_dummy_hcd(struct usb_hcd *hcd)
+{
+       return (struct dummy_hcd *) (hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *dummy_hcd_to_hcd(struct dummy_hcd *dum)
+{
+       return container_of((void *) dum, struct usb_hcd, hcd_priv);
+}
+
+static inline struct device *dummy_dev(struct dummy_hcd *dum)
+{
+       return dummy_hcd_to_hcd(dum)->self.controller;
+}
+
+static inline struct device *udc_dev(struct dummy *dum)
+{
+       return dum->gadget.dev.parent;
+}
+
+static inline struct dummy *ep_to_dummy(struct dummy_ep *ep)
+{
+       return container_of(ep->gadget, struct dummy, gadget);
+}
+
+static inline struct dummy_hcd *gadget_to_dummy_hcd(struct usb_gadget *gadget)
+{
+       struct dummy *dum = container_of(gadget, struct dummy, gadget);
+       if (dum->gadget.speed == USB_SPEED_SUPER)
+               return dum->ss_hcd;
+       else
+               return dum->hs_hcd;
+}
+
+static inline struct dummy *gadget_dev_to_dummy(struct device *dev)
+{
+       return container_of(dev, struct dummy, gadget.dev);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* SLAVE/GADGET SIDE UTILITY ROUTINES */
+
+/* called with spinlock held */
+static void nuke(struct dummy *dum, struct dummy_ep *ep)
+{
+       while (!list_empty(&ep->queue)) {
+               struct dummy_request    *req;
+
+               req = list_entry(ep->queue.next, struct dummy_request, queue);
+               list_del_init(&req->queue);
+               req->req.status = -ESHUTDOWN;
+
+               spin_unlock(&dum->lock);
+               req->req.complete(&ep->ep, &req->req);
+               spin_lock(&dum->lock);
+       }
+}
+
+/* caller must hold lock */
+static void stop_activity(struct dummy *dum)
+{
+       struct dummy_ep *ep;
+
+       /* prevent any more requests */
+       dum->address = 0;
+
+       /* The timer is left running so that outstanding URBs can fail */
+
+       /* nuke any pending requests first, so driver i/o is quiesced */
+       list_for_each_entry(ep, &dum->gadget.ep_list, ep.ep_list)
+               nuke(dum, ep);
+
+       /* driver now does any non-usb quiescing necessary */
+}
+
+/**
+ * set_link_state_by_speed() - Sets the current state of the link according to
+ *     the hcd speed
+ * @dum_hcd: pointer to the dummy_hcd structure to update the link state for
+ *
+ * This function updates the port_status according to the link state and the
+ * speed of the hcd.
+ */
+static void set_link_state_by_speed(struct dummy_hcd *dum_hcd)
+{
+       struct dummy *dum = dum_hcd->dum;
+
+       if (dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3) {
+               if ((dum_hcd->port_status & USB_SS_PORT_STAT_POWER) == 0) {
+                       dum_hcd->port_status = 0;
+               } else if (!dum->pullup || dum->udc_suspended) {
+                       /* UDC suspend must cause a disconnect */
+                       dum_hcd->port_status &= ~(USB_PORT_STAT_CONNECTION |
+                                               USB_PORT_STAT_ENABLE);
+                       if ((dum_hcd->old_status &
+                            USB_PORT_STAT_CONNECTION) != 0)
+                               dum_hcd->port_status |=
+                                       (USB_PORT_STAT_C_CONNECTION << 16);
+               } else {
+                       /* device is connected and not suspended */
+                       dum_hcd->port_status |= (USB_PORT_STAT_CONNECTION |
+                                                USB_PORT_STAT_SPEED_5GBPS) ;
+                       if ((dum_hcd->old_status &
+                            USB_PORT_STAT_CONNECTION) == 0)
+                               dum_hcd->port_status |=
+                                       (USB_PORT_STAT_C_CONNECTION << 16);
+                       if ((dum_hcd->port_status &
+                            USB_PORT_STAT_ENABLE) == 1 &&
+                               (dum_hcd->port_status &
+                                USB_SS_PORT_LS_U0) == 1 &&
+                               dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
+                               dum_hcd->active = 1;
+               }
+       } else {
+               if ((dum_hcd->port_status & USB_PORT_STAT_POWER) == 0) {
+                       dum_hcd->port_status = 0;
+               } else if (!dum->pullup || dum->udc_suspended) {
+                       /* UDC suspend must cause a disconnect */
+                       dum_hcd->port_status &= ~(USB_PORT_STAT_CONNECTION |
+                                               USB_PORT_STAT_ENABLE |
+                                               USB_PORT_STAT_LOW_SPEED |
+                                               USB_PORT_STAT_HIGH_SPEED |
+                                               USB_PORT_STAT_SUSPEND);
+                       if ((dum_hcd->old_status &
+                            USB_PORT_STAT_CONNECTION) != 0)
+                               dum_hcd->port_status |=
+                                       (USB_PORT_STAT_C_CONNECTION << 16);
+               } else {
+                       dum_hcd->port_status |= USB_PORT_STAT_CONNECTION;
+                       if ((dum_hcd->old_status &
+                            USB_PORT_STAT_CONNECTION) == 0)
+                               dum_hcd->port_status |=
+                                       (USB_PORT_STAT_C_CONNECTION << 16);
+                       if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0)
+                               dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND;
+                       else if ((dum_hcd->port_status &
+                                 USB_PORT_STAT_SUSPEND) == 0 &&
+                                       dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
+                               dum_hcd->active = 1;
+               }
+       }
+}
+
+/* caller must hold lock */
+static void set_link_state(struct dummy_hcd *dum_hcd)
+{
+       struct dummy *dum = dum_hcd->dum;
+
+       dum_hcd->active = 0;
+       if (dum->pullup)
+               if ((dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3 &&
+                    dum->gadget.speed != USB_SPEED_SUPER) ||
+                   (dummy_hcd_to_hcd(dum_hcd)->speed != HCD_USB3 &&
+                    dum->gadget.speed == USB_SPEED_SUPER))
+                       return;
+
+       set_link_state_by_speed(dum_hcd);
+
+       if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0 ||
+            dum_hcd->active)
+               dum_hcd->resuming = 0;
+
+       /* if !connected or reset */
+       if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0 ||
+                       (dum_hcd->port_status & USB_PORT_STAT_RESET) != 0) {
+               /*
+                * We're connected and not reset (reset occurred now),
+                * and driver attached - disconnect!
+                */
+               if ((dum_hcd->old_status & USB_PORT_STAT_CONNECTION) != 0 &&
+                   (dum_hcd->old_status & USB_PORT_STAT_RESET) == 0 &&
+                   dum->driver) {
+                       stop_activity(dum);
+                       spin_unlock(&dum->lock);
+                       dum->driver->disconnect(&dum->gadget);
+                       spin_lock(&dum->lock);
+               }
+       } else if (dum_hcd->active != dum_hcd->old_active) {
+               if (dum_hcd->old_active && dum->driver->suspend) {
+                       spin_unlock(&dum->lock);
+                       dum->driver->suspend(&dum->gadget);
+                       spin_lock(&dum->lock);
+               } else if (!dum_hcd->old_active &&  dum->driver->resume) {
+                       spin_unlock(&dum->lock);
+                       dum->driver->resume(&dum->gadget);
+                       spin_lock(&dum->lock);
+               }
+       }
+
+       dum_hcd->old_status = dum_hcd->port_status;
+       dum_hcd->old_active = dum_hcd->active;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* SLAVE/GADGET SIDE DRIVER
+ *
+ * This only tracks gadget state.  All the work is done when the host
+ * side tries some (emulated) i/o operation.  Real device controller
+ * drivers would do real i/o using dma, fifos, irqs, timers, etc.
+ */
+
+#define is_enabled(dum) \
+       (dum->port_status & USB_PORT_STAT_ENABLE)
+
+static int dummy_enable(struct usb_ep *_ep,
+               const struct usb_endpoint_descriptor *desc)
+{
+       struct dummy            *dum;
+       struct dummy_hcd        *dum_hcd;
+       struct dummy_ep         *ep;
+       unsigned                max;
+       int                     retval;
+
+       ep = usb_ep_to_dummy_ep(_ep);
+       if (!_ep || !desc || ep->desc || _ep->name == ep0name
+                       || desc->bDescriptorType != USB_DT_ENDPOINT)
+               return -EINVAL;
+       dum = ep_to_dummy(ep);
+       if (!dum->driver)
+               return -ESHUTDOWN;
+
+       dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
+       if (!is_enabled(dum_hcd))
+               return -ESHUTDOWN;
+
+       /*
+        * For HS/FS devices only bits 0..10 of the wMaxPacketSize represent the
+        * maximum packet size.
+        * For SS devices the wMaxPacketSize is limited by 1024.
+        */
+       max = usb_endpoint_maxp(desc) & 0x7ff;
+
+       /* drivers must not request bad settings, since lower levels
+        * (hardware or its drivers) may not check.  some endpoints
+        * can't do iso, many have maxpacket limitations, etc.
+        *
+        * since this "hardware" driver is here to help debugging, we
+        * have some extra sanity checks.  (there could be more though,
+        * especially for "ep9out" style fixed function ones.)
+        */
+       retval = -EINVAL;
+       switch (usb_endpoint_type(desc)) {
+       case USB_ENDPOINT_XFER_BULK:
+               if (strstr(ep->ep.name, "-iso")
+                               || strstr(ep->ep.name, "-int")) {
+                       goto done;
+               }
+               switch (dum->gadget.speed) {
+               case USB_SPEED_SUPER:
+                       if (max == 1024)
+                               break;
+                       goto done;
+               case USB_SPEED_HIGH:
+                       if (max == 512)
+                               break;
+                       goto done;
+               case USB_SPEED_FULL:
+                       if (max == 8 || max == 16 || max == 32 || max == 64)
+                               /* we'll fake any legal size */
+                               break;
+                       /* save a return statement */
+               default:
+                       goto done;
+               }
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               if (strstr(ep->ep.name, "-iso")) /* bulk is ok */
+                       goto done;
+               /* real hardware might not handle all packet sizes */
+               switch (dum->gadget.speed) {
+               case USB_SPEED_SUPER:
+               case USB_SPEED_HIGH:
+                       if (max <= 1024)
+                               break;
+                       /* save a return statement */
+               case USB_SPEED_FULL:
+                       if (max <= 64)
+                               break;
+                       /* save a return statement */
+               default:
+                       if (max <= 8)
+                               break;
+                       goto done;
+               }
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               if (strstr(ep->ep.name, "-bulk")
+                               || strstr(ep->ep.name, "-int"))
+                       goto done;
+               /* real hardware might not handle all packet sizes */
+               switch (dum->gadget.speed) {
+               case USB_SPEED_SUPER:
+               case USB_SPEED_HIGH:
+                       if (max <= 1024)
+                               break;
+                       /* save a return statement */
+               case USB_SPEED_FULL:
+                       if (max <= 1023)
+                               break;
+                       /* save a return statement */
+               default:
+                       goto done;
+               }
+               break;
+       default:
+               /* few chips support control except on ep0 */
+               goto done;
+       }
+
+       _ep->maxpacket = max;
+       if (usb_ss_max_streams(_ep->comp_desc)) {
+               if (!usb_endpoint_xfer_bulk(desc)) {
+                       dev_err(udc_dev(dum), "Can't enable stream support on "
+                                       "non-bulk ep %s\n", _ep->name);
+                       return -EINVAL;
+               }
+               ep->stream_en = 1;
+       }
+       ep->desc = desc;
+
+       dev_dbg(udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d stream %s\n",
+               _ep->name,
+               desc->bEndpointAddress & 0x0f,
+               (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
+               ({ char *val;
+                switch (usb_endpoint_type(desc)) {
+                case USB_ENDPOINT_XFER_BULK:
+                        val = "bulk";
+                        break;
+                case USB_ENDPOINT_XFER_ISOC:
+                        val = "iso";
+                        break;
+                case USB_ENDPOINT_XFER_INT:
+                        val = "intr";
+                        break;
+                default:
+                        val = "ctrl";
+                        break;
+                } val; }),
+               max, ep->stream_en ? "enabled" : "disabled");
+
+       /* at this point real hardware should be NAKing transfers
+        * to that endpoint, until a buffer is queued to it.
+        */
+       ep->halted = ep->wedged = 0;
+       retval = 0;
+done:
+       return retval;
+}
+
+static int dummy_disable(struct usb_ep *_ep)
+{
+       struct dummy_ep         *ep;
+       struct dummy            *dum;
+       unsigned long           flags;
+
+       ep = usb_ep_to_dummy_ep(_ep);
+       if (!_ep || !ep->desc || _ep->name == ep0name)
+               return -EINVAL;
+       dum = ep_to_dummy(ep);
+
+       spin_lock_irqsave(&dum->lock, flags);
+       ep->desc = NULL;
+       ep->stream_en = 0;
+       nuke(dum, ep);
+       spin_unlock_irqrestore(&dum->lock, flags);
+
+       dev_dbg(udc_dev(dum), "disabled %s\n", _ep->name);
+       return 0;
+}
+
+static struct usb_request *dummy_alloc_request(struct usb_ep *_ep,
+               gfp_t mem_flags)
+{
+       struct dummy_ep         *ep;
+       struct dummy_request    *req;
+
+       if (!_ep)
+               return NULL;
+       ep = usb_ep_to_dummy_ep(_ep);
+
+       req = kzalloc(sizeof(*req), mem_flags);
+       if (!req)
+               return NULL;
+       INIT_LIST_HEAD(&req->queue);
+       return &req->req;
+}
+
+static void dummy_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct dummy_request    *req;
+
+       if (!_ep || !_req) {
+               WARN_ON(1);
+               return;
+       }
+
+       req = usb_request_to_dummy_request(_req);
+       WARN_ON(!list_empty(&req->queue));
+       kfree(req);
+}
+
+static void fifo_complete(struct usb_ep *ep, struct usb_request *req)
+{
+}
+
+static int dummy_queue(struct usb_ep *_ep, struct usb_request *_req,
+               gfp_t mem_flags)
+{
+       struct dummy_ep         *ep;
+       struct dummy_request    *req;
+       struct dummy            *dum;
+       struct dummy_hcd        *dum_hcd;
+       unsigned long           flags;
+
+       req = usb_request_to_dummy_request(_req);
+       if (!_req || !list_empty(&req->queue) || !_req->complete)
+               return -EINVAL;
+
+       ep = usb_ep_to_dummy_ep(_ep);
+       if (!_ep || (!ep->desc && _ep->name != ep0name))
+               return -EINVAL;
+
+       dum = ep_to_dummy(ep);
+       dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
+       if (!dum->driver || !is_enabled(dum_hcd))
+               return -ESHUTDOWN;
+
+#if 0
+       dev_dbg(udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n",
+                       ep, _req, _ep->name, _req->length, _req->buf);
+#endif
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+       spin_lock_irqsave(&dum->lock, flags);
+
+       /* implement an emulated single-request FIFO */
+       if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
+                       list_empty(&dum->fifo_req.queue) &&
+                       list_empty(&ep->queue) &&
+                       _req->length <= FIFO_SIZE) {
+               req = &dum->fifo_req;
+               req->req = *_req;
+               req->req.buf = dum->fifo_buf;
+               memcpy(dum->fifo_buf, _req->buf, _req->length);
+               req->req.context = dum;
+               req->req.complete = fifo_complete;
+
+               list_add_tail(&req->queue, &ep->queue);
+               spin_unlock(&dum->lock);
+               _req->actual = _req->length;
+               _req->status = 0;
+               _req->complete(_ep, _req);
+               spin_lock(&dum->lock);
+       }  else
+               list_add_tail(&req->queue, &ep->queue);
+       spin_unlock_irqrestore(&dum->lock, flags);
+
+       /* real hardware would likely enable transfers here, in case
+        * it'd been left NAKing.
+        */
+       return 0;
+}
+
+static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct dummy_ep         *ep;
+       struct dummy            *dum;
+       int                     retval = -EINVAL;
+       unsigned long           flags;
+       struct dummy_request    *req = NULL;
+
+       if (!_ep || !_req)
+               return retval;
+       ep = usb_ep_to_dummy_ep(_ep);
+       dum = ep_to_dummy(ep);
+
+       if (!dum->driver)
+               return -ESHUTDOWN;
+
+       local_irq_save(flags);
+       spin_lock(&dum->lock);
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req) {
+                       list_del_init(&req->queue);
+                       _req->status = -ECONNRESET;
+                       retval = 0;
+                       break;
+               }
+       }
+       spin_unlock(&dum->lock);
+
+       if (retval == 0) {
+               dev_dbg(udc_dev(dum),
+                               "dequeued req %p from %s, len %d buf %p\n",
+                               req, _ep->name, _req->length, _req->buf);
+               _req->complete(_ep, _req);
+       }
+       local_irq_restore(flags);
+       return retval;
+}
+
+static int
+dummy_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
+{
+       struct dummy_ep         *ep;
+       struct dummy            *dum;
+
+       if (!_ep)
+               return -EINVAL;
+       ep = usb_ep_to_dummy_ep(_ep);
+       dum = ep_to_dummy(ep);
+       if (!dum->driver)
+               return -ESHUTDOWN;
+       if (!value)
+               ep->halted = ep->wedged = 0;
+       else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
+                       !list_empty(&ep->queue))
+               return -EAGAIN;
+       else {
+               ep->halted = 1;
+               if (wedged)
+                       ep->wedged = 1;
+       }
+       /* FIXME clear emulated data toggle too */
+       return 0;
+}
+
+static int
+dummy_set_halt(struct usb_ep *_ep, int value)
+{
+       return dummy_set_halt_and_wedge(_ep, value, 0);
+}
+
+static int dummy_set_wedge(struct usb_ep *_ep)
+{
+       if (!_ep || _ep->name == ep0name)
+               return -EINVAL;
+       return dummy_set_halt_and_wedge(_ep, 1, 1);
+}
+
+static const struct usb_ep_ops dummy_ep_ops = {
+       .enable         = dummy_enable,
+       .disable        = dummy_disable,
+
+       .alloc_request  = dummy_alloc_request,
+       .free_request   = dummy_free_request,
+
+       .queue          = dummy_queue,
+       .dequeue        = dummy_dequeue,
+
+       .set_halt       = dummy_set_halt,
+       .set_wedge      = dummy_set_wedge,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* there are both host and device side versions of this call ... */
+static int dummy_g_get_frame(struct usb_gadget *_gadget)
+{
+       struct timeval  tv;
+
+       do_gettimeofday(&tv);
+       return tv.tv_usec / 1000;
+}
+
+static int dummy_wakeup(struct usb_gadget *_gadget)
+{
+       struct dummy_hcd *dum_hcd;
+
+       dum_hcd = gadget_to_dummy_hcd(_gadget);
+       if (!(dum_hcd->dum->devstatus & ((1 << USB_DEVICE_B_HNP_ENABLE)
+                               | (1 << USB_DEVICE_REMOTE_WAKEUP))))
+               return -EINVAL;
+       if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0)
+               return -ENOLINK;
+       if ((dum_hcd->port_status & USB_PORT_STAT_SUSPEND) == 0 &&
+                        dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
+               return -EIO;
+
+       /* FIXME: What if the root hub is suspended but the port isn't? */
+
+       /* hub notices our request, issues downstream resume, etc */
+       dum_hcd->resuming = 1;
+       dum_hcd->re_timeout = jiffies + msecs_to_jiffies(20);
+       mod_timer(&dummy_hcd_to_hcd(dum_hcd)->rh_timer, dum_hcd->re_timeout);
+       return 0;
+}
+
+static int dummy_set_selfpowered(struct usb_gadget *_gadget, int value)
+{
+       struct dummy    *dum;
+
+       dum = gadget_to_dummy_hcd(_gadget)->dum;
+       if (value)
+               dum->devstatus |= (1 << USB_DEVICE_SELF_POWERED);
+       else
+               dum->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
+       return 0;
+}
+
+static void dummy_udc_update_ep0(struct dummy *dum)
+{
+       if (dum->gadget.speed == USB_SPEED_SUPER)
+               dum->ep[0].ep.maxpacket = 9;
+       else
+               dum->ep[0].ep.maxpacket = 64;
+}
+
+static int dummy_pullup(struct usb_gadget *_gadget, int value)
+{
+       struct dummy_hcd *dum_hcd;
+       struct dummy    *dum;
+       unsigned long   flags;
+
+       dum = gadget_dev_to_dummy(&_gadget->dev);
+
+       if (value && dum->driver) {
+               if (mod_data.is_super_speed)
+                       dum->gadget.speed = dum->driver->max_speed;
+               else if (mod_data.is_high_speed)
+                       dum->gadget.speed = min_t(u8, USB_SPEED_HIGH,
+                                       dum->driver->max_speed);
+               else
+                       dum->gadget.speed = USB_SPEED_FULL;
+               dummy_udc_update_ep0(dum);
+
+               if (dum->gadget.speed < dum->driver->max_speed)
+                       dev_dbg(udc_dev(dum), "This device can perform faster"
+                               " if you connect it to a %s port...\n",
+                               usb_speed_string(dum->driver->max_speed));
+       }
+       dum_hcd = gadget_to_dummy_hcd(_gadget);
+
+       spin_lock_irqsave(&dum->lock, flags);
+       dum->pullup = (value != 0);
+       set_link_state(dum_hcd);
+       spin_unlock_irqrestore(&dum->lock, flags);
+
+       usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
+       return 0;
+}
+
+static int dummy_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+static int dummy_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+
+static const struct usb_gadget_ops dummy_ops = {
+       .get_frame      = dummy_g_get_frame,
+       .wakeup         = dummy_wakeup,
+       .set_selfpowered = dummy_set_selfpowered,
+       .pullup         = dummy_pullup,
+       .udc_start      = dummy_udc_start,
+       .udc_stop       = dummy_udc_stop,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* "function" sysfs attribute */
+static ssize_t function_show(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct dummy    *dum = gadget_dev_to_dummy(dev);
+
+       if (!dum->driver || !dum->driver->function)
+               return 0;
+       return scnprintf(buf, PAGE_SIZE, "%s\n", dum->driver->function);
+}
+static DEVICE_ATTR_RO(function);
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Driver registration/unregistration.
+ *
+ * This is basically hardware-specific; there's usually only one real USB
+ * device (not host) controller since that's how USB devices are intended
+ * to work.  So most implementations of these api calls will rely on the
+ * fact that only one driver will ever bind to the hardware.  But curious
+ * hardware can be built with discrete components, so the gadget API doesn't
+ * require that assumption.
+ *
+ * For this emulator, it might be convenient to create a usb slave device
+ * for each driver that registers:  just add to a big root hub.
+ */
+
+static int dummy_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct dummy_hcd        *dum_hcd = gadget_to_dummy_hcd(g);
+       struct dummy            *dum = dum_hcd->dum;
+
+       if (driver->max_speed == USB_SPEED_UNKNOWN)
+               return -EINVAL;
+
+       /*
+        * SLAVE side init ... the layer above hardware, which
+        * can't enumerate without help from the driver we're binding.
+        */
+
+       dum->devstatus = 0;
+
+       dum->driver = driver;
+       dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
+                       driver->driver.name);
+       return 0;
+}
+
+static int dummy_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct dummy_hcd        *dum_hcd = gadget_to_dummy_hcd(g);
+       struct dummy            *dum = dum_hcd->dum;
+
+       if (driver)
+               dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
+                               driver->driver.name);
+
+       dum->driver = NULL;
+
+       return 0;
+}
+
+#undef is_enabled
+
+/* The gadget structure is stored inside the hcd structure and will be
+ * released along with it. */
+static void init_dummy_udc_hw(struct dummy *dum)
+{
+       int i;
+
+       INIT_LIST_HEAD(&dum->gadget.ep_list);
+       for (i = 0; i < DUMMY_ENDPOINTS; i++) {
+               struct dummy_ep *ep = &dum->ep[i];
+
+               if (!ep_name[i])
+                       break;
+               ep->ep.name = ep_name[i];
+               ep->ep.ops = &dummy_ep_ops;
+               list_add_tail(&ep->ep.ep_list, &dum->gadget.ep_list);
+               ep->halted = ep->wedged = ep->already_seen =
+                               ep->setup_stage = 0;
+               usb_ep_set_maxpacket_limit(&ep->ep, ~0);
+               ep->ep.max_streams = 16;
+               ep->last_io = jiffies;
+               ep->gadget = &dum->gadget;
+               ep->desc = NULL;
+               INIT_LIST_HEAD(&ep->queue);
+       }
+
+       dum->gadget.ep0 = &dum->ep[0].ep;
+       list_del_init(&dum->ep[0].ep.ep_list);
+       INIT_LIST_HEAD(&dum->fifo_req.queue);
+
+#ifdef CONFIG_USB_OTG
+       dum->gadget.is_otg = 1;
+#endif
+}
+
+static int dummy_udc_probe(struct platform_device *pdev)
+{
+       struct dummy    *dum;
+       int             rc;
+
+       dum = *((void **)dev_get_platdata(&pdev->dev));
+       dum->gadget.name = gadget_name;
+       dum->gadget.ops = &dummy_ops;
+       dum->gadget.max_speed = USB_SPEED_SUPER;
+
+       dum->gadget.dev.parent = &pdev->dev;
+       init_dummy_udc_hw(dum);
+
+       rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget);
+       if (rc < 0)
+               goto err_udc;
+
+       rc = device_create_file(&dum->gadget.dev, &dev_attr_function);
+       if (rc < 0)
+               goto err_dev;
+       platform_set_drvdata(pdev, dum);
+       return rc;
+
+err_dev:
+       usb_del_gadget_udc(&dum->gadget);
+err_udc:
+       return rc;
+}
+
+static int dummy_udc_remove(struct platform_device *pdev)
+{
+       struct dummy    *dum = platform_get_drvdata(pdev);
+
+       device_remove_file(&dum->gadget.dev, &dev_attr_function);
+       usb_del_gadget_udc(&dum->gadget);
+       return 0;
+}
+
+static void dummy_udc_pm(struct dummy *dum, struct dummy_hcd *dum_hcd,
+               int suspend)
+{
+       spin_lock_irq(&dum->lock);
+       dum->udc_suspended = suspend;
+       set_link_state(dum_hcd);
+       spin_unlock_irq(&dum->lock);
+}
+
+static int dummy_udc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct dummy            *dum = platform_get_drvdata(pdev);
+       struct dummy_hcd        *dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
+
+       dev_dbg(&pdev->dev, "%s\n", __func__);
+       dummy_udc_pm(dum, dum_hcd, 1);
+       usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
+       return 0;
+}
+
+static int dummy_udc_resume(struct platform_device *pdev)
+{
+       struct dummy            *dum = platform_get_drvdata(pdev);
+       struct dummy_hcd        *dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
+
+       dev_dbg(&pdev->dev, "%s\n", __func__);
+       dummy_udc_pm(dum, dum_hcd, 0);
+       usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
+       return 0;
+}
+
+static struct platform_driver dummy_udc_driver = {
+       .probe          = dummy_udc_probe,
+       .remove         = dummy_udc_remove,
+       .suspend        = dummy_udc_suspend,
+       .resume         = dummy_udc_resume,
+       .driver         = {
+               .name   = (char *) gadget_name,
+               .owner  = THIS_MODULE,
+       },
+};
+
+/*-------------------------------------------------------------------------*/
+
+static unsigned int dummy_get_ep_idx(const struct usb_endpoint_descriptor *desc)
+{
+       unsigned int index;
+
+       index = usb_endpoint_num(desc) << 1;
+       if (usb_endpoint_dir_in(desc))
+               index |= 1;
+       return index;
+}
+
+/* MASTER/HOST SIDE DRIVER
+ *
+ * this uses the hcd framework to hook up to host side drivers.
+ * its root hub will only have one device, otherwise it acts like
+ * a normal host controller.
+ *
+ * when urbs are queued, they're just stuck on a list that we
+ * scan in a timer callback.  that callback connects writes from
+ * the host with reads from the device, and so on, based on the
+ * usb 2.0 rules.
+ */
+
+static int dummy_ep_stream_en(struct dummy_hcd *dum_hcd, struct urb *urb)
+{
+       const struct usb_endpoint_descriptor *desc = &urb->ep->desc;
+       u32 index;
+
+       if (!usb_endpoint_xfer_bulk(desc))
+               return 0;
+
+       index = dummy_get_ep_idx(desc);
+       return (1 << index) & dum_hcd->stream_en_ep;
+}
+
+/*
+ * The max stream number is saved as a nibble so for the 30 possible endpoints
+ * we only 15 bytes of memory. Therefore we are limited to max 16 streams (0
+ * means we use only 1 stream). The maximum according to the spec is 16bit so
+ * if the 16 stream limit is about to go, the array size should be incremented
+ * to 30 elements of type u16.
+ */
+static int get_max_streams_for_pipe(struct dummy_hcd *dum_hcd,
+               unsigned int pipe)
+{
+       int max_streams;
+
+       max_streams = dum_hcd->num_stream[usb_pipeendpoint(pipe)];
+       if (usb_pipeout(pipe))
+               max_streams >>= 4;
+       else
+               max_streams &= 0xf;
+       max_streams++;
+       return max_streams;
+}
+
+static void set_max_streams_for_pipe(struct dummy_hcd *dum_hcd,
+               unsigned int pipe, unsigned int streams)
+{
+       int max_streams;
+
+       streams--;
+       max_streams = dum_hcd->num_stream[usb_pipeendpoint(pipe)];
+       if (usb_pipeout(pipe)) {
+               streams <<= 4;
+               max_streams &= 0xf;
+       } else {
+               max_streams &= 0xf0;
+       }
+       max_streams |= streams;
+       dum_hcd->num_stream[usb_pipeendpoint(pipe)] = max_streams;
+}
+
+static int dummy_validate_stream(struct dummy_hcd *dum_hcd, struct urb *urb)
+{
+       unsigned int max_streams;
+       int enabled;
+
+       enabled = dummy_ep_stream_en(dum_hcd, urb);
+       if (!urb->stream_id) {
+               if (enabled)
+                       return -EINVAL;
+               return 0;
+       }
+       if (!enabled)
+               return -EINVAL;
+
+       max_streams = get_max_streams_for_pipe(dum_hcd,
+                       usb_pipeendpoint(urb->pipe));
+       if (urb->stream_id > max_streams) {
+               dev_err(dummy_dev(dum_hcd), "Stream id %d is out of range.\n",
+                               urb->stream_id);
+               BUG();
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int dummy_urb_enqueue(
+       struct usb_hcd                  *hcd,
+       struct urb                      *urb,
+       gfp_t                           mem_flags
+) {
+       struct dummy_hcd *dum_hcd;
+       struct urbp     *urbp;
+       unsigned long   flags;
+       int             rc;
+
+       urbp = kmalloc(sizeof *urbp, mem_flags);
+       if (!urbp)
+               return -ENOMEM;
+       urbp->urb = urb;
+       urbp->miter_started = 0;
+
+       dum_hcd = hcd_to_dummy_hcd(hcd);
+       spin_lock_irqsave(&dum_hcd->dum->lock, flags);
+
+       rc = dummy_validate_stream(dum_hcd, urb);
+       if (rc) {
+               kfree(urbp);
+               goto done;
+       }
+
+       rc = usb_hcd_link_urb_to_ep(hcd, urb);
+       if (rc) {
+               kfree(urbp);
+               goto done;
+       }
+
+       if (!dum_hcd->udev) {
+               dum_hcd->udev = urb->dev;
+               usb_get_dev(dum_hcd->udev);
+       } else if (unlikely(dum_hcd->udev != urb->dev))
+               dev_err(dummy_dev(dum_hcd), "usb_device address has changed!\n");
+
+       list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list);
+       urb->hcpriv = urbp;
+       if (usb_pipetype(urb->pipe) == PIPE_CONTROL)
+               urb->error_count = 1;           /* mark as a new urb */
+
+       /* kick the scheduler, it'll do the rest */
+       if (!timer_pending(&dum_hcd->timer))
+               mod_timer(&dum_hcd->timer, jiffies + 1);
+
+ done:
+       spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
+       return rc;
+}
+
+static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+{
+       struct dummy_hcd *dum_hcd;
+       unsigned long   flags;
+       int             rc;
+
+       /* giveback happens automatically in timer callback,
+        * so make sure the callback happens */
+       dum_hcd = hcd_to_dummy_hcd(hcd);
+       spin_lock_irqsave(&dum_hcd->dum->lock, flags);
+
+       rc = usb_hcd_check_unlink_urb(hcd, urb, status);
+       if (!rc && dum_hcd->rh_state != DUMMY_RH_RUNNING &&
+                       !list_empty(&dum_hcd->urbp_list))
+               mod_timer(&dum_hcd->timer, jiffies);
+
+       spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
+       return rc;
+}
+
+static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req,
+               u32 len)
+{
+       void *ubuf, *rbuf;
+       struct urbp *urbp = urb->hcpriv;
+       int to_host;
+       struct sg_mapping_iter *miter = &urbp->miter;
+       u32 trans = 0;
+       u32 this_sg;
+       bool next_sg;
+
+       to_host = usb_pipein(urb->pipe);
+       rbuf = req->req.buf + req->req.actual;
+
+       if (!urb->num_sgs) {
+               ubuf = urb->transfer_buffer + urb->actual_length;
+               if (to_host)
+                       memcpy(ubuf, rbuf, len);
+               else
+                       memcpy(rbuf, ubuf, len);
+               return len;
+       }
+
+       if (!urbp->miter_started) {
+               u32 flags = SG_MITER_ATOMIC;
+
+               if (to_host)
+                       flags |= SG_MITER_TO_SG;
+               else
+                       flags |= SG_MITER_FROM_SG;
+
+               sg_miter_start(miter, urb->sg, urb->num_sgs, flags);
+               urbp->miter_started = 1;
+       }
+       next_sg = sg_miter_next(miter);
+       if (next_sg == false) {
+               WARN_ON_ONCE(1);
+               return -EINVAL;
+       }
+       do {
+               ubuf = miter->addr;
+               this_sg = min_t(u32, len, miter->length);
+               miter->consumed = this_sg;
+               trans += this_sg;
+
+               if (to_host)
+                       memcpy(ubuf, rbuf, this_sg);
+               else
+                       memcpy(rbuf, ubuf, this_sg);
+               len -= this_sg;
+
+               if (!len)
+                       break;
+               next_sg = sg_miter_next(miter);
+               if (next_sg == false) {
+                       WARN_ON_ONCE(1);
+                       return -EINVAL;
+               }
+
+               rbuf += this_sg;
+       } while (1);
+
+       sg_miter_stop(miter);
+       return trans;
+}
+
+/* transfer up to a frame's worth; caller must own lock */
+static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
+               struct dummy_ep *ep, int limit, int *status)
+{
+       struct dummy            *dum = dum_hcd->dum;
+       struct dummy_request    *req;
+
+top:
+       /* if there's no request queued, the device is NAKing; return */
+       list_for_each_entry(req, &ep->queue, queue) {
+               unsigned        host_len, dev_len, len;
+               int             is_short, to_host;
+               int             rescan = 0;
+
+               if (dummy_ep_stream_en(dum_hcd, urb)) {
+                       if ((urb->stream_id != req->req.stream_id))
+                               continue;
+               }
+
+               /* 1..N packets of ep->ep.maxpacket each ... the last one
+                * may be short (including zero length).
+                *
+                * writer can send a zlp explicitly (length 0) or implicitly
+                * (length mod maxpacket zero, and 'zero' flag); they always
+                * terminate reads.
+                */
+               host_len = urb->transfer_buffer_length - urb->actual_length;
+               dev_len = req->req.length - req->req.actual;
+               len = min(host_len, dev_len);
+
+               /* FIXME update emulated data toggle too */
+
+               to_host = usb_pipein(urb->pipe);
+               if (unlikely(len == 0))
+                       is_short = 1;
+               else {
+                       /* not enough bandwidth left? */
+                       if (limit < ep->ep.maxpacket && limit < len)
+                               break;
+                       len = min_t(unsigned, len, limit);
+                       if (len == 0)
+                               break;
+
+                       /* use an extra pass for the final short packet */
+                       if (len > ep->ep.maxpacket) {
+                               rescan = 1;
+                               len -= (len % ep->ep.maxpacket);
+                       }
+                       is_short = (len % ep->ep.maxpacket) != 0;
+
+                       len = dummy_perform_transfer(urb, req, len);
+
+                       ep->last_io = jiffies;
+                       if ((int)len < 0) {
+                               req->req.status = len;
+                       } else {
+                               limit -= len;
+                               urb->actual_length += len;
+                               req->req.actual += len;
+                       }
+               }
+
+               /* short packets terminate, maybe with overflow/underflow.
+                * it's only really an error to write too much.
+                *
+                * partially filling a buffer optionally blocks queue advances
+                * (so completion handlers can clean up the queue) but we don't
+                * need to emulate such data-in-flight.
+                */
+               if (is_short) {
+                       if (host_len == dev_len) {
+                               req->req.status = 0;
+                               *status = 0;
+                       } else if (to_host) {
+                               req->req.status = 0;
+                               if (dev_len > host_len)
+                                       *status = -EOVERFLOW;
+                               else
+                                       *status = 0;
+                       } else if (!to_host) {
+                               *status = 0;
+                               if (host_len > dev_len)
+                                       req->req.status = -EOVERFLOW;
+                               else
+                                       req->req.status = 0;
+                       }
+
+               /* many requests terminate without a short packet */
+               } else {
+                       if (req->req.length == req->req.actual
+                                       && !req->req.zero)
+                               req->req.status = 0;
+                       if (urb->transfer_buffer_length == urb->actual_length
+                                       && !(urb->transfer_flags
+                                               & URB_ZERO_PACKET))
+                               *status = 0;
+               }
+
+               /* device side completion --> continuable */
+               if (req->req.status != -EINPROGRESS) {
+                       list_del_init(&req->queue);
+
+                       spin_unlock(&dum->lock);
+                       req->req.complete(&ep->ep, &req->req);
+                       spin_lock(&dum->lock);
+
+                       /* requests might have been unlinked... */
+                       rescan = 1;
+               }
+
+               /* host side completion --> terminate */
+               if (*status != -EINPROGRESS)
+                       break;
+
+               /* rescan to continue with any other queued i/o */
+               if (rescan)
+                       goto top;
+       }
+       return limit;
+}
+
+static int periodic_bytes(struct dummy *dum, struct dummy_ep *ep)
+{
+       int     limit = ep->ep.maxpacket;
+
+       if (dum->gadget.speed == USB_SPEED_HIGH) {
+               int     tmp;
+
+               /* high bandwidth mode */
+               tmp = usb_endpoint_maxp(ep->desc);
+               tmp = (tmp >> 11) & 0x03;
+               tmp *= 8 /* applies to entire frame */;
+               limit += limit * tmp;
+       }
+       if (dum->gadget.speed == USB_SPEED_SUPER) {
+               switch (usb_endpoint_type(ep->desc)) {
+               case USB_ENDPOINT_XFER_ISOC:
+                       /* Sec. 4.4.8.2 USB3.0 Spec */
+                       limit = 3 * 16 * 1024 * 8;
+                       break;
+               case USB_ENDPOINT_XFER_INT:
+                       /* Sec. 4.4.7.2 USB3.0 Spec */
+                       limit = 3 * 1024 * 8;
+                       break;
+               case USB_ENDPOINT_XFER_BULK:
+               default:
+                       break;
+               }
+       }
+       return limit;
+}
+
+#define is_active(dum_hcd)     ((dum_hcd->port_status & \
+               (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE | \
+                       USB_PORT_STAT_SUSPEND)) \
+               == (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE))
+
+static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address)
+{
+       int             i;
+
+       if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ?
+                       dum->ss_hcd : dum->hs_hcd)))
+               return NULL;
+       if ((address & ~USB_DIR_IN) == 0)
+               return &dum->ep[0];
+       for (i = 1; i < DUMMY_ENDPOINTS; i++) {
+               struct dummy_ep *ep = &dum->ep[i];
+
+               if (!ep->desc)
+                       continue;
+               if (ep->desc->bEndpointAddress == address)
+                       return ep;
+       }
+       return NULL;
+}
+
+#undef is_active
+
+#define Dev_Request    (USB_TYPE_STANDARD | USB_RECIP_DEVICE)
+#define Dev_InRequest  (Dev_Request | USB_DIR_IN)
+#define Intf_Request   (USB_TYPE_STANDARD | USB_RECIP_INTERFACE)
+#define Intf_InRequest (Intf_Request | USB_DIR_IN)
+#define Ep_Request     (USB_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+#define Ep_InRequest   (Ep_Request | USB_DIR_IN)
+
+
+/**
+ * handle_control_request() - handles all control transfers
+ * @dum: pointer to dummy (the_controller)
+ * @urb: the urb request to handle
+ * @setup: pointer to the setup data for a USB device control
+ *      request
+ * @status: pointer to request handling status
+ *
+ * Return 0 - if the request was handled
+ *       1 - if the request wasn't handles
+ *       error code on error
+ */
+static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,
+                                 struct usb_ctrlrequest *setup,
+                                 int *status)
+{
+       struct dummy_ep         *ep2;
+       struct dummy            *dum = dum_hcd->dum;
+       int                     ret_val = 1;
+       unsigned        w_index;
+       unsigned        w_value;
+
+       w_index = le16_to_cpu(setup->wIndex);
+       w_value = le16_to_cpu(setup->wValue);
+       switch (setup->bRequest) {
+       case USB_REQ_SET_ADDRESS:
+               if (setup->bRequestType != Dev_Request)
+                       break;
+               dum->address = w_value;
+               *status = 0;
+               dev_dbg(udc_dev(dum), "set_address = %d\n",
+                               w_value);
+               ret_val = 0;
+               break;
+       case USB_REQ_SET_FEATURE:
+               if (setup->bRequestType == Dev_Request) {
+                       ret_val = 0;
+                       switch (w_value) {
+                       case USB_DEVICE_REMOTE_WAKEUP:
+                               break;
+                       case USB_DEVICE_B_HNP_ENABLE:
+                               dum->gadget.b_hnp_enable = 1;
+                               break;
+                       case USB_DEVICE_A_HNP_SUPPORT:
+                               dum->gadget.a_hnp_support = 1;
+                               break;
+                       case USB_DEVICE_A_ALT_HNP_SUPPORT:
+                               dum->gadget.a_alt_hnp_support = 1;
+                               break;
+                       case USB_DEVICE_U1_ENABLE:
+                               if (dummy_hcd_to_hcd(dum_hcd)->speed ==
+                                   HCD_USB3)
+                                       w_value = USB_DEV_STAT_U1_ENABLED;
+                               else
+                                       ret_val = -EOPNOTSUPP;
+                               break;
+                       case USB_DEVICE_U2_ENABLE:
+                               if (dummy_hcd_to_hcd(dum_hcd)->speed ==
+                                   HCD_USB3)
+                                       w_value = USB_DEV_STAT_U2_ENABLED;
+                               else
+                                       ret_val = -EOPNOTSUPP;
+                               break;
+                       case USB_DEVICE_LTM_ENABLE:
+                               if (dummy_hcd_to_hcd(dum_hcd)->speed ==
+                                   HCD_USB3)
+                                       w_value = USB_DEV_STAT_LTM_ENABLED;
+                               else
+                                       ret_val = -EOPNOTSUPP;
+                               break;
+                       default:
+                               ret_val = -EOPNOTSUPP;
+                       }
+                       if (ret_val == 0) {
+                               dum->devstatus |= (1 << w_value);
+                               *status = 0;
+                       }
+               } else if (setup->bRequestType == Ep_Request) {
+                       /* endpoint halt */
+                       ep2 = find_endpoint(dum, w_index);
+                       if (!ep2 || ep2->ep.name == ep0name) {
+                               ret_val = -EOPNOTSUPP;
+                               break;
+                       }
+                       ep2->halted = 1;
+                       ret_val = 0;
+                       *status = 0;
+               }
+               break;
+       case USB_REQ_CLEAR_FEATURE:
+               if (setup->bRequestType == Dev_Request) {
+                       ret_val = 0;
+                       switch (w_value) {
+                       case USB_DEVICE_REMOTE_WAKEUP:
+                               w_value = USB_DEVICE_REMOTE_WAKEUP;
+                               break;
+                       case USB_DEVICE_U1_ENABLE:
+                               if (dummy_hcd_to_hcd(dum_hcd)->speed ==
+                                   HCD_USB3)
+                                       w_value = USB_DEV_STAT_U1_ENABLED;
+                               else
+                                       ret_val = -EOPNOTSUPP;
+                               break;
+                       case USB_DEVICE_U2_ENABLE:
+                               if (dummy_hcd_to_hcd(dum_hcd)->speed ==
+                                   HCD_USB3)
+                                       w_value = USB_DEV_STAT_U2_ENABLED;
+                               else
+                                       ret_val = -EOPNOTSUPP;
+                               break;
+                       case USB_DEVICE_LTM_ENABLE:
+                               if (dummy_hcd_to_hcd(dum_hcd)->speed ==
+                                   HCD_USB3)
+                                       w_value = USB_DEV_STAT_LTM_ENABLED;
+                               else
+                                       ret_val = -EOPNOTSUPP;
+                               break;
+                       default:
+                               ret_val = -EOPNOTSUPP;
+                               break;
+                       }
+                       if (ret_val == 0) {
+                               dum->devstatus &= ~(1 << w_value);
+                               *status = 0;
+                       }
+               } else if (setup->bRequestType == Ep_Request) {
+                       /* endpoint halt */
+                       ep2 = find_endpoint(dum, w_index);
+                       if (!ep2) {
+                               ret_val = -EOPNOTSUPP;
+                               break;
+                       }
+                       if (!ep2->wedged)
+                               ep2->halted = 0;
+                       ret_val = 0;
+                       *status = 0;
+               }
+               break;
+       case USB_REQ_GET_STATUS:
+               if (setup->bRequestType == Dev_InRequest
+                               || setup->bRequestType == Intf_InRequest
+                               || setup->bRequestType == Ep_InRequest) {
+                       char *buf;
+                       /*
+                        * device: remote wakeup, selfpowered
+                        * interface: nothing
+                        * endpoint: halt
+                        */
+                       buf = (char *)urb->transfer_buffer;
+                       if (urb->transfer_buffer_length > 0) {
+                               if (setup->bRequestType == Ep_InRequest) {
+                                       ep2 = find_endpoint(dum, w_index);
+                                       if (!ep2) {
+                                               ret_val = -EOPNOTSUPP;
+                                               break;
+                                       }
+                                       buf[0] = ep2->halted;
+                               } else if (setup->bRequestType ==
+                                          Dev_InRequest) {
+                                       buf[0] = (u8)dum->devstatus;
+                               } else
+                                       buf[0] = 0;
+                       }
+                       if (urb->transfer_buffer_length > 1)
+                               buf[1] = 0;
+                       urb->actual_length = min_t(u32, 2,
+                               urb->transfer_buffer_length);
+                       ret_val = 0;
+                       *status = 0;
+               }
+               break;
+       }
+       return ret_val;
+}
+
+/* drive both sides of the transfers; looks like irq handlers to
+ * both drivers except the callbacks aren't in_irq().
+ */
+static void dummy_timer(unsigned long _dum_hcd)
+{
+       struct dummy_hcd        *dum_hcd = (struct dummy_hcd *) _dum_hcd;
+       struct dummy            *dum = dum_hcd->dum;
+       struct urbp             *urbp, *tmp;
+       unsigned long           flags;
+       int                     limit, total;
+       int                     i;
+
+       /* simplistic model for one frame's bandwidth */
+       switch (dum->gadget.speed) {
+       case USB_SPEED_LOW:
+               total = 8/*bytes*/ * 12/*packets*/;
+               break;
+       case USB_SPEED_FULL:
+               total = 64/*bytes*/ * 19/*packets*/;
+               break;
+       case USB_SPEED_HIGH:
+               total = 512/*bytes*/ * 13/*packets*/ * 8/*uframes*/;
+               break;
+       case USB_SPEED_SUPER:
+               /* Bus speed is 500000 bytes/ms, so use a little less */
+               total = 490000;
+               break;
+       default:
+               dev_err(dummy_dev(dum_hcd), "bogus device speed\n");
+               return;
+       }
+
+       /* FIXME if HZ != 1000 this will probably misbehave ... */
+
+       /* look at each urb queued by the host side driver */
+       spin_lock_irqsave(&dum->lock, flags);
+
+       if (!dum_hcd->udev) {
+               dev_err(dummy_dev(dum_hcd),
+                               "timer fired with no URBs pending?\n");
+               spin_unlock_irqrestore(&dum->lock, flags);
+               return;
+       }
+
+       for (i = 0; i < DUMMY_ENDPOINTS; i++) {
+               if (!ep_name[i])
+                       break;
+               dum->ep[i].already_seen = 0;
+       }
+
+restart:
+       list_for_each_entry_safe(urbp, tmp, &dum_hcd->urbp_list, urbp_list) {
+               struct urb              *urb;
+               struct dummy_request    *req;
+               u8                      address;
+               struct dummy_ep         *ep = NULL;
+               int                     type;
+               int                     status = -EINPROGRESS;
+
+               urb = urbp->urb;
+               if (urb->unlinked)
+                       goto return_urb;
+               else if (dum_hcd->rh_state != DUMMY_RH_RUNNING)
+                       continue;
+               type = usb_pipetype(urb->pipe);
+
+               /* used up this frame's non-periodic bandwidth?
+                * FIXME there's infinite bandwidth for control and
+                * periodic transfers ... unrealistic.
+                */
+               if (total <= 0 && type == PIPE_BULK)
+                       continue;
+
+               /* find the gadget's ep for this request (if configured) */
+               address = usb_pipeendpoint (urb->pipe);
+               if (usb_pipein(urb->pipe))
+                       address |= USB_DIR_IN;
+               ep = find_endpoint(dum, address);
+               if (!ep) {
+                       /* set_configuration() disagreement */
+                       dev_dbg(dummy_dev(dum_hcd),
+                               "no ep configured for urb %p\n",
+                               urb);
+                       status = -EPROTO;
+                       goto return_urb;
+               }
+
+               if (ep->already_seen)
+                       continue;
+               ep->already_seen = 1;
+               if (ep == &dum->ep[0] && urb->error_count) {
+                       ep->setup_stage = 1;    /* a new urb */
+                       urb->error_count = 0;
+               }
+               if (ep->halted && !ep->setup_stage) {
+                       /* NOTE: must not be iso! */
+                       dev_dbg(dummy_dev(dum_hcd), "ep %s halted, urb %p\n",
+                                       ep->ep.name, urb);
+                       status = -EPIPE;
+                       goto return_urb;
+               }
+               /* FIXME make sure both ends agree on maxpacket */
+
+               /* handle control requests */
+               if (ep == &dum->ep[0] && ep->setup_stage) {
+                       struct usb_ctrlrequest          setup;
+                       int                             value = 1;
+
+                       setup = *(struct usb_ctrlrequest *) urb->setup_packet;
+                       /* paranoia, in case of stale queued data */
+                       list_for_each_entry(req, &ep->queue, queue) {
+                               list_del_init(&req->queue);
+                               req->req.status = -EOVERFLOW;
+                               dev_dbg(udc_dev(dum), "stale req = %p\n",
+                                               req);
+
+                               spin_unlock(&dum->lock);
+                               req->req.complete(&ep->ep, &req->req);
+                               spin_lock(&dum->lock);
+                               ep->already_seen = 0;
+                               goto restart;
+                       }
+
+                       /* gadget driver never sees set_address or operations
+                        * on standard feature flags.  some hardware doesn't
+                        * even expose them.
+                        */
+                       ep->last_io = jiffies;
+                       ep->setup_stage = 0;
+                       ep->halted = 0;
+
+                       value = handle_control_request(dum_hcd, urb, &setup,
+                                                      &status);
+
+                       /* gadget driver handles all other requests.  block
+                        * until setup() returns; no reentrancy issues etc.
+                        */
+                       if (value > 0) {
+                               spin_unlock(&dum->lock);
+                               value = dum->driver->setup(&dum->gadget,
+                                               &setup);
+                               spin_lock(&dum->lock);
+
+                               if (value >= 0) {
+                                       /* no delays (max 64KB data stage) */
+                                       limit = 64*1024;
+                                       goto treat_control_like_bulk;
+                               }
+                               /* error, see below */
+                       }
+
+                       if (value < 0) {
+                               if (value != -EOPNOTSUPP)
+                                       dev_dbg(udc_dev(dum),
+                                               "setup --> %d\n",
+                                               value);
+                               status = -EPIPE;
+                               urb->actual_length = 0;
+                       }
+
+                       goto return_urb;
+               }
+
+               /* non-control requests */
+               limit = total;
+               switch (usb_pipetype(urb->pipe)) {
+               case PIPE_ISOCHRONOUS:
+                       /* FIXME is it urb->interval since the last xfer?
+                        * use urb->iso_frame_desc[i].
+                        * complete whether or not ep has requests queued.
+                        * report random errors, to debug drivers.
+                        */
+                       limit = max(limit, periodic_bytes(dum, ep));
+                       status = -ENOSYS;
+                       break;
+
+               case PIPE_INTERRUPT:
+                       /* FIXME is it urb->interval since the last xfer?
+                        * this almost certainly polls too fast.
+                        */
+                       limit = max(limit, periodic_bytes(dum, ep));
+                       /* FALLTHROUGH */
+
+               default:
+treat_control_like_bulk:
+                       ep->last_io = jiffies;
+                       total = transfer(dum_hcd, urb, ep, limit, &status);
+                       break;
+               }
+
+               /* incomplete transfer? */
+               if (status == -EINPROGRESS)
+                       continue;
+
+return_urb:
+               list_del(&urbp->urbp_list);
+               kfree(urbp);
+               if (ep)
+                       ep->already_seen = ep->setup_stage = 0;
+
+               usb_hcd_unlink_urb_from_ep(dummy_hcd_to_hcd(dum_hcd), urb);
+               spin_unlock(&dum->lock);
+               usb_hcd_giveback_urb(dummy_hcd_to_hcd(dum_hcd), urb, status);
+               spin_lock(&dum->lock);
+
+               goto restart;
+       }
+
+       if (list_empty(&dum_hcd->urbp_list)) {
+               usb_put_dev(dum_hcd->udev);
+               dum_hcd->udev = NULL;
+       } else if (dum_hcd->rh_state == DUMMY_RH_RUNNING) {
+               /* want a 1 msec delay here */
+               mod_timer(&dum_hcd->timer, jiffies + msecs_to_jiffies(1));
+       }
+
+       spin_unlock_irqrestore(&dum->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define PORT_C_MASK \
+       ((USB_PORT_STAT_C_CONNECTION \
+       | USB_PORT_STAT_C_ENABLE \
+       | USB_PORT_STAT_C_SUSPEND \
+       | USB_PORT_STAT_C_OVERCURRENT \
+       | USB_PORT_STAT_C_RESET) << 16)
+
+static int dummy_hub_status(struct usb_hcd *hcd, char *buf)
+{
+       struct dummy_hcd        *dum_hcd;
+       unsigned long           flags;
+       int                     retval = 0;
+
+       dum_hcd = hcd_to_dummy_hcd(hcd);
+
+       spin_lock_irqsave(&dum_hcd->dum->lock, flags);
+       if (!HCD_HW_ACCESSIBLE(hcd))
+               goto done;
+
+       if (dum_hcd->resuming && time_after_eq(jiffies, dum_hcd->re_timeout)) {
+               dum_hcd->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
+               dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND;
+               set_link_state(dum_hcd);
+       }
+
+       if ((dum_hcd->port_status & PORT_C_MASK) != 0) {
+               *buf = (1 << 1);
+               dev_dbg(dummy_dev(dum_hcd), "port status 0x%08x has changes\n",
+                               dum_hcd->port_status);
+               retval = 1;
+               if (dum_hcd->rh_state == DUMMY_RH_SUSPENDED)
+                       usb_hcd_resume_root_hub(hcd);
+       }
+done:
+       spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
+       return retval;
+}
+
+/* usb 3.0 root hub device descriptor */
+static struct {
+       struct usb_bos_descriptor bos;
+       struct usb_ss_cap_descriptor ss_cap;
+} __packed usb3_bos_desc = {
+
+       .bos = {
+               .bLength                = USB_DT_BOS_SIZE,
+               .bDescriptorType        = USB_DT_BOS,
+               .wTotalLength           = cpu_to_le16(sizeof(usb3_bos_desc)),
+               .bNumDeviceCaps         = 1,
+       },
+       .ss_cap = {
+               .bLength                = USB_DT_USB_SS_CAP_SIZE,
+               .bDescriptorType        = USB_DT_DEVICE_CAPABILITY,
+               .bDevCapabilityType     = USB_SS_CAP_TYPE,
+               .wSpeedSupported        = cpu_to_le16(USB_5GBPS_OPERATION),
+               .bFunctionalitySupport  = ilog2(USB_5GBPS_OPERATION),
+       },
+};
+
+static inline void
+ss_hub_descriptor(struct usb_hub_descriptor *desc)
+{
+       memset(desc, 0, sizeof *desc);
+       desc->bDescriptorType = 0x2a;
+       desc->bDescLength = 12;
+       desc->wHubCharacteristics = cpu_to_le16(0x0001);
+       desc->bNbrPorts = 1;
+       desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/
+       desc->u.ss.DeviceRemovable = 0xffff;
+}
+
+static inline void hub_descriptor(struct usb_hub_descriptor *desc)
+{
+       memset(desc, 0, sizeof *desc);
+       desc->bDescriptorType = 0x29;
+       desc->bDescLength = 9;
+       desc->wHubCharacteristics = cpu_to_le16(0x0001);
+       desc->bNbrPorts = 1;
+       desc->u.hs.DeviceRemovable[0] = 0xff;
+       desc->u.hs.DeviceRemovable[1] = 0xff;
+}
+
+static int dummy_hub_control(
+       struct usb_hcd  *hcd,
+       u16             typeReq,
+       u16             wValue,
+       u16             wIndex,
+       char            *buf,
+       u16             wLength
+) {
+       struct dummy_hcd *dum_hcd;
+       int             retval = 0;
+       unsigned long   flags;
+
+       if (!HCD_HW_ACCESSIBLE(hcd))
+               return -ETIMEDOUT;
+
+       dum_hcd = hcd_to_dummy_hcd(hcd);
+
+       spin_lock_irqsave(&dum_hcd->dum->lock, flags);
+       switch (typeReq) {
+       case ClearHubFeature:
+               break;
+       case ClearPortFeature:
+               switch (wValue) {
+               case USB_PORT_FEAT_SUSPEND:
+                       if (hcd->speed == HCD_USB3) {
+                               dev_dbg(dummy_dev(dum_hcd),
+                                        "USB_PORT_FEAT_SUSPEND req not "
+                                        "supported for USB 3.0 roothub\n");
+                               goto error;
+                       }
+                       if (dum_hcd->port_status & USB_PORT_STAT_SUSPEND) {
+                               /* 20msec resume signaling */
+                               dum_hcd->resuming = 1;
+                               dum_hcd->re_timeout = jiffies +
+                                               msecs_to_jiffies(20);
+                       }
+                       break;
+               case USB_PORT_FEAT_POWER:
+                       if (hcd->speed == HCD_USB3) {
+                               if (dum_hcd->port_status & USB_PORT_STAT_POWER)
+                                       dev_dbg(dummy_dev(dum_hcd),
+                                               "power-off\n");
+                       } else
+                               if (dum_hcd->port_status &
+                                                       USB_SS_PORT_STAT_POWER)
+                                       dev_dbg(dummy_dev(dum_hcd),
+                                               "power-off\n");
+                       /* FALLS THROUGH */
+               default:
+                       dum_hcd->port_status &= ~(1 << wValue);
+                       set_link_state(dum_hcd);
+               }
+               break;
+       case GetHubDescriptor:
+               if (hcd->speed == HCD_USB3 &&
+                               (wLength < USB_DT_SS_HUB_SIZE ||
+                                wValue != (USB_DT_SS_HUB << 8))) {
+                       dev_dbg(dummy_dev(dum_hcd),
+                               "Wrong hub descriptor type for "
+                               "USB 3.0 roothub.\n");
+                       goto error;
+               }
+               if (hcd->speed == HCD_USB3)
+                       ss_hub_descriptor((struct usb_hub_descriptor *) buf);
+               else
+                       hub_descriptor((struct usb_hub_descriptor *) buf);
+               break;
+
+       case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+               if (hcd->speed != HCD_USB3)
+                       goto error;
+
+               if ((wValue >> 8) != USB_DT_BOS)
+                       goto error;
+
+               memcpy(buf, &usb3_bos_desc, sizeof(usb3_bos_desc));
+               retval = sizeof(usb3_bos_desc);
+               break;
+
+       case GetHubStatus:
+               *(__le32 *) buf = cpu_to_le32(0);
+               break;
+       case GetPortStatus:
+               if (wIndex != 1)
+                       retval = -EPIPE;
+
+               /* whoever resets or resumes must GetPortStatus to
+                * complete it!!
+                */
+               if (dum_hcd->resuming &&
+                               time_after_eq(jiffies, dum_hcd->re_timeout)) {
+                       dum_hcd->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
+                       dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND;
+               }
+               if ((dum_hcd->port_status & USB_PORT_STAT_RESET) != 0 &&
+                               time_after_eq(jiffies, dum_hcd->re_timeout)) {
+                       dum_hcd->port_status |= (USB_PORT_STAT_C_RESET << 16);
+                       dum_hcd->port_status &= ~USB_PORT_STAT_RESET;
+                       if (dum_hcd->dum->pullup) {
+                               dum_hcd->port_status |= USB_PORT_STAT_ENABLE;
+
+                               if (hcd->speed < HCD_USB3) {
+                                       switch (dum_hcd->dum->gadget.speed) {
+                                       case USB_SPEED_HIGH:
+                                               dum_hcd->port_status |=
+                                                     USB_PORT_STAT_HIGH_SPEED;
+                                               break;
+                                       case USB_SPEED_LOW:
+                                               dum_hcd->dum->gadget.ep0->
+                                                       maxpacket = 8;
+                                               dum_hcd->port_status |=
+                                                       USB_PORT_STAT_LOW_SPEED;
+                                               break;
+                                       default:
+                                               dum_hcd->dum->gadget.speed =
+                                                       USB_SPEED_FULL;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               set_link_state(dum_hcd);
+               ((__le16 *) buf)[0] = cpu_to_le16(dum_hcd->port_status);
+               ((__le16 *) buf)[1] = cpu_to_le16(dum_hcd->port_status >> 16);
+               break;
+       case SetHubFeature:
+               retval = -EPIPE;
+               break;
+       case SetPortFeature:
+               switch (wValue) {
+               case USB_PORT_FEAT_LINK_STATE:
+                       if (hcd->speed != HCD_USB3) {
+                               dev_dbg(dummy_dev(dum_hcd),
+                                        "USB_PORT_FEAT_LINK_STATE req not "
+                                        "supported for USB 2.0 roothub\n");
+                               goto error;
+                       }
+                       /*
+                        * Since this is dummy we don't have an actual link so
+                        * there is nothing to do for the SET_LINK_STATE cmd
+                        */
+                       break;
+               case USB_PORT_FEAT_U1_TIMEOUT:
+               case USB_PORT_FEAT_U2_TIMEOUT:
+                       /* TODO: add suspend/resume support! */
+                       if (hcd->speed != HCD_USB3) {
+                               dev_dbg(dummy_dev(dum_hcd),
+                                        "USB_PORT_FEAT_U1/2_TIMEOUT req not "
+                                        "supported for USB 2.0 roothub\n");
+                               goto error;
+                       }
+                       break;
+               case USB_PORT_FEAT_SUSPEND:
+                       /* Applicable only for USB2.0 hub */
+                       if (hcd->speed == HCD_USB3) {
+                               dev_dbg(dummy_dev(dum_hcd),
+                                        "USB_PORT_FEAT_SUSPEND req not "
+                                        "supported for USB 3.0 roothub\n");
+                               goto error;
+                       }
+                       if (dum_hcd->active) {
+                               dum_hcd->port_status |= USB_PORT_STAT_SUSPEND;
+
+                               /* HNP would happen here; for now we
+                                * assume b_bus_req is always true.
+                                */
+                               set_link_state(dum_hcd);
+                               if (((1 << USB_DEVICE_B_HNP_ENABLE)
+                                               & dum_hcd->dum->devstatus) != 0)
+                                       dev_dbg(dummy_dev(dum_hcd),
+                                                       "no HNP yet!\n");
+                       }
+                       break;
+               case USB_PORT_FEAT_POWER:
+                       if (hcd->speed == HCD_USB3)
+                               dum_hcd->port_status |= USB_SS_PORT_STAT_POWER;
+                       else
+                               dum_hcd->port_status |= USB_PORT_STAT_POWER;
+                       set_link_state(dum_hcd);
+                       break;
+               case USB_PORT_FEAT_BH_PORT_RESET:
+                       /* Applicable only for USB3.0 hub */
+                       if (hcd->speed != HCD_USB3) {
+                               dev_dbg(dummy_dev(dum_hcd),
+                                        "USB_PORT_FEAT_BH_PORT_RESET req not "
+                                        "supported for USB 2.0 roothub\n");
+                               goto error;
+                       }
+                       /* FALLS THROUGH */
+               case USB_PORT_FEAT_RESET:
+                       /* if it's already enabled, disable */
+                       if (hcd->speed == HCD_USB3) {
+                               dum_hcd->port_status = 0;
+                               dum_hcd->port_status =
+                                       (USB_SS_PORT_STAT_POWER |
+                                        USB_PORT_STAT_CONNECTION |
+                                        USB_PORT_STAT_RESET);
+                       } else
+                               dum_hcd->port_status &= ~(USB_PORT_STAT_ENABLE
+                                       | USB_PORT_STAT_LOW_SPEED
+                                       | USB_PORT_STAT_HIGH_SPEED);
+                       /*
+                        * We want to reset device status. All but the
+                        * Self powered feature
+                        */
+                       dum_hcd->dum->devstatus &=
+                               (1 << USB_DEVICE_SELF_POWERED);
+                       /*
+                        * FIXME USB3.0: what is the correct reset signaling
+                        * interval? Is it still 50msec as for HS?
+                        */
+                       dum_hcd->re_timeout = jiffies + msecs_to_jiffies(50);
+                       /* FALLS THROUGH */
+               default:
+                       if (hcd->speed == HCD_USB3) {
+                               if ((dum_hcd->port_status &
+                                    USB_SS_PORT_STAT_POWER) != 0) {
+                                       dum_hcd->port_status |= (1 << wValue);
+                                       set_link_state(dum_hcd);
+                               }
+                       } else
+                               if ((dum_hcd->port_status &
+                                    USB_PORT_STAT_POWER) != 0) {
+                                       dum_hcd->port_status |= (1 << wValue);
+                                       set_link_state(dum_hcd);
+                               }
+               }
+               break;
+       case GetPortErrorCount:
+               if (hcd->speed != HCD_USB3) {
+                       dev_dbg(dummy_dev(dum_hcd),
+                                "GetPortErrorCount req not "
+                                "supported for USB 2.0 roothub\n");
+                       goto error;
+               }
+               /* We'll always return 0 since this is a dummy hub */
+               *(__le32 *) buf = cpu_to_le32(0);
+               break;
+       case SetHubDepth:
+               if (hcd->speed != HCD_USB3) {
+                       dev_dbg(dummy_dev(dum_hcd),
+                                "SetHubDepth req not supported for "
+                                "USB 2.0 roothub\n");
+                       goto error;
+               }
+               break;
+       default:
+               dev_dbg(dummy_dev(dum_hcd),
+                       "hub control req%04x v%04x i%04x l%d\n",
+                       typeReq, wValue, wIndex, wLength);
+error:
+               /* "protocol stall" on error */
+               retval = -EPIPE;
+       }
+       spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
+
+       if ((dum_hcd->port_status & PORT_C_MASK) != 0)
+               usb_hcd_poll_rh_status(hcd);
+       return retval;
+}
+
+static int dummy_bus_suspend(struct usb_hcd *hcd)
+{
+       struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
+
+       dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
+
+       spin_lock_irq(&dum_hcd->dum->lock);
+       dum_hcd->rh_state = DUMMY_RH_SUSPENDED;
+       set_link_state(dum_hcd);
+       hcd->state = HC_STATE_SUSPENDED;
+       spin_unlock_irq(&dum_hcd->dum->lock);
+       return 0;
+}
+
+static int dummy_bus_resume(struct usb_hcd *hcd)
+{
+       struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
+       int rc = 0;
+
+       dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
+
+       spin_lock_irq(&dum_hcd->dum->lock);
+       if (!HCD_HW_ACCESSIBLE(hcd)) {
+               rc = -ESHUTDOWN;
+       } else {
+               dum_hcd->rh_state = DUMMY_RH_RUNNING;
+               set_link_state(dum_hcd);
+               if (!list_empty(&dum_hcd->urbp_list))
+                       mod_timer(&dum_hcd->timer, jiffies);
+               hcd->state = HC_STATE_RUNNING;
+       }
+       spin_unlock_irq(&dum_hcd->dum->lock);
+       return rc;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static inline ssize_t show_urb(char *buf, size_t size, struct urb *urb)
+{
+       int ep = usb_pipeendpoint(urb->pipe);
+
+       return snprintf(buf, size,
+               "urb/%p %s ep%d%s%s len %d/%d\n",
+               urb,
+               ({ char *s;
+               switch (urb->dev->speed) {
+               case USB_SPEED_LOW:
+                       s = "ls";
+                       break;
+               case USB_SPEED_FULL:
+                       s = "fs";
+                       break;
+               case USB_SPEED_HIGH:
+                       s = "hs";
+                       break;
+               case USB_SPEED_SUPER:
+                       s = "ss";
+                       break;
+               default:
+                       s = "?";
+                       break;
+                } s; }),
+               ep, ep ? (usb_pipein(urb->pipe) ? "in" : "out") : "",
+               ({ char *s; \
+               switch (usb_pipetype(urb->pipe)) { \
+               case PIPE_CONTROL: \
+                       s = ""; \
+                       break; \
+               case PIPE_BULK: \
+                       s = "-bulk"; \
+                       break; \
+               case PIPE_INTERRUPT: \
+                       s = "-int"; \
+                       break; \
+               default: \
+                       s = "-iso"; \
+                       break; \
+               } s; }),
+               urb->actual_length, urb->transfer_buffer_length);
+}
+
+static ssize_t urbs_show(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct usb_hcd          *hcd = dev_get_drvdata(dev);
+       struct dummy_hcd        *dum_hcd = hcd_to_dummy_hcd(hcd);
+       struct urbp             *urbp;
+       size_t                  size = 0;
+       unsigned long           flags;
+
+       spin_lock_irqsave(&dum_hcd->dum->lock, flags);
+       list_for_each_entry(urbp, &dum_hcd->urbp_list, urbp_list) {
+               size_t          temp;
+
+               temp = show_urb(buf, PAGE_SIZE - size, urbp->urb);
+               buf += temp;
+               size += temp;
+       }
+       spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
+
+       return size;
+}
+static DEVICE_ATTR_RO(urbs);
+
+static int dummy_start_ss(struct dummy_hcd *dum_hcd)
+{
+       init_timer(&dum_hcd->timer);
+       dum_hcd->timer.function = dummy_timer;
+       dum_hcd->timer.data = (unsigned long)dum_hcd;
+       dum_hcd->rh_state = DUMMY_RH_RUNNING;
+       dum_hcd->stream_en_ep = 0;
+       INIT_LIST_HEAD(&dum_hcd->urbp_list);
+       dummy_hcd_to_hcd(dum_hcd)->power_budget = POWER_BUDGET;
+       dummy_hcd_to_hcd(dum_hcd)->state = HC_STATE_RUNNING;
+       dummy_hcd_to_hcd(dum_hcd)->uses_new_polling = 1;
+#ifdef CONFIG_USB_OTG
+       dummy_hcd_to_hcd(dum_hcd)->self.otg_port = 1;
+#endif
+       return 0;
+
+       /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
+       return device_create_file(dummy_dev(dum_hcd), &dev_attr_urbs);
+}
+
+static int dummy_start(struct usb_hcd *hcd)
+{
+       struct dummy_hcd        *dum_hcd = hcd_to_dummy_hcd(hcd);
+
+       /*
+        * MASTER side init ... we emulate a root hub that'll only ever
+        * talk to one device (the slave side).  Also appears in sysfs,
+        * just like more familiar pci-based HCDs.
+        */
+       if (!usb_hcd_is_primary_hcd(hcd))
+               return dummy_start_ss(dum_hcd);
+
+       spin_lock_init(&dum_hcd->dum->lock);
+       init_timer(&dum_hcd->timer);
+       dum_hcd->timer.function = dummy_timer;
+       dum_hcd->timer.data = (unsigned long)dum_hcd;
+       dum_hcd->rh_state = DUMMY_RH_RUNNING;
+
+       INIT_LIST_HEAD(&dum_hcd->urbp_list);
+
+       hcd->power_budget = POWER_BUDGET;
+       hcd->state = HC_STATE_RUNNING;
+       hcd->uses_new_polling = 1;
+
+#ifdef CONFIG_USB_OTG
+       hcd->self.otg_port = 1;
+#endif
+
+       /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
+       return device_create_file(dummy_dev(dum_hcd), &dev_attr_urbs);
+}
+
+static void dummy_stop(struct usb_hcd *hcd)
+{
+       struct dummy            *dum;
+
+       dum = hcd_to_dummy_hcd(hcd)->dum;
+       device_remove_file(dummy_dev(hcd_to_dummy_hcd(hcd)), &dev_attr_urbs);
+       usb_gadget_unregister_driver(dum->driver);
+       dev_info(dummy_dev(hcd_to_dummy_hcd(hcd)), "stopped\n");
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int dummy_h_get_frame(struct usb_hcd *hcd)
+{
+       return dummy_g_get_frame(NULL);
+}
+
+static int dummy_setup(struct usb_hcd *hcd)
+{
+       struct dummy *dum;
+
+       dum = *((void **)dev_get_platdata(hcd->self.controller));
+       hcd->self.sg_tablesize = ~0;
+       if (usb_hcd_is_primary_hcd(hcd)) {
+               dum->hs_hcd = hcd_to_dummy_hcd(hcd);
+               dum->hs_hcd->dum = dum;
+               /*
+                * Mark the first roothub as being USB 2.0.
+                * The USB 3.0 roothub will be registered later by
+                * dummy_hcd_probe()
+                */
+               hcd->speed = HCD_USB2;
+               hcd->self.root_hub->speed = USB_SPEED_HIGH;
+       } else {
+               dum->ss_hcd = hcd_to_dummy_hcd(hcd);
+               dum->ss_hcd->dum = dum;
+               hcd->speed = HCD_USB3;
+               hcd->self.root_hub->speed = USB_SPEED_SUPER;
+       }
+       return 0;
+}
+
+/* Change a group of bulk endpoints to support multiple stream IDs */
+static int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
+       struct usb_host_endpoint **eps, unsigned int num_eps,
+       unsigned int num_streams, gfp_t mem_flags)
+{
+       struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
+       unsigned long flags;
+       int max_stream;
+       int ret_streams = num_streams;
+       unsigned int index;
+       unsigned int i;
+
+       if (!num_eps)
+               return -EINVAL;
+
+       spin_lock_irqsave(&dum_hcd->dum->lock, flags);
+       for (i = 0; i < num_eps; i++) {
+               index = dummy_get_ep_idx(&eps[i]->desc);
+               if ((1 << index) & dum_hcd->stream_en_ep) {
+                       ret_streams = -EINVAL;
+                       goto out;
+               }
+               max_stream = usb_ss_max_streams(&eps[i]->ss_ep_comp);
+               if (!max_stream) {
+                       ret_streams = -EINVAL;
+                       goto out;
+               }
+               if (max_stream < ret_streams) {
+                       dev_dbg(dummy_dev(dum_hcd), "Ep 0x%x only supports %u "
+                                       "stream IDs.\n",
+                                       eps[i]->desc.bEndpointAddress,
+                                       max_stream);
+                       ret_streams = max_stream;
+               }
+       }
+
+       for (i = 0; i < num_eps; i++) {
+               index = dummy_get_ep_idx(&eps[i]->desc);
+               dum_hcd->stream_en_ep |= 1 << index;
+               set_max_streams_for_pipe(dum_hcd,
+                               usb_endpoint_num(&eps[i]->desc), ret_streams);
+       }
+out:
+       spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
+       return ret_streams;
+}
+
+/* Reverts a group of bulk endpoints back to not using stream IDs. */
+static int dummy_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
+       struct usb_host_endpoint **eps, unsigned int num_eps,
+       gfp_t mem_flags)
+{
+       struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
+       unsigned long flags;
+       int ret;
+       unsigned int index;
+       unsigned int i;
+
+       spin_lock_irqsave(&dum_hcd->dum->lock, flags);
+       for (i = 0; i < num_eps; i++) {
+               index = dummy_get_ep_idx(&eps[i]->desc);
+               if (!((1 << index) & dum_hcd->stream_en_ep)) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+       }
+
+       for (i = 0; i < num_eps; i++) {
+               index = dummy_get_ep_idx(&eps[i]->desc);
+               dum_hcd->stream_en_ep &= ~(1 << index);
+               set_max_streams_for_pipe(dum_hcd,
+                               usb_endpoint_num(&eps[i]->desc), 0);
+       }
+       ret = 0;
+out:
+       spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
+       return ret;
+}
+
+static struct hc_driver dummy_hcd = {
+       .description =          (char *) driver_name,
+       .product_desc =         "Dummy host controller",
+       .hcd_priv_size =        sizeof(struct dummy_hcd),
+
+       .flags =                HCD_USB3 | HCD_SHARED,
+
+       .reset =                dummy_setup,
+       .start =                dummy_start,
+       .stop =                 dummy_stop,
+
+       .urb_enqueue =          dummy_urb_enqueue,
+       .urb_dequeue =          dummy_urb_dequeue,
+
+       .get_frame_number =     dummy_h_get_frame,
+
+       .hub_status_data =      dummy_hub_status,
+       .hub_control =          dummy_hub_control,
+       .bus_suspend =          dummy_bus_suspend,
+       .bus_resume =           dummy_bus_resume,
+
+       .alloc_streams =        dummy_alloc_streams,
+       .free_streams =         dummy_free_streams,
+};
+
+static int dummy_hcd_probe(struct platform_device *pdev)
+{
+       struct dummy            *dum;
+       struct usb_hcd          *hs_hcd;
+       struct usb_hcd          *ss_hcd;
+       int                     retval;
+
+       dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
+       dum = *((void **)dev_get_platdata(&pdev->dev));
+
+       if (!mod_data.is_super_speed)
+               dummy_hcd.flags = HCD_USB2;
+       hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev));
+       if (!hs_hcd)
+               return -ENOMEM;
+       hs_hcd->has_tt = 1;
+
+       retval = usb_add_hcd(hs_hcd, 0, 0);
+       if (retval)
+               goto put_usb2_hcd;
+
+       if (mod_data.is_super_speed) {
+               ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev,
+                                       dev_name(&pdev->dev), hs_hcd);
+               if (!ss_hcd) {
+                       retval = -ENOMEM;
+                       goto dealloc_usb2_hcd;
+               }
+
+               retval = usb_add_hcd(ss_hcd, 0, 0);
+               if (retval)
+                       goto put_usb3_hcd;
+       }
+       return 0;
+
+put_usb3_hcd:
+       usb_put_hcd(ss_hcd);
+dealloc_usb2_hcd:
+       usb_remove_hcd(hs_hcd);
+put_usb2_hcd:
+       usb_put_hcd(hs_hcd);
+       dum->hs_hcd = dum->ss_hcd = NULL;
+       return retval;
+}
+
+static int dummy_hcd_remove(struct platform_device *pdev)
+{
+       struct dummy            *dum;
+
+       dum = hcd_to_dummy_hcd(platform_get_drvdata(pdev))->dum;
+
+       if (dum->ss_hcd) {
+               usb_remove_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
+               usb_put_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
+       }
+
+       usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
+       usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
+
+       dum->hs_hcd = NULL;
+       dum->ss_hcd = NULL;
+
+       return 0;
+}
+
+static int dummy_hcd_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct usb_hcd          *hcd;
+       struct dummy_hcd        *dum_hcd;
+       int                     rc = 0;
+
+       dev_dbg(&pdev->dev, "%s\n", __func__);
+
+       hcd = platform_get_drvdata(pdev);
+       dum_hcd = hcd_to_dummy_hcd(hcd);
+       if (dum_hcd->rh_state == DUMMY_RH_RUNNING) {
+               dev_warn(&pdev->dev, "Root hub isn't suspended!\n");
+               rc = -EBUSY;
+       } else
+               clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       return rc;
+}
+
+static int dummy_hcd_resume(struct platform_device *pdev)
+{
+       struct usb_hcd          *hcd;
+
+       dev_dbg(&pdev->dev, "%s\n", __func__);
+
+       hcd = platform_get_drvdata(pdev);
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       usb_hcd_poll_rh_status(hcd);
+       return 0;
+}
+
+static struct platform_driver dummy_hcd_driver = {
+       .probe          = dummy_hcd_probe,
+       .remove         = dummy_hcd_remove,
+       .suspend        = dummy_hcd_suspend,
+       .resume         = dummy_hcd_resume,
+       .driver         = {
+               .name   = (char *) driver_name,
+               .owner  = THIS_MODULE,
+       },
+};
+
+/*-------------------------------------------------------------------------*/
+#define MAX_NUM_UDC    2
+static struct platform_device *the_udc_pdev[MAX_NUM_UDC];
+static struct platform_device *the_hcd_pdev[MAX_NUM_UDC];
+
+static int __init init(void)
+{
+       int     retval = -ENOMEM;
+       int     i;
+       struct  dummy *dum[MAX_NUM_UDC];
+
+       if (usb_disabled())
+               return -ENODEV;
+
+       if (!mod_data.is_high_speed && mod_data.is_super_speed)
+               return -EINVAL;
+
+       if (mod_data.num < 1 || mod_data.num > MAX_NUM_UDC) {
+               pr_err("Number of emulated UDC must be in range of 1…%d\n",
+                               MAX_NUM_UDC);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < mod_data.num; i++) {
+               the_hcd_pdev[i] = platform_device_alloc(driver_name, i);
+               if (!the_hcd_pdev[i]) {
+                       i--;
+                       while (i >= 0)
+                               platform_device_put(the_hcd_pdev[i--]);
+                       return retval;
+               }
+       }
+       for (i = 0; i < mod_data.num; i++) {
+               the_udc_pdev[i] = platform_device_alloc(gadget_name, i);
+               if (!the_udc_pdev[i]) {
+                       i--;
+                       while (i >= 0)
+                               platform_device_put(the_udc_pdev[i--]);
+                       goto err_alloc_udc;
+               }
+       }
+       for (i = 0; i < mod_data.num; i++) {
+               dum[i] = kzalloc(sizeof(struct dummy), GFP_KERNEL);
+               if (!dum[i]) {
+                       retval = -ENOMEM;
+                       goto err_add_pdata;
+               }
+               retval = platform_device_add_data(the_hcd_pdev[i], &dum[i],
+                               sizeof(void *));
+               if (retval)
+                       goto err_add_pdata;
+               retval = platform_device_add_data(the_udc_pdev[i], &dum[i],
+                               sizeof(void *));
+               if (retval)
+                       goto err_add_pdata;
+       }
+
+       retval = platform_driver_register(&dummy_hcd_driver);
+       if (retval < 0)
+               goto err_add_pdata;
+       retval = platform_driver_register(&dummy_udc_driver);
+       if (retval < 0)
+               goto err_register_udc_driver;
+
+       for (i = 0; i < mod_data.num; i++) {
+               retval = platform_device_add(the_hcd_pdev[i]);
+               if (retval < 0) {
+                       i--;
+                       while (i >= 0)
+                               platform_device_del(the_hcd_pdev[i--]);
+                       goto err_add_hcd;
+               }
+       }
+       for (i = 0; i < mod_data.num; i++) {
+               if (!dum[i]->hs_hcd ||
+                               (!dum[i]->ss_hcd && mod_data.is_super_speed)) {
+                       /*
+                        * The hcd was added successfully but its probe
+                        * function failed for some reason.
+                        */
+                       retval = -EINVAL;
+                       goto err_add_udc;
+               }
+       }
+
+       for (i = 0; i < mod_data.num; i++) {
+               retval = platform_device_add(the_udc_pdev[i]);
+               if (retval < 0) {
+                       i--;
+                       while (i >= 0)
+                               platform_device_del(the_udc_pdev[i]);
+                       goto err_add_udc;
+               }
+       }
+
+       for (i = 0; i < mod_data.num; i++) {
+               if (!platform_get_drvdata(the_udc_pdev[i])) {
+                       /*
+                        * The udc was added successfully but its probe
+                        * function failed for some reason.
+                        */
+                       retval = -EINVAL;
+                       goto err_probe_udc;
+               }
+       }
+       return retval;
+
+err_probe_udc:
+       for (i = 0; i < mod_data.num; i++)
+               platform_device_del(the_udc_pdev[i]);
+err_add_udc:
+       for (i = 0; i < mod_data.num; i++)
+               platform_device_del(the_hcd_pdev[i]);
+err_add_hcd:
+       platform_driver_unregister(&dummy_udc_driver);
+err_register_udc_driver:
+       platform_driver_unregister(&dummy_hcd_driver);
+err_add_pdata:
+       for (i = 0; i < mod_data.num; i++)
+               kfree(dum[i]);
+       for (i = 0; i < mod_data.num; i++)
+               platform_device_put(the_udc_pdev[i]);
+err_alloc_udc:
+       for (i = 0; i < mod_data.num; i++)
+               platform_device_put(the_hcd_pdev[i]);
+       return retval;
+}
+module_init(init);
+
+static void __exit cleanup(void)
+{
+       int i;
+
+       for (i = 0; i < mod_data.num; i++) {
+               struct dummy *dum;
+
+               dum = *((void **)dev_get_platdata(&the_udc_pdev[i]->dev));
+
+               platform_device_unregister(the_udc_pdev[i]);
+               platform_device_unregister(the_hcd_pdev[i]);
+               kfree(dum);
+       }
+       platform_driver_unregister(&dummy_udc_driver);
+       platform_driver_unregister(&dummy_hcd_driver);
+}
+module_exit(cleanup);
diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c
new file mode 100644 (file)
index 0000000..e143d69
--- /dev/null
@@ -0,0 +1,1216 @@
+/*
+ * FOTG210 UDC Driver supports Bulk transfer so far
+ *
+ * Copyright (C) 2013 Faraday Technology Corporation
+ *
+ * Author : Yuan-Hsin Chen <yhchen@faraday-tech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#include "fotg210.h"
+
+#define        DRIVER_DESC     "FOTG210 USB Device Controller Driver"
+#define        DRIVER_VERSION  "30-April-2013"
+
+static const char udc_name[] = "fotg210_udc";
+static const char * const fotg210_ep_name[] = {
+       "ep0", "ep1", "ep2", "ep3", "ep4"};
+
+static void fotg210_disable_fifo_int(struct fotg210_ep *ep)
+{
+       u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR1);
+
+       if (ep->dir_in)
+               value |= DMISGR1_MF_IN_INT(ep->epnum - 1);
+       else
+               value |= DMISGR1_MF_OUTSPK_INT(ep->epnum - 1);
+       iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR1);
+}
+
+static void fotg210_enable_fifo_int(struct fotg210_ep *ep)
+{
+       u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR1);
+
+       if (ep->dir_in)
+               value &= ~DMISGR1_MF_IN_INT(ep->epnum - 1);
+       else
+               value &= ~DMISGR1_MF_OUTSPK_INT(ep->epnum - 1);
+       iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR1);
+}
+
+static void fotg210_set_cxdone(struct fotg210_udc *fotg210)
+{
+       u32 value = ioread32(fotg210->reg + FOTG210_DCFESR);
+
+       value |= DCFESR_CX_DONE;
+       iowrite32(value, fotg210->reg + FOTG210_DCFESR);
+}
+
+static void fotg210_done(struct fotg210_ep *ep, struct fotg210_request *req,
+                       int status)
+{
+       list_del_init(&req->queue);
+
+       /* don't modify queue heads during completion callback */
+       if (ep->fotg210->gadget.speed == USB_SPEED_UNKNOWN)
+               req->req.status = -ESHUTDOWN;
+       else
+               req->req.status = status;
+
+       spin_unlock(&ep->fotg210->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&ep->fotg210->lock);
+
+       if (ep->epnum) {
+               if (list_empty(&ep->queue))
+                       fotg210_disable_fifo_int(ep);
+       } else {
+               fotg210_set_cxdone(ep->fotg210);
+       }
+}
+
+static void fotg210_fifo_ep_mapping(struct fotg210_ep *ep, u32 epnum,
+                               u32 dir_in)
+{
+       struct fotg210_udc *fotg210 = ep->fotg210;
+       u32 val;
+
+       /* Driver should map an ep to a fifo and then map the fifo
+        * to the ep. What a brain-damaged design!
+        */
+
+       /* map a fifo to an ep */
+       val = ioread32(fotg210->reg + FOTG210_EPMAP);
+       val &= ~EPMAP_FIFONOMSK(epnum, dir_in);
+       val |= EPMAP_FIFONO(epnum, dir_in);
+       iowrite32(val, fotg210->reg + FOTG210_EPMAP);
+
+       /* map the ep to the fifo */
+       val = ioread32(fotg210->reg + FOTG210_FIFOMAP);
+       val &= ~FIFOMAP_EPNOMSK(epnum);
+       val |= FIFOMAP_EPNO(epnum);
+       iowrite32(val, fotg210->reg + FOTG210_FIFOMAP);
+
+       /* enable fifo */
+       val = ioread32(fotg210->reg + FOTG210_FIFOCF);
+       val |= FIFOCF_FIFO_EN(epnum - 1);
+       iowrite32(val, fotg210->reg + FOTG210_FIFOCF);
+}
+
+static void fotg210_set_fifo_dir(struct fotg210_ep *ep, u32 epnum, u32 dir_in)
+{
+       struct fotg210_udc *fotg210 = ep->fotg210;
+       u32 val;
+
+       val = ioread32(fotg210->reg + FOTG210_FIFOMAP);
+       val |= (dir_in ? FIFOMAP_DIRIN(epnum - 1) : FIFOMAP_DIROUT(epnum - 1));
+       iowrite32(val, fotg210->reg + FOTG210_FIFOMAP);
+}
+
+static void fotg210_set_tfrtype(struct fotg210_ep *ep, u32 epnum, u32 type)
+{
+       struct fotg210_udc *fotg210 = ep->fotg210;
+       u32 val;
+
+       val = ioread32(fotg210->reg + FOTG210_FIFOCF);
+       val |= FIFOCF_TYPE(type, epnum - 1);
+       iowrite32(val, fotg210->reg + FOTG210_FIFOCF);
+}
+
+static void fotg210_set_mps(struct fotg210_ep *ep, u32 epnum, u32 mps,
+                               u32 dir_in)
+{
+       struct fotg210_udc *fotg210 = ep->fotg210;
+       u32 val;
+       u32 offset = dir_in ? FOTG210_INEPMPSR(epnum) :
+                               FOTG210_OUTEPMPSR(epnum);
+
+       val = ioread32(fotg210->reg + offset);
+       val |= INOUTEPMPSR_MPS(mps);
+       iowrite32(val, fotg210->reg + offset);
+}
+
+static int fotg210_config_ep(struct fotg210_ep *ep,
+                    const struct usb_endpoint_descriptor *desc)
+{
+       struct fotg210_udc *fotg210 = ep->fotg210;
+
+       fotg210_set_fifo_dir(ep, ep->epnum, ep->dir_in);
+       fotg210_set_tfrtype(ep, ep->epnum, ep->type);
+       fotg210_set_mps(ep, ep->epnum, ep->ep.maxpacket, ep->dir_in);
+       fotg210_fifo_ep_mapping(ep, ep->epnum, ep->dir_in);
+
+       fotg210->ep[ep->epnum] = ep;
+
+       return 0;
+}
+
+static int fotg210_ep_enable(struct usb_ep *_ep,
+                         const struct usb_endpoint_descriptor *desc)
+{
+       struct fotg210_ep *ep;
+
+       ep = container_of(_ep, struct fotg210_ep, ep);
+
+       ep->desc = desc;
+       ep->epnum = usb_endpoint_num(desc);
+       ep->type = usb_endpoint_type(desc);
+       ep->dir_in = usb_endpoint_dir_in(desc);
+       ep->ep.maxpacket = usb_endpoint_maxp(desc);
+
+       return fotg210_config_ep(ep, desc);
+}
+
+static void fotg210_reset_tseq(struct fotg210_udc *fotg210, u8 epnum)
+{
+       struct fotg210_ep *ep = fotg210->ep[epnum];
+       u32 value;
+       void __iomem *reg;
+
+       reg = (ep->dir_in) ?
+               fotg210->reg + FOTG210_INEPMPSR(epnum) :
+               fotg210->reg + FOTG210_OUTEPMPSR(epnum);
+
+       /* Note: Driver needs to set and clear INOUTEPMPSR_RESET_TSEQ
+        *       bit. Controller wouldn't clear this bit. WTF!!!
+        */
+
+       value = ioread32(reg);
+       value |= INOUTEPMPSR_RESET_TSEQ;
+       iowrite32(value, reg);
+
+       value = ioread32(reg);
+       value &= ~INOUTEPMPSR_RESET_TSEQ;
+       iowrite32(value, reg);
+}
+
+static int fotg210_ep_release(struct fotg210_ep *ep)
+{
+       if (!ep->epnum)
+               return 0;
+       ep->epnum = 0;
+       ep->stall = 0;
+       ep->wedged = 0;
+
+       fotg210_reset_tseq(ep->fotg210, ep->epnum);
+
+       return 0;
+}
+
+static int fotg210_ep_disable(struct usb_ep *_ep)
+{
+       struct fotg210_ep *ep;
+       struct fotg210_request *req;
+       unsigned long flags;
+
+       BUG_ON(!_ep);
+
+       ep = container_of(_ep, struct fotg210_ep, ep);
+
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next,
+                       struct fotg210_request, queue);
+               spin_lock_irqsave(&ep->fotg210->lock, flags);
+               fotg210_done(ep, req, -ECONNRESET);
+               spin_unlock_irqrestore(&ep->fotg210->lock, flags);
+       }
+
+       return fotg210_ep_release(ep);
+}
+
+static struct usb_request *fotg210_ep_alloc_request(struct usb_ep *_ep,
+                                               gfp_t gfp_flags)
+{
+       struct fotg210_request *req;
+
+       req = kzalloc(sizeof(struct fotg210_request), gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void fotg210_ep_free_request(struct usb_ep *_ep,
+                                       struct usb_request *_req)
+{
+       struct fotg210_request *req;
+
+       req = container_of(_req, struct fotg210_request, req);
+       kfree(req);
+}
+
+static void fotg210_enable_dma(struct fotg210_ep *ep,
+                             dma_addr_t d, u32 len)
+{
+       u32 value;
+       struct fotg210_udc *fotg210 = ep->fotg210;
+
+       /* set transfer length and direction */
+       value = ioread32(fotg210->reg + FOTG210_DMACPSR1);
+       value &= ~(DMACPSR1_DMA_LEN(0xFFFF) | DMACPSR1_DMA_TYPE(1));
+       value |= DMACPSR1_DMA_LEN(len) | DMACPSR1_DMA_TYPE(ep->dir_in);
+       iowrite32(value, fotg210->reg + FOTG210_DMACPSR1);
+
+       /* set device DMA target FIFO number */
+       value = ioread32(fotg210->reg + FOTG210_DMATFNR);
+       if (ep->epnum)
+               value |= DMATFNR_ACC_FN(ep->epnum - 1);
+       else
+               value |= DMATFNR_ACC_CXF;
+       iowrite32(value, fotg210->reg + FOTG210_DMATFNR);
+
+       /* set DMA memory address */
+       iowrite32(d, fotg210->reg + FOTG210_DMACPSR2);
+
+       /* enable MDMA_EROR and MDMA_CMPLT interrupt */
+       value = ioread32(fotg210->reg + FOTG210_DMISGR2);
+       value &= ~(DMISGR2_MDMA_CMPLT | DMISGR2_MDMA_ERROR);
+       iowrite32(value, fotg210->reg + FOTG210_DMISGR2);
+
+       /* start DMA */
+       value = ioread32(fotg210->reg + FOTG210_DMACPSR1);
+       value |= DMACPSR1_DMA_START;
+       iowrite32(value, fotg210->reg + FOTG210_DMACPSR1);
+}
+
+static void fotg210_disable_dma(struct fotg210_ep *ep)
+{
+       iowrite32(DMATFNR_DISDMA, ep->fotg210->reg + FOTG210_DMATFNR);
+}
+
+static void fotg210_wait_dma_done(struct fotg210_ep *ep)
+{
+       u32 value;
+
+       do {
+               value = ioread32(ep->fotg210->reg + FOTG210_DISGR2);
+               if ((value & DISGR2_USBRST_INT) ||
+                   (value & DISGR2_DMA_ERROR))
+                       goto dma_reset;
+       } while (!(value & DISGR2_DMA_CMPLT));
+
+       value &= ~DISGR2_DMA_CMPLT;
+       iowrite32(value, ep->fotg210->reg + FOTG210_DISGR2);
+       return;
+
+dma_reset:
+       value = ioread32(ep->fotg210->reg + FOTG210_DMACPSR1);
+       value |= DMACPSR1_DMA_ABORT;
+       iowrite32(value, ep->fotg210->reg + FOTG210_DMACPSR1);
+
+       /* reset fifo */
+       if (ep->epnum) {
+               value = ioread32(ep->fotg210->reg +
+                               FOTG210_FIBCR(ep->epnum - 1));
+               value |= FIBCR_FFRST;
+               iowrite32(value, ep->fotg210->reg +
+                               FOTG210_FIBCR(ep->epnum - 1));
+       } else {
+               value = ioread32(ep->fotg210->reg + FOTG210_DCFESR);
+               value |= DCFESR_CX_CLR;
+               iowrite32(value, ep->fotg210->reg + FOTG210_DCFESR);
+       }
+}
+
+static void fotg210_start_dma(struct fotg210_ep *ep,
+                       struct fotg210_request *req)
+{
+       dma_addr_t d;
+       u8 *buffer;
+       u32 length;
+
+       if (ep->epnum) {
+               if (ep->dir_in) {
+                       buffer = req->req.buf;
+                       length = req->req.length;
+               } else {
+                       buffer = req->req.buf + req->req.actual;
+                       length = ioread32(ep->fotg210->reg +
+                                       FOTG210_FIBCR(ep->epnum - 1));
+                       length &= FIBCR_BCFX;
+               }
+       } else {
+               buffer = req->req.buf + req->req.actual;
+               if (req->req.length - req->req.actual > ep->ep.maxpacket)
+                       length = ep->ep.maxpacket;
+               else
+                       length = req->req.length;
+       }
+
+       d = dma_map_single(NULL, buffer, length,
+                       ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+
+       if (dma_mapping_error(NULL, d)) {
+               pr_err("dma_mapping_error\n");
+               return;
+       }
+
+       dma_sync_single_for_device(NULL, d, length,
+                                  ep->dir_in ? DMA_TO_DEVICE :
+                                       DMA_FROM_DEVICE);
+
+       fotg210_enable_dma(ep, d, length);
+
+       /* check if dma is done */
+       fotg210_wait_dma_done(ep);
+
+       fotg210_disable_dma(ep);
+
+       /* update actual transfer length */
+       req->req.actual += length;
+
+       dma_unmap_single(NULL, d, length, DMA_TO_DEVICE);
+}
+
+static void fotg210_ep0_queue(struct fotg210_ep *ep,
+                               struct fotg210_request *req)
+{
+       if (!req->req.length) {
+               fotg210_done(ep, req, 0);
+               return;
+       }
+       if (ep->dir_in) { /* if IN */
+               if (req->req.length) {
+                       fotg210_start_dma(ep, req);
+               } else {
+                       pr_err("%s : req->req.length = 0x%x\n",
+                              __func__, req->req.length);
+               }
+               if ((req->req.length == req->req.actual) ||
+                   (req->req.actual < ep->ep.maxpacket))
+                       fotg210_done(ep, req, 0);
+       } else { /* OUT */
+               if (!req->req.length) {
+                       fotg210_done(ep, req, 0);
+               } else {
+                       u32 value = ioread32(ep->fotg210->reg +
+                                               FOTG210_DMISGR0);
+
+                       value &= ~DMISGR0_MCX_OUT_INT;
+                       iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0);
+               }
+       }
+}
+
+static int fotg210_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
+                               gfp_t gfp_flags)
+{
+       struct fotg210_ep *ep;
+       struct fotg210_request *req;
+       unsigned long flags;
+       int request = 0;
+
+       ep = container_of(_ep, struct fotg210_ep, ep);
+       req = container_of(_req, struct fotg210_request, req);
+
+       if (ep->fotg210->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       spin_lock_irqsave(&ep->fotg210->lock, flags);
+
+       if (list_empty(&ep->queue))
+               request = 1;
+
+       list_add_tail(&req->queue, &ep->queue);
+
+       req->req.actual = 0;
+       req->req.status = -EINPROGRESS;
+
+       if (!ep->epnum) /* ep0 */
+               fotg210_ep0_queue(ep, req);
+       else if (request && !ep->stall)
+               fotg210_enable_fifo_int(ep);
+
+       spin_unlock_irqrestore(&ep->fotg210->lock, flags);
+
+       return 0;
+}
+
+static int fotg210_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct fotg210_ep *ep;
+       struct fotg210_request *req;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct fotg210_ep, ep);
+       req = container_of(_req, struct fotg210_request, req);
+
+       spin_lock_irqsave(&ep->fotg210->lock, flags);
+       if (!list_empty(&ep->queue))
+               fotg210_done(ep, req, -ECONNRESET);
+       spin_unlock_irqrestore(&ep->fotg210->lock, flags);
+
+       return 0;
+}
+
+static void fotg210_set_epnstall(struct fotg210_ep *ep)
+{
+       struct fotg210_udc *fotg210 = ep->fotg210;
+       u32 value;
+       void __iomem *reg;
+
+       /* check if IN FIFO is empty before stall */
+       if (ep->dir_in) {
+               do {
+                       value = ioread32(fotg210->reg + FOTG210_DCFESR);
+               } while (!(value & DCFESR_FIFO_EMPTY(ep->epnum - 1)));
+       }
+
+       reg = (ep->dir_in) ?
+               fotg210->reg + FOTG210_INEPMPSR(ep->epnum) :
+               fotg210->reg + FOTG210_OUTEPMPSR(ep->epnum);
+       value = ioread32(reg);
+       value |= INOUTEPMPSR_STL_EP;
+       iowrite32(value, reg);
+}
+
+static void fotg210_clear_epnstall(struct fotg210_ep *ep)
+{
+       struct fotg210_udc *fotg210 = ep->fotg210;
+       u32 value;
+       void __iomem *reg;
+
+       reg = (ep->dir_in) ?
+               fotg210->reg + FOTG210_INEPMPSR(ep->epnum) :
+               fotg210->reg + FOTG210_OUTEPMPSR(ep->epnum);
+       value = ioread32(reg);
+       value &= ~INOUTEPMPSR_STL_EP;
+       iowrite32(value, reg);
+}
+
+static int fotg210_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedge)
+{
+       struct fotg210_ep *ep;
+       struct fotg210_udc *fotg210;
+       unsigned long flags;
+       int ret = 0;
+
+       ep = container_of(_ep, struct fotg210_ep, ep);
+
+       fotg210 = ep->fotg210;
+
+       spin_lock_irqsave(&ep->fotg210->lock, flags);
+
+       if (value) {
+               fotg210_set_epnstall(ep);
+               ep->stall = 1;
+               if (wedge)
+                       ep->wedged = 1;
+       } else {
+               fotg210_reset_tseq(fotg210, ep->epnum);
+               fotg210_clear_epnstall(ep);
+               ep->stall = 0;
+               ep->wedged = 0;
+               if (!list_empty(&ep->queue))
+                       fotg210_enable_fifo_int(ep);
+       }
+
+       spin_unlock_irqrestore(&ep->fotg210->lock, flags);
+       return ret;
+}
+
+static int fotg210_ep_set_halt(struct usb_ep *_ep, int value)
+{
+       return fotg210_set_halt_and_wedge(_ep, value, 0);
+}
+
+static int fotg210_ep_set_wedge(struct usb_ep *_ep)
+{
+       return fotg210_set_halt_and_wedge(_ep, 1, 1);
+}
+
+static void fotg210_ep_fifo_flush(struct usb_ep *_ep)
+{
+}
+
+static struct usb_ep_ops fotg210_ep_ops = {
+       .enable         = fotg210_ep_enable,
+       .disable        = fotg210_ep_disable,
+
+       .alloc_request  = fotg210_ep_alloc_request,
+       .free_request   = fotg210_ep_free_request,
+
+       .queue          = fotg210_ep_queue,
+       .dequeue        = fotg210_ep_dequeue,
+
+       .set_halt       = fotg210_ep_set_halt,
+       .fifo_flush     = fotg210_ep_fifo_flush,
+       .set_wedge      = fotg210_ep_set_wedge,
+};
+
+static void fotg210_clear_tx0byte(struct fotg210_udc *fotg210)
+{
+       u32 value = ioread32(fotg210->reg + FOTG210_TX0BYTE);
+
+       value &= ~(TX0BYTE_EP1 | TX0BYTE_EP2 | TX0BYTE_EP3
+                  | TX0BYTE_EP4);
+       iowrite32(value, fotg210->reg + FOTG210_TX0BYTE);
+}
+
+static void fotg210_clear_rx0byte(struct fotg210_udc *fotg210)
+{
+       u32 value = ioread32(fotg210->reg + FOTG210_RX0BYTE);
+
+       value &= ~(RX0BYTE_EP1 | RX0BYTE_EP2 | RX0BYTE_EP3
+                  | RX0BYTE_EP4);
+       iowrite32(value, fotg210->reg + FOTG210_RX0BYTE);
+}
+
+/* read 8-byte setup packet only */
+static void fotg210_rdsetupp(struct fotg210_udc *fotg210,
+                  u8 *buffer)
+{
+       int i = 0;
+       u8 *tmp = buffer;
+       u32 data;
+       u32 length = 8;
+
+       iowrite32(DMATFNR_ACC_CXF, fotg210->reg + FOTG210_DMATFNR);
+
+       for (i = (length >> 2); i > 0; i--) {
+               data = ioread32(fotg210->reg + FOTG210_CXPORT);
+               *tmp = data & 0xFF;
+               *(tmp + 1) = (data >> 8) & 0xFF;
+               *(tmp + 2) = (data >> 16) & 0xFF;
+               *(tmp + 3) = (data >> 24) & 0xFF;
+               tmp = tmp + 4;
+       }
+
+       switch (length % 4) {
+       case 1:
+               data = ioread32(fotg210->reg + FOTG210_CXPORT);
+               *tmp = data & 0xFF;
+               break;
+       case 2:
+               data = ioread32(fotg210->reg + FOTG210_CXPORT);
+               *tmp = data & 0xFF;
+               *(tmp + 1) = (data >> 8) & 0xFF;
+               break;
+       case 3:
+               data = ioread32(fotg210->reg + FOTG210_CXPORT);
+               *tmp = data & 0xFF;
+               *(tmp + 1) = (data >> 8) & 0xFF;
+               *(tmp + 2) = (data >> 16) & 0xFF;
+               break;
+       default:
+               break;
+       }
+
+       iowrite32(DMATFNR_DISDMA, fotg210->reg + FOTG210_DMATFNR);
+}
+
+static void fotg210_set_configuration(struct fotg210_udc *fotg210)
+{
+       u32 value = ioread32(fotg210->reg + FOTG210_DAR);
+
+       value |= DAR_AFT_CONF;
+       iowrite32(value, fotg210->reg + FOTG210_DAR);
+}
+
+static void fotg210_set_dev_addr(struct fotg210_udc *fotg210, u32 addr)
+{
+       u32 value = ioread32(fotg210->reg + FOTG210_DAR);
+
+       value |= (addr & 0x7F);
+       iowrite32(value, fotg210->reg + FOTG210_DAR);
+}
+
+static void fotg210_set_cxstall(struct fotg210_udc *fotg210)
+{
+       u32 value = ioread32(fotg210->reg + FOTG210_DCFESR);
+
+       value |= DCFESR_CX_STL;
+       iowrite32(value, fotg210->reg + FOTG210_DCFESR);
+}
+
+static void fotg210_request_error(struct fotg210_udc *fotg210)
+{
+       fotg210_set_cxstall(fotg210);
+       pr_err("request error!!\n");
+}
+
+static void fotg210_set_address(struct fotg210_udc *fotg210,
+                               struct usb_ctrlrequest *ctrl)
+{
+       if (ctrl->wValue >= 0x0100) {
+               fotg210_request_error(fotg210);
+       } else {
+               fotg210_set_dev_addr(fotg210, ctrl->wValue);
+               fotg210_set_cxdone(fotg210);
+       }
+}
+
+static void fotg210_set_feature(struct fotg210_udc *fotg210,
+                               struct usb_ctrlrequest *ctrl)
+{
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               fotg210_set_cxdone(fotg210);
+               break;
+       case USB_RECIP_INTERFACE:
+               fotg210_set_cxdone(fotg210);
+               break;
+       case USB_RECIP_ENDPOINT: {
+               u8 epnum;
+               epnum = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
+               if (epnum)
+                       fotg210_set_epnstall(fotg210->ep[epnum]);
+               else
+                       fotg210_set_cxstall(fotg210);
+               fotg210_set_cxdone(fotg210);
+               }
+               break;
+       default:
+               fotg210_request_error(fotg210);
+               break;
+       }
+}
+
+static void fotg210_clear_feature(struct fotg210_udc *fotg210,
+                               struct usb_ctrlrequest *ctrl)
+{
+       struct fotg210_ep *ep =
+               fotg210->ep[ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK];
+
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               fotg210_set_cxdone(fotg210);
+               break;
+       case USB_RECIP_INTERFACE:
+               fotg210_set_cxdone(fotg210);
+               break;
+       case USB_RECIP_ENDPOINT:
+               if (ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK) {
+                       if (ep->wedged) {
+                               fotg210_set_cxdone(fotg210);
+                               break;
+                       }
+                       if (ep->stall)
+                               fotg210_set_halt_and_wedge(&ep->ep, 0, 0);
+               }
+               fotg210_set_cxdone(fotg210);
+               break;
+       default:
+               fotg210_request_error(fotg210);
+               break;
+       }
+}
+
+static int fotg210_is_epnstall(struct fotg210_ep *ep)
+{
+       struct fotg210_udc *fotg210 = ep->fotg210;
+       u32 value;
+       void __iomem *reg;
+
+       reg = (ep->dir_in) ?
+               fotg210->reg + FOTG210_INEPMPSR(ep->epnum) :
+               fotg210->reg + FOTG210_OUTEPMPSR(ep->epnum);
+       value = ioread32(reg);
+       return value & INOUTEPMPSR_STL_EP ? 1 : 0;
+}
+
+static void fotg210_get_status(struct fotg210_udc *fotg210,
+                               struct usb_ctrlrequest *ctrl)
+{
+       u8 epnum;
+
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               fotg210->ep0_data = 1 << USB_DEVICE_SELF_POWERED;
+               break;
+       case USB_RECIP_INTERFACE:
+               fotg210->ep0_data = 0;
+               break;
+       case USB_RECIP_ENDPOINT:
+               epnum = ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK;
+               if (epnum)
+                       fotg210->ep0_data =
+                               fotg210_is_epnstall(fotg210->ep[epnum])
+                               << USB_ENDPOINT_HALT;
+               else
+                       fotg210_request_error(fotg210);
+               break;
+
+       default:
+               fotg210_request_error(fotg210);
+               return;         /* exit */
+       }
+
+       fotg210->ep0_req->buf = &fotg210->ep0_data;
+       fotg210->ep0_req->length = 2;
+
+       spin_unlock(&fotg210->lock);
+       fotg210_ep_queue(fotg210->gadget.ep0, fotg210->ep0_req, GFP_KERNEL);
+       spin_lock(&fotg210->lock);
+}
+
+static int fotg210_setup_packet(struct fotg210_udc *fotg210,
+                               struct usb_ctrlrequest *ctrl)
+{
+       u8 *p = (u8 *)ctrl;
+       u8 ret = 0;
+
+       fotg210_rdsetupp(fotg210, p);
+
+       fotg210->ep[0]->dir_in = ctrl->bRequestType & USB_DIR_IN;
+
+       if (fotg210->gadget.speed == USB_SPEED_UNKNOWN) {
+               u32 value = ioread32(fotg210->reg + FOTG210_DMCR);
+               fotg210->gadget.speed = value & DMCR_HS_EN ?
+                               USB_SPEED_HIGH : USB_SPEED_FULL;
+       }
+
+       /* check request */
+       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+               switch (ctrl->bRequest) {
+               case USB_REQ_GET_STATUS:
+                       fotg210_get_status(fotg210, ctrl);
+                       break;
+               case USB_REQ_CLEAR_FEATURE:
+                       fotg210_clear_feature(fotg210, ctrl);
+                       break;
+               case USB_REQ_SET_FEATURE:
+                       fotg210_set_feature(fotg210, ctrl);
+                       break;
+               case USB_REQ_SET_ADDRESS:
+                       fotg210_set_address(fotg210, ctrl);
+                       break;
+               case USB_REQ_SET_CONFIGURATION:
+                       fotg210_set_configuration(fotg210);
+                       ret = 1;
+                       break;
+               default:
+                       ret = 1;
+                       break;
+               }
+       } else {
+               ret = 1;
+       }
+
+       return ret;
+}
+
+static void fotg210_ep0out(struct fotg210_udc *fotg210)
+{
+       struct fotg210_ep *ep = fotg210->ep[0];
+
+       if (!list_empty(&ep->queue) && !ep->dir_in) {
+               struct fotg210_request *req;
+
+               req = list_first_entry(&ep->queue,
+                       struct fotg210_request, queue);
+
+               if (req->req.length)
+                       fotg210_start_dma(ep, req);
+
+               if ((req->req.length - req->req.actual) < ep->ep.maxpacket)
+                       fotg210_done(ep, req, 0);
+       } else {
+               pr_err("%s : empty queue\n", __func__);
+       }
+}
+
+static void fotg210_ep0in(struct fotg210_udc *fotg210)
+{
+       struct fotg210_ep *ep = fotg210->ep[0];
+
+       if ((!list_empty(&ep->queue)) && (ep->dir_in)) {
+               struct fotg210_request *req;
+
+               req = list_entry(ep->queue.next,
+                               struct fotg210_request, queue);
+
+               if (req->req.length)
+                       fotg210_start_dma(ep, req);
+
+               if ((req->req.length - req->req.actual) < ep->ep.maxpacket)
+                       fotg210_done(ep, req, 0);
+       } else {
+               fotg210_set_cxdone(fotg210);
+       }
+}
+
+static void fotg210_clear_comabt_int(struct fotg210_udc *fotg210)
+{
+       u32 value = ioread32(fotg210->reg + FOTG210_DISGR0);
+
+       value &= ~DISGR0_CX_COMABT_INT;
+       iowrite32(value, fotg210->reg + FOTG210_DISGR0);
+}
+
+static void fotg210_in_fifo_handler(struct fotg210_ep *ep)
+{
+       struct fotg210_request *req = list_entry(ep->queue.next,
+                                       struct fotg210_request, queue);
+
+       if (req->req.length)
+               fotg210_start_dma(ep, req);
+       fotg210_done(ep, req, 0);
+}
+
+static void fotg210_out_fifo_handler(struct fotg210_ep *ep)
+{
+       struct fotg210_request *req = list_entry(ep->queue.next,
+                                                struct fotg210_request, queue);
+
+       fotg210_start_dma(ep, req);
+
+       /* finish out transfer */
+       if (req->req.length == req->req.actual ||
+           req->req.actual < ep->ep.maxpacket)
+               fotg210_done(ep, req, 0);
+}
+
+static irqreturn_t fotg210_irq(int irq, void *_fotg210)
+{
+       struct fotg210_udc *fotg210 = _fotg210;
+       u32 int_grp = ioread32(fotg210->reg + FOTG210_DIGR);
+       u32 int_msk = ioread32(fotg210->reg + FOTG210_DMIGR);
+
+       int_grp &= ~int_msk;
+
+       spin_lock(&fotg210->lock);
+
+       if (int_grp & DIGR_INT_G2) {
+               void __iomem *reg = fotg210->reg + FOTG210_DISGR2;
+               u32 int_grp2 = ioread32(reg);
+               u32 int_msk2 = ioread32(fotg210->reg + FOTG210_DMISGR2);
+               u32 value;
+
+               int_grp2 &= ~int_msk2;
+
+               if (int_grp2 & DISGR2_USBRST_INT) {
+                       value = ioread32(reg);
+                       value &= ~DISGR2_USBRST_INT;
+                       iowrite32(value, reg);
+                       pr_info("fotg210 udc reset\n");
+               }
+               if (int_grp2 & DISGR2_SUSP_INT) {
+                       value = ioread32(reg);
+                       value &= ~DISGR2_SUSP_INT;
+                       iowrite32(value, reg);
+                       pr_info("fotg210 udc suspend\n");
+               }
+               if (int_grp2 & DISGR2_RESM_INT) {
+                       value = ioread32(reg);
+                       value &= ~DISGR2_RESM_INT;
+                       iowrite32(value, reg);
+                       pr_info("fotg210 udc resume\n");
+               }
+               if (int_grp2 & DISGR2_ISO_SEQ_ERR_INT) {
+                       value = ioread32(reg);
+                       value &= ~DISGR2_ISO_SEQ_ERR_INT;
+                       iowrite32(value, reg);
+                       pr_info("fotg210 iso sequence error\n");
+               }
+               if (int_grp2 & DISGR2_ISO_SEQ_ABORT_INT) {
+                       value = ioread32(reg);
+                       value &= ~DISGR2_ISO_SEQ_ABORT_INT;
+                       iowrite32(value, reg);
+                       pr_info("fotg210 iso sequence abort\n");
+               }
+               if (int_grp2 & DISGR2_TX0BYTE_INT) {
+                       fotg210_clear_tx0byte(fotg210);
+                       value = ioread32(reg);
+                       value &= ~DISGR2_TX0BYTE_INT;
+                       iowrite32(value, reg);
+                       pr_info("fotg210 transferred 0 byte\n");
+               }
+               if (int_grp2 & DISGR2_RX0BYTE_INT) {
+                       fotg210_clear_rx0byte(fotg210);
+                       value = ioread32(reg);
+                       value &= ~DISGR2_RX0BYTE_INT;
+                       iowrite32(value, reg);
+                       pr_info("fotg210 received 0 byte\n");
+               }
+               if (int_grp2 & DISGR2_DMA_ERROR) {
+                       value = ioread32(reg);
+                       value &= ~DISGR2_DMA_ERROR;
+                       iowrite32(value, reg);
+               }
+       }
+
+       if (int_grp & DIGR_INT_G0) {
+               void __iomem *reg = fotg210->reg + FOTG210_DISGR0;
+               u32 int_grp0 = ioread32(reg);
+               u32 int_msk0 = ioread32(fotg210->reg + FOTG210_DMISGR0);
+               struct usb_ctrlrequest ctrl;
+
+               int_grp0 &= ~int_msk0;
+
+               /* the highest priority in this source register */
+               if (int_grp0 & DISGR0_CX_COMABT_INT) {
+                       fotg210_clear_comabt_int(fotg210);
+                       pr_info("fotg210 CX command abort\n");
+               }
+
+               if (int_grp0 & DISGR0_CX_SETUP_INT) {
+                       if (fotg210_setup_packet(fotg210, &ctrl)) {
+                               spin_unlock(&fotg210->lock);
+                               if (fotg210->driver->setup(&fotg210->gadget,
+                                                          &ctrl) < 0)
+                                       fotg210_set_cxstall(fotg210);
+                               spin_lock(&fotg210->lock);
+                       }
+               }
+               if (int_grp0 & DISGR0_CX_COMEND_INT)
+                       pr_info("fotg210 cmd end\n");
+
+               if (int_grp0 & DISGR0_CX_IN_INT)
+                       fotg210_ep0in(fotg210);
+
+               if (int_grp0 & DISGR0_CX_OUT_INT)
+                       fotg210_ep0out(fotg210);
+
+               if (int_grp0 & DISGR0_CX_COMFAIL_INT) {
+                       fotg210_set_cxstall(fotg210);
+                       pr_info("fotg210 ep0 fail\n");
+               }
+       }
+
+       if (int_grp & DIGR_INT_G1) {
+               void __iomem *reg = fotg210->reg + FOTG210_DISGR1;
+               u32 int_grp1 = ioread32(reg);
+               u32 int_msk1 = ioread32(fotg210->reg + FOTG210_DMISGR1);
+               int fifo;
+
+               int_grp1 &= ~int_msk1;
+
+               for (fifo = 0; fifo < FOTG210_MAX_FIFO_NUM; fifo++) {
+                       if (int_grp1 & DISGR1_IN_INT(fifo))
+                               fotg210_in_fifo_handler(fotg210->ep[fifo + 1]);
+
+                       if ((int_grp1 & DISGR1_OUT_INT(fifo)) ||
+                           (int_grp1 & DISGR1_SPK_INT(fifo)))
+                               fotg210_out_fifo_handler(fotg210->ep[fifo + 1]);
+               }
+       }
+
+       spin_unlock(&fotg210->lock);
+
+       return IRQ_HANDLED;
+}
+
+static void fotg210_disable_unplug(struct fotg210_udc *fotg210)
+{
+       u32 reg = ioread32(fotg210->reg + FOTG210_PHYTMSR);
+
+       reg &= ~PHYTMSR_UNPLUG;
+       iowrite32(reg, fotg210->reg + FOTG210_PHYTMSR);
+}
+
+static int fotg210_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct fotg210_udc *fotg210 = gadget_to_fotg210(g);
+       u32 value;
+
+       /* hook up the driver */
+       driver->driver.bus = NULL;
+       fotg210->driver = driver;
+
+       /* enable device global interrupt */
+       value = ioread32(fotg210->reg + FOTG210_DMCR);
+       value |= DMCR_GLINT_EN;
+       iowrite32(value, fotg210->reg + FOTG210_DMCR);
+
+       return 0;
+}
+
+static void fotg210_init(struct fotg210_udc *fotg210)
+{
+       u32 value;
+
+       /* disable global interrupt and set int polarity to active high */
+       iowrite32(GMIR_MHC_INT | GMIR_MOTG_INT | GMIR_INT_POLARITY,
+                 fotg210->reg + FOTG210_GMIR);
+
+       /* disable device global interrupt */
+       value = ioread32(fotg210->reg + FOTG210_DMCR);
+       value &= ~DMCR_GLINT_EN;
+       iowrite32(value, fotg210->reg + FOTG210_DMCR);
+
+       /* disable all fifo interrupt */
+       iowrite32(~(u32)0, fotg210->reg + FOTG210_DMISGR1);
+
+       /* disable cmd end */
+       value = ioread32(fotg210->reg + FOTG210_DMISGR0);
+       value |= DMISGR0_MCX_COMEND;
+       iowrite32(value, fotg210->reg + FOTG210_DMISGR0);
+}
+
+static int fotg210_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct fotg210_udc *fotg210 = gadget_to_fotg210(g);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&fotg210->lock, flags);
+
+       fotg210_init(fotg210);
+       fotg210->driver = NULL;
+
+       spin_unlock_irqrestore(&fotg210->lock, flags);
+
+       return 0;
+}
+
+static struct usb_gadget_ops fotg210_gadget_ops = {
+       .udc_start              = fotg210_udc_start,
+       .udc_stop               = fotg210_udc_stop,
+};
+
+static int fotg210_udc_remove(struct platform_device *pdev)
+{
+       struct fotg210_udc *fotg210 = platform_get_drvdata(pdev);
+
+       usb_del_gadget_udc(&fotg210->gadget);
+       iounmap(fotg210->reg);
+       free_irq(platform_get_irq(pdev, 0), fotg210);
+
+       fotg210_ep_free_request(&fotg210->ep[0]->ep, fotg210->ep0_req);
+       kfree(fotg210);
+
+       return 0;
+}
+
+static int fotg210_udc_probe(struct platform_device *pdev)
+{
+       struct resource *res, *ires;
+       struct fotg210_udc *fotg210 = NULL;
+       struct fotg210_ep *_ep[FOTG210_MAX_NUM_EP];
+       int ret = 0;
+       int i;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               pr_err("platform_get_resource error.\n");
+               return -ENODEV;
+       }
+
+       ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!ires) {
+               pr_err("platform_get_resource IORESOURCE_IRQ error.\n");
+               return -ENODEV;
+       }
+
+       ret = -ENOMEM;
+
+       /* initialize udc */
+       fotg210 = kzalloc(sizeof(struct fotg210_udc), GFP_KERNEL);
+       if (fotg210 == NULL)
+               goto err_alloc;
+
+       for (i = 0; i < FOTG210_MAX_NUM_EP; i++) {
+               _ep[i] = kzalloc(sizeof(struct fotg210_ep), GFP_KERNEL);
+               if (_ep[i] == NULL)
+                       goto err_alloc;
+               fotg210->ep[i] = _ep[i];
+       }
+
+       fotg210->reg = ioremap(res->start, resource_size(res));
+       if (fotg210->reg == NULL) {
+               pr_err("ioremap error.\n");
+               goto err_map;
+       }
+
+       spin_lock_init(&fotg210->lock);
+
+       platform_set_drvdata(pdev, fotg210);
+
+       fotg210->gadget.ops = &fotg210_gadget_ops;
+
+       fotg210->gadget.max_speed = USB_SPEED_HIGH;
+       fotg210->gadget.dev.parent = &pdev->dev;
+       fotg210->gadget.dev.dma_mask = pdev->dev.dma_mask;
+       fotg210->gadget.name = udc_name;
+
+       INIT_LIST_HEAD(&fotg210->gadget.ep_list);
+
+       for (i = 0; i < FOTG210_MAX_NUM_EP; i++) {
+               struct fotg210_ep *ep = fotg210->ep[i];
+
+               if (i) {
+                       INIT_LIST_HEAD(&fotg210->ep[i]->ep.ep_list);
+                       list_add_tail(&fotg210->ep[i]->ep.ep_list,
+                                     &fotg210->gadget.ep_list);
+               }
+               ep->fotg210 = fotg210;
+               INIT_LIST_HEAD(&ep->queue);
+               ep->ep.name = fotg210_ep_name[i];
+               ep->ep.ops = &fotg210_ep_ops;
+               usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
+       }
+       usb_ep_set_maxpacket_limit(&fotg210->ep[0]->ep, 0x40);
+       fotg210->gadget.ep0 = &fotg210->ep[0]->ep;
+       INIT_LIST_HEAD(&fotg210->gadget.ep0->ep_list);
+
+       fotg210->ep0_req = fotg210_ep_alloc_request(&fotg210->ep[0]->ep,
+                               GFP_KERNEL);
+       if (fotg210->ep0_req == NULL)
+               goto err_req;
+
+       fotg210_init(fotg210);
+
+       fotg210_disable_unplug(fotg210);
+
+       ret = request_irq(ires->start, fotg210_irq, IRQF_SHARED,
+                         udc_name, fotg210);
+       if (ret < 0) {
+               pr_err("request_irq error (%d)\n", ret);
+               goto err_irq;
+       }
+
+       ret = usb_add_gadget_udc(&pdev->dev, &fotg210->gadget);
+       if (ret)
+               goto err_add_udc;
+
+       dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
+
+       return 0;
+
+err_add_udc:
+err_irq:
+       free_irq(ires->start, fotg210);
+
+err_req:
+       fotg210_ep_free_request(&fotg210->ep[0]->ep, fotg210->ep0_req);
+
+err_map:
+       if (fotg210->reg)
+               iounmap(fotg210->reg);
+
+err_alloc:
+       kfree(fotg210);
+
+       return ret;
+}
+
+static struct platform_driver fotg210_driver = {
+       .driver         = {
+               .name = (char *)udc_name,
+               .owner  = THIS_MODULE,
+       },
+       .probe          = fotg210_udc_probe,
+       .remove         = fotg210_udc_remove,
+};
+
+module_platform_driver(fotg210_driver);
+
+MODULE_AUTHOR("Yuan-Hsin Chen, Feng-Hsin Chiang <john453@faraday-tech.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/gadget/udc/fotg210.h b/drivers/usb/gadget/udc/fotg210.h
new file mode 100644 (file)
index 0000000..bbf991b
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Faraday FOTG210 USB OTG controller
+ *
+ * Copyright (C) 2013 Faraday Technology Corporation
+ * Author: Yuan-Hsin Chen <yhchen@faraday-tech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+
+#define FOTG210_MAX_NUM_EP     5 /* ep0...ep4 */
+#define FOTG210_MAX_FIFO_NUM   4 /* fifo0...fifo4 */
+
+/* Global Mask of HC/OTG/DEV interrupt Register(0xC4) */
+#define FOTG210_GMIR           0xC4
+#define GMIR_INT_POLARITY      0x8 /*Active High*/
+#define GMIR_MHC_INT           0x4
+#define GMIR_MOTG_INT          0x2
+#define GMIR_MDEV_INT          0x1
+
+/*  Device Main Control Register(0x100) */
+#define FOTG210_DMCR           0x100
+#define DMCR_HS_EN             (1 << 6)
+#define DMCR_CHIP_EN           (1 << 5)
+#define DMCR_SFRST             (1 << 4)
+#define DMCR_GOSUSP            (1 << 3)
+#define DMCR_GLINT_EN          (1 << 2)
+#define DMCR_HALF_SPEED                (1 << 1)
+#define DMCR_CAP_RMWAKUP       (1 << 0)
+
+/* Device Address Register(0x104) */
+#define FOTG210_DAR            0x104
+#define DAR_AFT_CONF           (1 << 7)
+
+/* Device Test Register(0x108) */
+#define FOTG210_DTR            0x108
+#define DTR_TST_CLRFF          (1 << 0)
+
+/* PHY Test Mode Selector register(0x114) */
+#define FOTG210_PHYTMSR                0x114
+#define PHYTMSR_TST_PKT                (1 << 4)
+#define PHYTMSR_TST_SE0NAK     (1 << 3)
+#define PHYTMSR_TST_KSTA       (1 << 2)
+#define PHYTMSR_TST_JSTA       (1 << 1)
+#define PHYTMSR_UNPLUG         (1 << 0)
+
+/* Cx configuration and FIFO Empty Status register(0x120) */
+#define FOTG210_DCFESR         0x120
+#define DCFESR_FIFO_EMPTY(fifo)        (1 << 8 << (fifo))
+#define DCFESR_CX_EMP          (1 << 5)
+#define DCFESR_CX_CLR          (1 << 3)
+#define DCFESR_CX_STL          (1 << 2)
+#define DCFESR_TST_PKDONE      (1 << 1)
+#define DCFESR_CX_DONE         (1 << 0)
+
+/* Device IDLE Counter Register(0x124) */
+#define FOTG210_DICR           0x124
+
+/* Device Mask of Interrupt Group Register (0x130) */
+#define FOTG210_DMIGR          0x130
+#define DMIGR_MINT_G0          (1 << 0)
+
+/* Device Mask of Interrupt Source Group 0(0x134) */
+#define FOTG210_DMISGR0                0x134
+#define DMISGR0_MCX_COMEND     (1 << 3)
+#define DMISGR0_MCX_OUT_INT    (1 << 2)
+#define DMISGR0_MCX_IN_INT     (1 << 1)
+#define DMISGR0_MCX_SETUP_INT  (1 << 0)
+
+/* Device Mask of Interrupt Source Group 1 Register(0x138)*/
+#define FOTG210_DMISGR1                0x138
+#define DMISGR1_MF3_IN_INT     (1 << 19)
+#define DMISGR1_MF2_IN_INT     (1 << 18)
+#define DMISGR1_MF1_IN_INT     (1 << 17)
+#define DMISGR1_MF0_IN_INT     (1 << 16)
+#define DMISGR1_MF_IN_INT(fifo)        (1 << (16 + (fifo)))
+#define DMISGR1_MF3_SPK_INT    (1 << 7)
+#define DMISGR1_MF3_OUT_INT    (1 << 6)
+#define DMISGR1_MF2_SPK_INT    (1 << 5)
+#define DMISGR1_MF2_OUT_INT    (1 << 4)
+#define DMISGR1_MF1_SPK_INT    (1 << 3)
+#define DMISGR1_MF1_OUT_INT    (1 << 2)
+#define DMISGR1_MF0_SPK_INT    (1 << 1)
+#define DMISGR1_MF0_OUT_INT    (1 << 0)
+#define DMISGR1_MF_OUTSPK_INT(fifo)    (0x3 << (fifo) * 2)
+
+/* Device Mask of Interrupt Source Group 2 Register (0x13C) */
+#define FOTG210_DMISGR2                0x13C
+#define DMISGR2_MDMA_ERROR     (1 << 8)
+#define DMISGR2_MDMA_CMPLT     (1 << 7)
+
+/* Device Interrupt group Register (0x140) */
+#define FOTG210_DIGR           0x140
+#define DIGR_INT_G2            (1 << 2)
+#define DIGR_INT_G1            (1 << 1)
+#define DIGR_INT_G0            (1 << 0)
+
+/* Device Interrupt Source Group 0 Register (0x144) */
+#define FOTG210_DISGR0         0x144
+#define DISGR0_CX_COMABT_INT   (1 << 5)
+#define DISGR0_CX_COMFAIL_INT  (1 << 4)
+#define DISGR0_CX_COMEND_INT   (1 << 3)
+#define DISGR0_CX_OUT_INT      (1 << 2)
+#define DISGR0_CX_IN_INT       (1 << 1)
+#define DISGR0_CX_SETUP_INT    (1 << 0)
+
+/* Device Interrupt Source Group 1 Register (0x148) */
+#define FOTG210_DISGR1         0x148
+#define DISGR1_OUT_INT(fifo)   (1 << ((fifo) * 2))
+#define DISGR1_SPK_INT(fifo)   (1 << 1 << ((fifo) * 2))
+#define DISGR1_IN_INT(fifo)    (1 << 16 << (fifo))
+
+/* Device Interrupt Source Group 2 Register (0x14C) */
+#define FOTG210_DISGR2         0x14C
+#define DISGR2_DMA_ERROR       (1 << 8)
+#define DISGR2_DMA_CMPLT       (1 << 7)
+#define DISGR2_RX0BYTE_INT     (1 << 6)
+#define DISGR2_TX0BYTE_INT     (1 << 5)
+#define DISGR2_ISO_SEQ_ABORT_INT       (1 << 4)
+#define DISGR2_ISO_SEQ_ERR_INT (1 << 3)
+#define DISGR2_RESM_INT                (1 << 2)
+#define DISGR2_SUSP_INT                (1 << 1)
+#define DISGR2_USBRST_INT      (1 << 0)
+
+/* Device Receive Zero-Length Data Packet Register (0x150)*/
+#define FOTG210_RX0BYTE                0x150
+#define RX0BYTE_EP8            (1 << 7)
+#define RX0BYTE_EP7            (1 << 6)
+#define RX0BYTE_EP6            (1 << 5)
+#define RX0BYTE_EP5            (1 << 4)
+#define RX0BYTE_EP4            (1 << 3)
+#define RX0BYTE_EP3            (1 << 2)
+#define RX0BYTE_EP2            (1 << 1)
+#define RX0BYTE_EP1            (1 << 0)
+
+/* Device Transfer Zero-Length Data Packet Register (0x154)*/
+#define FOTG210_TX0BYTE                0x154
+#define TX0BYTE_EP8            (1 << 7)
+#define TX0BYTE_EP7            (1 << 6)
+#define TX0BYTE_EP6            (1 << 5)
+#define TX0BYTE_EP5            (1 << 4)
+#define TX0BYTE_EP4            (1 << 3)
+#define TX0BYTE_EP3            (1 << 2)
+#define TX0BYTE_EP2            (1 << 1)
+#define TX0BYTE_EP1            (1 << 0)
+
+/* Device IN Endpoint x MaxPacketSize Register(0x160+4*(x-1)) */
+#define FOTG210_INEPMPSR(ep)   (0x160 + 4 * ((ep) - 1))
+#define INOUTEPMPSR_MPS(mps)   ((mps) & 0x2FF)
+#define INOUTEPMPSR_STL_EP     (1 << 11)
+#define INOUTEPMPSR_RESET_TSEQ (1 << 12)
+
+/* Device OUT Endpoint x MaxPacketSize Register(0x180+4*(x-1)) */
+#define FOTG210_OUTEPMPSR(ep)  (0x180 + 4 * ((ep) - 1))
+
+/* Device Endpoint 1~4 Map Register (0x1A0) */
+#define FOTG210_EPMAP          0x1A0
+#define EPMAP_FIFONO(ep, dir)          \
+       ((((ep) - 1) << ((ep) - 1) * 8) << ((dir) ? 0 : 4))
+#define EPMAP_FIFONOMSK(ep, dir)       \
+       ((3 << ((ep) - 1) * 8) << ((dir) ? 0 : 4))
+
+/* Device FIFO Map Register (0x1A8) */
+#define FOTG210_FIFOMAP                0x1A8
+#define FIFOMAP_DIROUT(fifo)   (0x0 << 4 << (fifo) * 8)
+#define FIFOMAP_DIRIN(fifo)    (0x1 << 4 << (fifo) * 8)
+#define FIFOMAP_BIDIR(fifo)    (0x2 << 4 << (fifo) * 8)
+#define FIFOMAP_NA(fifo)       (0x3 << 4 << (fifo) * 8)
+#define FIFOMAP_EPNO(ep)       ((ep) << ((ep) - 1) * 8)
+#define FIFOMAP_EPNOMSK(ep)    (0xF << ((ep) - 1) * 8)
+
+/* Device FIFO Confuguration Register (0x1AC) */
+#define FOTG210_FIFOCF         0x1AC
+#define FIFOCF_TYPE(type, fifo)        ((type) << (fifo) * 8)
+#define FIFOCF_BLK_SIN(fifo)   (0x0 << (fifo) * 8 << 2)
+#define FIFOCF_BLK_DUB(fifo)   (0x1 << (fifo) * 8 << 2)
+#define FIFOCF_BLK_TRI(fifo)   (0x2 << (fifo) * 8 << 2)
+#define FIFOCF_BLKSZ_512(fifo) (0x0 << (fifo) * 8 << 4)
+#define FIFOCF_BLKSZ_1024(fifo)        (0x1 << (fifo) * 8 << 4)
+#define FIFOCF_FIFO_EN(fifo)   (0x1 << (fifo) * 8 << 5)
+
+/* Device FIFO n Instruction and Byte Count Register (0x1B0+4*n) */
+#define FOTG210_FIBCR(fifo)    (0x1B0 + (fifo) * 4)
+#define FIBCR_BCFX             0x7FF
+#define FIBCR_FFRST            (1 << 12)
+
+/* Device DMA Target FIFO Number Register (0x1C0) */
+#define FOTG210_DMATFNR                0x1C0
+#define DMATFNR_ACC_CXF                (1 << 4)
+#define DMATFNR_ACC_F3         (1 << 3)
+#define DMATFNR_ACC_F2         (1 << 2)
+#define DMATFNR_ACC_F1         (1 << 1)
+#define DMATFNR_ACC_F0         (1 << 0)
+#define DMATFNR_ACC_FN(fifo)   (1 << (fifo))
+#define DMATFNR_DISDMA         0
+
+/* Device DMA Controller Parameter setting 1 Register (0x1C8) */
+#define FOTG210_DMACPSR1       0x1C8
+#define DMACPSR1_DMA_LEN(len)  (((len) & 0xFFFF) << 8)
+#define DMACPSR1_DMA_ABORT     (1 << 3)
+#define DMACPSR1_DMA_TYPE(dir_in)      (((dir_in) ? 1 : 0) << 1)
+#define DMACPSR1_DMA_START     (1 << 0)
+
+/* Device DMA Controller Parameter setting 2 Register (0x1CC) */
+#define FOTG210_DMACPSR2       0x1CC
+
+/* Device DMA Controller Parameter setting 3 Register (0x1CC) */
+#define FOTG210_CXPORT         0x1D0
+
+struct fotg210_request {
+       struct usb_request      req;
+       struct list_head        queue;
+};
+
+struct fotg210_ep {
+       struct usb_ep           ep;
+       struct fotg210_udc      *fotg210;
+
+       struct list_head        queue;
+       unsigned                stall:1;
+       unsigned                wedged:1;
+       unsigned                use_dma:1;
+
+       unsigned char           epnum;
+       unsigned char           type;
+       unsigned char           dir_in;
+       unsigned int            maxp;
+       const struct usb_endpoint_descriptor    *desc;
+};
+
+struct fotg210_udc {
+       spinlock_t              lock; /* protect the struct */
+       void __iomem            *reg;
+
+       unsigned long           irq_trigger;
+
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+
+       struct fotg210_ep       *ep[FOTG210_MAX_NUM_EP];
+
+       struct usb_request      *ep0_req;       /* for internal request */
+       __le16                  ep0_data;
+       u8                      ep0_dir;        /* 0/0x80  out/in */
+
+       u8                      reenum;         /* if re-enumeration */
+};
+
+#define gadget_to_fotg210(g)   container_of((g), struct fotg210_udc, gadget)
diff --git a/drivers/usb/gadget/udc/fsl_mxc_udc.c b/drivers/usb/gadget/udc/fsl_mxc_udc.c
new file mode 100644 (file)
index 0000000..9b140fc
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2009
+ * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
+ *
+ * Description:
+ * Helper routines for i.MX3x SoCs from Freescale, needed by the fsl_usb2_udc.c
+ * driver to function correctly on these systems.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fsl_devices.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+static struct clk *mxc_ahb_clk;
+static struct clk *mxc_per_clk;
+static struct clk *mxc_ipg_clk;
+
+/* workaround ENGcm09152 for i.MX35 */
+#define MX35_USBPHYCTRL_OFFSET         0x600
+#define USBPHYCTRL_OTGBASE_OFFSET      0x8
+#define USBPHYCTRL_EVDO                        (1 << 23)
+
+int fsl_udc_clk_init(struct platform_device *pdev)
+{
+       struct fsl_usb2_platform_data *pdata;
+       unsigned long freq;
+       int ret;
+
+       pdata = dev_get_platdata(&pdev->dev);
+
+       mxc_ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+       if (IS_ERR(mxc_ipg_clk)) {
+               dev_err(&pdev->dev, "clk_get(\"ipg\") failed\n");
+               return PTR_ERR(mxc_ipg_clk);
+       }
+
+       mxc_ahb_clk = devm_clk_get(&pdev->dev, "ahb");
+       if (IS_ERR(mxc_ahb_clk)) {
+               dev_err(&pdev->dev, "clk_get(\"ahb\") failed\n");
+               return PTR_ERR(mxc_ahb_clk);
+       }
+
+       mxc_per_clk = devm_clk_get(&pdev->dev, "per");
+       if (IS_ERR(mxc_per_clk)) {
+               dev_err(&pdev->dev, "clk_get(\"per\") failed\n");
+               return PTR_ERR(mxc_per_clk);
+       }
+
+       clk_prepare_enable(mxc_ipg_clk);
+       clk_prepare_enable(mxc_ahb_clk);
+       clk_prepare_enable(mxc_per_clk);
+
+       /* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */
+       if (!strcmp(pdev->id_entry->name, "imx-udc-mx27")) {
+               freq = clk_get_rate(mxc_per_clk);
+               if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
+                   (freq < 59999000 || freq > 60001000)) {
+                       dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq);
+                       ret = -EINVAL;
+                       goto eclkrate;
+               }
+       }
+
+       return 0;
+
+eclkrate:
+       clk_disable_unprepare(mxc_ipg_clk);
+       clk_disable_unprepare(mxc_ahb_clk);
+       clk_disable_unprepare(mxc_per_clk);
+       mxc_per_clk = NULL;
+       return ret;
+}
+
+int fsl_udc_clk_finalize(struct platform_device *pdev)
+{
+       struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
+       int ret = 0;
+
+       /* workaround ENGcm09152 for i.MX35 */
+       if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
+               unsigned int v;
+               struct resource *res = platform_get_resource
+                       (pdev, IORESOURCE_MEM, 0);
+               void __iomem *phy_regs = ioremap(res->start +
+                                               MX35_USBPHYCTRL_OFFSET, 512);
+               if (!phy_regs) {
+                       dev_err(&pdev->dev, "ioremap for phy address fails\n");
+                       ret = -EINVAL;
+                       goto ioremap_err;
+               }
+
+               v = readl(phy_regs + USBPHYCTRL_OTGBASE_OFFSET);
+               writel(v | USBPHYCTRL_EVDO,
+                       phy_regs + USBPHYCTRL_OTGBASE_OFFSET);
+
+               iounmap(phy_regs);
+       }
+
+
+ioremap_err:
+       /* ULPI transceivers don't need usbpll */
+       if (pdata->phy_mode == FSL_USB2_PHY_ULPI) {
+               clk_disable_unprepare(mxc_per_clk);
+               mxc_per_clk = NULL;
+       }
+
+       return ret;
+}
+
+void fsl_udc_clk_release(void)
+{
+       if (mxc_per_clk)
+               clk_disable_unprepare(mxc_per_clk);
+       clk_disable_unprepare(mxc_ahb_clk);
+       clk_disable_unprepare(mxc_ipg_clk);
+}
diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c
new file mode 100644 (file)
index 0000000..7324308
--- /dev/null
@@ -0,0 +1,2731 @@
+/*
+ * driver/usb/gadget/fsl_qe_udc.c
+ *
+ * Copyright (c) 2006-2008 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ *     Xie Xiaobo <X.Xie@freescale.com>
+ *     Li Yang <leoli@freescale.com>
+ *     Based on bareboard code from Shlomi Gridish.
+ *
+ * Description:
+ * Freescle QE/CPM USB Pheripheral Controller Driver
+ * The controller can be found on MPC8360, MPC8272, and etc.
+ * MPC8360 Rev 1.1 may need QE mircocode update
+ *
+ * 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.
+ */
+
+#undef USB_TRACE
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/moduleparam.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/dma-mapping.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+#include <asm/qe.h>
+#include <asm/cpm.h>
+#include <asm/dma.h>
+#include <asm/reg.h>
+#include "fsl_qe_udc.h"
+
+#define DRIVER_DESC     "Freescale QE/CPM USB Device Controller driver"
+#define DRIVER_AUTHOR   "Xie XiaoBo"
+#define DRIVER_VERSION  "1.0"
+
+#define DMA_ADDR_INVALID        (~(dma_addr_t)0)
+
+static const char driver_name[] = "fsl_qe_udc";
+static const char driver_desc[] = DRIVER_DESC;
+
+/*ep name is important in gadget, it should obey the convention of ep_match()*/
+static const char *const ep_name[] = {
+       "ep0-control", /* everyone has ep0 */
+       /* 3 configurable endpoints */
+       "ep1",
+       "ep2",
+       "ep3",
+};
+
+static struct usb_endpoint_descriptor qe_ep0_desc = {
+       .bLength =              USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+
+       .bEndpointAddress =     0,
+       .bmAttributes =         USB_ENDPOINT_XFER_CONTROL,
+       .wMaxPacketSize =       USB_MAX_CTRL_PAYLOAD,
+};
+
+/********************************************************************
+ *      Internal Used Function Start
+********************************************************************/
+/*-----------------------------------------------------------------
+ * done() - retire a request; caller blocked irqs
+ *--------------------------------------------------------------*/
+static void done(struct qe_ep *ep, struct qe_req *req, int status)
+{
+       struct qe_udc *udc = ep->udc;
+       unsigned char stopped = ep->stopped;
+
+       /* the req->queue pointer is used by ep_queue() func, in which
+        * the request will be added into a udc_ep->queue 'd tail
+        * so here the req will be dropped from the ep->queue
+        */
+       list_del_init(&req->queue);
+
+       /* req.status should be set as -EINPROGRESS in ep_queue() */
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       if (req->mapped) {
+               dma_unmap_single(udc->gadget.dev.parent,
+                       req->req.dma, req->req.length,
+                       ep_is_in(ep)
+                               ? DMA_TO_DEVICE
+                               : DMA_FROM_DEVICE);
+               req->req.dma = DMA_ADDR_INVALID;
+               req->mapped = 0;
+       } else
+               dma_sync_single_for_cpu(udc->gadget.dev.parent,
+                       req->req.dma, req->req.length,
+                       ep_is_in(ep)
+                               ? DMA_TO_DEVICE
+                               : DMA_FROM_DEVICE);
+
+       if (status && (status != -ESHUTDOWN))
+               dev_vdbg(udc->dev, "complete %s req %p stat %d len %u/%u\n",
+                       ep->ep.name, &req->req, status,
+                       req->req.actual, req->req.length);
+
+       /* don't modify queue heads during completion callback */
+       ep->stopped = 1;
+       spin_unlock(&udc->lock);
+
+       /* this complete() should a func implemented by gadget layer,
+        * eg fsg->bulk_in_complete() */
+       if (req->req.complete)
+               req->req.complete(&ep->ep, &req->req);
+
+       spin_lock(&udc->lock);
+
+       ep->stopped = stopped;
+}
+
+/*-----------------------------------------------------------------
+ * nuke(): delete all requests related to this ep
+ *--------------------------------------------------------------*/
+static void nuke(struct qe_ep *ep, int status)
+{
+       /* Whether this eq has request linked */
+       while (!list_empty(&ep->queue)) {
+               struct qe_req *req = NULL;
+               req = list_entry(ep->queue.next, struct qe_req, queue);
+
+               done(ep, req, status);
+       }
+}
+
+/*---------------------------------------------------------------------------*
+ * USB and Endpoint manipulate process, include parameter and register       *
+ *---------------------------------------------------------------------------*/
+/* @value: 1--set stall 0--clean stall */
+static int qe_eprx_stall_change(struct qe_ep *ep, int value)
+{
+       u16 tem_usep;
+       u8 epnum = ep->epnum;
+       struct qe_udc *udc = ep->udc;
+
+       tem_usep = in_be16(&udc->usb_regs->usb_usep[epnum]);
+       tem_usep = tem_usep & ~USB_RHS_MASK;
+       if (value == 1)
+               tem_usep |= USB_RHS_STALL;
+       else if (ep->dir == USB_DIR_IN)
+               tem_usep |= USB_RHS_IGNORE_OUT;
+
+       out_be16(&udc->usb_regs->usb_usep[epnum], tem_usep);
+       return 0;
+}
+
+static int qe_eptx_stall_change(struct qe_ep *ep, int value)
+{
+       u16 tem_usep;
+       u8 epnum = ep->epnum;
+       struct qe_udc *udc = ep->udc;
+
+       tem_usep = in_be16(&udc->usb_regs->usb_usep[epnum]);
+       tem_usep = tem_usep & ~USB_THS_MASK;
+       if (value == 1)
+               tem_usep |= USB_THS_STALL;
+       else if (ep->dir == USB_DIR_OUT)
+               tem_usep |= USB_THS_IGNORE_IN;
+
+       out_be16(&udc->usb_regs->usb_usep[epnum], tem_usep);
+
+       return 0;
+}
+
+static int qe_ep0_stall(struct qe_udc *udc)
+{
+       qe_eptx_stall_change(&udc->eps[0], 1);
+       qe_eprx_stall_change(&udc->eps[0], 1);
+       udc->ep0_state = WAIT_FOR_SETUP;
+       udc->ep0_dir = 0;
+       return 0;
+}
+
+static int qe_eprx_nack(struct qe_ep *ep)
+{
+       u8 epnum = ep->epnum;
+       struct qe_udc *udc = ep->udc;
+
+       if (ep->state == EP_STATE_IDLE) {
+               /* Set the ep's nack */
+               clrsetbits_be16(&udc->usb_regs->usb_usep[epnum],
+                               USB_RHS_MASK, USB_RHS_NACK);
+
+               /* Mask Rx and Busy interrupts */
+               clrbits16(&udc->usb_regs->usb_usbmr,
+                               (USB_E_RXB_MASK | USB_E_BSY_MASK));
+
+               ep->state = EP_STATE_NACK;
+       }
+       return 0;
+}
+
+static int qe_eprx_normal(struct qe_ep *ep)
+{
+       struct qe_udc *udc = ep->udc;
+
+       if (ep->state == EP_STATE_NACK) {
+               clrsetbits_be16(&udc->usb_regs->usb_usep[ep->epnum],
+                               USB_RTHS_MASK, USB_THS_IGNORE_IN);
+
+               /* Unmask RX interrupts */
+               out_be16(&udc->usb_regs->usb_usber,
+                               USB_E_BSY_MASK | USB_E_RXB_MASK);
+               setbits16(&udc->usb_regs->usb_usbmr,
+                               (USB_E_RXB_MASK | USB_E_BSY_MASK));
+
+               ep->state = EP_STATE_IDLE;
+               ep->has_data = 0;
+       }
+
+       return 0;
+}
+
+static int qe_ep_cmd_stoptx(struct qe_ep *ep)
+{
+       if (ep->udc->soc_type == PORT_CPM)
+               cpm_command(CPM_USB_STOP_TX | (ep->epnum << CPM_USB_EP_SHIFT),
+                               CPM_USB_STOP_TX_OPCODE);
+       else
+               qe_issue_cmd(QE_USB_STOP_TX, QE_CR_SUBBLOCK_USB,
+                               ep->epnum, 0);
+
+       return 0;
+}
+
+static int qe_ep_cmd_restarttx(struct qe_ep *ep)
+{
+       if (ep->udc->soc_type == PORT_CPM)
+               cpm_command(CPM_USB_RESTART_TX | (ep->epnum <<
+                               CPM_USB_EP_SHIFT), CPM_USB_RESTART_TX_OPCODE);
+       else
+               qe_issue_cmd(QE_USB_RESTART_TX, QE_CR_SUBBLOCK_USB,
+                               ep->epnum, 0);
+
+       return 0;
+}
+
+static int qe_ep_flushtxfifo(struct qe_ep *ep)
+{
+       struct qe_udc *udc = ep->udc;
+       int i;
+
+       i = (int)ep->epnum;
+
+       qe_ep_cmd_stoptx(ep);
+       out_8(&udc->usb_regs->usb_uscom,
+               USB_CMD_FLUSH_FIFO | (USB_CMD_EP_MASK & (ep->epnum)));
+       out_be16(&udc->ep_param[i]->tbptr, in_be16(&udc->ep_param[i]->tbase));
+       out_be32(&udc->ep_param[i]->tstate, 0);
+       out_be16(&udc->ep_param[i]->tbcnt, 0);
+
+       ep->c_txbd = ep->txbase;
+       ep->n_txbd = ep->txbase;
+       qe_ep_cmd_restarttx(ep);
+       return 0;
+}
+
+static int qe_ep_filltxfifo(struct qe_ep *ep)
+{
+       struct qe_udc *udc = ep->udc;
+
+       out_8(&udc->usb_regs->usb_uscom,
+                       USB_CMD_STR_FIFO | (USB_CMD_EP_MASK & (ep->epnum)));
+       return 0;
+}
+
+static int qe_epbds_reset(struct qe_udc *udc, int pipe_num)
+{
+       struct qe_ep *ep;
+       u32 bdring_len;
+       struct qe_bd __iomem *bd;
+       int i;
+
+       ep = &udc->eps[pipe_num];
+
+       if (ep->dir == USB_DIR_OUT)
+               bdring_len = USB_BDRING_LEN_RX;
+       else
+               bdring_len = USB_BDRING_LEN;
+
+       bd = ep->rxbase;
+       for (i = 0; i < (bdring_len - 1); i++) {
+               out_be32((u32 __iomem *)bd, R_E | R_I);
+               bd++;
+       }
+       out_be32((u32 __iomem *)bd, R_E | R_I | R_W);
+
+       bd = ep->txbase;
+       for (i = 0; i < USB_BDRING_LEN_TX - 1; i++) {
+               out_be32(&bd->buf, 0);
+               out_be32((u32 __iomem *)bd, 0);
+               bd++;
+       }
+       out_be32((u32 __iomem *)bd, T_W);
+
+       return 0;
+}
+
+static int qe_ep_reset(struct qe_udc *udc, int pipe_num)
+{
+       struct qe_ep *ep;
+       u16 tmpusep;
+
+       ep = &udc->eps[pipe_num];
+       tmpusep = in_be16(&udc->usb_regs->usb_usep[pipe_num]);
+       tmpusep &= ~USB_RTHS_MASK;
+
+       switch (ep->dir) {
+       case USB_DIR_BOTH:
+               qe_ep_flushtxfifo(ep);
+               break;
+       case USB_DIR_OUT:
+               tmpusep |= USB_THS_IGNORE_IN;
+               break;
+       case USB_DIR_IN:
+               qe_ep_flushtxfifo(ep);
+               tmpusep |= USB_RHS_IGNORE_OUT;
+               break;
+       default:
+               break;
+       }
+       out_be16(&udc->usb_regs->usb_usep[pipe_num], tmpusep);
+
+       qe_epbds_reset(udc, pipe_num);
+
+       return 0;
+}
+
+static int qe_ep_toggledata01(struct qe_ep *ep)
+{
+       ep->data01 ^= 0x1;
+       return 0;
+}
+
+static int qe_ep_bd_init(struct qe_udc *udc, unsigned char pipe_num)
+{
+       struct qe_ep *ep = &udc->eps[pipe_num];
+       unsigned long tmp_addr = 0;
+       struct usb_ep_para __iomem *epparam;
+       int i;
+       struct qe_bd __iomem *bd;
+       int bdring_len;
+
+       if (ep->dir == USB_DIR_OUT)
+               bdring_len = USB_BDRING_LEN_RX;
+       else
+               bdring_len = USB_BDRING_LEN;
+
+       epparam = udc->ep_param[pipe_num];
+       /* alloc multi-ram for BD rings and set the ep parameters */
+       tmp_addr = cpm_muram_alloc(sizeof(struct qe_bd) * (bdring_len +
+                               USB_BDRING_LEN_TX), QE_ALIGNMENT_OF_BD);
+       if (IS_ERR_VALUE(tmp_addr))
+               return -ENOMEM;
+
+       out_be16(&epparam->rbase, (u16)tmp_addr);
+       out_be16(&epparam->tbase, (u16)(tmp_addr +
+                               (sizeof(struct qe_bd) * bdring_len)));
+
+       out_be16(&epparam->rbptr, in_be16(&epparam->rbase));
+       out_be16(&epparam->tbptr, in_be16(&epparam->tbase));
+
+       ep->rxbase = cpm_muram_addr(tmp_addr);
+       ep->txbase = cpm_muram_addr(tmp_addr + (sizeof(struct qe_bd)
+                               * bdring_len));
+       ep->n_rxbd = ep->rxbase;
+       ep->e_rxbd = ep->rxbase;
+       ep->n_txbd = ep->txbase;
+       ep->c_txbd = ep->txbase;
+       ep->data01 = 0; /* data0 */
+
+       /* Init TX and RX bds */
+       bd = ep->rxbase;
+       for (i = 0; i < bdring_len - 1; i++) {
+               out_be32(&bd->buf, 0);
+               out_be32((u32 __iomem *)bd, 0);
+               bd++;
+       }
+       out_be32(&bd->buf, 0);
+       out_be32((u32 __iomem *)bd, R_W);
+
+       bd = ep->txbase;
+       for (i = 0; i < USB_BDRING_LEN_TX - 1; i++) {
+               out_be32(&bd->buf, 0);
+               out_be32((u32 __iomem *)bd, 0);
+               bd++;
+       }
+       out_be32(&bd->buf, 0);
+       out_be32((u32 __iomem *)bd, T_W);
+
+       return 0;
+}
+
+static int qe_ep_rxbd_update(struct qe_ep *ep)
+{
+       unsigned int size;
+       int i;
+       unsigned int tmp;
+       struct qe_bd __iomem *bd;
+       unsigned int bdring_len;
+
+       if (ep->rxbase == NULL)
+               return -EINVAL;
+
+       bd = ep->rxbase;
+
+       ep->rxframe = kmalloc(sizeof(*ep->rxframe), GFP_ATOMIC);
+       if (ep->rxframe == NULL) {
+               dev_err(ep->udc->dev, "malloc rxframe failed\n");
+               return -ENOMEM;
+       }
+
+       qe_frame_init(ep->rxframe);
+
+       if (ep->dir == USB_DIR_OUT)
+               bdring_len = USB_BDRING_LEN_RX;
+       else
+               bdring_len = USB_BDRING_LEN;
+
+       size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * (bdring_len + 1);
+       ep->rxbuffer = kzalloc(size, GFP_ATOMIC);
+       if (ep->rxbuffer == NULL) {
+               dev_err(ep->udc->dev, "malloc rxbuffer failed,size=%d\n",
+                               size);
+               kfree(ep->rxframe);
+               return -ENOMEM;
+       }
+
+       ep->rxbuf_d = virt_to_phys((void *)ep->rxbuffer);
+       if (ep->rxbuf_d == DMA_ADDR_INVALID) {
+               ep->rxbuf_d = dma_map_single(ep->udc->gadget.dev.parent,
+                                       ep->rxbuffer,
+                                       size,
+                                       DMA_FROM_DEVICE);
+               ep->rxbufmap = 1;
+       } else {
+               dma_sync_single_for_device(ep->udc->gadget.dev.parent,
+                                       ep->rxbuf_d, size,
+                                       DMA_FROM_DEVICE);
+               ep->rxbufmap = 0;
+       }
+
+       size = ep->ep.maxpacket + USB_CRC_SIZE + 2;
+       tmp = ep->rxbuf_d;
+       tmp = (u32)(((tmp >> 2) << 2) + 4);
+
+       for (i = 0; i < bdring_len - 1; i++) {
+               out_be32(&bd->buf, tmp);
+               out_be32((u32 __iomem *)bd, (R_E | R_I));
+               tmp = tmp + size;
+               bd++;
+       }
+       out_be32(&bd->buf, tmp);
+       out_be32((u32 __iomem *)bd, (R_E | R_I | R_W));
+
+       return 0;
+}
+
+static int qe_ep_register_init(struct qe_udc *udc, unsigned char pipe_num)
+{
+       struct qe_ep *ep = &udc->eps[pipe_num];
+       struct usb_ep_para __iomem *epparam;
+       u16 usep, logepnum;
+       u16 tmp;
+       u8 rtfcr = 0;
+
+       epparam = udc->ep_param[pipe_num];
+
+       usep = 0;
+       logepnum = (ep->ep.desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+       usep |= (logepnum << USB_EPNUM_SHIFT);
+
+       switch (ep->ep.desc->bmAttributes & 0x03) {
+       case USB_ENDPOINT_XFER_BULK:
+               usep |= USB_TRANS_BULK;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               usep |=  USB_TRANS_ISO;
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               usep |= USB_TRANS_INT;
+               break;
+       default:
+               usep |= USB_TRANS_CTR;
+               break;
+       }
+
+       switch (ep->dir) {
+       case USB_DIR_OUT:
+               usep |= USB_THS_IGNORE_IN;
+               break;
+       case USB_DIR_IN:
+               usep |= USB_RHS_IGNORE_OUT;
+               break;
+       default:
+               break;
+       }
+       out_be16(&udc->usb_regs->usb_usep[pipe_num], usep);
+
+       rtfcr = 0x30;
+       out_8(&epparam->rbmr, rtfcr);
+       out_8(&epparam->tbmr, rtfcr);
+
+       tmp = (u16)(ep->ep.maxpacket + USB_CRC_SIZE);
+       /* MRBLR must be divisble by 4 */
+       tmp = (u16)(((tmp >> 2) << 2) + 4);
+       out_be16(&epparam->mrblr, tmp);
+
+       return 0;
+}
+
+static int qe_ep_init(struct qe_udc *udc,
+                     unsigned char pipe_num,
+                     const struct usb_endpoint_descriptor *desc)
+{
+       struct qe_ep *ep = &udc->eps[pipe_num];
+       unsigned long flags;
+       int reval = 0;
+       u16 max = 0;
+
+       max = usb_endpoint_maxp(desc);
+
+       /* check the max package size validate for this endpoint */
+       /* Refer to USB2.0 spec table 9-13,
+       */
+       if (pipe_num != 0) {
+               switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+               case USB_ENDPOINT_XFER_BULK:
+                       if (strstr(ep->ep.name, "-iso")
+                                       || strstr(ep->ep.name, "-int"))
+                               goto en_done;
+                       switch (udc->gadget.speed) {
+                       case USB_SPEED_HIGH:
+                       if ((max == 128) || (max == 256) || (max == 512))
+                               break;
+                       default:
+                               switch (max) {
+                               case 4:
+                               case 8:
+                               case 16:
+                               case 32:
+                               case 64:
+                                       break;
+                               default:
+                               case USB_SPEED_LOW:
+                                       goto en_done;
+                               }
+                       }
+                       break;
+               case USB_ENDPOINT_XFER_INT:
+                       if (strstr(ep->ep.name, "-iso"))        /* bulk is ok */
+                               goto en_done;
+                       switch (udc->gadget.speed) {
+                       case USB_SPEED_HIGH:
+                               if (max <= 1024)
+                                       break;
+                       case USB_SPEED_FULL:
+                               if (max <= 64)
+                                       break;
+                       default:
+                               if (max <= 8)
+                                       break;
+                               goto en_done;
+                       }
+                       break;
+               case USB_ENDPOINT_XFER_ISOC:
+                       if (strstr(ep->ep.name, "-bulk")
+                               || strstr(ep->ep.name, "-int"))
+                               goto en_done;
+                       switch (udc->gadget.speed) {
+                       case USB_SPEED_HIGH:
+                               if (max <= 1024)
+                                       break;
+                       case USB_SPEED_FULL:
+                               if (max <= 1023)
+                                       break;
+                       default:
+                               goto en_done;
+                       }
+                       break;
+               case USB_ENDPOINT_XFER_CONTROL:
+                       if (strstr(ep->ep.name, "-iso")
+                               || strstr(ep->ep.name, "-int"))
+                               goto en_done;
+                       switch (udc->gadget.speed) {
+                       case USB_SPEED_HIGH:
+                       case USB_SPEED_FULL:
+                               switch (max) {
+                               case 1:
+                               case 2:
+                               case 4:
+                               case 8:
+                               case 16:
+                               case 32:
+                               case 64:
+                                       break;
+                               default:
+                                       goto en_done;
+                               }
+                       case USB_SPEED_LOW:
+                               switch (max) {
+                               case 1:
+                               case 2:
+                               case 4:
+                               case 8:
+                                       break;
+                               default:
+                                       goto en_done;
+                               }
+                       default:
+                               goto en_done;
+                       }
+                       break;
+
+               default:
+                       goto en_done;
+               }
+       } /* if ep0*/
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /* initialize ep structure */
+       ep->ep.maxpacket = max;
+       ep->tm = (u8)(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+       ep->ep.desc = desc;
+       ep->stopped = 0;
+       ep->init = 1;
+
+       if (pipe_num == 0) {
+               ep->dir = USB_DIR_BOTH;
+               udc->ep0_dir = USB_DIR_OUT;
+               udc->ep0_state = WAIT_FOR_SETUP;
+       } else  {
+               switch (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
+               case USB_DIR_OUT:
+                       ep->dir = USB_DIR_OUT;
+                       break;
+               case USB_DIR_IN:
+                       ep->dir = USB_DIR_IN;
+               default:
+                       break;
+               }
+       }
+
+       /* hardware special operation */
+       qe_ep_bd_init(udc, pipe_num);
+       if ((ep->tm == USBP_TM_CTL) || (ep->dir == USB_DIR_OUT)) {
+               reval = qe_ep_rxbd_update(ep);
+               if (reval)
+                       goto en_done1;
+       }
+
+       if ((ep->tm == USBP_TM_CTL) || (ep->dir == USB_DIR_IN)) {
+               ep->txframe = kmalloc(sizeof(*ep->txframe), GFP_ATOMIC);
+               if (ep->txframe == NULL) {
+                       dev_err(udc->dev, "malloc txframe failed\n");
+                       goto en_done2;
+               }
+               qe_frame_init(ep->txframe);
+       }
+
+       qe_ep_register_init(udc, pipe_num);
+
+       /* Now HW will be NAKing transfers to that EP,
+        * until a buffer is queued to it. */
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+en_done2:
+       kfree(ep->rxbuffer);
+       kfree(ep->rxframe);
+en_done1:
+       spin_unlock_irqrestore(&udc->lock, flags);
+en_done:
+       dev_err(udc->dev, "failed to initialize %s\n", ep->ep.name);
+       return -ENODEV;
+}
+
+static inline void qe_usb_enable(struct qe_udc *udc)
+{
+       setbits8(&udc->usb_regs->usb_usmod, USB_MODE_EN);
+}
+
+static inline void qe_usb_disable(struct qe_udc *udc)
+{
+       clrbits8(&udc->usb_regs->usb_usmod, USB_MODE_EN);
+}
+
+/*----------------------------------------------------------------------------*
+ *             USB and EP basic manipulate function end                      *
+ *----------------------------------------------------------------------------*/
+
+
+/******************************************************************************
+               UDC transmit and receive process
+ ******************************************************************************/
+static void recycle_one_rxbd(struct qe_ep *ep)
+{
+       u32 bdstatus;
+
+       bdstatus = in_be32((u32 __iomem *)ep->e_rxbd);
+       bdstatus = R_I | R_E | (bdstatus & R_W);
+       out_be32((u32 __iomem *)ep->e_rxbd, bdstatus);
+
+       if (bdstatus & R_W)
+               ep->e_rxbd = ep->rxbase;
+       else
+               ep->e_rxbd++;
+}
+
+static void recycle_rxbds(struct qe_ep *ep, unsigned char stopatnext)
+{
+       u32 bdstatus;
+       struct qe_bd __iomem *bd, *nextbd;
+       unsigned char stop = 0;
+
+       nextbd = ep->n_rxbd;
+       bd = ep->e_rxbd;
+       bdstatus = in_be32((u32 __iomem *)bd);
+
+       while (!(bdstatus & R_E) && !(bdstatus & BD_LENGTH_MASK) && !stop) {
+               bdstatus = R_E | R_I | (bdstatus & R_W);
+               out_be32((u32 __iomem *)bd, bdstatus);
+
+               if (bdstatus & R_W)
+                       bd = ep->rxbase;
+               else
+                       bd++;
+
+               bdstatus = in_be32((u32 __iomem *)bd);
+               if (stopatnext && (bd == nextbd))
+                       stop = 1;
+       }
+
+       ep->e_rxbd = bd;
+}
+
+static void ep_recycle_rxbds(struct qe_ep *ep)
+{
+       struct qe_bd __iomem *bd = ep->n_rxbd;
+       u32 bdstatus;
+       u8 epnum = ep->epnum;
+       struct qe_udc *udc = ep->udc;
+
+       bdstatus = in_be32((u32 __iomem *)bd);
+       if (!(bdstatus & R_E) && !(bdstatus & BD_LENGTH_MASK)) {
+               bd = ep->rxbase +
+                               ((in_be16(&udc->ep_param[epnum]->rbptr) -
+                                 in_be16(&udc->ep_param[epnum]->rbase))
+                                >> 3);
+               bdstatus = in_be32((u32 __iomem *)bd);
+
+               if (bdstatus & R_W)
+                       bd = ep->rxbase;
+               else
+                       bd++;
+
+               ep->e_rxbd = bd;
+               recycle_rxbds(ep, 0);
+               ep->e_rxbd = ep->n_rxbd;
+       } else
+               recycle_rxbds(ep, 1);
+
+       if (in_be16(&udc->usb_regs->usb_usber) & USB_E_BSY_MASK)
+               out_be16(&udc->usb_regs->usb_usber, USB_E_BSY_MASK);
+
+       if (ep->has_data <= 0 && (!list_empty(&ep->queue)))
+               qe_eprx_normal(ep);
+
+       ep->localnack = 0;
+}
+
+static void setup_received_handle(struct qe_udc *udc,
+                                       struct usb_ctrlrequest *setup);
+static int qe_ep_rxframe_handle(struct qe_ep *ep);
+static void ep0_req_complete(struct qe_udc *udc, struct qe_req *req);
+/* when BD PID is setup, handle the packet */
+static int ep0_setup_handle(struct qe_udc *udc)
+{
+       struct qe_ep *ep = &udc->eps[0];
+       struct qe_frame *pframe;
+       unsigned int fsize;
+       u8 *cp;
+
+       pframe = ep->rxframe;
+       if ((frame_get_info(pframe) & PID_SETUP)
+                       && (udc->ep0_state == WAIT_FOR_SETUP)) {
+               fsize = frame_get_length(pframe);
+               if (unlikely(fsize != 8))
+                       return -EINVAL;
+               cp = (u8 *)&udc->local_setup_buff;
+               memcpy(cp, pframe->data, fsize);
+               ep->data01 = 1;
+
+               /* handle the usb command base on the usb_ctrlrequest */
+               setup_received_handle(udc, &udc->local_setup_buff);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int qe_ep0_rx(struct qe_udc *udc)
+{
+       struct qe_ep *ep = &udc->eps[0];
+       struct qe_frame *pframe;
+       struct qe_bd __iomem *bd;
+       u32 bdstatus, length;
+       u32 vaddr;
+
+       pframe = ep->rxframe;
+
+       if (ep->dir == USB_DIR_IN) {
+               dev_err(udc->dev, "ep0 not a control endpoint\n");
+               return -EINVAL;
+       }
+
+       bd = ep->n_rxbd;
+       bdstatus = in_be32((u32 __iomem *)bd);
+       length = bdstatus & BD_LENGTH_MASK;
+
+       while (!(bdstatus & R_E) && length) {
+               if ((bdstatus & R_F) && (bdstatus & R_L)
+                       && !(bdstatus & R_ERROR)) {
+                       if (length == USB_CRC_SIZE) {
+                               udc->ep0_state = WAIT_FOR_SETUP;
+                               dev_vdbg(udc->dev,
+                                       "receive a ZLP in status phase\n");
+                       } else {
+                               qe_frame_clean(pframe);
+                               vaddr = (u32)phys_to_virt(in_be32(&bd->buf));
+                               frame_set_data(pframe, (u8 *)vaddr);
+                               frame_set_length(pframe,
+                                               (length - USB_CRC_SIZE));
+                               frame_set_status(pframe, FRAME_OK);
+                               switch (bdstatus & R_PID) {
+                               case R_PID_SETUP:
+                                       frame_set_info(pframe, PID_SETUP);
+                                       break;
+                               case R_PID_DATA1:
+                                       frame_set_info(pframe, PID_DATA1);
+                                       break;
+                               default:
+                                       frame_set_info(pframe, PID_DATA0);
+                                       break;
+                               }
+
+                               if ((bdstatus & R_PID) == R_PID_SETUP)
+                                       ep0_setup_handle(udc);
+                               else
+                                       qe_ep_rxframe_handle(ep);
+                       }
+               } else {
+                       dev_err(udc->dev, "The receive frame with error!\n");
+               }
+
+               /* note: don't clear the rxbd's buffer address */
+               recycle_one_rxbd(ep);
+
+               /* Get next BD */
+               if (bdstatus & R_W)
+                       bd = ep->rxbase;
+               else
+                       bd++;
+
+               bdstatus = in_be32((u32 __iomem *)bd);
+               length = bdstatus & BD_LENGTH_MASK;
+
+       }
+
+       ep->n_rxbd = bd;
+
+       return 0;
+}
+
+static int qe_ep_rxframe_handle(struct qe_ep *ep)
+{
+       struct qe_frame *pframe;
+       u8 framepid = 0;
+       unsigned int fsize;
+       u8 *cp;
+       struct qe_req *req;
+
+       pframe = ep->rxframe;
+
+       if (frame_get_info(pframe) & PID_DATA1)
+               framepid = 0x1;
+
+       if (framepid != ep->data01) {
+               dev_err(ep->udc->dev, "the data01 error!\n");
+               return -EIO;
+       }
+
+       fsize = frame_get_length(pframe);
+       if (list_empty(&ep->queue)) {
+               dev_err(ep->udc->dev, "the %s have no requeue!\n", ep->name);
+       } else {
+               req = list_entry(ep->queue.next, struct qe_req, queue);
+
+               cp = (u8 *)(req->req.buf) + req->req.actual;
+               if (cp) {
+                       memcpy(cp, pframe->data, fsize);
+                       req->req.actual += fsize;
+                       if ((fsize < ep->ep.maxpacket) ||
+                                       (req->req.actual >= req->req.length)) {
+                               if (ep->epnum == 0)
+                                       ep0_req_complete(ep->udc, req);
+                               else
+                                       done(ep, req, 0);
+                               if (list_empty(&ep->queue) && ep->epnum != 0)
+                                       qe_eprx_nack(ep);
+                       }
+               }
+       }
+
+       qe_ep_toggledata01(ep);
+
+       return 0;
+}
+
+static void ep_rx_tasklet(unsigned long data)
+{
+       struct qe_udc *udc = (struct qe_udc *)data;
+       struct qe_ep *ep;
+       struct qe_frame *pframe;
+       struct qe_bd __iomem *bd;
+       unsigned long flags;
+       u32 bdstatus, length;
+       u32 vaddr, i;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       for (i = 1; i < USB_MAX_ENDPOINTS; i++) {
+               ep = &udc->eps[i];
+
+               if (ep->dir == USB_DIR_IN || ep->enable_tasklet == 0) {
+                       dev_dbg(udc->dev,
+                               "This is a transmit ep or disable tasklet!\n");
+                       continue;
+               }
+
+               pframe = ep->rxframe;
+               bd = ep->n_rxbd;
+               bdstatus = in_be32((u32 __iomem *)bd);
+               length = bdstatus & BD_LENGTH_MASK;
+
+               while (!(bdstatus & R_E) && length) {
+                       if (list_empty(&ep->queue)) {
+                               qe_eprx_nack(ep);
+                               dev_dbg(udc->dev,
+                                       "The rxep have noreq %d\n",
+                                       ep->has_data);
+                               break;
+                       }
+
+                       if ((bdstatus & R_F) && (bdstatus & R_L)
+                               && !(bdstatus & R_ERROR)) {
+                               qe_frame_clean(pframe);
+                               vaddr = (u32)phys_to_virt(in_be32(&bd->buf));
+                               frame_set_data(pframe, (u8 *)vaddr);
+                               frame_set_length(pframe,
+                                               (length - USB_CRC_SIZE));
+                               frame_set_status(pframe, FRAME_OK);
+                               switch (bdstatus & R_PID) {
+                               case R_PID_DATA1:
+                                       frame_set_info(pframe, PID_DATA1);
+                                       break;
+                               case R_PID_SETUP:
+                                       frame_set_info(pframe, PID_SETUP);
+                                       break;
+                               default:
+                                       frame_set_info(pframe, PID_DATA0);
+                                       break;
+                               }
+                               /* handle the rx frame */
+                               qe_ep_rxframe_handle(ep);
+                       } else {
+                               dev_err(udc->dev,
+                                       "error in received frame\n");
+                       }
+                       /* note: don't clear the rxbd's buffer address */
+                       /*clear the length */
+                       out_be32((u32 __iomem *)bd, bdstatus & BD_STATUS_MASK);
+                       ep->has_data--;
+                       if (!(ep->localnack))
+                               recycle_one_rxbd(ep);
+
+                       /* Get next BD */
+                       if (bdstatus & R_W)
+                               bd = ep->rxbase;
+                       else
+                               bd++;
+
+                       bdstatus = in_be32((u32 __iomem *)bd);
+                       length = bdstatus & BD_LENGTH_MASK;
+               }
+
+               ep->n_rxbd = bd;
+
+               if (ep->localnack)
+                       ep_recycle_rxbds(ep);
+
+               ep->enable_tasklet = 0;
+       } /* for i=1 */
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+}
+
+static int qe_ep_rx(struct qe_ep *ep)
+{
+       struct qe_udc *udc;
+       struct qe_frame *pframe;
+       struct qe_bd __iomem *bd;
+       u16 swoffs, ucoffs, emptybds;
+
+       udc = ep->udc;
+       pframe = ep->rxframe;
+
+       if (ep->dir == USB_DIR_IN) {
+               dev_err(udc->dev, "transmit ep in rx function\n");
+               return -EINVAL;
+       }
+
+       bd = ep->n_rxbd;
+
+       swoffs = (u16)(bd - ep->rxbase);
+       ucoffs = (u16)((in_be16(&udc->ep_param[ep->epnum]->rbptr) -
+                       in_be16(&udc->ep_param[ep->epnum]->rbase)) >> 3);
+       if (swoffs < ucoffs)
+               emptybds = USB_BDRING_LEN_RX - ucoffs + swoffs;
+       else
+               emptybds = swoffs - ucoffs;
+
+       if (emptybds < MIN_EMPTY_BDS) {
+               qe_eprx_nack(ep);
+               ep->localnack = 1;
+               dev_vdbg(udc->dev, "%d empty bds, send NACK\n", emptybds);
+       }
+       ep->has_data = USB_BDRING_LEN_RX - emptybds;
+
+       if (list_empty(&ep->queue)) {
+               qe_eprx_nack(ep);
+               dev_vdbg(udc->dev, "The rxep have no req queued with %d BDs\n",
+                               ep->has_data);
+               return 0;
+       }
+
+       tasklet_schedule(&udc->rx_tasklet);
+       ep->enable_tasklet = 1;
+
+       return 0;
+}
+
+/* send data from a frame, no matter what tx_req */
+static int qe_ep_tx(struct qe_ep *ep, struct qe_frame *frame)
+{
+       struct qe_udc *udc = ep->udc;
+       struct qe_bd __iomem *bd;
+       u16 saveusbmr;
+       u32 bdstatus, pidmask;
+       u32 paddr;
+
+       if (ep->dir == USB_DIR_OUT) {
+               dev_err(udc->dev, "receive ep passed to tx function\n");
+               return -EINVAL;
+       }
+
+       /* Disable the Tx interrupt */
+       saveusbmr = in_be16(&udc->usb_regs->usb_usbmr);
+       out_be16(&udc->usb_regs->usb_usbmr,
+                       saveusbmr & ~(USB_E_TXB_MASK | USB_E_TXE_MASK));
+
+       bd = ep->n_txbd;
+       bdstatus = in_be32((u32 __iomem *)bd);
+
+       if (!(bdstatus & (T_R | BD_LENGTH_MASK))) {
+               if (frame_get_length(frame) == 0) {
+                       frame_set_data(frame, udc->nullbuf);
+                       frame_set_length(frame, 2);
+                       frame->info |= (ZLP | NO_CRC);
+                       dev_vdbg(udc->dev, "the frame size = 0\n");
+               }
+               paddr = virt_to_phys((void *)frame->data);
+               out_be32(&bd->buf, paddr);
+               bdstatus = (bdstatus&T_W);
+               if (!(frame_get_info(frame) & NO_CRC))
+                       bdstatus |= T_R | T_I | T_L | T_TC
+                                       | frame_get_length(frame);
+               else
+                       bdstatus |= T_R | T_I | T_L | frame_get_length(frame);
+
+               /* if the packet is a ZLP in status phase */
+               if ((ep->epnum == 0) && (udc->ep0_state == DATA_STATE_NEED_ZLP))
+                       ep->data01 = 0x1;
+
+               if (ep->data01) {
+                       pidmask = T_PID_DATA1;
+                       frame->info |= PID_DATA1;
+               } else {
+                       pidmask = T_PID_DATA0;
+                       frame->info |= PID_DATA0;
+               }
+               bdstatus |= T_CNF;
+               bdstatus |= pidmask;
+               out_be32((u32 __iomem *)bd, bdstatus);
+               qe_ep_filltxfifo(ep);
+
+               /* enable the TX interrupt */
+               out_be16(&udc->usb_regs->usb_usbmr, saveusbmr);
+
+               qe_ep_toggledata01(ep);
+               if (bdstatus & T_W)
+                       ep->n_txbd = ep->txbase;
+               else
+                       ep->n_txbd++;
+
+               return 0;
+       } else {
+               out_be16(&udc->usb_regs->usb_usbmr, saveusbmr);
+               dev_vdbg(udc->dev, "The tx bd is not ready!\n");
+               return -EBUSY;
+       }
+}
+
+/* when a bd was transmitted, the function can
+ * handle the tx_req, not include ep0           */
+static int txcomplete(struct qe_ep *ep, unsigned char restart)
+{
+       if (ep->tx_req != NULL) {
+               struct qe_req *req = ep->tx_req;
+               unsigned zlp = 0, last_len = 0;
+
+               last_len = min_t(unsigned, req->req.length - ep->sent,
+                               ep->ep.maxpacket);
+
+               if (!restart) {
+                       int asent = ep->last;
+                       ep->sent += asent;
+                       ep->last -= asent;
+               } else {
+                       ep->last = 0;
+               }
+
+               /* zlp needed when req->re.zero is set */
+               if (req->req.zero) {
+                       if (last_len == 0 ||
+                               (req->req.length % ep->ep.maxpacket) != 0)
+                               zlp = 0;
+                       else
+                               zlp = 1;
+               } else
+                       zlp = 0;
+
+               /* a request already were transmitted completely */
+               if (((ep->tx_req->req.length - ep->sent) <= 0) && !zlp) {
+                       done(ep, ep->tx_req, 0);
+                       ep->tx_req = NULL;
+                       ep->last = 0;
+                       ep->sent = 0;
+               }
+       }
+
+       /* we should gain a new tx_req fot this endpoint */
+       if (ep->tx_req == NULL) {
+               if (!list_empty(&ep->queue)) {
+                       ep->tx_req = list_entry(ep->queue.next, struct qe_req,
+                                                       queue);
+                       ep->last = 0;
+                       ep->sent = 0;
+               }
+       }
+
+       return 0;
+}
+
+/* give a frame and a tx_req, send some data */
+static int qe_usb_senddata(struct qe_ep *ep, struct qe_frame *frame)
+{
+       unsigned int size;
+       u8 *buf;
+
+       qe_frame_clean(frame);
+       size = min_t(u32, (ep->tx_req->req.length - ep->sent),
+                               ep->ep.maxpacket);
+       buf = (u8 *)ep->tx_req->req.buf + ep->sent;
+       if (buf && size) {
+               ep->last = size;
+               ep->tx_req->req.actual += size;
+               frame_set_data(frame, buf);
+               frame_set_length(frame, size);
+               frame_set_status(frame, FRAME_OK);
+               frame_set_info(frame, 0);
+               return qe_ep_tx(ep, frame);
+       }
+       return -EIO;
+}
+
+/* give a frame struct,send a ZLP */
+static int sendnulldata(struct qe_ep *ep, struct qe_frame *frame, uint infor)
+{
+       struct qe_udc *udc = ep->udc;
+
+       if (frame == NULL)
+               return -ENODEV;
+
+       qe_frame_clean(frame);
+       frame_set_data(frame, (u8 *)udc->nullbuf);
+       frame_set_length(frame, 2);
+       frame_set_status(frame, FRAME_OK);
+       frame_set_info(frame, (ZLP | NO_CRC | infor));
+
+       return qe_ep_tx(ep, frame);
+}
+
+static int frame_create_tx(struct qe_ep *ep, struct qe_frame *frame)
+{
+       struct qe_req *req = ep->tx_req;
+       int reval;
+
+       if (req == NULL)
+               return -ENODEV;
+
+       if ((req->req.length - ep->sent) > 0)
+               reval = qe_usb_senddata(ep, frame);
+       else
+               reval = sendnulldata(ep, frame, 0);
+
+       return reval;
+}
+
+/* if direction is DIR_IN, the status is Device->Host
+ * if direction is DIR_OUT, the status transaction is Device<-Host
+ * in status phase, udc create a request and gain status */
+static int ep0_prime_status(struct qe_udc *udc, int direction)
+{
+
+       struct qe_ep *ep = &udc->eps[0];
+
+       if (direction == USB_DIR_IN) {
+               udc->ep0_state = DATA_STATE_NEED_ZLP;
+               udc->ep0_dir = USB_DIR_IN;
+               sendnulldata(ep, ep->txframe, SETUP_STATUS | NO_REQ);
+       } else {
+               udc->ep0_dir = USB_DIR_OUT;
+               udc->ep0_state = WAIT_FOR_OUT_STATUS;
+       }
+
+       return 0;
+}
+
+/* a request complete in ep0, whether gadget request or udc request */
+static void ep0_req_complete(struct qe_udc *udc, struct qe_req *req)
+{
+       struct qe_ep *ep = &udc->eps[0];
+       /* because usb and ep's status already been set in ch9setaddress() */
+
+       switch (udc->ep0_state) {
+       case DATA_STATE_XMIT:
+               done(ep, req, 0);
+               /* receive status phase */
+               if (ep0_prime_status(udc, USB_DIR_OUT))
+                       qe_ep0_stall(udc);
+               break;
+
+       case DATA_STATE_NEED_ZLP:
+               done(ep, req, 0);
+               udc->ep0_state = WAIT_FOR_SETUP;
+               break;
+
+       case DATA_STATE_RECV:
+               done(ep, req, 0);
+               /* send status phase */
+               if (ep0_prime_status(udc, USB_DIR_IN))
+                       qe_ep0_stall(udc);
+               break;
+
+       case WAIT_FOR_OUT_STATUS:
+               done(ep, req, 0);
+               udc->ep0_state = WAIT_FOR_SETUP;
+               break;
+
+       case WAIT_FOR_SETUP:
+               dev_vdbg(udc->dev, "Unexpected interrupt\n");
+               break;
+
+       default:
+               qe_ep0_stall(udc);
+               break;
+       }
+}
+
+static int ep0_txcomplete(struct qe_ep *ep, unsigned char restart)
+{
+       struct qe_req *tx_req = NULL;
+       struct qe_frame *frame = ep->txframe;
+
+       if ((frame_get_info(frame) & (ZLP | NO_REQ)) == (ZLP | NO_REQ)) {
+               if (!restart)
+                       ep->udc->ep0_state = WAIT_FOR_SETUP;
+               else
+                       sendnulldata(ep, ep->txframe, SETUP_STATUS | NO_REQ);
+               return 0;
+       }
+
+       tx_req = ep->tx_req;
+       if (tx_req != NULL) {
+               if (!restart) {
+                       int asent = ep->last;
+                       ep->sent += asent;
+                       ep->last -= asent;
+               } else {
+                       ep->last = 0;
+               }
+
+               /* a request already were transmitted completely */
+               if ((ep->tx_req->req.length - ep->sent) <= 0) {
+                       ep->tx_req->req.actual = (unsigned int)ep->sent;
+                       ep0_req_complete(ep->udc, ep->tx_req);
+                       ep->tx_req = NULL;
+                       ep->last = 0;
+                       ep->sent = 0;
+               }
+       } else {
+               dev_vdbg(ep->udc->dev, "the ep0_controller have no req\n");
+       }
+
+       return 0;
+}
+
+static int ep0_txframe_handle(struct qe_ep *ep)
+{
+       /* if have error, transmit again */
+       if (frame_get_status(ep->txframe) & FRAME_ERROR) {
+               qe_ep_flushtxfifo(ep);
+               dev_vdbg(ep->udc->dev, "The EP0 transmit data have error!\n");
+               if (frame_get_info(ep->txframe) & PID_DATA0)
+                       ep->data01 = 0;
+               else
+                       ep->data01 = 1;
+
+               ep0_txcomplete(ep, 1);
+       } else
+               ep0_txcomplete(ep, 0);
+
+       frame_create_tx(ep, ep->txframe);
+       return 0;
+}
+
+static int qe_ep0_txconf(struct qe_ep *ep)
+{
+       struct qe_bd __iomem *bd;
+       struct qe_frame *pframe;
+       u32 bdstatus;
+
+       bd = ep->c_txbd;
+       bdstatus = in_be32((u32 __iomem *)bd);
+       while (!(bdstatus & T_R) && (bdstatus & ~T_W)) {
+               pframe = ep->txframe;
+
+               /* clear and recycle the BD */
+               out_be32((u32 __iomem *)bd, bdstatus & T_W);
+               out_be32(&bd->buf, 0);
+               if (bdstatus & T_W)
+                       ep->c_txbd = ep->txbase;
+               else
+                       ep->c_txbd++;
+
+               if (ep->c_txbd == ep->n_txbd) {
+                       if (bdstatus & DEVICE_T_ERROR) {
+                               frame_set_status(pframe, FRAME_ERROR);
+                               if (bdstatus & T_TO)
+                                       pframe->status |= TX_ER_TIMEOUT;
+                               if (bdstatus & T_UN)
+                                       pframe->status |= TX_ER_UNDERUN;
+                       }
+                       ep0_txframe_handle(ep);
+               }
+
+               bd = ep->c_txbd;
+               bdstatus = in_be32((u32 __iomem *)bd);
+       }
+
+       return 0;
+}
+
+static int ep_txframe_handle(struct qe_ep *ep)
+{
+       if (frame_get_status(ep->txframe) & FRAME_ERROR) {
+               qe_ep_flushtxfifo(ep);
+               dev_vdbg(ep->udc->dev, "The EP0 transmit data have error!\n");
+               if (frame_get_info(ep->txframe) & PID_DATA0)
+                       ep->data01 = 0;
+               else
+                       ep->data01 = 1;
+
+               txcomplete(ep, 1);
+       } else
+               txcomplete(ep, 0);
+
+       frame_create_tx(ep, ep->txframe); /* send the data */
+       return 0;
+}
+
+/* confirm the already trainsmited bd */
+static int qe_ep_txconf(struct qe_ep *ep)
+{
+       struct qe_bd __iomem *bd;
+       struct qe_frame *pframe = NULL;
+       u32 bdstatus;
+       unsigned char breakonrxinterrupt = 0;
+
+       bd = ep->c_txbd;
+       bdstatus = in_be32((u32 __iomem *)bd);
+       while (!(bdstatus & T_R) && (bdstatus & ~T_W)) {
+               pframe = ep->txframe;
+               if (bdstatus & DEVICE_T_ERROR) {
+                       frame_set_status(pframe, FRAME_ERROR);
+                       if (bdstatus & T_TO)
+                               pframe->status |= TX_ER_TIMEOUT;
+                       if (bdstatus & T_UN)
+                               pframe->status |= TX_ER_UNDERUN;
+               }
+
+               /* clear and recycle the BD */
+               out_be32((u32 __iomem *)bd, bdstatus & T_W);
+               out_be32(&bd->buf, 0);
+               if (bdstatus & T_W)
+                       ep->c_txbd = ep->txbase;
+               else
+                       ep->c_txbd++;
+
+               /* handle the tx frame */
+               ep_txframe_handle(ep);
+               bd = ep->c_txbd;
+               bdstatus = in_be32((u32 __iomem *)bd);
+       }
+       if (breakonrxinterrupt)
+               return -EIO;
+       else
+               return 0;
+}
+
+/* Add a request in queue, and try to transmit a packet */
+static int ep_req_send(struct qe_ep *ep, struct qe_req *req)
+{
+       int reval = 0;
+
+       if (ep->tx_req == NULL) {
+               ep->sent = 0;
+               ep->last = 0;
+               txcomplete(ep, 0); /* can gain a new tx_req */
+               reval = frame_create_tx(ep, ep->txframe);
+       }
+       return reval;
+}
+
+/* Maybe this is a good ideal */
+static int ep_req_rx(struct qe_ep *ep, struct qe_req *req)
+{
+       struct qe_udc *udc = ep->udc;
+       struct qe_frame *pframe = NULL;
+       struct qe_bd __iomem *bd;
+       u32 bdstatus, length;
+       u32 vaddr, fsize;
+       u8 *cp;
+       u8 finish_req = 0;
+       u8 framepid;
+
+       if (list_empty(&ep->queue)) {
+               dev_vdbg(udc->dev, "the req already finish!\n");
+               return 0;
+       }
+       pframe = ep->rxframe;
+
+       bd = ep->n_rxbd;
+       bdstatus = in_be32((u32 __iomem *)bd);
+       length = bdstatus & BD_LENGTH_MASK;
+
+       while (!(bdstatus & R_E) && length) {
+               if (finish_req)
+                       break;
+               if ((bdstatus & R_F) && (bdstatus & R_L)
+                                       && !(bdstatus & R_ERROR)) {
+                       qe_frame_clean(pframe);
+                       vaddr = (u32)phys_to_virt(in_be32(&bd->buf));
+                       frame_set_data(pframe, (u8 *)vaddr);
+                       frame_set_length(pframe, (length - USB_CRC_SIZE));
+                       frame_set_status(pframe, FRAME_OK);
+                       switch (bdstatus & R_PID) {
+                       case R_PID_DATA1:
+                               frame_set_info(pframe, PID_DATA1); break;
+                       default:
+                               frame_set_info(pframe, PID_DATA0); break;
+                       }
+                       /* handle the rx frame */
+
+                       if (frame_get_info(pframe) & PID_DATA1)
+                               framepid = 0x1;
+                       else
+                               framepid = 0;
+
+                       if (framepid != ep->data01) {
+                               dev_vdbg(udc->dev, "the data01 error!\n");
+                       } else {
+                               fsize = frame_get_length(pframe);
+
+                               cp = (u8 *)(req->req.buf) + req->req.actual;
+                               if (cp) {
+                                       memcpy(cp, pframe->data, fsize);
+                                       req->req.actual += fsize;
+                                       if ((fsize < ep->ep.maxpacket)
+                                               || (req->req.actual >=
+                                                       req->req.length)) {
+                                               finish_req = 1;
+                                               done(ep, req, 0);
+                                               if (list_empty(&ep->queue))
+                                                       qe_eprx_nack(ep);
+                                       }
+                               }
+                               qe_ep_toggledata01(ep);
+                       }
+               } else {
+                       dev_err(udc->dev, "The receive frame with error!\n");
+               }
+
+               /* note: don't clear the rxbd's buffer address *
+                * only Clear the length */
+               out_be32((u32 __iomem *)bd, (bdstatus & BD_STATUS_MASK));
+               ep->has_data--;
+
+               /* Get next BD */
+               if (bdstatus & R_W)
+                       bd = ep->rxbase;
+               else
+                       bd++;
+
+               bdstatus = in_be32((u32 __iomem *)bd);
+               length = bdstatus & BD_LENGTH_MASK;
+       }
+
+       ep->n_rxbd = bd;
+       ep_recycle_rxbds(ep);
+
+       return 0;
+}
+
+/* only add the request in queue */
+static int ep_req_receive(struct qe_ep *ep, struct qe_req *req)
+{
+       if (ep->state == EP_STATE_NACK) {
+               if (ep->has_data <= 0) {
+                       /* Enable rx and unmask rx interrupt */
+                       qe_eprx_normal(ep);
+               } else {
+                       /* Copy the exist BD data */
+                       ep_req_rx(ep, req);
+               }
+       }
+
+       return 0;
+}
+
+/********************************************************************
+       Internal Used Function End
+********************************************************************/
+
+/*-----------------------------------------------------------------------
+       Endpoint Management Functions For Gadget
+ -----------------------------------------------------------------------*/
+static int qe_ep_enable(struct usb_ep *_ep,
+                        const struct usb_endpoint_descriptor *desc)
+{
+       struct qe_udc *udc;
+       struct qe_ep *ep;
+       int retval = 0;
+       unsigned char epnum;
+
+       ep = container_of(_ep, struct qe_ep, ep);
+
+       /* catch various bogus parameters */
+       if (!_ep || !desc || _ep->name == ep_name[0] ||
+                       (desc->bDescriptorType != USB_DT_ENDPOINT))
+               return -EINVAL;
+
+       udc = ep->udc;
+       if (!udc->driver || (udc->gadget.speed == USB_SPEED_UNKNOWN))
+               return -ESHUTDOWN;
+
+       epnum = (u8)desc->bEndpointAddress & 0xF;
+
+       retval = qe_ep_init(udc, epnum, desc);
+       if (retval != 0) {
+               cpm_muram_free(cpm_muram_offset(ep->rxbase));
+               dev_dbg(udc->dev, "enable ep%d failed\n", ep->epnum);
+               return -EINVAL;
+       }
+       dev_dbg(udc->dev, "enable ep%d successful\n", ep->epnum);
+       return 0;
+}
+
+static int qe_ep_disable(struct usb_ep *_ep)
+{
+       struct qe_udc *udc;
+       struct qe_ep *ep;
+       unsigned long flags;
+       unsigned int size;
+
+       ep = container_of(_ep, struct qe_ep, ep);
+       udc = ep->udc;
+
+       if (!_ep || !ep->ep.desc) {
+               dev_dbg(udc->dev, "%s not enabled\n", _ep ? ep->ep.name : NULL);
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&udc->lock, flags);
+       /* Nuke all pending requests (does flush) */
+       nuke(ep, -ESHUTDOWN);
+       ep->ep.desc = NULL;
+       ep->stopped = 1;
+       ep->tx_req = NULL;
+       qe_ep_reset(udc, ep->epnum);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       cpm_muram_free(cpm_muram_offset(ep->rxbase));
+
+       if (ep->dir == USB_DIR_OUT)
+               size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) *
+                               (USB_BDRING_LEN_RX + 1);
+       else
+               size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) *
+                               (USB_BDRING_LEN + 1);
+
+       if (ep->dir != USB_DIR_IN) {
+               kfree(ep->rxframe);
+               if (ep->rxbufmap) {
+                       dma_unmap_single(udc->gadget.dev.parent,
+                                       ep->rxbuf_d, size,
+                                       DMA_FROM_DEVICE);
+                       ep->rxbuf_d = DMA_ADDR_INVALID;
+               } else {
+                       dma_sync_single_for_cpu(
+                                       udc->gadget.dev.parent,
+                                       ep->rxbuf_d, size,
+                                       DMA_FROM_DEVICE);
+               }
+               kfree(ep->rxbuffer);
+       }
+
+       if (ep->dir != USB_DIR_OUT)
+               kfree(ep->txframe);
+
+       dev_dbg(udc->dev, "disabled %s OK\n", _ep->name);
+       return 0;
+}
+
+static struct usb_request *qe_alloc_request(struct usb_ep *_ep,        gfp_t gfp_flags)
+{
+       struct qe_req *req;
+
+       req = kzalloc(sizeof(*req), gfp_flags);
+       if (!req)
+               return NULL;
+
+       req->req.dma = DMA_ADDR_INVALID;
+
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void qe_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct qe_req *req;
+
+       req = container_of(_req, struct qe_req, req);
+
+       if (_req)
+               kfree(req);
+}
+
+static int __qe_ep_queue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct qe_ep *ep = container_of(_ep, struct qe_ep, ep);
+       struct qe_req *req = container_of(_req, struct qe_req, req);
+       struct qe_udc *udc;
+       int reval;
+
+       udc = ep->udc;
+       /* catch various bogus parameters */
+       if (!_req || !req->req.complete || !req->req.buf
+                       || !list_empty(&req->queue)) {
+               dev_dbg(udc->dev, "bad params\n");
+               return -EINVAL;
+       }
+       if (!_ep || (!ep->ep.desc && ep_index(ep))) {
+               dev_dbg(udc->dev, "bad ep\n");
+               return -EINVAL;
+       }
+
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       req->ep = ep;
+
+       /* map virtual address to hardware */
+       if (req->req.dma == DMA_ADDR_INVALID) {
+               req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
+                                       req->req.buf,
+                                       req->req.length,
+                                       ep_is_in(ep)
+                                       ? DMA_TO_DEVICE :
+                                       DMA_FROM_DEVICE);
+               req->mapped = 1;
+       } else {
+               dma_sync_single_for_device(ep->udc->gadget.dev.parent,
+                                       req->req.dma, req->req.length,
+                                       ep_is_in(ep)
+                                       ? DMA_TO_DEVICE :
+                                       DMA_FROM_DEVICE);
+               req->mapped = 0;
+       }
+
+       req->req.status = -EINPROGRESS;
+       req->req.actual = 0;
+
+       list_add_tail(&req->queue, &ep->queue);
+       dev_vdbg(udc->dev, "gadget have request in %s! %d\n",
+                       ep->name, req->req.length);
+
+       /* push the request to device */
+       if (ep_is_in(ep))
+               reval = ep_req_send(ep, req);
+
+       /* EP0 */
+       if (ep_index(ep) == 0 && req->req.length > 0) {
+               if (ep_is_in(ep))
+                       udc->ep0_state = DATA_STATE_XMIT;
+               else
+                       udc->ep0_state = DATA_STATE_RECV;
+       }
+
+       if (ep->dir == USB_DIR_OUT)
+               reval = ep_req_receive(ep, req);
+
+       return 0;
+}
+
+/* queues (submits) an I/O request to an endpoint */
+static int qe_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
+                      gfp_t gfp_flags)
+{
+       struct qe_ep *ep = container_of(_ep, struct qe_ep, ep);
+       struct qe_udc *udc = ep->udc;
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       ret = __qe_ep_queue(_ep, _req);
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return ret;
+}
+
+/* dequeues (cancels, unlinks) an I/O request from an endpoint */
+static int qe_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct qe_ep *ep = container_of(_ep, struct qe_ep, ep);
+       struct qe_req *req;
+       unsigned long flags;
+
+       if (!_ep || !_req)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+
+       if (&req->req != _req) {
+               spin_unlock_irqrestore(&ep->udc->lock, flags);
+               return -EINVAL;
+       }
+
+       done(ep, req, -ECONNRESET);
+
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+       return 0;
+}
+
+/*-----------------------------------------------------------------
+ * modify the endpoint halt feature
+ * @ep: the non-isochronous endpoint being stalled
+ * @value: 1--set halt  0--clear halt
+ * Returns zero, or a negative error code.
+*----------------------------------------------------------------*/
+static int qe_ep_set_halt(struct usb_ep *_ep, int value)
+{
+       struct qe_ep *ep;
+       unsigned long flags;
+       int status = -EOPNOTSUPP;
+       struct qe_udc *udc;
+
+       ep = container_of(_ep, struct qe_ep, ep);
+       if (!_ep || !ep->ep.desc) {
+               status = -EINVAL;
+               goto out;
+       }
+
+       udc = ep->udc;
+       /* Attempt to halt IN ep will fail if any transfer requests
+        * are still queue */
+       if (value && ep_is_in(ep) && !list_empty(&ep->queue)) {
+               status = -EAGAIN;
+               goto out;
+       }
+
+       status = 0;
+       spin_lock_irqsave(&ep->udc->lock, flags);
+       qe_eptx_stall_change(ep, value);
+       qe_eprx_stall_change(ep, value);
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+
+       if (ep->epnum == 0) {
+               udc->ep0_state = WAIT_FOR_SETUP;
+               udc->ep0_dir = 0;
+       }
+
+       /* set data toggle to DATA0 on clear halt */
+       if (value == 0)
+               ep->data01 = 0;
+out:
+       dev_vdbg(udc->dev, "%s %s halt stat %d\n", ep->ep.name,
+                       value ?  "set" : "clear", status);
+
+       return status;
+}
+
+static struct usb_ep_ops qe_ep_ops = {
+       .enable = qe_ep_enable,
+       .disable = qe_ep_disable,
+
+       .alloc_request = qe_alloc_request,
+       .free_request = qe_free_request,
+
+       .queue = qe_ep_queue,
+       .dequeue = qe_ep_dequeue,
+
+       .set_halt = qe_ep_set_halt,
+};
+
+/*------------------------------------------------------------------------
+       Gadget Driver Layer Operations
+ ------------------------------------------------------------------------*/
+
+/* Get the current frame number */
+static int qe_get_frame(struct usb_gadget *gadget)
+{
+       struct qe_udc *udc = container_of(gadget, struct qe_udc, gadget);
+       u16 tmp;
+
+       tmp = in_be16(&udc->usb_param->frame_n);
+       if (tmp & 0x8000)
+               tmp = tmp & 0x07ff;
+       else
+               tmp = -EINVAL;
+
+       return (int)tmp;
+}
+
+static int fsl_qe_start(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver);
+static int fsl_qe_stop(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver);
+
+/* defined in usb_gadget.h */
+static const struct usb_gadget_ops qe_gadget_ops = {
+       .get_frame = qe_get_frame,
+       .udc_start = fsl_qe_start,
+       .udc_stop = fsl_qe_stop,
+};
+
+/*-------------------------------------------------------------------------
+       USB ep0 Setup process in BUS Enumeration
+ -------------------------------------------------------------------------*/
+static int udc_reset_ep_queue(struct qe_udc *udc, u8 pipe)
+{
+       struct qe_ep *ep = &udc->eps[pipe];
+
+       nuke(ep, -ECONNRESET);
+       ep->tx_req = NULL;
+       return 0;
+}
+
+static int reset_queues(struct qe_udc *udc)
+{
+       u8 pipe;
+
+       for (pipe = 0; pipe < USB_MAX_ENDPOINTS; pipe++)
+               udc_reset_ep_queue(udc, pipe);
+
+       /* report disconnect; the driver is already quiesced */
+       spin_unlock(&udc->lock);
+       udc->driver->disconnect(&udc->gadget);
+       spin_lock(&udc->lock);
+
+       return 0;
+}
+
+static void ch9setaddress(struct qe_udc *udc, u16 value, u16 index,
+                       u16 length)
+{
+       /* Save the new address to device struct */
+       udc->device_address = (u8) value;
+       /* Update usb state */
+       udc->usb_state = USB_STATE_ADDRESS;
+
+       /* Status phase , send a ZLP */
+       if (ep0_prime_status(udc, USB_DIR_IN))
+               qe_ep0_stall(udc);
+}
+
+static void ownercomplete(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct qe_req *req = container_of(_req, struct qe_req, req);
+
+       req->req.buf = NULL;
+       kfree(req);
+}
+
+static void ch9getstatus(struct qe_udc *udc, u8 request_type, u16 value,
+                       u16 index, u16 length)
+{
+       u16 usb_status = 0;
+       struct qe_req *req;
+       struct qe_ep *ep;
+       int status = 0;
+
+       ep = &udc->eps[0];
+       if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
+               /* Get device status */
+               usb_status = 1 << USB_DEVICE_SELF_POWERED;
+       } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) {
+               /* Get interface status */
+               /* We don't have interface information in udc driver */
+               usb_status = 0;
+       } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_ENDPOINT) {
+               /* Get endpoint status */
+               int pipe = index & USB_ENDPOINT_NUMBER_MASK;
+               struct qe_ep *target_ep = &udc->eps[pipe];
+               u16 usep;
+
+               /* stall if endpoint doesn't exist */
+               if (!target_ep->ep.desc)
+                       goto stall;
+
+               usep = in_be16(&udc->usb_regs->usb_usep[pipe]);
+               if (index & USB_DIR_IN) {
+                       if (target_ep->dir != USB_DIR_IN)
+                               goto stall;
+                       if ((usep & USB_THS_MASK) == USB_THS_STALL)
+                               usb_status = 1 << USB_ENDPOINT_HALT;
+               } else {
+                       if (target_ep->dir != USB_DIR_OUT)
+                               goto stall;
+                       if ((usep & USB_RHS_MASK) == USB_RHS_STALL)
+                               usb_status = 1 << USB_ENDPOINT_HALT;
+               }
+       }
+
+       req = container_of(qe_alloc_request(&ep->ep, GFP_KERNEL),
+                                       struct qe_req, req);
+       req->req.length = 2;
+       req->req.buf = udc->statusbuf;
+       *(u16 *)req->req.buf = cpu_to_le16(usb_status);
+       req->req.status = -EINPROGRESS;
+       req->req.actual = 0;
+       req->req.complete = ownercomplete;
+
+       udc->ep0_dir = USB_DIR_IN;
+
+       /* data phase */
+       status = __qe_ep_queue(&ep->ep, &req->req);
+
+       if (status == 0)
+               return;
+stall:
+       dev_err(udc->dev, "Can't respond to getstatus request \n");
+       qe_ep0_stall(udc);
+}
+
+/* only handle the setup request, suppose the device in normal status */
+static void setup_received_handle(struct qe_udc *udc,
+                               struct usb_ctrlrequest *setup)
+{
+       /* Fix Endian (udc->local_setup_buff is cpu Endian now)*/
+       u16 wValue = le16_to_cpu(setup->wValue);
+       u16 wIndex = le16_to_cpu(setup->wIndex);
+       u16 wLength = le16_to_cpu(setup->wLength);
+
+       /* clear the previous request in the ep0 */
+       udc_reset_ep_queue(udc, 0);
+
+       if (setup->bRequestType & USB_DIR_IN)
+               udc->ep0_dir = USB_DIR_IN;
+       else
+               udc->ep0_dir = USB_DIR_OUT;
+
+       switch (setup->bRequest) {
+       case USB_REQ_GET_STATUS:
+               /* Data+Status phase form udc */
+               if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
+                                       != (USB_DIR_IN | USB_TYPE_STANDARD))
+                       break;
+               ch9getstatus(udc, setup->bRequestType, wValue, wIndex,
+                                       wLength);
+               return;
+
+       case USB_REQ_SET_ADDRESS:
+               /* Status phase from udc */
+               if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
+                                               USB_RECIP_DEVICE))
+                       break;
+               ch9setaddress(udc, wValue, wIndex, wLength);
+               return;
+
+       case USB_REQ_CLEAR_FEATURE:
+       case USB_REQ_SET_FEATURE:
+               /* Requests with no data phase, status phase from udc */
+               if ((setup->bRequestType & USB_TYPE_MASK)
+                                       != USB_TYPE_STANDARD)
+                       break;
+
+               if ((setup->bRequestType & USB_RECIP_MASK)
+                               == USB_RECIP_ENDPOINT) {
+                       int pipe = wIndex & USB_ENDPOINT_NUMBER_MASK;
+                       struct qe_ep *ep;
+
+                       if (wValue != 0 || wLength != 0
+                               || pipe > USB_MAX_ENDPOINTS)
+                               break;
+                       ep = &udc->eps[pipe];
+
+                       spin_unlock(&udc->lock);
+                       qe_ep_set_halt(&ep->ep,
+                                       (setup->bRequest == USB_REQ_SET_FEATURE)
+                                               ? 1 : 0);
+                       spin_lock(&udc->lock);
+               }
+
+               ep0_prime_status(udc, USB_DIR_IN);
+
+               return;
+
+       default:
+               break;
+       }
+
+       if (wLength) {
+               /* Data phase from gadget, status phase from udc */
+               if (setup->bRequestType & USB_DIR_IN) {
+                       udc->ep0_state = DATA_STATE_XMIT;
+                       udc->ep0_dir = USB_DIR_IN;
+               } else {
+                       udc->ep0_state = DATA_STATE_RECV;
+                       udc->ep0_dir = USB_DIR_OUT;
+               }
+               spin_unlock(&udc->lock);
+               if (udc->driver->setup(&udc->gadget,
+                                       &udc->local_setup_buff) < 0)
+                       qe_ep0_stall(udc);
+               spin_lock(&udc->lock);
+       } else {
+               /* No data phase, IN status from gadget */
+               udc->ep0_dir = USB_DIR_IN;
+               spin_unlock(&udc->lock);
+               if (udc->driver->setup(&udc->gadget,
+                                       &udc->local_setup_buff) < 0)
+                       qe_ep0_stall(udc);
+               spin_lock(&udc->lock);
+               udc->ep0_state = DATA_STATE_NEED_ZLP;
+       }
+}
+
+/*-------------------------------------------------------------------------
+       USB Interrupt handlers
+ -------------------------------------------------------------------------*/
+static void suspend_irq(struct qe_udc *udc)
+{
+       udc->resume_state = udc->usb_state;
+       udc->usb_state = USB_STATE_SUSPENDED;
+
+       /* report suspend to the driver ,serial.c not support this*/
+       if (udc->driver->suspend)
+               udc->driver->suspend(&udc->gadget);
+}
+
+static void resume_irq(struct qe_udc *udc)
+{
+       udc->usb_state = udc->resume_state;
+       udc->resume_state = 0;
+
+       /* report resume to the driver , serial.c not support this*/
+       if (udc->driver->resume)
+               udc->driver->resume(&udc->gadget);
+}
+
+static void idle_irq(struct qe_udc *udc)
+{
+       u8 usbs;
+
+       usbs = in_8(&udc->usb_regs->usb_usbs);
+       if (usbs & USB_IDLE_STATUS_MASK) {
+               if ((udc->usb_state) != USB_STATE_SUSPENDED)
+                       suspend_irq(udc);
+       } else {
+               if (udc->usb_state == USB_STATE_SUSPENDED)
+                       resume_irq(udc);
+       }
+}
+
+static int reset_irq(struct qe_udc *udc)
+{
+       unsigned char i;
+
+       if (udc->usb_state == USB_STATE_DEFAULT)
+               return 0;
+
+       qe_usb_disable(udc);
+       out_8(&udc->usb_regs->usb_usadr, 0);
+
+       for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
+               if (udc->eps[i].init)
+                       qe_ep_reset(udc, i);
+       }
+
+       reset_queues(udc);
+       udc->usb_state = USB_STATE_DEFAULT;
+       udc->ep0_state = WAIT_FOR_SETUP;
+       udc->ep0_dir = USB_DIR_OUT;
+       qe_usb_enable(udc);
+       return 0;
+}
+
+static int bsy_irq(struct qe_udc *udc)
+{
+       return 0;
+}
+
+static int txe_irq(struct qe_udc *udc)
+{
+       return 0;
+}
+
+/* ep0 tx interrupt also in here */
+static int tx_irq(struct qe_udc *udc)
+{
+       struct qe_ep *ep;
+       struct qe_bd __iomem *bd;
+       int i, res = 0;
+
+       if ((udc->usb_state == USB_STATE_ADDRESS)
+               && (in_8(&udc->usb_regs->usb_usadr) == 0))
+               out_8(&udc->usb_regs->usb_usadr, udc->device_address);
+
+       for (i = (USB_MAX_ENDPOINTS-1); ((i >= 0) && (res == 0)); i--) {
+               ep = &udc->eps[i];
+               if (ep && ep->init && (ep->dir != USB_DIR_OUT)) {
+                       bd = ep->c_txbd;
+                       if (!(in_be32((u32 __iomem *)bd) & T_R)
+                                               && (in_be32(&bd->buf))) {
+                               /* confirm the transmitted bd */
+                               if (ep->epnum == 0)
+                                       res = qe_ep0_txconf(ep);
+                               else
+                                       res = qe_ep_txconf(ep);
+                       }
+               }
+       }
+       return res;
+}
+
+
+/* setup packect's rx is handle in the function too */
+static void rx_irq(struct qe_udc *udc)
+{
+       struct qe_ep *ep;
+       struct qe_bd __iomem *bd;
+       int i;
+
+       for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
+               ep = &udc->eps[i];
+               if (ep && ep->init && (ep->dir != USB_DIR_IN)) {
+                       bd = ep->n_rxbd;
+                       if (!(in_be32((u32 __iomem *)bd) & R_E)
+                                               && (in_be32(&bd->buf))) {
+                               if (ep->epnum == 0) {
+                                       qe_ep0_rx(udc);
+                               } else {
+                                       /*non-setup package receive*/
+                                       qe_ep_rx(ep);
+                               }
+                       }
+               }
+       }
+}
+
+static irqreturn_t qe_udc_irq(int irq, void *_udc)
+{
+       struct qe_udc *udc = (struct qe_udc *)_udc;
+       u16 irq_src;
+       irqreturn_t status = IRQ_NONE;
+       unsigned long flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       irq_src = in_be16(&udc->usb_regs->usb_usber) &
+               in_be16(&udc->usb_regs->usb_usbmr);
+       /* Clear notification bits */
+       out_be16(&udc->usb_regs->usb_usber, irq_src);
+       /* USB Interrupt */
+       if (irq_src & USB_E_IDLE_MASK) {
+               idle_irq(udc);
+               irq_src &= ~USB_E_IDLE_MASK;
+               status = IRQ_HANDLED;
+       }
+
+       if (irq_src & USB_E_TXB_MASK) {
+               tx_irq(udc);
+               irq_src &= ~USB_E_TXB_MASK;
+               status = IRQ_HANDLED;
+       }
+
+       if (irq_src & USB_E_RXB_MASK) {
+               rx_irq(udc);
+               irq_src &= ~USB_E_RXB_MASK;
+               status = IRQ_HANDLED;
+       }
+
+       if (irq_src & USB_E_RESET_MASK) {
+               reset_irq(udc);
+               irq_src &= ~USB_E_RESET_MASK;
+               status = IRQ_HANDLED;
+       }
+
+       if (irq_src & USB_E_BSY_MASK) {
+               bsy_irq(udc);
+               irq_src &= ~USB_E_BSY_MASK;
+               status = IRQ_HANDLED;
+       }
+
+       if (irq_src & USB_E_TXE_MASK) {
+               txe_irq(udc);
+               irq_src &= ~USB_E_TXE_MASK;
+               status = IRQ_HANDLED;
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return status;
+}
+
+/*-------------------------------------------------------------------------
+       Gadget driver probe and unregister.
+ --------------------------------------------------------------------------*/
+static int fsl_qe_start(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct qe_udc *udc;
+       unsigned long flags;
+
+       udc = container_of(gadget, struct qe_udc, gadget);
+       /* lock is needed but whether should use this lock or another */
+       spin_lock_irqsave(&udc->lock, flags);
+
+       driver->driver.bus = NULL;
+       /* hook up the driver */
+       udc->driver = driver;
+       udc->gadget.speed = driver->max_speed;
+
+       /* Enable IRQ reg and Set usbcmd reg EN bit */
+       qe_usb_enable(udc);
+
+       out_be16(&udc->usb_regs->usb_usber, 0xffff);
+       out_be16(&udc->usb_regs->usb_usbmr, USB_E_DEFAULT_DEVICE);
+       udc->usb_state = USB_STATE_ATTACHED;
+       udc->ep0_state = WAIT_FOR_SETUP;
+       udc->ep0_dir = USB_DIR_OUT;
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       dev_info(udc->dev, "%s bind to driver %s\n", udc->gadget.name,
+                       driver->driver.name);
+       return 0;
+}
+
+static int fsl_qe_stop(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct qe_udc *udc;
+       struct qe_ep *loop_ep;
+       unsigned long flags;
+
+       udc = container_of(gadget, struct qe_udc, gadget);
+       /* stop usb controller, disable intr */
+       qe_usb_disable(udc);
+
+       /* in fact, no needed */
+       udc->usb_state = USB_STATE_ATTACHED;
+       udc->ep0_state = WAIT_FOR_SETUP;
+       udc->ep0_dir = 0;
+
+       /* stand operation */
+       spin_lock_irqsave(&udc->lock, flags);
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       nuke(&udc->eps[0], -ESHUTDOWN);
+       list_for_each_entry(loop_ep, &udc->gadget.ep_list, ep.ep_list)
+               nuke(loop_ep, -ESHUTDOWN);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       udc->driver = NULL;
+
+       dev_info(udc->dev, "unregistered gadget driver '%s'\r\n",
+                       driver->driver.name);
+       return 0;
+}
+
+/* udc structure's alloc and setup, include ep-param alloc */
+static struct qe_udc *qe_udc_config(struct platform_device *ofdev)
+{
+       struct qe_udc *udc;
+       struct device_node *np = ofdev->dev.of_node;
+       unsigned int tmp_addr = 0;
+       struct usb_device_para __iomem *usbpram;
+       unsigned int i;
+       u64 size;
+       u32 offset;
+
+       udc = kzalloc(sizeof(*udc), GFP_KERNEL);
+       if (udc == NULL) {
+               dev_err(&ofdev->dev, "malloc udc failed\n");
+               goto cleanup;
+       }
+
+       udc->dev = &ofdev->dev;
+
+       /* get default address of usb parameter in MURAM from device tree */
+       offset = *of_get_address(np, 1, &size, NULL);
+       udc->usb_param = cpm_muram_addr(offset);
+       memset_io(udc->usb_param, 0, size);
+
+       usbpram = udc->usb_param;
+       out_be16(&usbpram->frame_n, 0);
+       out_be32(&usbpram->rstate, 0);
+
+       tmp_addr = cpm_muram_alloc((USB_MAX_ENDPOINTS *
+                                       sizeof(struct usb_ep_para)),
+                                          USB_EP_PARA_ALIGNMENT);
+       if (IS_ERR_VALUE(tmp_addr))
+               goto cleanup;
+
+       for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
+               out_be16(&usbpram->epptr[i], (u16)tmp_addr);
+               udc->ep_param[i] = cpm_muram_addr(tmp_addr);
+               tmp_addr += 32;
+       }
+
+       memset_io(udc->ep_param[0], 0,
+                       USB_MAX_ENDPOINTS * sizeof(struct usb_ep_para));
+
+       udc->resume_state = USB_STATE_NOTATTACHED;
+       udc->usb_state = USB_STATE_POWERED;
+       udc->ep0_dir = 0;
+
+       spin_lock_init(&udc->lock);
+       return udc;
+
+cleanup:
+       kfree(udc);
+       return NULL;
+}
+
+/* USB Controller register init */
+static int qe_udc_reg_init(struct qe_udc *udc)
+{
+       struct usb_ctlr __iomem *qe_usbregs;
+       qe_usbregs = udc->usb_regs;
+
+       /* Spec says that we must enable the USB controller to change mode. */
+       out_8(&qe_usbregs->usb_usmod, 0x01);
+       /* Mode changed, now disable it, since muram isn't initialized yet. */
+       out_8(&qe_usbregs->usb_usmod, 0x00);
+
+       /* Initialize the rest. */
+       out_be16(&qe_usbregs->usb_usbmr, 0);
+       out_8(&qe_usbregs->usb_uscom, 0);
+       out_be16(&qe_usbregs->usb_usber, USBER_ALL_CLEAR);
+
+       return 0;
+}
+
+static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
+{
+       struct qe_ep *ep = &udc->eps[pipe_num];
+
+       ep->udc = udc;
+       strcpy(ep->name, ep_name[pipe_num]);
+       ep->ep.name = ep_name[pipe_num];
+
+       ep->ep.ops = &qe_ep_ops;
+       ep->stopped = 1;
+       usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
+       ep->ep.desc = NULL;
+       ep->dir = 0xff;
+       ep->epnum = (u8)pipe_num;
+       ep->sent = 0;
+       ep->last = 0;
+       ep->init = 0;
+       ep->rxframe = NULL;
+       ep->txframe = NULL;
+       ep->tx_req = NULL;
+       ep->state = EP_STATE_IDLE;
+       ep->has_data = 0;
+
+       /* the queue lists any req for this ep */
+       INIT_LIST_HEAD(&ep->queue);
+
+       /* gagdet.ep_list used for ep_autoconfig so no ep0*/
+       if (pipe_num != 0)
+               list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+
+       ep->gadget = &udc->gadget;
+
+       return 0;
+}
+
+/*-----------------------------------------------------------------------
+ *     UDC device Driver operation functions                           *
+ *----------------------------------------------------------------------*/
+static void qe_udc_release(struct device *dev)
+{
+       struct qe_udc *udc = container_of(dev, struct qe_udc, gadget.dev);
+       int i;
+
+       complete(udc->done);
+       cpm_muram_free(cpm_muram_offset(udc->ep_param[0]));
+       for (i = 0; i < USB_MAX_ENDPOINTS; i++)
+               udc->ep_param[i] = NULL;
+
+       kfree(udc);
+}
+
+/* Driver probe functions */
+static const struct of_device_id qe_udc_match[];
+static int qe_udc_probe(struct platform_device *ofdev)
+{
+       struct qe_udc *udc;
+       const struct of_device_id *match;
+       struct device_node *np = ofdev->dev.of_node;
+       struct qe_ep *ep;
+       unsigned int ret = 0;
+       unsigned int i;
+       const void *prop;
+
+       match = of_match_device(qe_udc_match, &ofdev->dev);
+       if (!match)
+               return -EINVAL;
+
+       prop = of_get_property(np, "mode", NULL);
+       if (!prop || strcmp(prop, "peripheral"))
+               return -ENODEV;
+
+       /* Initialize the udc structure including QH member and other member */
+       udc = qe_udc_config(ofdev);
+       if (!udc) {
+               dev_err(&ofdev->dev, "failed to initialize\n");
+               return -ENOMEM;
+       }
+
+       udc->soc_type = (unsigned long)match->data;
+       udc->usb_regs = of_iomap(np, 0);
+       if (!udc->usb_regs) {
+               ret = -ENOMEM;
+               goto err1;
+       }
+
+       /* initialize usb hw reg except for regs for EP,
+        * leave usbintr reg untouched*/
+       qe_udc_reg_init(udc);
+
+       /* here comes the stand operations for probe
+        * set the qe_udc->gadget.xxx */
+       udc->gadget.ops = &qe_gadget_ops;
+
+       /* gadget.ep0 is a pointer */
+       udc->gadget.ep0 = &udc->eps[0].ep;
+
+       INIT_LIST_HEAD(&udc->gadget.ep_list);
+
+       /* modify in register gadget process */
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+
+       /* name: Identifies the controller hardware type. */
+       udc->gadget.name = driver_name;
+       udc->gadget.dev.parent = &ofdev->dev;
+
+       /* initialize qe_ep struct */
+       for (i = 0; i < USB_MAX_ENDPOINTS ; i++) {
+               /* because the ep type isn't decide here so
+                * qe_ep_init() should be called in ep_enable() */
+
+               /* setup the qe_ep struct and link ep.ep.list
+                * into gadget.ep_list */
+               qe_ep_config(udc, (unsigned char)i);
+       }
+
+       /* ep0 initialization in here */
+       ret = qe_ep_init(udc, 0, &qe_ep0_desc);
+       if (ret)
+               goto err2;
+
+       /* create a buf for ZLP send, need to remain zeroed */
+       udc->nullbuf = devm_kzalloc(&ofdev->dev, 256, GFP_KERNEL);
+       if (udc->nullbuf == NULL) {
+               dev_err(udc->dev, "cannot alloc nullbuf\n");
+               ret = -ENOMEM;
+               goto err3;
+       }
+
+       /* buffer for data of get_status request */
+       udc->statusbuf = devm_kzalloc(&ofdev->dev, 2, GFP_KERNEL);
+       if (udc->statusbuf == NULL) {
+               ret = -ENOMEM;
+               goto err3;
+       }
+
+       udc->nullp = virt_to_phys((void *)udc->nullbuf);
+       if (udc->nullp == DMA_ADDR_INVALID) {
+               udc->nullp = dma_map_single(
+                                       udc->gadget.dev.parent,
+                                       udc->nullbuf,
+                                       256,
+                                       DMA_TO_DEVICE);
+               udc->nullmap = 1;
+       } else {
+               dma_sync_single_for_device(udc->gadget.dev.parent,
+                                       udc->nullp, 256,
+                                       DMA_TO_DEVICE);
+       }
+
+       tasklet_init(&udc->rx_tasklet, ep_rx_tasklet,
+                       (unsigned long)udc);
+       /* request irq and disable DR  */
+       udc->usb_irq = irq_of_parse_and_map(np, 0);
+       if (!udc->usb_irq) {
+               ret = -EINVAL;
+               goto err_noirq;
+       }
+
+       ret = request_irq(udc->usb_irq, qe_udc_irq, 0,
+                               driver_name, udc);
+       if (ret) {
+               dev_err(udc->dev, "cannot request irq %d err %d\n",
+                               udc->usb_irq, ret);
+               goto err4;
+       }
+
+       ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
+                       qe_udc_release);
+       if (ret)
+               goto err5;
+
+       platform_set_drvdata(ofdev, udc);
+       dev_info(udc->dev,
+                       "%s USB controller initialized as device\n",
+                       (udc->soc_type == PORT_QE) ? "QE" : "CPM");
+       return 0;
+
+err5:
+       free_irq(udc->usb_irq, udc);
+err4:
+       irq_dispose_mapping(udc->usb_irq);
+err_noirq:
+       if (udc->nullmap) {
+               dma_unmap_single(udc->gadget.dev.parent,
+                       udc->nullp, 256,
+                               DMA_TO_DEVICE);
+                       udc->nullp = DMA_ADDR_INVALID;
+       } else {
+               dma_sync_single_for_cpu(udc->gadget.dev.parent,
+                       udc->nullp, 256,
+                               DMA_TO_DEVICE);
+       }
+err3:
+       ep = &udc->eps[0];
+       cpm_muram_free(cpm_muram_offset(ep->rxbase));
+       kfree(ep->rxframe);
+       kfree(ep->rxbuffer);
+       kfree(ep->txframe);
+err2:
+       iounmap(udc->usb_regs);
+err1:
+       kfree(udc);
+       return ret;
+}
+
+#ifdef CONFIG_PM
+static int qe_udc_suspend(struct platform_device *dev, pm_message_t state)
+{
+       return -ENOTSUPP;
+}
+
+static int qe_udc_resume(struct platform_device *dev)
+{
+       return -ENOTSUPP;
+}
+#endif
+
+static int qe_udc_remove(struct platform_device *ofdev)
+{
+       struct qe_udc *udc = platform_get_drvdata(ofdev);
+       struct qe_ep *ep;
+       unsigned int size;
+       DECLARE_COMPLETION(done);
+
+       usb_del_gadget_udc(&udc->gadget);
+
+       udc->done = &done;
+       tasklet_disable(&udc->rx_tasklet);
+
+       if (udc->nullmap) {
+               dma_unmap_single(udc->gadget.dev.parent,
+                       udc->nullp, 256,
+                               DMA_TO_DEVICE);
+                       udc->nullp = DMA_ADDR_INVALID;
+       } else {
+               dma_sync_single_for_cpu(udc->gadget.dev.parent,
+                       udc->nullp, 256,
+                               DMA_TO_DEVICE);
+       }
+
+       ep = &udc->eps[0];
+       cpm_muram_free(cpm_muram_offset(ep->rxbase));
+       size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * (USB_BDRING_LEN + 1);
+
+       kfree(ep->rxframe);
+       if (ep->rxbufmap) {
+               dma_unmap_single(udc->gadget.dev.parent,
+                               ep->rxbuf_d, size,
+                               DMA_FROM_DEVICE);
+               ep->rxbuf_d = DMA_ADDR_INVALID;
+       } else {
+               dma_sync_single_for_cpu(udc->gadget.dev.parent,
+                               ep->rxbuf_d, size,
+                               DMA_FROM_DEVICE);
+       }
+
+       kfree(ep->rxbuffer);
+       kfree(ep->txframe);
+
+       free_irq(udc->usb_irq, udc);
+       irq_dispose_mapping(udc->usb_irq);
+
+       tasklet_kill(&udc->rx_tasklet);
+
+       iounmap(udc->usb_regs);
+
+       /* wait for release() of gadget.dev to free udc */
+       wait_for_completion(&done);
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static const struct of_device_id qe_udc_match[] = {
+       {
+               .compatible = "fsl,mpc8323-qe-usb",
+               .data = (void *)PORT_QE,
+       },
+       {
+               .compatible = "fsl,mpc8360-qe-usb",
+               .data = (void *)PORT_QE,
+       },
+       {
+               .compatible = "fsl,mpc8272-cpm-usb",
+               .data = (void *)PORT_CPM,
+       },
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, qe_udc_match);
+
+static struct platform_driver udc_driver = {
+       .driver = {
+               .name = driver_name,
+               .owner = THIS_MODULE,
+               .of_match_table = qe_udc_match,
+       },
+       .probe          = qe_udc_probe,
+       .remove         = qe_udc_remove,
+#ifdef CONFIG_PM
+       .suspend        = qe_udc_suspend,
+       .resume         = qe_udc_resume,
+#endif
+};
+
+module_platform_driver(udc_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.h b/drivers/usb/gadget/udc/fsl_qe_udc.h
new file mode 100644 (file)
index 0000000..7026919
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * drivers/usb/gadget/qe_udc.h
+ *
+ * Copyright (C) 2006-2008 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ *     Xiaobo Xie <X.Xie@freescale.com>
+ *     Li Yang <leoli@freescale.com>
+ *
+ * Description:
+ * Freescale USB device/endpoint management registers
+ *
+ * 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.
+ */
+
+#ifndef __FSL_QE_UDC_H
+#define __FSL_QE_UDC_H
+
+/* SoC type */
+#define PORT_CPM       0
+#define PORT_QE                1
+
+#define USB_MAX_ENDPOINTS               4
+#define USB_MAX_PIPES                   USB_MAX_ENDPOINTS
+#define USB_EP0_MAX_SIZE               64
+#define USB_MAX_CTRL_PAYLOAD            0x4000
+#define USB_BDRING_LEN                 16
+#define USB_BDRING_LEN_RX              256
+#define USB_BDRING_LEN_TX              16
+#define MIN_EMPTY_BDS                  128
+#define MAX_DATA_BDS                   8
+#define USB_CRC_SIZE                   2
+#define USB_DIR_BOTH                   0x88
+#define R_BUF_MAXSIZE                  0x800
+#define USB_EP_PARA_ALIGNMENT          32
+
+/* USB Mode Register bit define */
+#define USB_MODE_EN            0x01
+#define USB_MODE_HOST          0x02
+#define USB_MODE_TEST          0x04
+#define USB_MODE_SFTE          0x08
+#define USB_MODE_RESUME                0x40
+#define USB_MODE_LSS           0x80
+
+/* USB Slave Address Register Mask */
+#define USB_SLVADDR_MASK       0x7F
+
+/* USB Endpoint register define */
+#define USB_EPNUM_MASK         0xF000
+#define USB_EPNUM_SHIFT                12
+
+#define USB_TRANS_MODE_SHIFT   8
+#define USB_TRANS_CTR          0x0000
+#define USB_TRANS_INT          0x0100
+#define USB_TRANS_BULK         0x0200
+#define USB_TRANS_ISO          0x0300
+
+#define USB_EP_MF              0x0020
+#define USB_EP_RTE             0x0010
+
+#define USB_THS_SHIFT          2
+#define USB_THS_MASK           0x000c
+#define USB_THS_NORMAL         0x0
+#define USB_THS_IGNORE_IN      0x0004
+#define USB_THS_NACK           0x0008
+#define USB_THS_STALL          0x000c
+
+#define USB_RHS_SHIFT          0
+#define USB_RHS_MASK           0x0003
+#define USB_RHS_NORMAL         0x0
+#define USB_RHS_IGNORE_OUT     0x0001
+#define USB_RHS_NACK           0x0002
+#define USB_RHS_STALL          0x0003
+
+#define USB_RTHS_MASK          0x000f
+
+/* USB Command Register define */
+#define USB_CMD_STR_FIFO       0x80
+#define USB_CMD_FLUSH_FIFO     0x40
+#define USB_CMD_ISFT           0x20
+#define USB_CMD_DSFT           0x10
+#define USB_CMD_EP_MASK                0x03
+
+/* USB Event and Mask Register define */
+#define USB_E_MSF_MASK         0x0800
+#define USB_E_SFT_MASK         0x0400
+#define USB_E_RESET_MASK       0x0200
+#define USB_E_IDLE_MASK                0x0100
+#define USB_E_TXE4_MASK                0x0080
+#define USB_E_TXE3_MASK                0x0040
+#define USB_E_TXE2_MASK                0x0020
+#define USB_E_TXE1_MASK                0x0010
+#define USB_E_SOF_MASK         0x0008
+#define USB_E_BSY_MASK         0x0004
+#define USB_E_TXB_MASK         0x0002
+#define USB_E_RXB_MASK         0x0001
+#define USBER_ALL_CLEAR        0x0fff
+
+#define USB_E_DEFAULT_DEVICE   (USB_E_RESET_MASK | USB_E_TXE4_MASK | \
+                               USB_E_TXE3_MASK | USB_E_TXE2_MASK | \
+                               USB_E_TXE1_MASK | USB_E_BSY_MASK | \
+                               USB_E_TXB_MASK | USB_E_RXB_MASK)
+
+#define USB_E_TXE_MASK         (USB_E_TXE4_MASK | USB_E_TXE3_MASK|\
+                                USB_E_TXE2_MASK | USB_E_TXE1_MASK)
+/* USB Status Register define */
+#define USB_IDLE_STATUS_MASK   0x01
+
+/* USB Start of Frame Timer */
+#define USB_USSFT_MASK         0x3FFF
+
+/* USB Frame Number Register */
+#define USB_USFRN_MASK         0xFFFF
+
+struct usb_device_para{
+       u16     epptr[4];
+       u32     rstate;
+       u32     rptr;
+       u16     frame_n;
+       u16     rbcnt;
+       u32     rtemp;
+       u32     rxusb_data;
+       u16     rxuptr;
+       u8      reso[2];
+       u32     softbl;
+       u8      sofucrctemp;
+};
+
+struct usb_ep_para{
+       u16     rbase;
+       u16     tbase;
+       u8      rbmr;
+       u8      tbmr;
+       u16     mrblr;
+       u16     rbptr;
+       u16     tbptr;
+       u32     tstate;
+       u32     tptr;
+       u16     tcrc;
+       u16     tbcnt;
+       u32     ttemp;
+       u16     txusbu_ptr;
+       u8      reserve[2];
+};
+
+#define USB_BUSMODE_GBL                0x20
+#define USB_BUSMODE_BO_MASK    0x18
+#define USB_BUSMODE_BO_SHIFT   0x3
+#define USB_BUSMODE_BE         0x2
+#define USB_BUSMODE_CETM       0x04
+#define USB_BUSMODE_DTB                0x02
+
+/* Endpoint basic handle */
+#define ep_index(EP)           ((EP)->ep.desc->bEndpointAddress & 0xF)
+#define ep_maxpacket(EP)       ((EP)->ep.maxpacket)
+#define ep_is_in(EP)   ((ep_index(EP) == 0) ? (EP->udc->ep0_dir == \
+                       USB_DIR_IN) : ((EP)->ep.desc->bEndpointAddress \
+                       & USB_DIR_IN) == USB_DIR_IN)
+
+/* ep0 transfer state */
+#define WAIT_FOR_SETUP          0
+#define DATA_STATE_XMIT         1
+#define DATA_STATE_NEED_ZLP     2
+#define WAIT_FOR_OUT_STATUS     3
+#define DATA_STATE_RECV         4
+
+/* ep tramsfer mode */
+#define USBP_TM_CTL    0
+#define USBP_TM_ISO    1
+#define USBP_TM_BULK   2
+#define USBP_TM_INT    3
+
+/*-----------------------------------------------------------------------------
+       USB RX And TX DATA Frame
+ -----------------------------------------------------------------------------*/
+struct qe_frame{
+       u8 *data;
+       u32 len;
+       u32 status;
+       u32 info;
+
+       void *privdata;
+       struct list_head node;
+};
+
+/* Frame structure, info field. */
+#define PID_DATA0              0x80000000 /* Data toggle zero */
+#define PID_DATA1              0x40000000 /* Data toggle one  */
+#define PID_SETUP              0x20000000 /* setup bit */
+#define SETUP_STATUS           0x10000000 /* setup status bit */
+#define SETADDR_STATUS         0x08000000 /* setupup address status bit */
+#define NO_REQ                 0x04000000 /* Frame without request */
+#define HOST_DATA              0x02000000 /* Host data frame */
+#define FIRST_PACKET_IN_FRAME  0x01000000 /* first packet in the frame */
+#define TOKEN_FRAME            0x00800000 /* Host token frame */
+#define ZLP                    0x00400000 /* Zero length packet */
+#define IN_TOKEN_FRAME         0x00200000 /* In token package */
+#define OUT_TOKEN_FRAME        0x00100000 /* Out token package */
+#define SETUP_TOKEN_FRAME      0x00080000 /* Setup token package */
+#define STALL_FRAME            0x00040000 /* Stall handshake */
+#define NACK_FRAME             0x00020000 /* Nack handshake */
+#define NO_PID                 0x00010000 /* No send PID */
+#define NO_CRC                 0x00008000 /* No send CRC */
+#define HOST_COMMAND           0x00004000 /* Host command frame   */
+
+/* Frame status field */
+/* Receive side */
+#define FRAME_OK               0x00000000 /* Frame transmitted or received OK */
+#define FRAME_ERROR            0x80000000 /* Error occurred on frame */
+#define START_FRAME_LOST       0x40000000 /* START_FRAME_LOST */
+#define END_FRAME_LOST         0x20000000 /* END_FRAME_LOST */
+#define RX_ER_NONOCT           0x10000000 /* Rx Non Octet Aligned Packet */
+#define RX_ER_BITSTUFF         0x08000000 /* Frame Aborted --Received packet
+                                            with bit stuff error */
+#define RX_ER_CRC              0x04000000 /* Received packet with CRC error */
+#define RX_ER_OVERUN           0x02000000 /* Over-run occurred on reception */
+#define RX_ER_PID              0x01000000 /* Wrong PID received */
+/* Tranmit side */
+#define TX_ER_NAK              0x00800000 /* Received NAK handshake */
+#define TX_ER_STALL            0x00400000 /* Received STALL handshake */
+#define TX_ER_TIMEOUT          0x00200000 /* Transmit time out */
+#define TX_ER_UNDERUN          0x00100000 /* Transmit underrun */
+#define FRAME_INPROGRESS       0x00080000 /* Frame is being transmitted */
+#define ER_DATA_UNDERUN        0x00040000 /* Frame is shorter then expected */
+#define ER_DATA_OVERUN         0x00020000 /* Frame is longer then expected */
+
+/* QE USB frame operation functions */
+#define frame_get_length(frm) (frm->len)
+#define frame_set_length(frm, leng) (frm->len = leng)
+#define frame_get_data(frm) (frm->data)
+#define frame_set_data(frm, dat) (frm->data = dat)
+#define frame_get_info(frm) (frm->info)
+#define frame_set_info(frm, inf) (frm->info = inf)
+#define frame_get_status(frm) (frm->status)
+#define frame_set_status(frm, stat) (frm->status = stat)
+#define frame_get_privdata(frm) (frm->privdata)
+#define frame_set_privdata(frm, dat) (frm->privdata = dat)
+
+static inline void qe_frame_clean(struct qe_frame *frm)
+{
+       frame_set_data(frm, NULL);
+       frame_set_length(frm, 0);
+       frame_set_status(frm, FRAME_OK);
+       frame_set_info(frm, 0);
+       frame_set_privdata(frm, NULL);
+}
+
+static inline void qe_frame_init(struct qe_frame *frm)
+{
+       qe_frame_clean(frm);
+       INIT_LIST_HEAD(&(frm->node));
+}
+
+struct qe_req {
+       struct usb_request req;
+       struct list_head queue;
+       /* ep_queue() func will add
+        a request->queue into a udc_ep->queue 'd tail */
+       struct qe_ep *ep;
+       unsigned mapped:1;
+};
+
+struct qe_ep {
+       struct usb_ep ep;
+       struct list_head queue;
+       struct qe_udc *udc;
+       struct usb_gadget *gadget;
+
+       u8 state;
+
+       struct qe_bd __iomem *rxbase;
+       struct qe_bd __iomem *n_rxbd;
+       struct qe_bd __iomem *e_rxbd;
+
+       struct qe_bd __iomem *txbase;
+       struct qe_bd __iomem *n_txbd;
+       struct qe_bd __iomem *c_txbd;
+
+       struct qe_frame *rxframe;
+       u8 *rxbuffer;
+       dma_addr_t rxbuf_d;
+       u8 rxbufmap;
+       unsigned char localnack;
+       int has_data;
+
+       struct qe_frame *txframe;
+       struct qe_req *tx_req;
+       int sent;  /*data already sent */
+       int last;  /*data sent in the last time*/
+
+       u8 dir;
+       u8 epnum;
+       u8 tm; /* transfer mode */
+       u8 data01;
+       u8 init;
+
+       u8 already_seen;
+       u8 enable_tasklet;
+       u8 setup_stage;
+       u32 last_io;            /* timestamp */
+
+       char name[14];
+
+       unsigned double_buf:1;
+       unsigned stopped:1;
+       unsigned fnf:1;
+       unsigned has_dma:1;
+
+       u8 ackwait;
+       u8 dma_channel;
+       u16 dma_counter;
+       int lch;
+
+       struct timer_list timer;
+};
+
+struct qe_udc {
+       struct usb_gadget gadget;
+       struct usb_gadget_driver *driver;
+       struct device *dev;
+       struct qe_ep eps[USB_MAX_ENDPOINTS];
+       struct usb_ctrlrequest local_setup_buff;
+       spinlock_t lock;        /* lock for set/config qe_udc */
+       unsigned long soc_type;         /* QE or CPM soc */
+
+       struct qe_req *status_req;      /* ep0 status request */
+
+       /* USB and EP Parameter Block pointer */
+       struct usb_device_para __iomem *usb_param;
+       struct usb_ep_para __iomem *ep_param[4];
+
+       u32 max_pipes;          /* Device max pipes */
+       u32 max_use_endpts;     /* Max endpointes to be used */
+       u32 bus_reset;          /* Device is bus reseting */
+       u32 resume_state;       /* USB state to resume*/
+       u32 usb_state;          /* USB current state */
+       u32 usb_next_state;     /* USB next state */
+       u32 ep0_state;          /* Enpoint zero state */
+       u32 ep0_dir;            /* Enpoint zero direction: can be
+                               USB_DIR_IN or USB_DIR_OUT*/
+       u32 usb_sof_count;      /* SOF count */
+       u32 errors;             /* USB ERRORs count */
+
+       u8 *tmpbuf;
+       u32 c_start;
+       u32 c_end;
+
+       u8 *nullbuf;
+       u8 *statusbuf;
+       dma_addr_t nullp;
+       u8 nullmap;
+       u8 device_address;      /* Device USB address */
+
+       unsigned int usb_clock;
+       unsigned int usb_irq;
+       struct usb_ctlr __iomem *usb_regs;
+
+       struct tasklet_struct rx_tasklet;
+
+       struct completion *done;        /* to make sure release() is done */
+};
+
+#define EP_STATE_IDLE  0
+#define EP_STATE_NACK  1
+#define EP_STATE_STALL 2
+
+/*
+ * transmit BD's status
+ */
+#define T_R           0x80000000         /* ready bit */
+#define T_W           0x20000000         /* wrap bit */
+#define T_I           0x10000000         /* interrupt on completion */
+#define T_L           0x08000000         /* last */
+#define T_TC          0x04000000         /* transmit CRC */
+#define T_CNF         0x02000000         /* wait for  transmit confirm */
+#define T_LSP         0x01000000         /* Low-speed transaction */
+#define T_PID         0x00c00000         /* packet id */
+#define T_NAK         0x00100000         /* No ack. */
+#define T_STAL        0x00080000         /* Stall received */
+#define T_TO          0x00040000         /* time out */
+#define T_UN          0x00020000         /* underrun */
+
+#define DEVICE_T_ERROR    (T_UN | T_TO)
+#define HOST_T_ERROR      (T_UN | T_TO | T_NAK | T_STAL)
+#define DEVICE_T_BD_MASK  DEVICE_T_ERROR
+#define HOST_T_BD_MASK    HOST_T_ERROR
+
+#define T_PID_SHIFT   6
+#define T_PID_DATA0   0x00800000         /* Data 0 toggle */
+#define T_PID_DATA1   0x00c00000         /* Data 1 toggle */
+
+/*
+ * receive BD's status
+ */
+#define R_E           0x80000000         /* buffer empty */
+#define R_W           0x20000000         /* wrap bit */
+#define R_I           0x10000000         /* interrupt on reception */
+#define R_L           0x08000000         /* last */
+#define R_F           0x04000000         /* first */
+#define R_PID         0x00c00000         /* packet id */
+#define R_NO          0x00100000         /* Rx Non Octet Aligned Packet */
+#define R_AB          0x00080000         /* Frame Aborted */
+#define R_CR          0x00040000         /* CRC Error */
+#define R_OV          0x00020000         /* Overrun */
+
+#define R_ERROR       (R_NO | R_AB | R_CR | R_OV)
+#define R_BD_MASK     R_ERROR
+
+#define R_PID_DATA0   0x00000000
+#define R_PID_DATA1   0x00400000
+#define R_PID_SETUP   0x00800000
+
+#define CPM_USB_STOP_TX 0x2e600000
+#define CPM_USB_RESTART_TX 0x2e600000
+#define CPM_USB_STOP_TX_OPCODE 0x0a
+#define CPM_USB_RESTART_TX_OPCODE 0x0b
+#define CPM_USB_EP_SHIFT 5
+
+#endif  /* __FSL_QE_UDC_H */
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c
new file mode 100644 (file)
index 0000000..57944ee
--- /dev/null
@@ -0,0 +1,2682 @@
+/*
+ * Copyright (C) 2004-2007,2011-2012 Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Author: Li Yang <leoli@freescale.com>
+ *         Jiang Bo <tanya.jiang@freescale.com>
+ *
+ * Description:
+ * Freescale high-speed USB SOC DR module device controller driver.
+ * This can be found on MPC8349E/MPC8313E/MPC5121E cpus.
+ * The driver is previously named as mpc_udc.  Based on bare board
+ * code from Dave Liu and Shlomi Gridish.
+ *
+ * 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.
+ */
+
+#undef VERBOSE
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/mm.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/dmapool.h>
+#include <linux/delay.h>
+#include <linux/of_device.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/unaligned.h>
+#include <asm/dma.h>
+
+#include "fsl_usb2_udc.h"
+
+#define        DRIVER_DESC     "Freescale High-Speed USB SOC Device Controller driver"
+#define        DRIVER_AUTHOR   "Li Yang/Jiang Bo"
+#define        DRIVER_VERSION  "Apr 20, 2007"
+
+#define        DMA_ADDR_INVALID        (~(dma_addr_t)0)
+
+static const char driver_name[] = "fsl-usb2-udc";
+static const char driver_desc[] = DRIVER_DESC;
+
+static struct usb_dr_device *dr_regs;
+
+static struct usb_sys_interface *usb_sys_regs;
+
+/* it is initialized in probe()  */
+static struct fsl_udc *udc_controller = NULL;
+
+static const struct usb_endpoint_descriptor
+fsl_ep0_desc = {
+       .bLength =              USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bEndpointAddress =     0,
+       .bmAttributes =         USB_ENDPOINT_XFER_CONTROL,
+       .wMaxPacketSize =       USB_MAX_CTRL_PAYLOAD,
+};
+
+static void fsl_ep_fifo_flush(struct usb_ep *_ep);
+
+#ifdef CONFIG_PPC32
+/*
+ * On some SoCs, the USB controller registers can be big or little endian,
+ * depending on the version of the chip. In order to be able to run the
+ * same kernel binary on 2 different versions of an SoC, the BE/LE decision
+ * must be made at run time. _fsl_readl and fsl_writel are pointers to the
+ * BE or LE readl() and writel() functions, and fsl_readl() and fsl_writel()
+ * call through those pointers. Platform code for SoCs that have BE USB
+ * registers should set pdata->big_endian_mmio flag.
+ *
+ * This also applies to controller-to-cpu accessors for the USB descriptors,
+ * since their endianness is also SoC dependant. Platform code for SoCs that
+ * have BE USB descriptors should set pdata->big_endian_desc flag.
+ */
+static u32 _fsl_readl_be(const unsigned __iomem *p)
+{
+       return in_be32(p);
+}
+
+static u32 _fsl_readl_le(const unsigned __iomem *p)
+{
+       return in_le32(p);
+}
+
+static void _fsl_writel_be(u32 v, unsigned __iomem *p)
+{
+       out_be32(p, v);
+}
+
+static void _fsl_writel_le(u32 v, unsigned __iomem *p)
+{
+       out_le32(p, v);
+}
+
+static u32 (*_fsl_readl)(const unsigned __iomem *p);
+static void (*_fsl_writel)(u32 v, unsigned __iomem *p);
+
+#define fsl_readl(p)           (*_fsl_readl)((p))
+#define fsl_writel(v, p)       (*_fsl_writel)((v), (p))
+
+static inline void fsl_set_accessors(struct fsl_usb2_platform_data *pdata)
+{
+       if (pdata->big_endian_mmio) {
+               _fsl_readl = _fsl_readl_be;
+               _fsl_writel = _fsl_writel_be;
+       } else {
+               _fsl_readl = _fsl_readl_le;
+               _fsl_writel = _fsl_writel_le;
+       }
+}
+
+static inline u32 cpu_to_hc32(const u32 x)
+{
+       return udc_controller->pdata->big_endian_desc
+               ? (__force u32)cpu_to_be32(x)
+               : (__force u32)cpu_to_le32(x);
+}
+
+static inline u32 hc32_to_cpu(const u32 x)
+{
+       return udc_controller->pdata->big_endian_desc
+               ? be32_to_cpu((__force __be32)x)
+               : le32_to_cpu((__force __le32)x);
+}
+#else /* !CONFIG_PPC32 */
+static inline void fsl_set_accessors(struct fsl_usb2_platform_data *pdata) {}
+
+#define fsl_readl(addr)                readl(addr)
+#define fsl_writel(val32, addr) writel(val32, addr)
+#define cpu_to_hc32(x)         cpu_to_le32(x)
+#define hc32_to_cpu(x)         le32_to_cpu(x)
+#endif /* CONFIG_PPC32 */
+
+/********************************************************************
+ *     Internal Used Function
+********************************************************************/
+/*-----------------------------------------------------------------
+ * done() - retire a request; caller blocked irqs
+ * @status : request status to be set, only works when
+ *     request is still in progress.
+ *--------------------------------------------------------------*/
+static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
+{
+       struct fsl_udc *udc = NULL;
+       unsigned char stopped = ep->stopped;
+       struct ep_td_struct *curr_td, *next_td;
+       int j;
+
+       udc = (struct fsl_udc *)ep->udc;
+       /* Removed the req from fsl_ep->queue */
+       list_del_init(&req->queue);
+
+       /* req.status should be set as -EINPROGRESS in ep_queue() */
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       /* Free dtd for the request */
+       next_td = req->head;
+       for (j = 0; j < req->dtd_count; j++) {
+               curr_td = next_td;
+               if (j != req->dtd_count - 1) {
+                       next_td = curr_td->next_td_virt;
+               }
+               dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
+       }
+
+       usb_gadget_unmap_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+
+       if (status && (status != -ESHUTDOWN))
+               VDBG("complete %s req %p stat %d len %u/%u",
+                       ep->ep.name, &req->req, status,
+                       req->req.actual, req->req.length);
+
+       ep->stopped = 1;
+
+       spin_unlock(&ep->udc->lock);
+       /* complete() is from gadget layer,
+        * eg fsg->bulk_in_complete() */
+       if (req->req.complete)
+               req->req.complete(&ep->ep, &req->req);
+
+       spin_lock(&ep->udc->lock);
+       ep->stopped = stopped;
+}
+
+/*-----------------------------------------------------------------
+ * nuke(): delete all requests related to this ep
+ * called with spinlock held
+ *--------------------------------------------------------------*/
+static void nuke(struct fsl_ep *ep, int status)
+{
+       ep->stopped = 1;
+
+       /* Flush fifo */
+       fsl_ep_fifo_flush(&ep->ep);
+
+       /* Whether this eq has request linked */
+       while (!list_empty(&ep->queue)) {
+               struct fsl_req *req = NULL;
+
+               req = list_entry(ep->queue.next, struct fsl_req, queue);
+               done(ep, req, status);
+       }
+}
+
+/*------------------------------------------------------------------
+       Internal Hardware related function
+ ------------------------------------------------------------------*/
+
+static int dr_controller_setup(struct fsl_udc *udc)
+{
+       unsigned int tmp, portctrl, ep_num;
+       unsigned int max_no_of_ep;
+       unsigned int ctrl;
+       unsigned long timeout;
+
+#define FSL_UDC_RESET_TIMEOUT 1000
+
+       /* Config PHY interface */
+       portctrl = fsl_readl(&dr_regs->portsc1);
+       portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH);
+       switch (udc->phy_mode) {
+       case FSL_USB2_PHY_ULPI:
+               if (udc->pdata->have_sysif_regs) {
+                       if (udc->pdata->controller_ver) {
+                               /* controller version 1.6 or above */
+                               ctrl = __raw_readl(&usb_sys_regs->control);
+                               ctrl &= ~USB_CTRL_UTMI_PHY_EN;
+                               ctrl |= USB_CTRL_USB_EN;
+                               __raw_writel(ctrl, &usb_sys_regs->control);
+                       }
+               }
+               portctrl |= PORTSCX_PTS_ULPI;
+               break;
+       case FSL_USB2_PHY_UTMI_WIDE:
+               portctrl |= PORTSCX_PTW_16BIT;
+               /* fall through */
+       case FSL_USB2_PHY_UTMI:
+               if (udc->pdata->have_sysif_regs) {
+                       if (udc->pdata->controller_ver) {
+                               /* controller version 1.6 or above */
+                               ctrl = __raw_readl(&usb_sys_regs->control);
+                               ctrl |= (USB_CTRL_UTMI_PHY_EN |
+                                       USB_CTRL_USB_EN);
+                               __raw_writel(ctrl, &usb_sys_regs->control);
+                               mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI
+                                       PHY CLK to become stable - 10ms*/
+                       }
+               }
+               portctrl |= PORTSCX_PTS_UTMI;
+               break;
+       case FSL_USB2_PHY_SERIAL:
+               portctrl |= PORTSCX_PTS_FSLS;
+               break;
+       default:
+               return -EINVAL;
+       }
+       fsl_writel(portctrl, &dr_regs->portsc1);
+
+       /* Stop and reset the usb controller */
+       tmp = fsl_readl(&dr_regs->usbcmd);
+       tmp &= ~USB_CMD_RUN_STOP;
+       fsl_writel(tmp, &dr_regs->usbcmd);
+
+       tmp = fsl_readl(&dr_regs->usbcmd);
+       tmp |= USB_CMD_CTRL_RESET;
+       fsl_writel(tmp, &dr_regs->usbcmd);
+
+       /* Wait for reset to complete */
+       timeout = jiffies + FSL_UDC_RESET_TIMEOUT;
+       while (fsl_readl(&dr_regs->usbcmd) & USB_CMD_CTRL_RESET) {
+               if (time_after(jiffies, timeout)) {
+                       ERR("udc reset timeout!\n");
+                       return -ETIMEDOUT;
+               }
+               cpu_relax();
+       }
+
+       /* Set the controller as device mode */
+       tmp = fsl_readl(&dr_regs->usbmode);
+       tmp &= ~USB_MODE_CTRL_MODE_MASK;        /* clear mode bits */
+       tmp |= USB_MODE_CTRL_MODE_DEVICE;
+       /* Disable Setup Lockout */
+       tmp |= USB_MODE_SETUP_LOCK_OFF;
+       if (udc->pdata->es)
+               tmp |= USB_MODE_ES;
+       fsl_writel(tmp, &dr_regs->usbmode);
+
+       /* Clear the setup status */
+       fsl_writel(0, &dr_regs->usbsts);
+
+       tmp = udc->ep_qh_dma;
+       tmp &= USB_EP_LIST_ADDRESS_MASK;
+       fsl_writel(tmp, &dr_regs->endpointlistaddr);
+
+       VDBG("vir[qh_base] is %p phy[qh_base] is 0x%8x reg is 0x%8x",
+               udc->ep_qh, (int)tmp,
+               fsl_readl(&dr_regs->endpointlistaddr));
+
+       max_no_of_ep = (0x0000001F & fsl_readl(&dr_regs->dccparams));
+       for (ep_num = 1; ep_num < max_no_of_ep; ep_num++) {
+               tmp = fsl_readl(&dr_regs->endptctrl[ep_num]);
+               tmp &= ~(EPCTRL_TX_TYPE | EPCTRL_RX_TYPE);
+               tmp |= (EPCTRL_EP_TYPE_BULK << EPCTRL_TX_EP_TYPE_SHIFT)
+               | (EPCTRL_EP_TYPE_BULK << EPCTRL_RX_EP_TYPE_SHIFT);
+               fsl_writel(tmp, &dr_regs->endptctrl[ep_num]);
+       }
+       /* Config control enable i/o output, cpu endian register */
+#ifndef CONFIG_ARCH_MXC
+       if (udc->pdata->have_sysif_regs) {
+               ctrl = __raw_readl(&usb_sys_regs->control);
+               ctrl |= USB_CTRL_IOENB;
+               __raw_writel(ctrl, &usb_sys_regs->control);
+       }
+#endif
+
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+       /* Turn on cache snooping hardware, since some PowerPC platforms
+        * wholly rely on hardware to deal with cache coherent. */
+
+       if (udc->pdata->have_sysif_regs) {
+               /* Setup Snooping for all the 4GB space */
+               tmp = SNOOP_SIZE_2GB;   /* starts from 0x0, size 2G */
+               __raw_writel(tmp, &usb_sys_regs->snoop1);
+               tmp |= 0x80000000;      /* starts from 0x8000000, size 2G */
+               __raw_writel(tmp, &usb_sys_regs->snoop2);
+       }
+#endif
+
+       return 0;
+}
+
+/* Enable DR irq and set controller to run state */
+static void dr_controller_run(struct fsl_udc *udc)
+{
+       u32 temp;
+
+       /* Enable DR irq reg */
+       temp = USB_INTR_INT_EN | USB_INTR_ERR_INT_EN
+               | USB_INTR_PTC_DETECT_EN | USB_INTR_RESET_EN
+               | USB_INTR_DEVICE_SUSPEND | USB_INTR_SYS_ERR_EN;
+
+       fsl_writel(temp, &dr_regs->usbintr);
+
+       /* Clear stopped bit */
+       udc->stopped = 0;
+
+       /* Set the controller as device mode */
+       temp = fsl_readl(&dr_regs->usbmode);
+       temp |= USB_MODE_CTRL_MODE_DEVICE;
+       fsl_writel(temp, &dr_regs->usbmode);
+
+       /* Set controller to Run */
+       temp = fsl_readl(&dr_regs->usbcmd);
+       temp |= USB_CMD_RUN_STOP;
+       fsl_writel(temp, &dr_regs->usbcmd);
+}
+
+static void dr_controller_stop(struct fsl_udc *udc)
+{
+       unsigned int tmp;
+
+       pr_debug("%s\n", __func__);
+
+       /* if we're in OTG mode, and the Host is currently using the port,
+        * stop now and don't rip the controller out from under the
+        * ehci driver
+        */
+       if (udc->gadget.is_otg) {
+               if (!(fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID)) {
+                       pr_debug("udc: Leaving early\n");
+                       return;
+               }
+       }
+
+       /* disable all INTR */
+       fsl_writel(0, &dr_regs->usbintr);
+
+       /* Set stopped bit for isr */
+       udc->stopped = 1;
+
+       /* disable IO output */
+/*     usb_sys_regs->control = 0; */
+
+       /* set controller to Stop */
+       tmp = fsl_readl(&dr_regs->usbcmd);
+       tmp &= ~USB_CMD_RUN_STOP;
+       fsl_writel(tmp, &dr_regs->usbcmd);
+}
+
+static void dr_ep_setup(unsigned char ep_num, unsigned char dir,
+                       unsigned char ep_type)
+{
+       unsigned int tmp_epctrl = 0;
+
+       tmp_epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
+       if (dir) {
+               if (ep_num)
+                       tmp_epctrl |= EPCTRL_TX_DATA_TOGGLE_RST;
+               tmp_epctrl |= EPCTRL_TX_ENABLE;
+               tmp_epctrl &= ~EPCTRL_TX_TYPE;
+               tmp_epctrl |= ((unsigned int)(ep_type)
+                               << EPCTRL_TX_EP_TYPE_SHIFT);
+       } else {
+               if (ep_num)
+                       tmp_epctrl |= EPCTRL_RX_DATA_TOGGLE_RST;
+               tmp_epctrl |= EPCTRL_RX_ENABLE;
+               tmp_epctrl &= ~EPCTRL_RX_TYPE;
+               tmp_epctrl |= ((unsigned int)(ep_type)
+                               << EPCTRL_RX_EP_TYPE_SHIFT);
+       }
+
+       fsl_writel(tmp_epctrl, &dr_regs->endptctrl[ep_num]);
+}
+
+static void
+dr_ep_change_stall(unsigned char ep_num, unsigned char dir, int value)
+{
+       u32 tmp_epctrl = 0;
+
+       tmp_epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
+
+       if (value) {
+               /* set the stall bit */
+               if (dir)
+                       tmp_epctrl |= EPCTRL_TX_EP_STALL;
+               else
+                       tmp_epctrl |= EPCTRL_RX_EP_STALL;
+       } else {
+               /* clear the stall bit and reset data toggle */
+               if (dir) {
+                       tmp_epctrl &= ~EPCTRL_TX_EP_STALL;
+                       tmp_epctrl |= EPCTRL_TX_DATA_TOGGLE_RST;
+               } else {
+                       tmp_epctrl &= ~EPCTRL_RX_EP_STALL;
+                       tmp_epctrl |= EPCTRL_RX_DATA_TOGGLE_RST;
+               }
+       }
+       fsl_writel(tmp_epctrl, &dr_regs->endptctrl[ep_num]);
+}
+
+/* Get stall status of a specific ep
+   Return: 0: not stalled; 1:stalled */
+static int dr_ep_get_stall(unsigned char ep_num, unsigned char dir)
+{
+       u32 epctrl;
+
+       epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
+       if (dir)
+               return (epctrl & EPCTRL_TX_EP_STALL) ? 1 : 0;
+       else
+               return (epctrl & EPCTRL_RX_EP_STALL) ? 1 : 0;
+}
+
+/********************************************************************
+       Internal Structure Build up functions
+********************************************************************/
+
+/*------------------------------------------------------------------
+* struct_ep_qh_setup(): set the Endpoint Capabilites field of QH
+ * @zlt: Zero Length Termination Select (1: disable; 0: enable)
+ * @mult: Mult field
+ ------------------------------------------------------------------*/
+static void struct_ep_qh_setup(struct fsl_udc *udc, unsigned char ep_num,
+               unsigned char dir, unsigned char ep_type,
+               unsigned int max_pkt_len,
+               unsigned int zlt, unsigned char mult)
+{
+       struct ep_queue_head *p_QH = &udc->ep_qh[2 * ep_num + dir];
+       unsigned int tmp = 0;
+
+       /* set the Endpoint Capabilites in QH */
+       switch (ep_type) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               /* Interrupt On Setup (IOS). for control ep  */
+               tmp = (max_pkt_len << EP_QUEUE_HEAD_MAX_PKT_LEN_POS)
+                       | EP_QUEUE_HEAD_IOS;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               tmp = (max_pkt_len << EP_QUEUE_HEAD_MAX_PKT_LEN_POS)
+                       | (mult << EP_QUEUE_HEAD_MULT_POS);
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+       case USB_ENDPOINT_XFER_INT:
+               tmp = max_pkt_len << EP_QUEUE_HEAD_MAX_PKT_LEN_POS;
+               break;
+       default:
+               VDBG("error ep type is %d", ep_type);
+               return;
+       }
+       if (zlt)
+               tmp |= EP_QUEUE_HEAD_ZLT_SEL;
+
+       p_QH->max_pkt_length = cpu_to_hc32(tmp);
+       p_QH->next_dtd_ptr = 1;
+       p_QH->size_ioc_int_sts = 0;
+}
+
+/* Setup qh structure and ep register for ep0. */
+static void ep0_setup(struct fsl_udc *udc)
+{
+       /* the intialization of an ep includes: fields in QH, Regs,
+        * fsl_ep struct */
+       struct_ep_qh_setup(udc, 0, USB_RECV, USB_ENDPOINT_XFER_CONTROL,
+                       USB_MAX_CTRL_PAYLOAD, 0, 0);
+       struct_ep_qh_setup(udc, 0, USB_SEND, USB_ENDPOINT_XFER_CONTROL,
+                       USB_MAX_CTRL_PAYLOAD, 0, 0);
+       dr_ep_setup(0, USB_RECV, USB_ENDPOINT_XFER_CONTROL);
+       dr_ep_setup(0, USB_SEND, USB_ENDPOINT_XFER_CONTROL);
+
+       return;
+
+}
+
+/***********************************************************************
+               Endpoint Management Functions
+***********************************************************************/
+
+/*-------------------------------------------------------------------------
+ * when configurations are set, or when interface settings change
+ * for example the do_set_interface() in gadget layer,
+ * the driver will enable or disable the relevant endpoints
+ * ep0 doesn't use this routine. It is always enabled.
+-------------------------------------------------------------------------*/
+static int fsl_ep_enable(struct usb_ep *_ep,
+               const struct usb_endpoint_descriptor *desc)
+{
+       struct fsl_udc *udc = NULL;
+       struct fsl_ep *ep = NULL;
+       unsigned short max = 0;
+       unsigned char mult = 0, zlt;
+       int retval = -EINVAL;
+       unsigned long flags = 0;
+
+       ep = container_of(_ep, struct fsl_ep, ep);
+
+       /* catch various bogus parameters */
+       if (!_ep || !desc
+                       || (desc->bDescriptorType != USB_DT_ENDPOINT))
+               return -EINVAL;
+
+       udc = ep->udc;
+
+       if (!udc->driver || (udc->gadget.speed == USB_SPEED_UNKNOWN))
+               return -ESHUTDOWN;
+
+       max = usb_endpoint_maxp(desc);
+
+       /* Disable automatic zlp generation.  Driver is responsible to indicate
+        * explicitly through req->req.zero.  This is needed to enable multi-td
+        * request. */
+       zlt = 1;
+
+       /* Assume the max packet size from gadget is always correct */
+       switch (desc->bmAttributes & 0x03) {
+       case USB_ENDPOINT_XFER_CONTROL:
+       case USB_ENDPOINT_XFER_BULK:
+       case USB_ENDPOINT_XFER_INT:
+               /* mult = 0.  Execute N Transactions as demonstrated by
+                * the USB variable length packet protocol where N is
+                * computed using the Maximum Packet Length (dQH) and
+                * the Total Bytes field (dTD) */
+               mult = 0;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               /* Calculate transactions needed for high bandwidth iso */
+               mult = (unsigned char)(1 + ((max >> 11) & 0x03));
+               max = max & 0x7ff;      /* bit 0~10 */
+               /* 3 transactions at most */
+               if (mult > 3)
+                       goto en_done;
+               break;
+       default:
+               goto en_done;
+       }
+
+       spin_lock_irqsave(&udc->lock, flags);
+       ep->ep.maxpacket = max;
+       ep->ep.desc = desc;
+       ep->stopped = 0;
+
+       /* Controller related setup */
+       /* Init EPx Queue Head (Ep Capabilites field in QH
+        * according to max, zlt, mult) */
+       struct_ep_qh_setup(udc, (unsigned char) ep_index(ep),
+                       (unsigned char) ((desc->bEndpointAddress & USB_DIR_IN)
+                                       ?  USB_SEND : USB_RECV),
+                       (unsigned char) (desc->bmAttributes
+                                       & USB_ENDPOINT_XFERTYPE_MASK),
+                       max, zlt, mult);
+
+       /* Init endpoint ctrl register */
+       dr_ep_setup((unsigned char) ep_index(ep),
+                       (unsigned char) ((desc->bEndpointAddress & USB_DIR_IN)
+                                       ? USB_SEND : USB_RECV),
+                       (unsigned char) (desc->bmAttributes
+                                       & USB_ENDPOINT_XFERTYPE_MASK));
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       retval = 0;
+
+       VDBG("enabled %s (ep%d%s) maxpacket %d",ep->ep.name,
+                       ep->ep.desc->bEndpointAddress & 0x0f,
+                       (desc->bEndpointAddress & USB_DIR_IN)
+                               ? "in" : "out", max);
+en_done:
+       return retval;
+}
+
+/*---------------------------------------------------------------------
+ * @ep : the ep being unconfigured. May not be ep0
+ * Any pending and uncomplete req will complete with status (-ESHUTDOWN)
+*---------------------------------------------------------------------*/
+static int fsl_ep_disable(struct usb_ep *_ep)
+{
+       struct fsl_udc *udc = NULL;
+       struct fsl_ep *ep = NULL;
+       unsigned long flags = 0;
+       u32 epctrl;
+       int ep_num;
+
+       ep = container_of(_ep, struct fsl_ep, ep);
+       if (!_ep || !ep->ep.desc) {
+               VDBG("%s not enabled", _ep ? ep->ep.name : NULL);
+               return -EINVAL;
+       }
+
+       /* disable ep on controller */
+       ep_num = ep_index(ep);
+       epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
+       if (ep_is_in(ep)) {
+               epctrl &= ~(EPCTRL_TX_ENABLE | EPCTRL_TX_TYPE);
+               epctrl |= EPCTRL_EP_TYPE_BULK << EPCTRL_TX_EP_TYPE_SHIFT;
+       } else {
+               epctrl &= ~(EPCTRL_RX_ENABLE | EPCTRL_TX_TYPE);
+               epctrl |= EPCTRL_EP_TYPE_BULK << EPCTRL_RX_EP_TYPE_SHIFT;
+       }
+       fsl_writel(epctrl, &dr_regs->endptctrl[ep_num]);
+
+       udc = (struct fsl_udc *)ep->udc;
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /* nuke all pending requests (does flush) */
+       nuke(ep, -ESHUTDOWN);
+
+       ep->ep.desc = NULL;
+       ep->stopped = 1;
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       VDBG("disabled %s OK", _ep->name);
+       return 0;
+}
+
+/*---------------------------------------------------------------------
+ * allocate a request object used by this endpoint
+ * the main operation is to insert the req->queue to the eq->queue
+ * Returns the request, or null if one could not be allocated
+*---------------------------------------------------------------------*/
+static struct usb_request *
+fsl_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct fsl_req *req = NULL;
+
+       req = kzalloc(sizeof *req, gfp_flags);
+       if (!req)
+               return NULL;
+
+       req->req.dma = DMA_ADDR_INVALID;
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void fsl_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct fsl_req *req = NULL;
+
+       req = container_of(_req, struct fsl_req, req);
+
+       if (_req)
+               kfree(req);
+}
+
+/* Actually add a dTD chain to an empty dQH and let go */
+static void fsl_prime_ep(struct fsl_ep *ep, struct ep_td_struct *td)
+{
+       struct ep_queue_head *qh = get_qh_by_ep(ep);
+
+       /* Write dQH next pointer and terminate bit to 0 */
+       qh->next_dtd_ptr = cpu_to_hc32(td->td_dma
+                       & EP_QUEUE_HEAD_NEXT_POINTER_MASK);
+
+       /* Clear active and halt bit */
+       qh->size_ioc_int_sts &= cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE
+                                       | EP_QUEUE_HEAD_STATUS_HALT));
+
+       /* Ensure that updates to the QH will occur before priming. */
+       wmb();
+
+       /* Prime endpoint by writing correct bit to ENDPTPRIME */
+       fsl_writel(ep_is_in(ep) ? (1 << (ep_index(ep) + 16))
+                       : (1 << (ep_index(ep))), &dr_regs->endpointprime);
+}
+
+/* Add dTD chain to the dQH of an EP */
+static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
+{
+       u32 temp, bitmask, tmp_stat;
+
+       /* VDBG("QH addr Register 0x%8x", dr_regs->endpointlistaddr);
+       VDBG("ep_qh[%d] addr is 0x%8x", i, (u32)&(ep->udc->ep_qh[i])); */
+
+       bitmask = ep_is_in(ep)
+               ? (1 << (ep_index(ep) + 16))
+               : (1 << (ep_index(ep)));
+
+       /* check if the pipe is empty */
+       if (!(list_empty(&ep->queue)) && !(ep_index(ep) == 0)) {
+               /* Add td to the end */
+               struct fsl_req *lastreq;
+               lastreq = list_entry(ep->queue.prev, struct fsl_req, queue);
+               lastreq->tail->next_td_ptr =
+                       cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK);
+               /* Ensure dTD's next dtd pointer to be updated */
+               wmb();
+               /* Read prime bit, if 1 goto done */
+               if (fsl_readl(&dr_regs->endpointprime) & bitmask)
+                       return;
+
+               do {
+                       /* Set ATDTW bit in USBCMD */
+                       temp = fsl_readl(&dr_regs->usbcmd);
+                       fsl_writel(temp | USB_CMD_ATDTW, &dr_regs->usbcmd);
+
+                       /* Read correct status bit */
+                       tmp_stat = fsl_readl(&dr_regs->endptstatus) & bitmask;
+
+               } while (!(fsl_readl(&dr_regs->usbcmd) & USB_CMD_ATDTW));
+
+               /* Write ATDTW bit to 0 */
+               temp = fsl_readl(&dr_regs->usbcmd);
+               fsl_writel(temp & ~USB_CMD_ATDTW, &dr_regs->usbcmd);
+
+               if (tmp_stat)
+                       return;
+       }
+
+       fsl_prime_ep(ep, req->head);
+}
+
+/* Fill in the dTD structure
+ * @req: request that the transfer belongs to
+ * @length: return actually data length of the dTD
+ * @dma: return dma address of the dTD
+ * @is_last: return flag if it is the last dTD of the request
+ * return: pointer to the built dTD */
+static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
+               dma_addr_t *dma, int *is_last, gfp_t gfp_flags)
+{
+       u32 swap_temp;
+       struct ep_td_struct *dtd;
+
+       /* how big will this transfer be? */
+       *length = min(req->req.length - req->req.actual,
+                       (unsigned)EP_MAX_LENGTH_TRANSFER);
+
+       dtd = dma_pool_alloc(udc_controller->td_pool, gfp_flags, dma);
+       if (dtd == NULL)
+               return dtd;
+
+       dtd->td_dma = *dma;
+       /* Clear reserved field */
+       swap_temp = hc32_to_cpu(dtd->size_ioc_sts);
+       swap_temp &= ~DTD_RESERVED_FIELDS;
+       dtd->size_ioc_sts = cpu_to_hc32(swap_temp);
+
+       /* Init all of buffer page pointers */
+       swap_temp = (u32) (req->req.dma + req->req.actual);
+       dtd->buff_ptr0 = cpu_to_hc32(swap_temp);
+       dtd->buff_ptr1 = cpu_to_hc32(swap_temp + 0x1000);
+       dtd->buff_ptr2 = cpu_to_hc32(swap_temp + 0x2000);
+       dtd->buff_ptr3 = cpu_to_hc32(swap_temp + 0x3000);
+       dtd->buff_ptr4 = cpu_to_hc32(swap_temp + 0x4000);
+
+       req->req.actual += *length;
+
+       /* zlp is needed if req->req.zero is set */
+       if (req->req.zero) {
+               if (*length == 0 || (*length % req->ep->ep.maxpacket) != 0)
+                       *is_last = 1;
+               else
+                       *is_last = 0;
+       } else if (req->req.length == req->req.actual)
+               *is_last = 1;
+       else
+               *is_last = 0;
+
+       if ((*is_last) == 0)
+               VDBG("multi-dtd request!");
+       /* Fill in the transfer size; set active bit */
+       swap_temp = ((*length << DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE);
+
+       /* Enable interrupt for the last dtd of a request */
+       if (*is_last && !req->req.no_interrupt)
+               swap_temp |= DTD_IOC;
+
+       dtd->size_ioc_sts = cpu_to_hc32(swap_temp);
+
+       mb();
+
+       VDBG("length = %d address= 0x%x", *length, (int)*dma);
+
+       return dtd;
+}
+
+/* Generate dtd chain for a request */
+static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags)
+{
+       unsigned        count;
+       int             is_last;
+       int             is_first =1;
+       struct ep_td_struct     *last_dtd = NULL, *dtd;
+       dma_addr_t dma;
+
+       do {
+               dtd = fsl_build_dtd(req, &count, &dma, &is_last, gfp_flags);
+               if (dtd == NULL)
+                       return -ENOMEM;
+
+               if (is_first) {
+                       is_first = 0;
+                       req->head = dtd;
+               } else {
+                       last_dtd->next_td_ptr = cpu_to_hc32(dma);
+                       last_dtd->next_td_virt = dtd;
+               }
+               last_dtd = dtd;
+
+               req->dtd_count++;
+       } while (!is_last);
+
+       dtd->next_td_ptr = cpu_to_hc32(DTD_NEXT_TERMINATE);
+
+       req->tail = dtd;
+
+       return 0;
+}
+
+/* queues (submits) an I/O request to an endpoint */
+static int
+fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+       struct fsl_ep *ep = container_of(_ep, struct fsl_ep, ep);
+       struct fsl_req *req = container_of(_req, struct fsl_req, req);
+       struct fsl_udc *udc;
+       unsigned long flags;
+       int ret;
+
+       /* catch various bogus parameters */
+       if (!_req || !req->req.complete || !req->req.buf
+                       || !list_empty(&req->queue)) {
+               VDBG("%s, bad params", __func__);
+               return -EINVAL;
+       }
+       if (unlikely(!_ep || !ep->ep.desc)) {
+               VDBG("%s, bad ep", __func__);
+               return -EINVAL;
+       }
+       if (usb_endpoint_xfer_isoc(ep->ep.desc)) {
+               if (req->req.length > ep->ep.maxpacket)
+                       return -EMSGSIZE;
+       }
+
+       udc = ep->udc;
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       req->ep = ep;
+
+       ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+       if (ret)
+               return ret;
+
+       req->req.status = -EINPROGRESS;
+       req->req.actual = 0;
+       req->dtd_count = 0;
+
+       /* build dtds and push them to device queue */
+       if (!fsl_req_to_dtd(req, gfp_flags)) {
+               spin_lock_irqsave(&udc->lock, flags);
+               fsl_queue_td(ep, req);
+       } else {
+               return -ENOMEM;
+       }
+
+       /* irq handler advances the queue */
+       if (req != NULL)
+               list_add_tail(&req->queue, &ep->queue);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+/* dequeues (cancels, unlinks) an I/O request from an endpoint */
+static int fsl_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct fsl_ep *ep = container_of(_ep, struct fsl_ep, ep);
+       struct fsl_req *req;
+       unsigned long flags;
+       int ep_num, stopped, ret = 0;
+       u32 epctrl;
+
+       if (!_ep || !_req)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+       stopped = ep->stopped;
+
+       /* Stop the ep before we deal with the queue */
+       ep->stopped = 1;
+       ep_num = ep_index(ep);
+       epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
+       if (ep_is_in(ep))
+               epctrl &= ~EPCTRL_TX_ENABLE;
+       else
+               epctrl &= ~EPCTRL_RX_ENABLE;
+       fsl_writel(epctrl, &dr_regs->endptctrl[ep_num]);
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* The request is in progress, or completed but not dequeued */
+       if (ep->queue.next == &req->queue) {
+               _req->status = -ECONNRESET;
+               fsl_ep_fifo_flush(_ep); /* flush current transfer */
+
+               /* The request isn't the last request in this ep queue */
+               if (req->queue.next != &ep->queue) {
+                       struct fsl_req *next_req;
+
+                       next_req = list_entry(req->queue.next, struct fsl_req,
+                                       queue);
+
+                       /* prime with dTD of next request */
+                       fsl_prime_ep(ep, next_req->head);
+               }
+       /* The request hasn't been processed, patch up the TD chain */
+       } else {
+               struct fsl_req *prev_req;
+
+               prev_req = list_entry(req->queue.prev, struct fsl_req, queue);
+               prev_req->tail->next_td_ptr = req->tail->next_td_ptr;
+       }
+
+       done(ep, req, -ECONNRESET);
+
+       /* Enable EP */
+out:   epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
+       if (ep_is_in(ep))
+               epctrl |= EPCTRL_TX_ENABLE;
+       else
+               epctrl |= EPCTRL_RX_ENABLE;
+       fsl_writel(epctrl, &dr_regs->endptctrl[ep_num]);
+       ep->stopped = stopped;
+
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+       return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------
+ * modify the endpoint halt feature
+ * @ep: the non-isochronous endpoint being stalled
+ * @value: 1--set halt  0--clear halt
+ * Returns zero, or a negative error code.
+*----------------------------------------------------------------*/
+static int fsl_ep_set_halt(struct usb_ep *_ep, int value)
+{
+       struct fsl_ep *ep = NULL;
+       unsigned long flags = 0;
+       int status = -EOPNOTSUPP;       /* operation not supported */
+       unsigned char ep_dir = 0, ep_num = 0;
+       struct fsl_udc *udc = NULL;
+
+       ep = container_of(_ep, struct fsl_ep, ep);
+       udc = ep->udc;
+       if (!_ep || !ep->ep.desc) {
+               status = -EINVAL;
+               goto out;
+       }
+
+       if (usb_endpoint_xfer_isoc(ep->ep.desc)) {
+               status = -EOPNOTSUPP;
+               goto out;
+       }
+
+       /* Attempt to halt IN ep will fail if any transfer requests
+        * are still queue */
+       if (value && ep_is_in(ep) && !list_empty(&ep->queue)) {
+               status = -EAGAIN;
+               goto out;
+       }
+
+       status = 0;
+       ep_dir = ep_is_in(ep) ? USB_SEND : USB_RECV;
+       ep_num = (unsigned char)(ep_index(ep));
+       spin_lock_irqsave(&ep->udc->lock, flags);
+       dr_ep_change_stall(ep_num, ep_dir, value);
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+
+       if (ep_index(ep) == 0) {
+               udc->ep0_state = WAIT_FOR_SETUP;
+               udc->ep0_dir = 0;
+       }
+out:
+       VDBG(" %s %s halt stat %d", ep->ep.name,
+                       value ?  "set" : "clear", status);
+
+       return status;
+}
+
+static int fsl_ep_fifo_status(struct usb_ep *_ep)
+{
+       struct fsl_ep *ep;
+       struct fsl_udc *udc;
+       int size = 0;
+       u32 bitmask;
+       struct ep_queue_head *qh;
+
+       ep = container_of(_ep, struct fsl_ep, ep);
+       if (!_ep || (!ep->ep.desc && ep_index(ep) != 0))
+               return -ENODEV;
+
+       udc = (struct fsl_udc *)ep->udc;
+
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       qh = get_qh_by_ep(ep);
+
+       bitmask = (ep_is_in(ep)) ? (1 << (ep_index(ep) + 16)) :
+           (1 << (ep_index(ep)));
+
+       if (fsl_readl(&dr_regs->endptstatus) & bitmask)
+               size = (qh->size_ioc_int_sts & DTD_PACKET_SIZE)
+                   >> DTD_LENGTH_BIT_POS;
+
+       pr_debug("%s %u\n", __func__, size);
+       return size;
+}
+
+static void fsl_ep_fifo_flush(struct usb_ep *_ep)
+{
+       struct fsl_ep *ep;
+       int ep_num, ep_dir;
+       u32 bits;
+       unsigned long timeout;
+#define FSL_UDC_FLUSH_TIMEOUT 1000
+
+       if (!_ep) {
+               return;
+       } else {
+               ep = container_of(_ep, struct fsl_ep, ep);
+               if (!ep->ep.desc)
+                       return;
+       }
+       ep_num = ep_index(ep);
+       ep_dir = ep_is_in(ep) ? USB_SEND : USB_RECV;
+
+       if (ep_num == 0)
+               bits = (1 << 16) | 1;
+       else if (ep_dir == USB_SEND)
+               bits = 1 << (16 + ep_num);
+       else
+               bits = 1 << ep_num;
+
+       timeout = jiffies + FSL_UDC_FLUSH_TIMEOUT;
+       do {
+               fsl_writel(bits, &dr_regs->endptflush);
+
+               /* Wait until flush complete */
+               while (fsl_readl(&dr_regs->endptflush)) {
+                       if (time_after(jiffies, timeout)) {
+                               ERR("ep flush timeout\n");
+                               return;
+                       }
+                       cpu_relax();
+               }
+               /* See if we need to flush again */
+       } while (fsl_readl(&dr_regs->endptstatus) & bits);
+}
+
+static struct usb_ep_ops fsl_ep_ops = {
+       .enable = fsl_ep_enable,
+       .disable = fsl_ep_disable,
+
+       .alloc_request = fsl_alloc_request,
+       .free_request = fsl_free_request,
+
+       .queue = fsl_ep_queue,
+       .dequeue = fsl_ep_dequeue,
+
+       .set_halt = fsl_ep_set_halt,
+       .fifo_status = fsl_ep_fifo_status,
+       .fifo_flush = fsl_ep_fifo_flush,        /* flush fifo */
+};
+
+/*-------------------------------------------------------------------------
+               Gadget Driver Layer Operations
+-------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------
+ * Get the current frame number (from DR frame_index Reg )
+ *----------------------------------------------------------------------*/
+static int fsl_get_frame(struct usb_gadget *gadget)
+{
+       return (int)(fsl_readl(&dr_regs->frindex) & USB_FRINDEX_MASKS);
+}
+
+/*-----------------------------------------------------------------------
+ * Tries to wake up the host connected to this gadget
+ -----------------------------------------------------------------------*/
+static int fsl_wakeup(struct usb_gadget *gadget)
+{
+       struct fsl_udc *udc = container_of(gadget, struct fsl_udc, gadget);
+       u32 portsc;
+
+       /* Remote wakeup feature not enabled by host */
+       if (!udc->remote_wakeup)
+               return -ENOTSUPP;
+
+       portsc = fsl_readl(&dr_regs->portsc1);
+       /* not suspended? */
+       if (!(portsc & PORTSCX_PORT_SUSPEND))
+               return 0;
+       /* trigger force resume */
+       portsc |= PORTSCX_PORT_FORCE_RESUME;
+       fsl_writel(portsc, &dr_regs->portsc1);
+       return 0;
+}
+
+static int can_pullup(struct fsl_udc *udc)
+{
+       return udc->driver && udc->softconnect && udc->vbus_active;
+}
+
+/* Notify controller that VBUS is powered, Called by whatever
+   detects VBUS sessions */
+static int fsl_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+       struct fsl_udc  *udc;
+       unsigned long   flags;
+
+       udc = container_of(gadget, struct fsl_udc, gadget);
+       spin_lock_irqsave(&udc->lock, flags);
+       VDBG("VBUS %s", is_active ? "on" : "off");
+       udc->vbus_active = (is_active != 0);
+       if (can_pullup(udc))
+               fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
+                               &dr_regs->usbcmd);
+       else
+               fsl_writel((fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP),
+                               &dr_regs->usbcmd);
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+/* constrain controller's VBUS power usage
+ * This call is used by gadget drivers during SET_CONFIGURATION calls,
+ * reporting how much power the device may consume.  For example, this
+ * could affect how quickly batteries are recharged.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+       struct fsl_udc *udc;
+
+       udc = container_of(gadget, struct fsl_udc, gadget);
+       if (!IS_ERR_OR_NULL(udc->transceiver))
+               return usb_phy_set_power(udc->transceiver, mA);
+       return -ENOTSUPP;
+}
+
+/* Change Data+ pullup status
+ * this func is used by usb_gadget_connect/disconnet
+ */
+static int fsl_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct fsl_udc *udc;
+
+       udc = container_of(gadget, struct fsl_udc, gadget);
+
+       if (!udc->vbus_active)
+               return -EOPNOTSUPP;
+
+       udc->softconnect = (is_on != 0);
+       if (can_pullup(udc))
+               fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
+                               &dr_regs->usbcmd);
+       else
+               fsl_writel((fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP),
+                               &dr_regs->usbcmd);
+
+       return 0;
+}
+
+static int fsl_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+static int fsl_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+/* defined in gadget.h */
+static const struct usb_gadget_ops fsl_gadget_ops = {
+       .get_frame = fsl_get_frame,
+       .wakeup = fsl_wakeup,
+/*     .set_selfpowered = fsl_set_selfpowered, */ /* Always selfpowered */
+       .vbus_session = fsl_vbus_session,
+       .vbus_draw = fsl_vbus_draw,
+       .pullup = fsl_pullup,
+       .udc_start = fsl_udc_start,
+       .udc_stop = fsl_udc_stop,
+};
+
+/* Set protocol stall on ep0, protocol stall will automatically be cleared
+   on new transaction */
+static void ep0stall(struct fsl_udc *udc)
+{
+       u32 tmp;
+
+       /* must set tx and rx to stall at the same time */
+       tmp = fsl_readl(&dr_regs->endptctrl[0]);
+       tmp |= EPCTRL_TX_EP_STALL | EPCTRL_RX_EP_STALL;
+       fsl_writel(tmp, &dr_regs->endptctrl[0]);
+       udc->ep0_state = WAIT_FOR_SETUP;
+       udc->ep0_dir = 0;
+}
+
+/* Prime a status phase for ep0 */
+static int ep0_prime_status(struct fsl_udc *udc, int direction)
+{
+       struct fsl_req *req = udc->status_req;
+       struct fsl_ep *ep;
+       int ret;
+
+       if (direction == EP_DIR_IN)
+               udc->ep0_dir = USB_DIR_IN;
+       else
+               udc->ep0_dir = USB_DIR_OUT;
+
+       ep = &udc->eps[0];
+       if (udc->ep0_state != DATA_STATE_XMIT)
+               udc->ep0_state = WAIT_FOR_OUT_STATUS;
+
+       req->ep = ep;
+       req->req.length = 0;
+       req->req.status = -EINPROGRESS;
+       req->req.actual = 0;
+       req->req.complete = NULL;
+       req->dtd_count = 0;
+
+       ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+       if (ret)
+               return ret;
+
+       if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
+               fsl_queue_td(ep, req);
+       else
+               return -ENOMEM;
+
+       list_add_tail(&req->queue, &ep->queue);
+
+       return 0;
+}
+
+static void udc_reset_ep_queue(struct fsl_udc *udc, u8 pipe)
+{
+       struct fsl_ep *ep = get_ep_by_pipe(udc, pipe);
+
+       if (ep->name)
+               nuke(ep, -ESHUTDOWN);
+}
+
+/*
+ * ch9 Set address
+ */
+static void ch9setaddress(struct fsl_udc *udc, u16 value, u16 index, u16 length)
+{
+       /* Save the new address to device struct */
+       udc->device_address = (u8) value;
+       /* Update usb state */
+       udc->usb_state = USB_STATE_ADDRESS;
+       /* Status phase */
+       if (ep0_prime_status(udc, EP_DIR_IN))
+               ep0stall(udc);
+}
+
+/*
+ * ch9 Get status
+ */
+static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
+               u16 index, u16 length)
+{
+       u16 tmp = 0;            /* Status, cpu endian */
+       struct fsl_req *req;
+       struct fsl_ep *ep;
+       int ret;
+
+       ep = &udc->eps[0];
+
+       if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
+               /* Get device status */
+               tmp = 1 << USB_DEVICE_SELF_POWERED;
+               tmp |= udc->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP;
+       } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) {
+               /* Get interface status */
+               /* We don't have interface information in udc driver */
+               tmp = 0;
+       } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_ENDPOINT) {
+               /* Get endpoint status */
+               struct fsl_ep *target_ep;
+
+               target_ep = get_ep_by_pipe(udc, get_pipe_by_windex(index));
+
+               /* stall if endpoint doesn't exist */
+               if (!target_ep->ep.desc)
+                       goto stall;
+               tmp = dr_ep_get_stall(ep_index(target_ep), ep_is_in(target_ep))
+                               << USB_ENDPOINT_HALT;
+       }
+
+       udc->ep0_dir = USB_DIR_IN;
+       /* Borrow the per device status_req */
+       req = udc->status_req;
+       /* Fill in the reqest structure */
+       *((u16 *) req->req.buf) = cpu_to_le16(tmp);
+
+       req->ep = ep;
+       req->req.length = 2;
+       req->req.status = -EINPROGRESS;
+       req->req.actual = 0;
+       req->req.complete = NULL;
+       req->dtd_count = 0;
+
+       ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+       if (ret)
+               goto stall;
+
+       /* prime the data phase */
+       if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
+               fsl_queue_td(ep, req);
+       else                    /* no mem */
+               goto stall;
+
+       list_add_tail(&req->queue, &ep->queue);
+       udc->ep0_state = DATA_STATE_XMIT;
+       if (ep0_prime_status(udc, EP_DIR_OUT))
+               ep0stall(udc);
+
+       return;
+stall:
+       ep0stall(udc);
+}
+
+static void setup_received_irq(struct fsl_udc *udc,
+               struct usb_ctrlrequest *setup)
+{
+       u16 wValue = le16_to_cpu(setup->wValue);
+       u16 wIndex = le16_to_cpu(setup->wIndex);
+       u16 wLength = le16_to_cpu(setup->wLength);
+
+       udc_reset_ep_queue(udc, 0);
+
+       /* We process some stardard setup requests here */
+       switch (setup->bRequest) {
+       case USB_REQ_GET_STATUS:
+               /* Data+Status phase from udc */
+               if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
+                                       != (USB_DIR_IN | USB_TYPE_STANDARD))
+                       break;
+               ch9getstatus(udc, setup->bRequestType, wValue, wIndex, wLength);
+               return;
+
+       case USB_REQ_SET_ADDRESS:
+               /* Status phase from udc */
+               if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD
+                                               | USB_RECIP_DEVICE))
+                       break;
+               ch9setaddress(udc, wValue, wIndex, wLength);
+               return;
+
+       case USB_REQ_CLEAR_FEATURE:
+       case USB_REQ_SET_FEATURE:
+               /* Status phase from udc */
+       {
+               int rc = -EOPNOTSUPP;
+               u16 ptc = 0;
+
+               if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK))
+                               == (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) {
+                       int pipe = get_pipe_by_windex(wIndex);
+                       struct fsl_ep *ep;
+
+                       if (wValue != 0 || wLength != 0 || pipe >= udc->max_ep)
+                               break;
+                       ep = get_ep_by_pipe(udc, pipe);
+
+                       spin_unlock(&udc->lock);
+                       rc = fsl_ep_set_halt(&ep->ep,
+                                       (setup->bRequest == USB_REQ_SET_FEATURE)
+                                               ? 1 : 0);
+                       spin_lock(&udc->lock);
+
+               } else if ((setup->bRequestType & (USB_RECIP_MASK
+                               | USB_TYPE_MASK)) == (USB_RECIP_DEVICE
+                               | USB_TYPE_STANDARD)) {
+                       /* Note: The driver has not include OTG support yet.
+                        * This will be set when OTG support is added */
+                       if (wValue == USB_DEVICE_TEST_MODE)
+                               ptc = wIndex >> 8;
+                       else if (gadget_is_otg(&udc->gadget)) {
+                               if (setup->bRequest ==
+                                   USB_DEVICE_B_HNP_ENABLE)
+                                       udc->gadget.b_hnp_enable = 1;
+                               else if (setup->bRequest ==
+                                        USB_DEVICE_A_HNP_SUPPORT)
+                                       udc->gadget.a_hnp_support = 1;
+                               else if (setup->bRequest ==
+                                        USB_DEVICE_A_ALT_HNP_SUPPORT)
+                                       udc->gadget.a_alt_hnp_support = 1;
+                       }
+                       rc = 0;
+               } else
+                       break;
+
+               if (rc == 0) {
+                       if (ep0_prime_status(udc, EP_DIR_IN))
+                               ep0stall(udc);
+               }
+               if (ptc) {
+                       u32 tmp;
+
+                       mdelay(10);
+                       tmp = fsl_readl(&dr_regs->portsc1) | (ptc << 16);
+                       fsl_writel(tmp, &dr_regs->portsc1);
+                       printk(KERN_INFO "udc: switch to test mode %d.\n", ptc);
+               }
+
+               return;
+       }
+
+       default:
+               break;
+       }
+
+       /* Requests handled by gadget */
+       if (wLength) {
+               /* Data phase from gadget, status phase from udc */
+               udc->ep0_dir = (setup->bRequestType & USB_DIR_IN)
+                               ?  USB_DIR_IN : USB_DIR_OUT;
+               spin_unlock(&udc->lock);
+               if (udc->driver->setup(&udc->gadget,
+                               &udc->local_setup_buff) < 0)
+                       ep0stall(udc);
+               spin_lock(&udc->lock);
+               udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
+                               ?  DATA_STATE_XMIT : DATA_STATE_RECV;
+               /*
+                * If the data stage is IN, send status prime immediately.
+                * See 2.0 Spec chapter 8.5.3.3 for detail.
+                */
+               if (udc->ep0_state == DATA_STATE_XMIT)
+                       if (ep0_prime_status(udc, EP_DIR_OUT))
+                               ep0stall(udc);
+
+       } else {
+               /* No data phase, IN status from gadget */
+               udc->ep0_dir = USB_DIR_IN;
+               spin_unlock(&udc->lock);
+               if (udc->driver->setup(&udc->gadget,
+                               &udc->local_setup_buff) < 0)
+                       ep0stall(udc);
+               spin_lock(&udc->lock);
+               udc->ep0_state = WAIT_FOR_OUT_STATUS;
+       }
+}
+
+/* Process request for Data or Status phase of ep0
+ * prime status phase if needed */
+static void ep0_req_complete(struct fsl_udc *udc, struct fsl_ep *ep0,
+               struct fsl_req *req)
+{
+       if (udc->usb_state == USB_STATE_ADDRESS) {
+               /* Set the new address */
+               u32 new_address = (u32) udc->device_address;
+               fsl_writel(new_address << USB_DEVICE_ADDRESS_BIT_POS,
+                               &dr_regs->deviceaddr);
+       }
+
+       done(ep0, req, 0);
+
+       switch (udc->ep0_state) {
+       case DATA_STATE_XMIT:
+               /* already primed at setup_received_irq */
+               udc->ep0_state = WAIT_FOR_OUT_STATUS;
+               break;
+       case DATA_STATE_RECV:
+               /* send status phase */
+               if (ep0_prime_status(udc, EP_DIR_IN))
+                       ep0stall(udc);
+               break;
+       case WAIT_FOR_OUT_STATUS:
+               udc->ep0_state = WAIT_FOR_SETUP;
+               break;
+       case WAIT_FOR_SETUP:
+               ERR("Unexpect ep0 packets\n");
+               break;
+       default:
+               ep0stall(udc);
+               break;
+       }
+}
+
+/* Tripwire mechanism to ensure a setup packet payload is extracted without
+ * being corrupted by another incoming setup packet */
+static void tripwire_handler(struct fsl_udc *udc, u8 ep_num, u8 *buffer_ptr)
+{
+       u32 temp;
+       struct ep_queue_head *qh;
+       struct fsl_usb2_platform_data *pdata = udc->pdata;
+
+       qh = &udc->ep_qh[ep_num * 2 + EP_DIR_OUT];
+
+       /* Clear bit in ENDPTSETUPSTAT */
+       temp = fsl_readl(&dr_regs->endptsetupstat);
+       fsl_writel(temp | (1 << ep_num), &dr_regs->endptsetupstat);
+
+       /* while a hazard exists when setup package arrives */
+       do {
+               /* Set Setup Tripwire */
+               temp = fsl_readl(&dr_regs->usbcmd);
+               fsl_writel(temp | USB_CMD_SUTW, &dr_regs->usbcmd);
+
+               /* Copy the setup packet to local buffer */
+               if (pdata->le_setup_buf) {
+                       u32 *p = (u32 *)buffer_ptr;
+                       u32 *s = (u32 *)qh->setup_buffer;
+
+                       /* Convert little endian setup buffer to CPU endian */
+                       *p++ = le32_to_cpu(*s++);
+                       *p = le32_to_cpu(*s);
+               } else {
+                       memcpy(buffer_ptr, (u8 *) qh->setup_buffer, 8);
+               }
+       } while (!(fsl_readl(&dr_regs->usbcmd) & USB_CMD_SUTW));
+
+       /* Clear Setup Tripwire */
+       temp = fsl_readl(&dr_regs->usbcmd);
+       fsl_writel(temp & ~USB_CMD_SUTW, &dr_regs->usbcmd);
+}
+
+/* process-ep_req(): free the completed Tds for this req */
+static int process_ep_req(struct fsl_udc *udc, int pipe,
+               struct fsl_req *curr_req)
+{
+       struct ep_td_struct *curr_td;
+       int     td_complete, actual, remaining_length, j, tmp;
+       int     status = 0;
+       int     errors = 0;
+       struct  ep_queue_head *curr_qh = &udc->ep_qh[pipe];
+       int direction = pipe % 2;
+
+       curr_td = curr_req->head;
+       td_complete = 0;
+       actual = curr_req->req.length;
+
+       for (j = 0; j < curr_req->dtd_count; j++) {
+               remaining_length = (hc32_to_cpu(curr_td->size_ioc_sts)
+                                       & DTD_PACKET_SIZE)
+                               >> DTD_LENGTH_BIT_POS;
+               actual -= remaining_length;
+
+               errors = hc32_to_cpu(curr_td->size_ioc_sts);
+               if (errors & DTD_ERROR_MASK) {
+                       if (errors & DTD_STATUS_HALTED) {
+                               ERR("dTD error %08x QH=%d\n", errors, pipe);
+                               /* Clear the errors and Halt condition */
+                               tmp = hc32_to_cpu(curr_qh->size_ioc_int_sts);
+                               tmp &= ~errors;
+                               curr_qh->size_ioc_int_sts = cpu_to_hc32(tmp);
+                               status = -EPIPE;
+                               /* FIXME: continue with next queued TD? */
+
+                               break;
+                       }
+                       if (errors & DTD_STATUS_DATA_BUFF_ERR) {
+                               VDBG("Transfer overflow");
+                               status = -EPROTO;
+                               break;
+                       } else if (errors & DTD_STATUS_TRANSACTION_ERR) {
+                               VDBG("ISO error");
+                               status = -EILSEQ;
+                               break;
+                       } else
+                               ERR("Unknown error has occurred (0x%x)!\n",
+                                       errors);
+
+               } else if (hc32_to_cpu(curr_td->size_ioc_sts)
+                               & DTD_STATUS_ACTIVE) {
+                       VDBG("Request not complete");
+                       status = REQ_UNCOMPLETE;
+                       return status;
+               } else if (remaining_length) {
+                       if (direction) {
+                               VDBG("Transmit dTD remaining length not zero");
+                               status = -EPROTO;
+                               break;
+                       } else {
+                               td_complete++;
+                               break;
+                       }
+               } else {
+                       td_complete++;
+                       VDBG("dTD transmitted successful");
+               }
+
+               if (j != curr_req->dtd_count - 1)
+                       curr_td = (struct ep_td_struct *)curr_td->next_td_virt;
+       }
+
+       if (status)
+               return status;
+
+       curr_req->req.actual = actual;
+
+       return 0;
+}
+
+/* Process a DTD completion interrupt */
+static void dtd_complete_irq(struct fsl_udc *udc)
+{
+       u32 bit_pos;
+       int i, ep_num, direction, bit_mask, status;
+       struct fsl_ep *curr_ep;
+       struct fsl_req *curr_req, *temp_req;
+
+       /* Clear the bits in the register */
+       bit_pos = fsl_readl(&dr_regs->endptcomplete);
+       fsl_writel(bit_pos, &dr_regs->endptcomplete);
+
+       if (!bit_pos)
+               return;
+
+       for (i = 0; i < udc->max_ep; i++) {
+               ep_num = i >> 1;
+               direction = i % 2;
+
+               bit_mask = 1 << (ep_num + 16 * direction);
+
+               if (!(bit_pos & bit_mask))
+                       continue;
+
+               curr_ep = get_ep_by_pipe(udc, i);
+
+               /* If the ep is configured */
+               if (curr_ep->name == NULL) {
+                       WARNING("Invalid EP?");
+                       continue;
+               }
+
+               /* process the req queue until an uncomplete request */
+               list_for_each_entry_safe(curr_req, temp_req, &curr_ep->queue,
+                               queue) {
+                       status = process_ep_req(udc, i, curr_req);
+
+                       VDBG("status of process_ep_req= %d, ep = %d",
+                                       status, ep_num);
+                       if (status == REQ_UNCOMPLETE)
+                               break;
+                       /* write back status to req */
+                       curr_req->req.status = status;
+
+                       if (ep_num == 0) {
+                               ep0_req_complete(udc, curr_ep, curr_req);
+                               break;
+                       } else
+                               done(curr_ep, curr_req, status);
+               }
+       }
+}
+
+static inline enum usb_device_speed portscx_device_speed(u32 reg)
+{
+       switch (reg & PORTSCX_PORT_SPEED_MASK) {
+       case PORTSCX_PORT_SPEED_HIGH:
+               return USB_SPEED_HIGH;
+       case PORTSCX_PORT_SPEED_FULL:
+               return USB_SPEED_FULL;
+       case PORTSCX_PORT_SPEED_LOW:
+               return USB_SPEED_LOW;
+       default:
+               return USB_SPEED_UNKNOWN;
+       }
+}
+
+/* Process a port change interrupt */
+static void port_change_irq(struct fsl_udc *udc)
+{
+       if (udc->bus_reset)
+               udc->bus_reset = 0;
+
+       /* Bus resetting is finished */
+       if (!(fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET))
+               /* Get the speed */
+               udc->gadget.speed =
+                       portscx_device_speed(fsl_readl(&dr_regs->portsc1));
+
+       /* Update USB state */
+       if (!udc->resume_state)
+               udc->usb_state = USB_STATE_DEFAULT;
+}
+
+/* Process suspend interrupt */
+static void suspend_irq(struct fsl_udc *udc)
+{
+       udc->resume_state = udc->usb_state;
+       udc->usb_state = USB_STATE_SUSPENDED;
+
+       /* report suspend to the driver, serial.c does not support this */
+       if (udc->driver->suspend)
+               udc->driver->suspend(&udc->gadget);
+}
+
+static void bus_resume(struct fsl_udc *udc)
+{
+       udc->usb_state = udc->resume_state;
+       udc->resume_state = 0;
+
+       /* report resume to the driver, serial.c does not support this */
+       if (udc->driver->resume)
+               udc->driver->resume(&udc->gadget);
+}
+
+/* Clear up all ep queues */
+static int reset_queues(struct fsl_udc *udc)
+{
+       u8 pipe;
+
+       for (pipe = 0; pipe < udc->max_pipes; pipe++)
+               udc_reset_ep_queue(udc, pipe);
+
+       /* report disconnect; the driver is already quiesced */
+       spin_unlock(&udc->lock);
+       udc->driver->disconnect(&udc->gadget);
+       spin_lock(&udc->lock);
+
+       return 0;
+}
+
+/* Process reset interrupt */
+static void reset_irq(struct fsl_udc *udc)
+{
+       u32 temp;
+       unsigned long timeout;
+
+       /* Clear the device address */
+       temp = fsl_readl(&dr_regs->deviceaddr);
+       fsl_writel(temp & ~USB_DEVICE_ADDRESS_MASK, &dr_regs->deviceaddr);
+
+       udc->device_address = 0;
+
+       /* Clear usb state */
+       udc->resume_state = 0;
+       udc->ep0_dir = 0;
+       udc->ep0_state = WAIT_FOR_SETUP;
+       udc->remote_wakeup = 0; /* default to 0 on reset */
+       udc->gadget.b_hnp_enable = 0;
+       udc->gadget.a_hnp_support = 0;
+       udc->gadget.a_alt_hnp_support = 0;
+
+       /* Clear all the setup token semaphores */
+       temp = fsl_readl(&dr_regs->endptsetupstat);
+       fsl_writel(temp, &dr_regs->endptsetupstat);
+
+       /* Clear all the endpoint complete status bits */
+       temp = fsl_readl(&dr_regs->endptcomplete);
+       fsl_writel(temp, &dr_regs->endptcomplete);
+
+       timeout = jiffies + 100;
+       while (fsl_readl(&dr_regs->endpointprime)) {
+               /* Wait until all endptprime bits cleared */
+               if (time_after(jiffies, timeout)) {
+                       ERR("Timeout for reset\n");
+                       break;
+               }
+               cpu_relax();
+       }
+
+       /* Write 1s to the flush register */
+       fsl_writel(0xffffffff, &dr_regs->endptflush);
+
+       if (fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET) {
+               VDBG("Bus reset");
+               /* Bus is reseting */
+               udc->bus_reset = 1;
+               /* Reset all the queues, include XD, dTD, EP queue
+                * head and TR Queue */
+               reset_queues(udc);
+               udc->usb_state = USB_STATE_DEFAULT;
+       } else {
+               VDBG("Controller reset");
+               /* initialize usb hw reg except for regs for EP, not
+                * touch usbintr reg */
+               dr_controller_setup(udc);
+
+               /* Reset all internal used Queues */
+               reset_queues(udc);
+
+               ep0_setup(udc);
+
+               /* Enable DR IRQ reg, Set Run bit, change udc state */
+               dr_controller_run(udc);
+               udc->usb_state = USB_STATE_ATTACHED;
+       }
+}
+
+/*
+ * USB device controller interrupt handler
+ */
+static irqreturn_t fsl_udc_irq(int irq, void *_udc)
+{
+       struct fsl_udc *udc = _udc;
+       u32 irq_src;
+       irqreturn_t status = IRQ_NONE;
+       unsigned long flags;
+
+       /* Disable ISR for OTG host mode */
+       if (udc->stopped)
+               return IRQ_NONE;
+       spin_lock_irqsave(&udc->lock, flags);
+       irq_src = fsl_readl(&dr_regs->usbsts) & fsl_readl(&dr_regs->usbintr);
+       /* Clear notification bits */
+       fsl_writel(irq_src, &dr_regs->usbsts);
+
+       /* VDBG("irq_src [0x%8x]", irq_src); */
+
+       /* Need to resume? */
+       if (udc->usb_state == USB_STATE_SUSPENDED)
+               if ((fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_SUSPEND) == 0)
+                       bus_resume(udc);
+
+       /* USB Interrupt */
+       if (irq_src & USB_STS_INT) {
+               VDBG("Packet int");
+               /* Setup package, we only support ep0 as control ep */
+               if (fsl_readl(&dr_regs->endptsetupstat) & EP_SETUP_STATUS_EP0) {
+                       tripwire_handler(udc, 0,
+                                       (u8 *) (&udc->local_setup_buff));
+                       setup_received_irq(udc, &udc->local_setup_buff);
+                       status = IRQ_HANDLED;
+               }
+
+               /* completion of dtd */
+               if (fsl_readl(&dr_regs->endptcomplete)) {
+                       dtd_complete_irq(udc);
+                       status = IRQ_HANDLED;
+               }
+       }
+
+       /* SOF (for ISO transfer) */
+       if (irq_src & USB_STS_SOF) {
+               status = IRQ_HANDLED;
+       }
+
+       /* Port Change */
+       if (irq_src & USB_STS_PORT_CHANGE) {
+               port_change_irq(udc);
+               status = IRQ_HANDLED;
+       }
+
+       /* Reset Received */
+       if (irq_src & USB_STS_RESET) {
+               VDBG("reset int");
+               reset_irq(udc);
+               status = IRQ_HANDLED;
+       }
+
+       /* Sleep Enable (Suspend) */
+       if (irq_src & USB_STS_SUSPEND) {
+               suspend_irq(udc);
+               status = IRQ_HANDLED;
+       }
+
+       if (irq_src & (USB_STS_ERR | USB_STS_SYS_ERR)) {
+               VDBG("Error IRQ %x", irq_src);
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return status;
+}
+
+/*----------------------------------------------------------------*
+ * Hook to gadget drivers
+ * Called by initialization code of gadget drivers
+*----------------------------------------------------------------*/
+static int fsl_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       int retval = 0;
+       unsigned long flags = 0;
+
+       /* lock is needed but whether should use this lock or another */
+       spin_lock_irqsave(&udc_controller->lock, flags);
+
+       driver->driver.bus = NULL;
+       /* hook up the driver */
+       udc_controller->driver = driver;
+       spin_unlock_irqrestore(&udc_controller->lock, flags);
+
+       if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
+               /* Suspend the controller until OTG enable it */
+               udc_controller->stopped = 1;
+               printk(KERN_INFO "Suspend udc for OTG auto detect\n");
+
+               /* connect to bus through transceiver */
+               if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
+                       retval = otg_set_peripheral(
+                                       udc_controller->transceiver->otg,
+                                                   &udc_controller->gadget);
+                       if (retval < 0) {
+                               ERR("can't bind to transceiver\n");
+                               udc_controller->driver = 0;
+                               return retval;
+                       }
+               }
+       } else {
+               /* Enable DR IRQ reg and set USBCMD reg Run bit */
+               dr_controller_run(udc_controller);
+               udc_controller->usb_state = USB_STATE_ATTACHED;
+               udc_controller->ep0_state = WAIT_FOR_SETUP;
+               udc_controller->ep0_dir = 0;
+       }
+
+       return retval;
+}
+
+/* Disconnect from gadget driver */
+static int fsl_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct fsl_ep *loop_ep;
+       unsigned long flags;
+
+       if (!IS_ERR_OR_NULL(udc_controller->transceiver))
+               otg_set_peripheral(udc_controller->transceiver->otg, NULL);
+
+       /* stop DR, disable intr */
+       dr_controller_stop(udc_controller);
+
+       /* in fact, no needed */
+       udc_controller->usb_state = USB_STATE_ATTACHED;
+       udc_controller->ep0_state = WAIT_FOR_SETUP;
+       udc_controller->ep0_dir = 0;
+
+       /* stand operation */
+       spin_lock_irqsave(&udc_controller->lock, flags);
+       udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
+       nuke(&udc_controller->eps[0], -ESHUTDOWN);
+       list_for_each_entry(loop_ep, &udc_controller->gadget.ep_list,
+                       ep.ep_list)
+               nuke(loop_ep, -ESHUTDOWN);
+       spin_unlock_irqrestore(&udc_controller->lock, flags);
+
+       udc_controller->driver = NULL;
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------
+               PROC File System Support
+-------------------------------------------------------------------------*/
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+#include <linux/seq_file.h>
+
+static const char proc_filename[] = "driver/fsl_usb2_udc";
+
+static int fsl_proc_read(struct seq_file *m, void *v)
+{
+       unsigned long flags;
+       int i;
+       u32 tmp_reg;
+       struct fsl_ep *ep = NULL;
+       struct fsl_req *req;
+
+       struct fsl_udc *udc = udc_controller;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /* ------basic driver information ---- */
+       seq_printf(m,
+                       DRIVER_DESC "\n"
+                       "%s version: %s\n"
+                       "Gadget driver: %s\n\n",
+                       driver_name, DRIVER_VERSION,
+                       udc->driver ? udc->driver->driver.name : "(none)");
+
+       /* ------ DR Registers ----- */
+       tmp_reg = fsl_readl(&dr_regs->usbcmd);
+       seq_printf(m,
+                       "USBCMD reg:\n"
+                       "SetupTW: %d\n"
+                       "Run/Stop: %s\n\n",
+                       (tmp_reg & USB_CMD_SUTW) ? 1 : 0,
+                       (tmp_reg & USB_CMD_RUN_STOP) ? "Run" : "Stop");
+
+       tmp_reg = fsl_readl(&dr_regs->usbsts);
+       seq_printf(m,
+                       "USB Status Reg:\n"
+                       "Dr Suspend: %d Reset Received: %d System Error: %s "
+                       "USB Error Interrupt: %s\n\n",
+                       (tmp_reg & USB_STS_SUSPEND) ? 1 : 0,
+                       (tmp_reg & USB_STS_RESET) ? 1 : 0,
+                       (tmp_reg & USB_STS_SYS_ERR) ? "Err" : "Normal",
+                       (tmp_reg & USB_STS_ERR) ? "Err detected" : "No err");
+
+       tmp_reg = fsl_readl(&dr_regs->usbintr);
+       seq_printf(m,
+                       "USB Interrupt Enable Reg:\n"
+                       "Sleep Enable: %d SOF Received Enable: %d "
+                       "Reset Enable: %d\n"
+                       "System Error Enable: %d "
+                       "Port Change Dectected Enable: %d\n"
+                       "USB Error Intr Enable: %d USB Intr Enable: %d\n\n",
+                       (tmp_reg & USB_INTR_DEVICE_SUSPEND) ? 1 : 0,
+                       (tmp_reg & USB_INTR_SOF_EN) ? 1 : 0,
+                       (tmp_reg & USB_INTR_RESET_EN) ? 1 : 0,
+                       (tmp_reg & USB_INTR_SYS_ERR_EN) ? 1 : 0,
+                       (tmp_reg & USB_INTR_PTC_DETECT_EN) ? 1 : 0,
+                       (tmp_reg & USB_INTR_ERR_INT_EN) ? 1 : 0,
+                       (tmp_reg & USB_INTR_INT_EN) ? 1 : 0);
+
+       tmp_reg = fsl_readl(&dr_regs->frindex);
+       seq_printf(m,
+                       "USB Frame Index Reg: Frame Number is 0x%x\n\n",
+                       (tmp_reg & USB_FRINDEX_MASKS));
+
+       tmp_reg = fsl_readl(&dr_regs->deviceaddr);
+       seq_printf(m,
+                       "USB Device Address Reg: Device Addr is 0x%x\n\n",
+                       (tmp_reg & USB_DEVICE_ADDRESS_MASK));
+
+       tmp_reg = fsl_readl(&dr_regs->endpointlistaddr);
+       seq_printf(m,
+                       "USB Endpoint List Address Reg: "
+                       "Device Addr is 0x%x\n\n",
+                       (tmp_reg & USB_EP_LIST_ADDRESS_MASK));
+
+       tmp_reg = fsl_readl(&dr_regs->portsc1);
+       seq_printf(m,
+               "USB Port Status&Control Reg:\n"
+               "Port Transceiver Type : %s Port Speed: %s\n"
+               "PHY Low Power Suspend: %s Port Reset: %s "
+               "Port Suspend Mode: %s\n"
+               "Over-current Change: %s "
+               "Port Enable/Disable Change: %s\n"
+               "Port Enabled/Disabled: %s "
+               "Current Connect Status: %s\n\n", ( {
+                       const char *s;
+                       switch (tmp_reg & PORTSCX_PTS_FSLS) {
+                       case PORTSCX_PTS_UTMI:
+                               s = "UTMI"; break;
+                       case PORTSCX_PTS_ULPI:
+                               s = "ULPI "; break;
+                       case PORTSCX_PTS_FSLS:
+                               s = "FS/LS Serial"; break;
+                       default:
+                               s = "None"; break;
+                       }
+                       s;} ),
+               usb_speed_string(portscx_device_speed(tmp_reg)),
+               (tmp_reg & PORTSCX_PHY_LOW_POWER_SPD) ?
+               "Normal PHY mode" : "Low power mode",
+               (tmp_reg & PORTSCX_PORT_RESET) ? "In Reset" :
+               "Not in Reset",
+               (tmp_reg & PORTSCX_PORT_SUSPEND) ? "In " : "Not in",
+               (tmp_reg & PORTSCX_OVER_CURRENT_CHG) ? "Dected" :
+               "No",
+               (tmp_reg & PORTSCX_PORT_EN_DIS_CHANGE) ? "Disable" :
+               "Not change",
+               (tmp_reg & PORTSCX_PORT_ENABLE) ? "Enable" :
+               "Not correct",
+               (tmp_reg & PORTSCX_CURRENT_CONNECT_STATUS) ?
+               "Attached" : "Not-Att");
+
+       tmp_reg = fsl_readl(&dr_regs->usbmode);
+       seq_printf(m,
+                       "USB Mode Reg: Controller Mode is: %s\n\n", ( {
+                               const char *s;
+                               switch (tmp_reg & USB_MODE_CTRL_MODE_HOST) {
+                               case USB_MODE_CTRL_MODE_IDLE:
+                                       s = "Idle"; break;
+                               case USB_MODE_CTRL_MODE_DEVICE:
+                                       s = "Device Controller"; break;
+                               case USB_MODE_CTRL_MODE_HOST:
+                                       s = "Host Controller"; break;
+                               default:
+                                       s = "None"; break;
+                               }
+                               s;
+                       } ));
+
+       tmp_reg = fsl_readl(&dr_regs->endptsetupstat);
+       seq_printf(m,
+                       "Endpoint Setup Status Reg: SETUP on ep 0x%x\n\n",
+                       (tmp_reg & EP_SETUP_STATUS_MASK));
+
+       for (i = 0; i < udc->max_ep / 2; i++) {
+               tmp_reg = fsl_readl(&dr_regs->endptctrl[i]);
+               seq_printf(m, "EP Ctrl Reg [0x%x]: = [0x%x]\n", i, tmp_reg);
+       }
+       tmp_reg = fsl_readl(&dr_regs->endpointprime);
+       seq_printf(m, "EP Prime Reg = [0x%x]\n\n", tmp_reg);
+
+#ifndef CONFIG_ARCH_MXC
+       if (udc->pdata->have_sysif_regs) {
+               tmp_reg = usb_sys_regs->snoop1;
+               seq_printf(m, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg);
+
+               tmp_reg = usb_sys_regs->control;
+               seq_printf(m, "General Control Reg : = [0x%x]\n\n", tmp_reg);
+       }
+#endif
+
+       /* ------fsl_udc, fsl_ep, fsl_request structure information ----- */
+       ep = &udc->eps[0];
+       seq_printf(m, "For %s Maxpkt is 0x%x index is 0x%x\n",
+                       ep->ep.name, ep_maxpacket(ep), ep_index(ep));
+
+       if (list_empty(&ep->queue)) {
+               seq_puts(m, "its req queue is empty\n\n");
+       } else {
+               list_for_each_entry(req, &ep->queue, queue) {
+                       seq_printf(m,
+                               "req %p actual 0x%x length 0x%x buf %p\n",
+                               &req->req, req->req.actual,
+                               req->req.length, req->req.buf);
+               }
+       }
+       /* other gadget->eplist ep */
+       list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
+               if (ep->ep.desc) {
+                       seq_printf(m,
+                                       "\nFor %s Maxpkt is 0x%x "
+                                       "index is 0x%x\n",
+                                       ep->ep.name, ep_maxpacket(ep),
+                                       ep_index(ep));
+
+                       if (list_empty(&ep->queue)) {
+                               seq_puts(m, "its req queue is empty\n\n");
+                       } else {
+                               list_for_each_entry(req, &ep->queue, queue) {
+                                       seq_printf(m,
+                                               "req %p actual 0x%x length "
+                                               "0x%x  buf %p\n",
+                                               &req->req, req->req.actual,
+                                               req->req.length, req->req.buf);
+                               }       /* end for each_entry of ep req */
+                       }       /* end for else */
+               }       /* end for if(ep->queue) */
+       }       /* end (ep->desc) */
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int fsl_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, fsl_proc_read, NULL);
+}
+
+static const struct file_operations fsl_proc_fops = {
+       .open           = fsl_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+#define create_proc_file()     proc_create(proc_filename, 0, NULL, &fsl_proc_fops)
+#define remove_proc_file()     remove_proc_entry(proc_filename, NULL)
+
+#else                          /* !CONFIG_USB_GADGET_DEBUG_FILES */
+
+#define create_proc_file()     do {} while (0)
+#define remove_proc_file()     do {} while (0)
+
+#endif                         /* CONFIG_USB_GADGET_DEBUG_FILES */
+
+/*-------------------------------------------------------------------------*/
+
+/* Release udc structures */
+static void fsl_udc_release(struct device *dev)
+{
+       complete(udc_controller->done);
+       dma_free_coherent(dev->parent, udc_controller->ep_qh_size,
+                       udc_controller->ep_qh, udc_controller->ep_qh_dma);
+       kfree(udc_controller);
+}
+
+/******************************************************************
+       Internal structure setup functions
+*******************************************************************/
+/*------------------------------------------------------------------
+ * init resource for globle controller
+ * Return the udc handle on success or NULL on failure
+ ------------------------------------------------------------------*/
+static int struct_udc_setup(struct fsl_udc *udc,
+               struct platform_device *pdev)
+{
+       struct fsl_usb2_platform_data *pdata;
+       size_t size;
+
+       pdata = dev_get_platdata(&pdev->dev);
+       udc->phy_mode = pdata->phy_mode;
+
+       udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);
+       if (!udc->eps)
+               return -1;
+
+       /* initialized QHs, take care of alignment */
+       size = udc->max_ep * sizeof(struct ep_queue_head);
+       if (size < QH_ALIGNMENT)
+               size = QH_ALIGNMENT;
+       else if ((size % QH_ALIGNMENT) != 0) {
+               size += QH_ALIGNMENT + 1;
+               size &= ~(QH_ALIGNMENT - 1);
+       }
+       udc->ep_qh = dma_alloc_coherent(&pdev->dev, size,
+                                       &udc->ep_qh_dma, GFP_KERNEL);
+       if (!udc->ep_qh) {
+               ERR("malloc QHs for udc failed\n");
+               kfree(udc->eps);
+               return -1;
+       }
+
+       udc->ep_qh_size = size;
+
+       /* Initialize ep0 status request structure */
+       /* FIXME: fsl_alloc_request() ignores ep argument */
+       udc->status_req = container_of(fsl_alloc_request(NULL, GFP_KERNEL),
+                       struct fsl_req, req);
+       /* allocate a small amount of memory to get valid address */
+       udc->status_req->req.buf = kmalloc(8, GFP_KERNEL);
+
+       udc->resume_state = USB_STATE_NOTATTACHED;
+       udc->usb_state = USB_STATE_POWERED;
+       udc->ep0_dir = 0;
+       udc->remote_wakeup = 0; /* default to 0 on reset */
+
+       return 0;
+}
+
+/*----------------------------------------------------------------
+ * Setup the fsl_ep struct for eps
+ * Link fsl_ep->ep to gadget->ep_list
+ * ep0out is not used so do nothing here
+ * ep0in should be taken care
+ *--------------------------------------------------------------*/
+static int struct_ep_setup(struct fsl_udc *udc, unsigned char index,
+               char *name, int link)
+{
+       struct fsl_ep *ep = &udc->eps[index];
+
+       ep->udc = udc;
+       strcpy(ep->name, name);
+       ep->ep.name = ep->name;
+
+       ep->ep.ops = &fsl_ep_ops;
+       ep->stopped = 0;
+
+       /* for ep0: maxP defined in desc
+        * for other eps, maxP is set by epautoconfig() called by gadget layer
+        */
+       usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
+
+       /* the queue lists any req for this ep */
+       INIT_LIST_HEAD(&ep->queue);
+
+       /* gagdet.ep_list used for ep_autoconfig so no ep0 */
+       if (link)
+               list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+       ep->gadget = &udc->gadget;
+       ep->qh = &udc->ep_qh[index];
+
+       return 0;
+}
+
+/* Driver probe function
+ * all intialization operations implemented here except enabling usb_intr reg
+ * board setup should have been done in the platform code
+ */
+static int fsl_udc_probe(struct platform_device *pdev)
+{
+       struct fsl_usb2_platform_data *pdata;
+       struct resource *res;
+       int ret = -ENODEV;
+       unsigned int i;
+       u32 dccparams;
+
+       udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
+       if (udc_controller == NULL)
+               return -ENOMEM;
+
+       pdata = dev_get_platdata(&pdev->dev);
+       udc_controller->pdata = pdata;
+       spin_lock_init(&udc_controller->lock);
+       udc_controller->stopped = 1;
+
+#ifdef CONFIG_USB_OTG
+       if (pdata->operating_mode == FSL_USB2_DR_OTG) {
+               udc_controller->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+               if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
+                       ERR("Can't find OTG driver!\n");
+                       ret = -ENODEV;
+                       goto err_kfree;
+               }
+       }
+#endif
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENXIO;
+               goto err_kfree;
+       }
+
+       if (pdata->operating_mode == FSL_USB2_DR_DEVICE) {
+               if (!request_mem_region(res->start, resource_size(res),
+                                       driver_name)) {
+                       ERR("request mem region for %s failed\n", pdev->name);
+                       ret = -EBUSY;
+                       goto err_kfree;
+               }
+       }
+
+       dr_regs = ioremap(res->start, resource_size(res));
+       if (!dr_regs) {
+               ret = -ENOMEM;
+               goto err_release_mem_region;
+       }
+
+       pdata->regs = (void *)dr_regs;
+
+       /*
+        * do platform specific init: check the clock, grab/config pins, etc.
+        */
+       if (pdata->init && pdata->init(pdev)) {
+               ret = -ENODEV;
+               goto err_iounmap_noclk;
+       }
+
+       /* Set accessors only after pdata->init() ! */
+       fsl_set_accessors(pdata);
+
+#ifndef CONFIG_ARCH_MXC
+       if (pdata->have_sysif_regs)
+               usb_sys_regs = (void *)dr_regs + USB_DR_SYS_OFFSET;
+#endif
+
+       /* Initialize USB clocks */
+       ret = fsl_udc_clk_init(pdev);
+       if (ret < 0)
+               goto err_iounmap_noclk;
+
+       /* Read Device Controller Capability Parameters register */
+       dccparams = fsl_readl(&dr_regs->dccparams);
+       if (!(dccparams & DCCPARAMS_DC)) {
+               ERR("This SOC doesn't support device role\n");
+               ret = -ENODEV;
+               goto err_iounmap;
+       }
+       /* Get max device endpoints */
+       /* DEN is bidirectional ep number, max_ep doubles the number */
+       udc_controller->max_ep = (dccparams & DCCPARAMS_DEN_MASK) * 2;
+
+       udc_controller->irq = platform_get_irq(pdev, 0);
+       if (!udc_controller->irq) {
+               ret = -ENODEV;
+               goto err_iounmap;
+       }
+
+       ret = request_irq(udc_controller->irq, fsl_udc_irq, IRQF_SHARED,
+                       driver_name, udc_controller);
+       if (ret != 0) {
+               ERR("cannot request irq %d err %d\n",
+                               udc_controller->irq, ret);
+               goto err_iounmap;
+       }
+
+       /* Initialize the udc structure including QH member and other member */
+       if (struct_udc_setup(udc_controller, pdev)) {
+               ERR("Can't initialize udc data structure\n");
+               ret = -ENOMEM;
+               goto err_free_irq;
+       }
+
+       if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
+               /* initialize usb hw reg except for regs for EP,
+                * leave usbintr reg untouched */
+               dr_controller_setup(udc_controller);
+       }
+
+       ret = fsl_udc_clk_finalize(pdev);
+       if (ret)
+               goto err_free_irq;
+
+       /* Setup gadget structure */
+       udc_controller->gadget.ops = &fsl_gadget_ops;
+       udc_controller->gadget.max_speed = USB_SPEED_HIGH;
+       udc_controller->gadget.ep0 = &udc_controller->eps[0].ep;
+       INIT_LIST_HEAD(&udc_controller->gadget.ep_list);
+       udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
+       udc_controller->gadget.name = driver_name;
+
+       /* Setup gadget.dev and register with kernel */
+       dev_set_name(&udc_controller->gadget.dev, "gadget");
+       udc_controller->gadget.dev.of_node = pdev->dev.of_node;
+
+       if (!IS_ERR_OR_NULL(udc_controller->transceiver))
+               udc_controller->gadget.is_otg = 1;
+
+       /* setup QH and epctrl for ep0 */
+       ep0_setup(udc_controller);
+
+       /* setup udc->eps[] for ep0 */
+       struct_ep_setup(udc_controller, 0, "ep0", 0);
+       /* for ep0: the desc defined here;
+        * for other eps, gadget layer called ep_enable with defined desc
+        */
+       udc_controller->eps[0].ep.desc = &fsl_ep0_desc;
+       usb_ep_set_maxpacket_limit(&udc_controller->eps[0].ep,
+                                  USB_MAX_CTRL_PAYLOAD);
+
+       /* setup the udc->eps[] for non-control endpoints and link
+        * to gadget.ep_list */
+       for (i = 1; i < (int)(udc_controller->max_ep / 2); i++) {
+               char name[14];
+
+               sprintf(name, "ep%dout", i);
+               struct_ep_setup(udc_controller, i * 2, name, 1);
+               sprintf(name, "ep%din", i);
+               struct_ep_setup(udc_controller, i * 2 + 1, name, 1);
+       }
+
+       /* use dma_pool for TD management */
+       udc_controller->td_pool = dma_pool_create("udc_td", &pdev->dev,
+                       sizeof(struct ep_td_struct),
+                       DTD_ALIGNMENT, UDC_DMA_BOUNDARY);
+       if (udc_controller->td_pool == NULL) {
+               ret = -ENOMEM;
+               goto err_free_irq;
+       }
+
+       ret = usb_add_gadget_udc_release(&pdev->dev, &udc_controller->gadget,
+                       fsl_udc_release);
+       if (ret)
+               goto err_del_udc;
+
+       create_proc_file();
+       return 0;
+
+err_del_udc:
+       dma_pool_destroy(udc_controller->td_pool);
+err_free_irq:
+       free_irq(udc_controller->irq, udc_controller);
+err_iounmap:
+       if (pdata->exit)
+               pdata->exit(pdev);
+       fsl_udc_clk_release();
+err_iounmap_noclk:
+       iounmap(dr_regs);
+err_release_mem_region:
+       if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
+               release_mem_region(res->start, resource_size(res));
+err_kfree:
+       kfree(udc_controller);
+       udc_controller = NULL;
+       return ret;
+}
+
+/* Driver removal function
+ * Free resources and finish pending transactions
+ */
+static int __exit fsl_udc_remove(struct platform_device *pdev)
+{
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
+
+       DECLARE_COMPLETION(done);
+
+       if (!udc_controller)
+               return -ENODEV;
+
+       udc_controller->done = &done;
+       usb_del_gadget_udc(&udc_controller->gadget);
+
+       fsl_udc_clk_release();
+
+       /* DR has been stopped in usb_gadget_unregister_driver() */
+       remove_proc_file();
+
+       /* Free allocated memory */
+       kfree(udc_controller->status_req->req.buf);
+       kfree(udc_controller->status_req);
+       kfree(udc_controller->eps);
+
+       dma_pool_destroy(udc_controller->td_pool);
+       free_irq(udc_controller->irq, udc_controller);
+       iounmap(dr_regs);
+       if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
+               release_mem_region(res->start, resource_size(res));
+
+       /* free udc --wait for the release() finished */
+       wait_for_completion(&done);
+
+       /*
+        * do platform specific un-initialization:
+        * release iomux pins, etc.
+        */
+       if (pdata->exit)
+               pdata->exit(pdev);
+
+       return 0;
+}
+
+/*-----------------------------------------------------------------
+ * Modify Power management attributes
+ * Used by OTG statemachine to disable gadget temporarily
+ -----------------------------------------------------------------*/
+static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       dr_controller_stop(udc_controller);
+       return 0;
+}
+
+/*-----------------------------------------------------------------
+ * Invoked on USB resume. May be called in_interrupt.
+ * Here we start the DR controller and enable the irq
+ *-----------------------------------------------------------------*/
+static int fsl_udc_resume(struct platform_device *pdev)
+{
+       /* Enable DR irq reg and set controller Run */
+       if (udc_controller->stopped) {
+               dr_controller_setup(udc_controller);
+               dr_controller_run(udc_controller);
+       }
+       udc_controller->usb_state = USB_STATE_ATTACHED;
+       udc_controller->ep0_state = WAIT_FOR_SETUP;
+       udc_controller->ep0_dir = 0;
+       return 0;
+}
+
+static int fsl_udc_otg_suspend(struct device *dev, pm_message_t state)
+{
+       struct fsl_udc *udc = udc_controller;
+       u32 mode, usbcmd;
+
+       mode = fsl_readl(&dr_regs->usbmode) & USB_MODE_CTRL_MODE_MASK;
+
+       pr_debug("%s(): mode 0x%x stopped %d\n", __func__, mode, udc->stopped);
+
+       /*
+        * If the controller is already stopped, then this must be a
+        * PM suspend.  Remember this fact, so that we will leave the
+        * controller stopped at PM resume time.
+        */
+       if (udc->stopped) {
+               pr_debug("gadget already stopped, leaving early\n");
+               udc->already_stopped = 1;
+               return 0;
+       }
+
+       if (mode != USB_MODE_CTRL_MODE_DEVICE) {
+               pr_debug("gadget not in device mode, leaving early\n");
+               return 0;
+       }
+
+       /* stop the controller */
+       usbcmd = fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP;
+       fsl_writel(usbcmd, &dr_regs->usbcmd);
+
+       udc->stopped = 1;
+
+       pr_info("USB Gadget suspended\n");
+
+       return 0;
+}
+
+static int fsl_udc_otg_resume(struct device *dev)
+{
+       pr_debug("%s(): stopped %d  already_stopped %d\n", __func__,
+                udc_controller->stopped, udc_controller->already_stopped);
+
+       /*
+        * If the controller was stopped at suspend time, then
+        * don't resume it now.
+        */
+       if (udc_controller->already_stopped) {
+               udc_controller->already_stopped = 0;
+               pr_debug("gadget was already stopped, leaving early\n");
+               return 0;
+       }
+
+       pr_info("USB Gadget resume\n");
+
+       return fsl_udc_resume(NULL);
+}
+/*-------------------------------------------------------------------------
+       Register entry point for the peripheral controller driver
+--------------------------------------------------------------------------*/
+static const struct platform_device_id fsl_udc_devtype[] = {
+       {
+               .name = "imx-udc-mx27",
+       }, {
+               .name = "imx-udc-mx51",
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(platform, fsl_udc_devtype);
+static struct platform_driver udc_driver = {
+       .remove         = __exit_p(fsl_udc_remove),
+       /* Just for FSL i.mx SoC currently */
+       .id_table       = fsl_udc_devtype,
+       /* these suspend and resume are not usb suspend and resume */
+       .suspend        = fsl_udc_suspend,
+       .resume         = fsl_udc_resume,
+       .driver         = {
+                       .name = driver_name,
+                       .owner = THIS_MODULE,
+                       /* udc suspend/resume called from OTG driver */
+                       .suspend = fsl_udc_otg_suspend,
+                       .resume  = fsl_udc_otg_resume,
+       },
+};
+
+module_platform_driver_probe(udc_driver, fsl_udc_probe);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:fsl-usb2-udc");
diff --git a/drivers/usb/gadget/udc/fsl_usb2_udc.h b/drivers/usb/gadget/udc/fsl_usb2_udc.h
new file mode 100644 (file)
index 0000000..c6703bb
--- /dev/null
@@ -0,0 +1,611 @@
+/*
+ * Copyright (C) 2004,2012 Freescale Semiconductor, Inc
+ * 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 as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Freescale USB device/endpoint management registers
+ */
+#ifndef __FSL_USB2_UDC_H
+#define __FSL_USB2_UDC_H
+
+/* ### define USB registers here
+ */
+#define USB_MAX_CTRL_PAYLOAD           64
+#define USB_DR_SYS_OFFSET              0x400
+
+ /* USB DR device mode registers (Little Endian) */
+struct usb_dr_device {
+       /* Capability register */
+       u8 res1[256];
+       u16 caplength;          /* Capability Register Length */
+       u16 hciversion;         /* Host Controller Interface Version */
+       u32 hcsparams;          /* Host Controller Structural Parameters */
+       u32 hccparams;          /* Host Controller Capability Parameters */
+       u8 res2[20];
+       u32 dciversion;         /* Device Controller Interface Version */
+       u32 dccparams;          /* Device Controller Capability Parameters */
+       u8 res3[24];
+       /* Operation register */
+       u32 usbcmd;             /* USB Command Register */
+       u32 usbsts;             /* USB Status Register */
+       u32 usbintr;            /* USB Interrupt Enable Register */
+       u32 frindex;            /* Frame Index Register */
+       u8 res4[4];
+       u32 deviceaddr;         /* Device Address */
+       u32 endpointlistaddr;   /* Endpoint List Address Register */
+       u8 res5[4];
+       u32 burstsize;          /* Master Interface Data Burst Size Register */
+       u32 txttfilltuning;     /* Transmit FIFO Tuning Controls Register */
+       u8 res6[24];
+       u32 configflag;         /* Configure Flag Register */
+       u32 portsc1;            /* Port 1 Status and Control Register */
+       u8 res7[28];
+       u32 otgsc;              /* On-The-Go Status and Control */
+       u32 usbmode;            /* USB Mode Register */
+       u32 endptsetupstat;     /* Endpoint Setup Status Register */
+       u32 endpointprime;      /* Endpoint Initialization Register */
+       u32 endptflush;         /* Endpoint Flush Register */
+       u32 endptstatus;        /* Endpoint Status Register */
+       u32 endptcomplete;      /* Endpoint Complete Register */
+       u32 endptctrl[6];       /* Endpoint Control Registers */
+};
+
+ /* USB DR host mode registers (Little Endian) */
+struct usb_dr_host {
+       /* Capability register */
+       u8 res1[256];
+       u16 caplength;          /* Capability Register Length */
+       u16 hciversion;         /* Host Controller Interface Version */
+       u32 hcsparams;          /* Host Controller Structural Parameters */
+       u32 hccparams;          /* Host Controller Capability Parameters */
+       u8 res2[20];
+       u32 dciversion;         /* Device Controller Interface Version */
+       u32 dccparams;          /* Device Controller Capability Parameters */
+       u8 res3[24];
+       /* Operation register */
+       u32 usbcmd;             /* USB Command Register */
+       u32 usbsts;             /* USB Status Register */
+       u32 usbintr;            /* USB Interrupt Enable Register */
+       u32 frindex;            /* Frame Index Register */
+       u8 res4[4];
+       u32 periodiclistbase;   /* Periodic Frame List Base Address Register */
+       u32 asynclistaddr;      /* Current Asynchronous List Address Register */
+       u8 res5[4];
+       u32 burstsize;          /* Master Interface Data Burst Size Register */
+       u32 txttfilltuning;     /* Transmit FIFO Tuning Controls Register */
+       u8 res6[24];
+       u32 configflag;         /* Configure Flag Register */
+       u32 portsc1;            /* Port 1 Status and Control Register */
+       u8 res7[28];
+       u32 otgsc;              /* On-The-Go Status and Control */
+       u32 usbmode;            /* USB Mode Register */
+       u32 endptsetupstat;     /* Endpoint Setup Status Register */
+       u32 endpointprime;      /* Endpoint Initialization Register */
+       u32 endptflush;         /* Endpoint Flush Register */
+       u32 endptstatus;        /* Endpoint Status Register */
+       u32 endptcomplete;      /* Endpoint Complete Register */
+       u32 endptctrl[6];       /* Endpoint Control Registers */
+};
+
+ /* non-EHCI USB system interface registers (Big Endian) */
+struct usb_sys_interface {
+       u32 snoop1;
+       u32 snoop2;
+       u32 age_cnt_thresh;     /* Age Count Threshold Register */
+       u32 pri_ctrl;           /* Priority Control Register */
+       u32 si_ctrl;            /* System Interface Control Register */
+       u8 res[236];
+       u32 control;            /* General Purpose Control Register */
+};
+
+/* ep0 transfer state */
+#define WAIT_FOR_SETUP          0
+#define DATA_STATE_XMIT         1
+#define DATA_STATE_NEED_ZLP     2
+#define WAIT_FOR_OUT_STATUS     3
+#define DATA_STATE_RECV         4
+
+/* Device Controller Capability Parameter register */
+#define DCCPARAMS_DC                           0x00000080
+#define DCCPARAMS_DEN_MASK                     0x0000001f
+
+/* Frame Index Register Bit Masks */
+#define        USB_FRINDEX_MASKS                       0x3fff
+/* USB CMD  Register Bit Masks */
+#define  USB_CMD_RUN_STOP                     0x00000001
+#define  USB_CMD_CTRL_RESET                   0x00000002
+#define  USB_CMD_PERIODIC_SCHEDULE_EN         0x00000010
+#define  USB_CMD_ASYNC_SCHEDULE_EN            0x00000020
+#define  USB_CMD_INT_AA_DOORBELL              0x00000040
+#define  USB_CMD_ASP                          0x00000300
+#define  USB_CMD_ASYNC_SCH_PARK_EN            0x00000800
+#define  USB_CMD_SUTW                         0x00002000
+#define  USB_CMD_ATDTW                        0x00004000
+#define  USB_CMD_ITC                          0x00FF0000
+
+/* bit 15,3,2 are frame list size */
+#define  USB_CMD_FRAME_SIZE_1024              0x00000000
+#define  USB_CMD_FRAME_SIZE_512               0x00000004
+#define  USB_CMD_FRAME_SIZE_256               0x00000008
+#define  USB_CMD_FRAME_SIZE_128               0x0000000C
+#define  USB_CMD_FRAME_SIZE_64                0x00008000
+#define  USB_CMD_FRAME_SIZE_32                0x00008004
+#define  USB_CMD_FRAME_SIZE_16                0x00008008
+#define  USB_CMD_FRAME_SIZE_8                 0x0000800C
+
+/* bit 9-8 are async schedule park mode count */
+#define  USB_CMD_ASP_00                       0x00000000
+#define  USB_CMD_ASP_01                       0x00000100
+#define  USB_CMD_ASP_10                       0x00000200
+#define  USB_CMD_ASP_11                       0x00000300
+#define  USB_CMD_ASP_BIT_POS                  8
+
+/* bit 23-16 are interrupt threshold control */
+#define  USB_CMD_ITC_NO_THRESHOLD             0x00000000
+#define  USB_CMD_ITC_1_MICRO_FRM              0x00010000
+#define  USB_CMD_ITC_2_MICRO_FRM              0x00020000
+#define  USB_CMD_ITC_4_MICRO_FRM              0x00040000
+#define  USB_CMD_ITC_8_MICRO_FRM              0x00080000
+#define  USB_CMD_ITC_16_MICRO_FRM             0x00100000
+#define  USB_CMD_ITC_32_MICRO_FRM             0x00200000
+#define  USB_CMD_ITC_64_MICRO_FRM             0x00400000
+#define  USB_CMD_ITC_BIT_POS                  16
+
+/* USB STS Register Bit Masks */
+#define  USB_STS_INT                          0x00000001
+#define  USB_STS_ERR                          0x00000002
+#define  USB_STS_PORT_CHANGE                  0x00000004
+#define  USB_STS_FRM_LST_ROLL                 0x00000008
+#define  USB_STS_SYS_ERR                      0x00000010
+#define  USB_STS_IAA                          0x00000020
+#define  USB_STS_RESET                        0x00000040
+#define  USB_STS_SOF                          0x00000080
+#define  USB_STS_SUSPEND                      0x00000100
+#define  USB_STS_HC_HALTED                    0x00001000
+#define  USB_STS_RCL                          0x00002000
+#define  USB_STS_PERIODIC_SCHEDULE            0x00004000
+#define  USB_STS_ASYNC_SCHEDULE               0x00008000
+
+/* USB INTR Register Bit Masks */
+#define  USB_INTR_INT_EN                      0x00000001
+#define  USB_INTR_ERR_INT_EN                  0x00000002
+#define  USB_INTR_PTC_DETECT_EN               0x00000004
+#define  USB_INTR_FRM_LST_ROLL_EN             0x00000008
+#define  USB_INTR_SYS_ERR_EN                  0x00000010
+#define  USB_INTR_ASYN_ADV_EN                 0x00000020
+#define  USB_INTR_RESET_EN                    0x00000040
+#define  USB_INTR_SOF_EN                      0x00000080
+#define  USB_INTR_DEVICE_SUSPEND              0x00000100
+
+/* Device Address bit masks */
+#define  USB_DEVICE_ADDRESS_MASK              0xFE000000
+#define  USB_DEVICE_ADDRESS_BIT_POS           25
+
+/* endpoint list address bit masks */
+#define USB_EP_LIST_ADDRESS_MASK              0xfffff800
+
+/* PORTSCX  Register Bit Masks */
+#define  PORTSCX_CURRENT_CONNECT_STATUS       0x00000001
+#define  PORTSCX_CONNECT_STATUS_CHANGE        0x00000002
+#define  PORTSCX_PORT_ENABLE                  0x00000004
+#define  PORTSCX_PORT_EN_DIS_CHANGE           0x00000008
+#define  PORTSCX_OVER_CURRENT_ACT             0x00000010
+#define  PORTSCX_OVER_CURRENT_CHG             0x00000020
+#define  PORTSCX_PORT_FORCE_RESUME            0x00000040
+#define  PORTSCX_PORT_SUSPEND                 0x00000080
+#define  PORTSCX_PORT_RESET                   0x00000100
+#define  PORTSCX_LINE_STATUS_BITS             0x00000C00
+#define  PORTSCX_PORT_POWER                   0x00001000
+#define  PORTSCX_PORT_INDICTOR_CTRL           0x0000C000
+#define  PORTSCX_PORT_TEST_CTRL               0x000F0000
+#define  PORTSCX_WAKE_ON_CONNECT_EN           0x00100000
+#define  PORTSCX_WAKE_ON_CONNECT_DIS          0x00200000
+#define  PORTSCX_WAKE_ON_OVER_CURRENT         0x00400000
+#define  PORTSCX_PHY_LOW_POWER_SPD            0x00800000
+#define  PORTSCX_PORT_FORCE_FULL_SPEED        0x01000000
+#define  PORTSCX_PORT_SPEED_MASK              0x0C000000
+#define  PORTSCX_PORT_WIDTH                   0x10000000
+#define  PORTSCX_PHY_TYPE_SEL                 0xC0000000
+
+/* bit 11-10 are line status */
+#define  PORTSCX_LINE_STATUS_SE0              0x00000000
+#define  PORTSCX_LINE_STATUS_JSTATE           0x00000400
+#define  PORTSCX_LINE_STATUS_KSTATE           0x00000800
+#define  PORTSCX_LINE_STATUS_UNDEF            0x00000C00
+#define  PORTSCX_LINE_STATUS_BIT_POS          10
+
+/* bit 15-14 are port indicator control */
+#define  PORTSCX_PIC_OFF                      0x00000000
+#define  PORTSCX_PIC_AMBER                    0x00004000
+#define  PORTSCX_PIC_GREEN                    0x00008000
+#define  PORTSCX_PIC_UNDEF                    0x0000C000
+#define  PORTSCX_PIC_BIT_POS                  14
+
+/* bit 19-16 are port test control */
+#define  PORTSCX_PTC_DISABLE                  0x00000000
+#define  PORTSCX_PTC_JSTATE                   0x00010000
+#define  PORTSCX_PTC_KSTATE                   0x00020000
+#define  PORTSCX_PTC_SEQNAK                   0x00030000
+#define  PORTSCX_PTC_PACKET                   0x00040000
+#define  PORTSCX_PTC_FORCE_EN                 0x00050000
+#define  PORTSCX_PTC_BIT_POS                  16
+
+/* bit 27-26 are port speed */
+#define  PORTSCX_PORT_SPEED_FULL              0x00000000
+#define  PORTSCX_PORT_SPEED_LOW               0x04000000
+#define  PORTSCX_PORT_SPEED_HIGH              0x08000000
+#define  PORTSCX_PORT_SPEED_UNDEF             0x0C000000
+#define  PORTSCX_SPEED_BIT_POS                26
+
+/* bit 28 is parallel transceiver width for UTMI interface */
+#define  PORTSCX_PTW                          0x10000000
+#define  PORTSCX_PTW_8BIT                     0x00000000
+#define  PORTSCX_PTW_16BIT                    0x10000000
+
+/* bit 31-30 are port transceiver select */
+#define  PORTSCX_PTS_UTMI                     0x00000000
+#define  PORTSCX_PTS_ULPI                     0x80000000
+#define  PORTSCX_PTS_FSLS                     0xC0000000
+#define  PORTSCX_PTS_BIT_POS                  30
+
+/* otgsc Register Bit Masks */
+#define  OTGSC_CTRL_VUSB_DISCHARGE            0x00000001
+#define  OTGSC_CTRL_VUSB_CHARGE               0x00000002
+#define  OTGSC_CTRL_OTG_TERM                  0x00000008
+#define  OTGSC_CTRL_DATA_PULSING              0x00000010
+#define  OTGSC_STS_USB_ID                     0x00000100
+#define  OTGSC_STS_A_VBUS_VALID               0x00000200
+#define  OTGSC_STS_A_SESSION_VALID            0x00000400
+#define  OTGSC_STS_B_SESSION_VALID            0x00000800
+#define  OTGSC_STS_B_SESSION_END              0x00001000
+#define  OTGSC_STS_1MS_TOGGLE                 0x00002000
+#define  OTGSC_STS_DATA_PULSING               0x00004000
+#define  OTGSC_INTSTS_USB_ID                  0x00010000
+#define  OTGSC_INTSTS_A_VBUS_VALID            0x00020000
+#define  OTGSC_INTSTS_A_SESSION_VALID         0x00040000
+#define  OTGSC_INTSTS_B_SESSION_VALID         0x00080000
+#define  OTGSC_INTSTS_B_SESSION_END           0x00100000
+#define  OTGSC_INTSTS_1MS                     0x00200000
+#define  OTGSC_INTSTS_DATA_PULSING            0x00400000
+#define  OTGSC_INTR_USB_ID                    0x01000000
+#define  OTGSC_INTR_A_VBUS_VALID              0x02000000
+#define  OTGSC_INTR_A_SESSION_VALID           0x04000000
+#define  OTGSC_INTR_B_SESSION_VALID           0x08000000
+#define  OTGSC_INTR_B_SESSION_END             0x10000000
+#define  OTGSC_INTR_1MS_TIMER                 0x20000000
+#define  OTGSC_INTR_DATA_PULSING              0x40000000
+
+/* USB MODE Register Bit Masks */
+#define  USB_MODE_CTRL_MODE_IDLE              0x00000000
+#define  USB_MODE_CTRL_MODE_DEVICE            0x00000002
+#define  USB_MODE_CTRL_MODE_HOST              0x00000003
+#define  USB_MODE_CTRL_MODE_MASK              0x00000003
+#define  USB_MODE_CTRL_MODE_RSV               0x00000001
+#define  USB_MODE_ES                          0x00000004 /* Endian Select */
+#define  USB_MODE_SETUP_LOCK_OFF              0x00000008
+#define  USB_MODE_STREAM_DISABLE              0x00000010
+/* Endpoint Flush Register */
+#define EPFLUSH_TX_OFFSET                    0x00010000
+#define EPFLUSH_RX_OFFSET                    0x00000000
+
+/* Endpoint Setup Status bit masks */
+#define  EP_SETUP_STATUS_MASK                 0x0000003F
+#define  EP_SETUP_STATUS_EP0                 0x00000001
+
+/* ENDPOINTCTRLx  Register Bit Masks */
+#define  EPCTRL_TX_ENABLE                     0x00800000
+#define  EPCTRL_TX_DATA_TOGGLE_RST            0x00400000       /* Not EP0 */
+#define  EPCTRL_TX_DATA_TOGGLE_INH            0x00200000       /* Not EP0 */
+#define  EPCTRL_TX_TYPE                       0x000C0000
+#define  EPCTRL_TX_DATA_SOURCE                0x00020000       /* Not EP0 */
+#define  EPCTRL_TX_EP_STALL                   0x00010000
+#define  EPCTRL_RX_ENABLE                     0x00000080
+#define  EPCTRL_RX_DATA_TOGGLE_RST            0x00000040       /* Not EP0 */
+#define  EPCTRL_RX_DATA_TOGGLE_INH            0x00000020       /* Not EP0 */
+#define  EPCTRL_RX_TYPE                       0x0000000C
+#define  EPCTRL_RX_DATA_SINK                  0x00000002       /* Not EP0 */
+#define  EPCTRL_RX_EP_STALL                   0x00000001
+
+/* bit 19-18 and 3-2 are endpoint type */
+#define  EPCTRL_EP_TYPE_CONTROL               0
+#define  EPCTRL_EP_TYPE_ISO                   1
+#define  EPCTRL_EP_TYPE_BULK                  2
+#define  EPCTRL_EP_TYPE_INTERRUPT             3
+#define  EPCTRL_TX_EP_TYPE_SHIFT              18
+#define  EPCTRL_RX_EP_TYPE_SHIFT              2
+
+/* SNOOPn Register Bit Masks */
+#define  SNOOP_ADDRESS_MASK                   0xFFFFF000
+#define  SNOOP_SIZE_ZERO                      0x00     /* snooping disable */
+#define  SNOOP_SIZE_4KB                       0x0B     /* 4KB snoop size */
+#define  SNOOP_SIZE_8KB                       0x0C
+#define  SNOOP_SIZE_16KB                      0x0D
+#define  SNOOP_SIZE_32KB                      0x0E
+#define  SNOOP_SIZE_64KB                      0x0F
+#define  SNOOP_SIZE_128KB                     0x10
+#define  SNOOP_SIZE_256KB                     0x11
+#define  SNOOP_SIZE_512KB                     0x12
+#define  SNOOP_SIZE_1MB                       0x13
+#define  SNOOP_SIZE_2MB                       0x14
+#define  SNOOP_SIZE_4MB                       0x15
+#define  SNOOP_SIZE_8MB                       0x16
+#define  SNOOP_SIZE_16MB                      0x17
+#define  SNOOP_SIZE_32MB                      0x18
+#define  SNOOP_SIZE_64MB                      0x19
+#define  SNOOP_SIZE_128MB                     0x1A
+#define  SNOOP_SIZE_256MB                     0x1B
+#define  SNOOP_SIZE_512MB                     0x1C
+#define  SNOOP_SIZE_1GB                       0x1D
+#define  SNOOP_SIZE_2GB                       0x1E     /* 2GB snoop size */
+
+/* pri_ctrl Register Bit Masks */
+#define  PRI_CTRL_PRI_LVL1                    0x0000000C
+#define  PRI_CTRL_PRI_LVL0                    0x00000003
+
+/* si_ctrl Register Bit Masks */
+#define  SI_CTRL_ERR_DISABLE                  0x00000010
+#define  SI_CTRL_IDRC_DISABLE                 0x00000008
+#define  SI_CTRL_RD_SAFE_EN                   0x00000004
+#define  SI_CTRL_RD_PREFETCH_DISABLE          0x00000002
+#define  SI_CTRL_RD_PREFEFETCH_VAL            0x00000001
+
+/* control Register Bit Masks */
+#define  USB_CTRL_IOENB                       0x00000004
+#define  USB_CTRL_ULPI_INT0EN                 0x00000001
+#define USB_CTRL_UTMI_PHY_EN                 0x00000200
+#define USB_CTRL_USB_EN                              0x00000004
+#define USB_CTRL_ULPI_PHY_CLK_SEL            0x00000400
+
+/* Endpoint Queue Head data struct
+ * Rem: all the variables of qh are LittleEndian Mode
+ * and NEXT_POINTER_MASK should operate on a LittleEndian, Phy Addr
+ */
+struct ep_queue_head {
+       u32 max_pkt_length;     /* Mult(31-30) , Zlt(29) , Max Pkt len
+                                  and IOS(15) */
+       u32 curr_dtd_ptr;       /* Current dTD Pointer(31-5) */
+       u32 next_dtd_ptr;       /* Next dTD Pointer(31-5), T(0) */
+       u32 size_ioc_int_sts;   /* Total bytes (30-16), IOC (15),
+                                  MultO(11-10), STS (7-0)  */
+       u32 buff_ptr0;          /* Buffer pointer Page 0 (31-12) */
+       u32 buff_ptr1;          /* Buffer pointer Page 1 (31-12) */
+       u32 buff_ptr2;          /* Buffer pointer Page 2 (31-12) */
+       u32 buff_ptr3;          /* Buffer pointer Page 3 (31-12) */
+       u32 buff_ptr4;          /* Buffer pointer Page 4 (31-12) */
+       u32 res1;
+       u8 setup_buffer[8];     /* Setup data 8 bytes */
+       u32 res2[4];
+};
+
+/* Endpoint Queue Head Bit Masks */
+#define  EP_QUEUE_HEAD_MULT_POS               30
+#define  EP_QUEUE_HEAD_ZLT_SEL                0x20000000
+#define  EP_QUEUE_HEAD_MAX_PKT_LEN_POS        16
+#define  EP_QUEUE_HEAD_MAX_PKT_LEN(ep_info)   (((ep_info)>>16)&0x07ff)
+#define  EP_QUEUE_HEAD_IOS                    0x00008000
+#define  EP_QUEUE_HEAD_NEXT_TERMINATE         0x00000001
+#define  EP_QUEUE_HEAD_IOC                    0x00008000
+#define  EP_QUEUE_HEAD_MULTO                  0x00000C00
+#define  EP_QUEUE_HEAD_STATUS_HALT           0x00000040
+#define  EP_QUEUE_HEAD_STATUS_ACTIVE          0x00000080
+#define  EP_QUEUE_CURRENT_OFFSET_MASK         0x00000FFF
+#define  EP_QUEUE_HEAD_NEXT_POINTER_MASK      0xFFFFFFE0
+#define  EP_QUEUE_FRINDEX_MASK                0x000007FF
+#define  EP_MAX_LENGTH_TRANSFER               0x4000
+
+/* Endpoint Transfer Descriptor data struct */
+/* Rem: all the variables of td are LittleEndian Mode */
+struct ep_td_struct {
+       u32 next_td_ptr;        /* Next TD pointer(31-5), T(0) set
+                                  indicate invalid */
+       u32 size_ioc_sts;       /* Total bytes (30-16), IOC (15),
+                                  MultO(11-10), STS (7-0)  */
+       u32 buff_ptr0;          /* Buffer pointer Page 0 */
+       u32 buff_ptr1;          /* Buffer pointer Page 1 */
+       u32 buff_ptr2;          /* Buffer pointer Page 2 */
+       u32 buff_ptr3;          /* Buffer pointer Page 3 */
+       u32 buff_ptr4;          /* Buffer pointer Page 4 */
+       u32 res;
+       /* 32 bytes */
+       dma_addr_t td_dma;      /* dma address for this td */
+       /* virtual address of next td specified in next_td_ptr */
+       struct ep_td_struct *next_td_virt;
+};
+
+/* Endpoint Transfer Descriptor bit Masks */
+#define  DTD_NEXT_TERMINATE                   0x00000001
+#define  DTD_IOC                              0x00008000
+#define  DTD_STATUS_ACTIVE                    0x00000080
+#define  DTD_STATUS_HALTED                    0x00000040
+#define  DTD_STATUS_DATA_BUFF_ERR             0x00000020
+#define  DTD_STATUS_TRANSACTION_ERR           0x00000008
+#define  DTD_RESERVED_FIELDS                  0x80007300
+#define  DTD_ADDR_MASK                        0xFFFFFFE0
+#define  DTD_PACKET_SIZE                      0x7FFF0000
+#define  DTD_LENGTH_BIT_POS                   16
+#define  DTD_ERROR_MASK                       (DTD_STATUS_HALTED | \
+                                               DTD_STATUS_DATA_BUFF_ERR | \
+                                               DTD_STATUS_TRANSACTION_ERR)
+/* Alignment requirements; must be a power of two */
+#define DTD_ALIGNMENT                          0x20
+#define QH_ALIGNMENT                           2048
+
+/* Controller dma boundary */
+#define UDC_DMA_BOUNDARY                       0x1000
+
+/*-------------------------------------------------------------------------*/
+
+/* ### driver private data
+ */
+struct fsl_req {
+       struct usb_request req;
+       struct list_head queue;
+       /* ep_queue() func will add
+          a request->queue into a udc_ep->queue 'd tail */
+       struct fsl_ep *ep;
+       unsigned mapped:1;
+
+       struct ep_td_struct *head, *tail;       /* For dTD List
+                                                  cpu endian Virtual addr */
+       unsigned int dtd_count;
+};
+
+#define REQ_UNCOMPLETE                 1
+
+struct fsl_ep {
+       struct usb_ep ep;
+       struct list_head queue;
+       struct fsl_udc *udc;
+       struct ep_queue_head *qh;
+       struct usb_gadget *gadget;
+
+       char name[14];
+       unsigned stopped:1;
+};
+
+#define EP_DIR_IN      1
+#define EP_DIR_OUT     0
+
+struct fsl_udc {
+       struct usb_gadget gadget;
+       struct usb_gadget_driver *driver;
+       struct fsl_usb2_platform_data *pdata;
+       struct completion *done;        /* to make sure release() is done */
+       struct fsl_ep *eps;
+       unsigned int max_ep;
+       unsigned int irq;
+
+       struct usb_ctrlrequest local_setup_buff;
+       spinlock_t lock;
+       struct usb_phy *transceiver;
+       unsigned softconnect:1;
+       unsigned vbus_active:1;
+       unsigned stopped:1;
+       unsigned remote_wakeup:1;
+       unsigned already_stopped:1;
+       unsigned big_endian_desc:1;
+
+       struct ep_queue_head *ep_qh;    /* Endpoints Queue-Head */
+       struct fsl_req *status_req;     /* ep0 status request */
+       struct dma_pool *td_pool;       /* dma pool for DTD */
+       enum fsl_usb2_phy_modes phy_mode;
+
+       size_t ep_qh_size;              /* size after alignment adjustment*/
+       dma_addr_t ep_qh_dma;           /* dma address of QH */
+
+       u32 max_pipes;          /* Device max pipes */
+       u32 bus_reset;          /* Device is bus resetting */
+       u32 resume_state;       /* USB state to resume */
+       u32 usb_state;          /* USB current state */
+       u32 ep0_state;          /* Endpoint zero state */
+       u32 ep0_dir;            /* Endpoint zero direction: can be
+                                  USB_DIR_IN or USB_DIR_OUT */
+       u8 device_address;      /* Device USB address */
+};
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+#define DBG(fmt, args...)      printk(KERN_DEBUG "[%s]  " fmt "\n", \
+                               __func__, ## args)
+#else
+#define DBG(fmt, args...)      do{}while(0)
+#endif
+
+#if 0
+static void dump_msg(const char *label, const u8 * buf, unsigned int length)
+{
+       unsigned int start, num, i;
+       char line[52], *p;
+
+       if (length >= 512)
+               return;
+       DBG("%s, length %u:\n", label, length);
+       start = 0;
+       while (length > 0) {
+               num = min(length, 16u);
+               p = line;
+               for (i = 0; i < num; ++i) {
+                       if (i == 8)
+                               *p++ = ' ';
+                       sprintf(p, " %02x", buf[i]);
+                       p += 3;
+               }
+               *p = 0;
+               printk(KERN_DEBUG "%6x: %s\n", start, line);
+               buf += num;
+               start += num;
+               length -= num;
+       }
+}
+#endif
+
+#ifdef VERBOSE
+#define VDBG           DBG
+#else
+#define VDBG(stuff...) do{}while(0)
+#endif
+
+#define ERR(stuff...)          pr_err("udc: " stuff)
+#define WARNING(stuff...)              pr_warning("udc: " stuff)
+#define INFO(stuff...)         pr_info("udc: " stuff)
+
+/*-------------------------------------------------------------------------*/
+
+/* ### Add board specific defines here
+ */
+
+/*
+ * ### pipe direction macro from device view
+ */
+#define USB_RECV       0       /* OUT EP */
+#define USB_SEND       1       /* IN EP */
+
+/*
+ * ### internal used help routines.
+ */
+#define ep_index(EP)           ((EP)->ep.desc->bEndpointAddress&0xF)
+#define ep_maxpacket(EP)       ((EP)->ep.maxpacket)
+#define ep_is_in(EP)   ( (ep_index(EP) == 0) ? (EP->udc->ep0_dir == \
+                       USB_DIR_IN) : ((EP)->ep.desc->bEndpointAddress \
+                       & USB_DIR_IN)==USB_DIR_IN)
+#define get_ep_by_pipe(udc, pipe)      ((pipe == 1)? &udc->eps[0]: \
+                                       &udc->eps[pipe])
+#define get_pipe_by_windex(windex)     ((windex & USB_ENDPOINT_NUMBER_MASK) \
+                                       * 2 + ((windex & USB_DIR_IN) ? 1 : 0))
+#define get_pipe_by_ep(EP)     (ep_index(EP) * 2 + ep_is_in(EP))
+
+static inline struct ep_queue_head *get_qh_by_ep(struct fsl_ep *ep)
+{
+       /* we only have one ep0 structure but two queue heads */
+       if (ep_index(ep) != 0)
+               return ep->qh;
+       else
+               return &ep->udc->ep_qh[(ep->udc->ep0_dir ==
+                               USB_DIR_IN) ? 1 : 0];
+}
+
+struct platform_device;
+#ifdef CONFIG_ARCH_MXC
+int fsl_udc_clk_init(struct platform_device *pdev);
+int fsl_udc_clk_finalize(struct platform_device *pdev);
+void fsl_udc_clk_release(void);
+#else
+static inline int fsl_udc_clk_init(struct platform_device *pdev)
+{
+       return 0;
+}
+static inline int fsl_udc_clk_finalize(struct platform_device *pdev)
+{
+       return 0;
+}
+static inline void fsl_udc_clk_release(void)
+{
+}
+#endif
+
+#endif
diff --git a/drivers/usb/gadget/udc/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c
new file mode 100644 (file)
index 0000000..d40255f
--- /dev/null
@@ -0,0 +1,1499 @@
+/*
+ * Fusb300 UDC (USB gadget)
+ *
+ * Copyright (C) 2010 Faraday Technology Corp.
+ *
+ * Author : Yuan-hsin Chen <yhchen@faraday-tech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#include "fusb300_udc.h"
+
+MODULE_DESCRIPTION("FUSB300  USB gadget driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yuan-Hsin Chen, Feng-Hsin Chiang <john453@faraday-tech.com>");
+MODULE_ALIAS("platform:fusb300_udc");
+
+#define DRIVER_VERSION "20 October 2010"
+
+static const char udc_name[] = "fusb300_udc";
+static const char * const fusb300_ep_name[] = {
+       "ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7", "ep8", "ep9",
+       "ep10", "ep11", "ep12", "ep13", "ep14", "ep15"
+};
+
+static void done(struct fusb300_ep *ep, struct fusb300_request *req,
+                int status);
+
+static void fusb300_enable_bit(struct fusb300 *fusb300, u32 offset,
+                              u32 value)
+{
+       u32 reg = ioread32(fusb300->reg + offset);
+
+       reg |= value;
+       iowrite32(reg, fusb300->reg + offset);
+}
+
+static void fusb300_disable_bit(struct fusb300 *fusb300, u32 offset,
+                               u32 value)
+{
+       u32 reg = ioread32(fusb300->reg + offset);
+
+       reg &= ~value;
+       iowrite32(reg, fusb300->reg + offset);
+}
+
+
+static void fusb300_ep_setting(struct fusb300_ep *ep,
+                              struct fusb300_ep_info info)
+{
+       ep->epnum = info.epnum;
+       ep->type = info.type;
+}
+
+static int fusb300_ep_release(struct fusb300_ep *ep)
+{
+       if (!ep->epnum)
+               return 0;
+       ep->epnum = 0;
+       ep->stall = 0;
+       ep->wedged = 0;
+       return 0;
+}
+
+static void fusb300_set_fifo_entry(struct fusb300 *fusb300,
+                                  u32 ep)
+{
+       u32 val = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
+
+       val &= ~FUSB300_EPSET1_FIFOENTRY_MSK;
+       val |= FUSB300_EPSET1_FIFOENTRY(FUSB300_FIFO_ENTRY_NUM);
+       iowrite32(val, fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
+}
+
+static void fusb300_set_start_entry(struct fusb300 *fusb300,
+                                   u8 ep)
+{
+       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
+       u32 start_entry = fusb300->fifo_entry_num * FUSB300_FIFO_ENTRY_NUM;
+
+       reg &= ~FUSB300_EPSET1_START_ENTRY_MSK  ;
+       reg |= FUSB300_EPSET1_START_ENTRY(start_entry);
+       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
+       if (fusb300->fifo_entry_num == FUSB300_MAX_FIFO_ENTRY) {
+               fusb300->fifo_entry_num = 0;
+               fusb300->addrofs = 0;
+               pr_err("fifo entry is over the maximum number!\n");
+       } else
+               fusb300->fifo_entry_num++;
+}
+
+/* set fusb300_set_start_entry first before fusb300_set_epaddrofs */
+static void fusb300_set_epaddrofs(struct fusb300 *fusb300,
+                                 struct fusb300_ep_info info)
+{
+       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET2(info.epnum));
+
+       reg &= ~FUSB300_EPSET2_ADDROFS_MSK;
+       reg |= FUSB300_EPSET2_ADDROFS(fusb300->addrofs);
+       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET2(info.epnum));
+       fusb300->addrofs += (info.maxpacket + 7) / 8 * FUSB300_FIFO_ENTRY_NUM;
+}
+
+static void ep_fifo_setting(struct fusb300 *fusb300,
+                           struct fusb300_ep_info info)
+{
+       fusb300_set_fifo_entry(fusb300, info.epnum);
+       fusb300_set_start_entry(fusb300, info.epnum);
+       fusb300_set_epaddrofs(fusb300, info);
+}
+
+static void fusb300_set_eptype(struct fusb300 *fusb300,
+                              struct fusb300_ep_info info)
+{
+       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+
+       reg &= ~FUSB300_EPSET1_TYPE_MSK;
+       reg |= FUSB300_EPSET1_TYPE(info.type);
+       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+}
+
+static void fusb300_set_epdir(struct fusb300 *fusb300,
+                             struct fusb300_ep_info info)
+{
+       u32 reg;
+
+       if (!info.dir_in)
+               return;
+       reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+       reg &= ~FUSB300_EPSET1_DIR_MSK;
+       reg |= FUSB300_EPSET1_DIRIN;
+       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+}
+
+static void fusb300_set_ep_active(struct fusb300 *fusb300,
+                         u8 ep)
+{
+       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
+
+       reg |= FUSB300_EPSET1_ACTEN;
+       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
+}
+
+static void fusb300_set_epmps(struct fusb300 *fusb300,
+                             struct fusb300_ep_info info)
+{
+       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET2(info.epnum));
+
+       reg &= ~FUSB300_EPSET2_MPS_MSK;
+       reg |= FUSB300_EPSET2_MPS(info.maxpacket);
+       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET2(info.epnum));
+}
+
+static void fusb300_set_interval(struct fusb300 *fusb300,
+                                struct fusb300_ep_info info)
+{
+       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+
+       reg &= ~FUSB300_EPSET1_INTERVAL(0x7);
+       reg |= FUSB300_EPSET1_INTERVAL(info.interval);
+       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+}
+
+static void fusb300_set_bwnum(struct fusb300 *fusb300,
+                             struct fusb300_ep_info info)
+{
+       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+
+       reg &= ~FUSB300_EPSET1_BWNUM(0x3);
+       reg |= FUSB300_EPSET1_BWNUM(info.bw_num);
+       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+}
+
+static void set_ep_reg(struct fusb300 *fusb300,
+                     struct fusb300_ep_info info)
+{
+       fusb300_set_eptype(fusb300, info);
+       fusb300_set_epdir(fusb300, info);
+       fusb300_set_epmps(fusb300, info);
+
+       if (info.interval)
+               fusb300_set_interval(fusb300, info);
+
+       if (info.bw_num)
+               fusb300_set_bwnum(fusb300, info);
+
+       fusb300_set_ep_active(fusb300, info.epnum);
+}
+
+static int config_ep(struct fusb300_ep *ep,
+                    const struct usb_endpoint_descriptor *desc)
+{
+       struct fusb300 *fusb300 = ep->fusb300;
+       struct fusb300_ep_info info;
+
+       ep->ep.desc = desc;
+
+       info.interval = 0;
+       info.addrofs = 0;
+       info.bw_num = 0;
+
+       info.type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+       info.dir_in = (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? 1 : 0;
+       info.maxpacket = usb_endpoint_maxp(desc);
+       info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+
+       if ((info.type == USB_ENDPOINT_XFER_INT) ||
+          (info.type == USB_ENDPOINT_XFER_ISOC)) {
+               info.interval = desc->bInterval;
+               if (info.type == USB_ENDPOINT_XFER_ISOC)
+                       info.bw_num = ((desc->wMaxPacketSize & 0x1800) >> 11);
+       }
+
+       ep_fifo_setting(fusb300, info);
+
+       set_ep_reg(fusb300, info);
+
+       fusb300_ep_setting(ep, info);
+
+       fusb300->ep[info.epnum] = ep;
+
+       return 0;
+}
+
+static int fusb300_enable(struct usb_ep *_ep,
+                         const struct usb_endpoint_descriptor *desc)
+{
+       struct fusb300_ep *ep;
+
+       ep = container_of(_ep, struct fusb300_ep, ep);
+
+       if (ep->fusb300->reenum) {
+               ep->fusb300->fifo_entry_num = 0;
+               ep->fusb300->addrofs = 0;
+               ep->fusb300->reenum = 0;
+       }
+
+       return config_ep(ep, desc);
+}
+
+static int fusb300_disable(struct usb_ep *_ep)
+{
+       struct fusb300_ep *ep;
+       struct fusb300_request *req;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct fusb300_ep, ep);
+
+       BUG_ON(!ep);
+
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct fusb300_request, queue);
+               spin_lock_irqsave(&ep->fusb300->lock, flags);
+               done(ep, req, -ECONNRESET);
+               spin_unlock_irqrestore(&ep->fusb300->lock, flags);
+       }
+
+       return fusb300_ep_release(ep);
+}
+
+static struct usb_request *fusb300_alloc_request(struct usb_ep *_ep,
+                                               gfp_t gfp_flags)
+{
+       struct fusb300_request *req;
+
+       req = kzalloc(sizeof(struct fusb300_request), gfp_flags);
+       if (!req)
+               return NULL;
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void fusb300_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct fusb300_request *req;
+
+       req = container_of(_req, struct fusb300_request, req);
+       kfree(req);
+}
+
+static int enable_fifo_int(struct fusb300_ep *ep)
+{
+       struct fusb300 *fusb300 = ep->fusb300;
+
+       if (ep->epnum) {
+               fusb300_enable_bit(fusb300, FUSB300_OFFSET_IGER0,
+                       FUSB300_IGER0_EEPn_FIFO_INT(ep->epnum));
+       } else {
+               pr_err("can't enable_fifo_int ep0\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int disable_fifo_int(struct fusb300_ep *ep)
+{
+       struct fusb300 *fusb300 = ep->fusb300;
+
+       if (ep->epnum) {
+               fusb300_disable_bit(fusb300, FUSB300_OFFSET_IGER0,
+                       FUSB300_IGER0_EEPn_FIFO_INT(ep->epnum));
+       } else {
+               pr_err("can't disable_fifo_int ep0\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void fusb300_set_cxlen(struct fusb300 *fusb300, u32 length)
+{
+       u32 reg;
+
+       reg = ioread32(fusb300->reg + FUSB300_OFFSET_CSR);
+       reg &= ~FUSB300_CSR_LEN_MSK;
+       reg |= FUSB300_CSR_LEN(length);
+       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_CSR);
+}
+
+/* write data to cx fifo */
+static void fusb300_wrcxf(struct fusb300_ep *ep,
+                  struct fusb300_request *req)
+{
+       int i = 0;
+       u8 *tmp;
+       u32 data;
+       struct fusb300 *fusb300 = ep->fusb300;
+       u32 length = req->req.length - req->req.actual;
+
+       tmp = req->req.buf + req->req.actual;
+
+       if (length > SS_CTL_MAX_PACKET_SIZE) {
+               fusb300_set_cxlen(fusb300, SS_CTL_MAX_PACKET_SIZE);
+               for (i = (SS_CTL_MAX_PACKET_SIZE >> 2); i > 0; i--) {
+                       data = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16 |
+                               *(tmp + 3) << 24;
+                       iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
+                       tmp += 4;
+               }
+               req->req.actual += SS_CTL_MAX_PACKET_SIZE;
+       } else { /* length is less than max packet size */
+               fusb300_set_cxlen(fusb300, length);
+               for (i = length >> 2; i > 0; i--) {
+                       data = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16 |
+                               *(tmp + 3) << 24;
+                       printk(KERN_DEBUG "    0x%x\n", data);
+                       iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
+                       tmp = tmp + 4;
+               }
+               switch (length % 4) {
+               case 1:
+                       data = *tmp;
+                       printk(KERN_DEBUG "    0x%x\n", data);
+                       iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
+                       break;
+               case 2:
+                       data = *tmp | *(tmp + 1) << 8;
+                       printk(KERN_DEBUG "    0x%x\n", data);
+                       iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
+                       break;
+               case 3:
+                       data = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16;
+                       printk(KERN_DEBUG "    0x%x\n", data);
+                       iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
+                       break;
+               default:
+                       break;
+               }
+               req->req.actual += length;
+       }
+}
+
+static void fusb300_set_epnstall(struct fusb300 *fusb300, u8 ep)
+{
+       fusb300_enable_bit(fusb300, FUSB300_OFFSET_EPSET0(ep),
+               FUSB300_EPSET0_STL);
+}
+
+static void fusb300_clear_epnstall(struct fusb300 *fusb300, u8 ep)
+{
+       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
+
+       if (reg & FUSB300_EPSET0_STL) {
+               printk(KERN_DEBUG "EP%d stall... Clear!!\n", ep);
+               reg |= FUSB300_EPSET0_STL_CLR;
+               iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
+       }
+}
+
+static void ep0_queue(struct fusb300_ep *ep, struct fusb300_request *req)
+{
+       if (ep->fusb300->ep0_dir) { /* if IN */
+               if (req->req.length) {
+                       fusb300_wrcxf(ep, req);
+               } else
+                       printk(KERN_DEBUG "%s : req->req.length = 0x%x\n",
+                               __func__, req->req.length);
+               if ((req->req.length == req->req.actual) ||
+                   (req->req.actual < ep->ep.maxpacket))
+                       done(ep, req, 0);
+       } else { /* OUT */
+               if (!req->req.length)
+                       done(ep, req, 0);
+               else
+                       fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER1,
+                               FUSB300_IGER1_CX_OUT_INT);
+       }
+}
+
+static int fusb300_queue(struct usb_ep *_ep, struct usb_request *_req,
+                        gfp_t gfp_flags)
+{
+       struct fusb300_ep *ep;
+       struct fusb300_request *req;
+       unsigned long flags;
+       int request  = 0;
+
+       ep = container_of(_ep, struct fusb300_ep, ep);
+       req = container_of(_req, struct fusb300_request, req);
+
+       if (ep->fusb300->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       spin_lock_irqsave(&ep->fusb300->lock, flags);
+
+       if (list_empty(&ep->queue))
+               request = 1;
+
+       list_add_tail(&req->queue, &ep->queue);
+
+       req->req.actual = 0;
+       req->req.status = -EINPROGRESS;
+
+       if (ep->ep.desc == NULL) /* ep0 */
+               ep0_queue(ep, req);
+       else if (request && !ep->stall)
+               enable_fifo_int(ep);
+
+       spin_unlock_irqrestore(&ep->fusb300->lock, flags);
+
+       return 0;
+}
+
+static int fusb300_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct fusb300_ep *ep;
+       struct fusb300_request *req;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct fusb300_ep, ep);
+       req = container_of(_req, struct fusb300_request, req);
+
+       spin_lock_irqsave(&ep->fusb300->lock, flags);
+       if (!list_empty(&ep->queue))
+               done(ep, req, -ECONNRESET);
+       spin_unlock_irqrestore(&ep->fusb300->lock, flags);
+
+       return 0;
+}
+
+static int fusb300_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedge)
+{
+       struct fusb300_ep *ep;
+       struct fusb300 *fusb300;
+       unsigned long flags;
+       int ret = 0;
+
+       ep = container_of(_ep, struct fusb300_ep, ep);
+
+       fusb300 = ep->fusb300;
+
+       spin_lock_irqsave(&ep->fusb300->lock, flags);
+
+       if (!list_empty(&ep->queue)) {
+               ret = -EAGAIN;
+               goto out;
+       }
+
+       if (value) {
+               fusb300_set_epnstall(fusb300, ep->epnum);
+               ep->stall = 1;
+               if (wedge)
+                       ep->wedged = 1;
+       } else {
+               fusb300_clear_epnstall(fusb300, ep->epnum);
+               ep->stall = 0;
+               ep->wedged = 0;
+       }
+
+out:
+       spin_unlock_irqrestore(&ep->fusb300->lock, flags);
+       return ret;
+}
+
+static int fusb300_set_halt(struct usb_ep *_ep, int value)
+{
+       return fusb300_set_halt_and_wedge(_ep, value, 0);
+}
+
+static int fusb300_set_wedge(struct usb_ep *_ep)
+{
+       return fusb300_set_halt_and_wedge(_ep, 1, 1);
+}
+
+static void fusb300_fifo_flush(struct usb_ep *_ep)
+{
+}
+
+static struct usb_ep_ops fusb300_ep_ops = {
+       .enable         = fusb300_enable,
+       .disable        = fusb300_disable,
+
+       .alloc_request  = fusb300_alloc_request,
+       .free_request   = fusb300_free_request,
+
+       .queue          = fusb300_queue,
+       .dequeue        = fusb300_dequeue,
+
+       .set_halt       = fusb300_set_halt,
+       .fifo_flush     = fusb300_fifo_flush,
+       .set_wedge      = fusb300_set_wedge,
+};
+
+/*****************************************************************************/
+static void fusb300_clear_int(struct fusb300 *fusb300, u32 offset,
+                      u32 value)
+{
+       iowrite32(value, fusb300->reg + offset);
+}
+
+static void fusb300_reset(void)
+{
+}
+
+static void fusb300_set_cxstall(struct fusb300 *fusb300)
+{
+       fusb300_enable_bit(fusb300, FUSB300_OFFSET_CSR,
+                          FUSB300_CSR_STL);
+}
+
+static void fusb300_set_cxdone(struct fusb300 *fusb300)
+{
+       fusb300_enable_bit(fusb300, FUSB300_OFFSET_CSR,
+                          FUSB300_CSR_DONE);
+}
+
+/* read data from cx fifo */
+static void fusb300_rdcxf(struct fusb300 *fusb300,
+                  u8 *buffer, u32 length)
+{
+       int i = 0;
+       u8 *tmp;
+       u32 data;
+
+       tmp = buffer;
+
+       for (i = (length >> 2); i > 0; i--) {
+               data = ioread32(fusb300->reg + FUSB300_OFFSET_CXPORT);
+               printk(KERN_DEBUG "    0x%x\n", data);
+               *tmp = data & 0xFF;
+               *(tmp + 1) = (data >> 8) & 0xFF;
+               *(tmp + 2) = (data >> 16) & 0xFF;
+               *(tmp + 3) = (data >> 24) & 0xFF;
+               tmp = tmp + 4;
+       }
+
+       switch (length % 4) {
+       case 1:
+               data = ioread32(fusb300->reg + FUSB300_OFFSET_CXPORT);
+               printk(KERN_DEBUG "    0x%x\n", data);
+               *tmp = data & 0xFF;
+               break;
+       case 2:
+               data = ioread32(fusb300->reg + FUSB300_OFFSET_CXPORT);
+               printk(KERN_DEBUG "    0x%x\n", data);
+               *tmp = data & 0xFF;
+               *(tmp + 1) = (data >> 8) & 0xFF;
+               break;
+       case 3:
+               data = ioread32(fusb300->reg + FUSB300_OFFSET_CXPORT);
+               printk(KERN_DEBUG "    0x%x\n", data);
+               *tmp = data & 0xFF;
+               *(tmp + 1) = (data >> 8) & 0xFF;
+               *(tmp + 2) = (data >> 16) & 0xFF;
+               break;
+       default:
+               break;
+       }
+}
+
+static void fusb300_rdfifo(struct fusb300_ep *ep,
+                         struct fusb300_request *req,
+                         u32 length)
+{
+       int i = 0;
+       u8 *tmp;
+       u32 data, reg;
+       struct fusb300 *fusb300 = ep->fusb300;
+
+       tmp = req->req.buf + req->req.actual;
+       req->req.actual += length;
+
+       if (req->req.actual > req->req.length)
+               printk(KERN_DEBUG "req->req.actual > req->req.length\n");
+
+       for (i = (length >> 2); i > 0; i--) {
+               data = ioread32(fusb300->reg +
+                       FUSB300_OFFSET_EPPORT(ep->epnum));
+               *tmp = data & 0xFF;
+               *(tmp + 1) = (data >> 8) & 0xFF;
+               *(tmp + 2) = (data >> 16) & 0xFF;
+               *(tmp + 3) = (data >> 24) & 0xFF;
+               tmp = tmp + 4;
+       }
+
+       switch (length % 4) {
+       case 1:
+               data = ioread32(fusb300->reg +
+                       FUSB300_OFFSET_EPPORT(ep->epnum));
+               *tmp = data & 0xFF;
+               break;
+       case 2:
+               data = ioread32(fusb300->reg +
+                       FUSB300_OFFSET_EPPORT(ep->epnum));
+               *tmp = data & 0xFF;
+               *(tmp + 1) = (data >> 8) & 0xFF;
+               break;
+       case 3:
+               data = ioread32(fusb300->reg +
+                       FUSB300_OFFSET_EPPORT(ep->epnum));
+               *tmp = data & 0xFF;
+               *(tmp + 1) = (data >> 8) & 0xFF;
+               *(tmp + 2) = (data >> 16) & 0xFF;
+               break;
+       default:
+               break;
+       }
+
+       do {
+               reg = ioread32(fusb300->reg + FUSB300_OFFSET_IGR1);
+               reg &= FUSB300_IGR1_SYNF0_EMPTY_INT;
+               if (i)
+                       printk(KERN_INFO "sync fifo is not empty!\n");
+               i++;
+       } while (!reg);
+}
+
+static u8 fusb300_get_epnstall(struct fusb300 *fusb300, u8 ep)
+{
+       u8 value;
+       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
+
+       value = reg & FUSB300_EPSET0_STL;
+
+       return value;
+}
+
+static u8 fusb300_get_cxstall(struct fusb300 *fusb300)
+{
+       u8 value;
+       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_CSR);
+
+       value = (reg & FUSB300_CSR_STL) >> 1;
+
+       return value;
+}
+
+static void request_error(struct fusb300 *fusb300)
+{
+       fusb300_set_cxstall(fusb300);
+       printk(KERN_DEBUG "request error!!\n");
+}
+
+static void get_status(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
+__releases(fusb300->lock)
+__acquires(fusb300->lock)
+{
+       u8 ep;
+       u16 status = 0;
+       u16 w_index = ctrl->wIndex;
+
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               status = 1 << USB_DEVICE_SELF_POWERED;
+               break;
+       case USB_RECIP_INTERFACE:
+               status = 0;
+               break;
+       case USB_RECIP_ENDPOINT:
+               ep = w_index & USB_ENDPOINT_NUMBER_MASK;
+               if (ep) {
+                       if (fusb300_get_epnstall(fusb300, ep))
+                               status = 1 << USB_ENDPOINT_HALT;
+               } else {
+                       if (fusb300_get_cxstall(fusb300))
+                               status = 0;
+               }
+               break;
+
+       default:
+               request_error(fusb300);
+               return;         /* exit */
+       }
+
+       fusb300->ep0_data = cpu_to_le16(status);
+       fusb300->ep0_req->buf = &fusb300->ep0_data;
+       fusb300->ep0_req->length = 2;
+
+       spin_unlock(&fusb300->lock);
+       fusb300_queue(fusb300->gadget.ep0, fusb300->ep0_req, GFP_KERNEL);
+       spin_lock(&fusb300->lock);
+}
+
+static void set_feature(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
+{
+       u8 ep;
+
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               fusb300_set_cxdone(fusb300);
+               break;
+       case USB_RECIP_INTERFACE:
+               fusb300_set_cxdone(fusb300);
+               break;
+       case USB_RECIP_ENDPOINT: {
+               u16 w_index = le16_to_cpu(ctrl->wIndex);
+
+               ep = w_index & USB_ENDPOINT_NUMBER_MASK;
+               if (ep)
+                       fusb300_set_epnstall(fusb300, ep);
+               else
+                       fusb300_set_cxstall(fusb300);
+               fusb300_set_cxdone(fusb300);
+               }
+               break;
+       default:
+               request_error(fusb300);
+               break;
+       }
+}
+
+static void fusb300_clear_seqnum(struct fusb300 *fusb300, u8 ep)
+{
+       fusb300_enable_bit(fusb300, FUSB300_OFFSET_EPSET0(ep),
+                           FUSB300_EPSET0_CLRSEQNUM);
+}
+
+static void clear_feature(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
+{
+       struct fusb300_ep *ep =
+               fusb300->ep[ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK];
+
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               fusb300_set_cxdone(fusb300);
+               break;
+       case USB_RECIP_INTERFACE:
+               fusb300_set_cxdone(fusb300);
+               break;
+       case USB_RECIP_ENDPOINT:
+               if (ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK) {
+                       if (ep->wedged) {
+                               fusb300_set_cxdone(fusb300);
+                               break;
+                       }
+                       if (ep->stall) {
+                               ep->stall = 0;
+                               fusb300_clear_seqnum(fusb300, ep->epnum);
+                               fusb300_clear_epnstall(fusb300, ep->epnum);
+                               if (!list_empty(&ep->queue))
+                                       enable_fifo_int(ep);
+                       }
+               }
+               fusb300_set_cxdone(fusb300);
+               break;
+       default:
+               request_error(fusb300);
+               break;
+       }
+}
+
+static void fusb300_set_dev_addr(struct fusb300 *fusb300, u16 addr)
+{
+       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_DAR);
+
+       reg &= ~FUSB300_DAR_DRVADDR_MSK;
+       reg |= FUSB300_DAR_DRVADDR(addr);
+
+       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_DAR);
+}
+
+static void set_address(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
+{
+       if (ctrl->wValue >= 0x0100)
+               request_error(fusb300);
+       else {
+               fusb300_set_dev_addr(fusb300, ctrl->wValue);
+               fusb300_set_cxdone(fusb300);
+       }
+}
+
+#define UVC_COPY_DESCRIPTORS(mem, src) \
+       do { \
+               const struct usb_descriptor_header * const *__src; \
+               for (__src = src; *__src; ++__src) { \
+                       memcpy(mem, *__src, (*__src)->bLength); \
+                       mem += (*__src)->bLength; \
+               } \
+       } while (0)
+
+static int setup_packet(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
+{
+       u8 *p = (u8 *)ctrl;
+       u8 ret = 0;
+       u8 i = 0;
+
+       fusb300_rdcxf(fusb300, p, 8);
+       fusb300->ep0_dir = ctrl->bRequestType & USB_DIR_IN;
+       fusb300->ep0_length = ctrl->wLength;
+
+       /* check request */
+       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+               switch (ctrl->bRequest) {
+               case USB_REQ_GET_STATUS:
+                       get_status(fusb300, ctrl);
+                       break;
+               case USB_REQ_CLEAR_FEATURE:
+                       clear_feature(fusb300, ctrl);
+                       break;
+               case USB_REQ_SET_FEATURE:
+                       set_feature(fusb300, ctrl);
+                       break;
+               case USB_REQ_SET_ADDRESS:
+                       set_address(fusb300, ctrl);
+                       break;
+               case USB_REQ_SET_CONFIGURATION:
+                       fusb300_enable_bit(fusb300, FUSB300_OFFSET_DAR,
+                                          FUSB300_DAR_SETCONFG);
+                       /* clear sequence number */
+                       for (i = 1; i <= FUSB300_MAX_NUM_EP; i++)
+                               fusb300_clear_seqnum(fusb300, i);
+                       fusb300->reenum = 1;
+                       ret = 1;
+                       break;
+               default:
+                       ret = 1;
+                       break;
+               }
+       } else
+               ret = 1;
+
+       return ret;
+}
+
+static void done(struct fusb300_ep *ep, struct fusb300_request *req,
+                int status)
+{
+       list_del_init(&req->queue);
+
+       /* don't modify queue heads during completion callback */
+       if (ep->fusb300->gadget.speed == USB_SPEED_UNKNOWN)
+               req->req.status = -ESHUTDOWN;
+       else
+               req->req.status = status;
+
+       spin_unlock(&ep->fusb300->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&ep->fusb300->lock);
+
+       if (ep->epnum) {
+               disable_fifo_int(ep);
+               if (!list_empty(&ep->queue))
+                       enable_fifo_int(ep);
+       } else
+               fusb300_set_cxdone(ep->fusb300);
+}
+
+static void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep, dma_addr_t d,
+               u32 len)
+{
+       u32 value;
+       u32 reg;
+
+       /* wait SW owner */
+       do {
+               reg = ioread32(ep->fusb300->reg +
+                       FUSB300_OFFSET_EPPRD_W0(ep->epnum));
+               reg &= FUSB300_EPPRD0_H;
+       } while (reg);
+
+       iowrite32(d, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W1(ep->epnum));
+
+       value = FUSB300_EPPRD0_BTC(len) | FUSB300_EPPRD0_H |
+               FUSB300_EPPRD0_F | FUSB300_EPPRD0_L | FUSB300_EPPRD0_I;
+       iowrite32(value, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W0(ep->epnum));
+
+       iowrite32(0x0, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W2(ep->epnum));
+
+       fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_EPPRDRDY,
+               FUSB300_EPPRDR_EP_PRD_RDY(ep->epnum));
+}
+
+static void fusb300_wait_idma_finished(struct fusb300_ep *ep)
+{
+       u32 reg;
+
+       do {
+               reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGR1);
+               if ((reg & FUSB300_IGR1_VBUS_CHG_INT) ||
+                   (reg & FUSB300_IGR1_WARM_RST_INT) ||
+                   (reg & FUSB300_IGR1_HOT_RST_INT) ||
+                   (reg & FUSB300_IGR1_USBRST_INT)
+               )
+                       goto IDMA_RESET;
+               reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGR0);
+               reg &= FUSB300_IGR0_EPn_PRD_INT(ep->epnum);
+       } while (!reg);
+
+       fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0,
+               FUSB300_IGR0_EPn_PRD_INT(ep->epnum));
+       return;
+
+IDMA_RESET:
+       reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGER0);
+       reg &= ~FUSB300_IGER0_EEPn_PRD_INT(ep->epnum);
+       iowrite32(reg, ep->fusb300->reg + FUSB300_OFFSET_IGER0);
+}
+
+static void fusb300_set_idma(struct fusb300_ep *ep,
+                       struct fusb300_request *req)
+{
+       int ret;
+
+       ret = usb_gadget_map_request(&ep->fusb300->gadget,
+                       &req->req, DMA_TO_DEVICE);
+       if (ret)
+               return;
+
+       fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,
+               FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
+
+       fusb300_fill_idma_prdtbl(ep, req->req.dma, req->req.length);
+       /* check idma is done */
+       fusb300_wait_idma_finished(ep);
+
+       usb_gadget_unmap_request(&ep->fusb300->gadget,
+                       &req->req, DMA_TO_DEVICE);
+}
+
+static void in_ep_fifo_handler(struct fusb300_ep *ep)
+{
+       struct fusb300_request *req = list_entry(ep->queue.next,
+                                       struct fusb300_request, queue);
+
+       if (req->req.length)
+               fusb300_set_idma(ep, req);
+       done(ep, req, 0);
+}
+
+static void out_ep_fifo_handler(struct fusb300_ep *ep)
+{
+       struct fusb300 *fusb300 = ep->fusb300;
+       struct fusb300_request *req = list_entry(ep->queue.next,
+                                                struct fusb300_request, queue);
+       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPFFR(ep->epnum));
+       u32 length = reg & FUSB300_FFR_BYCNT;
+
+       fusb300_rdfifo(ep, req, length);
+
+       /* finish out transfer */
+       if ((req->req.length == req->req.actual) || (length < ep->ep.maxpacket))
+               done(ep, req, 0);
+}
+
+static void check_device_mode(struct fusb300 *fusb300)
+{
+       u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_GCR);
+
+       switch (reg & FUSB300_GCR_DEVEN_MSK) {
+       case FUSB300_GCR_DEVEN_SS:
+               fusb300->gadget.speed = USB_SPEED_SUPER;
+               break;
+       case FUSB300_GCR_DEVEN_HS:
+               fusb300->gadget.speed = USB_SPEED_HIGH;
+               break;
+       case FUSB300_GCR_DEVEN_FS:
+               fusb300->gadget.speed = USB_SPEED_FULL;
+               break;
+       default:
+               fusb300->gadget.speed = USB_SPEED_UNKNOWN;
+               break;
+       }
+       printk(KERN_INFO "dev_mode = %d\n", (reg & FUSB300_GCR_DEVEN_MSK));
+}
+
+
+static void fusb300_ep0out(struct fusb300 *fusb300)
+{
+       struct fusb300_ep *ep = fusb300->ep[0];
+       u32 reg;
+
+       if (!list_empty(&ep->queue)) {
+               struct fusb300_request *req;
+
+               req = list_first_entry(&ep->queue,
+                       struct fusb300_request, queue);
+               if (req->req.length)
+                       fusb300_rdcxf(ep->fusb300, req->req.buf,
+                               req->req.length);
+               done(ep, req, 0);
+               reg = ioread32(fusb300->reg + FUSB300_OFFSET_IGER1);
+               reg &= ~FUSB300_IGER1_CX_OUT_INT;
+               iowrite32(reg, fusb300->reg + FUSB300_OFFSET_IGER1);
+       } else
+               pr_err("%s : empty queue\n", __func__);
+}
+
+static void fusb300_ep0in(struct fusb300 *fusb300)
+{
+       struct fusb300_request *req;
+       struct fusb300_ep *ep = fusb300->ep[0];
+
+       if ((!list_empty(&ep->queue)) && (fusb300->ep0_dir)) {
+               req = list_entry(ep->queue.next,
+                               struct fusb300_request, queue);
+               if (req->req.length)
+                       fusb300_wrcxf(ep, req);
+               if ((req->req.length - req->req.actual) < ep->ep.maxpacket)
+                       done(ep, req, 0);
+       } else
+               fusb300_set_cxdone(fusb300);
+}
+
+static void fusb300_grp2_handler(void)
+{
+}
+
+static void fusb300_grp3_handler(void)
+{
+}
+
+static void fusb300_grp4_handler(void)
+{
+}
+
+static void fusb300_grp5_handler(void)
+{
+}
+
+static irqreturn_t fusb300_irq(int irq, void *_fusb300)
+{
+       struct fusb300 *fusb300 = _fusb300;
+       u32 int_grp1 = ioread32(fusb300->reg + FUSB300_OFFSET_IGR1);
+       u32 int_grp1_en = ioread32(fusb300->reg + FUSB300_OFFSET_IGER1);
+       u32 int_grp0 = ioread32(fusb300->reg + FUSB300_OFFSET_IGR0);
+       u32 int_grp0_en = ioread32(fusb300->reg + FUSB300_OFFSET_IGER0);
+       struct usb_ctrlrequest ctrl;
+       u8 in;
+       u32 reg;
+       int i;
+
+       spin_lock(&fusb300->lock);
+
+       int_grp1 &= int_grp1_en;
+       int_grp0 &= int_grp0_en;
+
+       if (int_grp1 & FUSB300_IGR1_WARM_RST_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_WARM_RST_INT);
+               printk(KERN_INFO"fusb300_warmreset\n");
+               fusb300_reset();
+       }
+
+       if (int_grp1 & FUSB300_IGR1_HOT_RST_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_HOT_RST_INT);
+               printk(KERN_INFO"fusb300_hotreset\n");
+               fusb300_reset();
+       }
+
+       if (int_grp1 & FUSB300_IGR1_USBRST_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_USBRST_INT);
+               fusb300_reset();
+       }
+       /* COMABT_INT has a highest priority */
+
+       if (int_grp1 & FUSB300_IGR1_CX_COMABT_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_CX_COMABT_INT);
+               printk(KERN_INFO"fusb300_ep0abt\n");
+       }
+
+       if (int_grp1 & FUSB300_IGR1_VBUS_CHG_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_VBUS_CHG_INT);
+               printk(KERN_INFO"fusb300_vbus_change\n");
+       }
+
+       if (int_grp1 & FUSB300_IGR1_U3_EXIT_FAIL_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_U3_EXIT_FAIL_INT);
+       }
+
+       if (int_grp1 & FUSB300_IGR1_U2_EXIT_FAIL_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_U2_EXIT_FAIL_INT);
+       }
+
+       if (int_grp1 & FUSB300_IGR1_U1_EXIT_FAIL_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_U1_EXIT_FAIL_INT);
+       }
+
+       if (int_grp1 & FUSB300_IGR1_U2_ENTRY_FAIL_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_U2_ENTRY_FAIL_INT);
+       }
+
+       if (int_grp1 & FUSB300_IGR1_U1_ENTRY_FAIL_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_U1_ENTRY_FAIL_INT);
+       }
+
+       if (int_grp1 & FUSB300_IGR1_U3_EXIT_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_U3_EXIT_INT);
+               printk(KERN_INFO "FUSB300_IGR1_U3_EXIT_INT\n");
+       }
+
+       if (int_grp1 & FUSB300_IGR1_U2_EXIT_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_U2_EXIT_INT);
+               printk(KERN_INFO "FUSB300_IGR1_U2_EXIT_INT\n");
+       }
+
+       if (int_grp1 & FUSB300_IGR1_U1_EXIT_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_U1_EXIT_INT);
+               printk(KERN_INFO "FUSB300_IGR1_U1_EXIT_INT\n");
+       }
+
+       if (int_grp1 & FUSB300_IGR1_U3_ENTRY_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_U3_ENTRY_INT);
+               printk(KERN_INFO "FUSB300_IGR1_U3_ENTRY_INT\n");
+               fusb300_enable_bit(fusb300, FUSB300_OFFSET_SSCR1,
+                                  FUSB300_SSCR1_GO_U3_DONE);
+       }
+
+       if (int_grp1 & FUSB300_IGR1_U2_ENTRY_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_U2_ENTRY_INT);
+               printk(KERN_INFO "FUSB300_IGR1_U2_ENTRY_INT\n");
+       }
+
+       if (int_grp1 & FUSB300_IGR1_U1_ENTRY_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_U1_ENTRY_INT);
+               printk(KERN_INFO "FUSB300_IGR1_U1_ENTRY_INT\n");
+       }
+
+       if (int_grp1 & FUSB300_IGR1_RESM_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_RESM_INT);
+               printk(KERN_INFO "fusb300_resume\n");
+       }
+
+       if (int_grp1 & FUSB300_IGR1_SUSP_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_SUSP_INT);
+               printk(KERN_INFO "fusb300_suspend\n");
+       }
+
+       if (int_grp1 & FUSB300_IGR1_HS_LPM_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_HS_LPM_INT);
+               printk(KERN_INFO "fusb300_HS_LPM_INT\n");
+       }
+
+       if (int_grp1 & FUSB300_IGR1_DEV_MODE_CHG_INT) {
+               fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+                                 FUSB300_IGR1_DEV_MODE_CHG_INT);
+               check_device_mode(fusb300);
+       }
+
+       if (int_grp1 & FUSB300_IGR1_CX_COMFAIL_INT) {
+               fusb300_set_cxstall(fusb300);
+               printk(KERN_INFO "fusb300_ep0fail\n");
+       }
+
+       if (int_grp1 & FUSB300_IGR1_CX_SETUP_INT) {
+               printk(KERN_INFO "fusb300_ep0setup\n");
+               if (setup_packet(fusb300, &ctrl)) {
+                       spin_unlock(&fusb300->lock);
+                       if (fusb300->driver->setup(&fusb300->gadget, &ctrl) < 0)
+                               fusb300_set_cxstall(fusb300);
+                       spin_lock(&fusb300->lock);
+               }
+       }
+
+       if (int_grp1 & FUSB300_IGR1_CX_CMDEND_INT)
+               printk(KERN_INFO "fusb300_cmdend\n");
+
+
+       if (int_grp1 & FUSB300_IGR1_CX_OUT_INT) {
+               printk(KERN_INFO "fusb300_cxout\n");
+               fusb300_ep0out(fusb300);
+       }
+
+       if (int_grp1 & FUSB300_IGR1_CX_IN_INT) {
+               printk(KERN_INFO "fusb300_cxin\n");
+               fusb300_ep0in(fusb300);
+       }
+
+       if (int_grp1 & FUSB300_IGR1_INTGRP5)
+               fusb300_grp5_handler();
+
+       if (int_grp1 & FUSB300_IGR1_INTGRP4)
+               fusb300_grp4_handler();
+
+       if (int_grp1 & FUSB300_IGR1_INTGRP3)
+               fusb300_grp3_handler();
+
+       if (int_grp1 & FUSB300_IGR1_INTGRP2)
+               fusb300_grp2_handler();
+
+       if (int_grp0) {
+               for (i = 1; i < FUSB300_MAX_NUM_EP; i++) {
+                       if (int_grp0 & FUSB300_IGR0_EPn_FIFO_INT(i)) {
+                               reg = ioread32(fusb300->reg +
+                                       FUSB300_OFFSET_EPSET1(i));
+                               in = (reg & FUSB300_EPSET1_DIRIN) ? 1 : 0;
+                               if (in)
+                                       in_ep_fifo_handler(fusb300->ep[i]);
+                               else
+                                       out_ep_fifo_handler(fusb300->ep[i]);
+                       }
+               }
+       }
+
+       spin_unlock(&fusb300->lock);
+
+       return IRQ_HANDLED;
+}
+
+static void fusb300_set_u2_timeout(struct fusb300 *fusb300,
+                                  u32 time)
+{
+       u32 reg;
+
+       reg = ioread32(fusb300->reg + FUSB300_OFFSET_TT);
+       reg &= ~0xff;
+       reg |= FUSB300_SSCR2_U2TIMEOUT(time);
+
+       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_TT);
+}
+
+static void fusb300_set_u1_timeout(struct fusb300 *fusb300,
+                                  u32 time)
+{
+       u32 reg;
+
+       reg = ioread32(fusb300->reg + FUSB300_OFFSET_TT);
+       reg &= ~(0xff << 8);
+       reg |= FUSB300_SSCR2_U1TIMEOUT(time);
+
+       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_TT);
+}
+
+static void init_controller(struct fusb300 *fusb300)
+{
+       u32 reg;
+       u32 mask = 0;
+       u32 val = 0;
+
+       /* split on */
+       mask = val = FUSB300_AHBBCR_S0_SPLIT_ON | FUSB300_AHBBCR_S1_SPLIT_ON;
+       reg = ioread32(fusb300->reg + FUSB300_OFFSET_AHBCR);
+       reg &= ~mask;
+       reg |= val;
+       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_AHBCR);
+
+       /* enable high-speed LPM */
+       mask = val = FUSB300_HSCR_HS_LPM_PERMIT;
+       reg = ioread32(fusb300->reg + FUSB300_OFFSET_HSCR);
+       reg &= ~mask;
+       reg |= val;
+       iowrite32(reg, fusb300->reg + FUSB300_OFFSET_HSCR);
+
+       /*set u1 u2 timmer*/
+       fusb300_set_u2_timeout(fusb300, 0xff);
+       fusb300_set_u1_timeout(fusb300, 0xff);
+
+       /* enable all grp1 interrupt */
+       iowrite32(0xcfffff9f, fusb300->reg + FUSB300_OFFSET_IGER1);
+}
+/*------------------------------------------------------------------------*/
+static int fusb300_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct fusb300 *fusb300 = to_fusb300(g);
+
+       /* hook up the driver */
+       driver->driver.bus = NULL;
+       fusb300->driver = driver;
+
+       return 0;
+}
+
+static int fusb300_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct fusb300 *fusb300 = to_fusb300(g);
+
+       init_controller(fusb300);
+       fusb300->driver = NULL;
+
+       return 0;
+}
+/*--------------------------------------------------------------------------*/
+
+static int fusb300_udc_pullup(struct usb_gadget *_gadget, int is_active)
+{
+       return 0;
+}
+
+static const struct usb_gadget_ops fusb300_gadget_ops = {
+       .pullup         = fusb300_udc_pullup,
+       .udc_start      = fusb300_udc_start,
+       .udc_stop       = fusb300_udc_stop,
+};
+
+static int __exit fusb300_remove(struct platform_device *pdev)
+{
+       struct fusb300 *fusb300 = platform_get_drvdata(pdev);
+
+       usb_del_gadget_udc(&fusb300->gadget);
+       iounmap(fusb300->reg);
+       free_irq(platform_get_irq(pdev, 0), fusb300);
+
+       fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
+       kfree(fusb300);
+
+       return 0;
+}
+
+static int fusb300_probe(struct platform_device *pdev)
+{
+       struct resource *res, *ires, *ires1;
+       void __iomem *reg = NULL;
+       struct fusb300 *fusb300 = NULL;
+       struct fusb300_ep *_ep[FUSB300_MAX_NUM_EP];
+       int ret = 0;
+       int i;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENODEV;
+               pr_err("platform_get_resource error.\n");
+               goto clean_up;
+       }
+
+       ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!ires) {
+               ret = -ENODEV;
+               dev_err(&pdev->dev,
+                       "platform_get_resource IORESOURCE_IRQ error.\n");
+               goto clean_up;
+       }
+
+       ires1 = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+       if (!ires1) {
+               ret = -ENODEV;
+               dev_err(&pdev->dev,
+                       "platform_get_resource IORESOURCE_IRQ 1 error.\n");
+               goto clean_up;
+       }
+
+       reg = ioremap(res->start, resource_size(res));
+       if (reg == NULL) {
+               ret = -ENOMEM;
+               pr_err("ioremap error.\n");
+               goto clean_up;
+       }
+
+       /* initialize udc */
+       fusb300 = kzalloc(sizeof(struct fusb300), GFP_KERNEL);
+       if (fusb300 == NULL)
+               goto clean_up;
+
+       for (i = 0; i < FUSB300_MAX_NUM_EP; i++) {
+               _ep[i] = kzalloc(sizeof(struct fusb300_ep), GFP_KERNEL);
+               if (_ep[i] == NULL)
+                       goto clean_up;
+               fusb300->ep[i] = _ep[i];
+       }
+
+       spin_lock_init(&fusb300->lock);
+
+       platform_set_drvdata(pdev, fusb300);
+
+       fusb300->gadget.ops = &fusb300_gadget_ops;
+
+       fusb300->gadget.max_speed = USB_SPEED_HIGH;
+       fusb300->gadget.name = udc_name;
+       fusb300->reg = reg;
+
+       ret = request_irq(ires->start, fusb300_irq, IRQF_SHARED,
+                         udc_name, fusb300);
+       if (ret < 0) {
+               pr_err("request_irq error (%d)\n", ret);
+               goto clean_up;
+       }
+
+       ret = request_irq(ires1->start, fusb300_irq,
+                       IRQF_SHARED, udc_name, fusb300);
+       if (ret < 0) {
+               pr_err("request_irq1 error (%d)\n", ret);
+               goto clean_up;
+       }
+
+       INIT_LIST_HEAD(&fusb300->gadget.ep_list);
+
+       for (i = 0; i < FUSB300_MAX_NUM_EP ; i++) {
+               struct fusb300_ep *ep = fusb300->ep[i];
+
+               if (i != 0) {
+                       INIT_LIST_HEAD(&fusb300->ep[i]->ep.ep_list);
+                       list_add_tail(&fusb300->ep[i]->ep.ep_list,
+                                    &fusb300->gadget.ep_list);
+               }
+               ep->fusb300 = fusb300;
+               INIT_LIST_HEAD(&ep->queue);
+               ep->ep.name = fusb300_ep_name[i];
+               ep->ep.ops = &fusb300_ep_ops;
+               usb_ep_set_maxpacket_limit(&ep->ep, HS_BULK_MAX_PACKET_SIZE);
+       }
+       usb_ep_set_maxpacket_limit(&fusb300->ep[0]->ep, HS_CTL_MAX_PACKET_SIZE);
+       fusb300->ep[0]->epnum = 0;
+       fusb300->gadget.ep0 = &fusb300->ep[0]->ep;
+       INIT_LIST_HEAD(&fusb300->gadget.ep0->ep_list);
+
+       fusb300->ep0_req = fusb300_alloc_request(&fusb300->ep[0]->ep,
+                               GFP_KERNEL);
+       if (fusb300->ep0_req == NULL) {
+               ret = -ENOMEM;
+               goto clean_up3;
+       }
+
+       init_controller(fusb300);
+       ret = usb_add_gadget_udc(&pdev->dev, &fusb300->gadget);
+       if (ret)
+               goto err_add_udc;
+
+       dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
+
+       return 0;
+
+err_add_udc:
+       fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
+
+clean_up3:
+       free_irq(ires->start, fusb300);
+
+clean_up:
+       if (fusb300) {
+               if (fusb300->ep0_req)
+                       fusb300_free_request(&fusb300->ep[0]->ep,
+                               fusb300->ep0_req);
+               kfree(fusb300);
+       }
+       if (reg)
+               iounmap(reg);
+
+       return ret;
+}
+
+static struct platform_driver fusb300_driver = {
+       .remove =       __exit_p(fusb300_remove),
+       .driver         = {
+               .name = (char *) udc_name,
+               .owner  = THIS_MODULE,
+       },
+};
+
+module_platform_driver_probe(fusb300_driver, fusb300_probe);
diff --git a/drivers/usb/gadget/udc/fusb300_udc.h b/drivers/usb/gadget/udc/fusb300_udc.h
new file mode 100644 (file)
index 0000000..ae811d8
--- /dev/null
@@ -0,0 +1,678 @@
+/*
+ * Fusb300 UDC (USB gadget)
+ *
+ * Copyright (C) 2010 Faraday Technology Corp.
+ *
+ * Author : Yuan-hsin Chen <yhchen@faraday-tech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+
+#ifndef __FUSB300_UDC_H__
+#define __FUSB300_UDC_H_
+
+#include <linux/kernel.h>
+
+#define FUSB300_OFFSET_GCR             0x00
+#define FUSB300_OFFSET_GTM             0x04
+#define FUSB300_OFFSET_DAR             0x08
+#define FUSB300_OFFSET_CSR             0x0C
+#define FUSB300_OFFSET_CXPORT          0x10
+#define FUSB300_OFFSET_EPSET0(n)       (0x20 + (n - 1) * 0x30)
+#define FUSB300_OFFSET_EPSET1(n)       (0x24 + (n - 1) * 0x30)
+#define FUSB300_OFFSET_EPSET2(n)       (0x28 + (n - 1) * 0x30)
+#define FUSB300_OFFSET_EPFFR(n)                (0x2c + (n - 1) * 0x30)
+#define FUSB300_OFFSET_EPSTRID(n)      (0x40 + (n - 1) * 0x30)
+#define FUSB300_OFFSET_HSPTM           0x300
+#define FUSB300_OFFSET_HSCR            0x304
+#define FUSB300_OFFSET_SSCR0           0x308
+#define FUSB300_OFFSET_SSCR1           0x30C
+#define FUSB300_OFFSET_TT              0x310
+#define FUSB300_OFFSET_DEVNOTF         0x314
+#define FUSB300_OFFSET_DNC1            0x318
+#define FUSB300_OFFSET_CS              0x31C
+#define FUSB300_OFFSET_SOF             0x324
+#define FUSB300_OFFSET_EFCS            0x328
+#define FUSB300_OFFSET_IGR0            0x400
+#define FUSB300_OFFSET_IGR1            0x404
+#define FUSB300_OFFSET_IGR2            0x408
+#define FUSB300_OFFSET_IGR3            0x40C
+#define FUSB300_OFFSET_IGR4            0x410
+#define FUSB300_OFFSET_IGR5            0x414
+#define FUSB300_OFFSET_IGER0           0x420
+#define FUSB300_OFFSET_IGER1           0x424
+#define FUSB300_OFFSET_IGER2           0x428
+#define FUSB300_OFFSET_IGER3           0x42C
+#define FUSB300_OFFSET_IGER4           0x430
+#define FUSB300_OFFSET_IGER5           0x434
+#define FUSB300_OFFSET_DMAHMER         0x500
+#define FUSB300_OFFSET_EPPRDRDY                0x504
+#define FUSB300_OFFSET_DMAEPMR         0x508
+#define FUSB300_OFFSET_DMAENR          0x50C
+#define FUSB300_OFFSET_DMAAPR          0x510
+#define FUSB300_OFFSET_AHBCR           0x514
+#define FUSB300_OFFSET_EPPRD_W0(n)     (0x520 + (n - 1) * 0x10)
+#define FUSB300_OFFSET_EPPRD_W1(n)     (0x524 + (n - 1) * 0x10)
+#define FUSB300_OFFSET_EPPRD_W2(n)     (0x528 + (n - 1) * 0x10)
+#define FUSB300_OFFSET_EPRD_PTR(n)     (0x52C + (n - 1) * 0x10)
+#define FUSB300_OFFSET_BUFDBG_START    0x800
+#define FUSB300_OFFSET_BUFDBG_END      0xBFC
+#define FUSB300_OFFSET_EPPORT(n)       (0x1010 + (n - 1) * 0x10)
+
+/*
+ * *   Global Control Register (offset = 000H)
+ * */
+#define FUSB300_GCR_SF_RST             (1 << 8)
+#define FUSB300_GCR_VBUS_STATUS                (1 << 7)
+#define FUSB300_GCR_FORCE_HS_SUSP      (1 << 6)
+#define FUSB300_GCR_SYNC_FIFO1_CLR     (1 << 5)
+#define FUSB300_GCR_SYNC_FIFO0_CLR     (1 << 4)
+#define FUSB300_GCR_FIFOCLR            (1 << 3)
+#define FUSB300_GCR_GLINTEN            (1 << 2)
+#define FUSB300_GCR_DEVEN_FS           0x3
+#define FUSB300_GCR_DEVEN_HS           0x2
+#define FUSB300_GCR_DEVEN_SS           0x1
+#define FUSB300_GCR_DEVDIS             0x0
+#define FUSB300_GCR_DEVEN_MSK          0x3
+
+
+/*
+ * *Global Test Mode (offset = 004H)
+ * */
+#define FUSB300_GTM_TST_DIS_SOFGEN     (1 << 16)
+#define FUSB300_GTM_TST_CUR_EP_ENTRY(n)        ((n & 0xF) << 12)
+#define FUSB300_GTM_TST_EP_ENTRY(n)    ((n & 0xF) << 8)
+#define FUSB300_GTM_TST_EP_NUM(n)      ((n & 0xF) << 4)
+#define FUSB300_GTM_TST_FIFO_DEG       (1 << 1)
+#define FUSB300_GTM_TSTMODE            (1 << 0)
+
+/*
+ * * Device Address Register (offset = 008H)
+ * */
+#define FUSB300_DAR_SETCONFG   (1 << 7)
+#define FUSB300_DAR_DRVADDR(x) (x & 0x7F)
+#define FUSB300_DAR_DRVADDR_MSK        0x7F
+
+/*
+ * *Control Transfer Configuration and Status Register
+ * (CX_Config_Status, offset = 00CH)
+ * */
+#define FUSB300_CSR_LEN(x)     ((x & 0xFFFF) << 8)
+#define FUSB300_CSR_LEN_MSK    (0xFFFF << 8)
+#define FUSB300_CSR_EMP                (1 << 4)
+#define FUSB300_CSR_FUL                (1 << 3)
+#define FUSB300_CSR_CLR                (1 << 2)
+#define FUSB300_CSR_STL                (1 << 1)
+#define FUSB300_CSR_DONE       (1 << 0)
+
+/*
+ * * EPn Setting 0 (EPn_SET0, offset = 020H+(n-1)*30H, n=1~15 )
+ * */
+#define FUSB300_EPSET0_STL_CLR         (1 << 3)
+#define FUSB300_EPSET0_CLRSEQNUM       (1 << 2)
+#define FUSB300_EPSET0_STL             (1 << 0)
+
+/*
+ * * EPn Setting 1 (EPn_SET1, offset = 024H+(n-1)*30H, n=1~15)
+ * */
+#define FUSB300_EPSET1_START_ENTRY(x)  ((x & 0xFF) << 24)
+#define FUSB300_EPSET1_START_ENTRY_MSK (0xFF << 24)
+#define FUSB300_EPSET1_FIFOENTRY(x)    ((x & 0x1F) << 12)
+#define FUSB300_EPSET1_FIFOENTRY_MSK   (0x1f << 12)
+#define FUSB300_EPSET1_INTERVAL(x)     ((x & 0x7) << 6)
+#define FUSB300_EPSET1_BWNUM(x)                ((x & 0x3) << 4)
+#define FUSB300_EPSET1_TYPEISO         (1 << 2)
+#define FUSB300_EPSET1_TYPEBLK         (2 << 2)
+#define FUSB300_EPSET1_TYPEINT         (3 << 2)
+#define FUSB300_EPSET1_TYPE(x)         ((x & 0x3) << 2)
+#define FUSB300_EPSET1_TYPE_MSK                (0x3 << 2)
+#define FUSB300_EPSET1_DIROUT          (0 << 1)
+#define FUSB300_EPSET1_DIRIN           (1 << 1)
+#define FUSB300_EPSET1_DIR(x)          ((x & 0x1) << 1)
+#define FUSB300_EPSET1_DIRIN           (1 << 1)
+#define FUSB300_EPSET1_DIR_MSK         ((0x1) << 1)
+#define FUSB300_EPSET1_ACTDIS          0
+#define FUSB300_EPSET1_ACTEN           1
+
+/*
+ * *EPn Setting 2 (EPn_SET2, offset = 028H+(n-1)*30H, n=1~15)
+ * */
+#define FUSB300_EPSET2_ADDROFS(x)      ((x & 0x7FFF) << 16)
+#define FUSB300_EPSET2_ADDROFS_MSK     (0x7fff << 16)
+#define FUSB300_EPSET2_MPS(x)          (x & 0x7FF)
+#define FUSB300_EPSET2_MPS_MSK         0x7FF
+
+/*
+ * * EPn FIFO Register (offset = 2cH+(n-1)*30H)
+ * */
+#define FUSB300_FFR_RST                (1 << 31)
+#define FUSB300_FF_FUL         (1 << 30)
+#define FUSB300_FF_EMPTY       (1 << 29)
+#define FUSB300_FFR_BYCNT      0x1FFFF
+
+/*
+ * *EPn Stream ID (EPn_STR_ID, offset = 040H+(n-1)*30H, n=1~15)
+ * */
+#define FUSB300_STRID_STREN    (1 << 16)
+#define FUSB300_STRID_STRID(x) (x & 0xFFFF)
+
+/*
+ * *HS PHY Test Mode (offset = 300H)
+ * */
+#define FUSB300_HSPTM_TSTPKDONE                (1 << 4)
+#define FUSB300_HSPTM_TSTPKT           (1 << 3)
+#define FUSB300_HSPTM_TSTSET0NAK       (1 << 2)
+#define FUSB300_HSPTM_TSTKSTA          (1 << 1)
+#define FUSB300_HSPTM_TSTJSTA          (1 << 0)
+
+/*
+ * *HS Control Register (offset = 304H)
+ * */
+#define FUSB300_HSCR_HS_LPM_PERMIT     (1 << 8)
+#define FUSB300_HSCR_HS_LPM_RMWKUP     (1 << 7)
+#define FUSB300_HSCR_CAP_LPM_RMWKUP    (1 << 6)
+#define FUSB300_HSCR_HS_GOSUSP         (1 << 5)
+#define FUSB300_HSCR_HS_GORMWKU                (1 << 4)
+#define FUSB300_HSCR_CAP_RMWKUP                (1 << 3)
+#define FUSB300_HSCR_IDLECNT_0MS       0
+#define FUSB300_HSCR_IDLECNT_1MS       1
+#define FUSB300_HSCR_IDLECNT_2MS       2
+#define FUSB300_HSCR_IDLECNT_3MS       3
+#define FUSB300_HSCR_IDLECNT_4MS       4
+#define FUSB300_HSCR_IDLECNT_5MS       5
+#define FUSB300_HSCR_IDLECNT_6MS       6
+#define FUSB300_HSCR_IDLECNT_7MS       7
+
+/*
+ * * SS Controller Register 0 (offset = 308H)
+ * */
+#define FUSB300_SSCR0_MAX_INTERVAL(x)  ((x & 0x7) << 4)
+#define FUSB300_SSCR0_U2_FUN_EN                (1 << 1)
+#define FUSB300_SSCR0_U1_FUN_EN                (1 << 0)
+
+/*
+ * * SS Controller Register 1 (offset = 30CH)
+ * */
+#define FUSB300_SSCR1_GO_U3_DONE       (1 << 8)
+#define FUSB300_SSCR1_TXDEEMPH_LEVEL   (1 << 7)
+#define FUSB300_SSCR1_DIS_SCRMB                (1 << 6)
+#define FUSB300_SSCR1_FORCE_RECOVERY   (1 << 5)
+#define FUSB300_SSCR1_U3_WAKEUP_EN     (1 << 4)
+#define FUSB300_SSCR1_U2_EXIT_EN       (1 << 3)
+#define FUSB300_SSCR1_U1_EXIT_EN       (1 << 2)
+#define FUSB300_SSCR1_U2_ENTRY_EN      (1 << 1)
+#define FUSB300_SSCR1_U1_ENTRY_EN      (1 << 0)
+
+/*
+ * *SS Controller Register 2  (offset = 310H)
+ * */
+#define FUSB300_SSCR2_SS_TX_SWING              (1 << 25)
+#define FUSB300_SSCR2_FORCE_LINKPM_ACCEPT      (1 << 24)
+#define FUSB300_SSCR2_U2_INACT_TIMEOUT(x)      ((x & 0xFF) << 16)
+#define FUSB300_SSCR2_U1TIMEOUT(x)             ((x & 0xFF) << 8)
+#define FUSB300_SSCR2_U2TIMEOUT(x)             (x & 0xFF)
+
+/*
+ * *SS Device Notification Control (DEV_NOTF, offset = 314H)
+ * */
+#define FUSB300_DEVNOTF_CONTEXT0(x)            ((x & 0xFFFFFF) << 8)
+#define FUSB300_DEVNOTF_TYPE_DIS               0
+#define FUSB300_DEVNOTF_TYPE_FUNCWAKE          1
+#define FUSB300_DEVNOTF_TYPE_LTM               2
+#define FUSB300_DEVNOTF_TYPE_BUSINT_ADJMSG     3
+
+/*
+ * *BFM Arbiter Priority Register (BFM_ARB offset = 31CH)
+ * */
+#define FUSB300_BFMARB_ARB_M1  (1 << 3)
+#define FUSB300_BFMARB_ARB_M0  (1 << 2)
+#define FUSB300_BFMARB_ARB_S1  (1 << 1)
+#define FUSB300_BFMARB_ARB_S0  1
+
+/*
+ * *Vendor Specific IO Control Register (offset = 320H)
+ * */
+#define FUSB300_VSIC_VCTLOAD_N (1 << 8)
+#define FUSB300_VSIC_VCTL(x)   (x & 0x3F)
+
+/*
+ * *SOF Mask Timer (offset = 324H)
+ * */
+#define FUSB300_SOF_MASK_TIMER_HS      0x044c
+#define FUSB300_SOF_MASK_TIMER_FS      0x2710
+
+/*
+ * *Error Flag and Control Status (offset = 328H)
+ * */
+#define FUSB300_EFCS_PM_STATE_U3       3
+#define FUSB300_EFCS_PM_STATE_U2       2
+#define FUSB300_EFCS_PM_STATE_U1       1
+#define FUSB300_EFCS_PM_STATE_U0       0
+
+/*
+ * *Interrupt Group 0 Register (offset = 400H)
+ * */
+#define FUSB300_IGR0_EP15_PRD_INT      (1 << 31)
+#define FUSB300_IGR0_EP14_PRD_INT      (1 << 30)
+#define FUSB300_IGR0_EP13_PRD_INT      (1 << 29)
+#define FUSB300_IGR0_EP12_PRD_INT      (1 << 28)
+#define FUSB300_IGR0_EP11_PRD_INT      (1 << 27)
+#define FUSB300_IGR0_EP10_PRD_INT      (1 << 26)
+#define FUSB300_IGR0_EP9_PRD_INT       (1 << 25)
+#define FUSB300_IGR0_EP8_PRD_INT       (1 << 24)
+#define FUSB300_IGR0_EP7_PRD_INT       (1 << 23)
+#define FUSB300_IGR0_EP6_PRD_INT       (1 << 22)
+#define FUSB300_IGR0_EP5_PRD_INT       (1 << 21)
+#define FUSB300_IGR0_EP4_PRD_INT       (1 << 20)
+#define FUSB300_IGR0_EP3_PRD_INT       (1 << 19)
+#define FUSB300_IGR0_EP2_PRD_INT       (1 << 18)
+#define FUSB300_IGR0_EP1_PRD_INT       (1 << 17)
+#define FUSB300_IGR0_EPn_PRD_INT(n)    (1 << (n + 16))
+
+#define FUSB300_IGR0_EP15_FIFO_INT     (1 << 15)
+#define FUSB300_IGR0_EP14_FIFO_INT     (1 << 14)
+#define FUSB300_IGR0_EP13_FIFO_INT     (1 << 13)
+#define FUSB300_IGR0_EP12_FIFO_INT     (1 << 12)
+#define FUSB300_IGR0_EP11_FIFO_INT     (1 << 11)
+#define FUSB300_IGR0_EP10_FIFO_INT     (1 << 10)
+#define FUSB300_IGR0_EP9_FIFO_INT      (1 << 9)
+#define FUSB300_IGR0_EP8_FIFO_INT      (1 << 8)
+#define FUSB300_IGR0_EP7_FIFO_INT      (1 << 7)
+#define FUSB300_IGR0_EP6_FIFO_INT      (1 << 6)
+#define FUSB300_IGR0_EP5_FIFO_INT      (1 << 5)
+#define FUSB300_IGR0_EP4_FIFO_INT      (1 << 4)
+#define FUSB300_IGR0_EP3_FIFO_INT      (1 << 3)
+#define FUSB300_IGR0_EP2_FIFO_INT      (1 << 2)
+#define FUSB300_IGR0_EP1_FIFO_INT      (1 << 1)
+#define FUSB300_IGR0_EPn_FIFO_INT(n)   (1 << n)
+
+/*
+ * *Interrupt Group 1 Register (offset = 404H)
+ * */
+#define FUSB300_IGR1_INTGRP5           (1 << 31)
+#define FUSB300_IGR1_VBUS_CHG_INT      (1 << 30)
+#define FUSB300_IGR1_SYNF1_EMPTY_INT   (1 << 29)
+#define FUSB300_IGR1_SYNF0_EMPTY_INT   (1 << 28)
+#define FUSB300_IGR1_U3_EXIT_FAIL_INT  (1 << 27)
+#define FUSB300_IGR1_U2_EXIT_FAIL_INT  (1 << 26)
+#define FUSB300_IGR1_U1_EXIT_FAIL_INT  (1 << 25)
+#define FUSB300_IGR1_U2_ENTRY_FAIL_INT (1 << 24)
+#define FUSB300_IGR1_U1_ENTRY_FAIL_INT (1 << 23)
+#define FUSB300_IGR1_U3_EXIT_INT       (1 << 22)
+#define FUSB300_IGR1_U2_EXIT_INT       (1 << 21)
+#define FUSB300_IGR1_U1_EXIT_INT       (1 << 20)
+#define FUSB300_IGR1_U3_ENTRY_INT      (1 << 19)
+#define FUSB300_IGR1_U2_ENTRY_INT      (1 << 18)
+#define FUSB300_IGR1_U1_ENTRY_INT      (1 << 17)
+#define FUSB300_IGR1_HOT_RST_INT       (1 << 16)
+#define FUSB300_IGR1_WARM_RST_INT      (1 << 15)
+#define FUSB300_IGR1_RESM_INT          (1 << 14)
+#define FUSB300_IGR1_SUSP_INT          (1 << 13)
+#define FUSB300_IGR1_HS_LPM_INT                (1 << 12)
+#define FUSB300_IGR1_USBRST_INT                (1 << 11)
+#define FUSB300_IGR1_DEV_MODE_CHG_INT  (1 << 9)
+#define FUSB300_IGR1_CX_COMABT_INT     (1 << 8)
+#define FUSB300_IGR1_CX_COMFAIL_INT    (1 << 7)
+#define FUSB300_IGR1_CX_CMDEND_INT     (1 << 6)
+#define FUSB300_IGR1_CX_OUT_INT                (1 << 5)
+#define FUSB300_IGR1_CX_IN_INT         (1 << 4)
+#define FUSB300_IGR1_CX_SETUP_INT      (1 << 3)
+#define FUSB300_IGR1_INTGRP4           (1 << 2)
+#define FUSB300_IGR1_INTGRP3           (1 << 1)
+#define FUSB300_IGR1_INTGRP2           (1 << 0)
+
+/*
+ * *Interrupt Group 2 Register (offset = 408H)
+ * */
+#define FUSB300_IGR2_EP6_STR_ACCEPT_INT                (1 << 29)
+#define FUSB300_IGR2_EP6_STR_RESUME_INT                (1 << 28)
+#define FUSB300_IGR2_EP6_STR_REQ_INT           (1 << 27)
+#define FUSB300_IGR2_EP6_STR_NOTRDY_INT                (1 << 26)
+#define FUSB300_IGR2_EP6_STR_PRIME_INT         (1 << 25)
+#define FUSB300_IGR2_EP5_STR_ACCEPT_INT                (1 << 24)
+#define FUSB300_IGR2_EP5_STR_RESUME_INT                (1 << 23)
+#define FUSB300_IGR2_EP5_STR_REQ_INT           (1 << 22)
+#define FUSB300_IGR2_EP5_STR_NOTRDY_INT                (1 << 21)
+#define FUSB300_IGR2_EP5_STR_PRIME_INT         (1 << 20)
+#define FUSB300_IGR2_EP4_STR_ACCEPT_INT                (1 << 19)
+#define FUSB300_IGR2_EP4_STR_RESUME_INT                (1 << 18)
+#define FUSB300_IGR2_EP4_STR_REQ_INT           (1 << 17)
+#define FUSB300_IGR2_EP4_STR_NOTRDY_INT                (1 << 16)
+#define FUSB300_IGR2_EP4_STR_PRIME_INT         (1 << 15)
+#define FUSB300_IGR2_EP3_STR_ACCEPT_INT                (1 << 14)
+#define FUSB300_IGR2_EP3_STR_RESUME_INT                (1 << 13)
+#define FUSB300_IGR2_EP3_STR_REQ_INT           (1 << 12)
+#define FUSB300_IGR2_EP3_STR_NOTRDY_INT                (1 << 11)
+#define FUSB300_IGR2_EP3_STR_PRIME_INT         (1 << 10)
+#define FUSB300_IGR2_EP2_STR_ACCEPT_INT                (1 << 9)
+#define FUSB300_IGR2_EP2_STR_RESUME_INT                (1 << 8)
+#define FUSB300_IGR2_EP2_STR_REQ_INT           (1 << 7)
+#define FUSB300_IGR2_EP2_STR_NOTRDY_INT                (1 << 6)
+#define FUSB300_IGR2_EP2_STR_PRIME_INT         (1 << 5)
+#define FUSB300_IGR2_EP1_STR_ACCEPT_INT                (1 << 4)
+#define FUSB300_IGR2_EP1_STR_RESUME_INT                (1 << 3)
+#define FUSB300_IGR2_EP1_STR_REQ_INT           (1 << 2)
+#define FUSB300_IGR2_EP1_STR_NOTRDY_INT                (1 << 1)
+#define FUSB300_IGR2_EP1_STR_PRIME_INT         (1 << 0)
+
+#define FUSB300_IGR2_EP_STR_ACCEPT_INT(n)      (1 << (5 * n - 1))
+#define FUSB300_IGR2_EP_STR_RESUME_INT(n)      (1 << (5 * n - 2))
+#define FUSB300_IGR2_EP_STR_REQ_INT(n)         (1 << (5 * n - 3))
+#define FUSB300_IGR2_EP_STR_NOTRDY_INT(n)      (1 << (5 * n - 4))
+#define FUSB300_IGR2_EP_STR_PRIME_INT(n)       (1 << (5 * n - 5))
+
+/*
+ * *Interrupt Group 3 Register (offset = 40CH)
+ * */
+#define FUSB300_IGR3_EP12_STR_ACCEPT_INT       (1 << 29)
+#define FUSB300_IGR3_EP12_STR_RESUME_INT       (1 << 28)
+#define FUSB300_IGR3_EP12_STR_REQ_INT          (1 << 27)
+#define FUSB300_IGR3_EP12_STR_NOTRDY_INT       (1 << 26)
+#define FUSB300_IGR3_EP12_STR_PRIME_INT                (1 << 25)
+#define FUSB300_IGR3_EP11_STR_ACCEPT_INT       (1 << 24)
+#define FUSB300_IGR3_EP11_STR_RESUME_INT       (1 << 23)
+#define FUSB300_IGR3_EP11_STR_REQ_INT          (1 << 22)
+#define FUSB300_IGR3_EP11_STR_NOTRDY_INT       (1 << 21)
+#define FUSB300_IGR3_EP11_STR_PRIME_INT                (1 << 20)
+#define FUSB300_IGR3_EP10_STR_ACCEPT_INT       (1 << 19)
+#define FUSB300_IGR3_EP10_STR_RESUME_INT       (1 << 18)
+#define FUSB300_IGR3_EP10_STR_REQ_INT          (1 << 17)
+#define FUSB300_IGR3_EP10_STR_NOTRDY_INT       (1 << 16)
+#define FUSB300_IGR3_EP10_STR_PRIME_INT                (1 << 15)
+#define FUSB300_IGR3_EP9_STR_ACCEPT_INT                (1 << 14)
+#define FUSB300_IGR3_EP9_STR_RESUME_INT                (1 << 13)
+#define FUSB300_IGR3_EP9_STR_REQ_INT           (1 << 12)
+#define FUSB300_IGR3_EP9_STR_NOTRDY_INT                (1 << 11)
+#define FUSB300_IGR3_EP9_STR_PRIME_INT         (1 << 10)
+#define FUSB300_IGR3_EP8_STR_ACCEPT_INT                (1 << 9)
+#define FUSB300_IGR3_EP8_STR_RESUME_INT                (1 << 8)
+#define FUSB300_IGR3_EP8_STR_REQ_INT           (1 << 7)
+#define FUSB300_IGR3_EP8_STR_NOTRDY_INT                (1 << 6)
+#define FUSB300_IGR3_EP8_STR_PRIME_INT         (1 << 5)
+#define FUSB300_IGR3_EP7_STR_ACCEPT_INT                (1 << 4)
+#define FUSB300_IGR3_EP7_STR_RESUME_INT                (1 << 3)
+#define FUSB300_IGR3_EP7_STR_REQ_INT           (1 << 2)
+#define FUSB300_IGR3_EP7_STR_NOTRDY_INT                (1 << 1)
+#define FUSB300_IGR3_EP7_STR_PRIME_INT         (1 << 0)
+
+#define FUSB300_IGR3_EP_STR_ACCEPT_INT(n)      (1 << (5 * (n - 6) - 1))
+#define FUSB300_IGR3_EP_STR_RESUME_INT(n)      (1 << (5 * (n - 6) - 2))
+#define FUSB300_IGR3_EP_STR_REQ_INT(n)         (1 << (5 * (n - 6) - 3))
+#define FUSB300_IGR3_EP_STR_NOTRDY_INT(n)      (1 << (5 * (n - 6) - 4))
+#define FUSB300_IGR3_EP_STR_PRIME_INT(n)       (1 << (5 * (n - 6) - 5))
+
+/*
+ * *Interrupt Group 4 Register (offset = 410H)
+ * */
+#define FUSB300_IGR4_EP15_RX0_INT              (1 << 31)
+#define FUSB300_IGR4_EP14_RX0_INT              (1 << 30)
+#define FUSB300_IGR4_EP13_RX0_INT              (1 << 29)
+#define FUSB300_IGR4_EP12_RX0_INT              (1 << 28)
+#define FUSB300_IGR4_EP11_RX0_INT              (1 << 27)
+#define FUSB300_IGR4_EP10_RX0_INT              (1 << 26)
+#define FUSB300_IGR4_EP9_RX0_INT               (1 << 25)
+#define FUSB300_IGR4_EP8_RX0_INT               (1 << 24)
+#define FUSB300_IGR4_EP7_RX0_INT               (1 << 23)
+#define FUSB300_IGR4_EP6_RX0_INT               (1 << 22)
+#define FUSB300_IGR4_EP5_RX0_INT               (1 << 21)
+#define FUSB300_IGR4_EP4_RX0_INT               (1 << 20)
+#define FUSB300_IGR4_EP3_RX0_INT               (1 << 19)
+#define FUSB300_IGR4_EP2_RX0_INT               (1 << 18)
+#define FUSB300_IGR4_EP1_RX0_INT               (1 << 17)
+#define FUSB300_IGR4_EP_RX0_INT(x)             (1 << (x + 16))
+#define FUSB300_IGR4_EP15_STR_ACCEPT_INT       (1 << 14)
+#define FUSB300_IGR4_EP15_STR_RESUME_INT       (1 << 13)
+#define FUSB300_IGR4_EP15_STR_REQ_INT          (1 << 12)
+#define FUSB300_IGR4_EP15_STR_NOTRDY_INT       (1 << 11)
+#define FUSB300_IGR4_EP15_STR_PRIME_INT                (1 << 10)
+#define FUSB300_IGR4_EP14_STR_ACCEPT_INT       (1 << 9)
+#define FUSB300_IGR4_EP14_STR_RESUME_INT       (1 << 8)
+#define FUSB300_IGR4_EP14_STR_REQ_INT          (1 << 7)
+#define FUSB300_IGR4_EP14_STR_NOTRDY_INT       (1 << 6)
+#define FUSB300_IGR4_EP14_STR_PRIME_INT                (1 << 5)
+#define FUSB300_IGR4_EP13_STR_ACCEPT_INT       (1 << 4)
+#define FUSB300_IGR4_EP13_STR_RESUME_INT       (1 << 3)
+#define FUSB300_IGR4_EP13_STR_REQ_INT          (1 << 2)
+#define FUSB300_IGR4_EP13_STR_NOTRDY_INT       (1 << 1)
+#define FUSB300_IGR4_EP13_STR_PRIME_INT                (1 << 0)
+
+#define FUSB300_IGR4_EP_STR_ACCEPT_INT(n)      (1 << (5 * (n - 12) - 1))
+#define FUSB300_IGR4_EP_STR_RESUME_INT(n)      (1 << (5 * (n - 12) - 2))
+#define FUSB300_IGR4_EP_STR_REQ_INT(n)         (1 << (5 * (n - 12) - 3))
+#define FUSB300_IGR4_EP_STR_NOTRDY_INT(n)      (1 << (5 * (n - 12) - 4))
+#define FUSB300_IGR4_EP_STR_PRIME_INT(n)       (1 << (5 * (n - 12) - 5))
+
+/*
+ * *Interrupt Group 5 Register (offset = 414H)
+ * */
+#define FUSB300_IGR5_EP_STL_INT(n)     (1 << n)
+
+/*
+ * *Interrupt Enable Group 0 Register (offset = 420H)
+ * */
+#define FUSB300_IGER0_EEP15_PRD_INT    (1 << 31)
+#define FUSB300_IGER0_EEP14_PRD_INT    (1 << 30)
+#define FUSB300_IGER0_EEP13_PRD_INT    (1 << 29)
+#define FUSB300_IGER0_EEP12_PRD_INT    (1 << 28)
+#define FUSB300_IGER0_EEP11_PRD_INT    (1 << 27)
+#define FUSB300_IGER0_EEP10_PRD_INT    (1 << 26)
+#define FUSB300_IGER0_EEP9_PRD_INT     (1 << 25)
+#define FUSB300_IGER0_EP8_PRD_INT      (1 << 24)
+#define FUSB300_IGER0_EEP7_PRD_INT     (1 << 23)
+#define FUSB300_IGER0_EEP6_PRD_INT     (1 << 22)
+#define FUSB300_IGER0_EEP5_PRD_INT     (1 << 21)
+#define FUSB300_IGER0_EEP4_PRD_INT     (1 << 20)
+#define FUSB300_IGER0_EEP3_PRD_INT     (1 << 19)
+#define FUSB300_IGER0_EEP2_PRD_INT     (1 << 18)
+#define FUSB300_IGER0_EEP1_PRD_INT     (1 << 17)
+#define FUSB300_IGER0_EEPn_PRD_INT(n)  (1 << (n + 16))
+
+#define FUSB300_IGER0_EEP15_FIFO_INT   (1 << 15)
+#define FUSB300_IGER0_EEP14_FIFO_INT   (1 << 14)
+#define FUSB300_IGER0_EEP13_FIFO_INT   (1 << 13)
+#define FUSB300_IGER0_EEP12_FIFO_INT   (1 << 12)
+#define FUSB300_IGER0_EEP11_FIFO_INT   (1 << 11)
+#define FUSB300_IGER0_EEP10_FIFO_INT   (1 << 10)
+#define FUSB300_IGER0_EEP9_FIFO_INT    (1 << 9)
+#define FUSB300_IGER0_EEP8_FIFO_INT    (1 << 8)
+#define FUSB300_IGER0_EEP7_FIFO_INT    (1 << 7)
+#define FUSB300_IGER0_EEP6_FIFO_INT    (1 << 6)
+#define FUSB300_IGER0_EEP5_FIFO_INT    (1 << 5)
+#define FUSB300_IGER0_EEP4_FIFO_INT    (1 << 4)
+#define FUSB300_IGER0_EEP3_FIFO_INT    (1 << 3)
+#define FUSB300_IGER0_EEP2_FIFO_INT    (1 << 2)
+#define FUSB300_IGER0_EEP1_FIFO_INT    (1 << 1)
+#define FUSB300_IGER0_EEPn_FIFO_INT(n) (1 << n)
+
+/*
+ * *Interrupt Enable Group 1 Register (offset = 424H)
+ * */
+#define FUSB300_IGER1_EINT_GRP5                (1 << 31)
+#define FUSB300_IGER1_VBUS_CHG_INT     (1 << 30)
+#define FUSB300_IGER1_SYNF1_EMPTY_INT  (1 << 29)
+#define FUSB300_IGER1_SYNF0_EMPTY_INT  (1 << 28)
+#define FUSB300_IGER1_U3_EXIT_FAIL_INT (1 << 27)
+#define FUSB300_IGER1_U2_EXIT_FAIL_INT (1 << 26)
+#define FUSB300_IGER1_U1_EXIT_FAIL_INT (1 << 25)
+#define FUSB300_IGER1_U2_ENTRY_FAIL_INT        (1 << 24)
+#define FUSB300_IGER1_U1_ENTRY_FAIL_INT        (1 << 23)
+#define FUSB300_IGER1_U3_EXIT_INT      (1 << 22)
+#define FUSB300_IGER1_U2_EXIT_INT      (1 << 21)
+#define FUSB300_IGER1_U1_EXIT_INT      (1 << 20)
+#define FUSB300_IGER1_U3_ENTRY_INT     (1 << 19)
+#define FUSB300_IGER1_U2_ENTRY_INT     (1 << 18)
+#define FUSB300_IGER1_U1_ENTRY_INT     (1 << 17)
+#define FUSB300_IGER1_HOT_RST_INT      (1 << 16)
+#define FUSB300_IGER1_WARM_RST_INT     (1 << 15)
+#define FUSB300_IGER1_RESM_INT         (1 << 14)
+#define FUSB300_IGER1_SUSP_INT         (1 << 13)
+#define FUSB300_IGER1_LPM_INT          (1 << 12)
+#define FUSB300_IGER1_HS_RST_INT       (1 << 11)
+#define FUSB300_IGER1_EDEV_MODE_CHG_INT        (1 << 9)
+#define FUSB300_IGER1_CX_COMABT_INT    (1 << 8)
+#define FUSB300_IGER1_CX_COMFAIL_INT   (1 << 7)
+#define FUSB300_IGER1_CX_CMDEND_INT    (1 << 6)
+#define FUSB300_IGER1_CX_OUT_INT       (1 << 5)
+#define FUSB300_IGER1_CX_IN_INT                (1 << 4)
+#define FUSB300_IGER1_CX_SETUP_INT     (1 << 3)
+#define FUSB300_IGER1_INTGRP4          (1 << 2)
+#define FUSB300_IGER1_INTGRP3          (1 << 1)
+#define FUSB300_IGER1_INTGRP2          (1 << 0)
+
+/*
+ * *Interrupt Enable Group 2 Register (offset = 428H)
+ * */
+#define FUSB300_IGER2_EEP_STR_ACCEPT_INT(n)    (1 << (5 * n - 1))
+#define FUSB300_IGER2_EEP_STR_RESUME_INT(n)    (1 << (5 * n - 2))
+#define FUSB300_IGER2_EEP_STR_REQ_INT(n)       (1 << (5 * n - 3))
+#define FUSB300_IGER2_EEP_STR_NOTRDY_INT(n)    (1 << (5 * n - 4))
+#define FUSB300_IGER2_EEP_STR_PRIME_INT(n)     (1 << (5 * n - 5))
+
+/*
+ * *Interrupt Enable Group 3 Register (offset = 42CH)
+ * */
+
+#define FUSB300_IGER3_EEP_STR_ACCEPT_INT(n)    (1 << (5 * (n - 6) - 1))
+#define FUSB300_IGER3_EEP_STR_RESUME_INT(n)    (1 << (5 * (n - 6) - 2))
+#define FUSB300_IGER3_EEP_STR_REQ_INT(n)       (1 << (5 * (n - 6) - 3))
+#define FUSB300_IGER3_EEP_STR_NOTRDY_INT(n)    (1 << (5 * (n - 6) - 4))
+#define FUSB300_IGER3_EEP_STR_PRIME_INT(n)     (1 << (5 * (n - 6) - 5))
+
+/*
+ * *Interrupt Enable Group 4 Register (offset = 430H)
+ * */
+
+#define FUSB300_IGER4_EEP_RX0_INT(n)           (1 << (n + 16))
+#define FUSB300_IGER4_EEP_STR_ACCEPT_INT(n)    (1 << (5 * (n - 6) - 1))
+#define FUSB300_IGER4_EEP_STR_RESUME_INT(n)    (1 << (5 * (n - 6) - 2))
+#define FUSB300_IGER4_EEP_STR_REQ_INT(n)       (1 << (5 * (n - 6) - 3))
+#define FUSB300_IGER4_EEP_STR_NOTRDY_INT(n)    (1 << (5 * (n - 6) - 4))
+#define FUSB300_IGER4_EEP_STR_PRIME_INT(n)     (1 << (5 * (n - 6) - 5))
+
+/* EP PRD Ready (EP_PRD_RDY, offset = 504H) */
+
+#define FUSB300_EPPRDR_EP15_PRD_RDY            (1 << 15)
+#define FUSB300_EPPRDR_EP14_PRD_RDY            (1 << 14)
+#define FUSB300_EPPRDR_EP13_PRD_RDY            (1 << 13)
+#define FUSB300_EPPRDR_EP12_PRD_RDY            (1 << 12)
+#define FUSB300_EPPRDR_EP11_PRD_RDY            (1 << 11)
+#define FUSB300_EPPRDR_EP10_PRD_RDY            (1 << 10)
+#define FUSB300_EPPRDR_EP9_PRD_RDY             (1 << 9)
+#define FUSB300_EPPRDR_EP8_PRD_RDY             (1 << 8)
+#define FUSB300_EPPRDR_EP7_PRD_RDY             (1 << 7)
+#define FUSB300_EPPRDR_EP6_PRD_RDY             (1 << 6)
+#define FUSB300_EPPRDR_EP5_PRD_RDY             (1 << 5)
+#define FUSB300_EPPRDR_EP4_PRD_RDY             (1 << 4)
+#define FUSB300_EPPRDR_EP3_PRD_RDY             (1 << 3)
+#define FUSB300_EPPRDR_EP2_PRD_RDY             (1 << 2)
+#define FUSB300_EPPRDR_EP1_PRD_RDY             (1 << 1)
+#define FUSB300_EPPRDR_EP_PRD_RDY(n)           (1 << n)
+
+/* AHB Bus Control Register (offset = 514H) */
+#define FUSB300_AHBBCR_S1_SPLIT_ON             (1 << 17)
+#define FUSB300_AHBBCR_S0_SPLIT_ON             (1 << 16)
+#define FUSB300_AHBBCR_S1_1entry               (0 << 12)
+#define FUSB300_AHBBCR_S1_4entry               (3 << 12)
+#define FUSB300_AHBBCR_S1_8entry               (5 << 12)
+#define FUSB300_AHBBCR_S1_16entry              (7 << 12)
+#define FUSB300_AHBBCR_S0_1entry               (0 << 8)
+#define FUSB300_AHBBCR_S0_4entry               (3 << 8)
+#define FUSB300_AHBBCR_S0_8entry               (5 << 8)
+#define FUSB300_AHBBCR_S0_16entry              (7 << 8)
+#define FUSB300_AHBBCR_M1_BURST_SINGLE         (0 << 4)
+#define FUSB300_AHBBCR_M1_BURST_INCR           (1 << 4)
+#define FUSB300_AHBBCR_M1_BURST_INCR4          (3 << 4)
+#define FUSB300_AHBBCR_M1_BURST_INCR8          (5 << 4)
+#define FUSB300_AHBBCR_M1_BURST_INCR16         (7 << 4)
+#define FUSB300_AHBBCR_M0_BURST_SINGLE         0
+#define FUSB300_AHBBCR_M0_BURST_INCR           1
+#define FUSB300_AHBBCR_M0_BURST_INCR4          3
+#define FUSB300_AHBBCR_M0_BURST_INCR8          5
+#define FUSB300_AHBBCR_M0_BURST_INCR16         7
+#define FUSB300_IGER5_EEP_STL_INT(n)           (1 << n)
+
+/* WORD 0 Data Structure of PRD Table */
+#define FUSB300_EPPRD0_M                       (1 << 30)
+#define FUSB300_EPPRD0_O                       (1 << 29)
+/* The finished prd */
+#define FUSB300_EPPRD0_F                       (1 << 28)
+#define FUSB300_EPPRD0_I                       (1 << 27)
+#define FUSB300_EPPRD0_A                       (1 << 26)
+/* To decide HW point to first prd at next time */
+#define FUSB300_EPPRD0_L                       (1 << 25)
+#define FUSB300_EPPRD0_H                       (1 << 24)
+#define FUSB300_EPPRD0_BTC(n)                  (n & 0xFFFFFF)
+
+/*----------------------------------------------------------------------*/
+#define FUSB300_MAX_NUM_EP             16
+
+#define FUSB300_FIFO_ENTRY_NUM         8
+#define FUSB300_MAX_FIFO_ENTRY         8
+
+#define SS_CTL_MAX_PACKET_SIZE         0x200
+#define SS_BULK_MAX_PACKET_SIZE                0x400
+#define SS_INT_MAX_PACKET_SIZE         0x400
+#define SS_ISO_MAX_PACKET_SIZE         0x400
+
+#define HS_BULK_MAX_PACKET_SIZE                0x200
+#define HS_CTL_MAX_PACKET_SIZE         0x40
+#define HS_INT_MAX_PACKET_SIZE         0x400
+#define HS_ISO_MAX_PACKET_SIZE         0x400
+
+struct fusb300_ep_info {
+       u8      epnum;
+       u8      type;
+       u8      interval;
+       u8      dir_in;
+       u16     maxpacket;
+       u16     addrofs;
+       u16     bw_num;
+};
+
+struct fusb300_request {
+
+       struct usb_request      req;
+       struct list_head        queue;
+};
+
+
+struct fusb300_ep {
+       struct usb_ep           ep;
+       struct fusb300          *fusb300;
+
+       struct list_head        queue;
+       unsigned                stall:1;
+       unsigned                wedged:1;
+       unsigned                use_dma:1;
+
+       unsigned char           epnum;
+       unsigned char           type;
+};
+
+struct fusb300 {
+       spinlock_t              lock;
+       void __iomem            *reg;
+
+       unsigned long           irq_trigger;
+
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+
+       struct fusb300_ep       *ep[FUSB300_MAX_NUM_EP];
+
+       struct usb_request      *ep0_req;       /* for internal request */
+       __le16                  ep0_data;
+       u32                     ep0_length;     /* for internal request */
+       u8                      ep0_dir;        /* 0/0x80  out/in */
+
+       u8                      fifo_entry_num; /* next start fifo entry */
+       u32                     addrofs;        /* next fifo address offset */
+       u8                      reenum;         /* if re-enumeration */
+};
+
+#define to_fusb300(g)          (container_of((g), struct fusb300, gadget))
+
+#endif
diff --git a/drivers/usb/gadget/udc/gadget_chips.h b/drivers/usb/gadget/udc/gadget_chips.h
new file mode 100644 (file)
index 0000000..bcd04bc
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * USB device controllers have lots of quirks.  Use these macros in
+ * gadget drivers or other code that needs to deal with them, and which
+ * autoconfigures instead of using early binding to the hardware.
+ *
+ * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by
+ * some config file that gets updated as new hardware is supported.
+ * (And avoiding all runtime comparisons in typical one-choice configs!)
+ *
+ * NOTE:  some of these controller drivers may not be available yet.
+ * Some are available on 2.4 kernels; several are available, but not
+ * yet pushed in the 2.6 mainline tree.
+ */
+
+#ifndef __GADGET_CHIPS_H
+#define __GADGET_CHIPS_H
+
+#include <linux/usb/gadget.h>
+
+/*
+ * NOTICE: the entries below are alphabetical and should be kept
+ * that way.
+ *
+ * Always be sure to add new entries to the correct position or
+ * accept the bashing later.
+ *
+ * If you have forgotten the alphabetical order let VIM/EMACS
+ * do that for you.
+ */
+#define gadget_is_at91(g)              (!strcmp("at91_udc", (g)->name))
+#define gadget_is_goku(g)              (!strcmp("goku_udc", (g)->name))
+#define gadget_is_musbhdrc(g)          (!strcmp("musb-hdrc", (g)->name))
+#define gadget_is_net2280(g)           (!strcmp("net2280", (g)->name))
+#define gadget_is_pxa(g)               (!strcmp("pxa25x_udc", (g)->name))
+#define gadget_is_pxa27x(g)            (!strcmp("pxa27x_udc", (g)->name))
+
+/**
+ * gadget_supports_altsettings - return true if altsettings work
+ * @gadget: the gadget in question
+ */
+static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
+{
+       /* PXA 21x/25x/26x has no altsettings at all */
+       if (gadget_is_pxa(gadget))
+               return false;
+
+       /* PXA 27x and 3xx have *broken* altsetting support */
+       if (gadget_is_pxa27x(gadget))
+               return false;
+
+       /* Everything else is *presumably* fine ... */
+       return true;
+}
+
+#endif /* __GADGET_CHIPS_H */
diff --git a/drivers/usb/gadget/udc/goku_udc.c b/drivers/usb/gadget/udc/goku_udc.c
new file mode 100644 (file)
index 0000000..6c85839
--- /dev/null
@@ -0,0 +1,1823 @@
+/*
+ * Toshiba TC86C001 ("Goku-S") USB Device Controller driver
+ *
+ * Copyright (C) 2000-2002 Lineo
+ *      by Stuart Lynne, Tom Rushworth, and Bruce Balden
+ * Copyright (C) 2002 Toshiba Corporation
+ * Copyright (C) 2003 MontaVista Software (source@mvista.com)
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/*
+ * This device has ep0 and three semi-configurable bulk/interrupt endpoints.
+ *
+ *  - Endpoint numbering is fixed: ep{1,2,3}-bulk
+ *  - Gadget drivers can choose ep maxpacket (8/16/32/64)
+ *  - Gadget drivers can choose direction (IN, OUT)
+ *  - DMA works with ep1 (OUT transfers) and ep2 (IN transfers).
+ */
+
+// #define     VERBOSE         /* extra debug messages (success too) */
+// #define     USB_TRACE       /* packet-level success messages */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/prefetch.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/unaligned.h>
+
+
+#include "goku_udc.h"
+
+#define        DRIVER_DESC             "TC86C001 USB Device Controller"
+#define        DRIVER_VERSION          "30-Oct 2003"
+
+static const char driver_name [] = "goku_udc";
+static const char driver_desc [] = DRIVER_DESC;
+
+MODULE_AUTHOR("source@mvista.com");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+
+/*
+ * IN dma behaves ok under testing, though the IN-dma abort paths don't
+ * seem to behave quite as expected.  Used by default.
+ *
+ * OUT dma documents design problems handling the common "short packet"
+ * transfer termination policy; it couldn't be enabled by default, even
+ * if the OUT-dma abort problems had a resolution.
+ */
+static unsigned use_dma = 1;
+
+#if 0
+//#include <linux/moduleparam.h>
+/* "modprobe goku_udc use_dma=1" etc
+ *     0 to disable dma
+ *     1 to use IN dma only (normal operation)
+ *     2 to use IN and OUT dma
+ */
+module_param(use_dma, uint, S_IRUGO);
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static void nuke(struct goku_ep *, int status);
+
+static inline void
+command(struct goku_udc_regs __iomem *regs, int command, unsigned epnum)
+{
+       writel(COMMAND_EP(epnum) | command, &regs->Command);
+       udelay(300);
+}
+
+static int
+goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+{
+       struct goku_udc *dev;
+       struct goku_ep  *ep;
+       u32             mode;
+       u16             max;
+       unsigned long   flags;
+
+       ep = container_of(_ep, struct goku_ep, ep);
+       if (!_ep || !desc
+                       || desc->bDescriptorType != USB_DT_ENDPOINT)
+               return -EINVAL;
+       dev = ep->dev;
+       if (ep == &dev->ep[0])
+               return -EINVAL;
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+       if (ep->num != usb_endpoint_num(desc))
+               return -EINVAL;
+
+       switch (usb_endpoint_type(desc)) {
+       case USB_ENDPOINT_XFER_BULK:
+       case USB_ENDPOINT_XFER_INT:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if ((readl(ep->reg_status) & EPxSTATUS_EP_MASK)
+                       != EPxSTATUS_EP_INVALID)
+               return -EBUSY;
+
+       /* enabling the no-toggle interrupt mode would need an api hook */
+       mode = 0;
+       max = get_unaligned_le16(&desc->wMaxPacketSize);
+       switch (max) {
+       case 64:        mode++;
+       case 32:        mode++;
+       case 16:        mode++;
+       case 8:         mode <<= 3;
+                       break;
+       default:
+               return -EINVAL;
+       }
+       mode |= 2 << 1;         /* bulk, or intr-with-toggle */
+
+       /* ep1/ep2 dma direction is chosen early; it works in the other
+        * direction, with pio.  be cautious with out-dma.
+        */
+       ep->is_in = usb_endpoint_dir_in(desc);
+       if (ep->is_in) {
+               mode |= 1;
+               ep->dma = (use_dma != 0) && (ep->num == UDC_MSTRD_ENDPOINT);
+       } else {
+               ep->dma = (use_dma == 2) && (ep->num == UDC_MSTWR_ENDPOINT);
+               if (ep->dma)
+                       DBG(dev, "%s out-dma hides short packets\n",
+                               ep->ep.name);
+       }
+
+       spin_lock_irqsave(&ep->dev->lock, flags);
+
+       /* ep1 and ep2 can do double buffering and/or dma */
+       if (ep->num < 3) {
+               struct goku_udc_regs __iomem    *regs = ep->dev->regs;
+               u32                             tmp;
+
+               /* double buffer except (for now) with pio in */
+               tmp = ((ep->dma || !ep->is_in)
+                               ? 0x10  /* double buffered */
+                               : 0x11  /* single buffer */
+                       ) << ep->num;
+               tmp |= readl(&regs->EPxSingle);
+               writel(tmp, &regs->EPxSingle);
+
+               tmp = (ep->dma ? 0x10/*dma*/ : 0x11/*pio*/) << ep->num;
+               tmp |= readl(&regs->EPxBCS);
+               writel(tmp, &regs->EPxBCS);
+       }
+       writel(mode, ep->reg_mode);
+       command(ep->dev->regs, COMMAND_RESET, ep->num);
+       ep->ep.maxpacket = max;
+       ep->stopped = 0;
+       ep->ep.desc = desc;
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+
+       DBG(dev, "enable %s %s %s maxpacket %u\n", ep->ep.name,
+               ep->is_in ? "IN" : "OUT",
+               ep->dma ? "dma" : "pio",
+               max);
+
+       return 0;
+}
+
+static void ep_reset(struct goku_udc_regs __iomem *regs, struct goku_ep *ep)
+{
+       struct goku_udc         *dev = ep->dev;
+
+       if (regs) {
+               command(regs, COMMAND_INVALID, ep->num);
+               if (ep->num) {
+                       if (ep->num == UDC_MSTWR_ENDPOINT)
+                               dev->int_enable &= ~(INT_MSTWREND
+                                                       |INT_MSTWRTMOUT);
+                       else if (ep->num == UDC_MSTRD_ENDPOINT)
+                               dev->int_enable &= ~INT_MSTRDEND;
+                       dev->int_enable &= ~INT_EPxDATASET (ep->num);
+               } else
+                       dev->int_enable &= ~INT_EP0;
+               writel(dev->int_enable, &regs->int_enable);
+               readl(&regs->int_enable);
+               if (ep->num < 3) {
+                       struct goku_udc_regs __iomem    *r = ep->dev->regs;
+                       u32                             tmp;
+
+                       tmp = readl(&r->EPxSingle);
+                       tmp &= ~(0x11 << ep->num);
+                       writel(tmp, &r->EPxSingle);
+
+                       tmp = readl(&r->EPxBCS);
+                       tmp &= ~(0x11 << ep->num);
+                       writel(tmp, &r->EPxBCS);
+               }
+               /* reset dma in case we're still using it */
+               if (ep->dma) {
+                       u32     master;
+
+                       master = readl(&regs->dma_master) & MST_RW_BITS;
+                       if (ep->num == UDC_MSTWR_ENDPOINT) {
+                               master &= ~MST_W_BITS;
+                               master |= MST_WR_RESET;
+                       } else {
+                               master &= ~MST_R_BITS;
+                               master |= MST_RD_RESET;
+                       }
+                       writel(master, &regs->dma_master);
+               }
+       }
+
+       usb_ep_set_maxpacket_limit(&ep->ep, MAX_FIFO_SIZE);
+       ep->ep.desc = NULL;
+       ep->stopped = 1;
+       ep->irqs = 0;
+       ep->dma = 0;
+}
+
+static int goku_ep_disable(struct usb_ep *_ep)
+{
+       struct goku_ep  *ep;
+       struct goku_udc *dev;
+       unsigned long   flags;
+
+       ep = container_of(_ep, struct goku_ep, ep);
+       if (!_ep || !ep->ep.desc)
+               return -ENODEV;
+       dev = ep->dev;
+       if (dev->ep0state == EP0_SUSPEND)
+               return -EBUSY;
+
+       VDBG(dev, "disable %s\n", _ep->name);
+
+       spin_lock_irqsave(&dev->lock, flags);
+       nuke(ep, -ESHUTDOWN);
+       ep_reset(dev->regs, ep);
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_request *
+goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct goku_request     *req;
+
+       if (!_ep)
+               return NULL;
+       req = kzalloc(sizeof *req, gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+       return &req->req;
+}
+
+static void
+goku_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct goku_request     *req;
+
+       if (!_ep || !_req)
+               return;
+
+       req = container_of(_req, struct goku_request, req);
+       WARN_ON(!list_empty(&req->queue));
+       kfree(req);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+done(struct goku_ep *ep, struct goku_request *req, int status)
+{
+       struct goku_udc         *dev;
+       unsigned                stopped = ep->stopped;
+
+       list_del_init(&req->queue);
+
+       if (likely(req->req.status == -EINPROGRESS))
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       dev = ep->dev;
+
+       if (ep->dma)
+               usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
+
+#ifndef USB_TRACE
+       if (status && status != -ESHUTDOWN)
+#endif
+               VDBG(dev, "complete %s req %p stat %d len %u/%u\n",
+                       ep->ep.name, &req->req, status,
+                       req->req.actual, req->req.length);
+
+       /* don't modify queue heads during completion callback */
+       ep->stopped = 1;
+       spin_unlock(&dev->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&dev->lock);
+       ep->stopped = stopped;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static inline int
+write_packet(u32 __iomem *fifo, u8 *buf, struct goku_request *req, unsigned max)
+{
+       unsigned        length, count;
+
+       length = min(req->req.length - req->req.actual, max);
+       req->req.actual += length;
+
+       count = length;
+       while (likely(count--))
+               writel(*buf++, fifo);
+       return length;
+}
+
+// return:  0 = still running, 1 = completed, negative = errno
+static int write_fifo(struct goku_ep *ep, struct goku_request *req)
+{
+       struct goku_udc *dev = ep->dev;
+       u32             tmp;
+       u8              *buf;
+       unsigned        count;
+       int             is_last;
+
+       tmp = readl(&dev->regs->DataSet);
+       buf = req->req.buf + req->req.actual;
+       prefetch(buf);
+
+       dev = ep->dev;
+       if (unlikely(ep->num == 0 && dev->ep0state != EP0_IN))
+               return -EL2HLT;
+
+       /* NOTE:  just single-buffered PIO-IN for now.  */
+       if (unlikely((tmp & DATASET_A(ep->num)) != 0))
+               return 0;
+
+       /* clear our "packet available" irq */
+       if (ep->num != 0)
+               writel(~INT_EPxDATASET(ep->num), &dev->regs->int_status);
+
+       count = write_packet(ep->reg_fifo, buf, req, ep->ep.maxpacket);
+
+       /* last packet often short (sometimes a zlp, especially on ep0) */
+       if (unlikely(count != ep->ep.maxpacket)) {
+               writel(~(1<<ep->num), &dev->regs->EOP);
+               if (ep->num == 0) {
+                       dev->ep[0].stopped = 1;
+                       dev->ep0state = EP0_STATUS;
+               }
+               is_last = 1;
+       } else {
+               if (likely(req->req.length != req->req.actual)
+                               || req->req.zero)
+                       is_last = 0;
+               else
+                       is_last = 1;
+       }
+#if 0          /* printk seemed to trash is_last...*/
+//#ifdef USB_TRACE
+       VDBG(dev, "wrote %s %u bytes%s IN %u left %p\n",
+               ep->ep.name, count, is_last ? "/last" : "",
+               req->req.length - req->req.actual, req);
+#endif
+
+       /* requests complete when all IN data is in the FIFO,
+        * or sometimes later, if a zlp was needed.
+        */
+       if (is_last) {
+               done(ep, req, 0);
+               return 1;
+       }
+
+       return 0;
+}
+
+static int read_fifo(struct goku_ep *ep, struct goku_request *req)
+{
+       struct goku_udc_regs __iomem    *regs;
+       u32                             size, set;
+       u8                              *buf;
+       unsigned                        bufferspace, is_short, dbuff;
+
+       regs = ep->dev->regs;
+top:
+       buf = req->req.buf + req->req.actual;
+       prefetchw(buf);
+
+       if (unlikely(ep->num == 0 && ep->dev->ep0state != EP0_OUT))
+               return -EL2HLT;
+
+       dbuff = (ep->num == 1 || ep->num == 2);
+       do {
+               /* ack dataset irq matching the status we'll handle */
+               if (ep->num != 0)
+                       writel(~INT_EPxDATASET(ep->num), &regs->int_status);
+
+               set = readl(&regs->DataSet) & DATASET_AB(ep->num);
+               size = readl(&regs->EPxSizeLA[ep->num]);
+               bufferspace = req->req.length - req->req.actual;
+
+               /* usually do nothing without an OUT packet */
+               if (likely(ep->num != 0 || bufferspace != 0)) {
+                       if (unlikely(set == 0))
+                               break;
+                       /* use ep1/ep2 double-buffering for OUT */
+                       if (!(size & PACKET_ACTIVE))
+                               size = readl(&regs->EPxSizeLB[ep->num]);
+                       if (!(size & PACKET_ACTIVE))    /* "can't happen" */
+                               break;
+                       size &= DATASIZE;       /* EPxSizeH == 0 */
+
+               /* ep0out no-out-data case for set_config, etc */
+               } else
+                       size = 0;
+
+               /* read all bytes from this packet */
+               req->req.actual += size;
+               is_short = (size < ep->ep.maxpacket);
+#ifdef USB_TRACE
+               VDBG(ep->dev, "read %s %u bytes%s OUT req %p %u/%u\n",
+                       ep->ep.name, size, is_short ? "/S" : "",
+                       req, req->req.actual, req->req.length);
+#endif
+               while (likely(size-- != 0)) {
+                       u8      byte = (u8) readl(ep->reg_fifo);
+
+                       if (unlikely(bufferspace == 0)) {
+                               /* this happens when the driver's buffer
+                                * is smaller than what the host sent.
+                                * discard the extra data in this packet.
+                                */
+                               if (req->req.status != -EOVERFLOW)
+                                       DBG(ep->dev, "%s overflow %u\n",
+                                               ep->ep.name, size);
+                               req->req.status = -EOVERFLOW;
+                       } else {
+                               *buf++ = byte;
+                               bufferspace--;
+                       }
+               }
+
+               /* completion */
+               if (unlikely(is_short || req->req.actual == req->req.length)) {
+                       if (unlikely(ep->num == 0)) {
+                               /* non-control endpoints now usable? */
+                               if (ep->dev->req_config)
+                                       writel(ep->dev->configured
+                                                       ? USBSTATE_CONFIGURED
+                                                       : 0,
+                                               &regs->UsbState);
+                               /* ep0out status stage */
+                               writel(~(1<<0), &regs->EOP);
+                               ep->stopped = 1;
+                               ep->dev->ep0state = EP0_STATUS;
+                       }
+                       done(ep, req, 0);
+
+                       /* empty the second buffer asap */
+                       if (dbuff && !list_empty(&ep->queue)) {
+                               req = list_entry(ep->queue.next,
+                                               struct goku_request, queue);
+                               goto top;
+                       }
+                       return 1;
+               }
+       } while (dbuff);
+       return 0;
+}
+
+static inline void
+pio_irq_enable(struct goku_udc *dev,
+               struct goku_udc_regs __iomem *regs, int epnum)
+{
+       dev->int_enable |= INT_EPxDATASET (epnum);
+       writel(dev->int_enable, &regs->int_enable);
+       /* write may still be posted */
+}
+
+static inline void
+pio_irq_disable(struct goku_udc *dev,
+               struct goku_udc_regs __iomem *regs, int epnum)
+{
+       dev->int_enable &= ~INT_EPxDATASET (epnum);
+       writel(dev->int_enable, &regs->int_enable);
+       /* write may still be posted */
+}
+
+static inline void
+pio_advance(struct goku_ep *ep)
+{
+       struct goku_request     *req;
+
+       if (unlikely(list_empty (&ep->queue)))
+               return;
+       req = list_entry(ep->queue.next, struct goku_request, queue);
+       (ep->is_in ? write_fifo : read_fifo)(ep, req);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+// return:  0 = q running, 1 = q stopped, negative = errno
+static int start_dma(struct goku_ep *ep, struct goku_request *req)
+{
+       struct goku_udc_regs __iomem    *regs = ep->dev->regs;
+       u32                             master;
+       u32                             start = req->req.dma;
+       u32                             end = start + req->req.length - 1;
+
+       master = readl(&regs->dma_master) & MST_RW_BITS;
+
+       /* re-init the bits affecting IN dma; careful with zlps */
+       if (likely(ep->is_in)) {
+               if (unlikely(master & MST_RD_ENA)) {
+                       DBG (ep->dev, "start, IN active dma %03x!!\n",
+                               master);
+//                     return -EL2HLT;
+               }
+               writel(end, &regs->in_dma_end);
+               writel(start, &regs->in_dma_start);
+
+               master &= ~MST_R_BITS;
+               if (unlikely(req->req.length == 0))
+                       master = MST_RD_ENA | MST_RD_EOPB;
+               else if ((req->req.length % ep->ep.maxpacket) != 0
+                                       || req->req.zero)
+                       master = MST_RD_ENA | MST_EOPB_ENA;
+               else
+                       master = MST_RD_ENA | MST_EOPB_DIS;
+
+               ep->dev->int_enable |= INT_MSTRDEND;
+
+       /* Goku DMA-OUT merges short packets, which plays poorly with
+        * protocols where short packets mark the transfer boundaries.
+        * The chip supports a nonstandard policy with INT_MSTWRTMOUT,
+        * ending transfers after 3 SOFs; we don't turn it on.
+        */
+       } else {
+               if (unlikely(master & MST_WR_ENA)) {
+                       DBG (ep->dev, "start, OUT active dma %03x!!\n",
+                               master);
+//                     return -EL2HLT;
+               }
+               writel(end, &regs->out_dma_end);
+               writel(start, &regs->out_dma_start);
+
+               master &= ~MST_W_BITS;
+               master |= MST_WR_ENA | MST_TIMEOUT_DIS;
+
+               ep->dev->int_enable |= INT_MSTWREND|INT_MSTWRTMOUT;
+       }
+
+       writel(master, &regs->dma_master);
+       writel(ep->dev->int_enable, &regs->int_enable);
+       return 0;
+}
+
+static void dma_advance(struct goku_udc *dev, struct goku_ep *ep)
+{
+       struct goku_request             *req;
+       struct goku_udc_regs __iomem    *regs = ep->dev->regs;
+       u32                             master;
+
+       master = readl(&regs->dma_master);
+
+       if (unlikely(list_empty(&ep->queue))) {
+stop:
+               if (ep->is_in)
+                       dev->int_enable &= ~INT_MSTRDEND;
+               else
+                       dev->int_enable &= ~(INT_MSTWREND|INT_MSTWRTMOUT);
+               writel(dev->int_enable, &regs->int_enable);
+               return;
+       }
+       req = list_entry(ep->queue.next, struct goku_request, queue);
+
+       /* normal hw dma completion (not abort) */
+       if (likely(ep->is_in)) {
+               if (unlikely(master & MST_RD_ENA))
+                       return;
+               req->req.actual = readl(&regs->in_dma_current);
+       } else {
+               if (unlikely(master & MST_WR_ENA))
+                       return;
+
+               /* hardware merges short packets, and also hides packet
+                * overruns.  a partial packet MAY be in the fifo here.
+                */
+               req->req.actual = readl(&regs->out_dma_current);
+       }
+       req->req.actual -= req->req.dma;
+       req->req.actual++;
+
+#ifdef USB_TRACE
+       VDBG(dev, "done %s %s dma, %u/%u bytes, req %p\n",
+               ep->ep.name, ep->is_in ? "IN" : "OUT",
+               req->req.actual, req->req.length, req);
+#endif
+       done(ep, req, 0);
+       if (list_empty(&ep->queue))
+               goto stop;
+       req = list_entry(ep->queue.next, struct goku_request, queue);
+       (void) start_dma(ep, req);
+}
+
+static void abort_dma(struct goku_ep *ep, int status)
+{
+       struct goku_udc_regs __iomem    *regs = ep->dev->regs;
+       struct goku_request             *req;
+       u32                             curr, master;
+
+       /* NAK future host requests, hoping the implicit delay lets the
+        * dma engine finish reading (or writing) its latest packet and
+        * empty the dma buffer (up to 16 bytes).
+        *
+        * This avoids needing to clean up a partial packet in the fifo;
+        * we can't do that for IN without side effects to HALT and TOGGLE.
+        */
+       command(regs, COMMAND_FIFO_DISABLE, ep->num);
+       req = list_entry(ep->queue.next, struct goku_request, queue);
+       master = readl(&regs->dma_master) & MST_RW_BITS;
+
+       /* FIXME using these resets isn't usably documented. this may
+        * not work unless it's followed by disabling the endpoint.
+        *
+        * FIXME the OUT reset path doesn't even behave consistently.
+        */
+       if (ep->is_in) {
+               if (unlikely((readl(&regs->dma_master) & MST_RD_ENA) == 0))
+                       goto finished;
+               curr = readl(&regs->in_dma_current);
+
+               writel(curr, &regs->in_dma_end);
+               writel(curr, &regs->in_dma_start);
+
+               master &= ~MST_R_BITS;
+               master |= MST_RD_RESET;
+               writel(master, &regs->dma_master);
+
+               if (readl(&regs->dma_master) & MST_RD_ENA)
+                       DBG(ep->dev, "IN dma active after reset!\n");
+
+       } else {
+               if (unlikely((readl(&regs->dma_master) & MST_WR_ENA) == 0))
+                       goto finished;
+               curr = readl(&regs->out_dma_current);
+
+               writel(curr, &regs->out_dma_end);
+               writel(curr, &regs->out_dma_start);
+
+               master &= ~MST_W_BITS;
+               master |= MST_WR_RESET;
+               writel(master, &regs->dma_master);
+
+               if (readl(&regs->dma_master) & MST_WR_ENA)
+                       DBG(ep->dev, "OUT dma active after reset!\n");
+       }
+       req->req.actual = (curr - req->req.dma) + 1;
+       req->req.status = status;
+
+       VDBG(ep->dev, "%s %s %s %d/%d\n", __func__, ep->ep.name,
+               ep->is_in ? "IN" : "OUT",
+               req->req.actual, req->req.length);
+
+       command(regs, COMMAND_FIFO_ENABLE, ep->num);
+
+       return;
+
+finished:
+       /* dma already completed; no abort needed */
+       command(regs, COMMAND_FIFO_ENABLE, ep->num);
+       req->req.actual = req->req.length;
+       req->req.status = 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+       struct goku_request     *req;
+       struct goku_ep          *ep;
+       struct goku_udc         *dev;
+       unsigned long           flags;
+       int                     status;
+
+       /* always require a cpu-view buffer so pio works */
+       req = container_of(_req, struct goku_request, req);
+       if (unlikely(!_req || !_req->complete
+                       || !_req->buf || !list_empty(&req->queue)))
+               return -EINVAL;
+       ep = container_of(_ep, struct goku_ep, ep);
+       if (unlikely(!_ep || (!ep->ep.desc && ep->num != 0)))
+               return -EINVAL;
+       dev = ep->dev;
+       if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN))
+               return -ESHUTDOWN;
+
+       /* can't touch registers when suspended */
+       if (dev->ep0state == EP0_SUSPEND)
+               return -EBUSY;
+
+       /* set up dma mapping in case the caller didn't */
+       if (ep->dma) {
+               status = usb_gadget_map_request(&dev->gadget, &req->req,
+                               ep->is_in);
+               if (status)
+                       return status;
+       }
+
+#ifdef USB_TRACE
+       VDBG(dev, "%s queue req %p, len %u buf %p\n",
+                       _ep->name, _req, _req->length, _req->buf);
+#endif
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       /* for ep0 IN without premature status, zlp is required and
+        * writing EOP starts the status stage (OUT).
+        */
+       if (unlikely(ep->num == 0 && ep->is_in))
+               _req->zero = 1;
+
+       /* kickstart this i/o queue? */
+       status = 0;
+       if (list_empty(&ep->queue) && likely(!ep->stopped)) {
+               /* dma:  done after dma completion IRQ (or error)
+                * pio:  done after last fifo operation
+                */
+               if (ep->dma)
+                       status = start_dma(ep, req);
+               else
+                       status = (ep->is_in ? write_fifo : read_fifo)(ep, req);
+
+               if (unlikely(status != 0)) {
+                       if (status > 0)
+                               status = 0;
+                       req = NULL;
+               }
+
+       } /* else pio or dma irq handler advances the queue. */
+
+       if (likely(req != NULL))
+               list_add_tail(&req->queue, &ep->queue);
+
+       if (likely(!list_empty(&ep->queue))
+                       && likely(ep->num != 0)
+                       && !ep->dma
+                       && !(dev->int_enable & INT_EPxDATASET (ep->num)))
+               pio_irq_enable(dev, dev->regs, ep->num);
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       /* pci writes may still be posted */
+       return status;
+}
+
+/* dequeue ALL requests */
+static void nuke(struct goku_ep *ep, int status)
+{
+       struct goku_request     *req;
+
+       ep->stopped = 1;
+       if (list_empty(&ep->queue))
+               return;
+       if (ep->dma)
+               abort_dma(ep, status);
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct goku_request, queue);
+               done(ep, req, status);
+       }
+}
+
+/* dequeue JUST ONE request */
+static int goku_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct goku_request     *req;
+       struct goku_ep          *ep;
+       struct goku_udc         *dev;
+       unsigned long           flags;
+
+       ep = container_of(_ep, struct goku_ep, ep);
+       if (!_ep || !_req || (!ep->ep.desc && ep->num != 0))
+               return -EINVAL;
+       dev = ep->dev;
+       if (!dev->driver)
+               return -ESHUTDOWN;
+
+       /* we can't touch (dma) registers when suspended */
+       if (dev->ep0state == EP0_SUSPEND)
+               return -EBUSY;
+
+       VDBG(dev, "%s %s %s %s %p\n", __func__, _ep->name,
+               ep->is_in ? "IN" : "OUT",
+               ep->dma ? "dma" : "pio",
+               _req);
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry (req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req) {
+               spin_unlock_irqrestore (&dev->lock, flags);
+               return -EINVAL;
+       }
+
+       if (ep->dma && ep->queue.next == &req->queue && !ep->stopped) {
+               abort_dma(ep, -ECONNRESET);
+               done(ep, req, -ECONNRESET);
+               dma_advance(dev, ep);
+       } else if (!list_empty(&req->queue))
+               done(ep, req, -ECONNRESET);
+       else
+               req = NULL;
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return req ? 0 : -EOPNOTSUPP;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void goku_clear_halt(struct goku_ep *ep)
+{
+       // assert (ep->num !=0)
+       VDBG(ep->dev, "%s clear halt\n", ep->ep.name);
+       command(ep->dev->regs, COMMAND_SETDATA0, ep->num);
+       command(ep->dev->regs, COMMAND_STALL_CLEAR, ep->num);
+       if (ep->stopped) {
+               ep->stopped = 0;
+               if (ep->dma) {
+                       struct goku_request     *req;
+
+                       if (list_empty(&ep->queue))
+                               return;
+                       req = list_entry(ep->queue.next, struct goku_request,
+                                               queue);
+                       (void) start_dma(ep, req);
+               } else
+                       pio_advance(ep);
+       }
+}
+
+static int goku_set_halt(struct usb_ep *_ep, int value)
+{
+       struct goku_ep  *ep;
+       unsigned long   flags;
+       int             retval = 0;
+
+       if (!_ep)
+               return -ENODEV;
+       ep = container_of (_ep, struct goku_ep, ep);
+
+       if (ep->num == 0) {
+               if (value) {
+                       ep->dev->ep0state = EP0_STALL;
+                       ep->dev->ep[0].stopped = 1;
+               } else
+                       return -EINVAL;
+
+       /* don't change EPxSTATUS_EP_INVALID to READY */
+       } else if (!ep->ep.desc) {
+               DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name);
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&ep->dev->lock, flags);
+       if (!list_empty(&ep->queue))
+               retval = -EAGAIN;
+       else if (ep->is_in && value
+                       /* data in (either) packet buffer? */
+                       && (readl(&ep->dev->regs->DataSet)
+                                       & DATASET_AB(ep->num)))
+               retval = -EAGAIN;
+       else if (!value)
+               goku_clear_halt(ep);
+       else {
+               ep->stopped = 1;
+               VDBG(ep->dev, "%s set halt\n", ep->ep.name);
+               command(ep->dev->regs, COMMAND_STALL, ep->num);
+               readl(ep->reg_status);
+       }
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+       return retval;
+}
+
+static int goku_fifo_status(struct usb_ep *_ep)
+{
+       struct goku_ep                  *ep;
+       struct goku_udc_regs __iomem    *regs;
+       u32                             size;
+
+       if (!_ep)
+               return -ENODEV;
+       ep = container_of(_ep, struct goku_ep, ep);
+
+       /* size is only reported sanely for OUT */
+       if (ep->is_in)
+               return -EOPNOTSUPP;
+
+       /* ignores 16-byte dma buffer; SizeH == 0 */
+       regs = ep->dev->regs;
+       size = readl(&regs->EPxSizeLA[ep->num]) & DATASIZE;
+       size += readl(&regs->EPxSizeLB[ep->num]) & DATASIZE;
+       VDBG(ep->dev, "%s %s %u\n", __func__, ep->ep.name, size);
+       return size;
+}
+
+static void goku_fifo_flush(struct usb_ep *_ep)
+{
+       struct goku_ep                  *ep;
+       struct goku_udc_regs __iomem    *regs;
+       u32                             size;
+
+       if (!_ep)
+               return;
+       ep = container_of(_ep, struct goku_ep, ep);
+       VDBG(ep->dev, "%s %s\n", __func__, ep->ep.name);
+
+       /* don't change EPxSTATUS_EP_INVALID to READY */
+       if (!ep->ep.desc && ep->num != 0) {
+               DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name);
+               return;
+       }
+
+       regs = ep->dev->regs;
+       size = readl(&regs->EPxSizeLA[ep->num]);
+       size &= DATASIZE;
+
+       /* Non-desirable behavior:  FIFO_CLEAR also clears the
+        * endpoint halt feature.  For OUT, we _could_ just read
+        * the bytes out (PIO, if !ep->dma); for in, no choice.
+        */
+       if (size)
+               command(regs, COMMAND_FIFO_CLEAR, ep->num);
+}
+
+static struct usb_ep_ops goku_ep_ops = {
+       .enable         = goku_ep_enable,
+       .disable        = goku_ep_disable,
+
+       .alloc_request  = goku_alloc_request,
+       .free_request   = goku_free_request,
+
+       .queue          = goku_queue,
+       .dequeue        = goku_dequeue,
+
+       .set_halt       = goku_set_halt,
+       .fifo_status    = goku_fifo_status,
+       .fifo_flush     = goku_fifo_flush,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int goku_get_frame(struct usb_gadget *_gadget)
+{
+       return -EOPNOTSUPP;
+}
+
+static int goku_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+static int goku_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+
+static const struct usb_gadget_ops goku_ops = {
+       .get_frame      = goku_get_frame,
+       .udc_start      = goku_udc_start,
+       .udc_stop       = goku_udc_stop,
+       // no remote wakeup
+       // not selfpowered
+};
+
+/*-------------------------------------------------------------------------*/
+
+static inline const char *dmastr(void)
+{
+       if (use_dma == 0)
+               return "(dma disabled)";
+       else if (use_dma == 2)
+               return "(dma IN and OUT)";
+       else
+               return "(dma IN)";
+}
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+static const char proc_node_name [] = "driver/udc";
+
+#define FOURBITS "%s%s%s%s"
+#define EIGHTBITS FOURBITS FOURBITS
+
+static void dump_intmask(struct seq_file *m, const char *label, u32 mask)
+{
+       /* int_status is the same format ... */
+       seq_printf(m,
+               "%s %05X =" FOURBITS EIGHTBITS EIGHTBITS "\n",
+               label, mask,
+               (mask & INT_PWRDETECT) ? " power" : "",
+               (mask & INT_SYSERROR) ? " sys" : "",
+               (mask & INT_MSTRDEND) ? " in-dma" : "",
+               (mask & INT_MSTWRTMOUT) ? " wrtmo" : "",
+
+               (mask & INT_MSTWREND) ? " out-dma" : "",
+               (mask & INT_MSTWRSET) ? " wrset" : "",
+               (mask & INT_ERR) ? " err" : "",
+               (mask & INT_SOF) ? " sof" : "",
+
+               (mask & INT_EP3NAK) ? " ep3nak" : "",
+               (mask & INT_EP2NAK) ? " ep2nak" : "",
+               (mask & INT_EP1NAK) ? " ep1nak" : "",
+               (mask & INT_EP3DATASET) ? " ep3" : "",
+
+               (mask & INT_EP2DATASET) ? " ep2" : "",
+               (mask & INT_EP1DATASET) ? " ep1" : "",
+               (mask & INT_STATUSNAK) ? " ep0snak" : "",
+               (mask & INT_STATUS) ? " ep0status" : "",
+
+               (mask & INT_SETUP) ? " setup" : "",
+               (mask & INT_ENDPOINT0) ? " ep0" : "",
+               (mask & INT_USBRESET) ? " reset" : "",
+               (mask & INT_SUSPEND) ? " suspend" : "");
+}
+
+
+static int udc_proc_read(struct seq_file *m, void *v)
+{
+       struct goku_udc                 *dev = m->private;
+       struct goku_udc_regs __iomem    *regs = dev->regs;
+       unsigned long                   flags;
+       int                             i, is_usb_connected;
+       u32                             tmp;
+
+       local_irq_save(flags);
+
+       /* basic device status */
+       tmp = readl(&regs->power_detect);
+       is_usb_connected = tmp & PW_DETECT;
+       seq_printf(m,
+               "%s - %s\n"
+               "%s version: %s %s\n"
+               "Gadget driver: %s\n"
+               "Host %s, %s\n"
+               "\n",
+               pci_name(dev->pdev), driver_desc,
+               driver_name, DRIVER_VERSION, dmastr(),
+               dev->driver ? dev->driver->driver.name : "(none)",
+               is_usb_connected
+                       ? ((tmp & PW_PULLUP) ? "full speed" : "powered")
+                       : "disconnected",
+               ({const char *state;
+               switch(dev->ep0state){
+               case EP0_DISCONNECT:    state = "ep0_disconnect"; break;
+               case EP0_IDLE:          state = "ep0_idle"; break;
+               case EP0_IN:            state = "ep0_in"; break;
+               case EP0_OUT:           state = "ep0_out"; break;
+               case EP0_STATUS:        state = "ep0_status"; break;
+               case EP0_STALL:         state = "ep0_stall"; break;
+               case EP0_SUSPEND:       state = "ep0_suspend"; break;
+               default:                state = "ep0_?"; break;
+               } state; })
+               );
+
+       dump_intmask(m, "int_status", readl(&regs->int_status));
+       dump_intmask(m, "int_enable", readl(&regs->int_enable));
+
+       if (!is_usb_connected || !dev->driver || (tmp & PW_PULLUP) == 0)
+               goto done;
+
+       /* registers for (active) device and ep0 */
+       if (seq_printf(m, "\nirqs %lu\ndataset %02x "
+                       "single.bcs %02x.%02x state %x addr %u\n",
+                       dev->irqs, readl(&regs->DataSet),
+                       readl(&regs->EPxSingle), readl(&regs->EPxBCS),
+                       readl(&regs->UsbState),
+                       readl(&regs->address)) < 0)
+               goto done;
+
+       tmp = readl(&regs->dma_master);
+       if (seq_printf(m,
+               "dma %03X =" EIGHTBITS "%s %s\n", tmp,
+               (tmp & MST_EOPB_DIS) ? " eopb-" : "",
+               (tmp & MST_EOPB_ENA) ? " eopb+" : "",
+               (tmp & MST_TIMEOUT_DIS) ? " tmo-" : "",
+               (tmp & MST_TIMEOUT_ENA) ? " tmo+" : "",
+
+               (tmp & MST_RD_EOPB) ? " eopb" : "",
+               (tmp & MST_RD_RESET) ? " in_reset" : "",
+               (tmp & MST_WR_RESET) ? " out_reset" : "",
+               (tmp & MST_RD_ENA) ? " IN" : "",
+
+               (tmp & MST_WR_ENA) ? " OUT" : "",
+               (tmp & MST_CONNECTION)
+                       ? "ep1in/ep2out"
+                       : "ep1out/ep2in") < 0)
+               goto done;
+
+       /* dump endpoint queues */
+       for (i = 0; i < 4; i++) {
+               struct goku_ep          *ep = &dev->ep [i];
+               struct goku_request     *req;
+
+               if (i && !ep->ep.desc)
+                       continue;
+
+               tmp = readl(ep->reg_status);
+               if (seq_printf(m,
+                       "%s %s max %u %s, irqs %lu, "
+                       "status %02x (%s) " FOURBITS "\n",
+                       ep->ep.name,
+                       ep->is_in ? "in" : "out",
+                       ep->ep.maxpacket,
+                       ep->dma ? "dma" : "pio",
+                       ep->irqs,
+                       tmp, ({ char *s;
+                       switch (tmp & EPxSTATUS_EP_MASK) {
+                       case EPxSTATUS_EP_READY:
+                               s = "ready"; break;
+                       case EPxSTATUS_EP_DATAIN:
+                               s = "packet"; break;
+                       case EPxSTATUS_EP_FULL:
+                               s = "full"; break;
+                       case EPxSTATUS_EP_TX_ERR:       // host will retry
+                               s = "tx_err"; break;
+                       case EPxSTATUS_EP_RX_ERR:
+                               s = "rx_err"; break;
+                       case EPxSTATUS_EP_BUSY:         /* ep0 only */
+                               s = "busy"; break;
+                       case EPxSTATUS_EP_STALL:
+                               s = "stall"; break;
+                       case EPxSTATUS_EP_INVALID:      // these "can't happen"
+                               s = "invalid"; break;
+                       default:
+                               s = "?"; break;
+                       } s; }),
+                       (tmp & EPxSTATUS_TOGGLE) ? "data1" : "data0",
+                       (tmp & EPxSTATUS_SUSPEND) ? " suspend" : "",
+                       (tmp & EPxSTATUS_FIFO_DISABLE) ? " disable" : "",
+                       (tmp & EPxSTATUS_STAGE_ERROR) ? " ep0stat" : ""
+                       ) < 0)
+                       goto done;
+
+               if (list_empty(&ep->queue)) {
+                       if (seq_puts(m, "\t(nothing queued)\n") < 0)
+                               goto done;
+                       continue;
+               }
+               list_for_each_entry(req, &ep->queue, queue) {
+                       if (ep->dma && req->queue.prev == &ep->queue) {
+                               if (i == UDC_MSTRD_ENDPOINT)
+                                       tmp = readl(&regs->in_dma_current);
+                               else
+                                       tmp = readl(&regs->out_dma_current);
+                               tmp -= req->req.dma;
+                               tmp++;
+                       } else
+                               tmp = req->req.actual;
+
+                       if (seq_printf(m,
+                               "\treq %p len %u/%u buf %p\n",
+                               &req->req, tmp, req->req.length,
+                               req->req.buf) < 0)
+                               goto done;
+               }
+       }
+
+done:
+       local_irq_restore(flags);
+       return 0;
+}
+
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int udc_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, udc_proc_read, PDE_DATA(file_inode(file)));
+}
+
+static const struct file_operations udc_proc_fops = {
+       .open           = udc_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
+
+/*-------------------------------------------------------------------------*/
+
+static void udc_reinit (struct goku_udc *dev)
+{
+       static char *names [] = { "ep0", "ep1-bulk", "ep2-bulk", "ep3-bulk" };
+
+       unsigned i;
+
+       INIT_LIST_HEAD (&dev->gadget.ep_list);
+       dev->gadget.ep0 = &dev->ep [0].ep;
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+       dev->ep0state = EP0_DISCONNECT;
+       dev->irqs = 0;
+
+       for (i = 0; i < 4; i++) {
+               struct goku_ep  *ep = &dev->ep[i];
+
+               ep->num = i;
+               ep->ep.name = names[i];
+               ep->reg_fifo = &dev->regs->ep_fifo [i];
+               ep->reg_status = &dev->regs->ep_status [i];
+               ep->reg_mode = &dev->regs->ep_mode[i];
+
+               ep->ep.ops = &goku_ep_ops;
+               list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
+               ep->dev = dev;
+               INIT_LIST_HEAD (&ep->queue);
+
+               ep_reset(NULL, ep);
+       }
+
+       dev->ep[0].reg_mode = NULL;
+       usb_ep_set_maxpacket_limit(&dev->ep[0].ep, MAX_EP0_SIZE);
+       list_del_init (&dev->ep[0].ep.ep_list);
+}
+
+static void udc_reset(struct goku_udc *dev)
+{
+       struct goku_udc_regs __iomem    *regs = dev->regs;
+
+       writel(0, &regs->power_detect);
+       writel(0, &regs->int_enable);
+       readl(&regs->int_enable);
+       dev->int_enable = 0;
+
+       /* deassert reset, leave USB D+ at hi-Z (no pullup)
+        * don't let INT_PWRDETECT sequence begin
+        */
+       udelay(250);
+       writel(PW_RESETB, &regs->power_detect);
+       readl(&regs->int_enable);
+}
+
+static void ep0_start(struct goku_udc *dev)
+{
+       struct goku_udc_regs __iomem    *regs = dev->regs;
+       unsigned                        i;
+
+       VDBG(dev, "%s\n", __func__);
+
+       udc_reset(dev);
+       udc_reinit (dev);
+       //writel(MST_EOPB_ENA | MST_TIMEOUT_ENA, &regs->dma_master);
+
+       /* hw handles set_address, set_feature, get_status; maybe more */
+       writel(   G_REQMODE_SET_INTF | G_REQMODE_GET_INTF
+               | G_REQMODE_SET_CONF | G_REQMODE_GET_CONF
+               | G_REQMODE_GET_DESC
+               | G_REQMODE_CLEAR_FEAT
+               , &regs->reqmode);
+
+       for (i = 0; i < 4; i++)
+               dev->ep[i].irqs = 0;
+
+       /* can't modify descriptors after writing UsbReady */
+       for (i = 0; i < DESC_LEN; i++)
+               writel(0, &regs->descriptors[i]);
+       writel(0, &regs->UsbReady);
+
+       /* expect ep0 requests when the host drops reset */
+       writel(PW_RESETB | PW_PULLUP, &regs->power_detect);
+       dev->int_enable = INT_DEVWIDE | INT_EP0;
+       writel(dev->int_enable, &dev->regs->int_enable);
+       readl(&regs->int_enable);
+       dev->gadget.speed = USB_SPEED_FULL;
+       dev->ep0state = EP0_IDLE;
+}
+
+static void udc_enable(struct goku_udc *dev)
+{
+       /* start enumeration now, or after power detect irq */
+       if (readl(&dev->regs->power_detect) & PW_DETECT)
+               ep0_start(dev);
+       else {
+               DBG(dev, "%s\n", __func__);
+               dev->int_enable = INT_PWRDETECT;
+               writel(dev->int_enable, &dev->regs->int_enable);
+       }
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* keeping it simple:
+ * - one bus driver, initted first;
+ * - one function driver, initted second
+ */
+
+/* when a driver is successfully registered, it will receive
+ * control requests including set_configuration(), which enables
+ * non-control requests.  then usb traffic follows until a
+ * disconnect is reported.  then a host may connect again, or
+ * the driver might get unbound.
+ */
+static int goku_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct goku_udc *dev = to_goku_udc(g);
+
+       /* hook up the driver */
+       driver->driver.bus = NULL;
+       dev->driver = driver;
+
+       /*
+        * then enable host detection and ep0; and we're ready
+        * for set_configuration as well as eventual disconnect.
+        */
+       udc_enable(dev);
+
+       return 0;
+}
+
+static void stop_activity(struct goku_udc *dev)
+{
+       unsigned        i;
+
+       DBG (dev, "%s\n", __func__);
+
+       /* disconnect gadget driver after quiesceing hw and the driver */
+       udc_reset (dev);
+       for (i = 0; i < 4; i++)
+               nuke(&dev->ep [i], -ESHUTDOWN);
+
+       if (dev->driver)
+               udc_enable(dev);
+}
+
+static int goku_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct goku_udc *dev = to_goku_udc(g);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&dev->lock, flags);
+       dev->driver = NULL;
+       stop_activity(dev);
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void ep0_setup(struct goku_udc *dev)
+{
+       struct goku_udc_regs __iomem    *regs = dev->regs;
+       struct usb_ctrlrequest          ctrl;
+       int                             tmp;
+
+       /* read SETUP packet and enter DATA stage */
+       ctrl.bRequestType = readl(&regs->bRequestType);
+       ctrl.bRequest = readl(&regs->bRequest);
+       ctrl.wValue  = cpu_to_le16((readl(&regs->wValueH)  << 8)
+                                       | readl(&regs->wValueL));
+       ctrl.wIndex  = cpu_to_le16((readl(&regs->wIndexH)  << 8)
+                                       | readl(&regs->wIndexL));
+       ctrl.wLength = cpu_to_le16((readl(&regs->wLengthH) << 8)
+                                       | readl(&regs->wLengthL));
+       writel(0, &regs->SetupRecv);
+
+       nuke(&dev->ep[0], 0);
+       dev->ep[0].stopped = 0;
+       if (likely(ctrl.bRequestType & USB_DIR_IN)) {
+               dev->ep[0].is_in = 1;
+               dev->ep0state = EP0_IN;
+               /* detect early status stages */
+               writel(ICONTROL_STATUSNAK, &dev->regs->IntControl);
+       } else {
+               dev->ep[0].is_in = 0;
+               dev->ep0state = EP0_OUT;
+
+               /* NOTE:  CLEAR_FEATURE is done in software so that we can
+                * synchronize transfer restarts after bulk IN stalls.  data
+                * won't even enter the fifo until the halt is cleared.
+                */
+               switch (ctrl.bRequest) {
+               case USB_REQ_CLEAR_FEATURE:
+                       switch (ctrl.bRequestType) {
+                       case USB_RECIP_ENDPOINT:
+                               tmp = le16_to_cpu(ctrl.wIndex) & 0x0f;
+                               /* active endpoint */
+                               if (tmp > 3 ||
+                                   (!dev->ep[tmp].ep.desc && tmp != 0))
+                                       goto stall;
+                               if (ctrl.wIndex & cpu_to_le16(
+                                               USB_DIR_IN)) {
+                                       if (!dev->ep[tmp].is_in)
+                                               goto stall;
+                               } else {
+                                       if (dev->ep[tmp].is_in)
+                                               goto stall;
+                               }
+                               if (ctrl.wValue != cpu_to_le16(
+                                               USB_ENDPOINT_HALT))
+                                       goto stall;
+                               if (tmp)
+                                       goku_clear_halt(&dev->ep[tmp]);
+succeed:
+                               /* start ep0out status stage */
+                               writel(~(1<<0), &regs->EOP);
+                               dev->ep[0].stopped = 1;
+                               dev->ep0state = EP0_STATUS;
+                               return;
+                       case USB_RECIP_DEVICE:
+                               /* device remote wakeup: always clear */
+                               if (ctrl.wValue != cpu_to_le16(1))
+                                       goto stall;
+                               VDBG(dev, "clear dev remote wakeup\n");
+                               goto succeed;
+                       case USB_RECIP_INTERFACE:
+                               goto stall;
+                       default:                /* pass to gadget driver */
+                               break;
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+#ifdef USB_TRACE
+       VDBG(dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
+               ctrl.bRequestType, ctrl.bRequest,
+               le16_to_cpu(ctrl.wValue), le16_to_cpu(ctrl.wIndex),
+               le16_to_cpu(ctrl.wLength));
+#endif
+
+       /* hw wants to know when we're configured (or not) */
+       dev->req_config = (ctrl.bRequest == USB_REQ_SET_CONFIGURATION
+                               && ctrl.bRequestType == USB_RECIP_DEVICE);
+       if (unlikely(dev->req_config))
+               dev->configured = (ctrl.wValue != cpu_to_le16(0));
+
+       /* delegate everything to the gadget driver.
+        * it may respond after this irq handler returns.
+        */
+       spin_unlock (&dev->lock);
+       tmp = dev->driver->setup(&dev->gadget, &ctrl);
+       spin_lock (&dev->lock);
+       if (unlikely(tmp < 0)) {
+stall:
+#ifdef USB_TRACE
+               VDBG(dev, "req %02x.%02x protocol STALL; err %d\n",
+                               ctrl.bRequestType, ctrl.bRequest, tmp);
+#endif
+               command(regs, COMMAND_STALL, 0);
+               dev->ep[0].stopped = 1;
+               dev->ep0state = EP0_STALL;
+       }
+
+       /* expect at least one data or status stage irq */
+}
+
+#define ACK(irqbit) { \
+               stat &= ~irqbit; \
+               writel(~irqbit, &regs->int_status); \
+               handled = 1; \
+               }
+
+static irqreturn_t goku_irq(int irq, void *_dev)
+{
+       struct goku_udc                 *dev = _dev;
+       struct goku_udc_regs __iomem    *regs = dev->regs;
+       struct goku_ep                  *ep;
+       u32                             stat, handled = 0;
+       unsigned                        i, rescans = 5;
+
+       spin_lock(&dev->lock);
+
+rescan:
+       stat = readl(&regs->int_status) & dev->int_enable;
+        if (!stat)
+               goto done;
+       dev->irqs++;
+
+       /* device-wide irqs */
+       if (unlikely(stat & INT_DEVWIDE)) {
+               if (stat & INT_SYSERROR) {
+                       ERROR(dev, "system error\n");
+                       stop_activity(dev);
+                       stat = 0;
+                       handled = 1;
+                       // FIXME have a neater way to prevent re-enumeration
+                       dev->driver = NULL;
+                       goto done;
+               }
+               if (stat & INT_PWRDETECT) {
+                       writel(~stat, &regs->int_status);
+                       if (readl(&dev->regs->power_detect) & PW_DETECT) {
+                               VDBG(dev, "connect\n");
+                               ep0_start(dev);
+                       } else {
+                               DBG(dev, "disconnect\n");
+                               if (dev->gadget.speed == USB_SPEED_FULL)
+                                       stop_activity(dev);
+                               dev->ep0state = EP0_DISCONNECT;
+                               dev->int_enable = INT_DEVWIDE;
+                               writel(dev->int_enable, &dev->regs->int_enable);
+                       }
+                       stat = 0;
+                       handled = 1;
+                       goto done;
+               }
+               if (stat & INT_SUSPEND) {
+                       ACK(INT_SUSPEND);
+                       if (readl(&regs->ep_status[0]) & EPxSTATUS_SUSPEND) {
+                               switch (dev->ep0state) {
+                               case EP0_DISCONNECT:
+                               case EP0_SUSPEND:
+                                       goto pm_next;
+                               default:
+                                       break;
+                               }
+                               DBG(dev, "USB suspend\n");
+                               dev->ep0state = EP0_SUSPEND;
+                               if (dev->gadget.speed != USB_SPEED_UNKNOWN
+                                               && dev->driver
+                                               && dev->driver->suspend) {
+                                       spin_unlock(&dev->lock);
+                                       dev->driver->suspend(&dev->gadget);
+                                       spin_lock(&dev->lock);
+                               }
+                       } else {
+                               if (dev->ep0state != EP0_SUSPEND) {
+                                       DBG(dev, "bogus USB resume %d\n",
+                                               dev->ep0state);
+                                       goto pm_next;
+                               }
+                               DBG(dev, "USB resume\n");
+                               dev->ep0state = EP0_IDLE;
+                               if (dev->gadget.speed != USB_SPEED_UNKNOWN
+                                               && dev->driver
+                                               && dev->driver->resume) {
+                                       spin_unlock(&dev->lock);
+                                       dev->driver->resume(&dev->gadget);
+                                       spin_lock(&dev->lock);
+                               }
+                       }
+               }
+pm_next:
+               if (stat & INT_USBRESET) {              /* hub reset done */
+                       ACK(INT_USBRESET);
+                       INFO(dev, "USB reset done, gadget %s\n",
+                               dev->driver->driver.name);
+               }
+               // and INT_ERR on some endpoint's crc/bitstuff/... problem
+       }
+
+       /* progress ep0 setup, data, or status stages.
+        * no transition {EP0_STATUS, EP0_STALL} --> EP0_IDLE; saves irqs
+        */
+       if (stat & INT_SETUP) {
+               ACK(INT_SETUP);
+               dev->ep[0].irqs++;
+               ep0_setup(dev);
+       }
+        if (stat & INT_STATUSNAK) {
+               ACK(INT_STATUSNAK|INT_ENDPOINT0);
+               if (dev->ep0state == EP0_IN) {
+                       ep = &dev->ep[0];
+                       ep->irqs++;
+                       nuke(ep, 0);
+                       writel(~(1<<0), &regs->EOP);
+                       dev->ep0state = EP0_STATUS;
+               }
+       }
+        if (stat & INT_ENDPOINT0) {
+               ACK(INT_ENDPOINT0);
+               ep = &dev->ep[0];
+               ep->irqs++;
+               pio_advance(ep);
+        }
+
+       /* dma completion */
+        if (stat & INT_MSTRDEND) {     /* IN */
+               ACK(INT_MSTRDEND);
+               ep = &dev->ep[UDC_MSTRD_ENDPOINT];
+               ep->irqs++;
+               dma_advance(dev, ep);
+        }
+        if (stat & INT_MSTWREND) {     /* OUT */
+               ACK(INT_MSTWREND);
+               ep = &dev->ep[UDC_MSTWR_ENDPOINT];
+               ep->irqs++;
+               dma_advance(dev, ep);
+        }
+        if (stat & INT_MSTWRTMOUT) {   /* OUT */
+               ACK(INT_MSTWRTMOUT);
+               ep = &dev->ep[UDC_MSTWR_ENDPOINT];
+               ep->irqs++;
+               ERROR(dev, "%s write timeout ?\n", ep->ep.name);
+               // reset dma? then dma_advance()
+        }
+
+       /* pio */
+       for (i = 1; i < 4; i++) {
+               u32             tmp = INT_EPxDATASET(i);
+
+               if (!(stat & tmp))
+                       continue;
+               ep = &dev->ep[i];
+               pio_advance(ep);
+               if (list_empty (&ep->queue))
+                       pio_irq_disable(dev, regs, i);
+               stat &= ~tmp;
+               handled = 1;
+               ep->irqs++;
+       }
+
+       if (rescans--)
+               goto rescan;
+
+done:
+       (void)readl(&regs->int_enable);
+       spin_unlock(&dev->lock);
+       if (stat)
+               DBG(dev, "unhandled irq status: %05x (%05x, %05x)\n", stat,
+                               readl(&regs->int_status), dev->int_enable);
+       return IRQ_RETVAL(handled);
+}
+
+#undef ACK
+
+/*-------------------------------------------------------------------------*/
+
+static void gadget_release(struct device *_dev)
+{
+       struct goku_udc *dev = dev_get_drvdata(_dev);
+
+       kfree(dev);
+}
+
+/* tear down the binding between this driver and the pci device */
+
+static void goku_remove(struct pci_dev *pdev)
+{
+       struct goku_udc         *dev = pci_get_drvdata(pdev);
+
+       DBG(dev, "%s\n", __func__);
+
+       usb_del_gadget_udc(&dev->gadget);
+
+       BUG_ON(dev->driver);
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+       remove_proc_entry(proc_node_name, NULL);
+#endif
+       if (dev->regs)
+               udc_reset(dev);
+       if (dev->got_irq)
+               free_irq(pdev->irq, dev);
+       if (dev->regs)
+               iounmap(dev->regs);
+       if (dev->got_region)
+               release_mem_region(pci_resource_start (pdev, 0),
+                               pci_resource_len (pdev, 0));
+       if (dev->enabled)
+               pci_disable_device(pdev);
+
+       dev->regs = NULL;
+
+       INFO(dev, "unbind\n");
+}
+
+/* wrap this driver around the specified pci device, but
+ * don't respond over USB until a gadget driver binds to us.
+ */
+
+static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       struct goku_udc         *dev = NULL;
+       unsigned long           resource, len;
+       void __iomem            *base = NULL;
+       int                     retval;
+
+       if (!pdev->irq) {
+               printk(KERN_ERR "Check PCI %s IRQ setup!\n", pci_name(pdev));
+               retval = -ENODEV;
+               goto err;
+       }
+
+       /* alloc, and start init */
+       dev = kzalloc (sizeof *dev, GFP_KERNEL);
+       if (dev == NULL){
+               pr_debug("enomem %s\n", pci_name(pdev));
+               retval = -ENOMEM;
+               goto err;
+       }
+
+       spin_lock_init(&dev->lock);
+       dev->pdev = pdev;
+       dev->gadget.ops = &goku_ops;
+       dev->gadget.max_speed = USB_SPEED_FULL;
+
+       /* the "gadget" abstracts/virtualizes the controller */
+       dev->gadget.name = driver_name;
+
+       /* now all the pci goodies ... */
+       retval = pci_enable_device(pdev);
+       if (retval < 0) {
+               DBG(dev, "can't enable, %d\n", retval);
+               goto err;
+       }
+       dev->enabled = 1;
+
+       resource = pci_resource_start(pdev, 0);
+       len = pci_resource_len(pdev, 0);
+       if (!request_mem_region(resource, len, driver_name)) {
+               DBG(dev, "controller already in use\n");
+               retval = -EBUSY;
+               goto err;
+       }
+       dev->got_region = 1;
+
+       base = ioremap_nocache(resource, len);
+       if (base == NULL) {
+               DBG(dev, "can't map memory\n");
+               retval = -EFAULT;
+               goto err;
+       }
+       dev->regs = (struct goku_udc_regs __iomem *) base;
+
+       pci_set_drvdata(pdev, dev);
+       INFO(dev, "%s\n", driver_desc);
+       INFO(dev, "version: " DRIVER_VERSION " %s\n", dmastr());
+       INFO(dev, "irq %d, pci mem %p\n", pdev->irq, base);
+
+       /* init to known state, then setup irqs */
+       udc_reset(dev);
+       udc_reinit (dev);
+       if (request_irq(pdev->irq, goku_irq, IRQF_SHARED,
+                       driver_name, dev) != 0) {
+               DBG(dev, "request interrupt %d failed\n", pdev->irq);
+               retval = -EBUSY;
+               goto err;
+       }
+       dev->got_irq = 1;
+       if (use_dma)
+               pci_set_master(pdev);
+
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+       proc_create_data(proc_node_name, 0, NULL, &udc_proc_fops, dev);
+#endif
+
+       retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+                       gadget_release);
+       if (retval)
+               goto err;
+
+       return 0;
+
+err:
+       if (dev)
+               goku_remove (pdev);
+       return retval;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static const struct pci_device_id pci_ids[] = { {
+       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class_mask =   ~0,
+       .vendor =       0x102f,         /* Toshiba */
+       .device =       0x0107,         /* this UDC */
+       .subvendor =    PCI_ANY_ID,
+       .subdevice =    PCI_ANY_ID,
+
+}, { /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE (pci, pci_ids);
+
+static struct pci_driver goku_pci_driver = {
+       .name =         (char *) driver_name,
+       .id_table =     pci_ids,
+
+       .probe =        goku_probe,
+       .remove =       goku_remove,
+
+       /* FIXME add power management support */
+};
+
+module_pci_driver(goku_pci_driver);
diff --git a/drivers/usb/gadget/udc/goku_udc.h b/drivers/usb/gadget/udc/goku_udc.h
new file mode 100644 (file)
index 0000000..86d2ada
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * Toshiba TC86C001 ("Goku-S") USB Device Controller driver
+ *
+ * Copyright (C) 2000-2002 Lineo
+ *      by Stuart Lynne, Tom Rushworth, and Bruce Balden
+ * Copyright (C) 2002 Toshiba Corporation
+ * Copyright (C) 2003 MontaVista Software (source@mvista.com)
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/*
+ * PCI BAR 0 points to these registers.
+ */
+struct goku_udc_regs {
+       /* irq management */
+       u32     int_status;             /* 0x000 */
+       u32     int_enable;
+#define INT_SUSPEND            0x00001         /* or resume */
+#define INT_USBRESET           0x00002
+#define INT_ENDPOINT0          0x00004
+#define INT_SETUP              0x00008
+#define INT_STATUS             0x00010
+#define INT_STATUSNAK          0x00020
+#define INT_EPxDATASET(n)      (0x00020 << (n))        /* 0 < n < 4 */
+#      define INT_EP1DATASET           0x00040
+#      define INT_EP2DATASET           0x00080
+#      define INT_EP3DATASET           0x00100
+#define INT_EPnNAK(n)          (0x00100 < (n))         /* 0 < n < 4 */
+#      define INT_EP1NAK               0x00200
+#      define INT_EP2NAK               0x00400
+#      define INT_EP3NAK               0x00800
+#define INT_SOF                        0x01000
+#define INT_ERR                        0x02000
+#define INT_MSTWRSET           0x04000
+#define INT_MSTWREND           0x08000
+#define INT_MSTWRTMOUT         0x10000
+#define INT_MSTRDEND           0x20000
+#define INT_SYSERROR           0x40000
+#define INT_PWRDETECT          0x80000
+
+#define        INT_DEVWIDE \
+       (INT_PWRDETECT|INT_SYSERROR/*|INT_ERR*/|INT_USBRESET|INT_SUSPEND)
+#define        INT_EP0 \
+       (INT_SETUP|INT_ENDPOINT0/*|INT_STATUS*/|INT_STATUSNAK)
+
+       u32     dma_master;
+#define MST_EOPB_DIS           0x0800
+#define MST_EOPB_ENA           0x0400
+#define MST_TIMEOUT_DIS                0x0200
+#define MST_TIMEOUT_ENA                0x0100
+#define MST_RD_EOPB            0x0080          /* write-only */
+#define MST_RD_RESET           0x0040
+#define MST_WR_RESET           0x0020
+#define MST_RD_ENA             0x0004          /* 1:start, 0:ignore */
+#define MST_WR_ENA             0x0002          /* 1:start, 0:ignore */
+#define MST_CONNECTION         0x0001          /* 0 for ep1out/ep2in */
+
+#define MST_R_BITS             (MST_EOPB_DIS|MST_EOPB_ENA \
+                                       |MST_RD_ENA|MST_RD_RESET)
+#define MST_W_BITS             (MST_TIMEOUT_DIS|MST_TIMEOUT_ENA \
+                                       |MST_WR_ENA|MST_WR_RESET)
+#define MST_RW_BITS            (MST_R_BITS|MST_W_BITS \
+                                       |MST_CONNECTION)
+
+/* these values assume (dma_master & MST_CONNECTION) == 0 */
+#define UDC_MSTWR_ENDPOINT        1
+#define UDC_MSTRD_ENDPOINT        2
+
+       /* dma master write */
+       u32     out_dma_start;
+       u32     out_dma_end;
+       u32     out_dma_current;
+
+       /* dma master read */
+       u32     in_dma_start;
+       u32     in_dma_end;
+       u32     in_dma_current;
+
+       u32     power_detect;
+#define PW_DETECT              0x04
+#define PW_RESETB              0x02
+#define PW_PULLUP              0x01
+
+       u8      _reserved0 [0x1d8];
+
+       /* endpoint registers */
+       u32     ep_fifo [4];            /* 0x200 */
+       u8      _reserved1 [0x10];
+       u32     ep_mode [4];            /* only 1-3 valid */
+       u8      _reserved2 [0x10];
+
+       u32     ep_status [4];
+#define EPxSTATUS_TOGGLE       0x40
+#define EPxSTATUS_SUSPEND      0x20
+#define EPxSTATUS_EP_MASK      (0x07<<2)
+#      define EPxSTATUS_EP_READY       (0<<2)
+#      define EPxSTATUS_EP_DATAIN      (1<<2)
+#      define EPxSTATUS_EP_FULL        (2<<2)
+#      define EPxSTATUS_EP_TX_ERR      (3<<2)
+#      define EPxSTATUS_EP_RX_ERR      (4<<2)
+#      define EPxSTATUS_EP_BUSY        (5<<2)
+#      define EPxSTATUS_EP_STALL       (6<<2)
+#      define EPxSTATUS_EP_INVALID     (7<<2)
+#define EPxSTATUS_FIFO_DISABLE 0x02
+#define EPxSTATUS_STAGE_ERROR  0x01
+
+       u8      _reserved3 [0x10];
+       u32     EPxSizeLA[4];
+#define PACKET_ACTIVE          (1<<7)
+#define DATASIZE               0x7f
+       u8      _reserved3a [0x10];
+       u32     EPxSizeLB[4];           /* only 1,2 valid */
+       u8      _reserved3b [0x10];
+       u32     EPxSizeHA[4];           /* only 1-3 valid */
+       u8      _reserved3c [0x10];
+       u32     EPxSizeHB[4];           /* only 1,2 valid */
+       u8      _reserved4[0x30];
+
+       /* SETUP packet contents */
+       u32     bRequestType;           /* 0x300 */
+       u32     bRequest;
+       u32     wValueL;
+       u32     wValueH;
+       u32     wIndexL;
+       u32     wIndexH;
+       u32     wLengthL;
+       u32     wLengthH;
+
+       /* command interaction/handshaking */
+       u32     SetupRecv;              /* 0x320 */
+       u32     CurrConfig;
+       u32     StdRequest;
+       u32     Request;
+       u32     DataSet;
+#define DATASET_A(epnum)       (1<<(2*(epnum)))
+#define DATASET_B(epnum)       (2<<(2*(epnum)))
+#define DATASET_AB(epnum)      (3<<(2*(epnum)))
+       u8      _reserved5[4];
+
+       u32     UsbState;
+#define USBSTATE_CONFIGURED    0x04
+#define USBSTATE_ADDRESSED     0x02
+#define USBSTATE_DEFAULT       0x01
+
+       u32     EOP;
+
+       u32     Command;                /* 0x340 */
+#define COMMAND_SETDATA0       2
+#define COMMAND_RESET          3
+#define COMMAND_STALL          4
+#define COMMAND_INVALID                5
+#define COMMAND_FIFO_DISABLE   7
+#define COMMAND_FIFO_ENABLE    8
+#define COMMAND_INIT_DESCRIPTOR        9
+#define COMMAND_FIFO_CLEAR     10      /* also stall */
+#define COMMAND_STALL_CLEAR    11
+#define COMMAND_EP(n)          ((n) << 4)
+
+       u32     EPxSingle;
+       u8      _reserved6[4];
+       u32     EPxBCS;
+       u8      _reserved7[8];
+       u32     IntControl;
+#define ICONTROL_STATUSNAK     1
+       u8      _reserved8[4];
+
+       u32     reqmode;        // 0x360 standard request mode, low 8 bits
+#define G_REQMODE_SET_INTF     (1<<7)
+#define G_REQMODE_GET_INTF     (1<<6)
+#define G_REQMODE_SET_CONF     (1<<5)
+#define G_REQMODE_GET_CONF     (1<<4)
+#define G_REQMODE_GET_DESC     (1<<3)
+#define G_REQMODE_SET_FEAT     (1<<2)
+#define G_REQMODE_CLEAR_FEAT   (1<<1)
+#define G_REQMODE_GET_STATUS   (1<<0)
+
+       u32     ReqMode;
+       u8      _reserved9[0x18];
+       u32     PortStatus;             /* 0x380 */
+       u8      _reserved10[8];
+       u32     address;
+       u32     buff_test;
+       u8      _reserved11[4];
+       u32     UsbReady;
+       u8      _reserved12[4];
+       u32     SetDescStall;           /* 0x3a0 */
+       u8      _reserved13[0x45c];
+
+       /* hardware could handle limited GET_DESCRIPTOR duties */
+#define        DESC_LEN        0x80
+       u32     descriptors[DESC_LEN];  /* 0x800 */
+       u8      _reserved14[0x600];
+
+} __attribute__ ((packed));
+
+#define        MAX_FIFO_SIZE   64
+#define        MAX_EP0_SIZE    8               /* ep0 fifo is bigger, though */
+
+
+/*-------------------------------------------------------------------------*/
+
+/* DRIVER DATA STRUCTURES and UTILITIES */
+
+struct goku_ep {
+       struct usb_ep                           ep;
+       struct goku_udc                         *dev;
+       unsigned long                           irqs;
+
+       unsigned                                num:8,
+                                               dma:1,
+                                               is_in:1,
+                                               stopped:1;
+
+       /* analogous to a host-side qh */
+       struct list_head                        queue;
+
+       u32 __iomem                             *reg_fifo;
+       u32 __iomem                             *reg_mode;
+       u32 __iomem                             *reg_status;
+};
+
+struct goku_request {
+       struct usb_request              req;
+       struct list_head                queue;
+
+       unsigned                        mapped:1;
+};
+
+enum ep0state {
+       EP0_DISCONNECT,         /* no host */
+       EP0_IDLE,               /* between STATUS ack and SETUP report */
+       EP0_IN, EP0_OUT,        /* data stage */
+       EP0_STATUS,             /* status stage */
+       EP0_STALL,              /* data or status stages */
+       EP0_SUSPEND,            /* usb suspend */
+};
+
+struct goku_udc {
+       /* each pci device provides one gadget, several endpoints */
+       struct usb_gadget               gadget;
+       spinlock_t                      lock;
+       struct goku_ep                  ep[4];
+       struct usb_gadget_driver        *driver;
+
+       enum ep0state                   ep0state;
+       unsigned                        got_irq:1,
+                                       got_region:1,
+                                       req_config:1,
+                                       configured:1,
+                                       enabled:1;
+
+       /* pci state used to access those endpoints */
+       struct pci_dev                  *pdev;
+       struct goku_udc_regs __iomem    *regs;
+       u32                             int_enable;
+
+       /* statistics... */
+       unsigned long                   irqs;
+};
+#define to_goku_udc(g)         (container_of((g), struct goku_udc, gadget))
+
+/*-------------------------------------------------------------------------*/
+
+#define xprintk(dev,level,fmt,args...) \
+       printk(level "%s %s: " fmt , driver_name , \
+                       pci_name(dev->pdev) , ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+       xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+       do { } while (0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG DBG
+#else
+#define VDBG(dev,fmt,args...) \
+       do { } while (0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+       xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARNING(dev,fmt,args...) \
+       xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+       xprintk(dev , KERN_INFO , fmt , ## args)
+
diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c
new file mode 100644 (file)
index 0000000..5d93f2b
--- /dev/null
@@ -0,0 +1,2235 @@
+/*
+ * USB Peripheral Controller driver for Aeroflex Gaisler GRUSBDC.
+ *
+ * 2013 (c) Aeroflex Gaisler AB
+ *
+ * This driver supports GRUSBDC USB Device Controller cores available in the
+ * GRLIB VHDL IP core library.
+ *
+ * Full documentation of the GRUSBDC core can be found here:
+ * http://www.gaisler.com/products/grlib/grip.pdf
+ *
+ * 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.
+ *
+ * Contributors:
+ * - Andreas Larsson <andreas@gaisler.com>
+ * - Marko Isomaki
+ */
+
+/*
+ * A GRUSBDC core can have up to 16 IN endpoints and 16 OUT endpoints each
+ * individually configurable to any of the four USB transfer types. This driver
+ * only supports cores in DMA mode.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+#include <asm/byteorder.h>
+
+#include "gr_udc.h"
+
+#define        DRIVER_NAME     "gr_udc"
+#define        DRIVER_DESC     "Aeroflex Gaisler GRUSBDC USB Peripheral Controller"
+
+static const char driver_name[] = DRIVER_NAME;
+static const char driver_desc[] = DRIVER_DESC;
+
+#define gr_read32(x) (ioread32be((x)))
+#define gr_write32(x, v) (iowrite32be((v), (x)))
+
+/* USB speed and corresponding string calculated from status register value */
+#define GR_SPEED(status) \
+       ((status & GR_STATUS_SP) ? USB_SPEED_FULL : USB_SPEED_HIGH)
+#define GR_SPEED_STR(status) usb_speed_string(GR_SPEED(status))
+
+/* Size of hardware buffer calculated from epctrl register value */
+#define GR_BUFFER_SIZE(epctrl)                                       \
+       ((((epctrl) & GR_EPCTRL_BUFSZ_MASK) >> GR_EPCTRL_BUFSZ_POS) * \
+        GR_EPCTRL_BUFSZ_SCALER)
+
+/* ---------------------------------------------------------------------- */
+/* Debug printout functionality */
+
+static const char * const gr_modestring[] = {"control", "iso", "bulk", "int"};
+
+static const char *gr_ep0state_string(enum gr_ep0state state)
+{
+       static const char *const names[] = {
+               [GR_EP0_DISCONNECT] = "disconnect",
+               [GR_EP0_SETUP] = "setup",
+               [GR_EP0_IDATA] = "idata",
+               [GR_EP0_ODATA] = "odata",
+               [GR_EP0_ISTATUS] = "istatus",
+               [GR_EP0_OSTATUS] = "ostatus",
+               [GR_EP0_STALL] = "stall",
+               [GR_EP0_SUSPEND] = "suspend",
+       };
+
+       if (state < 0 || state >= ARRAY_SIZE(names))
+               return "UNKNOWN";
+
+       return names[state];
+}
+
+#ifdef VERBOSE_DEBUG
+
+static void gr_dbgprint_request(const char *str, struct gr_ep *ep,
+                               struct gr_request *req)
+{
+       int buflen = ep->is_in ? req->req.length : req->req.actual;
+       int rowlen = 32;
+       int plen = min(rowlen, buflen);
+
+       dev_dbg(ep->dev->dev, "%s: 0x%p, %d bytes data%s:\n", str, req, buflen,
+               (buflen > plen ? " (truncated)" : ""));
+       print_hex_dump_debug("   ", DUMP_PREFIX_NONE,
+                            rowlen, 4, req->req.buf, plen, false);
+}
+
+static void gr_dbgprint_devreq(struct gr_udc *dev, u8 type, u8 request,
+                              u16 value, u16 index, u16 length)
+{
+       dev_vdbg(dev->dev, "REQ: %02x.%02x v%04x i%04x l%04x\n",
+                type, request, value, index, length);
+}
+#else /* !VERBOSE_DEBUG */
+
+static void gr_dbgprint_request(const char *str, struct gr_ep *ep,
+                               struct gr_request *req) {}
+
+static void gr_dbgprint_devreq(struct gr_udc *dev, u8 type, u8 request,
+                              u16 value, u16 index, u16 length) {}
+
+#endif /* VERBOSE_DEBUG */
+
+/* ---------------------------------------------------------------------- */
+/* Debugfs functionality */
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+
+static void gr_seq_ep_show(struct seq_file *seq, struct gr_ep *ep)
+{
+       u32 epctrl = gr_read32(&ep->regs->epctrl);
+       u32 epstat = gr_read32(&ep->regs->epstat);
+       int mode = (epctrl & GR_EPCTRL_TT_MASK) >> GR_EPCTRL_TT_POS;
+       struct gr_request *req;
+
+       seq_printf(seq, "%s:\n", ep->ep.name);
+       seq_printf(seq, "  mode = %s\n", gr_modestring[mode]);
+       seq_printf(seq, "  halted: %d\n", !!(epctrl & GR_EPCTRL_EH));
+       seq_printf(seq, "  disabled: %d\n", !!(epctrl & GR_EPCTRL_ED));
+       seq_printf(seq, "  valid: %d\n", !!(epctrl & GR_EPCTRL_EV));
+       seq_printf(seq, "  dma_start = %d\n", ep->dma_start);
+       seq_printf(seq, "  stopped = %d\n", ep->stopped);
+       seq_printf(seq, "  wedged = %d\n", ep->wedged);
+       seq_printf(seq, "  callback = %d\n", ep->callback);
+       seq_printf(seq, "  maxpacket = %d\n", ep->ep.maxpacket);
+       seq_printf(seq, "  maxpacket_limit = %d\n", ep->ep.maxpacket_limit);
+       seq_printf(seq, "  bytes_per_buffer = %d\n", ep->bytes_per_buffer);
+       if (mode == 1 || mode == 3)
+               seq_printf(seq, "  nt = %d\n",
+                          (epctrl & GR_EPCTRL_NT_MASK) >> GR_EPCTRL_NT_POS);
+
+       seq_printf(seq, "  Buffer 0: %s %s%d\n",
+                  epstat & GR_EPSTAT_B0 ? "valid" : "invalid",
+                  epstat & GR_EPSTAT_BS ? " " : "selected ",
+                  (epstat & GR_EPSTAT_B0CNT_MASK) >> GR_EPSTAT_B0CNT_POS);
+       seq_printf(seq, "  Buffer 1: %s %s%d\n",
+                  epstat & GR_EPSTAT_B1 ? "valid" : "invalid",
+                  epstat & GR_EPSTAT_BS ? "selected " : " ",
+                  (epstat & GR_EPSTAT_B1CNT_MASK) >> GR_EPSTAT_B1CNT_POS);
+
+       if (list_empty(&ep->queue)) {
+               seq_puts(seq, "  Queue: empty\n\n");
+               return;
+       }
+
+       seq_puts(seq, "  Queue:\n");
+       list_for_each_entry(req, &ep->queue, queue) {
+               struct gr_dma_desc *desc;
+               struct gr_dma_desc *next;
+
+               seq_printf(seq, "    0x%p: 0x%p %d %d\n", req,
+                          &req->req.buf, req->req.actual, req->req.length);
+
+               next = req->first_desc;
+               do {
+                       desc = next;
+                       next = desc->next_desc;
+                       seq_printf(seq, "    %c 0x%p (0x%08x): 0x%05x 0x%08x\n",
+                                  desc == req->curr_desc ? 'c' : ' ',
+                                  desc, desc->paddr, desc->ctrl, desc->data);
+               } while (desc != req->last_desc);
+       }
+       seq_puts(seq, "\n");
+}
+
+
+static int gr_seq_show(struct seq_file *seq, void *v)
+{
+       struct gr_udc *dev = seq->private;
+       u32 control = gr_read32(&dev->regs->control);
+       u32 status = gr_read32(&dev->regs->status);
+       struct gr_ep *ep;
+
+       seq_printf(seq, "usb state = %s\n",
+                  usb_state_string(dev->gadget.state));
+       seq_printf(seq, "address = %d\n",
+                  (control & GR_CONTROL_UA_MASK) >> GR_CONTROL_UA_POS);
+       seq_printf(seq, "speed = %s\n", GR_SPEED_STR(status));
+       seq_printf(seq, "ep0state = %s\n", gr_ep0state_string(dev->ep0state));
+       seq_printf(seq, "irq_enabled = %d\n", dev->irq_enabled);
+       seq_printf(seq, "remote_wakeup = %d\n", dev->remote_wakeup);
+       seq_printf(seq, "test_mode = %d\n", dev->test_mode);
+       seq_puts(seq, "\n");
+
+       list_for_each_entry(ep, &dev->ep_list, ep_list)
+               gr_seq_ep_show(seq, ep);
+
+       return 0;
+}
+
+static int gr_dfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, gr_seq_show, inode->i_private);
+}
+
+static const struct file_operations gr_dfs_fops = {
+       .owner          = THIS_MODULE,
+       .open           = gr_dfs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static void gr_dfs_create(struct gr_udc *dev)
+{
+       const char *name = "gr_udc_state";
+
+       dev->dfs_root = debugfs_create_dir(dev_name(dev->dev), NULL);
+       dev->dfs_state = debugfs_create_file(name, 0444, dev->dfs_root, dev,
+                                            &gr_dfs_fops);
+}
+
+static void gr_dfs_delete(struct gr_udc *dev)
+{
+       /* Handles NULL and ERR pointers internally */
+       debugfs_remove(dev->dfs_state);
+       debugfs_remove(dev->dfs_root);
+}
+
+#else /* !CONFIG_USB_GADGET_DEBUG_FS */
+
+static void gr_dfs_create(struct gr_udc *dev) {}
+static void gr_dfs_delete(struct gr_udc *dev) {}
+
+#endif /* CONFIG_USB_GADGET_DEBUG_FS */
+
+/* ---------------------------------------------------------------------- */
+/* DMA and request handling */
+
+/* Allocates a new struct gr_dma_desc, sets paddr and zeroes the rest */
+static struct gr_dma_desc *gr_alloc_dma_desc(struct gr_ep *ep, gfp_t gfp_flags)
+{
+       dma_addr_t paddr;
+       struct gr_dma_desc *dma_desc;
+
+       dma_desc = dma_pool_alloc(ep->dev->desc_pool, gfp_flags, &paddr);
+       if (!dma_desc) {
+               dev_err(ep->dev->dev, "Could not allocate from DMA pool\n");
+               return NULL;
+       }
+
+       memset(dma_desc, 0, sizeof(*dma_desc));
+       dma_desc->paddr = paddr;
+
+       return dma_desc;
+}
+
+static inline void gr_free_dma_desc(struct gr_udc *dev,
+                                   struct gr_dma_desc *desc)
+{
+       dma_pool_free(dev->desc_pool, desc, (dma_addr_t)desc->paddr);
+}
+
+/* Frees the chain of struct gr_dma_desc for the given request */
+static void gr_free_dma_desc_chain(struct gr_udc *dev, struct gr_request *req)
+{
+       struct gr_dma_desc *desc;
+       struct gr_dma_desc *next;
+
+       next = req->first_desc;
+       if (!next)
+               return;
+
+       do {
+               desc = next;
+               next = desc->next_desc;
+               gr_free_dma_desc(dev, desc);
+       } while (desc != req->last_desc);
+
+       req->first_desc = NULL;
+       req->curr_desc = NULL;
+       req->last_desc = NULL;
+}
+
+static void gr_ep0_setup(struct gr_udc *dev, struct gr_request *req);
+
+/*
+ * Frees allocated resources and calls the appropriate completion function/setup
+ * package handler for a finished request.
+ *
+ * Must be called with dev->lock held and irqs disabled.
+ */
+static void gr_finish_request(struct gr_ep *ep, struct gr_request *req,
+                             int status)
+       __releases(&dev->lock)
+       __acquires(&dev->lock)
+{
+       struct gr_udc *dev;
+
+       list_del_init(&req->queue);
+
+       if (likely(req->req.status == -EINPROGRESS))
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       dev = ep->dev;
+       usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
+       gr_free_dma_desc_chain(dev, req);
+
+       if (ep->is_in) /* For OUT, actual gets updated bit by bit */
+               req->req.actual = req->req.length;
+
+       if (!status) {
+               if (ep->is_in)
+                       gr_dbgprint_request("SENT", ep, req);
+               else
+                       gr_dbgprint_request("RECV", ep, req);
+       }
+
+       /* Prevent changes to ep->queue during callback */
+       ep->callback = 1;
+       if (req == dev->ep0reqo && !status) {
+               if (req->setup)
+                       gr_ep0_setup(dev, req);
+               else
+                       dev_err(dev->dev,
+                               "Unexpected non setup packet on ep0in\n");
+       } else if (req->req.complete) {
+               spin_unlock(&dev->lock);
+
+               req->req.complete(&ep->ep, &req->req);
+
+               spin_lock(&dev->lock);
+       }
+       ep->callback = 0;
+}
+
+static struct usb_request *gr_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct gr_request *req;
+
+       req = kzalloc(sizeof(*req), gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+/*
+ * Starts DMA for endpoint ep if there are requests in the queue.
+ *
+ * Must be called with dev->lock held and with !ep->stopped.
+ */
+static void gr_start_dma(struct gr_ep *ep)
+{
+       struct gr_request *req;
+       u32 dmactrl;
+
+       if (list_empty(&ep->queue)) {
+               ep->dma_start = 0;
+               return;
+       }
+
+       req = list_first_entry(&ep->queue, struct gr_request, queue);
+
+       /* A descriptor should already have been allocated */
+       BUG_ON(!req->curr_desc);
+
+       wmb(); /* Make sure all is settled before handing it over to DMA */
+
+       /* Set the descriptor pointer in the hardware */
+       gr_write32(&ep->regs->dmaaddr, req->curr_desc->paddr);
+
+       /* Announce available descriptors */
+       dmactrl = gr_read32(&ep->regs->dmactrl);
+       gr_write32(&ep->regs->dmactrl, dmactrl | GR_DMACTRL_DA);
+
+       ep->dma_start = 1;
+}
+
+/*
+ * Finishes the first request in the ep's queue and, if available, starts the
+ * next request in queue.
+ *
+ * Must be called with dev->lock held, irqs disabled and with !ep->stopped.
+ */
+static void gr_dma_advance(struct gr_ep *ep, int status)
+{
+       struct gr_request *req;
+
+       req = list_first_entry(&ep->queue, struct gr_request, queue);
+       gr_finish_request(ep, req, status);
+       gr_start_dma(ep); /* Regardless of ep->dma_start */
+}
+
+/*
+ * Abort DMA for an endpoint. Sets the abort DMA bit which causes an ongoing DMA
+ * transfer to be canceled and clears GR_DMACTRL_DA.
+ *
+ * Must be called with dev->lock held.
+ */
+static void gr_abort_dma(struct gr_ep *ep)
+{
+       u32 dmactrl;
+
+       dmactrl = gr_read32(&ep->regs->dmactrl);
+       gr_write32(&ep->regs->dmactrl, dmactrl | GR_DMACTRL_AD);
+}
+
+/*
+ * Allocates and sets up a struct gr_dma_desc and putting it on the descriptor
+ * chain.
+ *
+ * Size is not used for OUT endpoints. Hardware can not be instructed to handle
+ * smaller buffer than MAXPL in the OUT direction.
+ */
+static int gr_add_dma_desc(struct gr_ep *ep, struct gr_request *req,
+                          dma_addr_t data, unsigned size, gfp_t gfp_flags)
+{
+       struct gr_dma_desc *desc;
+
+       desc = gr_alloc_dma_desc(ep, gfp_flags);
+       if (!desc)
+               return -ENOMEM;
+
+       desc->data = data;
+       if (ep->is_in)
+               desc->ctrl =
+                       (GR_DESC_IN_CTRL_LEN_MASK & size) | GR_DESC_IN_CTRL_EN;
+       else
+               desc->ctrl = GR_DESC_OUT_CTRL_IE;
+
+       if (!req->first_desc) {
+               req->first_desc = desc;
+               req->curr_desc = desc;
+       } else {
+               req->last_desc->next_desc = desc;
+               req->last_desc->next = desc->paddr;
+               req->last_desc->ctrl |= GR_DESC_OUT_CTRL_NX;
+       }
+       req->last_desc = desc;
+
+       return 0;
+}
+
+/*
+ * Sets up a chain of struct gr_dma_descriptors pointing to buffers that
+ * together covers req->req.length bytes of the buffer at DMA address
+ * req->req.dma for the OUT direction.
+ *
+ * The first descriptor in the chain is enabled, the rest disabled. The
+ * interrupt handler will later enable them one by one when needed so we can
+ * find out when the transfer is finished. For OUT endpoints, all descriptors
+ * therefore generate interrutps.
+ */
+static int gr_setup_out_desc_list(struct gr_ep *ep, struct gr_request *req,
+                                 gfp_t gfp_flags)
+{
+       u16 bytes_left; /* Bytes left to provide descriptors for */
+       u16 bytes_used; /* Bytes accommodated for */
+       int ret = 0;
+
+       req->first_desc = NULL; /* Signals that no allocation is done yet */
+       bytes_left = req->req.length;
+       bytes_used = 0;
+       while (bytes_left > 0) {
+               dma_addr_t start = req->req.dma + bytes_used;
+               u16 size = min(bytes_left, ep->bytes_per_buffer);
+
+               /* Should not happen however - gr_queue stops such lengths */
+               if (size < ep->bytes_per_buffer)
+                       dev_warn(ep->dev->dev,
+                                "Buffer overrun risk: %u < %u bytes/buffer\n",
+                                size, ep->bytes_per_buffer);
+
+               ret = gr_add_dma_desc(ep, req, start, size, gfp_flags);
+               if (ret)
+                       goto alloc_err;
+
+               bytes_left -= size;
+               bytes_used += size;
+       }
+
+       req->first_desc->ctrl |= GR_DESC_OUT_CTRL_EN;
+
+       return 0;
+
+alloc_err:
+       gr_free_dma_desc_chain(ep->dev, req);
+
+       return ret;
+}
+
+/*
+ * Sets up a chain of struct gr_dma_descriptors pointing to buffers that
+ * together covers req->req.length bytes of the buffer at DMA address
+ * req->req.dma for the IN direction.
+ *
+ * When more data is provided than the maximum payload size, the hardware splits
+ * this up into several payloads automatically. Moreover, ep->bytes_per_buffer
+ * is always set to a multiple of the maximum payload (restricted to the valid
+ * number of maximum payloads during high bandwidth isochronous or interrupt
+ * transfers)
+ *
+ * All descriptors are enabled from the beginning and we only generate an
+ * interrupt for the last one indicating that the entire request has been pushed
+ * to hardware.
+ */
+static int gr_setup_in_desc_list(struct gr_ep *ep, struct gr_request *req,
+                                gfp_t gfp_flags)
+{
+       u16 bytes_left; /* Bytes left in req to provide descriptors for */
+       u16 bytes_used; /* Bytes in req accommodated for */
+       int ret = 0;
+
+       req->first_desc = NULL; /* Signals that no allocation is done yet */
+       bytes_left = req->req.length;
+       bytes_used = 0;
+       do { /* Allow for zero length packets */
+               dma_addr_t start = req->req.dma + bytes_used;
+               u16 size = min(bytes_left, ep->bytes_per_buffer);
+
+               ret = gr_add_dma_desc(ep, req, start, size, gfp_flags);
+               if (ret)
+                       goto alloc_err;
+
+               bytes_left -= size;
+               bytes_used += size;
+       } while (bytes_left > 0);
+
+       /*
+        * Send an extra zero length packet to indicate that no more data is
+        * available when req->req.zero is set and the data length is even
+        * multiples of ep->ep.maxpacket.
+        */
+       if (req->req.zero && (req->req.length % ep->ep.maxpacket == 0)) {
+               ret = gr_add_dma_desc(ep, req, 0, 0, gfp_flags);
+               if (ret)
+                       goto alloc_err;
+       }
+
+       /*
+        * For IN packets we only want to know when the last packet has been
+        * transmitted (not just put into internal buffers).
+        */
+       req->last_desc->ctrl |= GR_DESC_IN_CTRL_PI;
+
+       return 0;
+
+alloc_err:
+       gr_free_dma_desc_chain(ep->dev, req);
+
+       return ret;
+}
+
+/* Must be called with dev->lock held */
+static int gr_queue(struct gr_ep *ep, struct gr_request *req, gfp_t gfp_flags)
+{
+       struct gr_udc *dev = ep->dev;
+       int ret;
+
+       if (unlikely(!ep->ep.desc && ep->num != 0)) {
+               dev_err(dev->dev, "No ep descriptor for %s\n", ep->ep.name);
+               return -EINVAL;
+       }
+
+       if (unlikely(!req->req.buf || !list_empty(&req->queue))) {
+               dev_err(dev->dev,
+                       "Invalid request for %s: buf=%p list_empty=%d\n",
+                       ep->ep.name, req->req.buf, list_empty(&req->queue));
+               return -EINVAL;
+       }
+
+       /*
+        * The DMA controller can not handle smaller OUT buffers than
+        * maxpacket. It could lead to buffer overruns if unexpectedly long
+        * packet are received.
+        */
+       if (!ep->is_in && (req->req.length % ep->ep.maxpacket) != 0) {
+               dev_err(dev->dev,
+                       "OUT request length %d is not multiple of maxpacket\n",
+                       req->req.length);
+               return -EMSGSIZE;
+       }
+
+       if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+               dev_err(dev->dev, "-ESHUTDOWN");
+               return -ESHUTDOWN;
+       }
+
+       /* Can't touch registers when suspended */
+       if (dev->ep0state == GR_EP0_SUSPEND) {
+               dev_err(dev->dev, "-EBUSY");
+               return -EBUSY;
+       }
+
+       /* Set up DMA mapping in case the caller didn't */
+       ret = usb_gadget_map_request(&dev->gadget, &req->req, ep->is_in);
+       if (ret) {
+               dev_err(dev->dev, "usb_gadget_map_request");
+               return ret;
+       }
+
+       if (ep->is_in)
+               ret = gr_setup_in_desc_list(ep, req, gfp_flags);
+       else
+               ret = gr_setup_out_desc_list(ep, req, gfp_flags);
+       if (ret)
+               return ret;
+
+       req->req.status = -EINPROGRESS;
+       req->req.actual = 0;
+       list_add_tail(&req->queue, &ep->queue);
+
+       /* Start DMA if not started, otherwise interrupt handler handles it */
+       if (!ep->dma_start && likely(!ep->stopped))
+               gr_start_dma(ep);
+
+       return 0;
+}
+
+/*
+ * Queue a request from within the driver.
+ *
+ * Must be called with dev->lock held.
+ */
+static inline int gr_queue_int(struct gr_ep *ep, struct gr_request *req,
+                              gfp_t gfp_flags)
+{
+       if (ep->is_in)
+               gr_dbgprint_request("RESP", ep, req);
+
+       return gr_queue(ep, req, gfp_flags);
+}
+
+/* ---------------------------------------------------------------------- */
+/* General helper functions */
+
+/*
+ * Dequeue ALL requests.
+ *
+ * Must be called with dev->lock held and irqs disabled.
+ */
+static void gr_ep_nuke(struct gr_ep *ep)
+{
+       struct gr_request *req;
+
+       ep->stopped = 1;
+       ep->dma_start = 0;
+       gr_abort_dma(ep);
+
+       while (!list_empty(&ep->queue)) {
+               req = list_first_entry(&ep->queue, struct gr_request, queue);
+               gr_finish_request(ep, req, -ESHUTDOWN);
+       }
+}
+
+/*
+ * Reset the hardware state of this endpoint.
+ *
+ * Must be called with dev->lock held.
+ */
+static void gr_ep_reset(struct gr_ep *ep)
+{
+       gr_write32(&ep->regs->epctrl, 0);
+       gr_write32(&ep->regs->dmactrl, 0);
+
+       ep->ep.maxpacket = MAX_CTRL_PL_SIZE;
+       ep->ep.desc = NULL;
+       ep->stopped = 1;
+       ep->dma_start = 0;
+}
+
+/*
+ * Generate STALL on ep0in/out.
+ *
+ * Must be called with dev->lock held.
+ */
+static void gr_control_stall(struct gr_udc *dev)
+{
+       u32 epctrl;
+
+       epctrl = gr_read32(&dev->epo[0].regs->epctrl);
+       gr_write32(&dev->epo[0].regs->epctrl, epctrl | GR_EPCTRL_CS);
+       epctrl = gr_read32(&dev->epi[0].regs->epctrl);
+       gr_write32(&dev->epi[0].regs->epctrl, epctrl | GR_EPCTRL_CS);
+
+       dev->ep0state = GR_EP0_STALL;
+}
+
+/*
+ * Halts, halts and wedges, or clears halt for an endpoint.
+ *
+ * Must be called with dev->lock held.
+ */
+static int gr_ep_halt_wedge(struct gr_ep *ep, int halt, int wedge, int fromhost)
+{
+       u32 epctrl;
+       int retval = 0;
+
+       if (ep->num && !ep->ep.desc)
+               return -EINVAL;
+
+       if (ep->num && ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC)
+               return -EOPNOTSUPP;
+
+       /* Never actually halt ep0, and therefore never clear halt for ep0 */
+       if (!ep->num) {
+               if (halt && !fromhost) {
+                       /* ep0 halt from gadget - generate protocol stall */
+                       gr_control_stall(ep->dev);
+                       dev_dbg(ep->dev->dev, "EP: stall ep0\n");
+                       return 0;
+               }
+               return -EINVAL;
+       }
+
+       dev_dbg(ep->dev->dev, "EP: %s halt %s\n",
+               (halt ? (wedge ? "wedge" : "set") : "clear"), ep->ep.name);
+
+       epctrl = gr_read32(&ep->regs->epctrl);
+       if (halt) {
+               /* Set HALT */
+               gr_write32(&ep->regs->epctrl, epctrl | GR_EPCTRL_EH);
+               ep->stopped = 1;
+               if (wedge)
+                       ep->wedged = 1;
+       } else {
+               gr_write32(&ep->regs->epctrl, epctrl & ~GR_EPCTRL_EH);
+               ep->stopped = 0;
+               ep->wedged = 0;
+
+               /* Things might have been queued up in the meantime */
+               if (!ep->dma_start)
+                       gr_start_dma(ep);
+       }
+
+       return retval;
+}
+
+/* Must be called with dev->lock held */
+static inline void gr_set_ep0state(struct gr_udc *dev, enum gr_ep0state value)
+{
+       if (dev->ep0state != value)
+               dev_vdbg(dev->dev, "STATE:  ep0state=%s\n",
+                        gr_ep0state_string(value));
+       dev->ep0state = value;
+}
+
+/*
+ * Should only be called when endpoints can not generate interrupts.
+ *
+ * Must be called with dev->lock held.
+ */
+static void gr_disable_interrupts_and_pullup(struct gr_udc *dev)
+{
+       gr_write32(&dev->regs->control, 0);
+       wmb(); /* Make sure that we do not deny one of our interrupts */
+       dev->irq_enabled = 0;
+}
+
+/*
+ * Stop all device activity and disable data line pullup.
+ *
+ * Must be called with dev->lock held and irqs disabled.
+ */
+static void gr_stop_activity(struct gr_udc *dev)
+{
+       struct gr_ep *ep;
+
+       list_for_each_entry(ep, &dev->ep_list, ep_list)
+               gr_ep_nuke(ep);
+
+       gr_disable_interrupts_and_pullup(dev);
+
+       gr_set_ep0state(dev, GR_EP0_DISCONNECT);
+       usb_gadget_set_state(&dev->gadget, USB_STATE_NOTATTACHED);
+}
+
+/* ---------------------------------------------------------------------- */
+/* ep0 setup packet handling */
+
+static void gr_ep0_testmode_complete(struct usb_ep *_ep,
+                                    struct usb_request *_req)
+{
+       struct gr_ep *ep;
+       struct gr_udc *dev;
+       u32 control;
+
+       ep = container_of(_ep, struct gr_ep, ep);
+       dev = ep->dev;
+
+       spin_lock(&dev->lock);
+
+       control = gr_read32(&dev->regs->control);
+       control |= GR_CONTROL_TM | (dev->test_mode << GR_CONTROL_TS_POS);
+       gr_write32(&dev->regs->control, control);
+
+       spin_unlock(&dev->lock);
+}
+
+static void gr_ep0_dummy_complete(struct usb_ep *_ep, struct usb_request *_req)
+{
+       /* Nothing needs to be done here */
+}
+
+/*
+ * Queue a response on ep0in.
+ *
+ * Must be called with dev->lock held.
+ */
+static int gr_ep0_respond(struct gr_udc *dev, u8 *buf, int length,
+                         void (*complete)(struct usb_ep *ep,
+                                          struct usb_request *req))
+{
+       u8 *reqbuf = dev->ep0reqi->req.buf;
+       int status;
+       int i;
+
+       for (i = 0; i < length; i++)
+               reqbuf[i] = buf[i];
+       dev->ep0reqi->req.length = length;
+       dev->ep0reqi->req.complete = complete;
+
+       status = gr_queue_int(&dev->epi[0], dev->ep0reqi, GFP_ATOMIC);
+       if (status < 0)
+               dev_err(dev->dev,
+                       "Could not queue ep0in setup response: %d\n", status);
+
+       return status;
+}
+
+/*
+ * Queue a 2 byte response on ep0in.
+ *
+ * Must be called with dev->lock held.
+ */
+static inline int gr_ep0_respond_u16(struct gr_udc *dev, u16 response)
+{
+       __le16 le_response = cpu_to_le16(response);
+
+       return gr_ep0_respond(dev, (u8 *)&le_response, 2,
+                             gr_ep0_dummy_complete);
+}
+
+/*
+ * Queue a ZLP response on ep0in.
+ *
+ * Must be called with dev->lock held.
+ */
+static inline int gr_ep0_respond_empty(struct gr_udc *dev)
+{
+       return gr_ep0_respond(dev, NULL, 0, gr_ep0_dummy_complete);
+}
+
+/*
+ * This is run when a SET_ADDRESS request is received. First writes
+ * the new address to the control register which is updated internally
+ * when the next IN packet is ACKED.
+ *
+ * Must be called with dev->lock held.
+ */
+static void gr_set_address(struct gr_udc *dev, u8 address)
+{
+       u32 control;
+
+       control = gr_read32(&dev->regs->control) & ~GR_CONTROL_UA_MASK;
+       control |= (address << GR_CONTROL_UA_POS) & GR_CONTROL_UA_MASK;
+       control |= GR_CONTROL_SU;
+       gr_write32(&dev->regs->control, control);
+}
+
+/*
+ * Returns negative for STALL, 0 for successful handling and positive for
+ * delegation.
+ *
+ * Must be called with dev->lock held.
+ */
+static int gr_device_request(struct gr_udc *dev, u8 type, u8 request,
+                            u16 value, u16 index)
+{
+       u16 response;
+       u8 test;
+
+       switch (request) {
+       case USB_REQ_SET_ADDRESS:
+               dev_dbg(dev->dev, "STATUS: address %d\n", value & 0xff);
+               gr_set_address(dev, value & 0xff);
+               if (value)
+                       usb_gadget_set_state(&dev->gadget, USB_STATE_ADDRESS);
+               else
+                       usb_gadget_set_state(&dev->gadget, USB_STATE_DEFAULT);
+               return gr_ep0_respond_empty(dev);
+
+       case USB_REQ_GET_STATUS:
+               /* Self powered | remote wakeup */
+               response = 0x0001 | (dev->remote_wakeup ? 0x0002 : 0);
+               return gr_ep0_respond_u16(dev, response);
+
+       case USB_REQ_SET_FEATURE:
+               switch (value) {
+               case USB_DEVICE_REMOTE_WAKEUP:
+                       /* Allow remote wakeup */
+                       dev->remote_wakeup = 1;
+                       return gr_ep0_respond_empty(dev);
+
+               case USB_DEVICE_TEST_MODE:
+                       /* The hardware does not support TEST_FORCE_EN */
+                       test = index >> 8;
+                       if (test >= TEST_J && test <= TEST_PACKET) {
+                               dev->test_mode = test;
+                               return gr_ep0_respond(dev, NULL, 0,
+                                                     gr_ep0_testmode_complete);
+                       }
+               }
+               break;
+
+       case USB_REQ_CLEAR_FEATURE:
+               switch (value) {
+               case USB_DEVICE_REMOTE_WAKEUP:
+                       /* Disallow remote wakeup */
+                       dev->remote_wakeup = 0;
+                       return gr_ep0_respond_empty(dev);
+               }
+               break;
+       }
+
+       return 1; /* Delegate the rest */
+}
+
+/*
+ * Returns negative for STALL, 0 for successful handling and positive for
+ * delegation.
+ *
+ * Must be called with dev->lock held.
+ */
+static int gr_interface_request(struct gr_udc *dev, u8 type, u8 request,
+                               u16 value, u16 index)
+{
+       if (dev->gadget.state != USB_STATE_CONFIGURED)
+               return -1;
+
+       /*
+        * Should return STALL for invalid interfaces, but udc driver does not
+        * know anything about that. However, many gadget drivers do not handle
+        * GET_STATUS so we need to take care of that.
+        */
+
+       switch (request) {
+       case USB_REQ_GET_STATUS:
+               return gr_ep0_respond_u16(dev, 0x0000);
+
+       case USB_REQ_SET_FEATURE:
+       case USB_REQ_CLEAR_FEATURE:
+               /*
+                * No possible valid standard requests. Still let gadget drivers
+                * have a go at it.
+                */
+               break;
+       }
+
+       return 1; /* Delegate the rest */
+}
+
+/*
+ * Returns negative for STALL, 0 for successful handling and positive for
+ * delegation.
+ *
+ * Must be called with dev->lock held.
+ */
+static int gr_endpoint_request(struct gr_udc *dev, u8 type, u8 request,
+                              u16 value, u16 index)
+{
+       struct gr_ep *ep;
+       int status;
+       int halted;
+       u8 epnum = index & USB_ENDPOINT_NUMBER_MASK;
+       u8 is_in = index & USB_ENDPOINT_DIR_MASK;
+
+       if ((is_in && epnum >= dev->nepi) || (!is_in && epnum >= dev->nepo))
+               return -1;
+
+       if (dev->gadget.state != USB_STATE_CONFIGURED && epnum != 0)
+               return -1;
+
+       ep = (is_in ? &dev->epi[epnum] : &dev->epo[epnum]);
+
+       switch (request) {
+       case USB_REQ_GET_STATUS:
+               halted = gr_read32(&ep->regs->epctrl) & GR_EPCTRL_EH;
+               return gr_ep0_respond_u16(dev, halted ? 0x0001 : 0);
+
+       case USB_REQ_SET_FEATURE:
+               switch (value) {
+               case USB_ENDPOINT_HALT:
+                       status = gr_ep_halt_wedge(ep, 1, 0, 1);
+                       if (status >= 0)
+                               status = gr_ep0_respond_empty(dev);
+                       return status;
+               }
+               break;
+
+       case USB_REQ_CLEAR_FEATURE:
+               switch (value) {
+               case USB_ENDPOINT_HALT:
+                       if (ep->wedged)
+                               return -1;
+                       status = gr_ep_halt_wedge(ep, 0, 0, 1);
+                       if (status >= 0)
+                               status = gr_ep0_respond_empty(dev);
+                       return status;
+               }
+               break;
+       }
+
+       return 1; /* Delegate the rest */
+}
+
+/* Must be called with dev->lock held */
+static void gr_ep0out_requeue(struct gr_udc *dev)
+{
+       int ret = gr_queue_int(&dev->epo[0], dev->ep0reqo, GFP_ATOMIC);
+
+       if (ret)
+               dev_err(dev->dev, "Could not queue ep0out setup request: %d\n",
+                       ret);
+}
+
+/*
+ * The main function dealing with setup requests on ep0.
+ *
+ * Must be called with dev->lock held and irqs disabled
+ */
+static void gr_ep0_setup(struct gr_udc *dev, struct gr_request *req)
+       __releases(&dev->lock)
+       __acquires(&dev->lock)
+{
+       union {
+               struct usb_ctrlrequest ctrl;
+               u8 raw[8];
+               u32 word[2];
+       } u;
+       u8 type;
+       u8 request;
+       u16 value;
+       u16 index;
+       u16 length;
+       int i;
+       int status;
+
+       /* Restore from ep0 halt */
+       if (dev->ep0state == GR_EP0_STALL) {
+               gr_set_ep0state(dev, GR_EP0_SETUP);
+               if (!req->req.actual)
+                       goto out;
+       }
+
+       if (dev->ep0state == GR_EP0_ISTATUS) {
+               gr_set_ep0state(dev, GR_EP0_SETUP);
+               if (req->req.actual > 0)
+                       dev_dbg(dev->dev,
+                               "Unexpected setup packet at state %s\n",
+                               gr_ep0state_string(GR_EP0_ISTATUS));
+               else
+                       goto out; /* Got expected ZLP */
+       } else if (dev->ep0state != GR_EP0_SETUP) {
+               dev_info(dev->dev,
+                        "Unexpected ep0out request at state %s - stalling\n",
+                        gr_ep0state_string(dev->ep0state));
+               gr_control_stall(dev);
+               gr_set_ep0state(dev, GR_EP0_SETUP);
+               goto out;
+       } else if (!req->req.actual) {
+               dev_dbg(dev->dev, "Unexpected ZLP at state %s\n",
+                       gr_ep0state_string(dev->ep0state));
+               goto out;
+       }
+
+       /* Handle SETUP packet */
+       for (i = 0; i < req->req.actual; i++)
+               u.raw[i] = ((u8 *)req->req.buf)[i];
+
+       type = u.ctrl.bRequestType;
+       request = u.ctrl.bRequest;
+       value = le16_to_cpu(u.ctrl.wValue);
+       index = le16_to_cpu(u.ctrl.wIndex);
+       length = le16_to_cpu(u.ctrl.wLength);
+
+       gr_dbgprint_devreq(dev, type, request, value, index, length);
+
+       /* Check for data stage */
+       if (length) {
+               if (type & USB_DIR_IN)
+                       gr_set_ep0state(dev, GR_EP0_IDATA);
+               else
+                       gr_set_ep0state(dev, GR_EP0_ODATA);
+       }
+
+       status = 1; /* Positive status flags delegation */
+       if ((type & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+               switch (type & USB_RECIP_MASK) {
+               case USB_RECIP_DEVICE:
+                       status = gr_device_request(dev, type, request,
+                                                  value, index);
+                       break;
+               case USB_RECIP_ENDPOINT:
+                       status =  gr_endpoint_request(dev, type, request,
+                                                     value, index);
+                       break;
+               case USB_RECIP_INTERFACE:
+                       status = gr_interface_request(dev, type, request,
+                                                     value, index);
+                       break;
+               }
+       }
+
+       if (status > 0) {
+               spin_unlock(&dev->lock);
+
+               dev_vdbg(dev->dev, "DELEGATE\n");
+               status = dev->driver->setup(&dev->gadget, &u.ctrl);
+
+               spin_lock(&dev->lock);
+       }
+
+       /* Generate STALL on both ep0out and ep0in if requested */
+       if (unlikely(status < 0)) {
+               dev_vdbg(dev->dev, "STALL\n");
+               gr_control_stall(dev);
+       }
+
+       if ((type & USB_TYPE_MASK) == USB_TYPE_STANDARD &&
+           request == USB_REQ_SET_CONFIGURATION) {
+               if (!value) {
+                       dev_dbg(dev->dev, "STATUS: deconfigured\n");
+                       usb_gadget_set_state(&dev->gadget, USB_STATE_ADDRESS);
+               } else if (status >= 0) {
+                       /* Not configured unless gadget OK:s it */
+                       dev_dbg(dev->dev, "STATUS: configured: %d\n", value);
+                       usb_gadget_set_state(&dev->gadget,
+                                            USB_STATE_CONFIGURED);
+               }
+       }
+
+       /* Get ready for next stage */
+       if (dev->ep0state == GR_EP0_ODATA)
+               gr_set_ep0state(dev, GR_EP0_OSTATUS);
+       else if (dev->ep0state == GR_EP0_IDATA)
+               gr_set_ep0state(dev, GR_EP0_ISTATUS);
+       else
+               gr_set_ep0state(dev, GR_EP0_SETUP);
+
+out:
+       gr_ep0out_requeue(dev);
+}
+
+/* ---------------------------------------------------------------------- */
+/* VBUS and USB reset handling */
+
+/* Must be called with dev->lock held and irqs disabled  */
+static void gr_vbus_connected(struct gr_udc *dev, u32 status)
+{
+       u32 control;
+
+       dev->gadget.speed = GR_SPEED(status);
+       usb_gadget_set_state(&dev->gadget, USB_STATE_POWERED);
+
+       /* Turn on full interrupts and pullup */
+       control = (GR_CONTROL_SI | GR_CONTROL_UI | GR_CONTROL_VI |
+                  GR_CONTROL_SP | GR_CONTROL_EP);
+       gr_write32(&dev->regs->control, control);
+}
+
+/* Must be called with dev->lock held */
+static void gr_enable_vbus_detect(struct gr_udc *dev)
+{
+       u32 status;
+
+       dev->irq_enabled = 1;
+       wmb(); /* Make sure we do not ignore an interrupt */
+       gr_write32(&dev->regs->control, GR_CONTROL_VI);
+
+       /* Take care of the case we are already plugged in at this point */
+       status = gr_read32(&dev->regs->status);
+       if (status & GR_STATUS_VB)
+               gr_vbus_connected(dev, status);
+}
+
+/* Must be called with dev->lock held and irqs disabled */
+static void gr_vbus_disconnected(struct gr_udc *dev)
+{
+       gr_stop_activity(dev);
+
+       /* Report disconnect */
+       if (dev->driver && dev->driver->disconnect) {
+               spin_unlock(&dev->lock);
+
+               dev->driver->disconnect(&dev->gadget);
+
+               spin_lock(&dev->lock);
+       }
+
+       gr_enable_vbus_detect(dev);
+}
+
+/* Must be called with dev->lock held and irqs disabled */
+static void gr_udc_usbreset(struct gr_udc *dev, u32 status)
+{
+       gr_set_address(dev, 0);
+       gr_set_ep0state(dev, GR_EP0_SETUP);
+       usb_gadget_set_state(&dev->gadget, USB_STATE_DEFAULT);
+       dev->gadget.speed = GR_SPEED(status);
+
+       gr_ep_nuke(&dev->epo[0]);
+       gr_ep_nuke(&dev->epi[0]);
+       dev->epo[0].stopped = 0;
+       dev->epi[0].stopped = 0;
+       gr_ep0out_requeue(dev);
+}
+
+/* ---------------------------------------------------------------------- */
+/* Irq handling */
+
+/*
+ * Handles interrupts from in endpoints. Returns whether something was handled.
+ *
+ * Must be called with dev->lock held, irqs disabled and with !ep->stopped.
+ */
+static int gr_handle_in_ep(struct gr_ep *ep)
+{
+       struct gr_request *req;
+
+       req = list_first_entry(&ep->queue, struct gr_request, queue);
+       if (!req->last_desc)
+               return 0;
+
+       if (ACCESS_ONCE(req->last_desc->ctrl) & GR_DESC_IN_CTRL_EN)
+               return 0; /* Not put in hardware buffers yet */
+
+       if (gr_read32(&ep->regs->epstat) & (GR_EPSTAT_B1 | GR_EPSTAT_B0))
+               return 0; /* Not transmitted yet, still in hardware buffers */
+
+       /* Write complete */
+       gr_dma_advance(ep, 0);
+
+       return 1;
+}
+
+/*
+ * Handles interrupts from out endpoints. Returns whether something was handled.
+ *
+ * Must be called with dev->lock held, irqs disabled and with !ep->stopped.
+ */
+static int gr_handle_out_ep(struct gr_ep *ep)
+{
+       u32 ep_dmactrl;
+       u32 ctrl;
+       u16 len;
+       struct gr_request *req;
+       struct gr_udc *dev = ep->dev;
+
+       req = list_first_entry(&ep->queue, struct gr_request, queue);
+       if (!req->curr_desc)
+               return 0;
+
+       ctrl = ACCESS_ONCE(req->curr_desc->ctrl);
+       if (ctrl & GR_DESC_OUT_CTRL_EN)
+               return 0; /* Not received yet */
+
+       /* Read complete */
+       len = ctrl & GR_DESC_OUT_CTRL_LEN_MASK;
+       req->req.actual += len;
+       if (ctrl & GR_DESC_OUT_CTRL_SE)
+               req->setup = 1;
+
+       if (len < ep->ep.maxpacket || req->req.actual == req->req.length) {
+               /* Short packet or the expected size - we are done */
+
+               if ((ep == &dev->epo[0]) && (dev->ep0state == GR_EP0_OSTATUS)) {
+                       /*
+                        * Send a status stage ZLP to ack the DATA stage in the
+                        * OUT direction. This needs to be done before
+                        * gr_dma_advance as that can lead to a call to
+                        * ep0_setup that can change dev->ep0state.
+                        */
+                       gr_ep0_respond_empty(dev);
+                       gr_set_ep0state(dev, GR_EP0_SETUP);
+               }
+
+               gr_dma_advance(ep, 0);
+       } else {
+               /* Not done yet. Enable the next descriptor to receive more. */
+               req->curr_desc = req->curr_desc->next_desc;
+               req->curr_desc->ctrl |= GR_DESC_OUT_CTRL_EN;
+
+               ep_dmactrl = gr_read32(&ep->regs->dmactrl);
+               gr_write32(&ep->regs->dmactrl, ep_dmactrl | GR_DMACTRL_DA);
+       }
+
+       return 1;
+}
+
+/*
+ * Handle state changes. Returns whether something was handled.
+ *
+ * Must be called with dev->lock held and irqs disabled.
+ */
+static int gr_handle_state_changes(struct gr_udc *dev)
+{
+       u32 status = gr_read32(&dev->regs->status);
+       int handled = 0;
+       int powstate = !(dev->gadget.state == USB_STATE_NOTATTACHED ||
+                        dev->gadget.state == USB_STATE_ATTACHED);
+
+       /* VBUS valid detected */
+       if (!powstate && (status & GR_STATUS_VB)) {
+               dev_dbg(dev->dev, "STATUS: vbus valid detected\n");
+               gr_vbus_connected(dev, status);
+               handled = 1;
+       }
+
+       /* Disconnect */
+       if (powstate && !(status & GR_STATUS_VB)) {
+               dev_dbg(dev->dev, "STATUS: vbus invalid detected\n");
+               gr_vbus_disconnected(dev);
+               handled = 1;
+       }
+
+       /* USB reset detected */
+       if (status & GR_STATUS_UR) {
+               dev_dbg(dev->dev, "STATUS: USB reset - speed is %s\n",
+                       GR_SPEED_STR(status));
+               gr_write32(&dev->regs->status, GR_STATUS_UR);
+               gr_udc_usbreset(dev, status);
+               handled = 1;
+       }
+
+       /* Speed change */
+       if (dev->gadget.speed != GR_SPEED(status)) {
+               dev_dbg(dev->dev, "STATUS: USB Speed change to %s\n",
+                       GR_SPEED_STR(status));
+               dev->gadget.speed = GR_SPEED(status);
+               handled = 1;
+       }
+
+       /* Going into suspend */
+       if ((dev->ep0state != GR_EP0_SUSPEND) && !(status & GR_STATUS_SU)) {
+               dev_dbg(dev->dev, "STATUS: USB suspend\n");
+               gr_set_ep0state(dev, GR_EP0_SUSPEND);
+               dev->suspended_from = dev->gadget.state;
+               usb_gadget_set_state(&dev->gadget, USB_STATE_SUSPENDED);
+
+               if ((dev->gadget.speed != USB_SPEED_UNKNOWN) &&
+                   dev->driver && dev->driver->suspend) {
+                       spin_unlock(&dev->lock);
+
+                       dev->driver->suspend(&dev->gadget);
+
+                       spin_lock(&dev->lock);
+               }
+               handled = 1;
+       }
+
+       /* Coming out of suspend */
+       if ((dev->ep0state == GR_EP0_SUSPEND) && (status & GR_STATUS_SU)) {
+               dev_dbg(dev->dev, "STATUS: USB resume\n");
+               if (dev->suspended_from == USB_STATE_POWERED)
+                       gr_set_ep0state(dev, GR_EP0_DISCONNECT);
+               else
+                       gr_set_ep0state(dev, GR_EP0_SETUP);
+               usb_gadget_set_state(&dev->gadget, dev->suspended_from);
+
+               if ((dev->gadget.speed != USB_SPEED_UNKNOWN) &&
+                   dev->driver && dev->driver->resume) {
+                       spin_unlock(&dev->lock);
+
+                       dev->driver->resume(&dev->gadget);
+
+                       spin_lock(&dev->lock);
+               }
+               handled = 1;
+       }
+
+       return handled;
+}
+
+/* Non-interrupt context irq handler */
+static irqreturn_t gr_irq_handler(int irq, void *_dev)
+{
+       struct gr_udc *dev = _dev;
+       struct gr_ep *ep;
+       int handled = 0;
+       int i;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       if (!dev->irq_enabled)
+               goto out;
+
+       /*
+        * Check IN ep interrupts. We check these before the OUT eps because
+        * some gadgets reuse the request that might already be currently
+        * outstanding and needs to be completed (mainly setup requests).
+        */
+       for (i = 0; i < dev->nepi; i++) {
+               ep = &dev->epi[i];
+               if (!ep->stopped && !ep->callback && !list_empty(&ep->queue))
+                       handled = gr_handle_in_ep(ep) || handled;
+       }
+
+       /* Check OUT ep interrupts */
+       for (i = 0; i < dev->nepo; i++) {
+               ep = &dev->epo[i];
+               if (!ep->stopped && !ep->callback && !list_empty(&ep->queue))
+                       handled = gr_handle_out_ep(ep) || handled;
+       }
+
+       /* Check status interrupts */
+       handled = gr_handle_state_changes(dev) || handled;
+
+       /*
+        * Check AMBA DMA errors. Only check if we didn't find anything else to
+        * handle because this shouldn't happen if we did everything right.
+        */
+       if (!handled) {
+               list_for_each_entry(ep, &dev->ep_list, ep_list) {
+                       if (gr_read32(&ep->regs->dmactrl) & GR_DMACTRL_AE) {
+                               dev_err(dev->dev,
+                                       "AMBA Error occurred for %s\n",
+                                       ep->ep.name);
+                               handled = 1;
+                       }
+               }
+       }
+
+out:
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+/* Interrupt context irq handler */
+static irqreturn_t gr_irq(int irq, void *_dev)
+{
+       struct gr_udc *dev = _dev;
+
+       if (!dev->irq_enabled)
+               return IRQ_NONE;
+
+       return IRQ_WAKE_THREAD;
+}
+
+/* ---------------------------------------------------------------------- */
+/* USB ep ops */
+
+/* Enable endpoint. Not for ep0in and ep0out that are handled separately. */
+static int gr_ep_enable(struct usb_ep *_ep,
+                       const struct usb_endpoint_descriptor *desc)
+{
+       struct gr_udc *dev;
+       struct gr_ep *ep;
+       u8 mode;
+       u8 nt;
+       u16 max;
+       u16 buffer_size = 0;
+       u32 epctrl;
+
+       ep = container_of(_ep, struct gr_ep, ep);
+       if (!_ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT)
+               return -EINVAL;
+
+       dev = ep->dev;
+
+       /* 'ep0' IN and OUT are reserved */
+       if (ep == &dev->epo[0] || ep == &dev->epi[0])
+               return -EINVAL;
+
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       /* Make sure we are clear for enabling */
+       epctrl = gr_read32(&ep->regs->epctrl);
+       if (epctrl & GR_EPCTRL_EV)
+               return -EBUSY;
+
+       /* Check that directions match */
+       if (!ep->is_in != !usb_endpoint_dir_in(desc))
+               return -EINVAL;
+
+       /* Check ep num */
+       if ((!ep->is_in && ep->num >= dev->nepo) ||
+           (ep->is_in && ep->num >= dev->nepi))
+               return -EINVAL;
+
+       if (usb_endpoint_xfer_control(desc)) {
+               mode = 0;
+       } else if (usb_endpoint_xfer_isoc(desc)) {
+               mode = 1;
+       } else if (usb_endpoint_xfer_bulk(desc)) {
+               mode = 2;
+       } else if (usb_endpoint_xfer_int(desc)) {
+               mode = 3;
+       } else {
+               dev_err(dev->dev, "Unknown transfer type for %s\n",
+                       ep->ep.name);
+               return -EINVAL;
+       }
+
+       /*
+        * Bits 10-0 set the max payload. 12-11 set the number of
+        * additional transactions.
+        */
+       max = 0x7ff & usb_endpoint_maxp(desc);
+       nt = 0x3 & (usb_endpoint_maxp(desc) >> 11);
+       buffer_size = GR_BUFFER_SIZE(epctrl);
+       if (nt && (mode == 0 || mode == 2)) {
+               dev_err(dev->dev,
+                       "%s mode: multiple trans./microframe not valid\n",
+                       (mode == 2 ? "Bulk" : "Control"));
+               return -EINVAL;
+       } else if (nt == 0x11) {
+               dev_err(dev->dev, "Invalid value for trans./microframe\n");
+               return -EINVAL;
+       } else if ((nt + 1) * max > buffer_size) {
+               dev_err(dev->dev, "Hw buffer size %d < max payload %d * %d\n",
+                       buffer_size, (nt + 1), max);
+               return -EINVAL;
+       } else if (max == 0) {
+               dev_err(dev->dev, "Max payload cannot be set to 0\n");
+               return -EINVAL;
+       } else if (max > ep->ep.maxpacket_limit) {
+               dev_err(dev->dev, "Requested max payload %d > limit %d\n",
+                       max, ep->ep.maxpacket_limit);
+               return -EINVAL;
+       }
+
+       spin_lock(&ep->dev->lock);
+
+       if (!ep->stopped) {
+               spin_unlock(&ep->dev->lock);
+               return -EBUSY;
+       }
+
+       ep->stopped = 0;
+       ep->wedged = 0;
+       ep->ep.desc = desc;
+       ep->ep.maxpacket = max;
+       ep->dma_start = 0;
+
+
+       if (nt) {
+               /*
+                * Maximum possible size of all payloads in one microframe
+                * regardless of direction when using high-bandwidth mode.
+                */
+               ep->bytes_per_buffer = (nt + 1) * max;
+       } else if (ep->is_in) {
+               /*
+                * The biggest multiple of maximum packet size that fits into
+                * the buffer. The hardware will split up into many packets in
+                * the IN direction.
+                */
+               ep->bytes_per_buffer = (buffer_size / max) * max;
+       } else {
+               /*
+                * Only single packets will be placed the buffers in the OUT
+                * direction.
+                */
+               ep->bytes_per_buffer = max;
+       }
+
+       epctrl = (max << GR_EPCTRL_MAXPL_POS)
+               | (nt << GR_EPCTRL_NT_POS)
+               | (mode << GR_EPCTRL_TT_POS)
+               | GR_EPCTRL_EV;
+       if (ep->is_in)
+               epctrl |= GR_EPCTRL_PI;
+       gr_write32(&ep->regs->epctrl, epctrl);
+
+       gr_write32(&ep->regs->dmactrl, GR_DMACTRL_IE | GR_DMACTRL_AI);
+
+       spin_unlock(&ep->dev->lock);
+
+       dev_dbg(ep->dev->dev, "EP: %s enabled - %s with %d bytes/buffer\n",
+               ep->ep.name, gr_modestring[mode], ep->bytes_per_buffer);
+       return 0;
+}
+
+/* Disable endpoint. Not for ep0in and ep0out that are handled separately. */
+static int gr_ep_disable(struct usb_ep *_ep)
+{
+       struct gr_ep *ep;
+       struct gr_udc *dev;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct gr_ep, ep);
+       if (!_ep || !ep->ep.desc)
+               return -ENODEV;
+
+       dev = ep->dev;
+
+       /* 'ep0' IN and OUT are reserved */
+       if (ep == &dev->epo[0] || ep == &dev->epi[0])
+               return -EINVAL;
+
+       if (dev->ep0state == GR_EP0_SUSPEND)
+               return -EBUSY;
+
+       dev_dbg(ep->dev->dev, "EP: disable %s\n", ep->ep.name);
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       gr_ep_nuke(ep);
+       gr_ep_reset(ep);
+       ep->ep.desc = NULL;
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return 0;
+}
+
+/*
+ * Frees a request, but not any DMA buffers associated with it
+ * (gr_finish_request should already have taken care of that).
+ */
+static void gr_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct gr_request *req;
+
+       if (!_ep || !_req)
+               return;
+       req = container_of(_req, struct gr_request, req);
+
+       /* Leads to memory leak */
+       WARN(!list_empty(&req->queue),
+            "request not dequeued properly before freeing\n");
+
+       kfree(req);
+}
+
+/* Queue a request from the gadget */
+static int gr_queue_ext(struct usb_ep *_ep, struct usb_request *_req,
+                       gfp_t gfp_flags)
+{
+       struct gr_ep *ep;
+       struct gr_request *req;
+       struct gr_udc *dev;
+       int ret;
+
+       if (unlikely(!_ep || !_req))
+               return -EINVAL;
+
+       ep = container_of(_ep, struct gr_ep, ep);
+       req = container_of(_req, struct gr_request, req);
+       dev = ep->dev;
+
+       spin_lock(&ep->dev->lock);
+
+       /*
+        * The ep0 pointer in the gadget struct is used both for ep0in and
+        * ep0out. In a data stage in the out direction ep0out needs to be used
+        * instead of the default ep0in. Completion functions might use
+        * driver_data, so that needs to be copied as well.
+        */
+       if ((ep == &dev->epi[0]) && (dev->ep0state == GR_EP0_ODATA)) {
+               ep = &dev->epo[0];
+               ep->ep.driver_data = dev->epi[0].ep.driver_data;
+       }
+
+       if (ep->is_in)
+               gr_dbgprint_request("EXTERN", ep, req);
+
+       ret = gr_queue(ep, req, GFP_ATOMIC);
+
+       spin_unlock(&ep->dev->lock);
+
+       return ret;
+}
+
+/* Dequeue JUST ONE request */
+static int gr_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct gr_request *req;
+       struct gr_ep *ep;
+       struct gr_udc *dev;
+       int ret = 0;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct gr_ep, ep);
+       if (!_ep || !_req || (!ep->ep.desc && ep->num != 0))
+               return -EINVAL;
+       dev = ep->dev;
+       if (!dev->driver)
+               return -ESHUTDOWN;
+
+       /* We can't touch (DMA) registers when suspended */
+       if (dev->ep0state == GR_EP0_SUSPEND)
+               return -EBUSY;
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       /* Make sure it's actually queued on this endpoint */
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (list_first_entry(&ep->queue, struct gr_request, queue) == req) {
+               /* This request is currently being processed */
+               gr_abort_dma(ep);
+               if (ep->stopped)
+                       gr_finish_request(ep, req, -ECONNRESET);
+               else
+                       gr_dma_advance(ep, -ECONNRESET);
+       } else if (!list_empty(&req->queue)) {
+               /* Not being processed - gr_finish_request dequeues it */
+               gr_finish_request(ep, req, -ECONNRESET);
+       } else {
+               ret = -EOPNOTSUPP;
+       }
+
+out:
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return ret;
+}
+
+/* Helper for gr_set_halt and gr_set_wedge */
+static int gr_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge)
+{
+       int ret;
+       struct gr_ep *ep;
+
+       if (!_ep)
+               return -ENODEV;
+       ep = container_of(_ep, struct gr_ep, ep);
+
+       spin_lock(&ep->dev->lock);
+
+       /* Halting an IN endpoint should fail if queue is not empty */
+       if (halt && ep->is_in && !list_empty(&ep->queue)) {
+               ret = -EAGAIN;
+               goto out;
+       }
+
+       ret = gr_ep_halt_wedge(ep, halt, wedge, 0);
+
+out:
+       spin_unlock(&ep->dev->lock);
+
+       return ret;
+}
+
+/* Halt endpoint */
+static int gr_set_halt(struct usb_ep *_ep, int halt)
+{
+       return gr_set_halt_wedge(_ep, halt, 0);
+}
+
+/* Halt and wedge endpoint */
+static int gr_set_wedge(struct usb_ep *_ep)
+{
+       return gr_set_halt_wedge(_ep, 1, 1);
+}
+
+/*
+ * Return the total number of bytes currently stored in the internal buffers of
+ * the endpoint.
+ */
+static int gr_fifo_status(struct usb_ep *_ep)
+{
+       struct gr_ep *ep;
+       u32 epstat;
+       u32 bytes = 0;
+
+       if (!_ep)
+               return -ENODEV;
+       ep = container_of(_ep, struct gr_ep, ep);
+
+       epstat = gr_read32(&ep->regs->epstat);
+
+       if (epstat & GR_EPSTAT_B0)
+               bytes += (epstat & GR_EPSTAT_B0CNT_MASK) >> GR_EPSTAT_B0CNT_POS;
+       if (epstat & GR_EPSTAT_B1)
+               bytes += (epstat & GR_EPSTAT_B1CNT_MASK) >> GR_EPSTAT_B1CNT_POS;
+
+       return bytes;
+}
+
+
+/* Empty data from internal buffers of an endpoint. */
+static void gr_fifo_flush(struct usb_ep *_ep)
+{
+       struct gr_ep *ep;
+       u32 epctrl;
+
+       if (!_ep)
+               return;
+       ep = container_of(_ep, struct gr_ep, ep);
+       dev_vdbg(ep->dev->dev, "EP: flush fifo %s\n", ep->ep.name);
+
+       spin_lock(&ep->dev->lock);
+
+       epctrl = gr_read32(&ep->regs->epctrl);
+       epctrl |= GR_EPCTRL_CB;
+       gr_write32(&ep->regs->epctrl, epctrl);
+
+       spin_unlock(&ep->dev->lock);
+}
+
+static struct usb_ep_ops gr_ep_ops = {
+       .enable         = gr_ep_enable,
+       .disable        = gr_ep_disable,
+
+       .alloc_request  = gr_alloc_request,
+       .free_request   = gr_free_request,
+
+       .queue          = gr_queue_ext,
+       .dequeue        = gr_dequeue,
+
+       .set_halt       = gr_set_halt,
+       .set_wedge      = gr_set_wedge,
+       .fifo_status    = gr_fifo_status,
+       .fifo_flush     = gr_fifo_flush,
+};
+
+/* ---------------------------------------------------------------------- */
+/* USB Gadget ops */
+
+static int gr_get_frame(struct usb_gadget *_gadget)
+{
+       struct gr_udc *dev;
+
+       if (!_gadget)
+               return -ENODEV;
+       dev = container_of(_gadget, struct gr_udc, gadget);
+       return gr_read32(&dev->regs->status) & GR_STATUS_FN_MASK;
+}
+
+static int gr_wakeup(struct usb_gadget *_gadget)
+{
+       struct gr_udc *dev;
+
+       if (!_gadget)
+               return -ENODEV;
+       dev = container_of(_gadget, struct gr_udc, gadget);
+
+       /* Remote wakeup feature not enabled by host*/
+       if (!dev->remote_wakeup)
+               return -EINVAL;
+
+       spin_lock(&dev->lock);
+
+       gr_write32(&dev->regs->control,
+                  gr_read32(&dev->regs->control) | GR_CONTROL_RW);
+
+       spin_unlock(&dev->lock);
+
+       return 0;
+}
+
+static int gr_pullup(struct usb_gadget *_gadget, int is_on)
+{
+       struct gr_udc *dev;
+       u32 control;
+
+       if (!_gadget)
+               return -ENODEV;
+       dev = container_of(_gadget, struct gr_udc, gadget);
+
+       spin_lock(&dev->lock);
+
+       control = gr_read32(&dev->regs->control);
+       if (is_on)
+               control |= GR_CONTROL_EP;
+       else
+               control &= ~GR_CONTROL_EP;
+       gr_write32(&dev->regs->control, control);
+
+       spin_unlock(&dev->lock);
+
+       return 0;
+}
+
+static int gr_udc_start(struct usb_gadget *gadget,
+                       struct usb_gadget_driver *driver)
+{
+       struct gr_udc *dev = to_gr_udc(gadget);
+
+       spin_lock(&dev->lock);
+
+       /* Hook up the driver */
+       driver->driver.bus = NULL;
+       dev->driver = driver;
+
+       /* Get ready for host detection */
+       gr_enable_vbus_detect(dev);
+
+       spin_unlock(&dev->lock);
+
+       dev_info(dev->dev, "Started with gadget driver '%s'\n",
+                driver->driver.name);
+
+       return 0;
+}
+
+static int gr_udc_stop(struct usb_gadget *gadget,
+                      struct usb_gadget_driver *driver)
+{
+       struct gr_udc *dev = to_gr_udc(gadget);
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       dev->driver = NULL;
+       gr_stop_activity(dev);
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       dev_info(dev->dev, "Stopped\n");
+
+       return 0;
+}
+
+static const struct usb_gadget_ops gr_ops = {
+       .get_frame      = gr_get_frame,
+       .wakeup         = gr_wakeup,
+       .pullup         = gr_pullup,
+       .udc_start      = gr_udc_start,
+       .udc_stop       = gr_udc_stop,
+       /* Other operations not supported */
+};
+
+/* ---------------------------------------------------------------------- */
+/* Module probe, removal and of-matching */
+
+static const char * const onames[] = {
+       "ep0out", "ep1out", "ep2out", "ep3out", "ep4out", "ep5out",
+       "ep6out", "ep7out", "ep8out", "ep9out", "ep10out", "ep11out",
+       "ep12out", "ep13out", "ep14out", "ep15out"
+};
+
+static const char * const inames[] = {
+       "ep0in", "ep1in", "ep2in", "ep3in", "ep4in", "ep5in",
+       "ep6in", "ep7in", "ep8in", "ep9in", "ep10in", "ep11in",
+       "ep12in", "ep13in", "ep14in", "ep15in"
+};
+
+/* Must be called with dev->lock held */
+static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit)
+{
+       struct gr_ep *ep;
+       struct gr_request *req;
+       struct usb_request *_req;
+       void *buf;
+
+       if (is_in) {
+               ep = &dev->epi[num];
+               ep->ep.name = inames[num];
+               ep->regs = &dev->regs->epi[num];
+       } else {
+               ep = &dev->epo[num];
+               ep->ep.name = onames[num];
+               ep->regs = &dev->regs->epo[num];
+       }
+
+       gr_ep_reset(ep);
+       ep->num = num;
+       ep->is_in = is_in;
+       ep->dev = dev;
+       ep->ep.ops = &gr_ep_ops;
+       INIT_LIST_HEAD(&ep->queue);
+
+       if (num == 0) {
+               _req = gr_alloc_request(&ep->ep, GFP_ATOMIC);
+               buf = devm_kzalloc(dev->dev, PAGE_SIZE, GFP_DMA | GFP_ATOMIC);
+               if (!_req || !buf) {
+                       /* possible _req freed by gr_probe via gr_remove */
+                       return -ENOMEM;
+               }
+
+               req = container_of(_req, struct gr_request, req);
+               req->req.buf = buf;
+               req->req.length = MAX_CTRL_PL_SIZE;
+
+               if (is_in)
+                       dev->ep0reqi = req; /* Complete gets set as used */
+               else
+                       dev->ep0reqo = req; /* Completion treated separately */
+
+               usb_ep_set_maxpacket_limit(&ep->ep, MAX_CTRL_PL_SIZE);
+               ep->bytes_per_buffer = MAX_CTRL_PL_SIZE;
+       } else {
+               usb_ep_set_maxpacket_limit(&ep->ep, (u16)maxplimit);
+               list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+       }
+       list_add_tail(&ep->ep_list, &dev->ep_list);
+
+       return 0;
+}
+
+/* Must be called with dev->lock held */
+static int gr_udc_init(struct gr_udc *dev)
+{
+       struct device_node *np = dev->dev->of_node;
+       u32 epctrl_val;
+       u32 dmactrl_val;
+       int i;
+       int ret = 0;
+       u32 bufsize;
+
+       gr_set_address(dev, 0);
+
+       INIT_LIST_HEAD(&dev->gadget.ep_list);
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+       dev->gadget.ep0 = &dev->epi[0].ep;
+
+       INIT_LIST_HEAD(&dev->ep_list);
+       gr_set_ep0state(dev, GR_EP0_DISCONNECT);
+
+       for (i = 0; i < dev->nepo; i++) {
+               if (of_property_read_u32_index(np, "epobufsizes", i, &bufsize))
+                       bufsize = 1024;
+               ret = gr_ep_init(dev, i, 0, bufsize);
+               if (ret)
+                       return ret;
+       }
+
+       for (i = 0; i < dev->nepi; i++) {
+               if (of_property_read_u32_index(np, "epibufsizes", i, &bufsize))
+                       bufsize = 1024;
+               ret = gr_ep_init(dev, i, 1, bufsize);
+               if (ret)
+                       return ret;
+       }
+
+       /* Must be disabled by default */
+       dev->remote_wakeup = 0;
+
+       /* Enable ep0out and ep0in */
+       epctrl_val = (MAX_CTRL_PL_SIZE << GR_EPCTRL_MAXPL_POS) | GR_EPCTRL_EV;
+       dmactrl_val = GR_DMACTRL_IE | GR_DMACTRL_AI;
+       gr_write32(&dev->epo[0].regs->epctrl, epctrl_val);
+       gr_write32(&dev->epi[0].regs->epctrl, epctrl_val | GR_EPCTRL_PI);
+       gr_write32(&dev->epo[0].regs->dmactrl, dmactrl_val);
+       gr_write32(&dev->epi[0].regs->dmactrl, dmactrl_val);
+
+       return 0;
+}
+
+static int gr_remove(struct platform_device *pdev)
+{
+       struct gr_udc *dev = platform_get_drvdata(pdev);
+
+       if (dev->added)
+               usb_del_gadget_udc(&dev->gadget); /* Shuts everything down */
+       if (dev->driver)
+               return -EBUSY;
+
+       gr_dfs_delete(dev);
+       if (dev->desc_pool)
+               dma_pool_destroy(dev->desc_pool);
+       platform_set_drvdata(pdev, NULL);
+
+       gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req);
+       gr_free_request(&dev->epo[0].ep, &dev->ep0reqo->req);
+
+       return 0;
+}
+static int gr_request_irq(struct gr_udc *dev, int irq)
+{
+       return devm_request_threaded_irq(dev->dev, irq, gr_irq, gr_irq_handler,
+                                        IRQF_SHARED, driver_name, dev);
+}
+
+static int gr_probe(struct platform_device *pdev)
+{
+       struct gr_udc *dev;
+       struct resource *res;
+       struct gr_regs __iomem *regs;
+       int retval;
+       u32 status;
+
+       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+       dev->dev = &pdev->dev;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       regs = devm_ioremap_resource(dev->dev, res);
+       if (IS_ERR(regs))
+               return PTR_ERR(regs);
+
+       dev->irq = platform_get_irq(pdev, 0);
+       if (dev->irq <= 0) {
+               dev_err(dev->dev, "No irq found\n");
+               return -ENODEV;
+       }
+
+       /* Some core configurations has separate irqs for IN and OUT events */
+       dev->irqi = platform_get_irq(pdev, 1);
+       if (dev->irqi > 0) {
+               dev->irqo = platform_get_irq(pdev, 2);
+               if (dev->irqo <= 0) {
+                       dev_err(dev->dev, "Found irqi but not irqo\n");
+                       return -ENODEV;
+               }
+       } else {
+               dev->irqi = 0;
+       }
+
+       dev->gadget.name = driver_name;
+       dev->gadget.max_speed = USB_SPEED_HIGH;
+       dev->gadget.ops = &gr_ops;
+       dev->gadget.quirk_ep_out_aligned_size = true;
+
+       spin_lock_init(&dev->lock);
+       dev->regs = regs;
+
+       platform_set_drvdata(pdev, dev);
+
+       /* Determine number of endpoints and data interface mode */
+       status = gr_read32(&dev->regs->status);
+       dev->nepi = ((status & GR_STATUS_NEPI_MASK) >> GR_STATUS_NEPI_POS) + 1;
+       dev->nepo = ((status & GR_STATUS_NEPO_MASK) >> GR_STATUS_NEPO_POS) + 1;
+
+       if (!(status & GR_STATUS_DM)) {
+               dev_err(dev->dev, "Slave mode cores are not supported\n");
+               return -ENODEV;
+       }
+
+       /* --- Effects of the following calls might need explicit cleanup --- */
+
+       /* Create DMA pool for descriptors */
+       dev->desc_pool = dma_pool_create("desc_pool", dev->dev,
+                                        sizeof(struct gr_dma_desc), 4, 0);
+       if (!dev->desc_pool) {
+               dev_err(dev->dev, "Could not allocate DMA pool");
+               return -ENOMEM;
+       }
+
+       spin_lock(&dev->lock);
+
+       /* Inside lock so that no gadget can use this udc until probe is done */
+       retval = usb_add_gadget_udc(dev->dev, &dev->gadget);
+       if (retval) {
+               dev_err(dev->dev, "Could not add gadget udc");
+               goto out;
+       }
+       dev->added = 1;
+
+       retval = gr_udc_init(dev);
+       if (retval)
+               goto out;
+
+       gr_dfs_create(dev);
+
+       /* Clear all interrupt enables that might be left on since last boot */
+       gr_disable_interrupts_and_pullup(dev);
+
+       retval = gr_request_irq(dev, dev->irq);
+       if (retval) {
+               dev_err(dev->dev, "Failed to request irq %d\n", dev->irq);
+               goto out;
+       }
+
+       if (dev->irqi) {
+               retval = gr_request_irq(dev, dev->irqi);
+               if (retval) {
+                       dev_err(dev->dev, "Failed to request irqi %d\n",
+                               dev->irqi);
+                       goto out;
+               }
+               retval = gr_request_irq(dev, dev->irqo);
+               if (retval) {
+                       dev_err(dev->dev, "Failed to request irqo %d\n",
+                               dev->irqo);
+                       goto out;
+               }
+       }
+
+       if (dev->irqi)
+               dev_info(dev->dev, "regs: %p, irqs %d, %d, %d\n", dev->regs,
+                        dev->irq, dev->irqi, dev->irqo);
+       else
+               dev_info(dev->dev, "regs: %p, irq %d\n", dev->regs, dev->irq);
+
+out:
+       spin_unlock(&dev->lock);
+
+       if (retval)
+               gr_remove(pdev);
+
+       return retval;
+}
+
+static const struct of_device_id gr_match[] = {
+       {.name = "GAISLER_USBDC"},
+       {.name = "01_021"},
+       {},
+};
+MODULE_DEVICE_TABLE(of, gr_match);
+
+static struct platform_driver gr_driver = {
+       .driver = {
+               .name = DRIVER_NAME,
+               .owner = THIS_MODULE,
+               .of_match_table = gr_match,
+       },
+       .probe = gr_probe,
+       .remove = gr_remove,
+};
+module_platform_driver(gr_driver);
+
+MODULE_AUTHOR("Aeroflex Gaisler AB.");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/udc/gr_udc.h b/drivers/usb/gadget/udc/gr_udc.h
new file mode 100644 (file)
index 0000000..8388897
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * USB Peripheral Controller driver for Aeroflex Gaisler GRUSBDC.
+ *
+ * 2013 (c) Aeroflex Gaisler AB
+ *
+ * This driver supports GRUSBDC USB Device Controller cores available in the
+ * GRLIB VHDL IP core library.
+ *
+ * Full documentation of the GRUSBDC core can be found here:
+ * http://www.gaisler.com/products/grlib/grip.pdf
+ *
+ * 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.
+ *
+ * Contributors:
+ * - Andreas Larsson <andreas@gaisler.com>
+ * - Marko Isomaki
+ */
+
+/* Control registers on the AMBA bus */
+
+#define GR_MAXEP       16      /* Max # endpoints for *each* direction */
+
+struct gr_epregs {
+       u32 epctrl;
+       union {
+               struct { /* Slave mode*/
+                       u32 slvctrl;
+                       u32 slvdata;
+               };
+               struct { /* DMA mode*/
+                       u32 dmactrl;
+                       u32 dmaaddr;
+               };
+       };
+       u32 epstat;
+};
+
+struct gr_regs {
+       struct gr_epregs        epo[GR_MAXEP];  /* 0x000 - 0x0fc */
+       struct gr_epregs        epi[GR_MAXEP];  /* 0x100 - 0x1fc */
+       u32                     control;        /* 0x200 */
+       u32                     status;         /* 0x204 */
+};
+
+#define GR_EPCTRL_BUFSZ_SCALER 8
+#define GR_EPCTRL_BUFSZ_MASK   0xffe00000
+#define GR_EPCTRL_BUFSZ_POS    21
+#define GR_EPCTRL_PI           BIT(20)
+#define GR_EPCTRL_CB           BIT(19)
+#define GR_EPCTRL_CS           BIT(18)
+#define GR_EPCTRL_MAXPL_MASK   0x0003ff80
+#define GR_EPCTRL_MAXPL_POS    7
+#define GR_EPCTRL_NT_MASK      0x00000060
+#define GR_EPCTRL_NT_POS       5
+#define GR_EPCTRL_TT_MASK      0x00000018
+#define GR_EPCTRL_TT_POS       3
+#define GR_EPCTRL_EH           BIT(2)
+#define GR_EPCTRL_ED           BIT(1)
+#define GR_EPCTRL_EV           BIT(0)
+
+#define GR_DMACTRL_AE          BIT(10)
+#define GR_DMACTRL_AD          BIT(3)
+#define GR_DMACTRL_AI          BIT(2)
+#define GR_DMACTRL_IE          BIT(1)
+#define GR_DMACTRL_DA          BIT(0)
+
+#define GR_EPSTAT_PT           BIT(29)
+#define GR_EPSTAT_PR           BIT(29)
+#define GR_EPSTAT_B1CNT_MASK   0x1fff0000
+#define GR_EPSTAT_B1CNT_POS    16
+#define GR_EPSTAT_B0CNT_MASK   0x0000fff8
+#define GR_EPSTAT_B0CNT_POS    3
+#define GR_EPSTAT_B1           BIT(2)
+#define GR_EPSTAT_B0           BIT(1)
+#define GR_EPSTAT_BS           BIT(0)
+
+#define GR_CONTROL_SI          BIT(31)
+#define GR_CONTROL_UI          BIT(30)
+#define GR_CONTROL_VI          BIT(29)
+#define GR_CONTROL_SP          BIT(28)
+#define GR_CONTROL_FI          BIT(27)
+#define GR_CONTROL_EP          BIT(14)
+#define GR_CONTROL_DH          BIT(13)
+#define GR_CONTROL_RW          BIT(12)
+#define GR_CONTROL_TS_MASK     0x00000e00
+#define GR_CONTROL_TS_POS      9
+#define GR_CONTROL_TM          BIT(8)
+#define GR_CONTROL_UA_MASK     0x000000fe
+#define GR_CONTROL_UA_POS      1
+#define GR_CONTROL_SU          BIT(0)
+
+#define GR_STATUS_NEPI_MASK    0xf0000000
+#define GR_STATUS_NEPI_POS     28
+#define GR_STATUS_NEPO_MASK    0x0f000000
+#define GR_STATUS_NEPO_POS     24
+#define GR_STATUS_DM           BIT(23)
+#define GR_STATUS_SU           BIT(17)
+#define GR_STATUS_UR           BIT(16)
+#define GR_STATUS_VB           BIT(15)
+#define GR_STATUS_SP           BIT(14)
+#define GR_STATUS_AF_MASK      0x00003800
+#define GR_STATUS_AF_POS       11
+#define GR_STATUS_FN_MASK      0x000007ff
+#define GR_STATUS_FN_POS       0
+
+
+#define MAX_CTRL_PL_SIZE 64 /* As per USB standard for full and high speed */
+
+/*-------------------------------------------------------------------------*/
+
+/* Driver data structures and utilities */
+
+struct gr_dma_desc {
+       u32 ctrl;
+       u32 data;
+       u32 next;
+
+       /* These must be last because hw uses the previous three */
+       u32 paddr;
+       struct gr_dma_desc *next_desc;
+};
+
+#define GR_DESC_OUT_CTRL_SE            BIT(17)
+#define GR_DESC_OUT_CTRL_IE            BIT(15)
+#define GR_DESC_OUT_CTRL_NX            BIT(14)
+#define GR_DESC_OUT_CTRL_EN            BIT(13)
+#define GR_DESC_OUT_CTRL_LEN_MASK      0x00001fff
+
+#define GR_DESC_IN_CTRL_MO             BIT(18)
+#define GR_DESC_IN_CTRL_PI             BIT(17)
+#define GR_DESC_IN_CTRL_ML             BIT(16)
+#define GR_DESC_IN_CTRL_IE             BIT(15)
+#define GR_DESC_IN_CTRL_NX             BIT(14)
+#define GR_DESC_IN_CTRL_EN             BIT(13)
+#define GR_DESC_IN_CTRL_LEN_MASK       0x00001fff
+
+#define GR_DESC_DMAADDR_MASK           0xfffffffc
+
+struct gr_ep {
+       struct usb_ep ep;
+       struct gr_udc *dev;
+       u16 bytes_per_buffer;
+       unsigned int dma_start;
+       struct gr_epregs __iomem *regs;
+
+       unsigned num:8;
+       unsigned is_in:1;
+       unsigned stopped:1;
+       unsigned wedged:1;
+       unsigned callback:1;
+
+       /* analogous to a host-side qh */
+       struct list_head queue;
+
+       struct list_head ep_list;
+};
+
+struct gr_request {
+       struct usb_request req;
+       struct list_head queue;
+
+       /* Chain of dma descriptors */
+       struct gr_dma_desc *first_desc; /* First in the chain */
+       struct gr_dma_desc *curr_desc; /* Current descriptor */
+       struct gr_dma_desc *last_desc; /* Last in the chain */
+
+       u8 setup; /* Setup packet */
+};
+
+enum gr_ep0state {
+       GR_EP0_DISCONNECT = 0,  /* No host */
+       GR_EP0_SETUP,           /* Between STATUS ack and SETUP report */
+       GR_EP0_IDATA,           /* IN data stage */
+       GR_EP0_ODATA,           /* OUT data stage */
+       GR_EP0_ISTATUS,         /* Status stage after IN data stage */
+       GR_EP0_OSTATUS,         /* Status stage after OUT data stage */
+       GR_EP0_STALL,           /* Data or status stages */
+       GR_EP0_SUSPEND,         /* USB suspend */
+};
+
+struct gr_udc {
+       struct usb_gadget gadget;
+       struct gr_ep epi[GR_MAXEP];
+       struct gr_ep epo[GR_MAXEP];
+       struct usb_gadget_driver *driver;
+       struct dma_pool *desc_pool;
+       struct device *dev;
+
+       enum gr_ep0state ep0state;
+       struct gr_request *ep0reqo;
+       struct gr_request *ep0reqi;
+
+       struct gr_regs __iomem *regs;
+       int irq;
+       int irqi;
+       int irqo;
+
+       unsigned added:1;
+       unsigned irq_enabled:1;
+       unsigned remote_wakeup:1;
+
+       u8 test_mode;
+
+       enum usb_device_state suspended_from;
+
+       unsigned int nepi;
+       unsigned int nepo;
+
+       struct list_head ep_list;
+
+       spinlock_t lock; /* General lock, a.k.a. "dev->lock" in comments */
+
+       struct dentry *dfs_root;
+       struct dentry *dfs_state;
+};
+
+#define to_gr_udc(gadget)      (container_of((gadget), struct gr_udc, gadget))
diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
new file mode 100644 (file)
index 0000000..1629ad7
--- /dev/null
@@ -0,0 +1,3424 @@
+/*
+ * USB Gadget driver for LPC32xx
+ *
+ * Authors:
+ *    Kevin Wells <kevin.wells@nxp.com>
+ *    Mike James
+ *    Roland Stigge <stigge@antcom.de>
+ *
+ * Copyright (C) 2006 Philips Semiconductors
+ * Copyright (C) 2009 NXP Semiconductors
+ * Copyright (C) 2012 Roland Stigge
+ *
+ * Note: This driver is based on original work done by Mike James for
+ *       the LPC3180.
+ *
+ * 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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/clk.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/i2c.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/workqueue.h>
+#include <linux/of.h>
+#include <linux/usb/isp1301.h>
+
+#include <asm/byteorder.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+
+#include <mach/platform.h>
+#include <mach/irqs.h>
+#include <mach/board.h>
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#endif
+
+/*
+ * USB device configuration structure
+ */
+typedef void (*usc_chg_event)(int);
+struct lpc32xx_usbd_cfg {
+       int vbus_drv_pol;   /* 0=active low drive for VBUS via ISP1301 */
+       usc_chg_event conn_chgb; /* Connection change event (optional) */
+       usc_chg_event susp_chgb; /* Suspend/resume event (optional) */
+       usc_chg_event rmwk_chgb; /* Enable/disable remote wakeup */
+};
+
+/*
+ * controller driver data structures
+ */
+
+/* 16 endpoints (not to be confused with 32 hardware endpoints) */
+#define        NUM_ENDPOINTS   16
+
+/*
+ * IRQ indices make reading the code a little easier
+ */
+#define IRQ_USB_LP     0
+#define IRQ_USB_HP     1
+#define IRQ_USB_DEVDMA 2
+#define IRQ_USB_ATX    3
+
+#define EP_OUT 0 /* RX (from host) */
+#define EP_IN 1 /* TX (to host) */
+
+/* Returns the interrupt mask for the selected hardware endpoint */
+#define EP_MASK_SEL(ep, dir) (1 << (((ep) * 2) + dir))
+
+#define EP_INT_TYPE 0
+#define EP_ISO_TYPE 1
+#define EP_BLK_TYPE 2
+#define EP_CTL_TYPE 3
+
+/* EP0 states */
+#define WAIT_FOR_SETUP 0 /* Wait for setup packet */
+#define DATA_IN        1 /* Expect dev->host transfer */
+#define DATA_OUT       2 /* Expect host->dev transfer */
+
+/* DD (DMA Descriptor) structure, requires word alignment, this is already
+ * defined in the LPC32XX USB device header file, but this version is slightly
+ * modified to tag some work data with each DMA descriptor. */
+struct lpc32xx_usbd_dd_gad {
+       u32 dd_next_phy;
+       u32 dd_setup;
+       u32 dd_buffer_addr;
+       u32 dd_status;
+       u32 dd_iso_ps_mem_addr;
+       u32 this_dma;
+       u32 iso_status[6]; /* 5 spare */
+       u32 dd_next_v;
+};
+
+/*
+ * Logical endpoint structure
+ */
+struct lpc32xx_ep {
+       struct usb_ep           ep;
+       struct list_head        queue;
+       struct lpc32xx_udc      *udc;
+
+       u32                     hwep_num_base; /* Physical hardware EP */
+       u32                     hwep_num; /* Maps to hardware endpoint */
+       u32                     maxpacket;
+       u32                     lep;
+
+       bool                    is_in;
+       bool                    req_pending;
+       u32                     eptype;
+
+       u32                     totalints;
+
+       bool                    wedge;
+};
+
+/*
+ * Common UDC structure
+ */
+struct lpc32xx_udc {
+       struct usb_gadget       gadget;
+       struct usb_gadget_driver *driver;
+       struct platform_device  *pdev;
+       struct device           *dev;
+       struct dentry           *pde;
+       spinlock_t              lock;
+       struct i2c_client       *isp1301_i2c_client;
+
+       /* Board and device specific */
+       struct lpc32xx_usbd_cfg *board;
+       u32                     io_p_start;
+       u32                     io_p_size;
+       void __iomem            *udp_baseaddr;
+       int                     udp_irq[4];
+       struct clk              *usb_pll_clk;
+       struct clk              *usb_slv_clk;
+       struct clk              *usb_otg_clk;
+
+       /* DMA support */
+       u32                     *udca_v_base;
+       u32                     udca_p_base;
+       struct dma_pool         *dd_cache;
+
+       /* Common EP and control data */
+       u32                     enabled_devints;
+       u32                     enabled_hwepints;
+       u32                     dev_status;
+       u32                     realized_eps;
+
+       /* VBUS detection, pullup, and power flags */
+       u8                      vbus;
+       u8                      last_vbus;
+       int                     pullup;
+       int                     poweron;
+
+       /* Work queues related to I2C support */
+       struct work_struct      pullup_job;
+       struct work_struct      vbus_job;
+       struct work_struct      power_job;
+
+       /* USB device peripheral - various */
+       struct lpc32xx_ep       ep[NUM_ENDPOINTS];
+       bool                    enabled;
+       bool                    clocked;
+       bool                    suspended;
+       bool                    selfpowered;
+       int                     ep0state;
+       atomic_t                enabled_ep_cnt;
+       wait_queue_head_t       ep_disable_wait_queue;
+};
+
+/*
+ * Endpoint request
+ */
+struct lpc32xx_request {
+       struct usb_request      req;
+       struct list_head        queue;
+       struct lpc32xx_usbd_dd_gad *dd_desc_ptr;
+       bool                    mapped;
+       bool                    send_zlp;
+};
+
+static inline struct lpc32xx_udc *to_udc(struct usb_gadget *g)
+{
+       return container_of(g, struct lpc32xx_udc, gadget);
+}
+
+#define ep_dbg(epp, fmt, arg...) \
+       dev_dbg(epp->udc->dev, "%s: " fmt, __func__, ## arg)
+#define ep_err(epp, fmt, arg...) \
+       dev_err(epp->udc->dev, "%s: " fmt, __func__, ## arg)
+#define ep_info(epp, fmt, arg...) \
+       dev_info(epp->udc->dev, "%s: " fmt, __func__, ## arg)
+#define ep_warn(epp, fmt, arg...) \
+       dev_warn(epp->udc->dev, "%s:" fmt, __func__, ## arg)
+
+#define UDCA_BUFF_SIZE (128)
+
+/* TODO: When the clock framework is introduced in LPC32xx, IO_ADDRESS will
+ * be replaced with an inremap()ed pointer
+ * */
+#define USB_CTRL               IO_ADDRESS(LPC32XX_CLK_PM_BASE + 0x64)
+
+/* USB_CTRL bit defines */
+#define USB_SLAVE_HCLK_EN      (1 << 24)
+#define USB_HOST_NEED_CLK_EN   (1 << 21)
+#define USB_DEV_NEED_CLK_EN    (1 << 22)
+
+/**********************************************************************
+ * USB device controller register offsets
+ **********************************************************************/
+
+#define USBD_DEVINTST(x)       ((x) + 0x200)
+#define USBD_DEVINTEN(x)       ((x) + 0x204)
+#define USBD_DEVINTCLR(x)      ((x) + 0x208)
+#define USBD_DEVINTSET(x)      ((x) + 0x20C)
+#define USBD_CMDCODE(x)                ((x) + 0x210)
+#define USBD_CMDDATA(x)                ((x) + 0x214)
+#define USBD_RXDATA(x)         ((x) + 0x218)
+#define USBD_TXDATA(x)         ((x) + 0x21C)
+#define USBD_RXPLEN(x)         ((x) + 0x220)
+#define USBD_TXPLEN(x)         ((x) + 0x224)
+#define USBD_CTRL(x)           ((x) + 0x228)
+#define USBD_DEVINTPRI(x)      ((x) + 0x22C)
+#define USBD_EPINTST(x)                ((x) + 0x230)
+#define USBD_EPINTEN(x)                ((x) + 0x234)
+#define USBD_EPINTCLR(x)       ((x) + 0x238)
+#define USBD_EPINTSET(x)       ((x) + 0x23C)
+#define USBD_EPINTPRI(x)       ((x) + 0x240)
+#define USBD_REEP(x)           ((x) + 0x244)
+#define USBD_EPIND(x)          ((x) + 0x248)
+#define USBD_EPMAXPSIZE(x)     ((x) + 0x24C)
+/* DMA support registers only below */
+/* Set, clear, or get enabled state of the DMA request status. If
+ * enabled, an IN or OUT token will start a DMA transfer for the EP */
+#define USBD_DMARST(x)         ((x) + 0x250)
+#define USBD_DMARCLR(x)                ((x) + 0x254)
+#define USBD_DMARSET(x)                ((x) + 0x258)
+/* DMA UDCA head pointer */
+#define USBD_UDCAH(x)          ((x) + 0x280)
+/* EP DMA status, enable, and disable. This is used to specifically
+ * enabled or disable DMA for a specific EP */
+#define USBD_EPDMAST(x)                ((x) + 0x284)
+#define USBD_EPDMAEN(x)                ((x) + 0x288)
+#define USBD_EPDMADIS(x)       ((x) + 0x28C)
+/* DMA master interrupts enable and pending interrupts */
+#define USBD_DMAINTST(x)       ((x) + 0x290)
+#define USBD_DMAINTEN(x)       ((x) + 0x294)
+/* DMA end of transfer interrupt enable, disable, status */
+#define USBD_EOTINTST(x)       ((x) + 0x2A0)
+#define USBD_EOTINTCLR(x)      ((x) + 0x2A4)
+#define USBD_EOTINTSET(x)      ((x) + 0x2A8)
+/* New DD request interrupt enable, disable, status */
+#define USBD_NDDRTINTST(x)     ((x) + 0x2AC)
+#define USBD_NDDRTINTCLR(x)    ((x) + 0x2B0)
+#define USBD_NDDRTINTSET(x)    ((x) + 0x2B4)
+/* DMA error interrupt enable, disable, status */
+#define USBD_SYSERRTINTST(x)   ((x) + 0x2B8)
+#define USBD_SYSERRTINTCLR(x)  ((x) + 0x2BC)
+#define USBD_SYSERRTINTSET(x)  ((x) + 0x2C0)
+
+/**********************************************************************
+ * USBD_DEVINTST/USBD_DEVINTEN/USBD_DEVINTCLR/USBD_DEVINTSET/
+ * USBD_DEVINTPRI register definitions
+ **********************************************************************/
+#define USBD_ERR_INT           (1 << 9)
+#define USBD_EP_RLZED          (1 << 8)
+#define USBD_TXENDPKT          (1 << 7)
+#define USBD_RXENDPKT          (1 << 6)
+#define USBD_CDFULL            (1 << 5)
+#define USBD_CCEMPTY           (1 << 4)
+#define USBD_DEV_STAT          (1 << 3)
+#define USBD_EP_SLOW           (1 << 2)
+#define USBD_EP_FAST           (1 << 1)
+#define USBD_FRAME             (1 << 0)
+
+/**********************************************************************
+ * USBD_EPINTST/USBD_EPINTEN/USBD_EPINTCLR/USBD_EPINTSET/
+ * USBD_EPINTPRI register definitions
+ **********************************************************************/
+/* End point selection macro (RX) */
+#define USBD_RX_EP_SEL(e)      (1 << ((e) << 1))
+
+/* End point selection macro (TX) */
+#define USBD_TX_EP_SEL(e)      (1 << (((e) << 1) + 1))
+
+/**********************************************************************
+ * USBD_REEP/USBD_DMARST/USBD_DMARCLR/USBD_DMARSET/USBD_EPDMAST/
+ * USBD_EPDMAEN/USBD_EPDMADIS/
+ * USBD_NDDRTINTST/USBD_NDDRTINTCLR/USBD_NDDRTINTSET/
+ * USBD_EOTINTST/USBD_EOTINTCLR/USBD_EOTINTSET/
+ * USBD_SYSERRTINTST/USBD_SYSERRTINTCLR/USBD_SYSERRTINTSET
+ * register definitions
+ **********************************************************************/
+/* Endpoint selection macro */
+#define USBD_EP_SEL(e)         (1 << (e))
+
+/**********************************************************************
+ * SBD_DMAINTST/USBD_DMAINTEN
+ **********************************************************************/
+#define USBD_SYS_ERR_INT       (1 << 2)
+#define USBD_NEW_DD_INT                (1 << 1)
+#define USBD_EOT_INT           (1 << 0)
+
+/**********************************************************************
+ * USBD_RXPLEN register definitions
+ **********************************************************************/
+#define USBD_PKT_RDY           (1 << 11)
+#define USBD_DV                        (1 << 10)
+#define USBD_PK_LEN_MASK       0x3FF
+
+/**********************************************************************
+ * USBD_CTRL register definitions
+ **********************************************************************/
+#define USBD_LOG_ENDPOINT(e)   ((e) << 2)
+#define USBD_WR_EN             (1 << 1)
+#define USBD_RD_EN             (1 << 0)
+
+/**********************************************************************
+ * USBD_CMDCODE register definitions
+ **********************************************************************/
+#define USBD_CMD_CODE(c)       ((c) << 16)
+#define USBD_CMD_PHASE(p)      ((p) << 8)
+
+/**********************************************************************
+ * USBD_DMARST/USBD_DMARCLR/USBD_DMARSET register definitions
+ **********************************************************************/
+#define USBD_DMAEP(e)          (1 << (e))
+
+/* DD (DMA Descriptor) structure, requires word alignment */
+struct lpc32xx_usbd_dd {
+       u32 *dd_next;
+       u32 dd_setup;
+       u32 dd_buffer_addr;
+       u32 dd_status;
+       u32 dd_iso_ps_mem_addr;
+};
+
+/* dd_setup bit defines */
+#define DD_SETUP_ATLE_DMA_MODE 0x01
+#define DD_SETUP_NEXT_DD_VALID 0x04
+#define DD_SETUP_ISO_EP                0x10
+#define DD_SETUP_PACKETLEN(n)  (((n) & 0x7FF) << 5)
+#define DD_SETUP_DMALENBYTES(n)        (((n) & 0xFFFF) << 16)
+
+/* dd_status bit defines */
+#define DD_STATUS_DD_RETIRED   0x01
+#define DD_STATUS_STS_MASK     0x1E
+#define DD_STATUS_STS_NS       0x00 /* Not serviced */
+#define DD_STATUS_STS_BS       0x02 /* Being serviced */
+#define DD_STATUS_STS_NC       0x04 /* Normal completion */
+#define DD_STATUS_STS_DUR      0x06 /* Data underrun (short packet) */
+#define DD_STATUS_STS_DOR      0x08 /* Data overrun */
+#define DD_STATUS_STS_SE       0x12 /* System error */
+#define DD_STATUS_PKT_VAL      0x20 /* Packet valid */
+#define DD_STATUS_LSB_EX       0x40 /* LS byte extracted (ATLE) */
+#define DD_STATUS_MSB_EX       0x80 /* MS byte extracted (ATLE) */
+#define DD_STATUS_MLEN(n)      (((n) >> 8) & 0x3F)
+#define DD_STATUS_CURDMACNT(n) (((n) >> 16) & 0xFFFF)
+
+/*
+ *
+ * Protocol engine bits below
+ *
+ */
+/* Device Interrupt Bit Definitions */
+#define FRAME_INT              0x00000001
+#define EP_FAST_INT            0x00000002
+#define EP_SLOW_INT            0x00000004
+#define DEV_STAT_INT           0x00000008
+#define CCEMTY_INT             0x00000010
+#define CDFULL_INT             0x00000020
+#define RxENDPKT_INT           0x00000040
+#define TxENDPKT_INT           0x00000080
+#define EP_RLZED_INT           0x00000100
+#define ERR_INT                        0x00000200
+
+/* Rx & Tx Packet Length Definitions */
+#define PKT_LNGTH_MASK         0x000003FF
+#define PKT_DV                 0x00000400
+#define PKT_RDY                        0x00000800
+
+/* USB Control Definitions */
+#define CTRL_RD_EN             0x00000001
+#define CTRL_WR_EN             0x00000002
+
+/* Command Codes */
+#define CMD_SET_ADDR           0x00D00500
+#define CMD_CFG_DEV            0x00D80500
+#define CMD_SET_MODE           0x00F30500
+#define CMD_RD_FRAME           0x00F50500
+#define DAT_RD_FRAME           0x00F50200
+#define CMD_RD_TEST            0x00FD0500
+#define DAT_RD_TEST            0x00FD0200
+#define CMD_SET_DEV_STAT       0x00FE0500
+#define CMD_GET_DEV_STAT       0x00FE0500
+#define DAT_GET_DEV_STAT       0x00FE0200
+#define CMD_GET_ERR_CODE       0x00FF0500
+#define DAT_GET_ERR_CODE       0x00FF0200
+#define CMD_RD_ERR_STAT                0x00FB0500
+#define DAT_RD_ERR_STAT                0x00FB0200
+#define DAT_WR_BYTE(x)         (0x00000100 | ((x) << 16))
+#define CMD_SEL_EP(x)          (0x00000500 | ((x) << 16))
+#define DAT_SEL_EP(x)          (0x00000200 | ((x) << 16))
+#define CMD_SEL_EP_CLRI(x)     (0x00400500 | ((x) << 16))
+#define DAT_SEL_EP_CLRI(x)     (0x00400200 | ((x) << 16))
+#define CMD_SET_EP_STAT(x)     (0x00400500 | ((x) << 16))
+#define CMD_CLR_BUF            0x00F20500
+#define DAT_CLR_BUF            0x00F20200
+#define CMD_VALID_BUF          0x00FA0500
+
+/* Device Address Register Definitions */
+#define DEV_ADDR_MASK          0x7F
+#define DEV_EN                 0x80
+
+/* Device Configure Register Definitions */
+#define CONF_DVICE             0x01
+
+/* Device Mode Register Definitions */
+#define AP_CLK                 0x01
+#define INAK_CI                        0x02
+#define INAK_CO                        0x04
+#define INAK_II                        0x08
+#define INAK_IO                        0x10
+#define INAK_BI                        0x20
+#define INAK_BO                        0x40
+
+/* Device Status Register Definitions */
+#define DEV_CON                        0x01
+#define DEV_CON_CH             0x02
+#define DEV_SUS                        0x04
+#define DEV_SUS_CH             0x08
+#define DEV_RST                        0x10
+
+/* Error Code Register Definitions */
+#define ERR_EC_MASK            0x0F
+#define ERR_EA                 0x10
+
+/* Error Status Register Definitions */
+#define ERR_PID                        0x01
+#define ERR_UEPKT              0x02
+#define ERR_DCRC               0x04
+#define ERR_TIMOUT             0x08
+#define ERR_EOP                        0x10
+#define ERR_B_OVRN             0x20
+#define ERR_BTSTF              0x40
+#define ERR_TGL                        0x80
+
+/* Endpoint Select Register Definitions */
+#define EP_SEL_F               0x01
+#define EP_SEL_ST              0x02
+#define EP_SEL_STP             0x04
+#define EP_SEL_PO              0x08
+#define EP_SEL_EPN             0x10
+#define EP_SEL_B_1_FULL                0x20
+#define EP_SEL_B_2_FULL                0x40
+
+/* Endpoint Status Register Definitions */
+#define EP_STAT_ST             0x01
+#define EP_STAT_DA             0x20
+#define EP_STAT_RF_MO          0x40
+#define EP_STAT_CND_ST         0x80
+
+/* Clear Buffer Register Definitions */
+#define CLR_BUF_PO             0x01
+
+/* DMA Interrupt Bit Definitions */
+#define EOT_INT                        0x01
+#define NDD_REQ_INT            0x02
+#define SYS_ERR_INT            0x04
+
+#define        DRIVER_VERSION  "1.03"
+static const char driver_name[] = "lpc32xx_udc";
+
+/*
+ *
+ * proc interface support
+ *
+ */
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+static char *epnames[] = {"INT", "ISO", "BULK", "CTRL"};
+static const char debug_filename[] = "driver/udc";
+
+static void proc_ep_show(struct seq_file *s, struct lpc32xx_ep *ep)
+{
+       struct lpc32xx_request *req;
+
+       seq_printf(s, "\n");
+       seq_printf(s, "%12s, maxpacket %4d %3s",
+                       ep->ep.name, ep->ep.maxpacket,
+                       ep->is_in ? "in" : "out");
+       seq_printf(s, " type %4s", epnames[ep->eptype]);
+       seq_printf(s, " ints: %12d", ep->totalints);
+
+       if (list_empty(&ep->queue))
+               seq_printf(s, "\t(queue empty)\n");
+       else {
+               list_for_each_entry(req, &ep->queue, queue) {
+                       u32 length = req->req.actual;
+
+                       seq_printf(s, "\treq %p len %d/%d buf %p\n",
+                                  &req->req, length,
+                                  req->req.length, req->req.buf);
+               }
+       }
+}
+
+static int proc_udc_show(struct seq_file *s, void *unused)
+{
+       struct lpc32xx_udc *udc = s->private;
+       struct lpc32xx_ep *ep;
+       unsigned long flags;
+
+       seq_printf(s, "%s: version %s\n", driver_name, DRIVER_VERSION);
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       seq_printf(s, "vbus %s, pullup %s, %s powered%s, gadget %s\n\n",
+                  udc->vbus ? "present" : "off",
+                  udc->enabled ? (udc->vbus ? "active" : "enabled") :
+                  "disabled",
+                  udc->selfpowered ? "self" : "VBUS",
+                  udc->suspended ? ", suspended" : "",
+                  udc->driver ? udc->driver->driver.name : "(none)");
+
+       if (udc->enabled && udc->vbus) {
+               proc_ep_show(s, &udc->ep[0]);
+               list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list)
+                       proc_ep_show(s, ep);
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static int proc_udc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, proc_udc_show, PDE_DATA(inode));
+}
+
+static const struct file_operations proc_ops = {
+       .owner          = THIS_MODULE,
+       .open           = proc_udc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static void create_debug_file(struct lpc32xx_udc *udc)
+{
+       udc->pde = debugfs_create_file(debug_filename, 0, NULL, udc, &proc_ops);
+}
+
+static void remove_debug_file(struct lpc32xx_udc *udc)
+{
+       if (udc->pde)
+               debugfs_remove(udc->pde);
+}
+
+#else
+static inline void create_debug_file(struct lpc32xx_udc *udc) {}
+static inline void remove_debug_file(struct lpc32xx_udc *udc) {}
+#endif
+
+/* Primary initialization sequence for the ISP1301 transceiver */
+static void isp1301_udc_configure(struct lpc32xx_udc *udc)
+{
+       /* LPC32XX only supports DAT_SE0 USB mode */
+       /* This sequence is important */
+
+       /* Disable transparent UART mode first */
+       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+               (ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR),
+               MC1_UART_EN);
+
+       /* Set full speed and SE0 mode */
+       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+               (ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), ~0);
+       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+               ISP1301_I2C_MODE_CONTROL_1, (MC1_SPEED_REG | MC1_DAT_SE0));
+
+       /*
+        * The PSW_OE enable bit state is reversed in the ISP1301 User's Guide
+        */
+       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+               (ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR), ~0);
+       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+               ISP1301_I2C_MODE_CONTROL_2, (MC2_BI_DI | MC2_SPD_SUSP_CTRL));
+
+       /* Driver VBUS_DRV high or low depending on board setup */
+       if (udc->board->vbus_drv_pol != 0)
+               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+                       ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV);
+       else
+               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+                       ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
+                       OTG1_VBUS_DRV);
+
+       /* Bi-directional mode with suspend control
+        * Enable both pulldowns for now - the pullup will be enable when VBUS
+        * is detected */
+       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+               (ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), ~0);
+       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+               ISP1301_I2C_OTG_CONTROL_1,
+               (0 | OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));
+
+       /* Discharge VBUS (just in case) */
+       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+               ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DISCHRG);
+       msleep(1);
+       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+               (ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR),
+               OTG1_VBUS_DISCHRG);
+
+       /* Clear and enable VBUS high edge interrupt */
+       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+               ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
+       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+               ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
+       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+               ISP1301_I2C_INTERRUPT_FALLING, INT_VBUS_VLD);
+       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+               ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
+       i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+               ISP1301_I2C_INTERRUPT_RISING, INT_VBUS_VLD);
+
+       /* Enable usb_need_clk clock after transceiver is initialized */
+       writel((readl(USB_CTRL) | USB_DEV_NEED_CLK_EN), USB_CTRL);
+
+       dev_info(udc->dev, "ISP1301 Vendor ID  : 0x%04x\n",
+                i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00));
+       dev_info(udc->dev, "ISP1301 Product ID : 0x%04x\n",
+                i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x02));
+       dev_info(udc->dev, "ISP1301 Version ID : 0x%04x\n",
+                i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x14));
+}
+
+/* Enables or disables the USB device pullup via the ISP1301 transceiver */
+static void isp1301_pullup_set(struct lpc32xx_udc *udc)
+{
+       if (udc->pullup)
+               /* Enable pullup for bus signalling */
+               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+                       ISP1301_I2C_OTG_CONTROL_1, OTG1_DP_PULLUP);
+       else
+               /* Enable pullup for bus signalling */
+               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+                       ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
+                       OTG1_DP_PULLUP);
+}
+
+static void pullup_work(struct work_struct *work)
+{
+       struct lpc32xx_udc *udc =
+               container_of(work, struct lpc32xx_udc, pullup_job);
+
+       isp1301_pullup_set(udc);
+}
+
+static void isp1301_pullup_enable(struct lpc32xx_udc *udc, int en_pullup,
+                                 int block)
+{
+       if (en_pullup == udc->pullup)
+               return;
+
+       udc->pullup = en_pullup;
+       if (block)
+               isp1301_pullup_set(udc);
+       else
+               /* defer slow i2c pull up setting */
+               schedule_work(&udc->pullup_job);
+}
+
+#ifdef CONFIG_PM
+/* Powers up or down the ISP1301 transceiver */
+static void isp1301_set_powerstate(struct lpc32xx_udc *udc, int enable)
+{
+       if (enable != 0)
+               /* Power up ISP1301 - this ISP1301 will automatically wakeup
+                  when VBUS is detected */
+               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+                       ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR,
+                       MC2_GLOBAL_PWR_DN);
+       else
+               /* Power down ISP1301 */
+               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+                       ISP1301_I2C_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
+}
+
+static void power_work(struct work_struct *work)
+{
+       struct lpc32xx_udc *udc =
+               container_of(work, struct lpc32xx_udc, power_job);
+
+       isp1301_set_powerstate(udc, udc->poweron);
+}
+#endif
+
+/*
+ *
+ * USB protocol engine command/data read/write helper functions
+ *
+ */
+/* Issues a single command to the USB device state machine */
+static void udc_protocol_cmd_w(struct lpc32xx_udc *udc, u32 cmd)
+{
+       u32 pass = 0;
+       int to;
+
+       /* EP may lock on CLRI if this read isn't done */
+       u32 tmp = readl(USBD_DEVINTST(udc->udp_baseaddr));
+       (void) tmp;
+
+       while (pass == 0) {
+               writel(USBD_CCEMPTY, USBD_DEVINTCLR(udc->udp_baseaddr));
+
+               /* Write command code */
+               writel(cmd, USBD_CMDCODE(udc->udp_baseaddr));
+               to = 10000;
+               while (((readl(USBD_DEVINTST(udc->udp_baseaddr)) &
+                        USBD_CCEMPTY) == 0) && (to > 0)) {
+                       to--;
+               }
+
+               if (to > 0)
+                       pass = 1;
+
+               cpu_relax();
+       }
+}
+
+/* Issues 2 commands (or command and data) to the USB device state machine */
+static inline void udc_protocol_cmd_data_w(struct lpc32xx_udc *udc, u32 cmd,
+                                          u32 data)
+{
+       udc_protocol_cmd_w(udc, cmd);
+       udc_protocol_cmd_w(udc, data);
+}
+
+/* Issues a single command to the USB device state machine and reads
+ * response data */
+static u32 udc_protocol_cmd_r(struct lpc32xx_udc *udc, u32 cmd)
+{
+       u32 tmp;
+       int to = 1000;
+
+       /* Write a command and read data from the protocol engine */
+       writel((USBD_CDFULL | USBD_CCEMPTY),
+                    USBD_DEVINTCLR(udc->udp_baseaddr));
+
+       /* Write command code */
+       udc_protocol_cmd_w(udc, cmd);
+
+       tmp = readl(USBD_DEVINTST(udc->udp_baseaddr));
+       while ((!(readl(USBD_DEVINTST(udc->udp_baseaddr)) & USBD_CDFULL))
+              && (to > 0))
+               to--;
+       if (!to)
+               dev_dbg(udc->dev,
+                       "Protocol engine didn't receive response (CDFULL)\n");
+
+       return readl(USBD_CMDDATA(udc->udp_baseaddr));
+}
+
+/*
+ *
+ * USB device interrupt mask support functions
+ *
+ */
+/* Enable one or more USB device interrupts */
+static inline void uda_enable_devint(struct lpc32xx_udc *udc, u32 devmask)
+{
+       udc->enabled_devints |= devmask;
+       writel(udc->enabled_devints, USBD_DEVINTEN(udc->udp_baseaddr));
+}
+
+/* Disable one or more USB device interrupts */
+static inline void uda_disable_devint(struct lpc32xx_udc *udc, u32 mask)
+{
+       udc->enabled_devints &= ~mask;
+       writel(udc->enabled_devints, USBD_DEVINTEN(udc->udp_baseaddr));
+}
+
+/* Clear one or more USB device interrupts */
+static inline void uda_clear_devint(struct lpc32xx_udc *udc, u32 mask)
+{
+       writel(mask, USBD_DEVINTCLR(udc->udp_baseaddr));
+}
+
+/*
+ *
+ * Endpoint interrupt disable/enable functions
+ *
+ */
+/* Enable one or more USB endpoint interrupts */
+static void uda_enable_hwepint(struct lpc32xx_udc *udc, u32 hwep)
+{
+       udc->enabled_hwepints |= (1 << hwep);
+       writel(udc->enabled_hwepints, USBD_EPINTEN(udc->udp_baseaddr));
+}
+
+/* Disable one or more USB endpoint interrupts */
+static void uda_disable_hwepint(struct lpc32xx_udc *udc, u32 hwep)
+{
+       udc->enabled_hwepints &= ~(1 << hwep);
+       writel(udc->enabled_hwepints, USBD_EPINTEN(udc->udp_baseaddr));
+}
+
+/* Clear one or more USB endpoint interrupts */
+static inline void uda_clear_hwepint(struct lpc32xx_udc *udc, u32 hwep)
+{
+       writel((1 << hwep), USBD_EPINTCLR(udc->udp_baseaddr));
+}
+
+/* Enable DMA for the HW channel */
+static inline void udc_ep_dma_enable(struct lpc32xx_udc *udc, u32 hwep)
+{
+       writel((1 << hwep), USBD_EPDMAEN(udc->udp_baseaddr));
+}
+
+/* Disable DMA for the HW channel */
+static inline void udc_ep_dma_disable(struct lpc32xx_udc *udc, u32 hwep)
+{
+       writel((1 << hwep), USBD_EPDMADIS(udc->udp_baseaddr));
+}
+
+/*
+ *
+ * Endpoint realize/unrealize functions
+ *
+ */
+/* Before an endpoint can be used, it needs to be realized
+ * in the USB protocol engine - this realizes the endpoint.
+ * The interrupt (FIFO or DMA) is not enabled with this function */
+static void udc_realize_hwep(struct lpc32xx_udc *udc, u32 hwep,
+                            u32 maxpacket)
+{
+       int to = 1000;
+
+       writel(USBD_EP_RLZED, USBD_DEVINTCLR(udc->udp_baseaddr));
+       writel(hwep, USBD_EPIND(udc->udp_baseaddr));
+       udc->realized_eps |= (1 << hwep);
+       writel(udc->realized_eps, USBD_REEP(udc->udp_baseaddr));
+       writel(maxpacket, USBD_EPMAXPSIZE(udc->udp_baseaddr));
+
+       /* Wait until endpoint is realized in hardware */
+       while ((!(readl(USBD_DEVINTST(udc->udp_baseaddr)) &
+                 USBD_EP_RLZED)) && (to > 0))
+               to--;
+       if (!to)
+               dev_dbg(udc->dev, "EP not correctly realized in hardware\n");
+
+       writel(USBD_EP_RLZED, USBD_DEVINTCLR(udc->udp_baseaddr));
+}
+
+/* Unrealize an EP */
+static void udc_unrealize_hwep(struct lpc32xx_udc *udc, u32 hwep)
+{
+       udc->realized_eps &= ~(1 << hwep);
+       writel(udc->realized_eps, USBD_REEP(udc->udp_baseaddr));
+}
+
+/*
+ *
+ * Endpoint support functions
+ *
+ */
+/* Select and clear endpoint interrupt */
+static u32 udc_selep_clrint(struct lpc32xx_udc *udc, u32 hwep)
+{
+       udc_protocol_cmd_w(udc, CMD_SEL_EP_CLRI(hwep));
+       return udc_protocol_cmd_r(udc, DAT_SEL_EP_CLRI(hwep));
+}
+
+/* Disables the endpoint in the USB protocol engine */
+static void udc_disable_hwep(struct lpc32xx_udc *udc, u32 hwep)
+{
+       udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep),
+                               DAT_WR_BYTE(EP_STAT_DA));
+}
+
+/* Stalls the endpoint - endpoint will return STALL */
+static void udc_stall_hwep(struct lpc32xx_udc *udc, u32 hwep)
+{
+       udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep),
+                               DAT_WR_BYTE(EP_STAT_ST));
+}
+
+/* Clear stall or reset endpoint */
+static void udc_clrstall_hwep(struct lpc32xx_udc *udc, u32 hwep)
+{
+       udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(hwep),
+                               DAT_WR_BYTE(0));
+}
+
+/* Select an endpoint for endpoint status, clear, validate */
+static void udc_select_hwep(struct lpc32xx_udc *udc, u32 hwep)
+{
+       udc_protocol_cmd_w(udc, CMD_SEL_EP(hwep));
+}
+
+/*
+ *
+ * Endpoint buffer management functions
+ *
+ */
+/* Clear the current endpoint's buffer */
+static void udc_clr_buffer_hwep(struct lpc32xx_udc *udc, u32 hwep)
+{
+       udc_select_hwep(udc, hwep);
+       udc_protocol_cmd_w(udc, CMD_CLR_BUF);
+}
+
+/* Validate the current endpoint's buffer */
+static void udc_val_buffer_hwep(struct lpc32xx_udc *udc, u32 hwep)
+{
+       udc_select_hwep(udc, hwep);
+       udc_protocol_cmd_w(udc, CMD_VALID_BUF);
+}
+
+static inline u32 udc_clearep_getsts(struct lpc32xx_udc *udc, u32 hwep)
+{
+       /* Clear EP interrupt */
+       uda_clear_hwepint(udc, hwep);
+       return udc_selep_clrint(udc, hwep);
+}
+
+/*
+ *
+ * USB EP DMA support
+ *
+ */
+/* Allocate a DMA Descriptor */
+static struct lpc32xx_usbd_dd_gad *udc_dd_alloc(struct lpc32xx_udc *udc)
+{
+       dma_addr_t                      dma;
+       struct lpc32xx_usbd_dd_gad      *dd;
+
+       dd = (struct lpc32xx_usbd_dd_gad *) dma_pool_alloc(
+                       udc->dd_cache, (GFP_KERNEL | GFP_DMA), &dma);
+       if (dd)
+               dd->this_dma = dma;
+
+       return dd;
+}
+
+/* Free a DMA Descriptor */
+static void udc_dd_free(struct lpc32xx_udc *udc, struct lpc32xx_usbd_dd_gad *dd)
+{
+       dma_pool_free(udc->dd_cache, dd, dd->this_dma);
+}
+
+/*
+ *
+ * USB setup and shutdown functions
+ *
+ */
+/* Enables or disables most of the USB system clocks when low power mode is
+ * needed. Clocks are typically started on a connection event, and disabled
+ * when a cable is disconnected */
+static void udc_clk_set(struct lpc32xx_udc *udc, int enable)
+{
+       if (enable != 0) {
+               if (udc->clocked)
+                       return;
+
+               udc->clocked = 1;
+
+               /* 48MHz PLL up */
+               clk_enable(udc->usb_pll_clk);
+
+               /* Enable the USB device clock */
+               writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN,
+                            USB_CTRL);
+
+               clk_enable(udc->usb_otg_clk);
+       } else {
+               if (!udc->clocked)
+                       return;
+
+               udc->clocked = 0;
+
+               /* Never disable the USB_HCLK during normal operation */
+
+               /* 48MHz PLL dpwn */
+               clk_disable(udc->usb_pll_clk);
+
+               /* Disable the USB device clock */
+               writel(readl(USB_CTRL) & ~USB_DEV_NEED_CLK_EN,
+                            USB_CTRL);
+
+               clk_disable(udc->usb_otg_clk);
+       }
+}
+
+/* Set/reset USB device address */
+static void udc_set_address(struct lpc32xx_udc *udc, u32 addr)
+{
+       /* Address will be latched at the end of the status phase, or
+          latched immediately if function is called twice */
+       udc_protocol_cmd_data_w(udc, CMD_SET_ADDR,
+                               DAT_WR_BYTE(DEV_EN | addr));
+}
+
+/* Setup up a IN request for DMA transfer - this consists of determining the
+ * list of DMA addresses for the transfer, allocating DMA Descriptors,
+ * installing the DD into the UDCA, and then enabling the DMA for that EP */
+static int udc_ep_in_req_dma(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
+{
+       struct lpc32xx_request *req;
+       u32 hwep = ep->hwep_num;
+
+       ep->req_pending = 1;
+
+       /* There will always be a request waiting here */
+       req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
+
+       /* Place the DD Descriptor into the UDCA */
+       udc->udca_v_base[hwep] = req->dd_desc_ptr->this_dma;
+
+       /* Enable DMA and interrupt for the HW EP */
+       udc_ep_dma_enable(udc, hwep);
+
+       /* Clear ZLP if last packet is not of MAXP size */
+       if (req->req.length % ep->ep.maxpacket)
+               req->send_zlp = 0;
+
+       return 0;
+}
+
+/* Setup up a OUT request for DMA transfer - this consists of determining the
+ * list of DMA addresses for the transfer, allocating DMA Descriptors,
+ * installing the DD into the UDCA, and then enabling the DMA for that EP */
+static int udc_ep_out_req_dma(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
+{
+       struct lpc32xx_request *req;
+       u32 hwep = ep->hwep_num;
+
+       ep->req_pending = 1;
+
+       /* There will always be a request waiting here */
+       req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
+
+       /* Place the DD Descriptor into the UDCA */
+       udc->udca_v_base[hwep] = req->dd_desc_ptr->this_dma;
+
+       /* Enable DMA and interrupt for the HW EP */
+       udc_ep_dma_enable(udc, hwep);
+       return 0;
+}
+
+static void udc_disable(struct lpc32xx_udc *udc)
+{
+       u32 i;
+
+       /* Disable device */
+       udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(0));
+       udc_protocol_cmd_data_w(udc, CMD_SET_DEV_STAT, DAT_WR_BYTE(0));
+
+       /* Disable all device interrupts (including EP0) */
+       uda_disable_devint(udc, 0x3FF);
+
+       /* Disable and reset all endpoint interrupts */
+       for (i = 0; i < 32; i++) {
+               uda_disable_hwepint(udc, i);
+               uda_clear_hwepint(udc, i);
+               udc_disable_hwep(udc, i);
+               udc_unrealize_hwep(udc, i);
+               udc->udca_v_base[i] = 0;
+
+               /* Disable and clear all interrupts and DMA */
+               udc_ep_dma_disable(udc, i);
+               writel((1 << i), USBD_EOTINTCLR(udc->udp_baseaddr));
+               writel((1 << i), USBD_NDDRTINTCLR(udc->udp_baseaddr));
+               writel((1 << i), USBD_SYSERRTINTCLR(udc->udp_baseaddr));
+               writel((1 << i), USBD_DMARCLR(udc->udp_baseaddr));
+       }
+
+       /* Disable DMA interrupts */
+       writel(0, USBD_DMAINTEN(udc->udp_baseaddr));
+
+       writel(0, USBD_UDCAH(udc->udp_baseaddr));
+}
+
+static void udc_enable(struct lpc32xx_udc *udc)
+{
+       u32 i;
+       struct lpc32xx_ep *ep = &udc->ep[0];
+
+       /* Start with known state */
+       udc_disable(udc);
+
+       /* Enable device */
+       udc_protocol_cmd_data_w(udc, CMD_SET_DEV_STAT, DAT_WR_BYTE(DEV_CON));
+
+       /* EP interrupts on high priority, FRAME interrupt on low priority */
+       writel(USBD_EP_FAST, USBD_DEVINTPRI(udc->udp_baseaddr));
+       writel(0xFFFF, USBD_EPINTPRI(udc->udp_baseaddr));
+
+       /* Clear any pending device interrupts */
+       writel(0x3FF, USBD_DEVINTCLR(udc->udp_baseaddr));
+
+       /* Setup UDCA - not yet used (DMA) */
+       writel(udc->udca_p_base, USBD_UDCAH(udc->udp_baseaddr));
+
+       /* Only enable EP0 in and out for now, EP0 only works in FIFO mode */
+       for (i = 0; i <= 1; i++) {
+               udc_realize_hwep(udc, i, ep->ep.maxpacket);
+               uda_enable_hwepint(udc, i);
+               udc_select_hwep(udc, i);
+               udc_clrstall_hwep(udc, i);
+               udc_clr_buffer_hwep(udc, i);
+       }
+
+       /* Device interrupt setup */
+       uda_clear_devint(udc, (USBD_ERR_INT | USBD_DEV_STAT | USBD_EP_SLOW |
+                              USBD_EP_FAST));
+       uda_enable_devint(udc, (USBD_ERR_INT | USBD_DEV_STAT | USBD_EP_SLOW |
+                               USBD_EP_FAST));
+
+       /* Set device address to 0 - called twice to force a latch in the USB
+          engine without the need of a setup packet status closure */
+       udc_set_address(udc, 0);
+       udc_set_address(udc, 0);
+
+       /* Enable master DMA interrupts */
+       writel((USBD_SYS_ERR_INT | USBD_EOT_INT),
+                    USBD_DMAINTEN(udc->udp_baseaddr));
+
+       udc->dev_status = 0;
+}
+
+/*
+ *
+ * USB device board specific events handled via callbacks
+ *
+ */
+/* Connection change event - notify board function of change */
+static void uda_power_event(struct lpc32xx_udc *udc, u32 conn)
+{
+       /* Just notify of a connection change event (optional) */
+       if (udc->board->conn_chgb != NULL)
+               udc->board->conn_chgb(conn);
+}
+
+/* Suspend/resume event - notify board function of change */
+static void uda_resm_susp_event(struct lpc32xx_udc *udc, u32 conn)
+{
+       /* Just notify of a Suspend/resume change event (optional) */
+       if (udc->board->susp_chgb != NULL)
+               udc->board->susp_chgb(conn);
+
+       if (conn)
+               udc->suspended = 0;
+       else
+               udc->suspended = 1;
+}
+
+/* Remote wakeup enable/disable - notify board function of change */
+static void uda_remwkp_cgh(struct lpc32xx_udc *udc)
+{
+       if (udc->board->rmwk_chgb != NULL)
+               udc->board->rmwk_chgb(udc->dev_status &
+                                     (1 << USB_DEVICE_REMOTE_WAKEUP));
+}
+
+/* Reads data from FIFO, adjusts for alignment and data size */
+static void udc_pop_fifo(struct lpc32xx_udc *udc, u8 *data, u32 bytes)
+{
+       int n, i, bl;
+       u16 *p16;
+       u32 *p32, tmp, cbytes;
+
+       /* Use optimal data transfer method based on source address and size */
+       switch (((u32) data) & 0x3) {
+       case 0: /* 32-bit aligned */
+               p32 = (u32 *) data;
+               cbytes = (bytes & ~0x3);
+
+               /* Copy 32-bit aligned data first */
+               for (n = 0; n < cbytes; n += 4)
+                       *p32++ = readl(USBD_RXDATA(udc->udp_baseaddr));
+
+               /* Handle any remaining bytes */
+               bl = bytes - cbytes;
+               if (bl) {
+                       tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
+                       for (n = 0; n < bl; n++)
+                               data[cbytes + n] = ((tmp >> (n * 8)) & 0xFF);
+
+               }
+               break;
+
+       case 1: /* 8-bit aligned */
+       case 3:
+               /* Each byte has to be handled independently */
+               for (n = 0; n < bytes; n += 4) {
+                       tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
+
+                       bl = bytes - n;
+                       if (bl > 3)
+                               bl = 3;
+
+                       for (i = 0; i < bl; i++)
+                               data[n + i] = (u8) ((tmp >> (n * 8)) & 0xFF);
+               }
+               break;
+
+       case 2: /* 16-bit aligned */
+               p16 = (u16 *) data;
+               cbytes = (bytes & ~0x3);
+
+               /* Copy 32-bit sized objects first with 16-bit alignment */
+               for (n = 0; n < cbytes; n += 4) {
+                       tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
+                       *p16++ = (u16)(tmp & 0xFFFF);
+                       *p16++ = (u16)((tmp >> 16) & 0xFFFF);
+               }
+
+               /* Handle any remaining bytes */
+               bl = bytes - cbytes;
+               if (bl) {
+                       tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
+                       for (n = 0; n < bl; n++)
+                               data[cbytes + n] = ((tmp >> (n * 8)) & 0xFF);
+               }
+               break;
+       }
+}
+
+/* Read data from the FIFO for an endpoint. This function is for endpoints (such
+ * as EP0) that don't use DMA. This function should only be called if a packet
+ * is known to be ready to read for the endpoint. Note that the endpoint must
+ * be selected in the protocol engine prior to this call. */
+static u32 udc_read_hwep(struct lpc32xx_udc *udc, u32 hwep, u32 *data,
+                        u32 bytes)
+{
+       u32 tmpv;
+       int to = 1000;
+       u32 tmp, hwrep = ((hwep & 0x1E) << 1) | CTRL_RD_EN;
+
+       /* Setup read of endpoint */
+       writel(hwrep, USBD_CTRL(udc->udp_baseaddr));
+
+       /* Wait until packet is ready */
+       while ((((tmpv = readl(USBD_RXPLEN(udc->udp_baseaddr))) &
+                PKT_RDY) == 0) && (to > 0))
+               to--;
+       if (!to)
+               dev_dbg(udc->dev, "No packet ready on FIFO EP read\n");
+
+       /* Mask out count */
+       tmp = tmpv & PKT_LNGTH_MASK;
+       if (bytes < tmp)
+               tmp = bytes;
+
+       if ((tmp > 0) && (data != NULL))
+               udc_pop_fifo(udc, (u8 *) data, tmp);
+
+       writel(((hwep & 0x1E) << 1), USBD_CTRL(udc->udp_baseaddr));
+
+       /* Clear the buffer */
+       udc_clr_buffer_hwep(udc, hwep);
+
+       return tmp;
+}
+
+/* Stuffs data into the FIFO, adjusts for alignment and data size */
+static void udc_stuff_fifo(struct lpc32xx_udc *udc, u8 *data, u32 bytes)
+{
+       int n, i, bl;
+       u16 *p16;
+       u32 *p32, tmp, cbytes;
+
+       /* Use optimal data transfer method based on source address and size */
+       switch (((u32) data) & 0x3) {
+       case 0: /* 32-bit aligned */
+               p32 = (u32 *) data;
+               cbytes = (bytes & ~0x3);
+
+               /* Copy 32-bit aligned data first */
+               for (n = 0; n < cbytes; n += 4)
+                       writel(*p32++, USBD_TXDATA(udc->udp_baseaddr));
+
+               /* Handle any remaining bytes */
+               bl = bytes - cbytes;
+               if (bl) {
+                       tmp = 0;
+                       for (n = 0; n < bl; n++)
+                               tmp |= data[cbytes + n] << (n * 8);
+
+                       writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
+               }
+               break;
+
+       case 1: /* 8-bit aligned */
+       case 3:
+               /* Each byte has to be handled independently */
+               for (n = 0; n < bytes; n += 4) {
+                       bl = bytes - n;
+                       if (bl > 4)
+                               bl = 4;
+
+                       tmp = 0;
+                       for (i = 0; i < bl; i++)
+                               tmp |= data[n + i] << (i * 8);
+
+                       writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
+               }
+               break;
+
+       case 2: /* 16-bit aligned */
+               p16 = (u16 *) data;
+               cbytes = (bytes & ~0x3);
+
+               /* Copy 32-bit aligned data first */
+               for (n = 0; n < cbytes; n += 4) {
+                       tmp = *p16++ & 0xFFFF;
+                       tmp |= (*p16++ & 0xFFFF) << 16;
+                       writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
+               }
+
+               /* Handle any remaining bytes */
+               bl = bytes - cbytes;
+               if (bl) {
+                       tmp = 0;
+                       for (n = 0; n < bl; n++)
+                               tmp |= data[cbytes + n] << (n * 8);
+
+                       writel(tmp, USBD_TXDATA(udc->udp_baseaddr));
+               }
+               break;
+       }
+}
+
+/* Write data to the FIFO for an endpoint. This function is for endpoints (such
+ * as EP0) that don't use DMA. Note that the endpoint must be selected in the
+ * protocol engine prior to this call. */
+static void udc_write_hwep(struct lpc32xx_udc *udc, u32 hwep, u32 *data,
+                          u32 bytes)
+{
+       u32 hwwep = ((hwep & 0x1E) << 1) | CTRL_WR_EN;
+
+       if ((bytes > 0) && (data == NULL))
+               return;
+
+       /* Setup write of endpoint */
+       writel(hwwep, USBD_CTRL(udc->udp_baseaddr));
+
+       writel(bytes, USBD_TXPLEN(udc->udp_baseaddr));
+
+       /* Need at least 1 byte to trigger TX */
+       if (bytes == 0)
+               writel(0, USBD_TXDATA(udc->udp_baseaddr));
+       else
+               udc_stuff_fifo(udc, (u8 *) data, bytes);
+
+       writel(((hwep & 0x1E) << 1), USBD_CTRL(udc->udp_baseaddr));
+
+       udc_val_buffer_hwep(udc, hwep);
+}
+
+/* USB device reset - resets USB to a default state with just EP0
+   enabled */
+static void uda_usb_reset(struct lpc32xx_udc *udc)
+{
+       u32 i = 0;
+       /* Re-init device controller and EP0 */
+       udc_enable(udc);
+       udc->gadget.speed = USB_SPEED_FULL;
+
+       for (i = 1; i < NUM_ENDPOINTS; i++) {
+               struct lpc32xx_ep *ep = &udc->ep[i];
+               ep->req_pending = 0;
+       }
+}
+
+/* Send a ZLP on EP0 */
+static void udc_ep0_send_zlp(struct lpc32xx_udc *udc)
+{
+       udc_write_hwep(udc, EP_IN, NULL, 0);
+}
+
+/* Get current frame number */
+static u16 udc_get_current_frame(struct lpc32xx_udc *udc)
+{
+       u16 flo, fhi;
+
+       udc_protocol_cmd_w(udc, CMD_RD_FRAME);
+       flo = (u16) udc_protocol_cmd_r(udc, DAT_RD_FRAME);
+       fhi = (u16) udc_protocol_cmd_r(udc, DAT_RD_FRAME);
+
+       return (fhi << 8) | flo;
+}
+
+/* Set the device as configured - enables all endpoints */
+static inline void udc_set_device_configured(struct lpc32xx_udc *udc)
+{
+       udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(CONF_DVICE));
+}
+
+/* Set the device as unconfigured - disables all endpoints */
+static inline void udc_set_device_unconfigured(struct lpc32xx_udc *udc)
+{
+       udc_protocol_cmd_data_w(udc, CMD_CFG_DEV, DAT_WR_BYTE(0));
+}
+
+/* reinit == restore initial software state */
+static void udc_reinit(struct lpc32xx_udc *udc)
+{
+       u32 i;
+
+       INIT_LIST_HEAD(&udc->gadget.ep_list);
+       INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
+
+       for (i = 0; i < NUM_ENDPOINTS; i++) {
+               struct lpc32xx_ep *ep = &udc->ep[i];
+
+               if (i != 0)
+                       list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+               usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
+               INIT_LIST_HEAD(&ep->queue);
+               ep->req_pending = 0;
+       }
+
+       udc->ep0state = WAIT_FOR_SETUP;
+}
+
+/* Must be called with lock */
+static void done(struct lpc32xx_ep *ep, struct lpc32xx_request *req, int status)
+{
+       struct lpc32xx_udc *udc = ep->udc;
+
+       list_del_init(&req->queue);
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       if (ep->lep) {
+               usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
+
+               /* Free DDs */
+               udc_dd_free(udc, req->dd_desc_ptr);
+       }
+
+       if (status && status != -ESHUTDOWN)
+               ep_dbg(ep, "%s done %p, status %d\n", ep->ep.name, req, status);
+
+       ep->req_pending = 0;
+       spin_unlock(&udc->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&udc->lock);
+}
+
+/* Must be called with lock */
+static void nuke(struct lpc32xx_ep *ep, int status)
+{
+       struct lpc32xx_request *req;
+
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
+               done(ep, req, status);
+       }
+
+       if (status == -ESHUTDOWN) {
+               uda_disable_hwepint(ep->udc, ep->hwep_num);
+               udc_disable_hwep(ep->udc, ep->hwep_num);
+       }
+}
+
+/* IN endpoint 0 transfer */
+static int udc_ep0_in_req(struct lpc32xx_udc *udc)
+{
+       struct lpc32xx_request *req;
+       struct lpc32xx_ep *ep0 = &udc->ep[0];
+       u32 tsend, ts = 0;
+
+       if (list_empty(&ep0->queue))
+               /* Nothing to send */
+               return 0;
+       else
+               req = list_entry(ep0->queue.next, struct lpc32xx_request,
+                                queue);
+
+       tsend = ts = req->req.length - req->req.actual;
+       if (ts == 0) {
+               /* Send a ZLP */
+               udc_ep0_send_zlp(udc);
+               done(ep0, req, 0);
+               return 1;
+       } else if (ts > ep0->ep.maxpacket)
+               ts = ep0->ep.maxpacket; /* Just send what we can */
+
+       /* Write data to the EP0 FIFO and start transfer */
+       udc_write_hwep(udc, EP_IN, (req->req.buf + req->req.actual), ts);
+
+       /* Increment data pointer */
+       req->req.actual += ts;
+
+       if (tsend >= ep0->ep.maxpacket)
+               return 0; /* Stay in data transfer state */
+
+       /* Transfer request is complete */
+       udc->ep0state = WAIT_FOR_SETUP;
+       done(ep0, req, 0);
+       return 1;
+}
+
+/* OUT endpoint 0 transfer */
+static int udc_ep0_out_req(struct lpc32xx_udc *udc)
+{
+       struct lpc32xx_request *req;
+       struct lpc32xx_ep *ep0 = &udc->ep[0];
+       u32 tr, bufferspace;
+
+       if (list_empty(&ep0->queue))
+               return 0;
+       else
+               req = list_entry(ep0->queue.next, struct lpc32xx_request,
+                                queue);
+
+       if (req) {
+               if (req->req.length == 0) {
+                       /* Just dequeue request */
+                       done(ep0, req, 0);
+                       udc->ep0state = WAIT_FOR_SETUP;
+                       return 1;
+               }
+
+               /* Get data from FIFO */
+               bufferspace = req->req.length - req->req.actual;
+               if (bufferspace > ep0->ep.maxpacket)
+                       bufferspace = ep0->ep.maxpacket;
+
+               /* Copy data to buffer */
+               prefetchw(req->req.buf + req->req.actual);
+               tr = udc_read_hwep(udc, EP_OUT, req->req.buf + req->req.actual,
+                                  bufferspace);
+               req->req.actual += bufferspace;
+
+               if (tr < ep0->ep.maxpacket) {
+                       /* This is the last packet */
+                       done(ep0, req, 0);
+                       udc->ep0state = WAIT_FOR_SETUP;
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+/* Must be called with lock */
+static void stop_activity(struct lpc32xx_udc *udc)
+{
+       struct usb_gadget_driver *driver = udc->driver;
+       int i;
+
+       if (udc->gadget.speed == USB_SPEED_UNKNOWN)
+               driver = NULL;
+
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       udc->suspended = 0;
+
+       for (i = 0; i < NUM_ENDPOINTS; i++) {
+               struct lpc32xx_ep *ep = &udc->ep[i];
+               nuke(ep, -ESHUTDOWN);
+       }
+       if (driver) {
+               spin_unlock(&udc->lock);
+               driver->disconnect(&udc->gadget);
+               spin_lock(&udc->lock);
+       }
+
+       isp1301_pullup_enable(udc, 0, 0);
+       udc_disable(udc);
+       udc_reinit(udc);
+}
+
+/*
+ * Activate or kill host pullup
+ * Can be called with or without lock
+ */
+static void pullup(struct lpc32xx_udc *udc, int is_on)
+{
+       if (!udc->clocked)
+               return;
+
+       if (!udc->enabled || !udc->vbus)
+               is_on = 0;
+
+       if (is_on != udc->pullup)
+               isp1301_pullup_enable(udc, is_on, 0);
+}
+
+/* Must be called without lock */
+static int lpc32xx_ep_disable(struct usb_ep *_ep)
+{
+       struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
+       struct lpc32xx_udc *udc = ep->udc;
+       unsigned long   flags;
+
+       if ((ep->hwep_num_base == 0) || (ep->hwep_num == 0))
+               return -EINVAL;
+       spin_lock_irqsave(&udc->lock, flags);
+
+       nuke(ep, -ESHUTDOWN);
+
+       /* Clear all DMA statuses for this EP */
+       udc_ep_dma_disable(udc, ep->hwep_num);
+       writel(1 << ep->hwep_num, USBD_EOTINTCLR(udc->udp_baseaddr));
+       writel(1 << ep->hwep_num, USBD_NDDRTINTCLR(udc->udp_baseaddr));
+       writel(1 << ep->hwep_num, USBD_SYSERRTINTCLR(udc->udp_baseaddr));
+       writel(1 << ep->hwep_num, USBD_DMARCLR(udc->udp_baseaddr));
+
+       /* Remove the DD pointer in the UDCA */
+       udc->udca_v_base[ep->hwep_num] = 0;
+
+       /* Disable and reset endpoint and interrupt */
+       uda_clear_hwepint(udc, ep->hwep_num);
+       udc_unrealize_hwep(udc, ep->hwep_num);
+
+       ep->hwep_num = 0;
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       atomic_dec(&udc->enabled_ep_cnt);
+       wake_up(&udc->ep_disable_wait_queue);
+
+       return 0;
+}
+
+/* Must be called without lock */
+static int lpc32xx_ep_enable(struct usb_ep *_ep,
+                            const struct usb_endpoint_descriptor *desc)
+{
+       struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
+       struct lpc32xx_udc *udc = ep->udc;
+       u16 maxpacket;
+       u32 tmp;
+       unsigned long flags;
+
+       /* Verify EP data */
+       if ((!_ep) || (!ep) || (!desc) ||
+           (desc->bDescriptorType != USB_DT_ENDPOINT)) {
+               dev_dbg(udc->dev, "bad ep or descriptor\n");
+               return -EINVAL;
+       }
+       maxpacket = usb_endpoint_maxp(desc);
+       if ((maxpacket == 0) || (maxpacket > ep->maxpacket)) {
+               dev_dbg(udc->dev, "bad ep descriptor's packet size\n");
+               return -EINVAL;
+       }
+
+       /* Don't touch EP0 */
+       if (ep->hwep_num_base == 0) {
+               dev_dbg(udc->dev, "Can't re-enable EP0!!!\n");
+               return -EINVAL;
+       }
+
+       /* Is driver ready? */
+       if ((!udc->driver) || (udc->gadget.speed == USB_SPEED_UNKNOWN)) {
+               dev_dbg(udc->dev, "bogus device state\n");
+               return -ESHUTDOWN;
+       }
+
+       tmp = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+       switch (tmp) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               return -EINVAL;
+
+       case USB_ENDPOINT_XFER_INT:
+               if (maxpacket > ep->maxpacket) {
+                       dev_dbg(udc->dev,
+                               "Bad INT endpoint maxpacket %d\n", maxpacket);
+                       return -EINVAL;
+               }
+               break;
+
+       case USB_ENDPOINT_XFER_BULK:
+               switch (maxpacket) {
+               case 8:
+               case 16:
+               case 32:
+               case 64:
+                       break;
+
+               default:
+                       dev_dbg(udc->dev,
+                               "Bad BULK endpoint maxpacket %d\n", maxpacket);
+                       return -EINVAL;
+               }
+               break;
+
+       case USB_ENDPOINT_XFER_ISOC:
+               break;
+       }
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /* Initialize endpoint to match the selected descriptor */
+       ep->is_in = (desc->bEndpointAddress & USB_DIR_IN) != 0;
+       ep->ep.maxpacket = maxpacket;
+
+       /* Map hardware endpoint from base and direction */
+       if (ep->is_in)
+               /* IN endpoints are offset 1 from the OUT endpoint */
+               ep->hwep_num = ep->hwep_num_base + EP_IN;
+       else
+               ep->hwep_num = ep->hwep_num_base;
+
+       ep_dbg(ep, "EP enabled: %s, HW:%d, MP:%d IN:%d\n", ep->ep.name,
+              ep->hwep_num, maxpacket, (ep->is_in == 1));
+
+       /* Realize the endpoint, interrupt is enabled later when
+        * buffers are queued, IN EPs will NAK until buffers are ready */
+       udc_realize_hwep(udc, ep->hwep_num, ep->ep.maxpacket);
+       udc_clr_buffer_hwep(udc, ep->hwep_num);
+       uda_disable_hwepint(udc, ep->hwep_num);
+       udc_clrstall_hwep(udc, ep->hwep_num);
+
+       /* Clear all DMA statuses for this EP */
+       udc_ep_dma_disable(udc, ep->hwep_num);
+       writel(1 << ep->hwep_num, USBD_EOTINTCLR(udc->udp_baseaddr));
+       writel(1 << ep->hwep_num, USBD_NDDRTINTCLR(udc->udp_baseaddr));
+       writel(1 << ep->hwep_num, USBD_SYSERRTINTCLR(udc->udp_baseaddr));
+       writel(1 << ep->hwep_num, USBD_DMARCLR(udc->udp_baseaddr));
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       atomic_inc(&udc->enabled_ep_cnt);
+       return 0;
+}
+
+/*
+ * Allocate a USB request list
+ * Can be called with or without lock
+ */
+static struct usb_request *lpc32xx_ep_alloc_request(struct usb_ep *_ep,
+                                                   gfp_t gfp_flags)
+{
+       struct lpc32xx_request *req;
+
+       req = kzalloc(sizeof(struct lpc32xx_request), gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+       return &req->req;
+}
+
+/*
+ * De-allocate a USB request list
+ * Can be called with or without lock
+ */
+static void lpc32xx_ep_free_request(struct usb_ep *_ep,
+                                   struct usb_request *_req)
+{
+       struct lpc32xx_request *req;
+
+       req = container_of(_req, struct lpc32xx_request, req);
+       BUG_ON(!list_empty(&req->queue));
+       kfree(req);
+}
+
+/* Must be called without lock */
+static int lpc32xx_ep_queue(struct usb_ep *_ep,
+                           struct usb_request *_req, gfp_t gfp_flags)
+{
+       struct lpc32xx_request *req;
+       struct lpc32xx_ep *ep;
+       struct lpc32xx_udc *udc;
+       unsigned long flags;
+       int status = 0;
+
+       req = container_of(_req, struct lpc32xx_request, req);
+       ep = container_of(_ep, struct lpc32xx_ep, ep);
+
+       if (!_req || !_req->complete || !_req->buf ||
+           !list_empty(&req->queue))
+               return -EINVAL;
+
+       udc = ep->udc;
+
+       if (!_ep) {
+               dev_dbg(udc->dev, "invalid ep\n");
+               return -EINVAL;
+       }
+
+
+       if ((!udc) || (!udc->driver) ||
+           (udc->gadget.speed == USB_SPEED_UNKNOWN)) {
+               dev_dbg(udc->dev, "invalid device\n");
+               return -EINVAL;
+       }
+
+       if (ep->lep) {
+               struct lpc32xx_usbd_dd_gad *dd;
+
+               status = usb_gadget_map_request(&udc->gadget, _req, ep->is_in);
+               if (status)
+                       return status;
+
+               /* For the request, build a list of DDs */
+               dd = udc_dd_alloc(udc);
+               if (!dd) {
+                       /* Error allocating DD */
+                       return -ENOMEM;
+               }
+               req->dd_desc_ptr = dd;
+
+               /* Setup the DMA descriptor */
+               dd->dd_next_phy = dd->dd_next_v = 0;
+               dd->dd_buffer_addr = req->req.dma;
+               dd->dd_status = 0;
+
+               /* Special handling for ISO EPs */
+               if (ep->eptype == EP_ISO_TYPE) {
+                       dd->dd_setup = DD_SETUP_ISO_EP |
+                               DD_SETUP_PACKETLEN(0) |
+                               DD_SETUP_DMALENBYTES(1);
+                       dd->dd_iso_ps_mem_addr = dd->this_dma + 24;
+                       if (ep->is_in)
+                               dd->iso_status[0] = req->req.length;
+                       else
+                               dd->iso_status[0] = 0;
+               } else
+                       dd->dd_setup = DD_SETUP_PACKETLEN(ep->ep.maxpacket) |
+                               DD_SETUP_DMALENBYTES(req->req.length);
+       }
+
+       ep_dbg(ep, "%s queue req %p len %d buf %p (in=%d) z=%d\n", _ep->name,
+              _req, _req->length, _req->buf, ep->is_in, _req->zero);
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+       req->send_zlp = _req->zero;
+
+       /* Kickstart empty queues */
+       if (list_empty(&ep->queue)) {
+               list_add_tail(&req->queue, &ep->queue);
+
+               if (ep->hwep_num_base == 0) {
+                       /* Handle expected data direction */
+                       if (ep->is_in) {
+                               /* IN packet to host */
+                               udc->ep0state = DATA_IN;
+                               status = udc_ep0_in_req(udc);
+                       } else {
+                               /* OUT packet from host */
+                               udc->ep0state = DATA_OUT;
+                               status = udc_ep0_out_req(udc);
+                       }
+               } else if (ep->is_in) {
+                       /* IN packet to host and kick off transfer */
+                       if (!ep->req_pending)
+                               udc_ep_in_req_dma(udc, ep);
+               } else
+                       /* OUT packet from host and kick off list */
+                       if (!ep->req_pending)
+                               udc_ep_out_req_dma(udc, ep);
+       } else
+               list_add_tail(&req->queue, &ep->queue);
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return (status < 0) ? status : 0;
+}
+
+/* Must be called without lock */
+static int lpc32xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct lpc32xx_ep *ep;
+       struct lpc32xx_request *req;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct lpc32xx_ep, ep);
+       if (!_ep || ep->hwep_num_base == 0)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req) {
+               spin_unlock_irqrestore(&ep->udc->lock, flags);
+               return -EINVAL;
+       }
+
+       done(ep, req, -ECONNRESET);
+
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+
+       return 0;
+}
+
+/* Must be called without lock */
+static int lpc32xx_ep_set_halt(struct usb_ep *_ep, int value)
+{
+       struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
+       struct lpc32xx_udc *udc = ep->udc;
+       unsigned long flags;
+
+       if ((!ep) || (ep->hwep_num <= 1))
+               return -EINVAL;
+
+       /* Don't halt an IN EP */
+       if (ep->is_in)
+               return -EAGAIN;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       if (value == 1) {
+               /* stall */
+               udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(ep->hwep_num),
+                                       DAT_WR_BYTE(EP_STAT_ST));
+       } else {
+               /* End stall */
+               ep->wedge = 0;
+               udc_protocol_cmd_data_w(udc, CMD_SET_EP_STAT(ep->hwep_num),
+                                       DAT_WR_BYTE(0));
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+/* set the halt feature and ignores clear requests */
+static int lpc32xx_ep_set_wedge(struct usb_ep *_ep)
+{
+       struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
+
+       if (!_ep || !ep->udc)
+               return -EINVAL;
+
+       ep->wedge = 1;
+
+       return usb_ep_set_halt(_ep);
+}
+
+static const struct usb_ep_ops lpc32xx_ep_ops = {
+       .enable         = lpc32xx_ep_enable,
+       .disable        = lpc32xx_ep_disable,
+       .alloc_request  = lpc32xx_ep_alloc_request,
+       .free_request   = lpc32xx_ep_free_request,
+       .queue          = lpc32xx_ep_queue,
+       .dequeue        = lpc32xx_ep_dequeue,
+       .set_halt       = lpc32xx_ep_set_halt,
+       .set_wedge      = lpc32xx_ep_set_wedge,
+};
+
+/* Send a ZLP on a non-0 IN EP */
+void udc_send_in_zlp(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
+{
+       /* Clear EP status */
+       udc_clearep_getsts(udc, ep->hwep_num);
+
+       /* Send ZLP via FIFO mechanism */
+       udc_write_hwep(udc, ep->hwep_num, NULL, 0);
+}
+
+/*
+ * Handle EP completion for ZLP
+ * This function will only be called when a delayed ZLP needs to be sent out
+ * after a DMA transfer has filled both buffers.
+ */
+void udc_handle_eps(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
+{
+       u32 epstatus;
+       struct lpc32xx_request *req;
+
+       if (ep->hwep_num <= 0)
+               return;
+
+       uda_clear_hwepint(udc, ep->hwep_num);
+
+       /* If this interrupt isn't enabled, return now */
+       if (!(udc->enabled_hwepints & (1 << ep->hwep_num)))
+               return;
+
+       /* Get endpoint status */
+       epstatus = udc_clearep_getsts(udc, ep->hwep_num);
+
+       /*
+        * This should never happen, but protect against writing to the
+        * buffer when full.
+        */
+       if (epstatus & EP_SEL_F)
+               return;
+
+       if (ep->is_in) {
+               udc_send_in_zlp(udc, ep);
+               uda_disable_hwepint(udc, ep->hwep_num);
+       } else
+               return;
+
+       /* If there isn't a request waiting, something went wrong */
+       req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
+       if (req) {
+               done(ep, req, 0);
+
+               /* Start another request if ready */
+               if (!list_empty(&ep->queue)) {
+                       if (ep->is_in)
+                               udc_ep_in_req_dma(udc, ep);
+                       else
+                               udc_ep_out_req_dma(udc, ep);
+               } else
+                       ep->req_pending = 0;
+       }
+}
+
+
+/* DMA end of transfer completion */
+static void udc_handle_dma_ep(struct lpc32xx_udc *udc, struct lpc32xx_ep *ep)
+{
+       u32 status, epstatus;
+       struct lpc32xx_request *req;
+       struct lpc32xx_usbd_dd_gad *dd;
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+       ep->totalints++;
+#endif
+
+       req = list_entry(ep->queue.next, struct lpc32xx_request, queue);
+       if (!req) {
+               ep_err(ep, "DMA interrupt on no req!\n");
+               return;
+       }
+       dd = req->dd_desc_ptr;
+
+       /* DMA descriptor should always be retired for this call */
+       if (!(dd->dd_status & DD_STATUS_DD_RETIRED))
+               ep_warn(ep, "DMA descriptor did not retire\n");
+
+       /* Disable DMA */
+       udc_ep_dma_disable(udc, ep->hwep_num);
+       writel((1 << ep->hwep_num), USBD_EOTINTCLR(udc->udp_baseaddr));
+       writel((1 << ep->hwep_num), USBD_NDDRTINTCLR(udc->udp_baseaddr));
+
+       /* System error? */
+       if (readl(USBD_SYSERRTINTST(udc->udp_baseaddr)) &
+           (1 << ep->hwep_num)) {
+               writel((1 << ep->hwep_num),
+                            USBD_SYSERRTINTCLR(udc->udp_baseaddr));
+               ep_err(ep, "AHB critical error!\n");
+               ep->req_pending = 0;
+
+               /* The error could have occurred on a packet of a multipacket
+                * transfer, so recovering the transfer is not possible. Close
+                * the request with an error */
+               done(ep, req, -ECONNABORTED);
+               return;
+       }
+
+       /* Handle the current DD's status */
+       status = dd->dd_status;
+       switch (status & DD_STATUS_STS_MASK) {
+       case DD_STATUS_STS_NS:
+               /* DD not serviced? This shouldn't happen! */
+               ep->req_pending = 0;
+               ep_err(ep, "DMA critical EP error: DD not serviced (0x%x)!\n",
+                      status);
+
+               done(ep, req, -ECONNABORTED);
+               return;
+
+       case DD_STATUS_STS_BS:
+               /* Interrupt only fires on EOT - This shouldn't happen! */
+               ep->req_pending = 0;
+               ep_err(ep, "DMA critical EP error: EOT prior to service completion (0x%x)!\n",
+                      status);
+               done(ep, req, -ECONNABORTED);
+               return;
+
+       case DD_STATUS_STS_NC:
+       case DD_STATUS_STS_DUR:
+               /* Really just a short packet, not an underrun */
+               /* This is a good status and what we expect */
+               break;
+
+       default:
+               /* Data overrun, system error, or unknown */
+               ep->req_pending = 0;
+               ep_err(ep, "DMA critical EP error: System error (0x%x)!\n",
+                      status);
+               done(ep, req, -ECONNABORTED);
+               return;
+       }
+
+       /* ISO endpoints are handled differently */
+       if (ep->eptype == EP_ISO_TYPE) {
+               if (ep->is_in)
+                       req->req.actual = req->req.length;
+               else
+                       req->req.actual = dd->iso_status[0] & 0xFFFF;
+       } else
+               req->req.actual += DD_STATUS_CURDMACNT(status);
+
+       /* Send a ZLP if necessary. This will be done for non-int
+        * packets which have a size that is a divisor of MAXP */
+       if (req->send_zlp) {
+               /*
+                * If at least 1 buffer is available, send the ZLP now.
+                * Otherwise, the ZLP send needs to be deferred until a
+                * buffer is available.
+                */
+               if (udc_clearep_getsts(udc, ep->hwep_num) & EP_SEL_F) {
+                       udc_clearep_getsts(udc, ep->hwep_num);
+                       uda_enable_hwepint(udc, ep->hwep_num);
+                       epstatus = udc_clearep_getsts(udc, ep->hwep_num);
+
+                       /* Let the EP interrupt handle the ZLP */
+                       return;
+               } else
+                       udc_send_in_zlp(udc, ep);
+       }
+
+       /* Transfer request is complete */
+       done(ep, req, 0);
+
+       /* Start another request if ready */
+       udc_clearep_getsts(udc, ep->hwep_num);
+       if (!list_empty((&ep->queue))) {
+               if (ep->is_in)
+                       udc_ep_in_req_dma(udc, ep);
+               else
+                       udc_ep_out_req_dma(udc, ep);
+       } else
+               ep->req_pending = 0;
+
+}
+
+/*
+ *
+ * Endpoint 0 functions
+ *
+ */
+static void udc_handle_dev(struct lpc32xx_udc *udc)
+{
+       u32 tmp;
+
+       udc_protocol_cmd_w(udc, CMD_GET_DEV_STAT);
+       tmp = udc_protocol_cmd_r(udc, DAT_GET_DEV_STAT);
+
+       if (tmp & DEV_RST)
+               uda_usb_reset(udc);
+       else if (tmp & DEV_CON_CH)
+               uda_power_event(udc, (tmp & DEV_CON));
+       else if (tmp & DEV_SUS_CH) {
+               if (tmp & DEV_SUS) {
+                       if (udc->vbus == 0)
+                               stop_activity(udc);
+                       else if ((udc->gadget.speed != USB_SPEED_UNKNOWN) &&
+                                udc->driver) {
+                               /* Power down transceiver */
+                               udc->poweron = 0;
+                               schedule_work(&udc->pullup_job);
+                               uda_resm_susp_event(udc, 1);
+                       }
+               } else if ((udc->gadget.speed != USB_SPEED_UNKNOWN) &&
+                          udc->driver && udc->vbus) {
+                       uda_resm_susp_event(udc, 0);
+                       /* Power up transceiver */
+                       udc->poweron = 1;
+                       schedule_work(&udc->pullup_job);
+               }
+       }
+}
+
+static int udc_get_status(struct lpc32xx_udc *udc, u16 reqtype, u16 wIndex)
+{
+       struct lpc32xx_ep *ep;
+       u32 ep0buff = 0, tmp;
+
+       switch (reqtype & USB_RECIP_MASK) {
+       case USB_RECIP_INTERFACE:
+               break; /* Not supported */
+
+       case USB_RECIP_DEVICE:
+               ep0buff = (udc->selfpowered << USB_DEVICE_SELF_POWERED);
+               if (udc->dev_status & (1 << USB_DEVICE_REMOTE_WAKEUP))
+                       ep0buff |= (1 << USB_DEVICE_REMOTE_WAKEUP);
+               break;
+
+       case USB_RECIP_ENDPOINT:
+               tmp = wIndex & USB_ENDPOINT_NUMBER_MASK;
+               ep = &udc->ep[tmp];
+               if ((tmp == 0) || (tmp >= NUM_ENDPOINTS))
+                       return -EOPNOTSUPP;
+
+               if (wIndex & USB_DIR_IN) {
+                       if (!ep->is_in)
+                               return -EOPNOTSUPP; /* Something's wrong */
+               } else if (ep->is_in)
+                       return -EOPNOTSUPP; /* Not an IN endpoint */
+
+               /* Get status of the endpoint */
+               udc_protocol_cmd_w(udc, CMD_SEL_EP(ep->hwep_num));
+               tmp = udc_protocol_cmd_r(udc, DAT_SEL_EP(ep->hwep_num));
+
+               if (tmp & EP_SEL_ST)
+                       ep0buff = (1 << USB_ENDPOINT_HALT);
+               else
+                       ep0buff = 0;
+               break;
+
+       default:
+               break;
+       }
+
+       /* Return data */
+       udc_write_hwep(udc, EP_IN, &ep0buff, 2);
+
+       return 0;
+}
+
+static void udc_handle_ep0_setup(struct lpc32xx_udc *udc)
+{
+       struct lpc32xx_ep *ep, *ep0 = &udc->ep[0];
+       struct usb_ctrlrequest ctrlpkt;
+       int i, bytes;
+       u16 wIndex, wValue, wLength, reqtype, req, tmp;
+
+       /* Nuke previous transfers */
+       nuke(ep0, -EPROTO);
+
+       /* Get setup packet */
+       bytes = udc_read_hwep(udc, EP_OUT, (u32 *) &ctrlpkt, 8);
+       if (bytes != 8) {
+               ep_warn(ep0, "Incorrectly sized setup packet (s/b 8, is %d)!\n",
+                       bytes);
+               return;
+       }
+
+       /* Native endianness */
+       wIndex = le16_to_cpu(ctrlpkt.wIndex);
+       wValue = le16_to_cpu(ctrlpkt.wValue);
+       wLength = le16_to_cpu(ctrlpkt.wLength);
+       reqtype = le16_to_cpu(ctrlpkt.bRequestType);
+
+       /* Set direction of EP0 */
+       if (likely(reqtype & USB_DIR_IN))
+               ep0->is_in = 1;
+       else
+               ep0->is_in = 0;
+
+       /* Handle SETUP packet */
+       req = le16_to_cpu(ctrlpkt.bRequest);
+       switch (req) {
+       case USB_REQ_CLEAR_FEATURE:
+       case USB_REQ_SET_FEATURE:
+               switch (reqtype) {
+               case (USB_TYPE_STANDARD | USB_RECIP_DEVICE):
+                       if (wValue != USB_DEVICE_REMOTE_WAKEUP)
+                               goto stall; /* Nothing else handled */
+
+                       /* Tell board about event */
+                       if (req == USB_REQ_CLEAR_FEATURE)
+                               udc->dev_status &=
+                                       ~(1 << USB_DEVICE_REMOTE_WAKEUP);
+                       else
+                               udc->dev_status |=
+                                       (1 << USB_DEVICE_REMOTE_WAKEUP);
+                       uda_remwkp_cgh(udc);
+                       goto zlp_send;
+
+               case (USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
+                       tmp = wIndex & USB_ENDPOINT_NUMBER_MASK;
+                       if ((wValue != USB_ENDPOINT_HALT) ||
+                           (tmp >= NUM_ENDPOINTS))
+                               break;
+
+                       /* Find hardware endpoint from logical endpoint */
+                       ep = &udc->ep[tmp];
+                       tmp = ep->hwep_num;
+                       if (tmp == 0)
+                               break;
+
+                       if (req == USB_REQ_SET_FEATURE)
+                               udc_stall_hwep(udc, tmp);
+                       else if (!ep->wedge)
+                               udc_clrstall_hwep(udc, tmp);
+
+                       goto zlp_send;
+
+               default:
+                       break;
+               }
+
+
+       case USB_REQ_SET_ADDRESS:
+               if (reqtype == (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) {
+                       udc_set_address(udc, wValue);
+                       goto zlp_send;
+               }
+               break;
+
+       case USB_REQ_GET_STATUS:
+               udc_get_status(udc, reqtype, wIndex);
+               return;
+
+       default:
+               break; /* Let GadgetFS handle the descriptor instead */
+       }
+
+       if (likely(udc->driver)) {
+               /* device-2-host (IN) or no data setup command, process
+                * immediately */
+               spin_unlock(&udc->lock);
+               i = udc->driver->setup(&udc->gadget, &ctrlpkt);
+
+               spin_lock(&udc->lock);
+               if (req == USB_REQ_SET_CONFIGURATION) {
+                       /* Configuration is set after endpoints are realized */
+                       if (wValue) {
+                               /* Set configuration */
+                               udc_set_device_configured(udc);
+
+                               udc_protocol_cmd_data_w(udc, CMD_SET_MODE,
+                                                       DAT_WR_BYTE(AP_CLK |
+                                                       INAK_BI | INAK_II));
+                       } else {
+                               /* Clear configuration */
+                               udc_set_device_unconfigured(udc);
+
+                               /* Disable NAK interrupts */
+                               udc_protocol_cmd_data_w(udc, CMD_SET_MODE,
+                                                       DAT_WR_BYTE(AP_CLK));
+                       }
+               }
+
+               if (i < 0) {
+                       /* setup processing failed, force stall */
+                       dev_dbg(udc->dev,
+                               "req %02x.%02x protocol STALL; stat %d\n",
+                               reqtype, req, i);
+                       udc->ep0state = WAIT_FOR_SETUP;
+                       goto stall;
+               }
+       }
+
+       if (!ep0->is_in)
+               udc_ep0_send_zlp(udc); /* ZLP IN packet on data phase */
+
+       return;
+
+stall:
+       udc_stall_hwep(udc, EP_IN);
+       return;
+
+zlp_send:
+       udc_ep0_send_zlp(udc);
+       return;
+}
+
+/* IN endpoint 0 transfer */
+static void udc_handle_ep0_in(struct lpc32xx_udc *udc)
+{
+       struct lpc32xx_ep *ep0 = &udc->ep[0];
+       u32 epstatus;
+
+       /* Clear EP interrupt */
+       epstatus = udc_clearep_getsts(udc, EP_IN);
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+       ep0->totalints++;
+#endif
+
+       /* Stalled? Clear stall and reset buffers */
+       if (epstatus & EP_SEL_ST) {
+               udc_clrstall_hwep(udc, EP_IN);
+               nuke(ep0, -ECONNABORTED);
+               udc->ep0state = WAIT_FOR_SETUP;
+               return;
+       }
+
+       /* Is a buffer available? */
+       if (!(epstatus & EP_SEL_F)) {
+               /* Handle based on current state */
+               if (udc->ep0state == DATA_IN)
+                       udc_ep0_in_req(udc);
+               else {
+                       /* Unknown state for EP0 oe end of DATA IN phase */
+                       nuke(ep0, -ECONNABORTED);
+                       udc->ep0state = WAIT_FOR_SETUP;
+               }
+       }
+}
+
+/* OUT endpoint 0 transfer */
+static void udc_handle_ep0_out(struct lpc32xx_udc *udc)
+{
+       struct lpc32xx_ep *ep0 = &udc->ep[0];
+       u32 epstatus;
+
+       /* Clear EP interrupt */
+       epstatus = udc_clearep_getsts(udc, EP_OUT);
+
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+       ep0->totalints++;
+#endif
+
+       /* Stalled? */
+       if (epstatus & EP_SEL_ST) {
+               udc_clrstall_hwep(udc, EP_OUT);
+               nuke(ep0, -ECONNABORTED);
+               udc->ep0state = WAIT_FOR_SETUP;
+               return;
+       }
+
+       /* A NAK may occur if a packet couldn't be received yet */
+       if (epstatus & EP_SEL_EPN)
+               return;
+       /* Setup packet incoming? */
+       if (epstatus & EP_SEL_STP) {
+               nuke(ep0, 0);
+               udc->ep0state = WAIT_FOR_SETUP;
+       }
+
+       /* Data available? */
+       if (epstatus & EP_SEL_F)
+               /* Handle based on current state */
+               switch (udc->ep0state) {
+               case WAIT_FOR_SETUP:
+                       udc_handle_ep0_setup(udc);
+                       break;
+
+               case DATA_OUT:
+                       udc_ep0_out_req(udc);
+                       break;
+
+               default:
+                       /* Unknown state for EP0 */
+                       nuke(ep0, -ECONNABORTED);
+                       udc->ep0state = WAIT_FOR_SETUP;
+               }
+}
+
+/* Must be called without lock */
+static int lpc32xx_get_frame(struct usb_gadget *gadget)
+{
+       int frame;
+       unsigned long flags;
+       struct lpc32xx_udc *udc = to_udc(gadget);
+
+       if (!udc->clocked)
+               return -EINVAL;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       frame = (int) udc_get_current_frame(udc);
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return frame;
+}
+
+static int lpc32xx_wakeup(struct usb_gadget *gadget)
+{
+       return -ENOTSUPP;
+}
+
+static int lpc32xx_set_selfpowered(struct usb_gadget *gadget, int is_on)
+{
+       struct lpc32xx_udc *udc = to_udc(gadget);
+
+       /* Always self-powered */
+       udc->selfpowered = (is_on != 0);
+
+       return 0;
+}
+
+/*
+ * vbus is here!  turn everything on that's ready
+ * Must be called without lock
+ */
+static int lpc32xx_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+       unsigned long flags;
+       struct lpc32xx_udc *udc = to_udc(gadget);
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /* Doesn't need lock */
+       if (udc->driver) {
+               udc_clk_set(udc, 1);
+               udc_enable(udc);
+               pullup(udc, is_active);
+       } else {
+               stop_activity(udc);
+               pullup(udc, 0);
+
+               spin_unlock_irqrestore(&udc->lock, flags);
+               /*
+                *  Wait for all the endpoints to disable,
+                *  before disabling clocks. Don't wait if
+                *  endpoints are not enabled.
+                */
+               if (atomic_read(&udc->enabled_ep_cnt))
+                       wait_event_interruptible(udc->ep_disable_wait_queue,
+                                (atomic_read(&udc->enabled_ep_cnt) == 0));
+
+               spin_lock_irqsave(&udc->lock, flags);
+
+               udc_clk_set(udc, 0);
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+/* Can be called with or without lock */
+static int lpc32xx_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct lpc32xx_udc *udc = to_udc(gadget);
+
+       /* Doesn't need lock */
+       pullup(udc, is_on);
+
+       return 0;
+}
+
+static int lpc32xx_start(struct usb_gadget *, struct usb_gadget_driver *);
+static int lpc32xx_stop(struct usb_gadget *, struct usb_gadget_driver *);
+
+static const struct usb_gadget_ops lpc32xx_udc_ops = {
+       .get_frame              = lpc32xx_get_frame,
+       .wakeup                 = lpc32xx_wakeup,
+       .set_selfpowered        = lpc32xx_set_selfpowered,
+       .vbus_session           = lpc32xx_vbus_session,
+       .pullup                 = lpc32xx_pullup,
+       .udc_start              = lpc32xx_start,
+       .udc_stop               = lpc32xx_stop,
+};
+
+static void nop_release(struct device *dev)
+{
+       /* nothing to free */
+}
+
+static const struct lpc32xx_udc controller_template = {
+       .gadget = {
+               .ops    = &lpc32xx_udc_ops,
+               .name   = driver_name,
+               .dev    = {
+                       .init_name = "gadget",
+                       .release = nop_release,
+               }
+       },
+       .ep[0] = {
+               .ep = {
+                       .name   = "ep0",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 64,
+               .hwep_num_base  = 0,
+               .hwep_num       = 0, /* Can be 0 or 1, has special handling */
+               .lep            = 0,
+               .eptype         = EP_CTL_TYPE,
+       },
+       .ep[1] = {
+               .ep = {
+                       .name   = "ep1-int",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 64,
+               .hwep_num_base  = 2,
+               .hwep_num       = 0, /* 2 or 3, will be set later */
+               .lep            = 1,
+               .eptype         = EP_INT_TYPE,
+       },
+       .ep[2] = {
+               .ep = {
+                       .name   = "ep2-bulk",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 64,
+               .hwep_num_base  = 4,
+               .hwep_num       = 0, /* 4 or 5, will be set later */
+               .lep            = 2,
+               .eptype         = EP_BLK_TYPE,
+       },
+       .ep[3] = {
+               .ep = {
+                       .name   = "ep3-iso",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 1023,
+               .hwep_num_base  = 6,
+               .hwep_num       = 0, /* 6 or 7, will be set later */
+               .lep            = 3,
+               .eptype         = EP_ISO_TYPE,
+       },
+       .ep[4] = {
+               .ep = {
+                       .name   = "ep4-int",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 64,
+               .hwep_num_base  = 8,
+               .hwep_num       = 0, /* 8 or 9, will be set later */
+               .lep            = 4,
+               .eptype         = EP_INT_TYPE,
+       },
+       .ep[5] = {
+               .ep = {
+                       .name   = "ep5-bulk",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 64,
+               .hwep_num_base  = 10,
+               .hwep_num       = 0, /* 10 or 11, will be set later */
+               .lep            = 5,
+               .eptype         = EP_BLK_TYPE,
+       },
+       .ep[6] = {
+               .ep = {
+                       .name   = "ep6-iso",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 1023,
+               .hwep_num_base  = 12,
+               .hwep_num       = 0, /* 12 or 13, will be set later */
+               .lep            = 6,
+               .eptype         = EP_ISO_TYPE,
+       },
+       .ep[7] = {
+               .ep = {
+                       .name   = "ep7-int",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 64,
+               .hwep_num_base  = 14,
+               .hwep_num       = 0,
+               .lep            = 7,
+               .eptype         = EP_INT_TYPE,
+       },
+       .ep[8] = {
+               .ep = {
+                       .name   = "ep8-bulk",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 64,
+               .hwep_num_base  = 16,
+               .hwep_num       = 0,
+               .lep            = 8,
+               .eptype         = EP_BLK_TYPE,
+       },
+       .ep[9] = {
+               .ep = {
+                       .name   = "ep9-iso",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 1023,
+               .hwep_num_base  = 18,
+               .hwep_num       = 0,
+               .lep            = 9,
+               .eptype         = EP_ISO_TYPE,
+       },
+       .ep[10] = {
+               .ep = {
+                       .name   = "ep10-int",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 64,
+               .hwep_num_base  = 20,
+               .hwep_num       = 0,
+               .lep            = 10,
+               .eptype         = EP_INT_TYPE,
+       },
+       .ep[11] = {
+               .ep = {
+                       .name   = "ep11-bulk",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 64,
+               .hwep_num_base  = 22,
+               .hwep_num       = 0,
+               .lep            = 11,
+               .eptype         = EP_BLK_TYPE,
+       },
+       .ep[12] = {
+               .ep = {
+                       .name   = "ep12-iso",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 1023,
+               .hwep_num_base  = 24,
+               .hwep_num       = 0,
+               .lep            = 12,
+               .eptype         = EP_ISO_TYPE,
+       },
+       .ep[13] = {
+               .ep = {
+                       .name   = "ep13-int",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 64,
+               .hwep_num_base  = 26,
+               .hwep_num       = 0,
+               .lep            = 13,
+               .eptype         = EP_INT_TYPE,
+       },
+       .ep[14] = {
+               .ep = {
+                       .name   = "ep14-bulk",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 64,
+               .hwep_num_base  = 28,
+               .hwep_num       = 0,
+               .lep            = 14,
+               .eptype         = EP_BLK_TYPE,
+       },
+       .ep[15] = {
+               .ep = {
+                       .name   = "ep15-bulk",
+                       .ops    = &lpc32xx_ep_ops,
+               },
+               .maxpacket      = 1023,
+               .hwep_num_base  = 30,
+               .hwep_num       = 0,
+               .lep            = 15,
+               .eptype         = EP_BLK_TYPE,
+       },
+};
+
+/* ISO and status interrupts */
+static irqreturn_t lpc32xx_usb_lp_irq(int irq, void *_udc)
+{
+       u32 tmp, devstat;
+       struct lpc32xx_udc *udc = _udc;
+
+       spin_lock(&udc->lock);
+
+       /* Read the device status register */
+       devstat = readl(USBD_DEVINTST(udc->udp_baseaddr));
+
+       devstat &= ~USBD_EP_FAST;
+       writel(devstat, USBD_DEVINTCLR(udc->udp_baseaddr));
+       devstat = devstat & udc->enabled_devints;
+
+       /* Device specific handling needed? */
+       if (devstat & USBD_DEV_STAT)
+               udc_handle_dev(udc);
+
+       /* Start of frame? (devstat & FRAME_INT):
+        * The frame interrupt isn't really needed for ISO support,
+        * as the driver will queue the necessary packets */
+
+       /* Error? */
+       if (devstat & ERR_INT) {
+               /* All types of errors, from cable removal during transfer to
+                * misc protocol and bit errors. These are mostly for just info,
+                * as the USB hardware will work around these. If these errors
+                * happen alot, something is wrong. */
+               udc_protocol_cmd_w(udc, CMD_RD_ERR_STAT);
+               tmp = udc_protocol_cmd_r(udc, DAT_RD_ERR_STAT);
+               dev_dbg(udc->dev, "Device error (0x%x)!\n", tmp);
+       }
+
+       spin_unlock(&udc->lock);
+
+       return IRQ_HANDLED;
+}
+
+/* EP interrupts */
+static irqreturn_t lpc32xx_usb_hp_irq(int irq, void *_udc)
+{
+       u32 tmp;
+       struct lpc32xx_udc *udc = _udc;
+
+       spin_lock(&udc->lock);
+
+       /* Read the device status register */
+       writel(USBD_EP_FAST, USBD_DEVINTCLR(udc->udp_baseaddr));
+
+       /* Endpoints */
+       tmp = readl(USBD_EPINTST(udc->udp_baseaddr));
+
+       /* Special handling for EP0 */
+       if (tmp & (EP_MASK_SEL(0, EP_OUT) | EP_MASK_SEL(0, EP_IN))) {
+               /* Handle EP0 IN */
+               if (tmp & (EP_MASK_SEL(0, EP_IN)))
+                       udc_handle_ep0_in(udc);
+
+               /* Handle EP0 OUT */
+               if (tmp & (EP_MASK_SEL(0, EP_OUT)))
+                       udc_handle_ep0_out(udc);
+       }
+
+       /* All other EPs */
+       if (tmp & ~(EP_MASK_SEL(0, EP_OUT) | EP_MASK_SEL(0, EP_IN))) {
+               int i;
+
+               /* Handle other EP interrupts */
+               for (i = 1; i < NUM_ENDPOINTS; i++) {
+                       if (tmp & (1 << udc->ep[i].hwep_num))
+                               udc_handle_eps(udc, &udc->ep[i]);
+               }
+       }
+
+       spin_unlock(&udc->lock);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t lpc32xx_usb_devdma_irq(int irq, void *_udc)
+{
+       struct lpc32xx_udc *udc = _udc;
+
+       int i;
+       u32 tmp;
+
+       spin_lock(&udc->lock);
+
+       /* Handle EP DMA EOT interrupts */
+       tmp = readl(USBD_EOTINTST(udc->udp_baseaddr)) |
+               (readl(USBD_EPDMAST(udc->udp_baseaddr)) &
+                readl(USBD_NDDRTINTST(udc->udp_baseaddr))) |
+               readl(USBD_SYSERRTINTST(udc->udp_baseaddr));
+       for (i = 1; i < NUM_ENDPOINTS; i++) {
+               if (tmp & (1 << udc->ep[i].hwep_num))
+                       udc_handle_dma_ep(udc, &udc->ep[i]);
+       }
+
+       spin_unlock(&udc->lock);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ *
+ * VBUS detection, pullup handler, and Gadget cable state notification
+ *
+ */
+static void vbus_work(struct work_struct *work)
+{
+       u8 value;
+       struct lpc32xx_udc *udc = container_of(work, struct lpc32xx_udc,
+                                              vbus_job);
+
+       if (udc->enabled != 0) {
+               /* Discharge VBUS real quick */
+               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+                       ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DISCHRG);
+
+               /* Give VBUS some time (100mS) to discharge */
+               msleep(100);
+
+               /* Disable VBUS discharge resistor */
+               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+                       ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
+                       OTG1_VBUS_DISCHRG);
+
+               /* Clear interrupt */
+               i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+                       ISP1301_I2C_INTERRUPT_LATCH |
+                       ISP1301_I2C_REG_CLEAR_ADDR, ~0);
+
+               /* Get the VBUS status from the transceiver */
+               value = i2c_smbus_read_byte_data(udc->isp1301_i2c_client,
+                                                ISP1301_I2C_INTERRUPT_SOURCE);
+
+               /* VBUS on or off? */
+               if (value & INT_SESS_VLD)
+                       udc->vbus = 1;
+               else
+                       udc->vbus = 0;
+
+               /* VBUS changed? */
+               if (udc->last_vbus != udc->vbus) {
+                       udc->last_vbus = udc->vbus;
+                       lpc32xx_vbus_session(&udc->gadget, udc->vbus);
+               }
+       }
+
+       /* Re-enable after completion */
+       enable_irq(udc->udp_irq[IRQ_USB_ATX]);
+}
+
+static irqreturn_t lpc32xx_usb_vbus_irq(int irq, void *_udc)
+{
+       struct lpc32xx_udc *udc = _udc;
+
+       /* Defer handling of VBUS IRQ to work queue */
+       disable_irq_nosync(udc->udp_irq[IRQ_USB_ATX]);
+       schedule_work(&udc->vbus_job);
+
+       return IRQ_HANDLED;
+}
+
+static int lpc32xx_start(struct usb_gadget *gadget,
+                        struct usb_gadget_driver *driver)
+{
+       struct lpc32xx_udc *udc = to_udc(gadget);
+       int i;
+
+       if (!driver || driver->max_speed < USB_SPEED_FULL || !driver->setup) {
+               dev_err(udc->dev, "bad parameter.\n");
+               return -EINVAL;
+       }
+
+       if (udc->driver) {
+               dev_err(udc->dev, "UDC already has a gadget driver\n");
+               return -EBUSY;
+       }
+
+       udc->driver = driver;
+       udc->gadget.dev.of_node = udc->dev->of_node;
+       udc->enabled = 1;
+       udc->selfpowered = 1;
+       udc->vbus = 0;
+
+       /* Force VBUS process once to check for cable insertion */
+       udc->last_vbus = udc->vbus = 0;
+       schedule_work(&udc->vbus_job);
+
+       /* Do not re-enable ATX IRQ (3) */
+       for (i = IRQ_USB_LP; i < IRQ_USB_ATX; i++)
+               enable_irq(udc->udp_irq[i]);
+
+       return 0;
+}
+
+static int lpc32xx_stop(struct usb_gadget *gadget,
+                       struct usb_gadget_driver *driver)
+{
+       int i;
+       struct lpc32xx_udc *udc = to_udc(gadget);
+
+       if (!driver || driver != udc->driver)
+               return -EINVAL;
+
+       for (i = IRQ_USB_LP; i <= IRQ_USB_ATX; i++)
+               disable_irq(udc->udp_irq[i]);
+
+       if (udc->clocked) {
+               spin_lock(&udc->lock);
+               stop_activity(udc);
+               spin_unlock(&udc->lock);
+
+               /*
+                *  Wait for all the endpoints to disable,
+                *  before disabling clocks. Don't wait if
+                *  endpoints are not enabled.
+                */
+               if (atomic_read(&udc->enabled_ep_cnt))
+                       wait_event_interruptible(udc->ep_disable_wait_queue,
+                               (atomic_read(&udc->enabled_ep_cnt) == 0));
+
+               spin_lock(&udc->lock);
+               udc_clk_set(udc, 0);
+               spin_unlock(&udc->lock);
+       }
+
+       udc->enabled = 0;
+       udc->driver = NULL;
+
+       return 0;
+}
+
+static void lpc32xx_udc_shutdown(struct platform_device *dev)
+{
+       /* Force disconnect on reboot */
+       struct lpc32xx_udc *udc = platform_get_drvdata(dev);
+
+       pullup(udc, 0);
+}
+
+/*
+ * Callbacks to be overridden by options passed via OF (TODO)
+ */
+
+static void lpc32xx_usbd_conn_chg(int conn)
+{
+       /* Do nothing, it might be nice to enable an LED
+        * based on conn state being !0 */
+}
+
+static void lpc32xx_usbd_susp_chg(int susp)
+{
+       /* Device suspend if susp != 0 */
+}
+
+static void lpc32xx_rmwkup_chg(int remote_wakup_enable)
+{
+       /* Enable or disable USB remote wakeup */
+}
+
+struct lpc32xx_usbd_cfg lpc32xx_usbddata = {
+       .vbus_drv_pol = 0,
+       .conn_chgb = &lpc32xx_usbd_conn_chg,
+       .susp_chgb = &lpc32xx_usbd_susp_chg,
+       .rmwk_chgb = &lpc32xx_rmwkup_chg,
+};
+
+
+static u64 lpc32xx_usbd_dmamask = ~(u32) 0x7F;
+
+static int lpc32xx_udc_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct lpc32xx_udc *udc;
+       int retval, i;
+       struct resource *res;
+       dma_addr_t dma_handle;
+       struct device_node *isp1301_node;
+
+       udc = kmemdup(&controller_template, sizeof(*udc), GFP_KERNEL);
+       if (!udc)
+               return -ENOMEM;
+
+       for (i = 0; i <= 15; i++)
+               udc->ep[i].udc = udc;
+       udc->gadget.ep0 = &udc->ep[0].ep;
+
+       /* init software state */
+       udc->gadget.dev.parent = dev;
+       udc->pdev = pdev;
+       udc->dev = &pdev->dev;
+       udc->enabled = 0;
+
+       if (pdev->dev.of_node) {
+               isp1301_node = of_parse_phandle(pdev->dev.of_node,
+                                               "transceiver", 0);
+       } else {
+               isp1301_node = NULL;
+       }
+
+       udc->isp1301_i2c_client = isp1301_get_client(isp1301_node);
+       if (!udc->isp1301_i2c_client) {
+               retval = -EPROBE_DEFER;
+               goto phy_fail;
+       }
+
+       dev_info(udc->dev, "ISP1301 I2C device at address 0x%x\n",
+                udc->isp1301_i2c_client->addr);
+
+       pdev->dev.dma_mask = &lpc32xx_usbd_dmamask;
+       retval = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       if (retval)
+               goto resource_fail;
+
+       udc->board = &lpc32xx_usbddata;
+
+       /*
+        * Resources are mapped as follows:
+        *  IORESOURCE_MEM, base address and size of USB space
+        *  IORESOURCE_IRQ, USB device low priority interrupt number
+        *  IORESOURCE_IRQ, USB device high priority interrupt number
+        *  IORESOURCE_IRQ, USB device interrupt number
+        *  IORESOURCE_IRQ, USB transceiver interrupt number
+        */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               retval = -ENXIO;
+               goto resource_fail;
+       }
+
+       spin_lock_init(&udc->lock);
+
+       /* Get IRQs */
+       for (i = 0; i < 4; i++) {
+               udc->udp_irq[i] = platform_get_irq(pdev, i);
+               if (udc->udp_irq[i] < 0) {
+                       dev_err(udc->dev,
+                               "irq resource %d not available!\n", i);
+                       retval = udc->udp_irq[i];
+                       goto irq_fail;
+               }
+       }
+
+       udc->io_p_start = res->start;
+       udc->io_p_size = resource_size(res);
+       if (!request_mem_region(udc->io_p_start, udc->io_p_size, driver_name)) {
+               dev_err(udc->dev, "someone's using UDC memory\n");
+               retval = -EBUSY;
+               goto request_mem_region_fail;
+       }
+
+       udc->udp_baseaddr = ioremap(udc->io_p_start, udc->io_p_size);
+       if (!udc->udp_baseaddr) {
+               retval = -ENOMEM;
+               dev_err(udc->dev, "IO map failure\n");
+               goto io_map_fail;
+       }
+
+       /* Enable AHB slave USB clock, needed for further USB clock control */
+       writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL);
+
+       /* Get required clocks */
+       udc->usb_pll_clk = clk_get(&pdev->dev, "ck_pll5");
+       if (IS_ERR(udc->usb_pll_clk)) {
+               dev_err(udc->dev, "failed to acquire USB PLL\n");
+               retval = PTR_ERR(udc->usb_pll_clk);
+               goto pll_get_fail;
+       }
+       udc->usb_slv_clk = clk_get(&pdev->dev, "ck_usbd");
+       if (IS_ERR(udc->usb_slv_clk)) {
+               dev_err(udc->dev, "failed to acquire USB device clock\n");
+               retval = PTR_ERR(udc->usb_slv_clk);
+               goto usb_clk_get_fail;
+       }
+       udc->usb_otg_clk = clk_get(&pdev->dev, "ck_usb_otg");
+       if (IS_ERR(udc->usb_otg_clk)) {
+               dev_err(udc->dev, "failed to acquire USB otg clock\n");
+               retval = PTR_ERR(udc->usb_otg_clk);
+               goto usb_otg_clk_get_fail;
+       }
+
+       /* Setup PLL clock to 48MHz */
+       retval = clk_enable(udc->usb_pll_clk);
+       if (retval < 0) {
+               dev_err(udc->dev, "failed to start USB PLL\n");
+               goto pll_enable_fail;
+       }
+
+       retval = clk_set_rate(udc->usb_pll_clk, 48000);
+       if (retval < 0) {
+               dev_err(udc->dev, "failed to set USB clock rate\n");
+               goto pll_set_fail;
+       }
+
+       writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN, USB_CTRL);
+
+       /* Enable USB device clock */
+       retval = clk_enable(udc->usb_slv_clk);
+       if (retval < 0) {
+               dev_err(udc->dev, "failed to start USB device clock\n");
+               goto usb_clk_enable_fail;
+       }
+
+       /* Enable USB OTG clock */
+       retval = clk_enable(udc->usb_otg_clk);
+       if (retval < 0) {
+               dev_err(udc->dev, "failed to start USB otg clock\n");
+               goto usb_otg_clk_enable_fail;
+       }
+
+       /* Setup deferred workqueue data */
+       udc->poweron = udc->pullup = 0;
+       INIT_WORK(&udc->pullup_job, pullup_work);
+       INIT_WORK(&udc->vbus_job, vbus_work);
+#ifdef CONFIG_PM
+       INIT_WORK(&udc->power_job, power_work);
+#endif
+
+       /* All clocks are now on */
+       udc->clocked = 1;
+
+       isp1301_udc_configure(udc);
+       /* Allocate memory for the UDCA */
+       udc->udca_v_base = dma_alloc_coherent(&pdev->dev, UDCA_BUFF_SIZE,
+                                             &dma_handle,
+                                             (GFP_KERNEL | GFP_DMA));
+       if (!udc->udca_v_base) {
+               dev_err(udc->dev, "error getting UDCA region\n");
+               retval = -ENOMEM;
+               goto i2c_fail;
+       }
+       udc->udca_p_base = dma_handle;
+       dev_dbg(udc->dev, "DMA buffer(0x%x bytes), P:0x%08x, V:0x%p\n",
+               UDCA_BUFF_SIZE, udc->udca_p_base, udc->udca_v_base);
+
+       /* Setup the DD DMA memory pool */
+       udc->dd_cache = dma_pool_create("udc_dd", udc->dev,
+                                       sizeof(struct lpc32xx_usbd_dd_gad),
+                                       sizeof(u32), 0);
+       if (!udc->dd_cache) {
+               dev_err(udc->dev, "error getting DD DMA region\n");
+               retval = -ENOMEM;
+               goto dma_alloc_fail;
+       }
+
+       /* Clear USB peripheral and initialize gadget endpoints */
+       udc_disable(udc);
+       udc_reinit(udc);
+
+       /* Request IRQs - low and high priority USB device IRQs are routed to
+        * the same handler, while the DMA interrupt is routed elsewhere */
+       retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq,
+                            0, "udc_lp", udc);
+       if (retval < 0) {
+               dev_err(udc->dev, "LP request irq %d failed\n",
+                       udc->udp_irq[IRQ_USB_LP]);
+               goto irq_lp_fail;
+       }
+       retval = request_irq(udc->udp_irq[IRQ_USB_HP], lpc32xx_usb_hp_irq,
+                            0, "udc_hp", udc);
+       if (retval < 0) {
+               dev_err(udc->dev, "HP request irq %d failed\n",
+                       udc->udp_irq[IRQ_USB_HP]);
+               goto irq_hp_fail;
+       }
+
+       retval = request_irq(udc->udp_irq[IRQ_USB_DEVDMA],
+                            lpc32xx_usb_devdma_irq, 0, "udc_dma", udc);
+       if (retval < 0) {
+               dev_err(udc->dev, "DEV request irq %d failed\n",
+                       udc->udp_irq[IRQ_USB_DEVDMA]);
+               goto irq_dev_fail;
+       }
+
+       /* The transceiver interrupt is used for VBUS detection and will
+          kick off the VBUS handler function */
+       retval = request_irq(udc->udp_irq[IRQ_USB_ATX], lpc32xx_usb_vbus_irq,
+                            0, "udc_otg", udc);
+       if (retval < 0) {
+               dev_err(udc->dev, "VBUS request irq %d failed\n",
+                       udc->udp_irq[IRQ_USB_ATX]);
+               goto irq_xcvr_fail;
+       }
+
+       /* Initialize wait queue */
+       init_waitqueue_head(&udc->ep_disable_wait_queue);
+       atomic_set(&udc->enabled_ep_cnt, 0);
+
+       /* Keep all IRQs disabled until GadgetFS starts up */
+       for (i = IRQ_USB_LP; i <= IRQ_USB_ATX; i++)
+               disable_irq(udc->udp_irq[i]);
+
+       retval = usb_add_gadget_udc(dev, &udc->gadget);
+       if (retval < 0)
+               goto add_gadget_fail;
+
+       dev_set_drvdata(dev, udc);
+       device_init_wakeup(dev, 1);
+       create_debug_file(udc);
+
+       /* Disable clocks for now */
+       udc_clk_set(udc, 0);
+
+       dev_info(udc->dev, "%s version %s\n", driver_name, DRIVER_VERSION);
+       return 0;
+
+add_gadget_fail:
+       free_irq(udc->udp_irq[IRQ_USB_ATX], udc);
+irq_xcvr_fail:
+       free_irq(udc->udp_irq[IRQ_USB_DEVDMA], udc);
+irq_dev_fail:
+       free_irq(udc->udp_irq[IRQ_USB_HP], udc);
+irq_hp_fail:
+       free_irq(udc->udp_irq[IRQ_USB_LP], udc);
+irq_lp_fail:
+       dma_pool_destroy(udc->dd_cache);
+dma_alloc_fail:
+       dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
+                         udc->udca_v_base, udc->udca_p_base);
+i2c_fail:
+       clk_disable(udc->usb_otg_clk);
+usb_otg_clk_enable_fail:
+       clk_disable(udc->usb_slv_clk);
+usb_clk_enable_fail:
+pll_set_fail:
+       clk_disable(udc->usb_pll_clk);
+pll_enable_fail:
+       clk_put(udc->usb_otg_clk);
+usb_otg_clk_get_fail:
+       clk_put(udc->usb_slv_clk);
+usb_clk_get_fail:
+       clk_put(udc->usb_pll_clk);
+pll_get_fail:
+       iounmap(udc->udp_baseaddr);
+io_map_fail:
+       release_mem_region(udc->io_p_start, udc->io_p_size);
+       dev_err(udc->dev, "%s probe failed, %d\n", driver_name, retval);
+request_mem_region_fail:
+irq_fail:
+resource_fail:
+phy_fail:
+       kfree(udc);
+       return retval;
+}
+
+static int lpc32xx_udc_remove(struct platform_device *pdev)
+{
+       struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
+
+       usb_del_gadget_udc(&udc->gadget);
+       if (udc->driver)
+               return -EBUSY;
+
+       udc_clk_set(udc, 1);
+       udc_disable(udc);
+       pullup(udc, 0);
+
+       free_irq(udc->udp_irq[IRQ_USB_ATX], udc);
+
+       device_init_wakeup(&pdev->dev, 0);
+       remove_debug_file(udc);
+
+       dma_pool_destroy(udc->dd_cache);
+       dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
+                         udc->udca_v_base, udc->udca_p_base);
+       free_irq(udc->udp_irq[IRQ_USB_DEVDMA], udc);
+       free_irq(udc->udp_irq[IRQ_USB_HP], udc);
+       free_irq(udc->udp_irq[IRQ_USB_LP], udc);
+
+       clk_disable(udc->usb_otg_clk);
+       clk_put(udc->usb_otg_clk);
+       clk_disable(udc->usb_slv_clk);
+       clk_put(udc->usb_slv_clk);
+       clk_disable(udc->usb_pll_clk);
+       clk_put(udc->usb_pll_clk);
+       iounmap(udc->udp_baseaddr);
+       release_mem_region(udc->io_p_start, udc->io_p_size);
+       kfree(udc);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int lpc32xx_udc_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+       struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
+
+       if (udc->clocked) {
+               /* Power down ISP */
+               udc->poweron = 0;
+               isp1301_set_powerstate(udc, 0);
+
+               /* Disable clocking */
+               udc_clk_set(udc, 0);
+
+               /* Keep clock flag on, so we know to re-enable clocks
+                  on resume */
+               udc->clocked = 1;
+
+               /* Kill global USB clock */
+               clk_disable(udc->usb_slv_clk);
+       }
+
+       return 0;
+}
+
+static int lpc32xx_udc_resume(struct platform_device *pdev)
+{
+       struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
+
+       if (udc->clocked) {
+               /* Enable global USB clock */
+               clk_enable(udc->usb_slv_clk);
+
+               /* Enable clocking */
+               udc_clk_set(udc, 1);
+
+               /* ISP back to normal power mode */
+               udc->poweron = 1;
+               isp1301_set_powerstate(udc, 1);
+       }
+
+       return 0;
+}
+#else
+#define        lpc32xx_udc_suspend     NULL
+#define        lpc32xx_udc_resume      NULL
+#endif
+
+#ifdef CONFIG_OF
+static const struct of_device_id lpc32xx_udc_of_match[] = {
+       { .compatible = "nxp,lpc3220-udc", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, lpc32xx_udc_of_match);
+#endif
+
+static struct platform_driver lpc32xx_udc_driver = {
+       .remove         = lpc32xx_udc_remove,
+       .shutdown       = lpc32xx_udc_shutdown,
+       .suspend        = lpc32xx_udc_suspend,
+       .resume         = lpc32xx_udc_resume,
+       .driver         = {
+               .name   = (char *) driver_name,
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(lpc32xx_udc_of_match),
+       },
+};
+
+module_platform_driver_probe(lpc32xx_udc_driver, lpc32xx_udc_probe);
+
+MODULE_DESCRIPTION("LPC32XX udc driver");
+MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lpc32xx_udc");
diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c
new file mode 100644 (file)
index 0000000..de88d33
--- /dev/null
@@ -0,0 +1,1706 @@
+/*
+ * M66592 UDC (USB gadget)
+ *
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ *
+ * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#include "m66592-udc.h"
+
+MODULE_DESCRIPTION("M66592 USB gadget driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yoshihiro Shimoda");
+MODULE_ALIAS("platform:m66592_udc");
+
+#define DRIVER_VERSION "21 July 2009"
+
+static const char udc_name[] = "m66592_udc";
+static const char *m66592_ep_name[] = {
+       "ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7"
+};
+
+static void disable_controller(struct m66592 *m66592);
+static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req);
+static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req);
+static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
+                       gfp_t gfp_flags);
+
+static void transfer_complete(struct m66592_ep *ep,
+               struct m66592_request *req, int status);
+
+/*-------------------------------------------------------------------------*/
+static inline u16 get_usb_speed(struct m66592 *m66592)
+{
+       return (m66592_read(m66592, M66592_DVSTCTR) & M66592_RHST);
+}
+
+static void enable_pipe_irq(struct m66592 *m66592, u16 pipenum,
+               unsigned long reg)
+{
+       u16 tmp;
+
+       tmp = m66592_read(m66592, M66592_INTENB0);
+       m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
+                       M66592_INTENB0);
+       m66592_bset(m66592, (1 << pipenum), reg);
+       m66592_write(m66592, tmp, M66592_INTENB0);
+}
+
+static void disable_pipe_irq(struct m66592 *m66592, u16 pipenum,
+               unsigned long reg)
+{
+       u16 tmp;
+
+       tmp = m66592_read(m66592, M66592_INTENB0);
+       m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
+                       M66592_INTENB0);
+       m66592_bclr(m66592, (1 << pipenum), reg);
+       m66592_write(m66592, tmp, M66592_INTENB0);
+}
+
+static void m66592_usb_connect(struct m66592 *m66592)
+{
+       m66592_bset(m66592, M66592_CTRE, M66592_INTENB0);
+       m66592_bset(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
+                       M66592_INTENB0);
+       m66592_bset(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
+
+       m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
+}
+
+static void m66592_usb_disconnect(struct m66592 *m66592)
+__releases(m66592->lock)
+__acquires(m66592->lock)
+{
+       m66592_bclr(m66592, M66592_CTRE, M66592_INTENB0);
+       m66592_bclr(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
+                       M66592_INTENB0);
+       m66592_bclr(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
+       m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+
+       m66592->gadget.speed = USB_SPEED_UNKNOWN;
+       spin_unlock(&m66592->lock);
+       m66592->driver->disconnect(&m66592->gadget);
+       spin_lock(&m66592->lock);
+
+       disable_controller(m66592);
+       INIT_LIST_HEAD(&m66592->ep[0].queue);
+}
+
+static inline u16 control_reg_get_pid(struct m66592 *m66592, u16 pipenum)
+{
+       u16 pid = 0;
+       unsigned long offset;
+
+       if (pipenum == 0)
+               pid = m66592_read(m66592, M66592_DCPCTR) & M66592_PID;
+       else if (pipenum < M66592_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               pid = m66592_read(m66592, offset) & M66592_PID;
+       } else
+               pr_err("unexpect pipe num (%d)\n", pipenum);
+
+       return pid;
+}
+
+static inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum,
+               u16 pid)
+{
+       unsigned long offset;
+
+       if (pipenum == 0)
+               m66592_mdfy(m66592, pid, M66592_PID, M66592_DCPCTR);
+       else if (pipenum < M66592_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               m66592_mdfy(m66592, pid, M66592_PID, offset);
+       } else
+               pr_err("unexpect pipe num (%d)\n", pipenum);
+}
+
+static inline void pipe_start(struct m66592 *m66592, u16 pipenum)
+{
+       control_reg_set_pid(m66592, pipenum, M66592_PID_BUF);
+}
+
+static inline void pipe_stop(struct m66592 *m66592, u16 pipenum)
+{
+       control_reg_set_pid(m66592, pipenum, M66592_PID_NAK);
+}
+
+static inline void pipe_stall(struct m66592 *m66592, u16 pipenum)
+{
+       control_reg_set_pid(m66592, pipenum, M66592_PID_STALL);
+}
+
+static inline u16 control_reg_get(struct m66592 *m66592, u16 pipenum)
+{
+       u16 ret = 0;
+       unsigned long offset;
+
+       if (pipenum == 0)
+               ret = m66592_read(m66592, M66592_DCPCTR);
+       else if (pipenum < M66592_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               ret = m66592_read(m66592, offset);
+       } else
+               pr_err("unexpect pipe num (%d)\n", pipenum);
+
+       return ret;
+}
+
+static inline void control_reg_sqclr(struct m66592 *m66592, u16 pipenum)
+{
+       unsigned long offset;
+
+       pipe_stop(m66592, pipenum);
+
+       if (pipenum == 0)
+               m66592_bset(m66592, M66592_SQCLR, M66592_DCPCTR);
+       else if (pipenum < M66592_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               m66592_bset(m66592, M66592_SQCLR, offset);
+       } else
+               pr_err("unexpect pipe num(%d)\n", pipenum);
+}
+
+static inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
+{
+       u16 tmp;
+       int size;
+
+       if (pipenum == 0) {
+               tmp = m66592_read(m66592, M66592_DCPCFG);
+               if ((tmp & M66592_CNTMD) != 0)
+                       size = 256;
+               else {
+                       tmp = m66592_read(m66592, M66592_DCPMAXP);
+                       size = tmp & M66592_MAXP;
+               }
+       } else {
+               m66592_write(m66592, pipenum, M66592_PIPESEL);
+               tmp = m66592_read(m66592, M66592_PIPECFG);
+               if ((tmp & M66592_CNTMD) != 0) {
+                       tmp = m66592_read(m66592, M66592_PIPEBUF);
+                       size = ((tmp >> 10) + 1) * 64;
+               } else {
+                       tmp = m66592_read(m66592, M66592_PIPEMAXP);
+                       size = tmp & M66592_MXPS;
+               }
+       }
+
+       return size;
+}
+
+static inline void pipe_change(struct m66592 *m66592, u16 pipenum)
+{
+       struct m66592_ep *ep = m66592->pipenum2ep[pipenum];
+       unsigned short mbw;
+
+       if (ep->use_dma)
+               return;
+
+       m66592_mdfy(m66592, pipenum, M66592_CURPIPE, ep->fifosel);
+
+       ndelay(450);
+
+       if (m66592->pdata->on_chip)
+               mbw = M66592_MBW_32;
+       else
+               mbw = M66592_MBW_16;
+
+       m66592_bset(m66592, mbw, ep->fifosel);
+}
+
+static int pipe_buffer_setting(struct m66592 *m66592,
+               struct m66592_pipe_info *info)
+{
+       u16 bufnum = 0, buf_bsize = 0;
+       u16 pipecfg = 0;
+
+       if (info->pipe == 0)
+               return -EINVAL;
+
+       m66592_write(m66592, info->pipe, M66592_PIPESEL);
+
+       if (info->dir_in)
+               pipecfg |= M66592_DIR;
+       pipecfg |= info->type;
+       pipecfg |= info->epnum;
+       switch (info->type) {
+       case M66592_INT:
+               bufnum = 4 + (info->pipe - M66592_BASE_PIPENUM_INT);
+               buf_bsize = 0;
+               break;
+       case M66592_BULK:
+               /* isochronous pipes may be used as bulk pipes */
+               if (info->pipe >= M66592_BASE_PIPENUM_BULK)
+                       bufnum = info->pipe - M66592_BASE_PIPENUM_BULK;
+               else
+                       bufnum = info->pipe - M66592_BASE_PIPENUM_ISOC;
+
+               bufnum = M66592_BASE_BUFNUM + (bufnum * 16);
+               buf_bsize = 7;
+               pipecfg |= M66592_DBLB;
+               if (!info->dir_in)
+                       pipecfg |= M66592_SHTNAK;
+               break;
+       case M66592_ISO:
+               bufnum = M66592_BASE_BUFNUM +
+                        (info->pipe - M66592_BASE_PIPENUM_ISOC) * 16;
+               buf_bsize = 7;
+               break;
+       }
+
+       if (buf_bsize && ((bufnum + 16) >= M66592_MAX_BUFNUM)) {
+               pr_err("m66592 pipe memory is insufficient\n");
+               return -ENOMEM;
+       }
+
+       m66592_write(m66592, pipecfg, M66592_PIPECFG);
+       m66592_write(m66592, (buf_bsize << 10) | (bufnum), M66592_PIPEBUF);
+       m66592_write(m66592, info->maxpacket, M66592_PIPEMAXP);
+       if (info->interval)
+               info->interval--;
+       m66592_write(m66592, info->interval, M66592_PIPEPERI);
+
+       return 0;
+}
+
+static void pipe_buffer_release(struct m66592 *m66592,
+                               struct m66592_pipe_info *info)
+{
+       if (info->pipe == 0)
+               return;
+
+       if (is_bulk_pipe(info->pipe)) {
+               m66592->bulk--;
+       } else if (is_interrupt_pipe(info->pipe))
+               m66592->interrupt--;
+       else if (is_isoc_pipe(info->pipe)) {
+               m66592->isochronous--;
+               if (info->type == M66592_BULK)
+                       m66592->bulk--;
+       } else
+               pr_err("ep_release: unexpect pipenum (%d)\n",
+                               info->pipe);
+}
+
+static void pipe_initialize(struct m66592_ep *ep)
+{
+       struct m66592 *m66592 = ep->m66592;
+       unsigned short mbw;
+
+       m66592_mdfy(m66592, 0, M66592_CURPIPE, ep->fifosel);
+
+       m66592_write(m66592, M66592_ACLRM, ep->pipectr);
+       m66592_write(m66592, 0, ep->pipectr);
+       m66592_write(m66592, M66592_SQCLR, ep->pipectr);
+       if (ep->use_dma) {
+               m66592_mdfy(m66592, ep->pipenum, M66592_CURPIPE, ep->fifosel);
+
+               ndelay(450);
+
+               if (m66592->pdata->on_chip)
+                       mbw = M66592_MBW_32;
+               else
+                       mbw = M66592_MBW_16;
+
+               m66592_bset(m66592, mbw, ep->fifosel);
+       }
+}
+
+static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
+               const struct usb_endpoint_descriptor *desc,
+               u16 pipenum, int dma)
+{
+       if ((pipenum != 0) && dma) {
+               if (m66592->num_dma == 0) {
+                       m66592->num_dma++;
+                       ep->use_dma = 1;
+                       ep->fifoaddr = M66592_D0FIFO;
+                       ep->fifosel = M66592_D0FIFOSEL;
+                       ep->fifoctr = M66592_D0FIFOCTR;
+                       ep->fifotrn = M66592_D0FIFOTRN;
+               } else if (!m66592->pdata->on_chip && m66592->num_dma == 1) {
+                       m66592->num_dma++;
+                       ep->use_dma = 1;
+                       ep->fifoaddr = M66592_D1FIFO;
+                       ep->fifosel = M66592_D1FIFOSEL;
+                       ep->fifoctr = M66592_D1FIFOCTR;
+                       ep->fifotrn = M66592_D1FIFOTRN;
+               } else {
+                       ep->use_dma = 0;
+                       ep->fifoaddr = M66592_CFIFO;
+                       ep->fifosel = M66592_CFIFOSEL;
+                       ep->fifoctr = M66592_CFIFOCTR;
+                       ep->fifotrn = 0;
+               }
+       } else {
+               ep->use_dma = 0;
+               ep->fifoaddr = M66592_CFIFO;
+               ep->fifosel = M66592_CFIFOSEL;
+               ep->fifoctr = M66592_CFIFOCTR;
+               ep->fifotrn = 0;
+       }
+
+       ep->pipectr = get_pipectr_addr(pipenum);
+       ep->pipenum = pipenum;
+       ep->ep.maxpacket = usb_endpoint_maxp(desc);
+       m66592->pipenum2ep[pipenum] = ep;
+       m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep;
+       INIT_LIST_HEAD(&ep->queue);
+}
+
+static void m66592_ep_release(struct m66592_ep *ep)
+{
+       struct m66592 *m66592 = ep->m66592;
+       u16 pipenum = ep->pipenum;
+
+       if (pipenum == 0)
+               return;
+
+       if (ep->use_dma)
+               m66592->num_dma--;
+       ep->pipenum = 0;
+       ep->busy = 0;
+       ep->use_dma = 0;
+}
+
+static int alloc_pipe_config(struct m66592_ep *ep,
+               const struct usb_endpoint_descriptor *desc)
+{
+       struct m66592 *m66592 = ep->m66592;
+       struct m66592_pipe_info info;
+       int dma = 0;
+       int *counter;
+       int ret;
+
+       ep->ep.desc = desc;
+
+       BUG_ON(ep->pipenum);
+
+       switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+       case USB_ENDPOINT_XFER_BULK:
+               if (m66592->bulk >= M66592_MAX_NUM_BULK) {
+                       if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
+                               pr_err("bulk pipe is insufficient\n");
+                               return -ENODEV;
+                       } else {
+                               info.pipe = M66592_BASE_PIPENUM_ISOC
+                                               + m66592->isochronous;
+                               counter = &m66592->isochronous;
+                       }
+               } else {
+                       info.pipe = M66592_BASE_PIPENUM_BULK + m66592->bulk;
+                       counter = &m66592->bulk;
+               }
+               info.type = M66592_BULK;
+               dma = 1;
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               if (m66592->interrupt >= M66592_MAX_NUM_INT) {
+                       pr_err("interrupt pipe is insufficient\n");
+                       return -ENODEV;
+               }
+               info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt;
+               info.type = M66592_INT;
+               counter = &m66592->interrupt;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
+                       pr_err("isochronous pipe is insufficient\n");
+                       return -ENODEV;
+               }
+               info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous;
+               info.type = M66592_ISO;
+               counter = &m66592->isochronous;
+               break;
+       default:
+               pr_err("unexpect xfer type\n");
+               return -EINVAL;
+       }
+       ep->type = info.type;
+
+       info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+       info.maxpacket = usb_endpoint_maxp(desc);
+       info.interval = desc->bInterval;
+       if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+               info.dir_in = 1;
+       else
+               info.dir_in = 0;
+
+       ret = pipe_buffer_setting(m66592, &info);
+       if (ret < 0) {
+               pr_err("pipe_buffer_setting fail\n");
+               return ret;
+       }
+
+       (*counter)++;
+       if ((counter == &m66592->isochronous) && info.type == M66592_BULK)
+               m66592->bulk++;
+
+       m66592_ep_setting(m66592, ep, desc, info.pipe, dma);
+       pipe_initialize(ep);
+
+       return 0;
+}
+
+static int free_pipe_config(struct m66592_ep *ep)
+{
+       struct m66592 *m66592 = ep->m66592;
+       struct m66592_pipe_info info;
+
+       info.pipe = ep->pipenum;
+       info.type = ep->type;
+       pipe_buffer_release(m66592, &info);
+       m66592_ep_release(ep);
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static void pipe_irq_enable(struct m66592 *m66592, u16 pipenum)
+{
+       enable_irq_ready(m66592, pipenum);
+       enable_irq_nrdy(m66592, pipenum);
+}
+
+static void pipe_irq_disable(struct m66592 *m66592, u16 pipenum)
+{
+       disable_irq_ready(m66592, pipenum);
+       disable_irq_nrdy(m66592, pipenum);
+}
+
+/* if complete is true, gadget driver complete function is not call */
+static void control_end(struct m66592 *m66592, unsigned ccpl)
+{
+       m66592->ep[0].internal_ccpl = ccpl;
+       pipe_start(m66592, 0);
+       m66592_bset(m66592, M66592_CCPL, M66592_DCPCTR);
+}
+
+static void start_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+       struct m66592 *m66592 = ep->m66592;
+
+       pipe_change(m66592, ep->pipenum);
+       m66592_mdfy(m66592, M66592_ISEL | M66592_PIPE0,
+                       (M66592_ISEL | M66592_CURPIPE),
+                       M66592_CFIFOSEL);
+       m66592_write(m66592, M66592_BCLR, ep->fifoctr);
+       if (req->req.length == 0) {
+               m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
+               pipe_start(m66592, 0);
+               transfer_complete(ep, req, 0);
+       } else {
+               m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
+               irq_ep0_write(ep, req);
+       }
+}
+
+static void start_packet_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+       struct m66592 *m66592 = ep->m66592;
+       u16 tmp;
+
+       pipe_change(m66592, ep->pipenum);
+       disable_irq_empty(m66592, ep->pipenum);
+       pipe_start(m66592, ep->pipenum);
+
+       tmp = m66592_read(m66592, ep->fifoctr);
+       if (unlikely((tmp & M66592_FRDY) == 0))
+               pipe_irq_enable(m66592, ep->pipenum);
+       else
+               irq_packet_write(ep, req);
+}
+
+static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
+{
+       struct m66592 *m66592 = ep->m66592;
+       u16 pipenum = ep->pipenum;
+
+       if (ep->pipenum == 0) {
+               m66592_mdfy(m66592, M66592_PIPE0,
+                               (M66592_ISEL | M66592_CURPIPE),
+                               M66592_CFIFOSEL);
+               m66592_write(m66592, M66592_BCLR, ep->fifoctr);
+               pipe_start(m66592, pipenum);
+               pipe_irq_enable(m66592, pipenum);
+       } else {
+               if (ep->use_dma) {
+                       m66592_bset(m66592, M66592_TRCLR, ep->fifosel);
+                       pipe_change(m66592, pipenum);
+                       m66592_bset(m66592, M66592_TRENB, ep->fifosel);
+                       m66592_write(m66592,
+                               (req->req.length + ep->ep.maxpacket - 1)
+                                       / ep->ep.maxpacket,
+                               ep->fifotrn);
+               }
+               pipe_start(m66592, pipenum);    /* trigger once */
+               pipe_irq_enable(m66592, pipenum);
+       }
+}
+
+static void start_packet(struct m66592_ep *ep, struct m66592_request *req)
+{
+       if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
+               start_packet_write(ep, req);
+       else
+               start_packet_read(ep, req);
+}
+
+static void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
+{
+       u16 ctsq;
+
+       ctsq = m66592_read(ep->m66592, M66592_INTSTS0) & M66592_CTSQ;
+
+       switch (ctsq) {
+       case M66592_CS_RDDS:
+               start_ep0_write(ep, req);
+               break;
+       case M66592_CS_WRDS:
+               start_packet_read(ep, req);
+               break;
+
+       case M66592_CS_WRND:
+               control_end(ep->m66592, 0);
+               break;
+       default:
+               pr_err("start_ep0: unexpect ctsq(%x)\n", ctsq);
+               break;
+       }
+}
+
+static void init_controller(struct m66592 *m66592)
+{
+       unsigned int endian;
+
+       if (m66592->pdata->on_chip) {
+               if (m66592->pdata->endian)
+                       endian = 0; /* big endian */
+               else
+                       endian = M66592_LITTLE; /* little endian */
+
+               m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */
+               m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
+               m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+               m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
+
+               /* This is a workaound for SH7722 2nd cut */
+               m66592_bset(m66592, 0x8000, M66592_DVSTCTR);
+               m66592_bset(m66592, 0x1000, M66592_TESTMODE);
+               m66592_bclr(m66592, 0x8000, M66592_DVSTCTR);
+
+               m66592_bset(m66592, M66592_INTL, M66592_INTENB1);
+
+               m66592_write(m66592, 0, M66592_CFBCFG);
+               m66592_write(m66592, 0, M66592_D0FBCFG);
+               m66592_bset(m66592, endian, M66592_CFBCFG);
+               m66592_bset(m66592, endian, M66592_D0FBCFG);
+       } else {
+               unsigned int clock, vif, irq_sense;
+
+               if (m66592->pdata->endian)
+                       endian = M66592_BIGEND; /* big endian */
+               else
+                       endian = 0; /* little endian */
+
+               if (m66592->pdata->vif)
+                       vif = M66592_LDRV; /* 3.3v */
+               else
+                       vif = 0; /* 1.5v */
+
+               switch (m66592->pdata->xtal) {
+               case M66592_PLATDATA_XTAL_12MHZ:
+                       clock = M66592_XTAL12;
+                       break;
+               case M66592_PLATDATA_XTAL_24MHZ:
+                       clock = M66592_XTAL24;
+                       break;
+               case M66592_PLATDATA_XTAL_48MHZ:
+                       clock = M66592_XTAL48;
+                       break;
+               default:
+                       pr_warning("m66592-udc: xtal configuration error\n");
+                       clock = 0;
+               }
+
+               switch (m66592->irq_trigger) {
+               case IRQF_TRIGGER_LOW:
+                       irq_sense = M66592_INTL;
+                       break;
+               case IRQF_TRIGGER_FALLING:
+                       irq_sense = 0;
+                       break;
+               default:
+                       pr_warning("m66592-udc: irq trigger config error\n");
+                       irq_sense = 0;
+               }
+
+               m66592_bset(m66592,
+                           (vif & M66592_LDRV) | (endian & M66592_BIGEND),
+                           M66592_PINCFG);
+               m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */
+               m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL,
+                           M66592_SYSCFG);
+               m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
+               m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+               m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
+
+               m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+
+               msleep(3);
+
+               m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
+
+               msleep(1);
+
+               m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
+
+               m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
+               m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
+                            M66592_DMA0CFG);
+       }
+}
+
+static void disable_controller(struct m66592 *m66592)
+{
+       m66592_bclr(m66592, M66592_UTST, M66592_TESTMODE);
+       if (!m66592->pdata->on_chip) {
+               m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
+               udelay(1);
+               m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
+               udelay(1);
+               m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
+               udelay(1);
+               m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
+       }
+}
+
+static void m66592_start_xclock(struct m66592 *m66592)
+{
+       u16 tmp;
+
+       if (!m66592->pdata->on_chip) {
+               tmp = m66592_read(m66592, M66592_SYSCFG);
+               if (!(tmp & M66592_XCKE))
+                       m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+       }
+}
+
+/*-------------------------------------------------------------------------*/
+static void transfer_complete(struct m66592_ep *ep,
+               struct m66592_request *req, int status)
+__releases(m66592->lock)
+__acquires(m66592->lock)
+{
+       int restart = 0;
+
+       if (unlikely(ep->pipenum == 0)) {
+               if (ep->internal_ccpl) {
+                       ep->internal_ccpl = 0;
+                       return;
+               }
+       }
+
+       list_del_init(&req->queue);
+       if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
+               req->req.status = -ESHUTDOWN;
+       else
+               req->req.status = status;
+
+       if (!list_empty(&ep->queue))
+               restart = 1;
+
+       spin_unlock(&ep->m66592->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&ep->m66592->lock);
+
+       if (restart) {
+               req = list_entry(ep->queue.next, struct m66592_request, queue);
+               if (ep->ep.desc)
+                       start_packet(ep, req);
+       }
+}
+
+static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+       int i;
+       u16 tmp;
+       unsigned bufsize;
+       size_t size;
+       void *buf;
+       u16 pipenum = ep->pipenum;
+       struct m66592 *m66592 = ep->m66592;
+
+       pipe_change(m66592, pipenum);
+       m66592_bset(m66592, M66592_ISEL, ep->fifosel);
+
+       i = 0;
+       do {
+               tmp = m66592_read(m66592, ep->fifoctr);
+               if (i++ > 100000) {
+                       pr_err("pipe0 is busy. maybe cpu i/o bus "
+                               "conflict. please power off this controller.");
+                       return;
+               }
+               ndelay(1);
+       } while ((tmp & M66592_FRDY) == 0);
+
+       /* prepare parameters */
+       bufsize = get_buffer_size(m66592, pipenum);
+       buf = req->req.buf + req->req.actual;
+       size = min(bufsize, req->req.length - req->req.actual);
+
+       /* write fifo */
+       if (req->req.buf) {
+               if (size > 0)
+                       m66592_write_fifo(m66592, ep, buf, size);
+               if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
+                       m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
+       }
+
+       /* update parameters */
+       req->req.actual += size;
+
+       /* check transfer finish */
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
+               disable_irq_ready(m66592, pipenum);
+               disable_irq_empty(m66592, pipenum);
+       } else {
+               disable_irq_ready(m66592, pipenum);
+               enable_irq_empty(m66592, pipenum);
+       }
+       pipe_start(m66592, pipenum);
+}
+
+static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+       u16 tmp;
+       unsigned bufsize;
+       size_t size;
+       void *buf;
+       u16 pipenum = ep->pipenum;
+       struct m66592 *m66592 = ep->m66592;
+
+       pipe_change(m66592, pipenum);
+       tmp = m66592_read(m66592, ep->fifoctr);
+       if (unlikely((tmp & M66592_FRDY) == 0)) {
+               pipe_stop(m66592, pipenum);
+               pipe_irq_disable(m66592, pipenum);
+               pr_err("write fifo not ready. pipnum=%d\n", pipenum);
+               return;
+       }
+
+       /* prepare parameters */
+       bufsize = get_buffer_size(m66592, pipenum);
+       buf = req->req.buf + req->req.actual;
+       size = min(bufsize, req->req.length - req->req.actual);
+
+       /* write fifo */
+       if (req->req.buf) {
+               m66592_write_fifo(m66592, ep, buf, size);
+               if ((size == 0)
+                               || ((size % ep->ep.maxpacket) != 0)
+                               || ((bufsize != ep->ep.maxpacket)
+                                       && (bufsize > size)))
+                       m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
+       }
+
+       /* update parameters */
+       req->req.actual += size;
+       /* check transfer finish */
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
+               disable_irq_ready(m66592, pipenum);
+               enable_irq_empty(m66592, pipenum);
+       } else {
+               disable_irq_empty(m66592, pipenum);
+               pipe_irq_enable(m66592, pipenum);
+       }
+}
+
+static void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req)
+{
+       u16 tmp;
+       int rcv_len, bufsize, req_len;
+       int size;
+       void *buf;
+       u16 pipenum = ep->pipenum;
+       struct m66592 *m66592 = ep->m66592;
+       int finish = 0;
+
+       pipe_change(m66592, pipenum);
+       tmp = m66592_read(m66592, ep->fifoctr);
+       if (unlikely((tmp & M66592_FRDY) == 0)) {
+               req->req.status = -EPIPE;
+               pipe_stop(m66592, pipenum);
+               pipe_irq_disable(m66592, pipenum);
+               pr_err("read fifo not ready");
+               return;
+       }
+
+       /* prepare parameters */
+       rcv_len = tmp & M66592_DTLN;
+       bufsize = get_buffer_size(m66592, pipenum);
+
+       buf = req->req.buf + req->req.actual;
+       req_len = req->req.length - req->req.actual;
+       if (rcv_len < bufsize)
+               size = min(rcv_len, req_len);
+       else
+               size = min(bufsize, req_len);
+
+       /* update parameters */
+       req->req.actual += size;
+
+       /* check transfer finish */
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
+               pipe_stop(m66592, pipenum);
+               pipe_irq_disable(m66592, pipenum);
+               finish = 1;
+       }
+
+       /* read fifo */
+       if (req->req.buf) {
+               if (size == 0)
+                       m66592_write(m66592, M66592_BCLR, ep->fifoctr);
+               else
+                       m66592_read_fifo(m66592, ep->fifoaddr, buf, size);
+       }
+
+       if ((ep->pipenum != 0) && finish)
+               transfer_complete(ep, req, 0);
+}
+
+static void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb)
+{
+       u16 check;
+       u16 pipenum;
+       struct m66592_ep *ep;
+       struct m66592_request *req;
+
+       if ((status & M66592_BRDY0) && (enb & M66592_BRDY0)) {
+               m66592_write(m66592, ~M66592_BRDY0, M66592_BRDYSTS);
+               m66592_mdfy(m66592, M66592_PIPE0, M66592_CURPIPE,
+                               M66592_CFIFOSEL);
+
+               ep = &m66592->ep[0];
+               req = list_entry(ep->queue.next, struct m66592_request, queue);
+               irq_packet_read(ep, req);
+       } else {
+               for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
+                       check = 1 << pipenum;
+                       if ((status & check) && (enb & check)) {
+                               m66592_write(m66592, ~check, M66592_BRDYSTS);
+                               ep = m66592->pipenum2ep[pipenum];
+                               req = list_entry(ep->queue.next,
+                                                struct m66592_request, queue);
+                               if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
+                                       irq_packet_write(ep, req);
+                               else
+                                       irq_packet_read(ep, req);
+                       }
+               }
+       }
+}
+
+static void irq_pipe_empty(struct m66592 *m66592, u16 status, u16 enb)
+{
+       u16 tmp;
+       u16 check;
+       u16 pipenum;
+       struct m66592_ep *ep;
+       struct m66592_request *req;
+
+       if ((status & M66592_BEMP0) && (enb & M66592_BEMP0)) {
+               m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
+
+               ep = &m66592->ep[0];
+               req = list_entry(ep->queue.next, struct m66592_request, queue);
+               irq_ep0_write(ep, req);
+       } else {
+               for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
+                       check = 1 << pipenum;
+                       if ((status & check) && (enb & check)) {
+                               m66592_write(m66592, ~check, M66592_BEMPSTS);
+                               tmp = control_reg_get(m66592, pipenum);
+                               if ((tmp & M66592_INBUFM) == 0) {
+                                       disable_irq_empty(m66592, pipenum);
+                                       pipe_irq_disable(m66592, pipenum);
+                                       pipe_stop(m66592, pipenum);
+                                       ep = m66592->pipenum2ep[pipenum];
+                                       req = list_entry(ep->queue.next,
+                                                        struct m66592_request,
+                                                        queue);
+                                       if (!list_empty(&ep->queue))
+                                               transfer_complete(ep, req, 0);
+                               }
+                       }
+               }
+       }
+}
+
+static void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+__releases(m66592->lock)
+__acquires(m66592->lock)
+{
+       struct m66592_ep *ep;
+       u16 pid;
+       u16 status = 0;
+       u16 w_index = le16_to_cpu(ctrl->wIndex);
+
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               status = 1 << USB_DEVICE_SELF_POWERED;
+               break;
+       case USB_RECIP_INTERFACE:
+               status = 0;
+               break;
+       case USB_RECIP_ENDPOINT:
+               ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
+               pid = control_reg_get_pid(m66592, ep->pipenum);
+               if (pid == M66592_PID_STALL)
+                       status = 1 << USB_ENDPOINT_HALT;
+               else
+                       status = 0;
+               break;
+       default:
+               pipe_stall(m66592, 0);
+               return;         /* exit */
+       }
+
+       m66592->ep0_data = cpu_to_le16(status);
+       m66592->ep0_req->buf = &m66592->ep0_data;
+       m66592->ep0_req->length = 2;
+       /* AV: what happens if we get called again before that gets through? */
+       spin_unlock(&m66592->lock);
+       m66592_queue(m66592->gadget.ep0, m66592->ep0_req, GFP_KERNEL);
+       spin_lock(&m66592->lock);
+}
+
+static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               control_end(m66592, 1);
+               break;
+       case USB_RECIP_INTERFACE:
+               control_end(m66592, 1);
+               break;
+       case USB_RECIP_ENDPOINT: {
+               struct m66592_ep *ep;
+               struct m66592_request *req;
+               u16 w_index = le16_to_cpu(ctrl->wIndex);
+
+               ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
+               pipe_stop(m66592, ep->pipenum);
+               control_reg_sqclr(m66592, ep->pipenum);
+
+               control_end(m66592, 1);
+
+               req = list_entry(ep->queue.next,
+               struct m66592_request, queue);
+               if (ep->busy) {
+                       ep->busy = 0;
+                       if (list_empty(&ep->queue))
+                               break;
+                       start_packet(ep, req);
+               } else if (!list_empty(&ep->queue))
+                       pipe_start(m66592, ep->pipenum);
+               }
+               break;
+       default:
+               pipe_stall(m66592, 0);
+               break;
+       }
+}
+
+static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+       u16 tmp;
+       int timeout = 3000;
+
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               switch (le16_to_cpu(ctrl->wValue)) {
+               case USB_DEVICE_TEST_MODE:
+                       control_end(m66592, 1);
+                       /* Wait for the completion of status stage */
+                       do {
+                               tmp = m66592_read(m66592, M66592_INTSTS0) &
+                                                               M66592_CTSQ;
+                               udelay(1);
+                       } while (tmp != M66592_CS_IDST || timeout-- > 0);
+
+                       if (tmp == M66592_CS_IDST)
+                               m66592_bset(m66592,
+                                           le16_to_cpu(ctrl->wIndex >> 8),
+                                           M66592_TESTMODE);
+                       break;
+               default:
+                       pipe_stall(m66592, 0);
+                       break;
+               }
+               break;
+       case USB_RECIP_INTERFACE:
+               control_end(m66592, 1);
+               break;
+       case USB_RECIP_ENDPOINT: {
+               struct m66592_ep *ep;
+               u16 w_index = le16_to_cpu(ctrl->wIndex);
+
+               ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
+               pipe_stall(m66592, ep->pipenum);
+
+               control_end(m66592, 1);
+               }
+               break;
+       default:
+               pipe_stall(m66592, 0);
+               break;
+       }
+}
+
+/* if return value is true, call class driver's setup() */
+static int setup_packet(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+       u16 *p = (u16 *)ctrl;
+       unsigned long offset = M66592_USBREQ;
+       int i, ret = 0;
+
+       /* read fifo */
+       m66592_write(m66592, ~M66592_VALID, M66592_INTSTS0);
+
+       for (i = 0; i < 4; i++)
+               p[i] = m66592_read(m66592, offset + i*2);
+
+       /* check request */
+       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+               switch (ctrl->bRequest) {
+               case USB_REQ_GET_STATUS:
+                       get_status(m66592, ctrl);
+                       break;
+               case USB_REQ_CLEAR_FEATURE:
+                       clear_feature(m66592, ctrl);
+                       break;
+               case USB_REQ_SET_FEATURE:
+                       set_feature(m66592, ctrl);
+                       break;
+               default:
+                       ret = 1;
+                       break;
+               }
+       } else
+               ret = 1;
+       return ret;
+}
+
+static void m66592_update_usb_speed(struct m66592 *m66592)
+{
+       u16 speed = get_usb_speed(m66592);
+
+       switch (speed) {
+       case M66592_HSMODE:
+               m66592->gadget.speed = USB_SPEED_HIGH;
+               break;
+       case M66592_FSMODE:
+               m66592->gadget.speed = USB_SPEED_FULL;
+               break;
+       default:
+               m66592->gadget.speed = USB_SPEED_UNKNOWN;
+               pr_err("USB speed unknown\n");
+       }
+}
+
+static void irq_device_state(struct m66592 *m66592)
+{
+       u16 dvsq;
+
+       dvsq = m66592_read(m66592, M66592_INTSTS0) & M66592_DVSQ;
+       m66592_write(m66592, ~M66592_DVST, M66592_INTSTS0);
+
+       if (dvsq == M66592_DS_DFLT) {   /* bus reset */
+               m66592->driver->disconnect(&m66592->gadget);
+               m66592_update_usb_speed(m66592);
+       }
+       if (m66592->old_dvsq == M66592_DS_CNFG && dvsq != M66592_DS_CNFG)
+               m66592_update_usb_speed(m66592);
+       if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS)
+                       && m66592->gadget.speed == USB_SPEED_UNKNOWN)
+               m66592_update_usb_speed(m66592);
+
+       m66592->old_dvsq = dvsq;
+}
+
+static void irq_control_stage(struct m66592 *m66592)
+__releases(m66592->lock)
+__acquires(m66592->lock)
+{
+       struct usb_ctrlrequest ctrl;
+       u16 ctsq;
+
+       ctsq = m66592_read(m66592, M66592_INTSTS0) & M66592_CTSQ;
+       m66592_write(m66592, ~M66592_CTRT, M66592_INTSTS0);
+
+       switch (ctsq) {
+       case M66592_CS_IDST: {
+               struct m66592_ep *ep;
+               struct m66592_request *req;
+               ep = &m66592->ep[0];
+               req = list_entry(ep->queue.next, struct m66592_request, queue);
+               transfer_complete(ep, req, 0);
+               }
+               break;
+
+       case M66592_CS_RDDS:
+       case M66592_CS_WRDS:
+       case M66592_CS_WRND:
+               if (setup_packet(m66592, &ctrl)) {
+                       spin_unlock(&m66592->lock);
+                       if (m66592->driver->setup(&m66592->gadget, &ctrl) < 0)
+                               pipe_stall(m66592, 0);
+                       spin_lock(&m66592->lock);
+               }
+               break;
+       case M66592_CS_RDSS:
+       case M66592_CS_WRSS:
+               control_end(m66592, 0);
+               break;
+       default:
+               pr_err("ctrl_stage: unexpect ctsq(%x)\n", ctsq);
+               break;
+       }
+}
+
+static irqreturn_t m66592_irq(int irq, void *_m66592)
+{
+       struct m66592 *m66592 = _m66592;
+       u16 intsts0;
+       u16 intenb0;
+       u16 brdysts, nrdysts, bempsts;
+       u16 brdyenb, nrdyenb, bempenb;
+       u16 savepipe;
+       u16 mask0;
+
+       spin_lock(&m66592->lock);
+
+       intsts0 = m66592_read(m66592, M66592_INTSTS0);
+       intenb0 = m66592_read(m66592, M66592_INTENB0);
+
+       if (m66592->pdata->on_chip && !intsts0 && !intenb0) {
+               /*
+                * When USB clock stops, it cannot read register. Even if a
+                * clock stops, the interrupt occurs. So this driver turn on
+                * a clock by this timing and do re-reading of register.
+                */
+               m66592_start_xclock(m66592);
+               intsts0 = m66592_read(m66592, M66592_INTSTS0);
+               intenb0 = m66592_read(m66592, M66592_INTENB0);
+       }
+
+       savepipe = m66592_read(m66592, M66592_CFIFOSEL);
+
+       mask0 = intsts0 & intenb0;
+       if (mask0) {
+               brdysts = m66592_read(m66592, M66592_BRDYSTS);
+               nrdysts = m66592_read(m66592, M66592_NRDYSTS);
+               bempsts = m66592_read(m66592, M66592_BEMPSTS);
+               brdyenb = m66592_read(m66592, M66592_BRDYENB);
+               nrdyenb = m66592_read(m66592, M66592_NRDYENB);
+               bempenb = m66592_read(m66592, M66592_BEMPENB);
+
+               if (mask0 & M66592_VBINT) {
+                       m66592_write(m66592,  0xffff & ~M66592_VBINT,
+                                       M66592_INTSTS0);
+                       m66592_start_xclock(m66592);
+
+                       /* start vbus sampling */
+                       m66592->old_vbus = m66592_read(m66592, M66592_INTSTS0)
+                                       & M66592_VBSTS;
+                       m66592->scount = M66592_MAX_SAMPLING;
+
+                       mod_timer(&m66592->timer,
+                                       jiffies + msecs_to_jiffies(50));
+               }
+               if (intsts0 & M66592_DVSQ)
+                       irq_device_state(m66592);
+
+               if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE)
+                               && (brdysts & brdyenb)) {
+                       irq_pipe_ready(m66592, brdysts, brdyenb);
+               }
+               if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE)
+                               && (bempsts & bempenb)) {
+                       irq_pipe_empty(m66592, bempsts, bempenb);
+               }
+
+               if (intsts0 & M66592_CTRT)
+                       irq_control_stage(m66592);
+       }
+
+       m66592_write(m66592, savepipe, M66592_CFIFOSEL);
+
+       spin_unlock(&m66592->lock);
+       return IRQ_HANDLED;
+}
+
+static void m66592_timer(unsigned long _m66592)
+{
+       struct m66592 *m66592 = (struct m66592 *)_m66592;
+       unsigned long flags;
+       u16 tmp;
+
+       spin_lock_irqsave(&m66592->lock, flags);
+       tmp = m66592_read(m66592, M66592_SYSCFG);
+       if (!(tmp & M66592_RCKE)) {
+               m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
+               udelay(10);
+               m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
+       }
+       if (m66592->scount > 0) {
+               tmp = m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS;
+               if (tmp == m66592->old_vbus) {
+                       m66592->scount--;
+                       if (m66592->scount == 0) {
+                               if (tmp == M66592_VBSTS)
+                                       m66592_usb_connect(m66592);
+                               else
+                                       m66592_usb_disconnect(m66592);
+                       } else {
+                               mod_timer(&m66592->timer,
+                                       jiffies + msecs_to_jiffies(50));
+                       }
+               } else {
+                       m66592->scount = M66592_MAX_SAMPLING;
+                       m66592->old_vbus = tmp;
+                       mod_timer(&m66592->timer,
+                                       jiffies + msecs_to_jiffies(50));
+               }
+       }
+       spin_unlock_irqrestore(&m66592->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+static int m66592_enable(struct usb_ep *_ep,
+                        const struct usb_endpoint_descriptor *desc)
+{
+       struct m66592_ep *ep;
+
+       ep = container_of(_ep, struct m66592_ep, ep);
+       return alloc_pipe_config(ep, desc);
+}
+
+static int m66592_disable(struct usb_ep *_ep)
+{
+       struct m66592_ep *ep;
+       struct m66592_request *req;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct m66592_ep, ep);
+       BUG_ON(!ep);
+
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct m66592_request, queue);
+               spin_lock_irqsave(&ep->m66592->lock, flags);
+               transfer_complete(ep, req, -ECONNRESET);
+               spin_unlock_irqrestore(&ep->m66592->lock, flags);
+       }
+
+       pipe_irq_disable(ep->m66592, ep->pipenum);
+       return free_pipe_config(ep);
+}
+
+static struct usb_request *m66592_alloc_request(struct usb_ep *_ep,
+                                               gfp_t gfp_flags)
+{
+       struct m66592_request *req;
+
+       req = kzalloc(sizeof(struct m66592_request), gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void m66592_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct m66592_request *req;
+
+       req = container_of(_req, struct m66592_request, req);
+       kfree(req);
+}
+
+static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
+                       gfp_t gfp_flags)
+{
+       struct m66592_ep *ep;
+       struct m66592_request *req;
+       unsigned long flags;
+       int request = 0;
+
+       ep = container_of(_ep, struct m66592_ep, ep);
+       req = container_of(_req, struct m66592_request, req);
+
+       if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       spin_lock_irqsave(&ep->m66592->lock, flags);
+
+       if (list_empty(&ep->queue))
+               request = 1;
+
+       list_add_tail(&req->queue, &ep->queue);
+       req->req.actual = 0;
+       req->req.status = -EINPROGRESS;
+
+       if (ep->ep.desc == NULL)        /* control */
+               start_ep0(ep, req);
+       else {
+               if (request && !ep->busy)
+                       start_packet(ep, req);
+       }
+
+       spin_unlock_irqrestore(&ep->m66592->lock, flags);
+
+       return 0;
+}
+
+static int m66592_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct m66592_ep *ep;
+       struct m66592_request *req;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct m66592_ep, ep);
+       req = container_of(_req, struct m66592_request, req);
+
+       spin_lock_irqsave(&ep->m66592->lock, flags);
+       if (!list_empty(&ep->queue))
+               transfer_complete(ep, req, -ECONNRESET);
+       spin_unlock_irqrestore(&ep->m66592->lock, flags);
+
+       return 0;
+}
+
+static int m66592_set_halt(struct usb_ep *_ep, int value)
+{
+       struct m66592_ep *ep;
+       struct m66592_request *req;
+       unsigned long flags;
+       int ret = 0;
+
+       ep = container_of(_ep, struct m66592_ep, ep);
+       req = list_entry(ep->queue.next, struct m66592_request, queue);
+
+       spin_lock_irqsave(&ep->m66592->lock, flags);
+       if (!list_empty(&ep->queue)) {
+               ret = -EAGAIN;
+               goto out;
+       }
+       if (value) {
+               ep->busy = 1;
+               pipe_stall(ep->m66592, ep->pipenum);
+       } else {
+               ep->busy = 0;
+               pipe_stop(ep->m66592, ep->pipenum);
+       }
+
+out:
+       spin_unlock_irqrestore(&ep->m66592->lock, flags);
+       return ret;
+}
+
+static void m66592_fifo_flush(struct usb_ep *_ep)
+{
+       struct m66592_ep *ep;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct m66592_ep, ep);
+       spin_lock_irqsave(&ep->m66592->lock, flags);
+       if (list_empty(&ep->queue) && !ep->busy) {
+               pipe_stop(ep->m66592, ep->pipenum);
+               m66592_bclr(ep->m66592, M66592_BCLR, ep->fifoctr);
+       }
+       spin_unlock_irqrestore(&ep->m66592->lock, flags);
+}
+
+static struct usb_ep_ops m66592_ep_ops = {
+       .enable         = m66592_enable,
+       .disable        = m66592_disable,
+
+       .alloc_request  = m66592_alloc_request,
+       .free_request   = m66592_free_request,
+
+       .queue          = m66592_queue,
+       .dequeue        = m66592_dequeue,
+
+       .set_halt       = m66592_set_halt,
+       .fifo_flush     = m66592_fifo_flush,
+};
+
+/*-------------------------------------------------------------------------*/
+static int m66592_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct m66592 *m66592 = to_m66592(g);
+
+       /* hook up the driver */
+       driver->driver.bus = NULL;
+       m66592->driver = driver;
+
+       m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
+       if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
+               m66592_start_xclock(m66592);
+               /* start vbus sampling */
+               m66592->old_vbus = m66592_read(m66592,
+                                        M66592_INTSTS0) & M66592_VBSTS;
+               m66592->scount = M66592_MAX_SAMPLING;
+               mod_timer(&m66592->timer, jiffies + msecs_to_jiffies(50));
+       }
+
+       return 0;
+}
+
+static int m66592_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct m66592 *m66592 = to_m66592(g);
+
+       m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
+
+       init_controller(m66592);
+       disable_controller(m66592);
+
+       m66592->driver = NULL;
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static int m66592_get_frame(struct usb_gadget *_gadget)
+{
+       struct m66592 *m66592 = gadget_to_m66592(_gadget);
+       return m66592_read(m66592, M66592_FRMNUM) & 0x03FF;
+}
+
+static int m66592_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct m66592 *m66592 = gadget_to_m66592(gadget);
+       unsigned long flags;
+
+       spin_lock_irqsave(&m66592->lock, flags);
+       if (is_on)
+               m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
+       else
+               m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+       spin_unlock_irqrestore(&m66592->lock, flags);
+
+       return 0;
+}
+
+static const struct usb_gadget_ops m66592_gadget_ops = {
+       .get_frame              = m66592_get_frame,
+       .udc_start              = m66592_udc_start,
+       .udc_stop               = m66592_udc_stop,
+       .pullup                 = m66592_pullup,
+};
+
+static int __exit m66592_remove(struct platform_device *pdev)
+{
+       struct m66592           *m66592 = platform_get_drvdata(pdev);
+
+       usb_del_gadget_udc(&m66592->gadget);
+
+       del_timer_sync(&m66592->timer);
+       iounmap(m66592->reg);
+       free_irq(platform_get_irq(pdev, 0), m66592);
+       m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
+       if (m66592->pdata->on_chip) {
+               clk_disable(m66592->clk);
+               clk_put(m66592->clk);
+       }
+       kfree(m66592);
+       return 0;
+}
+
+static void nop_completion(struct usb_ep *ep, struct usb_request *r)
+{
+}
+
+static int m66592_probe(struct platform_device *pdev)
+{
+       struct resource *res, *ires;
+       void __iomem *reg = NULL;
+       struct m66592 *m66592 = NULL;
+       char clk_name[8];
+       int ret = 0;
+       int i;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENODEV;
+               pr_err("platform_get_resource error.\n");
+               goto clean_up;
+       }
+
+       ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!ires) {
+               ret = -ENODEV;
+               dev_err(&pdev->dev,
+                       "platform_get_resource IORESOURCE_IRQ error.\n");
+               goto clean_up;
+       }
+
+       reg = ioremap(res->start, resource_size(res));
+       if (reg == NULL) {
+               ret = -ENOMEM;
+               pr_err("ioremap error.\n");
+               goto clean_up;
+       }
+
+       if (dev_get_platdata(&pdev->dev) == NULL) {
+               dev_err(&pdev->dev, "no platform data\n");
+               ret = -ENODEV;
+               goto clean_up;
+       }
+
+       /* initialize ucd */
+       m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
+       if (m66592 == NULL) {
+               ret = -ENOMEM;
+               goto clean_up;
+       }
+
+       m66592->pdata = dev_get_platdata(&pdev->dev);
+       m66592->irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
+
+       spin_lock_init(&m66592->lock);
+       platform_set_drvdata(pdev, m66592);
+
+       m66592->gadget.ops = &m66592_gadget_ops;
+       m66592->gadget.max_speed = USB_SPEED_HIGH;
+       m66592->gadget.name = udc_name;
+
+       init_timer(&m66592->timer);
+       m66592->timer.function = m66592_timer;
+       m66592->timer.data = (unsigned long)m66592;
+       m66592->reg = reg;
+
+       ret = request_irq(ires->start, m66592_irq, IRQF_SHARED,
+                       udc_name, m66592);
+       if (ret < 0) {
+               pr_err("request_irq error (%d)\n", ret);
+               goto clean_up;
+       }
+
+       if (m66592->pdata->on_chip) {
+               snprintf(clk_name, sizeof(clk_name), "usbf%d", pdev->id);
+               m66592->clk = clk_get(&pdev->dev, clk_name);
+               if (IS_ERR(m66592->clk)) {
+                       dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
+                               clk_name);
+                       ret = PTR_ERR(m66592->clk);
+                       goto clean_up2;
+               }
+               clk_enable(m66592->clk);
+       }
+
+       INIT_LIST_HEAD(&m66592->gadget.ep_list);
+       m66592->gadget.ep0 = &m66592->ep[0].ep;
+       INIT_LIST_HEAD(&m66592->gadget.ep0->ep_list);
+       for (i = 0; i < M66592_MAX_NUM_PIPE; i++) {
+               struct m66592_ep *ep = &m66592->ep[i];
+
+               if (i != 0) {
+                       INIT_LIST_HEAD(&m66592->ep[i].ep.ep_list);
+                       list_add_tail(&m66592->ep[i].ep.ep_list,
+                                       &m66592->gadget.ep_list);
+               }
+               ep->m66592 = m66592;
+               INIT_LIST_HEAD(&ep->queue);
+               ep->ep.name = m66592_ep_name[i];
+               ep->ep.ops = &m66592_ep_ops;
+               usb_ep_set_maxpacket_limit(&ep->ep, 512);
+       }
+       usb_ep_set_maxpacket_limit(&m66592->ep[0].ep, 64);
+       m66592->ep[0].pipenum = 0;
+       m66592->ep[0].fifoaddr = M66592_CFIFO;
+       m66592->ep[0].fifosel = M66592_CFIFOSEL;
+       m66592->ep[0].fifoctr = M66592_CFIFOCTR;
+       m66592->ep[0].fifotrn = 0;
+       m66592->ep[0].pipectr = get_pipectr_addr(0);
+       m66592->pipenum2ep[0] = &m66592->ep[0];
+       m66592->epaddr2ep[0] = &m66592->ep[0];
+
+       m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
+       if (m66592->ep0_req == NULL) {
+               ret = -ENOMEM;
+               goto clean_up3;
+       }
+       m66592->ep0_req->complete = nop_completion;
+
+       init_controller(m66592);
+
+       ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
+       if (ret)
+               goto err_add_udc;
+
+       dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
+       return 0;
+
+err_add_udc:
+       m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
+
+clean_up3:
+       if (m66592->pdata->on_chip) {
+               clk_disable(m66592->clk);
+               clk_put(m66592->clk);
+       }
+clean_up2:
+       free_irq(ires->start, m66592);
+clean_up:
+       if (m66592) {
+               if (m66592->ep0_req)
+                       m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
+               kfree(m66592);
+       }
+       if (reg)
+               iounmap(reg);
+
+       return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+static struct platform_driver m66592_driver = {
+       .remove =       __exit_p(m66592_remove),
+       .driver         = {
+               .name = (char *) udc_name,
+               .owner  = THIS_MODULE,
+       },
+};
+
+module_platform_driver_probe(m66592_driver, m66592_probe);
diff --git a/drivers/usb/gadget/udc/m66592-udc.h b/drivers/usb/gadget/udc/m66592-udc.h
new file mode 100644 (file)
index 0000000..96d49d7
--- /dev/null
@@ -0,0 +1,606 @@
+/*
+ * M66592 UDC (USB gadget)
+ *
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ *
+ * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#ifndef __M66592_UDC_H__
+#define __M66592_UDC_H__
+
+#include <linux/clk.h>
+#include <linux/usb/m66592.h>
+
+#define M66592_SYSCFG          0x00
+#define M66592_XTAL            0xC000  /* b15-14: Crystal selection */
+#define   M66592_XTAL48                 0x8000         /* 48MHz */
+#define   M66592_XTAL24                 0x4000         /* 24MHz */
+#define   M66592_XTAL12                 0x0000         /* 12MHz */
+#define M66592_XCKE            0x2000  /* b13: External clock enable */
+#define M66592_RCKE            0x1000  /* b12: Register clock enable */
+#define M66592_PLLC            0x0800  /* b11: PLL control */
+#define M66592_SCKE            0x0400  /* b10: USB clock enable */
+#define M66592_ATCKM           0x0100  /* b8: Automatic clock supply */
+#define M66592_HSE             0x0080  /* b7: Hi-speed enable */
+#define M66592_DCFM            0x0040  /* b6: Controller function select  */
+#define M66592_DMRPD           0x0020  /* b5: D- pull down control */
+#define M66592_DPRPU           0x0010  /* b4: D+ pull up control */
+#define M66592_FSRPC           0x0004  /* b2: Full-speed receiver enable */
+#define M66592_PCUT            0x0002  /* b1: Low power sleep enable */
+#define M66592_USBE            0x0001  /* b0: USB module operation enable */
+
+#define M66592_SYSSTS          0x02
+#define M66592_LNST            0x0003  /* b1-0: D+, D- line status */
+#define   M66592_SE1            0x0003         /* SE1 */
+#define   M66592_KSTS           0x0002         /* K State */
+#define   M66592_JSTS           0x0001         /* J State */
+#define   M66592_SE0            0x0000         /* SE0 */
+
+#define M66592_DVSTCTR         0x04
+#define M66592_WKUP            0x0100  /* b8: Remote wakeup */
+#define M66592_RWUPE           0x0080  /* b7: Remote wakeup sense */
+#define M66592_USBRST          0x0040  /* b6: USB reset enable */
+#define M66592_RESUME          0x0020  /* b5: Resume enable */
+#define M66592_UACT            0x0010  /* b4: USB bus enable */
+#define M66592_RHST            0x0003  /* b1-0: Reset handshake status */
+#define   M66592_HSMODE                 0x0003         /* Hi-Speed mode */
+#define   M66592_FSMODE                 0x0002         /* Full-Speed mode */
+#define   M66592_HSPROC                 0x0001         /* HS handshake is processing */
+
+#define M66592_TESTMODE                0x06
+#define M66592_UTST            0x000F  /* b4-0: Test select */
+#define   M66592_H_TST_PACKET   0x000C         /* HOST TEST Packet */
+#define   M66592_H_TST_SE0_NAK  0x000B         /* HOST TEST SE0 NAK */
+#define   M66592_H_TST_K        0x000A         /* HOST TEST K */
+#define   M66592_H_TST_J        0x0009         /* HOST TEST J */
+#define   M66592_H_TST_NORMAL   0x0000         /* HOST Normal Mode */
+#define   M66592_P_TST_PACKET   0x0004         /* PERI TEST Packet */
+#define   M66592_P_TST_SE0_NAK  0x0003         /* PERI TEST SE0 NAK */
+#define   M66592_P_TST_K        0x0002         /* PERI TEST K */
+#define   M66592_P_TST_J        0x0001         /* PERI TEST J */
+#define   M66592_P_TST_NORMAL   0x0000         /* PERI Normal Mode */
+
+/* built-in registers */
+#define M66592_CFBCFG          0x0A
+#define M66592_D0FBCFG         0x0C
+#define M66592_LITTLE          0x0100  /* b8: Little endian mode */
+/* external chip case */
+#define M66592_PINCFG          0x0A
+#define M66592_LDRV            0x8000  /* b15: Drive Current Adjust */
+#define M66592_BIGEND          0x0100  /* b8: Big endian mode */
+
+#define M66592_DMA0CFG         0x0C
+#define M66592_DMA1CFG         0x0E
+#define M66592_DREQA           0x4000  /* b14: Dreq active select */
+#define M66592_BURST           0x2000  /* b13: Burst mode */
+#define M66592_DACKA           0x0400  /* b10: Dack active select */
+#define M66592_DFORM           0x0380  /* b9-7: DMA mode select */
+#define   M66592_CPU_ADR_RD_WR  0x0000   /* Address + RD/WR mode (CPU bus) */
+#define   M66592_CPU_DACK_RD_WR         0x0100   /* DACK + RD/WR mode (CPU bus) */
+#define   M66592_CPU_DACK_ONLY  0x0180   /* DACK only mode (CPU bus) */
+#define   M66592_SPLIT_DACK_ONLY 0x0200   /* DACK only mode (SPLIT bus) */
+#define   M66592_SPLIT_DACK_DSTB 0x0300   /* DACK + DSTB0 mode (SPLIT bus) */
+#define M66592_DENDA           0x0040  /* b6: Dend active select */
+#define M66592_PKTM            0x0020  /* b5: Packet mode */
+#define M66592_DENDE           0x0010  /* b4: Dend enable */
+#define M66592_OBUS            0x0004  /* b2: OUTbus mode */
+
+/* common case */
+#define M66592_CFIFO           0x10
+#define M66592_D0FIFO          0x14
+#define M66592_D1FIFO          0x18
+
+#define M66592_CFIFOSEL                0x1E
+#define M66592_D0FIFOSEL       0x24
+#define M66592_D1FIFOSEL       0x2A
+#define M66592_RCNT            0x8000  /* b15: Read count mode */
+#define M66592_REW             0x4000  /* b14: Buffer rewind */
+#define M66592_DCLRM           0x2000  /* b13: DMA buffer clear mode */
+#define M66592_DREQE           0x1000  /* b12: DREQ output enable */
+#define M66592_MBW_8           0x0000   /*  8bit */
+#define M66592_MBW_16          0x0400   /* 16bit */
+#define M66592_MBW_32          0x0800   /* 32bit */
+#define M66592_TRENB           0x0200  /* b9: Transaction counter enable */
+#define M66592_TRCLR           0x0100  /* b8: Transaction counter clear */
+#define M66592_DEZPM           0x0080  /* b7: Zero-length packet mode */
+#define M66592_ISEL            0x0020  /* b5: DCP FIFO port direction select */
+#define M66592_CURPIPE         0x0007  /* b2-0: PIPE select */
+
+#define M66592_CFIFOCTR                0x20
+#define M66592_D0FIFOCTR       0x26
+#define M66592_D1FIFOCTR       0x2c
+#define M66592_BVAL            0x8000  /* b15: Buffer valid flag */
+#define M66592_BCLR            0x4000  /* b14: Buffer clear */
+#define M66592_FRDY            0x2000  /* b13: FIFO ready */
+#define M66592_DTLN            0x0FFF  /* b11-0: FIFO received data length */
+
+#define M66592_CFIFOSIE                0x22
+#define M66592_TGL             0x8000  /* b15: Buffer toggle */
+#define M66592_SCLR            0x4000  /* b14: Buffer clear */
+#define M66592_SBUSY           0x2000  /* b13: SIE_FIFO busy */
+
+#define M66592_D0FIFOTRN       0x28
+#define M66592_D1FIFOTRN       0x2E
+#define M66592_TRNCNT          0xFFFF  /* b15-0: Transaction counter */
+
+#define M66592_INTENB0 0x30
+#define M66592_VBSE    0x8000  /* b15: VBUS interrupt */
+#define M66592_RSME    0x4000  /* b14: Resume interrupt */
+#define M66592_SOFE    0x2000  /* b13: Frame update interrupt */
+#define M66592_DVSE    0x1000  /* b12: Device state transition interrupt */
+#define M66592_CTRE    0x0800  /* b11: Control transfer stage transition irq */
+#define M66592_BEMPE   0x0400  /* b10: Buffer empty interrupt */
+#define M66592_NRDYE   0x0200  /* b9: Buffer not ready interrupt */
+#define M66592_BRDYE   0x0100  /* b8: Buffer ready interrupt */
+#define M66592_URST    0x0080  /* b7: USB reset detected interrupt */
+#define M66592_SADR    0x0040  /* b6: Set address executed interrupt */
+#define M66592_SCFG    0x0020  /* b5: Set configuration executed interrupt */
+#define M66592_SUSP    0x0010  /* b4: Suspend detected interrupt */
+#define M66592_WDST    0x0008  /* b3: Control write data stage completed irq */
+#define M66592_RDST    0x0004  /* b2: Control read data stage completed irq */
+#define M66592_CMPL    0x0002  /* b1: Control transfer complete interrupt */
+#define M66592_SERR    0x0001  /* b0: Sequence error interrupt */
+
+#define M66592_INTENB1 0x32
+#define M66592_BCHGE   0x4000  /* b14: USB us chenge interrupt */
+#define M66592_DTCHE   0x1000  /* b12: Detach sense interrupt */
+#define M66592_SIGNE   0x0020  /* b5: SETUP IGNORE interrupt */
+#define M66592_SACKE   0x0010  /* b4: SETUP ACK interrupt */
+#define M66592_BRDYM   0x0004  /* b2: BRDY clear timing */
+#define M66592_INTL    0x0002  /* b1: Interrupt sense select */
+#define M66592_PCSE    0x0001  /* b0: PCUT enable by CS assert */
+
+#define M66592_BRDYENB         0x36
+#define M66592_BRDYSTS         0x46
+#define M66592_BRDY7           0x0080  /* b7: PIPE7 */
+#define M66592_BRDY6           0x0040  /* b6: PIPE6 */
+#define M66592_BRDY5           0x0020  /* b5: PIPE5 */
+#define M66592_BRDY4           0x0010  /* b4: PIPE4 */
+#define M66592_BRDY3           0x0008  /* b3: PIPE3 */
+#define M66592_BRDY2           0x0004  /* b2: PIPE2 */
+#define M66592_BRDY1           0x0002  /* b1: PIPE1 */
+#define M66592_BRDY0           0x0001  /* b1: PIPE0 */
+
+#define M66592_NRDYENB         0x38
+#define M66592_NRDYSTS         0x48
+#define M66592_NRDY7           0x0080  /* b7: PIPE7 */
+#define M66592_NRDY6           0x0040  /* b6: PIPE6 */
+#define M66592_NRDY5           0x0020  /* b5: PIPE5 */
+#define M66592_NRDY4           0x0010  /* b4: PIPE4 */
+#define M66592_NRDY3           0x0008  /* b3: PIPE3 */
+#define M66592_NRDY2           0x0004  /* b2: PIPE2 */
+#define M66592_NRDY1           0x0002  /* b1: PIPE1 */
+#define M66592_NRDY0           0x0001  /* b1: PIPE0 */
+
+#define M66592_BEMPENB         0x3A
+#define M66592_BEMPSTS         0x4A
+#define M66592_BEMP7           0x0080  /* b7: PIPE7 */
+#define M66592_BEMP6           0x0040  /* b6: PIPE6 */
+#define M66592_BEMP5           0x0020  /* b5: PIPE5 */
+#define M66592_BEMP4           0x0010  /* b4: PIPE4 */
+#define M66592_BEMP3           0x0008  /* b3: PIPE3 */
+#define M66592_BEMP2           0x0004  /* b2: PIPE2 */
+#define M66592_BEMP1           0x0002  /* b1: PIPE1 */
+#define M66592_BEMP0           0x0001  /* b0: PIPE0 */
+
+#define M66592_SOFCFG          0x3C
+#define M66592_SOFM            0x000C  /* b3-2: SOF palse mode */
+#define   M66592_SOF_125US      0x0008   /* SOF OUT 125us uFrame Signal */
+#define   M66592_SOF_1MS        0x0004   /* SOF OUT 1ms Frame Signal */
+#define   M66592_SOF_DISABLE    0x0000   /* SOF OUT Disable */
+
+#define M66592_INTSTS0         0x40
+#define M66592_VBINT           0x8000  /* b15: VBUS interrupt */
+#define M66592_RESM            0x4000  /* b14: Resume interrupt */
+#define M66592_SOFR            0x2000  /* b13: SOF frame update interrupt */
+#define M66592_DVST            0x1000  /* b12: Device state transition */
+#define M66592_CTRT            0x0800  /* b11: Control stage transition */
+#define M66592_BEMP            0x0400  /* b10: Buffer empty interrupt */
+#define M66592_NRDY            0x0200  /* b9: Buffer not ready interrupt */
+#define M66592_BRDY            0x0100  /* b8: Buffer ready interrupt */
+#define M66592_VBSTS           0x0080  /* b7: VBUS input port */
+#define M66592_DVSQ            0x0070  /* b6-4: Device state */
+#define   M66592_DS_SPD_CNFG    0x0070    /* Suspend Configured */
+#define   M66592_DS_SPD_ADDR    0x0060    /* Suspend Address */
+#define   M66592_DS_SPD_DFLT    0x0050    /* Suspend Default */
+#define   M66592_DS_SPD_POWR    0x0040    /* Suspend Powered */
+#define   M66592_DS_SUSP        0x0040    /* Suspend */
+#define   M66592_DS_CNFG        0x0030    /* Configured */
+#define   M66592_DS_ADDS        0x0020    /* Address */
+#define   M66592_DS_DFLT        0x0010    /* Default */
+#define   M66592_DS_POWR        0x0000    /* Powered */
+#define M66592_DVSQS           0x0030  /* b5-4: Device state */
+#define M66592_VALID           0x0008  /* b3: Setup packet detected flag */
+#define M66592_CTSQ            0x0007  /* b2-0: Control transfer stage */
+#define   M66592_CS_SQER        0x0006   /* Sequence error */
+#define   M66592_CS_WRND        0x0005   /* Control write nodata status */
+#define   M66592_CS_WRSS        0x0004   /* Control write status stage */
+#define   M66592_CS_WRDS        0x0003   /* Control write data stage */
+#define   M66592_CS_RDSS        0x0002   /* Control read status stage */
+#define   M66592_CS_RDDS        0x0001   /* Control read data stage */
+#define   M66592_CS_IDST        0x0000   /* Idle or setup stage */
+
+#define M66592_INTSTS1         0x42
+#define M66592_BCHG            0x4000  /* b14: USB bus chenge interrupt */
+#define M66592_DTCH            0x1000  /* b12: Detach sense interrupt */
+#define M66592_SIGN            0x0020  /* b5: SETUP IGNORE interrupt */
+#define M66592_SACK            0x0010  /* b4: SETUP ACK interrupt */
+
+#define M66592_FRMNUM          0x4C
+#define M66592_OVRN            0x8000  /* b15: Overrun error */
+#define M66592_CRCE            0x4000  /* b14: Received data error */
+#define M66592_SOFRM           0x0800  /* b11: SOF output mode */
+#define M66592_FRNM            0x07FF  /* b10-0: Frame number */
+
+#define M66592_UFRMNUM         0x4E
+#define M66592_UFRNM           0x0007  /* b2-0: Micro frame number */
+
+#define M66592_RECOVER         0x50
+#define M66592_STSRECOV                0x0700  /* Status recovery */
+#define   M66592_STSR_HI        0x0400           /* FULL(0) or HI(1) Speed */
+#define   M66592_STSR_DEFAULT   0x0100           /* Default state */
+#define   M66592_STSR_ADDRESS   0x0200           /* Address state */
+#define   M66592_STSR_CONFIG    0x0300           /* Configured state */
+#define M66592_USBADDR         0x007F  /* b6-0: USB address */
+
+#define M66592_USBREQ                  0x54
+#define M66592_bRequest                        0xFF00  /* b15-8: bRequest */
+#define   M66592_GET_STATUS             0x0000
+#define   M66592_CLEAR_FEATURE          0x0100
+#define   M66592_ReqRESERVED            0x0200
+#define   M66592_SET_FEATURE            0x0300
+#define   M66592_ReqRESERVED1           0x0400
+#define   M66592_SET_ADDRESS            0x0500
+#define   M66592_GET_DESCRIPTOR                 0x0600
+#define   M66592_SET_DESCRIPTOR                 0x0700
+#define   M66592_GET_CONFIGURATION      0x0800
+#define   M66592_SET_CONFIGURATION      0x0900
+#define   M66592_GET_INTERFACE          0x0A00
+#define   M66592_SET_INTERFACE          0x0B00
+#define   M66592_SYNCH_FRAME            0x0C00
+#define M66592_bmRequestType           0x00FF  /* b7-0: bmRequestType */
+#define M66592_bmRequestTypeDir                0x0080  /* b7  : Data direction */
+#define   M66592_HOST_TO_DEVICE                 0x0000
+#define   M66592_DEVICE_TO_HOST                 0x0080
+#define M66592_bmRequestTypeType       0x0060  /* b6-5: Type */
+#define   M66592_STANDARD               0x0000
+#define   M66592_CLASS                  0x0020
+#define   M66592_VENDOR                         0x0040
+#define M66592_bmRequestTypeRecip      0x001F  /* b4-0: Recipient */
+#define   M66592_DEVICE                         0x0000
+#define   M66592_INTERFACE              0x0001
+#define   M66592_ENDPOINT               0x0002
+
+#define M66592_USBVAL                          0x56
+#define M66592_wValue                          0xFFFF  /* b15-0: wValue */
+/* Standard Feature Selector */
+#define   M66592_ENDPOINT_HALT                 0x0000
+#define   M66592_DEVICE_REMOTE_WAKEUP          0x0001
+#define   M66592_TEST_MODE                     0x0002
+/* Descriptor Types */
+#define M66592_DT_TYPE                         0xFF00
+#define M66592_GET_DT_TYPE(v)                  (((v) & DT_TYPE) >> 8)
+#define   M66592_DT_DEVICE                     0x01
+#define   M66592_DT_CONFIGURATION              0x02
+#define   M66592_DT_STRING                     0x03
+#define   M66592_DT_INTERFACE                  0x04
+#define   M66592_DT_ENDPOINT                   0x05
+#define   M66592_DT_DEVICE_QUALIFIER           0x06
+#define   M66592_DT_OTHER_SPEED_CONFIGURATION  0x07
+#define   M66592_DT_INTERFACE_POWER            0x08
+#define M66592_DT_INDEX                                0x00FF
+#define M66592_CONF_NUM                                0x00FF
+#define M66592_ALT_SET                         0x00FF
+
+#define M66592_USBINDEX                        0x58
+#define M66592_wIndex                  0xFFFF  /* b15-0: wIndex */
+#define M66592_TEST_SELECT             0xFF00  /* b15-b8: Test Mode */
+#define   M66592_TEST_J                         0x0100   /* Test_J */
+#define   M66592_TEST_K                         0x0200   /* Test_K */
+#define   M66592_TEST_SE0_NAK           0x0300   /* Test_SE0_NAK */
+#define   M66592_TEST_PACKET            0x0400   /* Test_Packet */
+#define   M66592_TEST_FORCE_ENABLE      0x0500   /* Test_Force_Enable */
+#define   M66592_TEST_STSelectors       0x0600   /* Standard test selectors */
+#define   M66592_TEST_Reserved          0x4000   /* Reserved */
+#define   M66592_TEST_VSTModes          0xC000   /* Vendor-specific tests */
+#define M66592_EP_DIR                  0x0080  /* b7: Endpoint Direction */
+#define   M66592_EP_DIR_IN              0x0080
+#define   M66592_EP_DIR_OUT             0x0000
+
+#define M66592_USBLENG         0x5A
+#define M66592_wLength         0xFFFF  /* b15-0: wLength */
+
+#define M66592_DCPCFG          0x5C
+#define M66592_CNTMD           0x0100  /* b8: Continuous transfer mode */
+#define M66592_DIR             0x0010  /* b4: Control transfer DIR select */
+
+#define M66592_DCPMAXP         0x5E
+#define M66592_DEVSEL          0xC000  /* b15-14: Device address select */
+#define   M66592_DEVICE_0       0x0000           /* Device address 0 */
+#define   M66592_DEVICE_1       0x4000           /* Device address 1 */
+#define   M66592_DEVICE_2       0x8000           /* Device address 2 */
+#define   M66592_DEVICE_3       0xC000           /* Device address 3 */
+#define M66592_MAXP            0x007F  /* b6-0: Maxpacket size of ep0 */
+
+#define M66592_DCPCTR          0x60
+#define M66592_BSTS            0x8000  /* b15: Buffer status */
+#define M66592_SUREQ           0x4000  /* b14: Send USB request  */
+#define M66592_SQCLR           0x0100  /* b8: Sequence toggle bit clear */
+#define M66592_SQSET           0x0080  /* b7: Sequence toggle bit set */
+#define M66592_SQMON           0x0040  /* b6: Sequence toggle bit monitor */
+#define M66592_CCPL            0x0004  /* b2: control transfer complete */
+#define M66592_PID             0x0003  /* b1-0: Response PID */
+#define   M66592_PID_STALL      0x0002           /* STALL */
+#define   M66592_PID_BUF        0x0001           /* BUF */
+#define   M66592_PID_NAK        0x0000           /* NAK */
+
+#define M66592_PIPESEL         0x64
+#define M66592_PIPENM          0x0007  /* b2-0: Pipe select */
+#define   M66592_PIPE0          0x0000           /* PIPE 0 */
+#define   M66592_PIPE1          0x0001           /* PIPE 1 */
+#define   M66592_PIPE2          0x0002           /* PIPE 2 */
+#define   M66592_PIPE3          0x0003           /* PIPE 3 */
+#define   M66592_PIPE4          0x0004           /* PIPE 4 */
+#define   M66592_PIPE5          0x0005           /* PIPE 5 */
+#define   M66592_PIPE6          0x0006           /* PIPE 6 */
+#define   M66592_PIPE7          0x0007           /* PIPE 7 */
+
+#define M66592_PIPECFG         0x66
+#define M66592_TYP             0xC000  /* b15-14: Transfer type */
+#define   M66592_ISO            0xC000           /* Isochronous */
+#define   M66592_INT            0x8000           /* Interrupt */
+#define   M66592_BULK           0x4000           /* Bulk */
+#define M66592_BFRE            0x0400  /* b10: Buffer ready interrupt mode */
+#define M66592_DBLB            0x0200  /* b9: Double buffer mode select */
+#define M66592_CNTMD           0x0100  /* b8: Continuous transfer mode */
+#define M66592_SHTNAK          0x0080  /* b7: Transfer end NAK */
+#define M66592_DIR             0x0010  /* b4: Transfer direction select */
+#define   M66592_DIR_H_OUT      0x0010           /* HOST OUT */
+#define   M66592_DIR_P_IN       0x0010           /* PERI IN */
+#define   M66592_DIR_H_IN       0x0000           /* HOST IN */
+#define   M66592_DIR_P_OUT      0x0000           /* PERI OUT */
+#define M66592_EPNUM           0x000F  /* b3-0: Eendpoint number select */
+#define   M66592_EP1            0x0001
+#define   M66592_EP2            0x0002
+#define   M66592_EP3            0x0003
+#define   M66592_EP4            0x0004
+#define   M66592_EP5            0x0005
+#define   M66592_EP6            0x0006
+#define   M66592_EP7            0x0007
+#define   M66592_EP8            0x0008
+#define   M66592_EP9            0x0009
+#define   M66592_EP10           0x000A
+#define   M66592_EP11           0x000B
+#define   M66592_EP12           0x000C
+#define   M66592_EP13           0x000D
+#define   M66592_EP14           0x000E
+#define   M66592_EP15           0x000F
+
+#define M66592_PIPEBUF         0x68
+#define M66592_BUFSIZE         0x7C00  /* b14-10: Pipe buffer size */
+#define M66592_BUF_SIZE(x)     ((((x) / 64) - 1) << 10)
+#define M66592_BUFNMB          0x00FF  /* b7-0: Pipe buffer number */
+
+#define M66592_PIPEMAXP                0x6A
+#define M66592_MXPS            0x07FF  /* b10-0: Maxpacket size */
+
+#define M66592_PIPEPERI                0x6C
+#define M66592_IFIS            0x1000  /* b12: ISO in-buffer flush mode */
+#define M66592_IITV            0x0007  /* b2-0: ISO interval */
+
+#define M66592_PIPE1CTR                0x70
+#define M66592_PIPE2CTR                0x72
+#define M66592_PIPE3CTR                0x74
+#define M66592_PIPE4CTR                0x76
+#define M66592_PIPE5CTR                0x78
+#define M66592_PIPE6CTR                0x7A
+#define M66592_PIPE7CTR                0x7C
+#define M66592_BSTS            0x8000  /* b15: Buffer status */
+#define M66592_INBUFM          0x4000  /* b14: IN buffer monitor (PIPE 1-5) */
+#define M66592_ACLRM           0x0200  /* b9: Out buffer auto clear mode */
+#define M66592_SQCLR           0x0100  /* b8: Sequence toggle bit clear */
+#define M66592_SQSET           0x0080  /* b7: Sequence toggle bit set */
+#define M66592_SQMON           0x0040  /* b6: Sequence toggle bit monitor */
+#define M66592_PID             0x0003  /* b1-0: Response PID */
+
+#define M66592_INVALID_REG     0x7E
+
+
+#define get_pipectr_addr(pipenum)      (M66592_PIPE1CTR + (pipenum - 1) * 2)
+
+#define M66592_MAX_SAMPLING    10
+
+#define M66592_MAX_NUM_PIPE    8
+#define M66592_MAX_NUM_BULK    3
+#define M66592_MAX_NUM_ISOC    2
+#define M66592_MAX_NUM_INT     2
+
+#define M66592_BASE_PIPENUM_BULK       3
+#define M66592_BASE_PIPENUM_ISOC       1
+#define M66592_BASE_PIPENUM_INT                6
+
+#define M66592_BASE_BUFNUM     6
+#define M66592_MAX_BUFNUM      0x4F
+
+struct m66592_pipe_info {
+       u16     pipe;
+       u16     epnum;
+       u16     maxpacket;
+       u16     type;
+       u16     interval;
+       u16     dir_in;
+};
+
+struct m66592_request {
+       struct usb_request      req;
+       struct list_head        queue;
+};
+
+struct m66592_ep {
+       struct usb_ep           ep;
+       struct m66592           *m66592;
+
+       struct list_head        queue;
+       unsigned                busy:1;
+       unsigned                internal_ccpl:1;        /* use only control */
+
+       /* this member can able to after m66592_enable */
+       unsigned                use_dma:1;
+       u16                     pipenum;
+       u16                     type;
+
+       /* register address */
+       unsigned long           fifoaddr;
+       unsigned long           fifosel;
+       unsigned long           fifoctr;
+       unsigned long           fifotrn;
+       unsigned long           pipectr;
+};
+
+struct m66592 {
+       spinlock_t              lock;
+       void __iomem            *reg;
+       struct clk *clk;
+       struct m66592_platdata  *pdata;
+       unsigned long           irq_trigger;
+
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+
+       struct m66592_ep        ep[M66592_MAX_NUM_PIPE];
+       struct m66592_ep        *pipenum2ep[M66592_MAX_NUM_PIPE];
+       struct m66592_ep        *epaddr2ep[16];
+
+       struct usb_request      *ep0_req;       /* for internal request */
+       __le16                  ep0_data;       /* for internal request */
+       u16                     old_vbus;
+
+       struct timer_list       timer;
+
+       int                     scount;
+
+       int                     old_dvsq;
+
+       /* pipe config */
+       int bulk;
+       int interrupt;
+       int isochronous;
+       int num_dma;
+};
+#define to_m66592(g)   (container_of((g), struct m66592, gadget))
+
+#define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget)
+#define m66592_to_gadget(m66592) (&m66592->gadget)
+
+#define is_bulk_pipe(pipenum)  \
+       ((pipenum >= M66592_BASE_PIPENUM_BULK) && \
+        (pipenum < (M66592_BASE_PIPENUM_BULK + M66592_MAX_NUM_BULK)))
+#define is_interrupt_pipe(pipenum)     \
+       ((pipenum >= M66592_BASE_PIPENUM_INT) && \
+        (pipenum < (M66592_BASE_PIPENUM_INT + M66592_MAX_NUM_INT)))
+#define is_isoc_pipe(pipenum)  \
+       ((pipenum >= M66592_BASE_PIPENUM_ISOC) && \
+        (pipenum < (M66592_BASE_PIPENUM_ISOC + M66592_MAX_NUM_ISOC)))
+
+#define enable_irq_ready(m66592, pipenum)      \
+       enable_pipe_irq(m66592, pipenum, M66592_BRDYENB)
+#define disable_irq_ready(m66592, pipenum)     \
+       disable_pipe_irq(m66592, pipenum, M66592_BRDYENB)
+#define enable_irq_empty(m66592, pipenum)      \
+       enable_pipe_irq(m66592, pipenum, M66592_BEMPENB)
+#define disable_irq_empty(m66592, pipenum)     \
+       disable_pipe_irq(m66592, pipenum, M66592_BEMPENB)
+#define enable_irq_nrdy(m66592, pipenum)       \
+       enable_pipe_irq(m66592, pipenum, M66592_NRDYENB)
+#define disable_irq_nrdy(m66592, pipenum)      \
+       disable_pipe_irq(m66592, pipenum, M66592_NRDYENB)
+
+/*-------------------------------------------------------------------------*/
+static inline u16 m66592_read(struct m66592 *m66592, unsigned long offset)
+{
+       return ioread16(m66592->reg + offset);
+}
+
+static inline void m66592_read_fifo(struct m66592 *m66592,
+               unsigned long offset,
+               void *buf, unsigned long len)
+{
+       void __iomem *fifoaddr = m66592->reg + offset;
+
+       if (m66592->pdata->on_chip) {
+               len = (len + 3) / 4;
+               ioread32_rep(fifoaddr, buf, len);
+       } else {
+               len = (len + 1) / 2;
+               ioread16_rep(fifoaddr, buf, len);
+       }
+}
+
+static inline void m66592_write(struct m66592 *m66592, u16 val,
+                               unsigned long offset)
+{
+       iowrite16(val, m66592->reg + offset);
+}
+
+static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
+               unsigned long offset)
+{
+       u16 tmp;
+       tmp = m66592_read(m66592, offset);
+       tmp = tmp & (~pat);
+       tmp = tmp | val;
+       m66592_write(m66592, tmp, offset);
+}
+
+#define m66592_bclr(m66592, val, offset)       \
+                       m66592_mdfy(m66592, 0, val, offset)
+#define m66592_bset(m66592, val, offset)       \
+                       m66592_mdfy(m66592, val, 0, offset)
+
+static inline void m66592_write_fifo(struct m66592 *m66592,
+               struct m66592_ep *ep,
+               void *buf, unsigned long len)
+{
+       void __iomem *fifoaddr = m66592->reg + ep->fifoaddr;
+
+       if (m66592->pdata->on_chip) {
+               unsigned long count;
+               unsigned char *pb;
+               int i;
+
+               count = len / 4;
+               iowrite32_rep(fifoaddr, buf, count);
+
+               if (len & 0x00000003) {
+                       pb = buf + count * 4;
+                       for (i = 0; i < (len & 0x00000003); i++) {
+                               if (m66592_read(m66592, M66592_CFBCFG)) /* le */
+                                       iowrite8(pb[i], fifoaddr + (3 - i));
+                               else
+                                       iowrite8(pb[i], fifoaddr + i);
+                       }
+               }
+       } else {
+               unsigned long odd = len & 0x0001;
+
+               len = len / 2;
+               iowrite16_rep(fifoaddr, buf, len);
+               if (odd) {
+                       unsigned char *p = buf + len*2;
+                       if (m66592->pdata->wr0_shorted_to_wr1)
+                               m66592_bclr(m66592, M66592_MBW_16, ep->fifosel);
+                       iowrite8(*p, fifoaddr);
+                       if (m66592->pdata->wr0_shorted_to_wr1)
+                               m66592_bset(m66592, M66592_MBW_16, ep->fifosel);
+               }
+       }
+}
+
+#endif /* ifndef __M66592_UDC_H__ */
+
+
diff --git a/drivers/usb/gadget/udc/mv_u3d.h b/drivers/usb/gadget/udc/mv_u3d.h
new file mode 100644 (file)
index 0000000..e32a787
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#ifndef __MV_U3D_H
+#define __MV_U3D_H
+
+#define MV_U3D_EP_CONTEXT_ALIGNMENT    32
+#define MV_U3D_TRB_ALIGNMENT   16
+#define MV_U3D_DMA_BOUNDARY    4096
+#define MV_U3D_EP0_MAX_PKT_SIZE        512
+
+/* ep0 transfer state */
+#define MV_U3D_WAIT_FOR_SETUP          0
+#define MV_U3D_DATA_STATE_XMIT         1
+#define MV_U3D_DATA_STATE_NEED_ZLP     2
+#define MV_U3D_WAIT_FOR_OUT_STATUS     3
+#define MV_U3D_DATA_STATE_RECV         4
+#define MV_U3D_STATUS_STAGE            5
+
+#define MV_U3D_EP_MAX_LENGTH_TRANSFER  0x10000
+
+/* USB3 Interrupt Status */
+#define MV_U3D_USBINT_SETUP            0x00000001
+#define MV_U3D_USBINT_RX_COMPLETE      0x00000002
+#define MV_U3D_USBINT_TX_COMPLETE      0x00000004
+#define MV_U3D_USBINT_UNDER_RUN        0x00000008
+#define MV_U3D_USBINT_RXDESC_ERR       0x00000010
+#define MV_U3D_USBINT_TXDESC_ERR       0x00000020
+#define MV_U3D_USBINT_RX_TRB_COMPLETE  0x00000040
+#define MV_U3D_USBINT_TX_TRB_COMPLETE  0x00000080
+#define MV_U3D_USBINT_VBUS_VALID       0x00010000
+#define MV_U3D_USBINT_STORAGE_CMD_FULL 0x00020000
+#define MV_U3D_USBINT_LINK_CHG         0x01000000
+
+/* USB3 Interrupt Enable */
+#define MV_U3D_INTR_ENABLE_SETUP               0x00000001
+#define MV_U3D_INTR_ENABLE_RX_COMPLETE         0x00000002
+#define MV_U3D_INTR_ENABLE_TX_COMPLETE         0x00000004
+#define MV_U3D_INTR_ENABLE_UNDER_RUN           0x00000008
+#define MV_U3D_INTR_ENABLE_RXDESC_ERR          0x00000010
+#define MV_U3D_INTR_ENABLE_TXDESC_ERR          0x00000020
+#define MV_U3D_INTR_ENABLE_RX_TRB_COMPLETE     0x00000040
+#define MV_U3D_INTR_ENABLE_TX_TRB_COMPLETE     0x00000080
+#define MV_U3D_INTR_ENABLE_RX_BUFFER_ERR       0x00000100
+#define MV_U3D_INTR_ENABLE_VBUS_VALID          0x00010000
+#define MV_U3D_INTR_ENABLE_STORAGE_CMD_FULL    0x00020000
+#define MV_U3D_INTR_ENABLE_LINK_CHG            0x01000000
+#define MV_U3D_INTR_ENABLE_PRIME_STATUS        0x02000000
+
+/* USB3 Link Change */
+#define MV_U3D_LINK_CHANGE_LINK_UP             0x00000001
+#define MV_U3D_LINK_CHANGE_SUSPEND             0x00000002
+#define MV_U3D_LINK_CHANGE_RESUME              0x00000004
+#define MV_U3D_LINK_CHANGE_WRESET              0x00000008
+#define MV_U3D_LINK_CHANGE_HRESET              0x00000010
+#define MV_U3D_LINK_CHANGE_VBUS_INVALID        0x00000020
+#define MV_U3D_LINK_CHANGE_INACT               0x00000040
+#define MV_U3D_LINK_CHANGE_DISABLE_AFTER_U0    0x00000080
+#define MV_U3D_LINK_CHANGE_U1                  0x00000100
+#define MV_U3D_LINK_CHANGE_U2                  0x00000200
+#define MV_U3D_LINK_CHANGE_U3                  0x00000400
+
+/* bridge setting */
+#define MV_U3D_BRIDGE_SETTING_VBUS_VALID       (1 << 16)
+
+/* Command Register Bit Masks */
+#define MV_U3D_CMD_RUN_STOP            0x00000001
+#define MV_U3D_CMD_CTRL_RESET          0x00000002
+
+/* ep control register */
+#define MV_U3D_EPXCR_EP_TYPE_CONTROL           0
+#define MV_U3D_EPXCR_EP_TYPE_ISOC              1
+#define MV_U3D_EPXCR_EP_TYPE_BULK              2
+#define MV_U3D_EPXCR_EP_TYPE_INT               3
+#define MV_U3D_EPXCR_EP_ENABLE_SHIFT           4
+#define MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT      12
+#define MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT     16
+#define MV_U3D_USB_BULK_BURST_OUT              6
+#define MV_U3D_USB_BULK_BURST_IN               14
+
+#define MV_U3D_EPXCR_EP_FLUSH          (1 << 7)
+#define MV_U3D_EPXCR_EP_HALT           (1 << 1)
+#define MV_U3D_EPXCR_EP_INIT           (1)
+
+/* TX/RX Status Register */
+#define MV_U3D_XFERSTATUS_COMPLETE_SHIFT       24
+#define MV_U3D_COMPLETE_INVALID        0
+#define MV_U3D_COMPLETE_SUCCESS        1
+#define MV_U3D_COMPLETE_BUFF_ERR       2
+#define MV_U3D_COMPLETE_SHORT_PACKET   3
+#define MV_U3D_COMPLETE_TRB_ERR        5
+#define MV_U3D_XFERSTATUS_TRB_LENGTH_MASK      (0xFFFFFF)
+
+#define MV_U3D_USB_LINK_BYPASS_VBUS    0x8
+
+#define MV_U3D_LTSSM_PHY_INIT_DONE             0x80000000
+#define MV_U3D_LTSSM_NEVER_GO_COMPLIANCE       0x40000000
+
+#define MV_U3D_USB3_OP_REGS_OFFSET     0x100
+#define MV_U3D_USB3_PHY_OFFSET         0xB800
+
+#define DCS_ENABLE     0x1
+
+/* timeout */
+#define MV_U3D_RESET_TIMEOUT           10000
+#define MV_U3D_FLUSH_TIMEOUT           100000
+#define MV_U3D_OWN_TIMEOUT             10000
+#define LOOPS_USEC_SHIFT       4
+#define LOOPS_USEC             (1 << LOOPS_USEC_SHIFT)
+#define LOOPS(timeout)         ((timeout) >> LOOPS_USEC_SHIFT)
+
+/* ep direction */
+#define MV_U3D_EP_DIR_IN               1
+#define MV_U3D_EP_DIR_OUT              0
+#define mv_u3d_ep_dir(ep)      (((ep)->ep_num == 0) ? \
+                               ((ep)->u3d->ep0_dir) : ((ep)->direction))
+
+/* usb capability registers */
+struct mv_u3d_cap_regs {
+       u32     rsvd[5];
+       u32     dboff;  /* doorbell register offset */
+       u32     rtsoff; /* runtime register offset */
+       u32     vuoff;  /* vendor unique register offset */
+};
+
+/* operation registers */
+struct mv_u3d_op_regs {
+       u32     usbcmd;         /* Command register */
+       u32     rsvd1[11];
+       u32     dcbaapl;        /* Device Context Base Address low register */
+       u32     dcbaaph;        /* Device Context Base Address high register */
+       u32     rsvd2[243];
+       u32     portsc;         /* port status and control register*/
+       u32     portlinkinfo;   /* port link info register*/
+       u32     rsvd3[9917];
+       u32     doorbell;       /* doorbell register */
+};
+
+/* control enpoint enable registers */
+struct epxcr {
+       u32     epxoutcr0;      /* ep out control 0 register */
+       u32     epxoutcr1;      /* ep out control 1 register */
+       u32     epxincr0;       /* ep in control 0 register */
+       u32     epxincr1;       /* ep in control 1 register */
+};
+
+/* transfer status registers */
+struct xferstatus {
+       u32     curdeqlo;       /* current TRB pointer low */
+       u32     curdeqhi;       /* current TRB pointer high */
+       u32     statuslo;       /* transfer status low */
+       u32     statushi;       /* transfer status high */
+};
+
+/* vendor unique control registers */
+struct mv_u3d_vuc_regs {
+       u32     ctrlepenable;   /* control endpoint enable register */
+       u32     setuplock;      /* setup lock register */
+       u32     endcomplete;    /* endpoint transfer complete register */
+       u32     intrcause;      /* interrupt cause register */
+       u32     intrenable;     /* interrupt enable register */
+       u32     trbcomplete;    /* TRB complete register */
+       u32     linkchange;     /* link change register */
+       u32     rsvd1[5];
+       u32     trbunderrun;    /* TRB underrun register */
+       u32     rsvd2[43];
+       u32     bridgesetting;  /* bridge setting register */
+       u32     rsvd3[7];
+       struct xferstatus       txst[16];       /* TX status register */
+       struct xferstatus       rxst[16];       /* RX status register */
+       u32     ltssm;          /* LTSSM control register */
+       u32     pipe;           /* PIPE control register */
+       u32     linkcr0;        /* link control 0 register */
+       u32     linkcr1;        /* link control 1 register */
+       u32     rsvd6[60];
+       u32     mib0;           /* MIB0 counter register */
+       u32     usblink;        /* usb link control register */
+       u32     ltssmstate;     /* LTSSM state register */
+       u32     linkerrorcause; /* link error cause register */
+       u32     rsvd7[60];
+       u32     devaddrtiebrkr; /* device address and tie breaker */
+       u32     itpinfo0;       /* ITP info 0 register */
+       u32     itpinfo1;       /* ITP info 1 register */
+       u32     rsvd8[61];
+       struct epxcr    epcr[16];       /* ep control register */
+       u32     rsvd9[64];
+       u32     phyaddr;        /* PHY address register */
+       u32     phydata;        /* PHY data register */
+};
+
+/* Endpoint context structure */
+struct mv_u3d_ep_context {
+       u32     rsvd0;
+       u32     rsvd1;
+       u32     trb_addr_lo;            /* TRB address low 32 bit */
+       u32     trb_addr_hi;            /* TRB address high 32 bit */
+       u32     rsvd2;
+       u32     rsvd3;
+       struct usb_ctrlrequest setup_buffer;    /* setup data buffer */
+};
+
+/* TRB control data structure */
+struct mv_u3d_trb_ctrl {
+       u32     own:1;          /* owner of TRB */
+       u32     rsvd1:3;
+       u32     chain:1;        /* associate this TRB with the
+                               next TRB on the Ring */
+       u32     ioc:1;          /* interrupt on complete */
+       u32     rsvd2:4;
+       u32     type:6;         /* TRB type */
+#define TYPE_NORMAL    1
+#define TYPE_DATA      3
+#define TYPE_LINK      6
+       u32     dir:1;          /* Working at data stage of control endpoint
+                               operation. 0 is OUT and 1 is IN. */
+       u32     rsvd3:15;
+};
+
+/* TRB data structure
+ * For multiple TRB, all the TRBs' physical address should be continuous.
+ */
+struct mv_u3d_trb_hw {
+       u32     buf_addr_lo;    /* data buffer address low 32 bit */
+       u32     buf_addr_hi;    /* data buffer address high 32 bit */
+       u32     trb_len;        /* transfer length */
+       struct mv_u3d_trb_ctrl  ctrl;   /* TRB control data */
+};
+
+/* TRB structure */
+struct mv_u3d_trb {
+       struct mv_u3d_trb_hw *trb_hw;   /* point to the trb_hw structure */
+       dma_addr_t trb_dma;             /* dma address for this trb_hw */
+       struct list_head trb_list;      /* trb list */
+};
+
+/* device data structure */
+struct mv_u3d {
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+       spinlock_t                      lock;   /* device lock */
+       struct completion               *done;
+       struct device                   *dev;
+       int                             irq;
+
+       /* usb controller registers */
+       struct mv_u3d_cap_regs __iomem  *cap_regs;
+       struct mv_u3d_op_regs __iomem   *op_regs;
+       struct mv_u3d_vuc_regs __iomem  *vuc_regs;
+       void __iomem                    *phy_regs;
+
+       unsigned int                    max_eps;
+       struct mv_u3d_ep_context        *ep_context;
+       size_t                          ep_context_size;
+       dma_addr_t                      ep_context_dma;
+
+       struct dma_pool                 *trb_pool; /* for TRB data structure */
+       struct mv_u3d_ep                *eps;
+
+       struct mv_u3d_req               *status_req; /* ep0 status request */
+       struct usb_ctrlrequest          local_setup_buff; /* store setup data*/
+
+       unsigned int            resume_state;   /* USB state to resume */
+       unsigned int            usb_state;      /* USB current state */
+       unsigned int            ep0_state;      /* Endpoint zero state */
+       unsigned int            ep0_dir;
+
+       unsigned int            dev_addr;       /* device address */
+
+       unsigned int            errors;
+
+       unsigned                softconnect:1;
+       unsigned                vbus_active:1;  /* vbus is active or not */
+       unsigned                remote_wakeup:1; /* support remote wakeup */
+       unsigned                clock_gating:1; /* clock gating or not */
+       unsigned                active:1;       /* udc is active or not */
+       unsigned                vbus_valid_detect:1; /* udc vbus detection */
+
+       struct mv_usb_addon_irq *vbus;
+       unsigned int            power;
+
+       struct clk              *clk;
+};
+
+/* endpoint data structure */
+struct mv_u3d_ep {
+       struct usb_ep           ep;
+       struct mv_u3d           *u3d;
+       struct list_head        queue;  /* ep request queued hardware */
+       struct list_head        req_list; /* list of ep request */
+       struct mv_u3d_ep_context        *ep_context; /* ep context */
+       u32                     direction;
+       char                    name[14];
+       u32                     processing; /* there is ep request
+                                               queued on haredware */
+       spinlock_t              req_lock; /* ep lock */
+       unsigned                wedge:1;
+       unsigned                enabled:1;
+       unsigned                ep_type:2;
+       unsigned                ep_num:8;
+};
+
+/* request data structure */
+struct mv_u3d_req {
+       struct usb_request      req;
+       struct mv_u3d_ep        *ep;
+       struct list_head        queue;  /* ep requst queued on hardware */
+       struct list_head        list;   /* ep request list */
+       struct list_head        trb_list; /* trb list of a request */
+
+       struct mv_u3d_trb       *trb_head; /* point to first trb of a request */
+       unsigned                trb_count; /* TRB number in the chain */
+       unsigned                chain;     /* TRB chain or not */
+};
+
+#endif
diff --git a/drivers/usb/gadget/udc/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c
new file mode 100644 (file)
index 0000000..1624871
--- /dev/null
@@ -0,0 +1,2070 @@
+/*
+ * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/notifier.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/pm.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/mv_usb.h>
+#include <linux/clk.h>
+
+#include "mv_u3d.h"
+
+#define DRIVER_DESC            "Marvell PXA USB3.0 Device Controller driver"
+
+static const char driver_name[] = "mv_u3d";
+static const char driver_desc[] = DRIVER_DESC;
+
+static void mv_u3d_nuke(struct mv_u3d_ep *ep, int status);
+static void mv_u3d_stop_activity(struct mv_u3d *u3d,
+                       struct usb_gadget_driver *driver);
+
+/* for endpoint 0 operations */
+static const struct usb_endpoint_descriptor mv_u3d_ep0_desc = {
+       .bLength =              USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bEndpointAddress =     0,
+       .bmAttributes =         USB_ENDPOINT_XFER_CONTROL,
+       .wMaxPacketSize =       MV_U3D_EP0_MAX_PKT_SIZE,
+};
+
+static void mv_u3d_ep0_reset(struct mv_u3d *u3d)
+{
+       struct mv_u3d_ep *ep;
+       u32 epxcr;
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               ep = &u3d->eps[i];
+               ep->u3d = u3d;
+
+               /* ep0 ep context, ep0 in and out share the same ep context */
+               ep->ep_context = &u3d->ep_context[1];
+       }
+
+       /* reset ep state machine */
+       /* reset ep0 out */
+       epxcr = ioread32(&u3d->vuc_regs->epcr[0].epxoutcr0);
+       epxcr |= MV_U3D_EPXCR_EP_INIT;
+       iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxoutcr0);
+       udelay(5);
+       epxcr &= ~MV_U3D_EPXCR_EP_INIT;
+       iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxoutcr0);
+
+       epxcr = ((MV_U3D_EP0_MAX_PKT_SIZE
+               << MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT)
+               | (1 << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT)
+               | (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
+               | MV_U3D_EPXCR_EP_TYPE_CONTROL);
+       iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxoutcr1);
+
+       /* reset ep0 in */
+       epxcr = ioread32(&u3d->vuc_regs->epcr[0].epxincr0);
+       epxcr |= MV_U3D_EPXCR_EP_INIT;
+       iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxincr0);
+       udelay(5);
+       epxcr &= ~MV_U3D_EPXCR_EP_INIT;
+       iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxincr0);
+
+       epxcr = ((MV_U3D_EP0_MAX_PKT_SIZE
+               << MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT)
+               | (1 << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT)
+               | (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
+               | MV_U3D_EPXCR_EP_TYPE_CONTROL);
+       iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxincr1);
+}
+
+static void mv_u3d_ep0_stall(struct mv_u3d *u3d)
+{
+       u32 tmp;
+       dev_dbg(u3d->dev, "%s\n", __func__);
+
+       /* set TX and RX to stall */
+       tmp = ioread32(&u3d->vuc_regs->epcr[0].epxoutcr0);
+       tmp |= MV_U3D_EPXCR_EP_HALT;
+       iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxoutcr0);
+
+       tmp = ioread32(&u3d->vuc_regs->epcr[0].epxincr0);
+       tmp |= MV_U3D_EPXCR_EP_HALT;
+       iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxincr0);
+
+       /* update ep0 state */
+       u3d->ep0_state = MV_U3D_WAIT_FOR_SETUP;
+       u3d->ep0_dir = MV_U3D_EP_DIR_OUT;
+}
+
+static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
+       struct mv_u3d_req *curr_req)
+{
+       struct mv_u3d_trb       *curr_trb;
+       dma_addr_t cur_deq_lo;
+       struct mv_u3d_ep_context        *curr_ep_context;
+       int trb_complete, actual, remaining_length = 0;
+       int direction, ep_num;
+       int retval = 0;
+       u32 tmp, status, length;
+
+       curr_ep_context = &u3d->ep_context[index];
+       direction = index % 2;
+       ep_num = index / 2;
+
+       trb_complete = 0;
+       actual = curr_req->req.length;
+
+       while (!list_empty(&curr_req->trb_list)) {
+               curr_trb = list_entry(curr_req->trb_list.next,
+                                       struct mv_u3d_trb, trb_list);
+               if (!curr_trb->trb_hw->ctrl.own) {
+                       dev_err(u3d->dev, "%s, TRB own error!\n",
+                               u3d->eps[index].name);
+                       return 1;
+               }
+
+               curr_trb->trb_hw->ctrl.own = 0;
+               if (direction == MV_U3D_EP_DIR_OUT) {
+                       tmp = ioread32(&u3d->vuc_regs->rxst[ep_num].statuslo);
+                       cur_deq_lo =
+                               ioread32(&u3d->vuc_regs->rxst[ep_num].curdeqlo);
+               } else {
+                       tmp = ioread32(&u3d->vuc_regs->txst[ep_num].statuslo);
+                       cur_deq_lo =
+                               ioread32(&u3d->vuc_regs->txst[ep_num].curdeqlo);
+               }
+
+               status = tmp >> MV_U3D_XFERSTATUS_COMPLETE_SHIFT;
+               length = tmp & MV_U3D_XFERSTATUS_TRB_LENGTH_MASK;
+
+               if (status == MV_U3D_COMPLETE_SUCCESS ||
+                       (status == MV_U3D_COMPLETE_SHORT_PACKET &&
+                       direction == MV_U3D_EP_DIR_OUT)) {
+                       remaining_length += length;
+                       actual -= remaining_length;
+               } else {
+                       dev_err(u3d->dev,
+                               "complete_tr error: ep=%d %s: error = 0x%x\n",
+                               index >> 1, direction ? "SEND" : "RECV",
+                               status);
+                       retval = -EPROTO;
+               }
+
+               list_del_init(&curr_trb->trb_list);
+       }
+       if (retval)
+               return retval;
+
+       curr_req->req.actual = actual;
+       return 0;
+}
+
+/*
+ * mv_u3d_done() - retire a request; caller blocked irqs
+ * @status : request status to be set, only works when
+ * request is still in progress.
+ */
+static
+void mv_u3d_done(struct mv_u3d_ep *ep, struct mv_u3d_req *req, int status)
+       __releases(&ep->udc->lock)
+       __acquires(&ep->udc->lock)
+{
+       struct mv_u3d *u3d = (struct mv_u3d *)ep->u3d;
+
+       dev_dbg(u3d->dev, "mv_u3d_done: remove req->queue\n");
+       /* Removed the req from ep queue */
+       list_del_init(&req->queue);
+
+       /* req.status should be set as -EINPROGRESS in ep_queue() */
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       /* Free trb for the request */
+       if (!req->chain)
+               dma_pool_free(u3d->trb_pool,
+                       req->trb_head->trb_hw, req->trb_head->trb_dma);
+       else {
+               dma_unmap_single(ep->u3d->gadget.dev.parent,
+                       (dma_addr_t)req->trb_head->trb_dma,
+                       req->trb_count * sizeof(struct mv_u3d_trb_hw),
+                       DMA_BIDIRECTIONAL);
+               kfree(req->trb_head->trb_hw);
+       }
+       kfree(req->trb_head);
+
+       usb_gadget_unmap_request(&u3d->gadget, &req->req, mv_u3d_ep_dir(ep));
+
+       if (status && (status != -ESHUTDOWN)) {
+               dev_dbg(u3d->dev, "complete %s req %p stat %d len %u/%u",
+                       ep->ep.name, &req->req, status,
+                       req->req.actual, req->req.length);
+       }
+
+       spin_unlock(&ep->u3d->lock);
+       /*
+        * complete() is from gadget layer,
+        * eg fsg->bulk_in_complete()
+        */
+       if (req->req.complete)
+               req->req.complete(&ep->ep, &req->req);
+
+       spin_lock(&ep->u3d->lock);
+}
+
+static int mv_u3d_queue_trb(struct mv_u3d_ep *ep, struct mv_u3d_req *req)
+{
+       u32 tmp, direction;
+       struct mv_u3d *u3d;
+       struct mv_u3d_ep_context *ep_context;
+       int retval = 0;
+
+       u3d = ep->u3d;
+       direction = mv_u3d_ep_dir(ep);
+
+       /* ep0 in and out share the same ep context slot 1*/
+       if (ep->ep_num == 0)
+               ep_context = &(u3d->ep_context[1]);
+       else
+               ep_context = &(u3d->ep_context[ep->ep_num * 2 + direction]);
+
+       /* check if the pipe is empty or not */
+       if (!list_empty(&ep->queue)) {
+               dev_err(u3d->dev, "add trb to non-empty queue!\n");
+               retval = -ENOMEM;
+               WARN_ON(1);
+       } else {
+               ep_context->rsvd0 = cpu_to_le32(1);
+               ep_context->rsvd1 = 0;
+
+               /* Configure the trb address and set the DCS bit.
+                * Both DCS bit and own bit in trb should be set.
+                */
+               ep_context->trb_addr_lo =
+                       cpu_to_le32(req->trb_head->trb_dma | DCS_ENABLE);
+               ep_context->trb_addr_hi = 0;
+
+               /* Ensure that updates to the EP Context will
+                * occure before Ring Bell.
+                */
+               wmb();
+
+               /* ring bell the ep */
+               if (ep->ep_num == 0)
+                       tmp = 0x1;
+               else
+                       tmp = ep->ep_num * 2
+                               + ((direction == MV_U3D_EP_DIR_OUT) ? 0 : 1);
+
+               iowrite32(tmp, &u3d->op_regs->doorbell);
+       }
+       return retval;
+}
+
+static struct mv_u3d_trb *mv_u3d_build_trb_one(struct mv_u3d_req *req,
+                               unsigned *length, dma_addr_t *dma)
+{
+       u32 temp;
+       unsigned int direction;
+       struct mv_u3d_trb *trb;
+       struct mv_u3d_trb_hw *trb_hw;
+       struct mv_u3d *u3d;
+
+       /* how big will this transfer be? */
+       *length = req->req.length - req->req.actual;
+       BUG_ON(*length > (unsigned)MV_U3D_EP_MAX_LENGTH_TRANSFER);
+
+       u3d = req->ep->u3d;
+
+       trb = kzalloc(sizeof(*trb), GFP_ATOMIC);
+       if (!trb)
+               return NULL;
+
+       /*
+        * Be careful that no _GFP_HIGHMEM is set,
+        * or we can not use dma_to_virt
+        * cannot use GFP_KERNEL in spin lock
+        */
+       trb_hw = dma_pool_alloc(u3d->trb_pool, GFP_ATOMIC, dma);
+       if (!trb_hw) {
+               kfree(trb);
+               dev_err(u3d->dev,
+                       "%s, dma_pool_alloc fail\n", __func__);
+               return NULL;
+       }
+       trb->trb_dma = *dma;
+       trb->trb_hw = trb_hw;
+
+       /* initialize buffer page pointers */
+       temp = (u32)(req->req.dma + req->req.actual);
+
+       trb_hw->buf_addr_lo = cpu_to_le32(temp);
+       trb_hw->buf_addr_hi = 0;
+       trb_hw->trb_len = cpu_to_le32(*length);
+       trb_hw->ctrl.own = 1;
+
+       if (req->ep->ep_num == 0)
+               trb_hw->ctrl.type = TYPE_DATA;
+       else
+               trb_hw->ctrl.type = TYPE_NORMAL;
+
+       req->req.actual += *length;
+
+       direction = mv_u3d_ep_dir(req->ep);
+       if (direction == MV_U3D_EP_DIR_IN)
+               trb_hw->ctrl.dir = 1;
+       else
+               trb_hw->ctrl.dir = 0;
+
+       /* Enable interrupt for the last trb of a request */
+       if (!req->req.no_interrupt)
+               trb_hw->ctrl.ioc = 1;
+
+       trb_hw->ctrl.chain = 0;
+
+       wmb();
+       return trb;
+}
+
+static int mv_u3d_build_trb_chain(struct mv_u3d_req *req, unsigned *length,
+               struct mv_u3d_trb *trb, int *is_last)
+{
+       u32 temp;
+       unsigned int direction;
+       struct mv_u3d *u3d;
+
+       /* how big will this transfer be? */
+       *length = min(req->req.length - req->req.actual,
+                       (unsigned)MV_U3D_EP_MAX_LENGTH_TRANSFER);
+
+       u3d = req->ep->u3d;
+
+       trb->trb_dma = 0;
+
+       /* initialize buffer page pointers */
+       temp = (u32)(req->req.dma + req->req.actual);
+
+       trb->trb_hw->buf_addr_lo = cpu_to_le32(temp);
+       trb->trb_hw->buf_addr_hi = 0;
+       trb->trb_hw->trb_len = cpu_to_le32(*length);
+       trb->trb_hw->ctrl.own = 1;
+
+       if (req->ep->ep_num == 0)
+               trb->trb_hw->ctrl.type = TYPE_DATA;
+       else
+               trb->trb_hw->ctrl.type = TYPE_NORMAL;
+
+       req->req.actual += *length;
+
+       direction = mv_u3d_ep_dir(req->ep);
+       if (direction == MV_U3D_EP_DIR_IN)
+               trb->trb_hw->ctrl.dir = 1;
+       else
+               trb->trb_hw->ctrl.dir = 0;
+
+       /* zlp is needed if req->req.zero is set */
+       if (req->req.zero) {
+               if (*length == 0 || (*length % req->ep->ep.maxpacket) != 0)
+                       *is_last = 1;
+               else
+                       *is_last = 0;
+       } else if (req->req.length == req->req.actual)
+               *is_last = 1;
+       else
+               *is_last = 0;
+
+       /* Enable interrupt for the last trb of a request */
+       if (*is_last && !req->req.no_interrupt)
+               trb->trb_hw->ctrl.ioc = 1;
+
+       if (*is_last)
+               trb->trb_hw->ctrl.chain = 0;
+       else {
+               trb->trb_hw->ctrl.chain = 1;
+               dev_dbg(u3d->dev, "chain trb\n");
+       }
+
+       wmb();
+
+       return 0;
+}
+
+/* generate TRB linked list for a request
+ * usb controller only supports continous trb chain,
+ * that trb structure physical address should be continous.
+ */
+static int mv_u3d_req_to_trb(struct mv_u3d_req *req)
+{
+       unsigned count;
+       int is_last;
+       struct mv_u3d_trb *trb;
+       struct mv_u3d_trb_hw *trb_hw;
+       struct mv_u3d *u3d;
+       dma_addr_t dma;
+       unsigned length;
+       unsigned trb_num;
+
+       u3d = req->ep->u3d;
+
+       INIT_LIST_HEAD(&req->trb_list);
+
+       length = req->req.length - req->req.actual;
+       /* normally the request transfer length is less than 16KB.
+        * we use buil_trb_one() to optimize it.
+        */
+       if (length <= (unsigned)MV_U3D_EP_MAX_LENGTH_TRANSFER) {
+               trb = mv_u3d_build_trb_one(req, &count, &dma);
+               list_add_tail(&trb->trb_list, &req->trb_list);
+               req->trb_head = trb;
+               req->trb_count = 1;
+               req->chain = 0;
+       } else {
+               trb_num = length / MV_U3D_EP_MAX_LENGTH_TRANSFER;
+               if (length % MV_U3D_EP_MAX_LENGTH_TRANSFER)
+                       trb_num++;
+
+               trb = kcalloc(trb_num, sizeof(*trb), GFP_ATOMIC);
+               if (!trb)
+                       return -ENOMEM;
+
+               trb_hw = kcalloc(trb_num, sizeof(*trb_hw), GFP_ATOMIC);
+               if (!trb_hw) {
+                       kfree(trb);
+                       return -ENOMEM;
+               }
+
+               do {
+                       trb->trb_hw = trb_hw;
+                       if (mv_u3d_build_trb_chain(req, &count,
+                                               trb, &is_last)) {
+                               dev_err(u3d->dev,
+                                       "%s, mv_u3d_build_trb_chain fail\n",
+                                       __func__);
+                               return -EIO;
+                       }
+
+                       list_add_tail(&trb->trb_list, &req->trb_list);
+                       req->trb_count++;
+                       trb++;
+                       trb_hw++;
+               } while (!is_last);
+
+               req->trb_head = list_entry(req->trb_list.next,
+                                       struct mv_u3d_trb, trb_list);
+               req->trb_head->trb_dma = dma_map_single(u3d->gadget.dev.parent,
+                                       req->trb_head->trb_hw,
+                                       trb_num * sizeof(*trb_hw),
+                                       DMA_BIDIRECTIONAL);
+
+               req->chain = 1;
+       }
+
+       return 0;
+}
+
+static int
+mv_u3d_start_queue(struct mv_u3d_ep *ep)
+{
+       struct mv_u3d *u3d = ep->u3d;
+       struct mv_u3d_req *req;
+       int ret;
+
+       if (!list_empty(&ep->req_list) && !ep->processing)
+               req = list_entry(ep->req_list.next, struct mv_u3d_req, list);
+       else
+               return 0;
+
+       ep->processing = 1;
+
+       /* set up dma mapping */
+       ret = usb_gadget_map_request(&u3d->gadget, &req->req,
+                                       mv_u3d_ep_dir(ep));
+       if (ret)
+               return ret;
+
+       req->req.status = -EINPROGRESS;
+       req->req.actual = 0;
+       req->trb_count = 0;
+
+       /* build trbs and push them to device queue */
+       if (!mv_u3d_req_to_trb(req)) {
+               ret = mv_u3d_queue_trb(ep, req);
+               if (ret) {
+                       ep->processing = 0;
+                       return ret;
+               }
+       } else {
+               ep->processing = 0;
+               dev_err(u3d->dev, "%s, mv_u3d_req_to_trb fail\n", __func__);
+               return -ENOMEM;
+       }
+
+       /* irq handler advances the queue */
+       if (req)
+               list_add_tail(&req->queue, &ep->queue);
+
+       return 0;
+}
+
+static int mv_u3d_ep_enable(struct usb_ep *_ep,
+               const struct usb_endpoint_descriptor *desc)
+{
+       struct mv_u3d *u3d;
+       struct mv_u3d_ep *ep;
+       struct mv_u3d_ep_context *ep_context;
+       u16 max = 0;
+       unsigned maxburst = 0;
+       u32 epxcr, direction;
+
+       if (!_ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT)
+               return -EINVAL;
+
+       ep = container_of(_ep, struct mv_u3d_ep, ep);
+       u3d = ep->u3d;
+
+       if (!u3d->driver || u3d->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       direction = mv_u3d_ep_dir(ep);
+       max = le16_to_cpu(desc->wMaxPacketSize);
+
+       if (!_ep->maxburst)
+               _ep->maxburst = 1;
+       maxburst = _ep->maxburst;
+
+       /* Get the endpoint context address */
+       ep_context = (struct mv_u3d_ep_context *)ep->ep_context;
+
+       /* Set the max burst size */
+       switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+       case USB_ENDPOINT_XFER_BULK:
+               if (maxburst > 16) {
+                       dev_dbg(u3d->dev,
+                               "max burst should not be greater "
+                               "than 16 on bulk ep\n");
+                       maxburst = 1;
+                       _ep->maxburst = maxburst;
+               }
+               dev_dbg(u3d->dev,
+                       "maxburst: %d on bulk %s\n", maxburst, ep->name);
+               break;
+       case USB_ENDPOINT_XFER_CONTROL:
+               /* control transfer only supports maxburst as one */
+               maxburst = 1;
+               _ep->maxburst = maxburst;
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               if (maxburst != 1) {
+                       dev_dbg(u3d->dev,
+                               "max burst should be 1 on int ep "
+                               "if transfer size is not 1024\n");
+                       maxburst = 1;
+                       _ep->maxburst = maxburst;
+               }
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               if (maxburst != 1) {
+                       dev_dbg(u3d->dev,
+                               "max burst should be 1 on isoc ep "
+                               "if transfer size is not 1024\n");
+                       maxburst = 1;
+                       _ep->maxburst = maxburst;
+               }
+               break;
+       default:
+               goto en_done;
+       }
+
+       ep->ep.maxpacket = max;
+       ep->ep.desc = desc;
+       ep->enabled = 1;
+
+       /* Enable the endpoint for Rx or Tx and set the endpoint type */
+       if (direction == MV_U3D_EP_DIR_OUT) {
+               epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
+               epxcr |= MV_U3D_EPXCR_EP_INIT;
+               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
+               udelay(5);
+               epxcr &= ~MV_U3D_EPXCR_EP_INIT;
+               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
+
+               epxcr = ((max << MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT)
+                     | ((maxburst - 1) << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT)
+                     | (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
+                     | (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK));
+               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr1);
+       } else {
+               epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
+               epxcr |= MV_U3D_EPXCR_EP_INIT;
+               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
+               udelay(5);
+               epxcr &= ~MV_U3D_EPXCR_EP_INIT;
+               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
+
+               epxcr = ((max << MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT)
+                     | ((maxburst - 1) << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT)
+                     | (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
+                     | (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK));
+               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr1);
+       }
+
+       return 0;
+en_done:
+       return -EINVAL;
+}
+
+static int  mv_u3d_ep_disable(struct usb_ep *_ep)
+{
+       struct mv_u3d *u3d;
+       struct mv_u3d_ep *ep;
+       struct mv_u3d_ep_context *ep_context;
+       u32 epxcr, direction;
+       unsigned long flags;
+
+       if (!_ep)
+               return -EINVAL;
+
+       ep = container_of(_ep, struct mv_u3d_ep, ep);
+       if (!ep->ep.desc)
+               return -EINVAL;
+
+       u3d = ep->u3d;
+
+       /* Get the endpoint context address */
+       ep_context = ep->ep_context;
+
+       direction = mv_u3d_ep_dir(ep);
+
+       /* nuke all pending requests (does flush) */
+       spin_lock_irqsave(&u3d->lock, flags);
+       mv_u3d_nuke(ep, -ESHUTDOWN);
+       spin_unlock_irqrestore(&u3d->lock, flags);
+
+       /* Disable the endpoint for Rx or Tx and reset the endpoint type */
+       if (direction == MV_U3D_EP_DIR_OUT) {
+               epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr1);
+               epxcr &= ~((1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
+                     | USB_ENDPOINT_XFERTYPE_MASK);
+               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr1);
+       } else {
+               epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr1);
+               epxcr &= ~((1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
+                     | USB_ENDPOINT_XFERTYPE_MASK);
+               iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr1);
+       }
+
+       ep->enabled = 0;
+
+       ep->ep.desc = NULL;
+       return 0;
+}
+
+static struct usb_request *
+mv_u3d_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct mv_u3d_req *req = NULL;
+
+       req = kzalloc(sizeof *req, gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void mv_u3d_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct mv_u3d_req *req = container_of(_req, struct mv_u3d_req, req);
+
+       kfree(req);
+}
+
+static void mv_u3d_ep_fifo_flush(struct usb_ep *_ep)
+{
+       struct mv_u3d *u3d;
+       u32 direction;
+       struct mv_u3d_ep *ep = container_of(_ep, struct mv_u3d_ep, ep);
+       unsigned int loops;
+       u32 tmp;
+
+       /* if endpoint is not enabled, cannot flush endpoint */
+       if (!ep->enabled)
+               return;
+
+       u3d = ep->u3d;
+       direction = mv_u3d_ep_dir(ep);
+
+       /* ep0 need clear bit after flushing fifo. */
+       if (!ep->ep_num) {
+               if (direction == MV_U3D_EP_DIR_OUT) {
+                       tmp = ioread32(&u3d->vuc_regs->epcr[0].epxoutcr0);
+                       tmp |= MV_U3D_EPXCR_EP_FLUSH;
+                       iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxoutcr0);
+                       udelay(10);
+                       tmp &= ~MV_U3D_EPXCR_EP_FLUSH;
+                       iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxoutcr0);
+               } else {
+                       tmp = ioread32(&u3d->vuc_regs->epcr[0].epxincr0);
+                       tmp |= MV_U3D_EPXCR_EP_FLUSH;
+                       iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxincr0);
+                       udelay(10);
+                       tmp &= ~MV_U3D_EPXCR_EP_FLUSH;
+                       iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxincr0);
+               }
+               return;
+       }
+
+       if (direction == MV_U3D_EP_DIR_OUT) {
+               tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
+               tmp |= MV_U3D_EPXCR_EP_FLUSH;
+               iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
+
+               /* Wait until flushing completed */
+               loops = LOOPS(MV_U3D_FLUSH_TIMEOUT);
+               while (ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0) &
+                       MV_U3D_EPXCR_EP_FLUSH) {
+                       /*
+                        * EP_FLUSH bit should be cleared to indicate this
+                        * operation is complete
+                        */
+                       if (loops == 0) {
+                               dev_dbg(u3d->dev,
+                                   "EP FLUSH TIMEOUT for ep%d%s\n", ep->ep_num,
+                                   direction ? "in" : "out");
+                               return;
+                       }
+                       loops--;
+                       udelay(LOOPS_USEC);
+               }
+       } else {        /* EP_DIR_IN */
+               tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
+               tmp |= MV_U3D_EPXCR_EP_FLUSH;
+               iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
+
+               /* Wait until flushing completed */
+               loops = LOOPS(MV_U3D_FLUSH_TIMEOUT);
+               while (ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0) &
+                       MV_U3D_EPXCR_EP_FLUSH) {
+                       /*
+                       * EP_FLUSH bit should be cleared to indicate this
+                       * operation is complete
+                       */
+                       if (loops == 0) {
+                               dev_dbg(u3d->dev,
+                                   "EP FLUSH TIMEOUT for ep%d%s\n", ep->ep_num,
+                                   direction ? "in" : "out");
+                               return;
+                       }
+                       loops--;
+                       udelay(LOOPS_USEC);
+               }
+       }
+}
+
+/* queues (submits) an I/O request to an endpoint */
+static int
+mv_u3d_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+       struct mv_u3d_ep *ep;
+       struct mv_u3d_req *req;
+       struct mv_u3d *u3d;
+       unsigned long flags;
+       int is_first_req = 0;
+
+       if (unlikely(!_ep || !_req))
+               return -EINVAL;
+
+       ep = container_of(_ep, struct mv_u3d_ep, ep);
+       u3d = ep->u3d;
+
+       req = container_of(_req, struct mv_u3d_req, req);
+
+       if (!ep->ep_num
+               && u3d->ep0_state == MV_U3D_STATUS_STAGE
+               && !_req->length) {
+               dev_dbg(u3d->dev, "ep0 status stage\n");
+               u3d->ep0_state = MV_U3D_WAIT_FOR_SETUP;
+               return 0;
+       }
+
+       dev_dbg(u3d->dev, "%s: %s, req: 0x%p\n",
+                       __func__, _ep->name, req);
+
+       /* catch various bogus parameters */
+       if (!req->req.complete || !req->req.buf
+                       || !list_empty(&req->queue)) {
+               dev_err(u3d->dev,
+                       "%s, bad params, _req: 0x%p,"
+                       "req->req.complete: 0x%p, req->req.buf: 0x%p,"
+                       "list_empty: 0x%x\n",
+                       __func__, _req,
+                       req->req.complete, req->req.buf,
+                       list_empty(&req->queue));
+               return -EINVAL;
+       }
+       if (unlikely(!ep->ep.desc)) {
+               dev_err(u3d->dev, "%s, bad ep\n", __func__);
+               return -EINVAL;
+       }
+       if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+               if (req->req.length > ep->ep.maxpacket)
+                       return -EMSGSIZE;
+       }
+
+       if (!u3d->driver || u3d->gadget.speed == USB_SPEED_UNKNOWN) {
+               dev_err(u3d->dev,
+                       "bad params of driver/speed\n");
+               return -ESHUTDOWN;
+       }
+
+       req->ep = ep;
+
+       /* Software list handles usb request. */
+       spin_lock_irqsave(&ep->req_lock, flags);
+       is_first_req = list_empty(&ep->req_list);
+       list_add_tail(&req->list, &ep->req_list);
+       spin_unlock_irqrestore(&ep->req_lock, flags);
+       if (!is_first_req) {
+               dev_dbg(u3d->dev, "list is not empty\n");
+               return 0;
+       }
+
+       dev_dbg(u3d->dev, "call mv_u3d_start_queue from usb_ep_queue\n");
+       spin_lock_irqsave(&u3d->lock, flags);
+       mv_u3d_start_queue(ep);
+       spin_unlock_irqrestore(&u3d->lock, flags);
+       return 0;
+}
+
+/* dequeues (cancels, unlinks) an I/O request from an endpoint */
+static int mv_u3d_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct mv_u3d_ep *ep;
+       struct mv_u3d_req *req;
+       struct mv_u3d *u3d;
+       struct mv_u3d_ep_context *ep_context;
+       struct mv_u3d_req *next_req;
+
+       unsigned long flags;
+       int ret = 0;
+
+       if (!_ep || !_req)
+               return -EINVAL;
+
+       ep = container_of(_ep, struct mv_u3d_ep, ep);
+       u3d = ep->u3d;
+
+       spin_lock_irqsave(&ep->u3d->lock, flags);
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* The request is in progress, or completed but not dequeued */
+       if (ep->queue.next == &req->queue) {
+               _req->status = -ECONNRESET;
+               mv_u3d_ep_fifo_flush(_ep);
+
+               /* The request isn't the last request in this ep queue */
+               if (req->queue.next != &ep->queue) {
+                       dev_dbg(u3d->dev,
+                               "it is the last request in this ep queue\n");
+                       ep_context = ep->ep_context;
+                       next_req = list_entry(req->queue.next,
+                                       struct mv_u3d_req, queue);
+
+                       /* Point first TRB of next request to the EP context. */
+                       iowrite32((unsigned long) next_req->trb_head,
+                                       &ep_context->trb_addr_lo);
+               } else {
+                       struct mv_u3d_ep_context *ep_context;
+                       ep_context = ep->ep_context;
+                       ep_context->trb_addr_lo = 0;
+                       ep_context->trb_addr_hi = 0;
+               }
+
+       } else
+               WARN_ON(1);
+
+       mv_u3d_done(ep, req, -ECONNRESET);
+
+       /* remove the req from the ep req list */
+       if (!list_empty(&ep->req_list)) {
+               struct mv_u3d_req *curr_req;
+               curr_req = list_entry(ep->req_list.next,
+                                       struct mv_u3d_req, list);
+               if (curr_req == req) {
+                       list_del_init(&req->list);
+                       ep->processing = 0;
+               }
+       }
+
+out:
+       spin_unlock_irqrestore(&ep->u3d->lock, flags);
+       return ret;
+}
+
+static void
+mv_u3d_ep_set_stall(struct mv_u3d *u3d, u8 ep_num, u8 direction, int stall)
+{
+       u32 tmp;
+       struct mv_u3d_ep *ep = u3d->eps;
+
+       dev_dbg(u3d->dev, "%s\n", __func__);
+       if (direction == MV_U3D_EP_DIR_OUT) {
+               tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
+               if (stall)
+                       tmp |= MV_U3D_EPXCR_EP_HALT;
+               else
+                       tmp &= ~MV_U3D_EPXCR_EP_HALT;
+               iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
+       } else {
+               tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
+               if (stall)
+                       tmp |= MV_U3D_EPXCR_EP_HALT;
+               else
+                       tmp &= ~MV_U3D_EPXCR_EP_HALT;
+               iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
+       }
+}
+
+static int mv_u3d_ep_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge)
+{
+       struct mv_u3d_ep *ep;
+       unsigned long flags = 0;
+       int status = 0;
+       struct mv_u3d *u3d;
+
+       ep = container_of(_ep, struct mv_u3d_ep, ep);
+       u3d = ep->u3d;
+       if (!ep->ep.desc) {
+               status = -EINVAL;
+               goto out;
+       }
+
+       if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+               status = -EOPNOTSUPP;
+               goto out;
+       }
+
+       /*
+        * Attempt to halt IN ep will fail if any transfer requests
+        * are still queue
+        */
+       if (halt && (mv_u3d_ep_dir(ep) == MV_U3D_EP_DIR_IN)
+                       && !list_empty(&ep->queue)) {
+               status = -EAGAIN;
+               goto out;
+       }
+
+       spin_lock_irqsave(&ep->u3d->lock, flags);
+       mv_u3d_ep_set_stall(u3d, ep->ep_num, mv_u3d_ep_dir(ep), halt);
+       if (halt && wedge)
+               ep->wedge = 1;
+       else if (!halt)
+               ep->wedge = 0;
+       spin_unlock_irqrestore(&ep->u3d->lock, flags);
+
+       if (ep->ep_num == 0)
+               u3d->ep0_dir = MV_U3D_EP_DIR_OUT;
+out:
+       return status;
+}
+
+static int mv_u3d_ep_set_halt(struct usb_ep *_ep, int halt)
+{
+       return mv_u3d_ep_set_halt_wedge(_ep, halt, 0);
+}
+
+static int mv_u3d_ep_set_wedge(struct usb_ep *_ep)
+{
+       return mv_u3d_ep_set_halt_wedge(_ep, 1, 1);
+}
+
+static struct usb_ep_ops mv_u3d_ep_ops = {
+       .enable         = mv_u3d_ep_enable,
+       .disable        = mv_u3d_ep_disable,
+
+       .alloc_request  = mv_u3d_alloc_request,
+       .free_request   = mv_u3d_free_request,
+
+       .queue          = mv_u3d_ep_queue,
+       .dequeue        = mv_u3d_ep_dequeue,
+
+       .set_wedge      = mv_u3d_ep_set_wedge,
+       .set_halt       = mv_u3d_ep_set_halt,
+       .fifo_flush     = mv_u3d_ep_fifo_flush,
+};
+
+static void mv_u3d_controller_stop(struct mv_u3d *u3d)
+{
+       u32 tmp;
+
+       if (!u3d->clock_gating && u3d->vbus_valid_detect)
+               iowrite32(MV_U3D_INTR_ENABLE_VBUS_VALID,
+                               &u3d->vuc_regs->intrenable);
+       else
+               iowrite32(0, &u3d->vuc_regs->intrenable);
+       iowrite32(~0x0, &u3d->vuc_regs->endcomplete);
+       iowrite32(~0x0, &u3d->vuc_regs->trbunderrun);
+       iowrite32(~0x0, &u3d->vuc_regs->trbcomplete);
+       iowrite32(~0x0, &u3d->vuc_regs->linkchange);
+       iowrite32(0x1, &u3d->vuc_regs->setuplock);
+
+       /* Reset the RUN bit in the command register to stop USB */
+       tmp = ioread32(&u3d->op_regs->usbcmd);
+       tmp &= ~MV_U3D_CMD_RUN_STOP;
+       iowrite32(tmp, &u3d->op_regs->usbcmd);
+       dev_dbg(u3d->dev, "after u3d_stop, USBCMD 0x%x\n",
+               ioread32(&u3d->op_regs->usbcmd));
+}
+
+static void mv_u3d_controller_start(struct mv_u3d *u3d)
+{
+       u32 usbintr;
+       u32 temp;
+
+       /* enable link LTSSM state machine */
+       temp = ioread32(&u3d->vuc_regs->ltssm);
+       temp |= MV_U3D_LTSSM_PHY_INIT_DONE;
+       iowrite32(temp, &u3d->vuc_regs->ltssm);
+
+       /* Enable interrupts */
+       usbintr = MV_U3D_INTR_ENABLE_LINK_CHG | MV_U3D_INTR_ENABLE_TXDESC_ERR |
+               MV_U3D_INTR_ENABLE_RXDESC_ERR | MV_U3D_INTR_ENABLE_TX_COMPLETE |
+               MV_U3D_INTR_ENABLE_RX_COMPLETE | MV_U3D_INTR_ENABLE_SETUP |
+               (u3d->vbus_valid_detect ? MV_U3D_INTR_ENABLE_VBUS_VALID : 0);
+       iowrite32(usbintr, &u3d->vuc_regs->intrenable);
+
+       /* Enable ctrl ep */
+       iowrite32(0x1, &u3d->vuc_regs->ctrlepenable);
+
+       /* Set the Run bit in the command register */
+       iowrite32(MV_U3D_CMD_RUN_STOP, &u3d->op_regs->usbcmd);
+       dev_dbg(u3d->dev, "after u3d_start, USBCMD 0x%x\n",
+               ioread32(&u3d->op_regs->usbcmd));
+}
+
+static int mv_u3d_controller_reset(struct mv_u3d *u3d)
+{
+       unsigned int loops;
+       u32 tmp;
+
+       /* Stop the controller */
+       tmp = ioread32(&u3d->op_regs->usbcmd);
+       tmp &= ~MV_U3D_CMD_RUN_STOP;
+       iowrite32(tmp, &u3d->op_regs->usbcmd);
+
+       /* Reset the controller to get default values */
+       iowrite32(MV_U3D_CMD_CTRL_RESET, &u3d->op_regs->usbcmd);
+
+       /* wait for reset to complete */
+       loops = LOOPS(MV_U3D_RESET_TIMEOUT);
+       while (ioread32(&u3d->op_regs->usbcmd) & MV_U3D_CMD_CTRL_RESET) {
+               if (loops == 0) {
+                       dev_err(u3d->dev,
+                               "Wait for RESET completed TIMEOUT\n");
+                       return -ETIMEDOUT;
+               }
+               loops--;
+               udelay(LOOPS_USEC);
+       }
+
+       /* Configure the Endpoint Context Address */
+       iowrite32(u3d->ep_context_dma, &u3d->op_regs->dcbaapl);
+       iowrite32(0, &u3d->op_regs->dcbaaph);
+
+       return 0;
+}
+
+static int mv_u3d_enable(struct mv_u3d *u3d)
+{
+       struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
+       int retval;
+
+       if (u3d->active)
+               return 0;
+
+       if (!u3d->clock_gating) {
+               u3d->active = 1;
+               return 0;
+       }
+
+       dev_dbg(u3d->dev, "enable u3d\n");
+       clk_enable(u3d->clk);
+       if (pdata->phy_init) {
+               retval = pdata->phy_init(u3d->phy_regs);
+               if (retval) {
+                       dev_err(u3d->dev,
+                               "init phy error %d\n", retval);
+                       clk_disable(u3d->clk);
+                       return retval;
+               }
+       }
+       u3d->active = 1;
+
+       return 0;
+}
+
+static void mv_u3d_disable(struct mv_u3d *u3d)
+{
+       struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
+       if (u3d->clock_gating && u3d->active) {
+               dev_dbg(u3d->dev, "disable u3d\n");
+               if (pdata->phy_deinit)
+                       pdata->phy_deinit(u3d->phy_regs);
+               clk_disable(u3d->clk);
+               u3d->active = 0;
+       }
+}
+
+static int mv_u3d_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+       struct mv_u3d *u3d;
+       unsigned long flags;
+       int retval = 0;
+
+       u3d = container_of(gadget, struct mv_u3d, gadget);
+
+       spin_lock_irqsave(&u3d->lock, flags);
+
+       u3d->vbus_active = (is_active != 0);
+       dev_dbg(u3d->dev, "%s: softconnect %d, vbus_active %d\n",
+               __func__, u3d->softconnect, u3d->vbus_active);
+       /*
+        * 1. external VBUS detect: we can disable/enable clock on demand.
+        * 2. UDC VBUS detect: we have to enable clock all the time.
+        * 3. No VBUS detect: we have to enable clock all the time.
+        */
+       if (u3d->driver && u3d->softconnect && u3d->vbus_active) {
+               retval = mv_u3d_enable(u3d);
+               if (retval == 0) {
+                       /*
+                        * after clock is disabled, we lost all the register
+                        *  context. We have to re-init registers
+                        */
+                       mv_u3d_controller_reset(u3d);
+                       mv_u3d_ep0_reset(u3d);
+                       mv_u3d_controller_start(u3d);
+               }
+       } else if (u3d->driver && u3d->softconnect) {
+               if (!u3d->active)
+                       goto out;
+
+               /* stop all the transfer in queue*/
+               mv_u3d_stop_activity(u3d, u3d->driver);
+               mv_u3d_controller_stop(u3d);
+               mv_u3d_disable(u3d);
+       }
+
+out:
+       spin_unlock_irqrestore(&u3d->lock, flags);
+       return retval;
+}
+
+/* constrain controller's VBUS power usage
+ * This call is used by gadget drivers during SET_CONFIGURATION calls,
+ * reporting how much power the device may consume.  For example, this
+ * could affect how quickly batteries are recharged.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static int mv_u3d_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+       struct mv_u3d *u3d = container_of(gadget, struct mv_u3d, gadget);
+
+       u3d->power = mA;
+
+       return 0;
+}
+
+static int mv_u3d_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct mv_u3d *u3d = container_of(gadget, struct mv_u3d, gadget);
+       unsigned long flags;
+       int retval = 0;
+
+       spin_lock_irqsave(&u3d->lock, flags);
+
+       dev_dbg(u3d->dev, "%s: softconnect %d, vbus_active %d\n",
+               __func__, u3d->softconnect, u3d->vbus_active);
+       u3d->softconnect = (is_on != 0);
+       if (u3d->driver && u3d->softconnect && u3d->vbus_active) {
+               retval = mv_u3d_enable(u3d);
+               if (retval == 0) {
+                       /*
+                        * after clock is disabled, we lost all the register
+                        *  context. We have to re-init registers
+                        */
+                       mv_u3d_controller_reset(u3d);
+                       mv_u3d_ep0_reset(u3d);
+                       mv_u3d_controller_start(u3d);
+               }
+       } else if (u3d->driver && u3d->vbus_active) {
+               /* stop all the transfer in queue*/
+               mv_u3d_stop_activity(u3d, u3d->driver);
+               mv_u3d_controller_stop(u3d);
+               mv_u3d_disable(u3d);
+       }
+
+       spin_unlock_irqrestore(&u3d->lock, flags);
+
+       return retval;
+}
+
+static int mv_u3d_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget);
+       struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
+       unsigned long flags;
+
+       if (u3d->driver)
+               return -EBUSY;
+
+       spin_lock_irqsave(&u3d->lock, flags);
+
+       if (!u3d->clock_gating) {
+               clk_enable(u3d->clk);
+               if (pdata->phy_init)
+                       pdata->phy_init(u3d->phy_regs);
+       }
+
+       /* hook up the driver ... */
+       driver->driver.bus = NULL;
+       u3d->driver = driver;
+
+       u3d->ep0_dir = USB_DIR_OUT;
+
+       spin_unlock_irqrestore(&u3d->lock, flags);
+
+       u3d->vbus_valid_detect = 1;
+
+       return 0;
+}
+
+static int mv_u3d_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget);
+       struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
+       unsigned long flags;
+
+       u3d->vbus_valid_detect = 0;
+       spin_lock_irqsave(&u3d->lock, flags);
+
+       /* enable clock to access controller register */
+       clk_enable(u3d->clk);
+       if (pdata->phy_init)
+               pdata->phy_init(u3d->phy_regs);
+
+       mv_u3d_controller_stop(u3d);
+       /* stop all usb activities */
+       u3d->gadget.speed = USB_SPEED_UNKNOWN;
+       mv_u3d_stop_activity(u3d, driver);
+       mv_u3d_disable(u3d);
+
+       if (pdata->phy_deinit)
+               pdata->phy_deinit(u3d->phy_regs);
+       clk_disable(u3d->clk);
+
+       spin_unlock_irqrestore(&u3d->lock, flags);
+
+       u3d->driver = NULL;
+
+       return 0;
+}
+
+/* device controller usb_gadget_ops structure */
+static const struct usb_gadget_ops mv_u3d_ops = {
+       /* notify controller that VBUS is powered or not */
+       .vbus_session   = mv_u3d_vbus_session,
+
+       /* constrain controller's VBUS power usage */
+       .vbus_draw      = mv_u3d_vbus_draw,
+
+       .pullup         = mv_u3d_pullup,
+       .udc_start      = mv_u3d_start,
+       .udc_stop       = mv_u3d_stop,
+};
+
+static int mv_u3d_eps_init(struct mv_u3d *u3d)
+{
+       struct mv_u3d_ep        *ep;
+       char name[14];
+       int i;
+
+       /* initialize ep0, ep0 in/out use eps[1] */
+       ep = &u3d->eps[1];
+       ep->u3d = u3d;
+       strncpy(ep->name, "ep0", sizeof(ep->name));
+       ep->ep.name = ep->name;
+       ep->ep.ops = &mv_u3d_ep_ops;
+       ep->wedge = 0;
+       usb_ep_set_maxpacket_limit(&ep->ep, MV_U3D_EP0_MAX_PKT_SIZE);
+       ep->ep_num = 0;
+       ep->ep.desc = &mv_u3d_ep0_desc;
+       INIT_LIST_HEAD(&ep->queue);
+       INIT_LIST_HEAD(&ep->req_list);
+       ep->ep_type = USB_ENDPOINT_XFER_CONTROL;
+
+       /* add ep0 ep_context */
+       ep->ep_context = &u3d->ep_context[1];
+
+       /* initialize other endpoints */
+       for (i = 2; i < u3d->max_eps * 2; i++) {
+               ep = &u3d->eps[i];
+               if (i & 1) {
+                       snprintf(name, sizeof(name), "ep%din", i >> 1);
+                       ep->direction = MV_U3D_EP_DIR_IN;
+               } else {
+                       snprintf(name, sizeof(name), "ep%dout", i >> 1);
+                       ep->direction = MV_U3D_EP_DIR_OUT;
+               }
+               ep->u3d = u3d;
+               strncpy(ep->name, name, sizeof(ep->name));
+               ep->ep.name = ep->name;
+
+               ep->ep.ops = &mv_u3d_ep_ops;
+               usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
+               ep->ep_num = i / 2;
+
+               INIT_LIST_HEAD(&ep->queue);
+               list_add_tail(&ep->ep.ep_list, &u3d->gadget.ep_list);
+
+               INIT_LIST_HEAD(&ep->req_list);
+               spin_lock_init(&ep->req_lock);
+               ep->ep_context = &u3d->ep_context[i];
+       }
+
+       return 0;
+}
+
+/* delete all endpoint requests, called with spinlock held */
+static void mv_u3d_nuke(struct mv_u3d_ep *ep, int status)
+{
+       /* endpoint fifo flush */
+       mv_u3d_ep_fifo_flush(&ep->ep);
+
+       while (!list_empty(&ep->queue)) {
+               struct mv_u3d_req *req = NULL;
+               req = list_entry(ep->queue.next, struct mv_u3d_req, queue);
+               mv_u3d_done(ep, req, status);
+       }
+}
+
+/* stop all USB activities */
+static
+void mv_u3d_stop_activity(struct mv_u3d *u3d, struct usb_gadget_driver *driver)
+{
+       struct mv_u3d_ep        *ep;
+
+       mv_u3d_nuke(&u3d->eps[1], -ESHUTDOWN);
+
+       list_for_each_entry(ep, &u3d->gadget.ep_list, ep.ep_list) {
+               mv_u3d_nuke(ep, -ESHUTDOWN);
+       }
+
+       /* report disconnect; the driver is already quiesced */
+       if (driver) {
+               spin_unlock(&u3d->lock);
+               driver->disconnect(&u3d->gadget);
+               spin_lock(&u3d->lock);
+       }
+}
+
+static void mv_u3d_irq_process_error(struct mv_u3d *u3d)
+{
+       /* Increment the error count */
+       u3d->errors++;
+       dev_err(u3d->dev, "%s\n", __func__);
+}
+
+static void mv_u3d_irq_process_link_change(struct mv_u3d *u3d)
+{
+       u32 linkchange;
+
+       linkchange = ioread32(&u3d->vuc_regs->linkchange);
+       iowrite32(linkchange, &u3d->vuc_regs->linkchange);
+
+       dev_dbg(u3d->dev, "linkchange: 0x%x\n", linkchange);
+
+       if (linkchange & MV_U3D_LINK_CHANGE_LINK_UP) {
+               dev_dbg(u3d->dev, "link up: ltssm state: 0x%x\n",
+                       ioread32(&u3d->vuc_regs->ltssmstate));
+
+               u3d->usb_state = USB_STATE_DEFAULT;
+               u3d->ep0_dir = MV_U3D_EP_DIR_OUT;
+               u3d->ep0_state = MV_U3D_WAIT_FOR_SETUP;
+
+               /* set speed */
+               u3d->gadget.speed = USB_SPEED_SUPER;
+       }
+
+       if (linkchange & MV_U3D_LINK_CHANGE_SUSPEND) {
+               dev_dbg(u3d->dev, "link suspend\n");
+               u3d->resume_state = u3d->usb_state;
+               u3d->usb_state = USB_STATE_SUSPENDED;
+       }
+
+       if (linkchange & MV_U3D_LINK_CHANGE_RESUME) {
+               dev_dbg(u3d->dev, "link resume\n");
+               u3d->usb_state = u3d->resume_state;
+               u3d->resume_state = 0;
+       }
+
+       if (linkchange & MV_U3D_LINK_CHANGE_WRESET) {
+               dev_dbg(u3d->dev, "warm reset\n");
+               u3d->usb_state = USB_STATE_POWERED;
+       }
+
+       if (linkchange & MV_U3D_LINK_CHANGE_HRESET) {
+               dev_dbg(u3d->dev, "hot reset\n");
+               u3d->usb_state = USB_STATE_DEFAULT;
+       }
+
+       if (linkchange & MV_U3D_LINK_CHANGE_INACT)
+               dev_dbg(u3d->dev, "inactive\n");
+
+       if (linkchange & MV_U3D_LINK_CHANGE_DISABLE_AFTER_U0)
+               dev_dbg(u3d->dev, "ss.disabled\n");
+
+       if (linkchange & MV_U3D_LINK_CHANGE_VBUS_INVALID) {
+               dev_dbg(u3d->dev, "vbus invalid\n");
+               u3d->usb_state = USB_STATE_ATTACHED;
+               u3d->vbus_valid_detect = 1;
+               /* if external vbus detect is not supported,
+                * we handle it here.
+                */
+               if (!u3d->vbus) {
+                       spin_unlock(&u3d->lock);
+                       mv_u3d_vbus_session(&u3d->gadget, 0);
+                       spin_lock(&u3d->lock);
+               }
+       }
+}
+
+static void mv_u3d_ch9setaddress(struct mv_u3d *u3d,
+                               struct usb_ctrlrequest *setup)
+{
+       u32 tmp;
+
+       if (u3d->usb_state != USB_STATE_DEFAULT) {
+               dev_err(u3d->dev,
+                       "%s, cannot setaddr in this state (%d)\n",
+                       __func__, u3d->usb_state);
+               goto err;
+       }
+
+       u3d->dev_addr = (u8)setup->wValue;
+
+       dev_dbg(u3d->dev, "%s: 0x%x\n", __func__, u3d->dev_addr);
+
+       if (u3d->dev_addr > 127) {
+               dev_err(u3d->dev,
+                       "%s, u3d address is wrong (out of range)\n", __func__);
+               u3d->dev_addr = 0;
+               goto err;
+       }
+
+       /* update usb state */
+       u3d->usb_state = USB_STATE_ADDRESS;
+
+       /* set the new address */
+       tmp = ioread32(&u3d->vuc_regs->devaddrtiebrkr);
+       tmp &= ~0x7F;
+       tmp |= (u32)u3d->dev_addr;
+       iowrite32(tmp, &u3d->vuc_regs->devaddrtiebrkr);
+
+       return;
+err:
+       mv_u3d_ep0_stall(u3d);
+}
+
+static int mv_u3d_is_set_configuration(struct usb_ctrlrequest *setup)
+{
+       if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD)
+               if (setup->bRequest == USB_REQ_SET_CONFIGURATION)
+                       return 1;
+
+       return 0;
+}
+
+static void mv_u3d_handle_setup_packet(struct mv_u3d *u3d, u8 ep_num,
+       struct usb_ctrlrequest *setup)
+       __releases(&u3c->lock)
+       __acquires(&u3c->lock)
+{
+       bool delegate = false;
+
+       mv_u3d_nuke(&u3d->eps[ep_num * 2 + MV_U3D_EP_DIR_IN], -ESHUTDOWN);
+
+       dev_dbg(u3d->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
+                       setup->bRequestType, setup->bRequest,
+                       setup->wValue, setup->wIndex, setup->wLength);
+
+       /* We process some stardard setup requests here */
+       if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+               switch (setup->bRequest) {
+               case USB_REQ_GET_STATUS:
+                       delegate = true;
+                       break;
+
+               case USB_REQ_SET_ADDRESS:
+                       mv_u3d_ch9setaddress(u3d, setup);
+                       break;
+
+               case USB_REQ_CLEAR_FEATURE:
+                       delegate = true;
+                       break;
+
+               case USB_REQ_SET_FEATURE:
+                       delegate = true;
+                       break;
+
+               default:
+                       delegate = true;
+               }
+       } else
+               delegate = true;
+
+       /* delegate USB standard requests to the gadget driver */
+       if (delegate == true) {
+               /* USB requests handled by gadget */
+               if (setup->wLength) {
+                       /* DATA phase from gadget, STATUS phase from u3d */
+                       u3d->ep0_dir = (setup->bRequestType & USB_DIR_IN)
+                                       ? MV_U3D_EP_DIR_IN : MV_U3D_EP_DIR_OUT;
+                       spin_unlock(&u3d->lock);
+                       if (u3d->driver->setup(&u3d->gadget,
+                               &u3d->local_setup_buff) < 0) {
+                               dev_err(u3d->dev, "setup error!\n");
+                               mv_u3d_ep0_stall(u3d);
+                       }
+                       spin_lock(&u3d->lock);
+               } else {
+                       /* no DATA phase, STATUS phase from gadget */
+                       u3d->ep0_dir = MV_U3D_EP_DIR_IN;
+                       u3d->ep0_state = MV_U3D_STATUS_STAGE;
+                       spin_unlock(&u3d->lock);
+                       if (u3d->driver->setup(&u3d->gadget,
+                               &u3d->local_setup_buff) < 0)
+                               mv_u3d_ep0_stall(u3d);
+                       spin_lock(&u3d->lock);
+               }
+
+               if (mv_u3d_is_set_configuration(setup)) {
+                       dev_dbg(u3d->dev, "u3d configured\n");
+                       u3d->usb_state = USB_STATE_CONFIGURED;
+               }
+       }
+}
+
+static void mv_u3d_get_setup_data(struct mv_u3d *u3d, u8 ep_num, u8 *buffer_ptr)
+{
+       struct mv_u3d_ep_context *epcontext;
+
+       epcontext = &u3d->ep_context[ep_num * 2 + MV_U3D_EP_DIR_IN];
+
+       /* Copy the setup packet to local buffer */
+       memcpy(buffer_ptr, (u8 *) &epcontext->setup_buffer, 8);
+}
+
+static void mv_u3d_irq_process_setup(struct mv_u3d *u3d)
+{
+       u32 tmp, i;
+       /* Process all Setup packet received interrupts */
+       tmp = ioread32(&u3d->vuc_regs->setuplock);
+       if (tmp) {
+               for (i = 0; i < u3d->max_eps; i++) {
+                       if (tmp & (1 << i)) {
+                               mv_u3d_get_setup_data(u3d, i,
+                                       (u8 *)(&u3d->local_setup_buff));
+                               mv_u3d_handle_setup_packet(u3d, i,
+                                       &u3d->local_setup_buff);
+                       }
+               }
+       }
+
+       iowrite32(tmp, &u3d->vuc_regs->setuplock);
+}
+
+static void mv_u3d_irq_process_tr_complete(struct mv_u3d *u3d)
+{
+       u32 tmp, bit_pos;
+       int i, ep_num = 0, direction = 0;
+       struct mv_u3d_ep        *curr_ep;
+       struct mv_u3d_req *curr_req, *temp_req;
+       int status;
+
+       tmp = ioread32(&u3d->vuc_regs->endcomplete);
+
+       dev_dbg(u3d->dev, "tr_complete: ep: 0x%x\n", tmp);
+       if (!tmp)
+               return;
+       iowrite32(tmp, &u3d->vuc_regs->endcomplete);
+
+       for (i = 0; i < u3d->max_eps * 2; i++) {
+               ep_num = i >> 1;
+               direction = i % 2;
+
+               bit_pos = 1 << (ep_num + 16 * direction);
+
+               if (!(bit_pos & tmp))
+                       continue;
+
+               if (i == 0)
+                       curr_ep = &u3d->eps[1];
+               else
+                       curr_ep = &u3d->eps[i];
+
+               /* remove req out of ep request list after completion */
+               dev_dbg(u3d->dev, "tr comp: check req_list\n");
+               spin_lock(&curr_ep->req_lock);
+               if (!list_empty(&curr_ep->req_list)) {
+                       struct mv_u3d_req *req;
+                       req = list_entry(curr_ep->req_list.next,
+                                               struct mv_u3d_req, list);
+                       list_del_init(&req->list);
+                       curr_ep->processing = 0;
+               }
+               spin_unlock(&curr_ep->req_lock);
+
+               /* process the req queue until an uncomplete request */
+               list_for_each_entry_safe(curr_req, temp_req,
+                       &curr_ep->queue, queue) {
+                       status = mv_u3d_process_ep_req(u3d, i, curr_req);
+                       if (status)
+                               break;
+                       /* write back status to req */
+                       curr_req->req.status = status;
+
+                       /* ep0 request completion */
+                       if (ep_num == 0) {
+                               mv_u3d_done(curr_ep, curr_req, 0);
+                               break;
+                       } else {
+                               mv_u3d_done(curr_ep, curr_req, status);
+                       }
+               }
+
+               dev_dbg(u3d->dev, "call mv_u3d_start_queue from ep complete\n");
+               mv_u3d_start_queue(curr_ep);
+       }
+}
+
+static irqreturn_t mv_u3d_irq(int irq, void *dev)
+{
+       struct mv_u3d *u3d = (struct mv_u3d *)dev;
+       u32 status, intr;
+       u32 bridgesetting;
+       u32 trbunderrun;
+
+       spin_lock(&u3d->lock);
+
+       status = ioread32(&u3d->vuc_regs->intrcause);
+       intr = ioread32(&u3d->vuc_regs->intrenable);
+       status &= intr;
+
+       if (status == 0) {
+               spin_unlock(&u3d->lock);
+               dev_err(u3d->dev, "irq error!\n");
+               return IRQ_NONE;
+       }
+
+       if (status & MV_U3D_USBINT_VBUS_VALID) {
+               bridgesetting = ioread32(&u3d->vuc_regs->bridgesetting);
+               if (bridgesetting & MV_U3D_BRIDGE_SETTING_VBUS_VALID) {
+                       /* write vbus valid bit of bridge setting to clear */
+                       bridgesetting = MV_U3D_BRIDGE_SETTING_VBUS_VALID;
+                       iowrite32(bridgesetting, &u3d->vuc_regs->bridgesetting);
+                       dev_dbg(u3d->dev, "vbus valid\n");
+
+                       u3d->usb_state = USB_STATE_POWERED;
+                       u3d->vbus_valid_detect = 0;
+                       /* if external vbus detect is not supported,
+                        * we handle it here.
+                        */
+                       if (!u3d->vbus) {
+                               spin_unlock(&u3d->lock);
+                               mv_u3d_vbus_session(&u3d->gadget, 1);
+                               spin_lock(&u3d->lock);
+                       }
+               } else
+                       dev_err(u3d->dev, "vbus bit is not set\n");
+       }
+
+       /* RX data is already in the 16KB FIFO.*/
+       if (status & MV_U3D_USBINT_UNDER_RUN) {
+               trbunderrun = ioread32(&u3d->vuc_regs->trbunderrun);
+               dev_err(u3d->dev, "under run, ep%d\n", trbunderrun);
+               iowrite32(trbunderrun, &u3d->vuc_regs->trbunderrun);
+               mv_u3d_irq_process_error(u3d);
+       }
+
+       if (status & (MV_U3D_USBINT_RXDESC_ERR | MV_U3D_USBINT_TXDESC_ERR)) {
+               /* write one to clear */
+               iowrite32(status & (MV_U3D_USBINT_RXDESC_ERR
+                       | MV_U3D_USBINT_TXDESC_ERR),
+                       &u3d->vuc_regs->intrcause);
+               dev_err(u3d->dev, "desc err 0x%x\n", status);
+               mv_u3d_irq_process_error(u3d);
+       }
+
+       if (status & MV_U3D_USBINT_LINK_CHG)
+               mv_u3d_irq_process_link_change(u3d);
+
+       if (status & MV_U3D_USBINT_TX_COMPLETE)
+               mv_u3d_irq_process_tr_complete(u3d);
+
+       if (status & MV_U3D_USBINT_RX_COMPLETE)
+               mv_u3d_irq_process_tr_complete(u3d);
+
+       if (status & MV_U3D_USBINT_SETUP)
+               mv_u3d_irq_process_setup(u3d);
+
+       spin_unlock(&u3d->lock);
+       return IRQ_HANDLED;
+}
+
+static int mv_u3d_remove(struct platform_device *dev)
+{
+       struct mv_u3d *u3d = platform_get_drvdata(dev);
+
+       BUG_ON(u3d == NULL);
+
+       usb_del_gadget_udc(&u3d->gadget);
+
+       /* free memory allocated in probe */
+       if (u3d->trb_pool)
+               dma_pool_destroy(u3d->trb_pool);
+
+       if (u3d->ep_context)
+               dma_free_coherent(&dev->dev, u3d->ep_context_size,
+                       u3d->ep_context, u3d->ep_context_dma);
+
+       kfree(u3d->eps);
+
+       if (u3d->irq)
+               free_irq(u3d->irq, u3d);
+
+       if (u3d->cap_regs)
+               iounmap(u3d->cap_regs);
+       u3d->cap_regs = NULL;
+
+       kfree(u3d->status_req);
+
+       clk_put(u3d->clk);
+
+       kfree(u3d);
+
+       return 0;
+}
+
+static int mv_u3d_probe(struct platform_device *dev)
+{
+       struct mv_u3d *u3d = NULL;
+       struct mv_usb_platform_data *pdata = dev_get_platdata(&dev->dev);
+       int retval = 0;
+       struct resource *r;
+       size_t size;
+
+       if (!dev_get_platdata(&dev->dev)) {
+               dev_err(&dev->dev, "missing platform_data\n");
+               retval = -ENODEV;
+               goto err_pdata;
+       }
+
+       u3d = kzalloc(sizeof(*u3d), GFP_KERNEL);
+       if (!u3d) {
+               retval = -ENOMEM;
+               goto err_alloc_private;
+       }
+
+       spin_lock_init(&u3d->lock);
+
+       platform_set_drvdata(dev, u3d);
+
+       u3d->dev = &dev->dev;
+       u3d->vbus = pdata->vbus;
+
+       u3d->clk = clk_get(&dev->dev, NULL);
+       if (IS_ERR(u3d->clk)) {
+               retval = PTR_ERR(u3d->clk);
+               goto err_get_clk;
+       }
+
+       r = platform_get_resource_byname(dev, IORESOURCE_MEM, "capregs");
+       if (!r) {
+               dev_err(&dev->dev, "no I/O memory resource defined\n");
+               retval = -ENODEV;
+               goto err_get_cap_regs;
+       }
+
+       u3d->cap_regs = (struct mv_u3d_cap_regs __iomem *)
+               ioremap(r->start, resource_size(r));
+       if (!u3d->cap_regs) {
+               dev_err(&dev->dev, "failed to map I/O memory\n");
+               retval = -EBUSY;
+               goto err_map_cap_regs;
+       } else {
+               dev_dbg(&dev->dev, "cap_regs address: 0x%lx/0x%lx\n",
+                       (unsigned long) r->start,
+                       (unsigned long) u3d->cap_regs);
+       }
+
+       /* we will access controller register, so enable the u3d controller */
+       clk_enable(u3d->clk);
+
+       if (pdata->phy_init) {
+               retval = pdata->phy_init(u3d->phy_regs);
+               if (retval) {
+                       dev_err(&dev->dev, "init phy error %d\n", retval);
+                       goto err_u3d_enable;
+               }
+       }
+
+       u3d->op_regs = (struct mv_u3d_op_regs __iomem *)(u3d->cap_regs
+               + MV_U3D_USB3_OP_REGS_OFFSET);
+
+       u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)(u3d->cap_regs
+               + ioread32(&u3d->cap_regs->vuoff));
+
+       u3d->max_eps = 16;
+
+       /*
+        * some platform will use usb to download image, it may not disconnect
+        * usb gadget before loading kernel. So first stop u3d here.
+        */
+       mv_u3d_controller_stop(u3d);
+       iowrite32(0xFFFFFFFF, &u3d->vuc_regs->intrcause);
+
+       if (pdata->phy_deinit)
+               pdata->phy_deinit(u3d->phy_regs);
+       clk_disable(u3d->clk);
+
+       size = u3d->max_eps * sizeof(struct mv_u3d_ep_context) * 2;
+       size = (size + MV_U3D_EP_CONTEXT_ALIGNMENT - 1)
+               & ~(MV_U3D_EP_CONTEXT_ALIGNMENT - 1);
+       u3d->ep_context = dma_alloc_coherent(&dev->dev, size,
+                                       &u3d->ep_context_dma, GFP_KERNEL);
+       if (!u3d->ep_context) {
+               dev_err(&dev->dev, "allocate ep context memory failed\n");
+               retval = -ENOMEM;
+               goto err_alloc_ep_context;
+       }
+       u3d->ep_context_size = size;
+
+       /* create TRB dma_pool resource */
+       u3d->trb_pool = dma_pool_create("u3d_trb",
+                       &dev->dev,
+                       sizeof(struct mv_u3d_trb_hw),
+                       MV_U3D_TRB_ALIGNMENT,
+                       MV_U3D_DMA_BOUNDARY);
+
+       if (!u3d->trb_pool) {
+               retval = -ENOMEM;
+               goto err_alloc_trb_pool;
+       }
+
+       size = u3d->max_eps * sizeof(struct mv_u3d_ep) * 2;
+       u3d->eps = kzalloc(size, GFP_KERNEL);
+       if (!u3d->eps) {
+               retval = -ENOMEM;
+               goto err_alloc_eps;
+       }
+
+       /* initialize ep0 status request structure */
+       u3d->status_req = kzalloc(sizeof(struct mv_u3d_req) + 8, GFP_KERNEL);
+       if (!u3d->status_req) {
+               retval = -ENOMEM;
+               goto err_alloc_status_req;
+       }
+       INIT_LIST_HEAD(&u3d->status_req->queue);
+
+       /* allocate a small amount of memory to get valid address */
+       u3d->status_req->req.buf = (char *)u3d->status_req
+                                       + sizeof(struct mv_u3d_req);
+       u3d->status_req->req.dma = virt_to_phys(u3d->status_req->req.buf);
+
+       u3d->resume_state = USB_STATE_NOTATTACHED;
+       u3d->usb_state = USB_STATE_ATTACHED;
+       u3d->ep0_dir = MV_U3D_EP_DIR_OUT;
+       u3d->remote_wakeup = 0;
+
+       r = platform_get_resource(dev, IORESOURCE_IRQ, 0);
+       if (!r) {
+               dev_err(&dev->dev, "no IRQ resource defined\n");
+               retval = -ENODEV;
+               goto err_get_irq;
+       }
+       u3d->irq = r->start;
+       if (request_irq(u3d->irq, mv_u3d_irq,
+               IRQF_SHARED, driver_name, u3d)) {
+               u3d->irq = 0;
+               dev_err(&dev->dev, "Request irq %d for u3d failed\n",
+                       u3d->irq);
+               retval = -ENODEV;
+               goto err_request_irq;
+       }
+
+       /* initialize gadget structure */
+       u3d->gadget.ops = &mv_u3d_ops;  /* usb_gadget_ops */
+       u3d->gadget.ep0 = &u3d->eps[1].ep;      /* gadget ep0 */
+       INIT_LIST_HEAD(&u3d->gadget.ep_list);   /* ep_list */
+       u3d->gadget.speed = USB_SPEED_UNKNOWN;  /* speed */
+
+       /* the "gadget" abstracts/virtualizes the controller */
+       u3d->gadget.name = driver_name;         /* gadget name */
+
+       mv_u3d_eps_init(u3d);
+
+       /* external vbus detection */
+       if (u3d->vbus) {
+               u3d->clock_gating = 1;
+               dev_err(&dev->dev, "external vbus detection\n");
+       }
+
+       if (!u3d->clock_gating)
+               u3d->vbus_active = 1;
+
+       /* enable usb3 controller vbus detection */
+       u3d->vbus_valid_detect = 1;
+
+       retval = usb_add_gadget_udc(&dev->dev, &u3d->gadget);
+       if (retval)
+               goto err_unregister;
+
+       dev_dbg(&dev->dev, "successful probe usb3 device %s clock gating.\n",
+               u3d->clock_gating ? "with" : "without");
+
+       return 0;
+
+err_unregister:
+       free_irq(u3d->irq, u3d);
+err_request_irq:
+err_get_irq:
+       kfree(u3d->status_req);
+err_alloc_status_req:
+       kfree(u3d->eps);
+err_alloc_eps:
+       dma_pool_destroy(u3d->trb_pool);
+err_alloc_trb_pool:
+       dma_free_coherent(&dev->dev, u3d->ep_context_size,
+               u3d->ep_context, u3d->ep_context_dma);
+err_alloc_ep_context:
+       if (pdata->phy_deinit)
+               pdata->phy_deinit(u3d->phy_regs);
+       clk_disable(u3d->clk);
+err_u3d_enable:
+       iounmap(u3d->cap_regs);
+err_map_cap_regs:
+err_get_cap_regs:
+err_get_clk:
+       clk_put(u3d->clk);
+       kfree(u3d);
+err_alloc_private:
+err_pdata:
+       return retval;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mv_u3d_suspend(struct device *dev)
+{
+       struct mv_u3d *u3d = dev_get_drvdata(dev);
+
+       /*
+        * only cable is unplugged, usb can suspend.
+        * So do not care about clock_gating == 1, it is handled by
+        * vbus session.
+        */
+       if (!u3d->clock_gating) {
+               mv_u3d_controller_stop(u3d);
+
+               spin_lock_irq(&u3d->lock);
+               /* stop all usb activities */
+               mv_u3d_stop_activity(u3d, u3d->driver);
+               spin_unlock_irq(&u3d->lock);
+
+               mv_u3d_disable(u3d);
+       }
+
+       return 0;
+}
+
+static int mv_u3d_resume(struct device *dev)
+{
+       struct mv_u3d *u3d = dev_get_drvdata(dev);
+       int retval;
+
+       if (!u3d->clock_gating) {
+               retval = mv_u3d_enable(u3d);
+               if (retval)
+                       return retval;
+
+               if (u3d->driver && u3d->softconnect) {
+                       mv_u3d_controller_reset(u3d);
+                       mv_u3d_ep0_reset(u3d);
+                       mv_u3d_controller_start(u3d);
+               }
+       }
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
+
+static void mv_u3d_shutdown(struct platform_device *dev)
+{
+       struct mv_u3d *u3d = platform_get_drvdata(dev);
+       u32 tmp;
+
+       tmp = ioread32(&u3d->op_regs->usbcmd);
+       tmp &= ~MV_U3D_CMD_RUN_STOP;
+       iowrite32(tmp, &u3d->op_regs->usbcmd);
+}
+
+static struct platform_driver mv_u3d_driver = {
+       .probe          = mv_u3d_probe,
+       .remove         = mv_u3d_remove,
+       .shutdown       = mv_u3d_shutdown,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "mv-u3d",
+               .pm     = &mv_u3d_pm_ops,
+       },
+};
+
+module_platform_driver(mv_u3d_driver);
+MODULE_ALIAS("platform:mv-u3d");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Yu Xu <yuxu@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/udc/mv_udc.h b/drivers/usb/gadget/udc/mv_udc.h
new file mode 100644 (file)
index 0000000..be77f20
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2011 Marvell International Ltd. 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 as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MV_UDC_H
+#define __MV_UDC_H
+
+#define VUSBHS_MAX_PORTS       8
+
+#define DQH_ALIGNMENT          2048
+#define DTD_ALIGNMENT          64
+#define DMA_BOUNDARY           4096
+
+#define EP_DIR_IN      1
+#define EP_DIR_OUT     0
+
+#define DMA_ADDR_INVALID       (~(dma_addr_t)0)
+
+#define EP0_MAX_PKT_SIZE       64
+/* ep0 transfer state */
+#define WAIT_FOR_SETUP         0
+#define DATA_STATE_XMIT                1
+#define DATA_STATE_NEED_ZLP    2
+#define WAIT_FOR_OUT_STATUS    3
+#define DATA_STATE_RECV                4
+
+#define CAPLENGTH_MASK         (0xff)
+#define DCCPARAMS_DEN_MASK     (0x1f)
+
+#define HCSPARAMS_PPC          (0x10)
+
+/* Frame Index Register Bit Masks */
+#define USB_FRINDEX_MASKS      0x3fff
+
+/* Command Register Bit Masks */
+#define USBCMD_RUN_STOP                                (0x00000001)
+#define USBCMD_CTRL_RESET                      (0x00000002)
+#define USBCMD_SETUP_TRIPWIRE_SET              (0x00002000)
+#define USBCMD_SETUP_TRIPWIRE_CLEAR            (~USBCMD_SETUP_TRIPWIRE_SET)
+
+#define USBCMD_ATDTW_TRIPWIRE_SET              (0x00004000)
+#define USBCMD_ATDTW_TRIPWIRE_CLEAR            (~USBCMD_ATDTW_TRIPWIRE_SET)
+
+/* bit 15,3,2 are for frame list size */
+#define USBCMD_FRAME_SIZE_1024                 (0x00000000) /* 000 */
+#define USBCMD_FRAME_SIZE_512                  (0x00000004) /* 001 */
+#define USBCMD_FRAME_SIZE_256                  (0x00000008) /* 010 */
+#define USBCMD_FRAME_SIZE_128                  (0x0000000C) /* 011 */
+#define USBCMD_FRAME_SIZE_64                   (0x00008000) /* 100 */
+#define USBCMD_FRAME_SIZE_32                   (0x00008004) /* 101 */
+#define USBCMD_FRAME_SIZE_16                   (0x00008008) /* 110 */
+#define USBCMD_FRAME_SIZE_8                    (0x0000800C) /* 111 */
+
+#define EPCTRL_TX_ALL_MASK                     (0xFFFF0000)
+#define EPCTRL_RX_ALL_MASK                     (0x0000FFFF)
+
+#define EPCTRL_TX_DATA_TOGGLE_RST              (0x00400000)
+#define EPCTRL_TX_EP_STALL                     (0x00010000)
+#define EPCTRL_RX_EP_STALL                     (0x00000001)
+#define EPCTRL_RX_DATA_TOGGLE_RST              (0x00000040)
+#define EPCTRL_RX_ENABLE                       (0x00000080)
+#define EPCTRL_TX_ENABLE                       (0x00800000)
+#define EPCTRL_CONTROL                         (0x00000000)
+#define EPCTRL_ISOCHRONOUS                     (0x00040000)
+#define EPCTRL_BULK                            (0x00080000)
+#define EPCTRL_INT                             (0x000C0000)
+#define EPCTRL_TX_TYPE                         (0x000C0000)
+#define EPCTRL_RX_TYPE                         (0x0000000C)
+#define EPCTRL_DATA_TOGGLE_INHIBIT             (0x00000020)
+#define EPCTRL_TX_EP_TYPE_SHIFT                        (18)
+#define EPCTRL_RX_EP_TYPE_SHIFT                        (2)
+
+#define EPCOMPLETE_MAX_ENDPOINTS               (16)
+
+/* endpoint list address bit masks */
+#define USB_EP_LIST_ADDRESS_MASK              0xfffff800
+
+#define PORTSCX_W1C_BITS                       0x2a
+#define PORTSCX_PORT_RESET                     0x00000100
+#define PORTSCX_PORT_POWER                     0x00001000
+#define PORTSCX_FORCE_FULL_SPEED_CONNECT       0x01000000
+#define PORTSCX_PAR_XCVR_SELECT                        0xC0000000
+#define PORTSCX_PORT_FORCE_RESUME              0x00000040
+#define PORTSCX_PORT_SUSPEND                   0x00000080
+#define PORTSCX_PORT_SPEED_FULL                        0x00000000
+#define PORTSCX_PORT_SPEED_LOW                 0x04000000
+#define PORTSCX_PORT_SPEED_HIGH                        0x08000000
+#define PORTSCX_PORT_SPEED_MASK                        0x0C000000
+
+/* USB MODE Register Bit Masks */
+#define USBMODE_CTRL_MODE_IDLE                 0x00000000
+#define USBMODE_CTRL_MODE_DEVICE               0x00000002
+#define USBMODE_CTRL_MODE_HOST                 0x00000003
+#define USBMODE_CTRL_MODE_RSV                  0x00000001
+#define USBMODE_SETUP_LOCK_OFF                 0x00000008
+#define USBMODE_STREAM_DISABLE                 0x00000010
+
+/* USB STS Register Bit Masks */
+#define USBSTS_INT                     0x00000001
+#define USBSTS_ERR                     0x00000002
+#define USBSTS_PORT_CHANGE             0x00000004
+#define USBSTS_FRM_LST_ROLL            0x00000008
+#define USBSTS_SYS_ERR                 0x00000010
+#define USBSTS_IAA                     0x00000020
+#define USBSTS_RESET                   0x00000040
+#define USBSTS_SOF                     0x00000080
+#define USBSTS_SUSPEND                 0x00000100
+#define USBSTS_HC_HALTED               0x00001000
+#define USBSTS_RCL                     0x00002000
+#define USBSTS_PERIODIC_SCHEDULE       0x00004000
+#define USBSTS_ASYNC_SCHEDULE          0x00008000
+
+
+/* Interrupt Enable Register Bit Masks */
+#define USBINTR_INT_EN                          (0x00000001)
+#define USBINTR_ERR_INT_EN                      (0x00000002)
+#define USBINTR_PORT_CHANGE_DETECT_EN           (0x00000004)
+
+#define USBINTR_ASYNC_ADV_AAE                   (0x00000020)
+#define USBINTR_ASYNC_ADV_AAE_ENABLE            (0x00000020)
+#define USBINTR_ASYNC_ADV_AAE_DISABLE           (0xFFFFFFDF)
+
+#define USBINTR_RESET_EN                        (0x00000040)
+#define USBINTR_SOF_UFRAME_EN                   (0x00000080)
+#define USBINTR_DEVICE_SUSPEND                  (0x00000100)
+
+#define USB_DEVICE_ADDRESS_MASK                        (0xfe000000)
+#define USB_DEVICE_ADDRESS_BIT_SHIFT           (25)
+
+struct mv_cap_regs {
+       u32     caplength_hciversion;
+       u32     hcsparams;      /* HC structural parameters */
+       u32     hccparams;      /* HC Capability Parameters*/
+       u32     reserved[5];
+       u32     dciversion;     /* DC version number and reserved 16 bits */
+       u32     dccparams;      /* DC Capability Parameters */
+};
+
+struct mv_op_regs {
+       u32     usbcmd;         /* Command register */
+       u32     usbsts;         /* Status register */
+       u32     usbintr;        /* Interrupt enable */
+       u32     frindex;        /* Frame index */
+       u32     reserved1[1];
+       u32     deviceaddr;     /* Device Address */
+       u32     eplistaddr;     /* Endpoint List Address */
+       u32     ttctrl;         /* HOST TT status and control */
+       u32     burstsize;      /* Programmable Burst Size */
+       u32     txfilltuning;   /* Host Transmit Pre-Buffer Packet Tuning */
+       u32     reserved[4];
+       u32     epnak;          /* Endpoint NAK */
+       u32     epnaken;        /* Endpoint NAK Enable */
+       u32     configflag;     /* Configured Flag register */
+       u32     portsc[VUSBHS_MAX_PORTS]; /* Port Status/Control x, x = 1..8 */
+       u32     otgsc;
+       u32     usbmode;        /* USB Host/Device mode */
+       u32     epsetupstat;    /* Endpoint Setup Status */
+       u32     epprime;        /* Endpoint Initialize */
+       u32     epflush;        /* Endpoint De-initialize */
+       u32     epstatus;       /* Endpoint Status */
+       u32     epcomplete;     /* Endpoint Interrupt On Complete */
+       u32     epctrlx[16];    /* Endpoint Control, where x = 0.. 15 */
+       u32     mcr;            /* Mux Control */
+       u32     isr;            /* Interrupt Status */
+       u32     ier;            /* Interrupt Enable */
+};
+
+struct mv_udc {
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+       spinlock_t                      lock;
+       struct completion               *done;
+       struct platform_device          *dev;
+       int                             irq;
+
+       struct mv_cap_regs __iomem      *cap_regs;
+       struct mv_op_regs __iomem       *op_regs;
+       void __iomem                    *phy_regs;
+       unsigned int                    max_eps;
+       struct mv_dqh                   *ep_dqh;
+       size_t                          ep_dqh_size;
+       dma_addr_t                      ep_dqh_dma;
+
+       struct dma_pool                 *dtd_pool;
+       struct mv_ep                    *eps;
+
+       struct mv_dtd                   *dtd_head;
+       struct mv_dtd                   *dtd_tail;
+       unsigned int                    dtd_entries;
+
+       struct mv_req                   *status_req;
+       struct usb_ctrlrequest          local_setup_buff;
+
+       unsigned int            resume_state;   /* USB state to resume */
+       unsigned int            usb_state;      /* USB current state */
+       unsigned int            ep0_state;      /* Endpoint zero state */
+       unsigned int            ep0_dir;
+
+       unsigned int            dev_addr;
+       unsigned int            test_mode;
+
+       int                     errors;
+       unsigned                softconnect:1,
+                               vbus_active:1,
+                               remote_wakeup:1,
+                               softconnected:1,
+                               force_fs:1,
+                               clock_gating:1,
+                               active:1,
+                               stopped:1;      /* stop bit is setted */
+
+       struct work_struct      vbus_work;
+       struct workqueue_struct *qwork;
+
+       struct usb_phy          *transceiver;
+
+       struct mv_usb_platform_data     *pdata;
+
+       /* some SOC has mutiple clock sources for USB*/
+       struct clk      *clk;
+};
+
+/* endpoint data structure */
+struct mv_ep {
+       struct usb_ep           ep;
+       struct mv_udc           *udc;
+       struct list_head        queue;
+       struct mv_dqh           *dqh;
+       u32                     direction;
+       char                    name[14];
+       unsigned                stopped:1,
+                               wedge:1,
+                               ep_type:2,
+                               ep_num:8;
+};
+
+/* request data structure */
+struct mv_req {
+       struct usb_request      req;
+       struct mv_dtd           *dtd, *head, *tail;
+       struct mv_ep            *ep;
+       struct list_head        queue;
+       unsigned int            test_mode;
+       unsigned                dtd_count;
+       unsigned                mapped:1;
+};
+
+#define EP_QUEUE_HEAD_MULT_POS                 30
+#define EP_QUEUE_HEAD_ZLT_SEL                  0x20000000
+#define EP_QUEUE_HEAD_MAX_PKT_LEN_POS          16
+#define EP_QUEUE_HEAD_MAX_PKT_LEN(ep_info)     (((ep_info)>>16)&0x07ff)
+#define EP_QUEUE_HEAD_IOS                      0x00008000
+#define EP_QUEUE_HEAD_NEXT_TERMINATE           0x00000001
+#define EP_QUEUE_HEAD_IOC                      0x00008000
+#define EP_QUEUE_HEAD_MULTO                    0x00000C00
+#define EP_QUEUE_HEAD_STATUS_HALT              0x00000040
+#define EP_QUEUE_HEAD_STATUS_ACTIVE            0x00000080
+#define EP_QUEUE_CURRENT_OFFSET_MASK           0x00000FFF
+#define EP_QUEUE_HEAD_NEXT_POINTER_MASK                0xFFFFFFE0
+#define EP_QUEUE_FRINDEX_MASK                  0x000007FF
+#define EP_MAX_LENGTH_TRANSFER                 0x4000
+
+struct mv_dqh {
+       /* Bits 16..26 Bit 15 is Interrupt On Setup */
+       u32     max_packet_length;
+       u32     curr_dtd_ptr;           /* Current dTD Pointer */
+       u32     next_dtd_ptr;           /* Next dTD Pointer */
+       /* Total bytes (16..30), IOC (15), INT (8), STS (0-7) */
+       u32     size_ioc_int_sts;
+       u32     buff_ptr0;              /* Buffer pointer Page 0 (12-31) */
+       u32     buff_ptr1;              /* Buffer pointer Page 1 (12-31) */
+       u32     buff_ptr2;              /* Buffer pointer Page 2 (12-31) */
+       u32     buff_ptr3;              /* Buffer pointer Page 3 (12-31) */
+       u32     buff_ptr4;              /* Buffer pointer Page 4 (12-31) */
+       u32     reserved1;
+       /* 8 bytes of setup data that follows the Setup PID */
+       u8      setup_buffer[8];
+       u32     reserved2[4];
+};
+
+
+#define DTD_NEXT_TERMINATE             (0x00000001)
+#define DTD_IOC                                (0x00008000)
+#define DTD_STATUS_ACTIVE              (0x00000080)
+#define DTD_STATUS_HALTED              (0x00000040)
+#define DTD_STATUS_DATA_BUFF_ERR       (0x00000020)
+#define DTD_STATUS_TRANSACTION_ERR     (0x00000008)
+#define DTD_RESERVED_FIELDS            (0x00007F00)
+#define DTD_ERROR_MASK                 (0x68)
+#define DTD_ADDR_MASK                  (0xFFFFFFE0)
+#define DTD_PACKET_SIZE                        0x7FFF0000
+#define DTD_LENGTH_BIT_POS             (16)
+
+struct mv_dtd {
+       u32     dtd_next;
+       u32     size_ioc_sts;
+       u32     buff_ptr0;              /* Buffer pointer Page 0 */
+       u32     buff_ptr1;              /* Buffer pointer Page 1 */
+       u32     buff_ptr2;              /* Buffer pointer Page 2 */
+       u32     buff_ptr3;              /* Buffer pointer Page 3 */
+       u32     buff_ptr4;              /* Buffer pointer Page 4 */
+       u32     scratch_ptr;
+       /* 32 bytes */
+       dma_addr_t td_dma;              /* dma address for this td */
+       struct mv_dtd *next_dtd_virt;
+};
+
+#endif
diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c
new file mode 100644 (file)
index 0000000..fcff3a5
--- /dev/null
@@ -0,0 +1,2423 @@
+/*
+ * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
+ * Author: Chao Xie <chao.xie@marvell.com>
+ *        Neil Zhang <zhangwm@marvell.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+#include <linux/pm.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/platform_data/mv_usb.h>
+#include <asm/unaligned.h>
+
+#include "mv_udc.h"
+
+#define DRIVER_DESC            "Marvell PXA USB Device Controller driver"
+#define DRIVER_VERSION         "8 Nov 2010"
+
+#define ep_dir(ep)     (((ep)->ep_num == 0) ? \
+                               ((ep)->udc->ep0_dir) : ((ep)->direction))
+
+/* timeout value -- usec */
+#define RESET_TIMEOUT          10000
+#define FLUSH_TIMEOUT          10000
+#define EPSTATUS_TIMEOUT       10000
+#define PRIME_TIMEOUT          10000
+#define READSAFE_TIMEOUT       1000
+
+#define LOOPS_USEC_SHIFT       1
+#define LOOPS_USEC             (1 << LOOPS_USEC_SHIFT)
+#define LOOPS(timeout)         ((timeout) >> LOOPS_USEC_SHIFT)
+
+static DECLARE_COMPLETION(release_done);
+
+static const char driver_name[] = "mv_udc";
+static const char driver_desc[] = DRIVER_DESC;
+
+static void nuke(struct mv_ep *ep, int status);
+static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver);
+
+/* for endpoint 0 operations */
+static const struct usb_endpoint_descriptor mv_ep0_desc = {
+       .bLength =              USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bEndpointAddress =     0,
+       .bmAttributes =         USB_ENDPOINT_XFER_CONTROL,
+       .wMaxPacketSize =       EP0_MAX_PKT_SIZE,
+};
+
+static void ep0_reset(struct mv_udc *udc)
+{
+       struct mv_ep *ep;
+       u32 epctrlx;
+       int i = 0;
+
+       /* ep0 in and out */
+       for (i = 0; i < 2; i++) {
+               ep = &udc->eps[i];
+               ep->udc = udc;
+
+               /* ep0 dQH */
+               ep->dqh = &udc->ep_dqh[i];
+
+               /* configure ep0 endpoint capabilities in dQH */
+               ep->dqh->max_packet_length =
+                       (EP0_MAX_PKT_SIZE << EP_QUEUE_HEAD_MAX_PKT_LEN_POS)
+                       | EP_QUEUE_HEAD_IOS;
+
+               ep->dqh->next_dtd_ptr = EP_QUEUE_HEAD_NEXT_TERMINATE;
+
+               epctrlx = readl(&udc->op_regs->epctrlx[0]);
+               if (i) {        /* TX */
+                       epctrlx |= EPCTRL_TX_ENABLE
+                               | (USB_ENDPOINT_XFER_CONTROL
+                                       << EPCTRL_TX_EP_TYPE_SHIFT);
+
+               } else {        /* RX */
+                       epctrlx |= EPCTRL_RX_ENABLE
+                               | (USB_ENDPOINT_XFER_CONTROL
+                                       << EPCTRL_RX_EP_TYPE_SHIFT);
+               }
+
+               writel(epctrlx, &udc->op_regs->epctrlx[0]);
+       }
+}
+
+/* protocol ep0 stall, will automatically be cleared on new transaction */
+static void ep0_stall(struct mv_udc *udc)
+{
+       u32     epctrlx;
+
+       /* set TX and RX to stall */
+       epctrlx = readl(&udc->op_regs->epctrlx[0]);
+       epctrlx |= EPCTRL_RX_EP_STALL | EPCTRL_TX_EP_STALL;
+       writel(epctrlx, &udc->op_regs->epctrlx[0]);
+
+       /* update ep0 state */
+       udc->ep0_state = WAIT_FOR_SETUP;
+       udc->ep0_dir = EP_DIR_OUT;
+}
+
+static int process_ep_req(struct mv_udc *udc, int index,
+       struct mv_req *curr_req)
+{
+       struct mv_dtd   *curr_dtd;
+       struct mv_dqh   *curr_dqh;
+       int td_complete, actual, remaining_length;
+       int i, direction;
+       int retval = 0;
+       u32 errors;
+       u32 bit_pos;
+
+       curr_dqh = &udc->ep_dqh[index];
+       direction = index % 2;
+
+       curr_dtd = curr_req->head;
+       td_complete = 0;
+       actual = curr_req->req.length;
+
+       for (i = 0; i < curr_req->dtd_count; i++) {
+               if (curr_dtd->size_ioc_sts & DTD_STATUS_ACTIVE) {
+                       dev_dbg(&udc->dev->dev, "%s, dTD not completed\n",
+                               udc->eps[index].name);
+                       return 1;
+               }
+
+               errors = curr_dtd->size_ioc_sts & DTD_ERROR_MASK;
+               if (!errors) {
+                       remaining_length =
+                               (curr_dtd->size_ioc_sts & DTD_PACKET_SIZE)
+                                       >> DTD_LENGTH_BIT_POS;
+                       actual -= remaining_length;
+
+                       if (remaining_length) {
+                               if (direction) {
+                                       dev_dbg(&udc->dev->dev,
+                                               "TX dTD remains data\n");
+                                       retval = -EPROTO;
+                                       break;
+                               } else
+                                       break;
+                       }
+               } else {
+                       dev_info(&udc->dev->dev,
+                               "complete_tr error: ep=%d %s: error = 0x%x\n",
+                               index >> 1, direction ? "SEND" : "RECV",
+                               errors);
+                       if (errors & DTD_STATUS_HALTED) {
+                               /* Clear the errors and Halt condition */
+                               curr_dqh->size_ioc_int_sts &= ~errors;
+                               retval = -EPIPE;
+                       } else if (errors & DTD_STATUS_DATA_BUFF_ERR) {
+                               retval = -EPROTO;
+                       } else if (errors & DTD_STATUS_TRANSACTION_ERR) {
+                               retval = -EILSEQ;
+                       }
+               }
+               if (i != curr_req->dtd_count - 1)
+                       curr_dtd = (struct mv_dtd *)curr_dtd->next_dtd_virt;
+       }
+       if (retval)
+               return retval;
+
+       if (direction == EP_DIR_OUT)
+               bit_pos = 1 << curr_req->ep->ep_num;
+       else
+               bit_pos = 1 << (16 + curr_req->ep->ep_num);
+
+       while ((curr_dqh->curr_dtd_ptr == curr_dtd->td_dma)) {
+               if (curr_dtd->dtd_next == EP_QUEUE_HEAD_NEXT_TERMINATE) {
+                       while (readl(&udc->op_regs->epstatus) & bit_pos)
+                               udelay(1);
+                       break;
+               }
+               udelay(1);
+       }
+
+       curr_req->req.actual = actual;
+
+       return 0;
+}
+
+/*
+ * done() - retire a request; caller blocked irqs
+ * @status : request status to be set, only works when
+ * request is still in progress.
+ */
+static void done(struct mv_ep *ep, struct mv_req *req, int status)
+       __releases(&ep->udc->lock)
+       __acquires(&ep->udc->lock)
+{
+       struct mv_udc *udc = NULL;
+       unsigned char stopped = ep->stopped;
+       struct mv_dtd *curr_td, *next_td;
+       int j;
+
+       udc = (struct mv_udc *)ep->udc;
+       /* Removed the req from fsl_ep->queue */
+       list_del_init(&req->queue);
+
+       /* req.status should be set as -EINPROGRESS in ep_queue() */
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       /* Free dtd for the request */
+       next_td = req->head;
+       for (j = 0; j < req->dtd_count; j++) {
+               curr_td = next_td;
+               if (j != req->dtd_count - 1)
+                       next_td = curr_td->next_dtd_virt;
+               dma_pool_free(udc->dtd_pool, curr_td, curr_td->td_dma);
+       }
+
+       usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
+
+       if (status && (status != -ESHUTDOWN))
+               dev_info(&udc->dev->dev, "complete %s req %p stat %d len %u/%u",
+                       ep->ep.name, &req->req, status,
+                       req->req.actual, req->req.length);
+
+       ep->stopped = 1;
+
+       spin_unlock(&ep->udc->lock);
+       /*
+        * complete() is from gadget layer,
+        * eg fsg->bulk_in_complete()
+        */
+       if (req->req.complete)
+               req->req.complete(&ep->ep, &req->req);
+
+       spin_lock(&ep->udc->lock);
+       ep->stopped = stopped;
+}
+
+static int queue_dtd(struct mv_ep *ep, struct mv_req *req)
+{
+       struct mv_udc *udc;
+       struct mv_dqh *dqh;
+       u32 bit_pos, direction;
+       u32 usbcmd, epstatus;
+       unsigned int loops;
+       int retval = 0;
+
+       udc = ep->udc;
+       direction = ep_dir(ep);
+       dqh = &(udc->ep_dqh[ep->ep_num * 2 + direction]);
+       bit_pos = 1 << (((direction == EP_DIR_OUT) ? 0 : 16) + ep->ep_num);
+
+       /* check if the pipe is empty */
+       if (!(list_empty(&ep->queue))) {
+               struct mv_req *lastreq;
+               lastreq = list_entry(ep->queue.prev, struct mv_req, queue);
+               lastreq->tail->dtd_next =
+                       req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK;
+
+               wmb();
+
+               if (readl(&udc->op_regs->epprime) & bit_pos)
+                       goto done;
+
+               loops = LOOPS(READSAFE_TIMEOUT);
+               while (1) {
+                       /* start with setting the semaphores */
+                       usbcmd = readl(&udc->op_regs->usbcmd);
+                       usbcmd |= USBCMD_ATDTW_TRIPWIRE_SET;
+                       writel(usbcmd, &udc->op_regs->usbcmd);
+
+                       /* read the endpoint status */
+                       epstatus = readl(&udc->op_regs->epstatus) & bit_pos;
+
+                       /*
+                        * Reread the ATDTW semaphore bit to check if it is
+                        * cleared. When hardware see a hazard, it will clear
+                        * the bit or else we remain set to 1 and we can
+                        * proceed with priming of endpoint if not already
+                        * primed.
+                        */
+                       if (readl(&udc->op_regs->usbcmd)
+                               & USBCMD_ATDTW_TRIPWIRE_SET)
+                               break;
+
+                       loops--;
+                       if (loops == 0) {
+                               dev_err(&udc->dev->dev,
+                                       "Timeout for ATDTW_TRIPWIRE...\n");
+                               retval = -ETIME;
+                               goto done;
+                       }
+                       udelay(LOOPS_USEC);
+               }
+
+               /* Clear the semaphore */
+               usbcmd = readl(&udc->op_regs->usbcmd);
+               usbcmd &= USBCMD_ATDTW_TRIPWIRE_CLEAR;
+               writel(usbcmd, &udc->op_regs->usbcmd);
+
+               if (epstatus)
+                       goto done;
+       }
+
+       /* Write dQH next pointer and terminate bit to 0 */
+       dqh->next_dtd_ptr = req->head->td_dma
+                               & EP_QUEUE_HEAD_NEXT_POINTER_MASK;
+
+       /* clear active and halt bit, in case set from a previous error */
+       dqh->size_ioc_int_sts &= ~(DTD_STATUS_ACTIVE | DTD_STATUS_HALTED);
+
+       /* Ensure that updates to the QH will occure before priming. */
+       wmb();
+
+       /* Prime the Endpoint */
+       writel(bit_pos, &udc->op_regs->epprime);
+
+done:
+       return retval;
+}
+
+static struct mv_dtd *build_dtd(struct mv_req *req, unsigned *length,
+               dma_addr_t *dma, int *is_last)
+{
+       struct mv_dtd *dtd;
+       struct mv_udc *udc;
+       struct mv_dqh *dqh;
+       u32 temp, mult = 0;
+
+       /* how big will this transfer be? */
+       if (usb_endpoint_xfer_isoc(req->ep->ep.desc)) {
+               dqh = req->ep->dqh;
+               mult = (dqh->max_packet_length >> EP_QUEUE_HEAD_MULT_POS)
+                               & 0x3;
+               *length = min(req->req.length - req->req.actual,
+                               (unsigned)(mult * req->ep->ep.maxpacket));
+       } else
+               *length = min(req->req.length - req->req.actual,
+                               (unsigned)EP_MAX_LENGTH_TRANSFER);
+
+       udc = req->ep->udc;
+
+       /*
+        * Be careful that no _GFP_HIGHMEM is set,
+        * or we can not use dma_to_virt
+        */
+       dtd = dma_pool_alloc(udc->dtd_pool, GFP_ATOMIC, dma);
+       if (dtd == NULL)
+               return dtd;
+
+       dtd->td_dma = *dma;
+       /* initialize buffer page pointers */
+       temp = (u32)(req->req.dma + req->req.actual);
+       dtd->buff_ptr0 = cpu_to_le32(temp);
+       temp &= ~0xFFF;
+       dtd->buff_ptr1 = cpu_to_le32(temp + 0x1000);
+       dtd->buff_ptr2 = cpu_to_le32(temp + 0x2000);
+       dtd->buff_ptr3 = cpu_to_le32(temp + 0x3000);
+       dtd->buff_ptr4 = cpu_to_le32(temp + 0x4000);
+
+       req->req.actual += *length;
+
+       /* zlp is needed if req->req.zero is set */
+       if (req->req.zero) {
+               if (*length == 0 || (*length % req->ep->ep.maxpacket) != 0)
+                       *is_last = 1;
+               else
+                       *is_last = 0;
+       } else if (req->req.length == req->req.actual)
+               *is_last = 1;
+       else
+               *is_last = 0;
+
+       /* Fill in the transfer size; set active bit */
+       temp = ((*length << DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE);
+
+       /* Enable interrupt for the last dtd of a request */
+       if (*is_last && !req->req.no_interrupt)
+               temp |= DTD_IOC;
+
+       temp |= mult << 10;
+
+       dtd->size_ioc_sts = temp;
+
+       mb();
+
+       return dtd;
+}
+
+/* generate dTD linked list for a request */
+static int req_to_dtd(struct mv_req *req)
+{
+       unsigned count;
+       int is_last, is_first = 1;
+       struct mv_dtd *dtd, *last_dtd = NULL;
+       struct mv_udc *udc;
+       dma_addr_t dma;
+
+       udc = req->ep->udc;
+
+       do {
+               dtd = build_dtd(req, &count, &dma, &is_last);
+               if (dtd == NULL)
+                       return -ENOMEM;
+
+               if (is_first) {
+                       is_first = 0;
+                       req->head = dtd;
+               } else {
+                       last_dtd->dtd_next = dma;
+                       last_dtd->next_dtd_virt = dtd;
+               }
+               last_dtd = dtd;
+               req->dtd_count++;
+       } while (!is_last);
+
+       /* set terminate bit to 1 for the last dTD */
+       dtd->dtd_next = DTD_NEXT_TERMINATE;
+
+       req->tail = dtd;
+
+       return 0;
+}
+
+static int mv_ep_enable(struct usb_ep *_ep,
+               const struct usb_endpoint_descriptor *desc)
+{
+       struct mv_udc *udc;
+       struct mv_ep *ep;
+       struct mv_dqh *dqh;
+       u16 max = 0;
+       u32 bit_pos, epctrlx, direction;
+       unsigned char zlt = 0, ios = 0, mult = 0;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct mv_ep, ep);
+       udc = ep->udc;
+
+       if (!_ep || !desc
+                       || desc->bDescriptorType != USB_DT_ENDPOINT)
+               return -EINVAL;
+
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       direction = ep_dir(ep);
+       max = usb_endpoint_maxp(desc);
+
+       /*
+        * disable HW zero length termination select
+        * driver handles zero length packet through req->req.zero
+        */
+       zlt = 1;
+
+       bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num);
+
+       /* Check if the Endpoint is Primed */
+       if ((readl(&udc->op_regs->epprime) & bit_pos)
+               || (readl(&udc->op_regs->epstatus) & bit_pos)) {
+               dev_info(&udc->dev->dev,
+                       "ep=%d %s: Init ERROR: ENDPTPRIME=0x%x,"
+                       " ENDPTSTATUS=0x%x, bit_pos=0x%x\n",
+                       (unsigned)ep->ep_num, direction ? "SEND" : "RECV",
+                       (unsigned)readl(&udc->op_regs->epprime),
+                       (unsigned)readl(&udc->op_regs->epstatus),
+                       (unsigned)bit_pos);
+               goto en_done;
+       }
+       /* Set the max packet length, interrupt on Setup and Mult fields */
+       switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+       case USB_ENDPOINT_XFER_BULK:
+               zlt = 1;
+               mult = 0;
+               break;
+       case USB_ENDPOINT_XFER_CONTROL:
+               ios = 1;
+       case USB_ENDPOINT_XFER_INT:
+               mult = 0;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               /* Calculate transactions needed for high bandwidth iso */
+               mult = (unsigned char)(1 + ((max >> 11) & 0x03));
+               max = max & 0x7ff;      /* bit 0~10 */
+               /* 3 transactions at most */
+               if (mult > 3)
+                       goto en_done;
+               break;
+       default:
+               goto en_done;
+       }
+
+       spin_lock_irqsave(&udc->lock, flags);
+       /* Get the endpoint queue head address */
+       dqh = ep->dqh;
+       dqh->max_packet_length = (max << EP_QUEUE_HEAD_MAX_PKT_LEN_POS)
+               | (mult << EP_QUEUE_HEAD_MULT_POS)
+               | (zlt ? EP_QUEUE_HEAD_ZLT_SEL : 0)
+               | (ios ? EP_QUEUE_HEAD_IOS : 0);
+       dqh->next_dtd_ptr = 1;
+       dqh->size_ioc_int_sts = 0;
+
+       ep->ep.maxpacket = max;
+       ep->ep.desc = desc;
+       ep->stopped = 0;
+
+       /* Enable the endpoint for Rx or Tx and set the endpoint type */
+       epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
+       if (direction == EP_DIR_IN) {
+               epctrlx &= ~EPCTRL_TX_ALL_MASK;
+               epctrlx |= EPCTRL_TX_ENABLE | EPCTRL_TX_DATA_TOGGLE_RST
+                       | ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+                               << EPCTRL_TX_EP_TYPE_SHIFT);
+       } else {
+               epctrlx &= ~EPCTRL_RX_ALL_MASK;
+               epctrlx |= EPCTRL_RX_ENABLE | EPCTRL_RX_DATA_TOGGLE_RST
+                       | ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+                               << EPCTRL_RX_EP_TYPE_SHIFT);
+       }
+       writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
+
+       /*
+        * Implement Guideline (GL# USB-7) The unused endpoint type must
+        * be programmed to bulk.
+        */
+       epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
+       if ((epctrlx & EPCTRL_RX_ENABLE) == 0) {
+               epctrlx |= (USB_ENDPOINT_XFER_BULK
+                               << EPCTRL_RX_EP_TYPE_SHIFT);
+               writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
+       }
+
+       epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
+       if ((epctrlx & EPCTRL_TX_ENABLE) == 0) {
+               epctrlx |= (USB_ENDPOINT_XFER_BULK
+                               << EPCTRL_TX_EP_TYPE_SHIFT);
+               writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+en_done:
+       return -EINVAL;
+}
+
+static int  mv_ep_disable(struct usb_ep *_ep)
+{
+       struct mv_udc *udc;
+       struct mv_ep *ep;
+       struct mv_dqh *dqh;
+       u32 bit_pos, epctrlx, direction;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct mv_ep, ep);
+       if ((_ep == NULL) || !ep->ep.desc)
+               return -EINVAL;
+
+       udc = ep->udc;
+
+       /* Get the endpoint queue head address */
+       dqh = ep->dqh;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       direction = ep_dir(ep);
+       bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num);
+
+       /* Reset the max packet length and the interrupt on Setup */
+       dqh->max_packet_length = 0;
+
+       /* Disable the endpoint for Rx or Tx and reset the endpoint type */
+       epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
+       epctrlx &= ~((direction == EP_DIR_IN)
+                       ? (EPCTRL_TX_ENABLE | EPCTRL_TX_TYPE)
+                       : (EPCTRL_RX_ENABLE | EPCTRL_RX_TYPE));
+       writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
+
+       /* nuke all pending requests (does flush) */
+       nuke(ep, -ESHUTDOWN);
+
+       ep->ep.desc = NULL;
+       ep->stopped = 1;
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static struct usb_request *
+mv_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct mv_req *req = NULL;
+
+       req = kzalloc(sizeof *req, gfp_flags);
+       if (!req)
+               return NULL;
+
+       req->req.dma = DMA_ADDR_INVALID;
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void mv_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct mv_req *req = NULL;
+
+       req = container_of(_req, struct mv_req, req);
+
+       if (_req)
+               kfree(req);
+}
+
+static void mv_ep_fifo_flush(struct usb_ep *_ep)
+{
+       struct mv_udc *udc;
+       u32 bit_pos, direction;
+       struct mv_ep *ep;
+       unsigned int loops;
+
+       if (!_ep)
+               return;
+
+       ep = container_of(_ep, struct mv_ep, ep);
+       if (!ep->ep.desc)
+               return;
+
+       udc = ep->udc;
+       direction = ep_dir(ep);
+
+       if (ep->ep_num == 0)
+               bit_pos = (1 << 16) | 1;
+       else if (direction == EP_DIR_OUT)
+               bit_pos = 1 << ep->ep_num;
+       else
+               bit_pos = 1 << (16 + ep->ep_num);
+
+       loops = LOOPS(EPSTATUS_TIMEOUT);
+       do {
+               unsigned int inter_loops;
+
+               if (loops == 0) {
+                       dev_err(&udc->dev->dev,
+                               "TIMEOUT for ENDPTSTATUS=0x%x, bit_pos=0x%x\n",
+                               (unsigned)readl(&udc->op_regs->epstatus),
+                               (unsigned)bit_pos);
+                       return;
+               }
+               /* Write 1 to the Flush register */
+               writel(bit_pos, &udc->op_regs->epflush);
+
+               /* Wait until flushing completed */
+               inter_loops = LOOPS(FLUSH_TIMEOUT);
+               while (readl(&udc->op_regs->epflush)) {
+                       /*
+                        * ENDPTFLUSH bit should be cleared to indicate this
+                        * operation is complete
+                        */
+                       if (inter_loops == 0) {
+                               dev_err(&udc->dev->dev,
+                                       "TIMEOUT for ENDPTFLUSH=0x%x,"
+                                       "bit_pos=0x%x\n",
+                                       (unsigned)readl(&udc->op_regs->epflush),
+                                       (unsigned)bit_pos);
+                               return;
+                       }
+                       inter_loops--;
+                       udelay(LOOPS_USEC);
+               }
+               loops--;
+       } while (readl(&udc->op_regs->epstatus) & bit_pos);
+}
+
+/* queues (submits) an I/O request to an endpoint */
+static int
+mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+       struct mv_ep *ep = container_of(_ep, struct mv_ep, ep);
+       struct mv_req *req = container_of(_req, struct mv_req, req);
+       struct mv_udc *udc = ep->udc;
+       unsigned long flags;
+       int retval;
+
+       /* catch various bogus parameters */
+       if (!_req || !req->req.complete || !req->req.buf
+                       || !list_empty(&req->queue)) {
+               dev_err(&udc->dev->dev, "%s, bad params", __func__);
+               return -EINVAL;
+       }
+       if (unlikely(!_ep || !ep->ep.desc)) {
+               dev_err(&udc->dev->dev, "%s, bad ep", __func__);
+               return -EINVAL;
+       }
+
+       udc = ep->udc;
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       req->ep = ep;
+
+       /* map virtual address to hardware */
+       retval = usb_gadget_map_request(&udc->gadget, _req, ep_dir(ep));
+       if (retval)
+               return retval;
+
+       req->req.status = -EINPROGRESS;
+       req->req.actual = 0;
+       req->dtd_count = 0;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /* build dtds and push them to device queue */
+       if (!req_to_dtd(req)) {
+               retval = queue_dtd(ep, req);
+               if (retval) {
+                       spin_unlock_irqrestore(&udc->lock, flags);
+                       dev_err(&udc->dev->dev, "Failed to queue dtd\n");
+                       goto err_unmap_dma;
+               }
+       } else {
+               spin_unlock_irqrestore(&udc->lock, flags);
+               dev_err(&udc->dev->dev, "Failed to dma_pool_alloc\n");
+               retval = -ENOMEM;
+               goto err_unmap_dma;
+       }
+
+       /* Update ep0 state */
+       if (ep->ep_num == 0)
+               udc->ep0_state = DATA_STATE_XMIT;
+
+       /* irq handler advances the queue */
+       list_add_tail(&req->queue, &ep->queue);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+
+err_unmap_dma:
+       usb_gadget_unmap_request(&udc->gadget, _req, ep_dir(ep));
+
+       return retval;
+}
+
+static void mv_prime_ep(struct mv_ep *ep, struct mv_req *req)
+{
+       struct mv_dqh *dqh = ep->dqh;
+       u32 bit_pos;
+
+       /* Write dQH next pointer and terminate bit to 0 */
+       dqh->next_dtd_ptr = req->head->td_dma
+               & EP_QUEUE_HEAD_NEXT_POINTER_MASK;
+
+       /* clear active and halt bit, in case set from a previous error */
+       dqh->size_ioc_int_sts &= ~(DTD_STATUS_ACTIVE | DTD_STATUS_HALTED);
+
+       /* Ensure that updates to the QH will occure before priming. */
+       wmb();
+
+       bit_pos = 1 << (((ep_dir(ep) == EP_DIR_OUT) ? 0 : 16) + ep->ep_num);
+
+       /* Prime the Endpoint */
+       writel(bit_pos, &ep->udc->op_regs->epprime);
+}
+
+/* dequeues (cancels, unlinks) an I/O request from an endpoint */
+static int mv_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct mv_ep *ep = container_of(_ep, struct mv_ep, ep);
+       struct mv_req *req;
+       struct mv_udc *udc = ep->udc;
+       unsigned long flags;
+       int stopped, ret = 0;
+       u32 epctrlx;
+
+       if (!_ep || !_req)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+       stopped = ep->stopped;
+
+       /* Stop the ep before we deal with the queue */
+       ep->stopped = 1;
+       epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
+       if (ep_dir(ep) == EP_DIR_IN)
+               epctrlx &= ~EPCTRL_TX_ENABLE;
+       else
+               epctrlx &= ~EPCTRL_RX_ENABLE;
+       writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* The request is in progress, or completed but not dequeued */
+       if (ep->queue.next == &req->queue) {
+               _req->status = -ECONNRESET;
+               mv_ep_fifo_flush(_ep);  /* flush current transfer */
+
+               /* The request isn't the last request in this ep queue */
+               if (req->queue.next != &ep->queue) {
+                       struct mv_req *next_req;
+
+                       next_req = list_entry(req->queue.next,
+                               struct mv_req, queue);
+
+                       /* Point the QH to the first TD of next request */
+                       mv_prime_ep(ep, next_req);
+               } else {
+                       struct mv_dqh *qh;
+
+                       qh = ep->dqh;
+                       qh->next_dtd_ptr = 1;
+                       qh->size_ioc_int_sts = 0;
+               }
+
+               /* The request hasn't been processed, patch up the TD chain */
+       } else {
+               struct mv_req *prev_req;
+
+               prev_req = list_entry(req->queue.prev, struct mv_req, queue);
+               writel(readl(&req->tail->dtd_next),
+                               &prev_req->tail->dtd_next);
+
+       }
+
+       done(ep, req, -ECONNRESET);
+
+       /* Enable EP */
+out:
+       epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
+       if (ep_dir(ep) == EP_DIR_IN)
+               epctrlx |= EPCTRL_TX_ENABLE;
+       else
+               epctrlx |= EPCTRL_RX_ENABLE;
+       writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
+       ep->stopped = stopped;
+
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+       return ret;
+}
+
+static void ep_set_stall(struct mv_udc *udc, u8 ep_num, u8 direction, int stall)
+{
+       u32 epctrlx;
+
+       epctrlx = readl(&udc->op_regs->epctrlx[ep_num]);
+
+       if (stall) {
+               if (direction == EP_DIR_IN)
+                       epctrlx |= EPCTRL_TX_EP_STALL;
+               else
+                       epctrlx |= EPCTRL_RX_EP_STALL;
+       } else {
+               if (direction == EP_DIR_IN) {
+                       epctrlx &= ~EPCTRL_TX_EP_STALL;
+                       epctrlx |= EPCTRL_TX_DATA_TOGGLE_RST;
+               } else {
+                       epctrlx &= ~EPCTRL_RX_EP_STALL;
+                       epctrlx |= EPCTRL_RX_DATA_TOGGLE_RST;
+               }
+       }
+       writel(epctrlx, &udc->op_regs->epctrlx[ep_num]);
+}
+
+static int ep_is_stall(struct mv_udc *udc, u8 ep_num, u8 direction)
+{
+       u32 epctrlx;
+
+       epctrlx = readl(&udc->op_regs->epctrlx[ep_num]);
+
+       if (direction == EP_DIR_OUT)
+               return (epctrlx & EPCTRL_RX_EP_STALL) ? 1 : 0;
+       else
+               return (epctrlx & EPCTRL_TX_EP_STALL) ? 1 : 0;
+}
+
+static int mv_ep_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge)
+{
+       struct mv_ep *ep;
+       unsigned long flags = 0;
+       int status = 0;
+       struct mv_udc *udc;
+
+       ep = container_of(_ep, struct mv_ep, ep);
+       udc = ep->udc;
+       if (!_ep || !ep->ep.desc) {
+               status = -EINVAL;
+               goto out;
+       }
+
+       if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+               status = -EOPNOTSUPP;
+               goto out;
+       }
+
+       /*
+        * Attempt to halt IN ep will fail if any transfer requests
+        * are still queue
+        */
+       if (halt && (ep_dir(ep) == EP_DIR_IN) && !list_empty(&ep->queue)) {
+               status = -EAGAIN;
+               goto out;
+       }
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+       ep_set_stall(udc, ep->ep_num, ep_dir(ep), halt);
+       if (halt && wedge)
+               ep->wedge = 1;
+       else if (!halt)
+               ep->wedge = 0;
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+
+       if (ep->ep_num == 0) {
+               udc->ep0_state = WAIT_FOR_SETUP;
+               udc->ep0_dir = EP_DIR_OUT;
+       }
+out:
+       return status;
+}
+
+static int mv_ep_set_halt(struct usb_ep *_ep, int halt)
+{
+       return mv_ep_set_halt_wedge(_ep, halt, 0);
+}
+
+static int mv_ep_set_wedge(struct usb_ep *_ep)
+{
+       return mv_ep_set_halt_wedge(_ep, 1, 1);
+}
+
+static struct usb_ep_ops mv_ep_ops = {
+       .enable         = mv_ep_enable,
+       .disable        = mv_ep_disable,
+
+       .alloc_request  = mv_alloc_request,
+       .free_request   = mv_free_request,
+
+       .queue          = mv_ep_queue,
+       .dequeue        = mv_ep_dequeue,
+
+       .set_wedge      = mv_ep_set_wedge,
+       .set_halt       = mv_ep_set_halt,
+       .fifo_flush     = mv_ep_fifo_flush,     /* flush fifo */
+};
+
+static void udc_clock_enable(struct mv_udc *udc)
+{
+       clk_prepare_enable(udc->clk);
+}
+
+static void udc_clock_disable(struct mv_udc *udc)
+{
+       clk_disable_unprepare(udc->clk);
+}
+
+static void udc_stop(struct mv_udc *udc)
+{
+       u32 tmp;
+
+       /* Disable interrupts */
+       tmp = readl(&udc->op_regs->usbintr);
+       tmp &= ~(USBINTR_INT_EN | USBINTR_ERR_INT_EN |
+               USBINTR_PORT_CHANGE_DETECT_EN | USBINTR_RESET_EN);
+       writel(tmp, &udc->op_regs->usbintr);
+
+       udc->stopped = 1;
+
+       /* Reset the Run the bit in the command register to stop VUSB */
+       tmp = readl(&udc->op_regs->usbcmd);
+       tmp &= ~USBCMD_RUN_STOP;
+       writel(tmp, &udc->op_regs->usbcmd);
+}
+
+static void udc_start(struct mv_udc *udc)
+{
+       u32 usbintr;
+
+       usbintr = USBINTR_INT_EN | USBINTR_ERR_INT_EN
+               | USBINTR_PORT_CHANGE_DETECT_EN
+               | USBINTR_RESET_EN | USBINTR_DEVICE_SUSPEND;
+       /* Enable interrupts */
+       writel(usbintr, &udc->op_regs->usbintr);
+
+       udc->stopped = 0;
+
+       /* Set the Run bit in the command register */
+       writel(USBCMD_RUN_STOP, &udc->op_regs->usbcmd);
+}
+
+static int udc_reset(struct mv_udc *udc)
+{
+       unsigned int loops;
+       u32 tmp, portsc;
+
+       /* Stop the controller */
+       tmp = readl(&udc->op_regs->usbcmd);
+       tmp &= ~USBCMD_RUN_STOP;
+       writel(tmp, &udc->op_regs->usbcmd);
+
+       /* Reset the controller to get default values */
+       writel(USBCMD_CTRL_RESET, &udc->op_regs->usbcmd);
+
+       /* wait for reset to complete */
+       loops = LOOPS(RESET_TIMEOUT);
+       while (readl(&udc->op_regs->usbcmd) & USBCMD_CTRL_RESET) {
+               if (loops == 0) {
+                       dev_err(&udc->dev->dev,
+                               "Wait for RESET completed TIMEOUT\n");
+                       return -ETIMEDOUT;
+               }
+               loops--;
+               udelay(LOOPS_USEC);
+       }
+
+       /* set controller to device mode */
+       tmp = readl(&udc->op_regs->usbmode);
+       tmp |= USBMODE_CTRL_MODE_DEVICE;
+
+       /* turn setup lockout off, require setup tripwire in usbcmd */
+       tmp |= USBMODE_SETUP_LOCK_OFF;
+
+       writel(tmp, &udc->op_regs->usbmode);
+
+       writel(0x0, &udc->op_regs->epsetupstat);
+
+       /* Configure the Endpoint List Address */
+       writel(udc->ep_dqh_dma & USB_EP_LIST_ADDRESS_MASK,
+               &udc->op_regs->eplistaddr);
+
+       portsc = readl(&udc->op_regs->portsc[0]);
+       if (readl(&udc->cap_regs->hcsparams) & HCSPARAMS_PPC)
+               portsc &= (~PORTSCX_W1C_BITS | ~PORTSCX_PORT_POWER);
+
+       if (udc->force_fs)
+               portsc |= PORTSCX_FORCE_FULL_SPEED_CONNECT;
+       else
+               portsc &= (~PORTSCX_FORCE_FULL_SPEED_CONNECT);
+
+       writel(portsc, &udc->op_regs->portsc[0]);
+
+       tmp = readl(&udc->op_regs->epctrlx[0]);
+       tmp &= ~(EPCTRL_TX_EP_STALL | EPCTRL_RX_EP_STALL);
+       writel(tmp, &udc->op_regs->epctrlx[0]);
+
+       return 0;
+}
+
+static int mv_udc_enable_internal(struct mv_udc *udc)
+{
+       int retval;
+
+       if (udc->active)
+               return 0;
+
+       dev_dbg(&udc->dev->dev, "enable udc\n");
+       udc_clock_enable(udc);
+       if (udc->pdata->phy_init) {
+               retval = udc->pdata->phy_init(udc->phy_regs);
+               if (retval) {
+                       dev_err(&udc->dev->dev,
+                               "init phy error %d\n", retval);
+                       udc_clock_disable(udc);
+                       return retval;
+               }
+       }
+       udc->active = 1;
+
+       return 0;
+}
+
+static int mv_udc_enable(struct mv_udc *udc)
+{
+       if (udc->clock_gating)
+               return mv_udc_enable_internal(udc);
+
+       return 0;
+}
+
+static void mv_udc_disable_internal(struct mv_udc *udc)
+{
+       if (udc->active) {
+               dev_dbg(&udc->dev->dev, "disable udc\n");
+               if (udc->pdata->phy_deinit)
+                       udc->pdata->phy_deinit(udc->phy_regs);
+               udc_clock_disable(udc);
+               udc->active = 0;
+       }
+}
+
+static void mv_udc_disable(struct mv_udc *udc)
+{
+       if (udc->clock_gating)
+               mv_udc_disable_internal(udc);
+}
+
+static int mv_udc_get_frame(struct usb_gadget *gadget)
+{
+       struct mv_udc *udc;
+       u16     retval;
+
+       if (!gadget)
+               return -ENODEV;
+
+       udc = container_of(gadget, struct mv_udc, gadget);
+
+       retval = readl(&udc->op_regs->frindex) & USB_FRINDEX_MASKS;
+
+       return retval;
+}
+
+/* Tries to wake up the host connected to this gadget */
+static int mv_udc_wakeup(struct usb_gadget *gadget)
+{
+       struct mv_udc *udc = container_of(gadget, struct mv_udc, gadget);
+       u32 portsc;
+
+       /* Remote wakeup feature not enabled by host */
+       if (!udc->remote_wakeup)
+               return -ENOTSUPP;
+
+       portsc = readl(&udc->op_regs->portsc);
+       /* not suspended? */
+       if (!(portsc & PORTSCX_PORT_SUSPEND))
+               return 0;
+       /* trigger force resume */
+       portsc |= PORTSCX_PORT_FORCE_RESUME;
+       writel(portsc, &udc->op_regs->portsc[0]);
+       return 0;
+}
+
+static int mv_udc_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+       struct mv_udc *udc;
+       unsigned long flags;
+       int retval = 0;
+
+       udc = container_of(gadget, struct mv_udc, gadget);
+       spin_lock_irqsave(&udc->lock, flags);
+
+       udc->vbus_active = (is_active != 0);
+
+       dev_dbg(&udc->dev->dev, "%s: softconnect %d, vbus_active %d\n",
+               __func__, udc->softconnect, udc->vbus_active);
+
+       if (udc->driver && udc->softconnect && udc->vbus_active) {
+               retval = mv_udc_enable(udc);
+               if (retval == 0) {
+                       /* Clock is disabled, need re-init registers */
+                       udc_reset(udc);
+                       ep0_reset(udc);
+                       udc_start(udc);
+               }
+       } else if (udc->driver && udc->softconnect) {
+               if (!udc->active)
+                       goto out;
+
+               /* stop all the transfer in queue*/
+               stop_activity(udc, udc->driver);
+               udc_stop(udc);
+               mv_udc_disable(udc);
+       }
+
+out:
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return retval;
+}
+
+static int mv_udc_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct mv_udc *udc;
+       unsigned long flags;
+       int retval = 0;
+
+       udc = container_of(gadget, struct mv_udc, gadget);
+       spin_lock_irqsave(&udc->lock, flags);
+
+       udc->softconnect = (is_on != 0);
+
+       dev_dbg(&udc->dev->dev, "%s: softconnect %d, vbus_active %d\n",
+                       __func__, udc->softconnect, udc->vbus_active);
+
+       if (udc->driver && udc->softconnect && udc->vbus_active) {
+               retval = mv_udc_enable(udc);
+               if (retval == 0) {
+                       /* Clock is disabled, need re-init registers */
+                       udc_reset(udc);
+                       ep0_reset(udc);
+                       udc_start(udc);
+               }
+       } else if (udc->driver && udc->vbus_active) {
+               /* stop all the transfer in queue*/
+               stop_activity(udc, udc->driver);
+               udc_stop(udc);
+               mv_udc_disable(udc);
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return retval;
+}
+
+static int mv_udc_start(struct usb_gadget *, struct usb_gadget_driver *);
+static int mv_udc_stop(struct usb_gadget *, struct usb_gadget_driver *);
+/* device controller usb_gadget_ops structure */
+static const struct usb_gadget_ops mv_ops = {
+
+       /* returns the current frame number */
+       .get_frame      = mv_udc_get_frame,
+
+       /* tries to wake up the host connected to this gadget */
+       .wakeup         = mv_udc_wakeup,
+
+       /* notify controller that VBUS is powered or not */
+       .vbus_session   = mv_udc_vbus_session,
+
+       /* D+ pullup, software-controlled connect/disconnect to USB host */
+       .pullup         = mv_udc_pullup,
+       .udc_start      = mv_udc_start,
+       .udc_stop       = mv_udc_stop,
+};
+
+static int eps_init(struct mv_udc *udc)
+{
+       struct mv_ep    *ep;
+       char name[14];
+       int i;
+
+       /* initialize ep0 */
+       ep = &udc->eps[0];
+       ep->udc = udc;
+       strncpy(ep->name, "ep0", sizeof(ep->name));
+       ep->ep.name = ep->name;
+       ep->ep.ops = &mv_ep_ops;
+       ep->wedge = 0;
+       ep->stopped = 0;
+       usb_ep_set_maxpacket_limit(&ep->ep, EP0_MAX_PKT_SIZE);
+       ep->ep_num = 0;
+       ep->ep.desc = &mv_ep0_desc;
+       INIT_LIST_HEAD(&ep->queue);
+
+       ep->ep_type = USB_ENDPOINT_XFER_CONTROL;
+
+       /* initialize other endpoints */
+       for (i = 2; i < udc->max_eps * 2; i++) {
+               ep = &udc->eps[i];
+               if (i % 2) {
+                       snprintf(name, sizeof(name), "ep%din", i / 2);
+                       ep->direction = EP_DIR_IN;
+               } else {
+                       snprintf(name, sizeof(name), "ep%dout", i / 2);
+                       ep->direction = EP_DIR_OUT;
+               }
+               ep->udc = udc;
+               strncpy(ep->name, name, sizeof(ep->name));
+               ep->ep.name = ep->name;
+
+               ep->ep.ops = &mv_ep_ops;
+               ep->stopped = 0;
+               usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
+               ep->ep_num = i / 2;
+
+               INIT_LIST_HEAD(&ep->queue);
+               list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+
+               ep->dqh = &udc->ep_dqh[i];
+       }
+
+       return 0;
+}
+
+/* delete all endpoint requests, called with spinlock held */
+static void nuke(struct mv_ep *ep, int status)
+{
+       /* called with spinlock held */
+       ep->stopped = 1;
+
+       /* endpoint fifo flush */
+       mv_ep_fifo_flush(&ep->ep);
+
+       while (!list_empty(&ep->queue)) {
+               struct mv_req *req = NULL;
+               req = list_entry(ep->queue.next, struct mv_req, queue);
+               done(ep, req, status);
+       }
+}
+
+/* stop all USB activities */
+static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver)
+{
+       struct mv_ep    *ep;
+
+       nuke(&udc->eps[0], -ESHUTDOWN);
+
+       list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
+               nuke(ep, -ESHUTDOWN);
+       }
+
+       /* report disconnect; the driver is already quiesced */
+       if (driver) {
+               spin_unlock(&udc->lock);
+               driver->disconnect(&udc->gadget);
+               spin_lock(&udc->lock);
+       }
+}
+
+static int mv_udc_start(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct mv_udc *udc;
+       int retval = 0;
+       unsigned long flags;
+
+       udc = container_of(gadget, struct mv_udc, gadget);
+
+       if (udc->driver)
+               return -EBUSY;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /* hook up the driver ... */
+       driver->driver.bus = NULL;
+       udc->driver = driver;
+
+       udc->usb_state = USB_STATE_ATTACHED;
+       udc->ep0_state = WAIT_FOR_SETUP;
+       udc->ep0_dir = EP_DIR_OUT;
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       if (udc->transceiver) {
+               retval = otg_set_peripheral(udc->transceiver->otg,
+                                       &udc->gadget);
+               if (retval) {
+                       dev_err(&udc->dev->dev,
+                               "unable to register peripheral to otg\n");
+                       udc->driver = NULL;
+                       return retval;
+               }
+       }
+
+       /* pullup is always on */
+       mv_udc_pullup(&udc->gadget, 1);
+
+       /* When boot with cable attached, there will be no vbus irq occurred */
+       if (udc->qwork)
+               queue_work(udc->qwork, &udc->vbus_work);
+
+       return 0;
+}
+
+static int mv_udc_stop(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct mv_udc *udc;
+       unsigned long flags;
+
+       udc = container_of(gadget, struct mv_udc, gadget);
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       mv_udc_enable(udc);
+       udc_stop(udc);
+
+       /* stop all usb activities */
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       stop_activity(udc, driver);
+       mv_udc_disable(udc);
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       /* unbind gadget driver */
+       udc->driver = NULL;
+
+       return 0;
+}
+
+static void mv_set_ptc(struct mv_udc *udc, u32 mode)
+{
+       u32 portsc;
+
+       portsc = readl(&udc->op_regs->portsc[0]);
+       portsc |= mode << 16;
+       writel(portsc, &udc->op_regs->portsc[0]);
+}
+
+static void prime_status_complete(struct usb_ep *ep, struct usb_request *_req)
+{
+       struct mv_ep *mvep = container_of(ep, struct mv_ep, ep);
+       struct mv_req *req = container_of(_req, struct mv_req, req);
+       struct mv_udc *udc;
+       unsigned long flags;
+
+       udc = mvep->udc;
+
+       dev_info(&udc->dev->dev, "switch to test mode %d\n", req->test_mode);
+
+       spin_lock_irqsave(&udc->lock, flags);
+       if (req->test_mode) {
+               mv_set_ptc(udc, req->test_mode);
+               req->test_mode = 0;
+       }
+       spin_unlock_irqrestore(&udc->lock, flags);
+}
+
+static int
+udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
+{
+       int retval = 0;
+       struct mv_req *req;
+       struct mv_ep *ep;
+
+       ep = &udc->eps[0];
+       udc->ep0_dir = direction;
+       udc->ep0_state = WAIT_FOR_OUT_STATUS;
+
+       req = udc->status_req;
+
+       /* fill in the reqest structure */
+       if (empty == false) {
+               *((u16 *) req->req.buf) = cpu_to_le16(status);
+               req->req.length = 2;
+       } else
+               req->req.length = 0;
+
+       req->ep = ep;
+       req->req.status = -EINPROGRESS;
+       req->req.actual = 0;
+       if (udc->test_mode) {
+               req->req.complete = prime_status_complete;
+               req->test_mode = udc->test_mode;
+               udc->test_mode = 0;
+       } else
+               req->req.complete = NULL;
+       req->dtd_count = 0;
+
+       if (req->req.dma == DMA_ADDR_INVALID) {
+               req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
+                               req->req.buf, req->req.length,
+                               ep_dir(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+               req->mapped = 1;
+       }
+
+       /* prime the data phase */
+       if (!req_to_dtd(req)) {
+               retval = queue_dtd(ep, req);
+               if (retval) {
+                       dev_err(&udc->dev->dev,
+                               "Failed to queue dtd when prime status\n");
+                       goto out;
+               }
+       } else{ /* no mem */
+               retval = -ENOMEM;
+               dev_err(&udc->dev->dev,
+                       "Failed to dma_pool_alloc when prime status\n");
+               goto out;
+       }
+
+       list_add_tail(&req->queue, &ep->queue);
+
+       return 0;
+out:
+       usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
+
+       return retval;
+}
+
+static void mv_udc_testmode(struct mv_udc *udc, u16 index)
+{
+       if (index <= TEST_FORCE_EN) {
+               udc->test_mode = index;
+               if (udc_prime_status(udc, EP_DIR_IN, 0, true))
+                       ep0_stall(udc);
+       } else
+               dev_err(&udc->dev->dev,
+                       "This test mode(%d) is not supported\n", index);
+}
+
+static void ch9setaddress(struct mv_udc *udc, struct usb_ctrlrequest *setup)
+{
+       udc->dev_addr = (u8)setup->wValue;
+
+       /* update usb state */
+       udc->usb_state = USB_STATE_ADDRESS;
+
+       if (udc_prime_status(udc, EP_DIR_IN, 0, true))
+               ep0_stall(udc);
+}
+
+static void ch9getstatus(struct mv_udc *udc, u8 ep_num,
+       struct usb_ctrlrequest *setup)
+{
+       u16 status = 0;
+       int retval;
+
+       if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
+               != (USB_DIR_IN | USB_TYPE_STANDARD))
+               return;
+
+       if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
+               status = 1 << USB_DEVICE_SELF_POWERED;
+               status |= udc->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP;
+       } else if ((setup->bRequestType & USB_RECIP_MASK)
+                       == USB_RECIP_INTERFACE) {
+               /* get interface status */
+               status = 0;
+       } else if ((setup->bRequestType & USB_RECIP_MASK)
+                       == USB_RECIP_ENDPOINT) {
+               u8 ep_num, direction;
+
+               ep_num = setup->wIndex & USB_ENDPOINT_NUMBER_MASK;
+               direction = (setup->wIndex & USB_ENDPOINT_DIR_MASK)
+                               ? EP_DIR_IN : EP_DIR_OUT;
+               status = ep_is_stall(udc, ep_num, direction)
+                               << USB_ENDPOINT_HALT;
+       }
+
+       retval = udc_prime_status(udc, EP_DIR_IN, status, false);
+       if (retval)
+               ep0_stall(udc);
+       else
+               udc->ep0_state = DATA_STATE_XMIT;
+}
+
+static void ch9clearfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup)
+{
+       u8 ep_num;
+       u8 direction;
+       struct mv_ep *ep;
+
+       if ((setup->bRequestType & (USB_TYPE_MASK | USB_RECIP_MASK))
+               == ((USB_TYPE_STANDARD | USB_RECIP_DEVICE))) {
+               switch (setup->wValue) {
+               case USB_DEVICE_REMOTE_WAKEUP:
+                       udc->remote_wakeup = 0;
+                       break;
+               default:
+                       goto out;
+               }
+       } else if ((setup->bRequestType & (USB_TYPE_MASK | USB_RECIP_MASK))
+               == ((USB_TYPE_STANDARD | USB_RECIP_ENDPOINT))) {
+               switch (setup->wValue) {
+               case USB_ENDPOINT_HALT:
+                       ep_num = setup->wIndex & USB_ENDPOINT_NUMBER_MASK;
+                       direction = (setup->wIndex & USB_ENDPOINT_DIR_MASK)
+                               ? EP_DIR_IN : EP_DIR_OUT;
+                       if (setup->wValue != 0 || setup->wLength != 0
+                               || ep_num > udc->max_eps)
+                               goto out;
+                       ep = &udc->eps[ep_num * 2 + direction];
+                       if (ep->wedge == 1)
+                               break;
+                       spin_unlock(&udc->lock);
+                       ep_set_stall(udc, ep_num, direction, 0);
+                       spin_lock(&udc->lock);
+                       break;
+               default:
+                       goto out;
+               }
+       } else
+               goto out;
+
+       if (udc_prime_status(udc, EP_DIR_IN, 0, true))
+               ep0_stall(udc);
+out:
+       return;
+}
+
+static void ch9setfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup)
+{
+       u8 ep_num;
+       u8 direction;
+
+       if ((setup->bRequestType & (USB_TYPE_MASK | USB_RECIP_MASK))
+               == ((USB_TYPE_STANDARD | USB_RECIP_DEVICE))) {
+               switch (setup->wValue) {
+               case USB_DEVICE_REMOTE_WAKEUP:
+                       udc->remote_wakeup = 1;
+                       break;
+               case USB_DEVICE_TEST_MODE:
+                       if (setup->wIndex & 0xFF
+                               ||  udc->gadget.speed != USB_SPEED_HIGH)
+                               ep0_stall(udc);
+
+                       if (udc->usb_state != USB_STATE_CONFIGURED
+                               && udc->usb_state != USB_STATE_ADDRESS
+                               && udc->usb_state != USB_STATE_DEFAULT)
+                               ep0_stall(udc);
+
+                       mv_udc_testmode(udc, (setup->wIndex >> 8));
+                       goto out;
+               default:
+                       goto out;
+               }
+       } else if ((setup->bRequestType & (USB_TYPE_MASK | USB_RECIP_MASK))
+               == ((USB_TYPE_STANDARD | USB_RECIP_ENDPOINT))) {
+               switch (setup->wValue) {
+               case USB_ENDPOINT_HALT:
+                       ep_num = setup->wIndex & USB_ENDPOINT_NUMBER_MASK;
+                       direction = (setup->wIndex & USB_ENDPOINT_DIR_MASK)
+                               ? EP_DIR_IN : EP_DIR_OUT;
+                       if (setup->wValue != 0 || setup->wLength != 0
+                               || ep_num > udc->max_eps)
+                               goto out;
+                       spin_unlock(&udc->lock);
+                       ep_set_stall(udc, ep_num, direction, 1);
+                       spin_lock(&udc->lock);
+                       break;
+               default:
+                       goto out;
+               }
+       } else
+               goto out;
+
+       if (udc_prime_status(udc, EP_DIR_IN, 0, true))
+               ep0_stall(udc);
+out:
+       return;
+}
+
+static void handle_setup_packet(struct mv_udc *udc, u8 ep_num,
+       struct usb_ctrlrequest *setup)
+       __releases(&ep->udc->lock)
+       __acquires(&ep->udc->lock)
+{
+       bool delegate = false;
+
+       nuke(&udc->eps[ep_num * 2 + EP_DIR_OUT], -ESHUTDOWN);
+
+       dev_dbg(&udc->dev->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
+                       setup->bRequestType, setup->bRequest,
+                       setup->wValue, setup->wIndex, setup->wLength);
+       /* We process some stardard setup requests here */
+       if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+               switch (setup->bRequest) {
+               case USB_REQ_GET_STATUS:
+                       ch9getstatus(udc, ep_num, setup);
+                       break;
+
+               case USB_REQ_SET_ADDRESS:
+                       ch9setaddress(udc, setup);
+                       break;
+
+               case USB_REQ_CLEAR_FEATURE:
+                       ch9clearfeature(udc, setup);
+                       break;
+
+               case USB_REQ_SET_FEATURE:
+                       ch9setfeature(udc, setup);
+                       break;
+
+               default:
+                       delegate = true;
+               }
+       } else
+               delegate = true;
+
+       /* delegate USB standard requests to the gadget driver */
+       if (delegate == true) {
+               /* USB requests handled by gadget */
+               if (setup->wLength) {
+                       /* DATA phase from gadget, STATUS phase from udc */
+                       udc->ep0_dir = (setup->bRequestType & USB_DIR_IN)
+                                       ?  EP_DIR_IN : EP_DIR_OUT;
+                       spin_unlock(&udc->lock);
+                       if (udc->driver->setup(&udc->gadget,
+                               &udc->local_setup_buff) < 0)
+                               ep0_stall(udc);
+                       spin_lock(&udc->lock);
+                       udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
+                                       ?  DATA_STATE_XMIT : DATA_STATE_RECV;
+               } else {
+                       /* no DATA phase, IN STATUS phase from gadget */
+                       udc->ep0_dir = EP_DIR_IN;
+                       spin_unlock(&udc->lock);
+                       if (udc->driver->setup(&udc->gadget,
+                               &udc->local_setup_buff) < 0)
+                               ep0_stall(udc);
+                       spin_lock(&udc->lock);
+                       udc->ep0_state = WAIT_FOR_OUT_STATUS;
+               }
+       }
+}
+
+/* complete DATA or STATUS phase of ep0 prime status phase if needed */
+static void ep0_req_complete(struct mv_udc *udc,
+       struct mv_ep *ep0, struct mv_req *req)
+{
+       u32 new_addr;
+
+       if (udc->usb_state == USB_STATE_ADDRESS) {
+               /* set the new address */
+               new_addr = (u32)udc->dev_addr;
+               writel(new_addr << USB_DEVICE_ADDRESS_BIT_SHIFT,
+                       &udc->op_regs->deviceaddr);
+       }
+
+       done(ep0, req, 0);
+
+       switch (udc->ep0_state) {
+       case DATA_STATE_XMIT:
+               /* receive status phase */
+               if (udc_prime_status(udc, EP_DIR_OUT, 0, true))
+                       ep0_stall(udc);
+               break;
+       case DATA_STATE_RECV:
+               /* send status phase */
+               if (udc_prime_status(udc, EP_DIR_IN, 0 , true))
+                       ep0_stall(udc);
+               break;
+       case WAIT_FOR_OUT_STATUS:
+               udc->ep0_state = WAIT_FOR_SETUP;
+               break;
+       case WAIT_FOR_SETUP:
+               dev_err(&udc->dev->dev, "unexpect ep0 packets\n");
+               break;
+       default:
+               ep0_stall(udc);
+               break;
+       }
+}
+
+static void get_setup_data(struct mv_udc *udc, u8 ep_num, u8 *buffer_ptr)
+{
+       u32 temp;
+       struct mv_dqh *dqh;
+
+       dqh = &udc->ep_dqh[ep_num * 2 + EP_DIR_OUT];
+
+       /* Clear bit in ENDPTSETUPSTAT */
+       writel((1 << ep_num), &udc->op_regs->epsetupstat);
+
+       /* while a hazard exists when setup package arrives */
+       do {
+               /* Set Setup Tripwire */
+               temp = readl(&udc->op_regs->usbcmd);
+               writel(temp | USBCMD_SETUP_TRIPWIRE_SET, &udc->op_regs->usbcmd);
+
+               /* Copy the setup packet to local buffer */
+               memcpy(buffer_ptr, (u8 *) dqh->setup_buffer, 8);
+       } while (!(readl(&udc->op_regs->usbcmd) & USBCMD_SETUP_TRIPWIRE_SET));
+
+       /* Clear Setup Tripwire */
+       temp = readl(&udc->op_regs->usbcmd);
+       writel(temp & ~USBCMD_SETUP_TRIPWIRE_SET, &udc->op_regs->usbcmd);
+}
+
+static void irq_process_tr_complete(struct mv_udc *udc)
+{
+       u32 tmp, bit_pos;
+       int i, ep_num = 0, direction = 0;
+       struct mv_ep    *curr_ep;
+       struct mv_req *curr_req, *temp_req;
+       int status;
+
+       /*
+        * We use separate loops for ENDPTSETUPSTAT and ENDPTCOMPLETE
+        * because the setup packets are to be read ASAP
+        */
+
+       /* Process all Setup packet received interrupts */
+       tmp = readl(&udc->op_regs->epsetupstat);
+
+       if (tmp) {
+               for (i = 0; i < udc->max_eps; i++) {
+                       if (tmp & (1 << i)) {
+                               get_setup_data(udc, i,
+                                       (u8 *)(&udc->local_setup_buff));
+                               handle_setup_packet(udc, i,
+                                       &udc->local_setup_buff);
+                       }
+               }
+       }
+
+       /* Don't clear the endpoint setup status register here.
+        * It is cleared as a setup packet is read out of the buffer
+        */
+
+       /* Process non-setup transaction complete interrupts */
+       tmp = readl(&udc->op_regs->epcomplete);
+
+       if (!tmp)
+               return;
+
+       writel(tmp, &udc->op_regs->epcomplete);
+
+       for (i = 0; i < udc->max_eps * 2; i++) {
+               ep_num = i >> 1;
+               direction = i % 2;
+
+               bit_pos = 1 << (ep_num + 16 * direction);
+
+               if (!(bit_pos & tmp))
+                       continue;
+
+               if (i == 1)
+                       curr_ep = &udc->eps[0];
+               else
+                       curr_ep = &udc->eps[i];
+               /* process the req queue until an uncomplete request */
+               list_for_each_entry_safe(curr_req, temp_req,
+                       &curr_ep->queue, queue) {
+                       status = process_ep_req(udc, i, curr_req);
+                       if (status)
+                               break;
+
+                       /* write back status to req */
+                       curr_req->req.status = status;
+
+                       /* ep0 request completion */
+                       if (ep_num == 0) {
+                               ep0_req_complete(udc, curr_ep, curr_req);
+                               break;
+                       } else {
+                               done(curr_ep, curr_req, status);
+                       }
+               }
+       }
+}
+
+static void irq_process_reset(struct mv_udc *udc)
+{
+       u32 tmp;
+       unsigned int loops;
+
+       udc->ep0_dir = EP_DIR_OUT;
+       udc->ep0_state = WAIT_FOR_SETUP;
+       udc->remote_wakeup = 0;         /* default to 0 on reset */
+
+       /* The address bits are past bit 25-31. Set the address */
+       tmp = readl(&udc->op_regs->deviceaddr);
+       tmp &= ~(USB_DEVICE_ADDRESS_MASK);
+       writel(tmp, &udc->op_regs->deviceaddr);
+
+       /* Clear all the setup token semaphores */
+       tmp = readl(&udc->op_regs->epsetupstat);
+       writel(tmp, &udc->op_regs->epsetupstat);
+
+       /* Clear all the endpoint complete status bits */
+       tmp = readl(&udc->op_regs->epcomplete);
+       writel(tmp, &udc->op_regs->epcomplete);
+
+       /* wait until all endptprime bits cleared */
+       loops = LOOPS(PRIME_TIMEOUT);
+       while (readl(&udc->op_regs->epprime) & 0xFFFFFFFF) {
+               if (loops == 0) {
+                       dev_err(&udc->dev->dev,
+                               "Timeout for ENDPTPRIME = 0x%x\n",
+                               readl(&udc->op_regs->epprime));
+                       break;
+               }
+               loops--;
+               udelay(LOOPS_USEC);
+       }
+
+       /* Write 1s to the Flush register */
+       writel((u32)~0, &udc->op_regs->epflush);
+
+       if (readl(&udc->op_regs->portsc[0]) & PORTSCX_PORT_RESET) {
+               dev_info(&udc->dev->dev, "usb bus reset\n");
+               udc->usb_state = USB_STATE_DEFAULT;
+               /* reset all the queues, stop all USB activities */
+               stop_activity(udc, udc->driver);
+       } else {
+               dev_info(&udc->dev->dev, "USB reset portsc 0x%x\n",
+                       readl(&udc->op_regs->portsc));
+
+               /*
+                * re-initialize
+                * controller reset
+                */
+               udc_reset(udc);
+
+               /* reset all the queues, stop all USB activities */
+               stop_activity(udc, udc->driver);
+
+               /* reset ep0 dQH and endptctrl */
+               ep0_reset(udc);
+
+               /* enable interrupt and set controller to run state */
+               udc_start(udc);
+
+               udc->usb_state = USB_STATE_ATTACHED;
+       }
+}
+
+static void handle_bus_resume(struct mv_udc *udc)
+{
+       udc->usb_state = udc->resume_state;
+       udc->resume_state = 0;
+
+       /* report resume to the driver */
+       if (udc->driver) {
+               if (udc->driver->resume) {
+                       spin_unlock(&udc->lock);
+                       udc->driver->resume(&udc->gadget);
+                       spin_lock(&udc->lock);
+               }
+       }
+}
+
+static void irq_process_suspend(struct mv_udc *udc)
+{
+       udc->resume_state = udc->usb_state;
+       udc->usb_state = USB_STATE_SUSPENDED;
+
+       if (udc->driver->suspend) {
+               spin_unlock(&udc->lock);
+               udc->driver->suspend(&udc->gadget);
+               spin_lock(&udc->lock);
+       }
+}
+
+static void irq_process_port_change(struct mv_udc *udc)
+{
+       u32 portsc;
+
+       portsc = readl(&udc->op_regs->portsc[0]);
+       if (!(portsc & PORTSCX_PORT_RESET)) {
+               /* Get the speed */
+               u32 speed = portsc & PORTSCX_PORT_SPEED_MASK;
+               switch (speed) {
+               case PORTSCX_PORT_SPEED_HIGH:
+                       udc->gadget.speed = USB_SPEED_HIGH;
+                       break;
+               case PORTSCX_PORT_SPEED_FULL:
+                       udc->gadget.speed = USB_SPEED_FULL;
+                       break;
+               case PORTSCX_PORT_SPEED_LOW:
+                       udc->gadget.speed = USB_SPEED_LOW;
+                       break;
+               default:
+                       udc->gadget.speed = USB_SPEED_UNKNOWN;
+                       break;
+               }
+       }
+
+       if (portsc & PORTSCX_PORT_SUSPEND) {
+               udc->resume_state = udc->usb_state;
+               udc->usb_state = USB_STATE_SUSPENDED;
+               if (udc->driver->suspend) {
+                       spin_unlock(&udc->lock);
+                       udc->driver->suspend(&udc->gadget);
+                       spin_lock(&udc->lock);
+               }
+       }
+
+       if (!(portsc & PORTSCX_PORT_SUSPEND)
+               && udc->usb_state == USB_STATE_SUSPENDED) {
+               handle_bus_resume(udc);
+       }
+
+       if (!udc->resume_state)
+               udc->usb_state = USB_STATE_DEFAULT;
+}
+
+static void irq_process_error(struct mv_udc *udc)
+{
+       /* Increment the error count */
+       udc->errors++;
+}
+
+static irqreturn_t mv_udc_irq(int irq, void *dev)
+{
+       struct mv_udc *udc = (struct mv_udc *)dev;
+       u32 status, intr;
+
+       /* Disable ISR when stopped bit is set */
+       if (udc->stopped)
+               return IRQ_NONE;
+
+       spin_lock(&udc->lock);
+
+       status = readl(&udc->op_regs->usbsts);
+       intr = readl(&udc->op_regs->usbintr);
+       status &= intr;
+
+       if (status == 0) {
+               spin_unlock(&udc->lock);
+               return IRQ_NONE;
+       }
+
+       /* Clear all the interrupts occurred */
+       writel(status, &udc->op_regs->usbsts);
+
+       if (status & USBSTS_ERR)
+               irq_process_error(udc);
+
+       if (status & USBSTS_RESET)
+               irq_process_reset(udc);
+
+       if (status & USBSTS_PORT_CHANGE)
+               irq_process_port_change(udc);
+
+       if (status & USBSTS_INT)
+               irq_process_tr_complete(udc);
+
+       if (status & USBSTS_SUSPEND)
+               irq_process_suspend(udc);
+
+       spin_unlock(&udc->lock);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t mv_udc_vbus_irq(int irq, void *dev)
+{
+       struct mv_udc *udc = (struct mv_udc *)dev;
+
+       /* polling VBUS and init phy may cause too much time*/
+       if (udc->qwork)
+               queue_work(udc->qwork, &udc->vbus_work);
+
+       return IRQ_HANDLED;
+}
+
+static void mv_udc_vbus_work(struct work_struct *work)
+{
+       struct mv_udc *udc;
+       unsigned int vbus;
+
+       udc = container_of(work, struct mv_udc, vbus_work);
+       if (!udc->pdata->vbus)
+               return;
+
+       vbus = udc->pdata->vbus->poll();
+       dev_info(&udc->dev->dev, "vbus is %d\n", vbus);
+
+       if (vbus == VBUS_HIGH)
+               mv_udc_vbus_session(&udc->gadget, 1);
+       else if (vbus == VBUS_LOW)
+               mv_udc_vbus_session(&udc->gadget, 0);
+}
+
+/* release device structure */
+static void gadget_release(struct device *_dev)
+{
+       struct mv_udc *udc;
+
+       udc = dev_get_drvdata(_dev);
+
+       complete(udc->done);
+}
+
+static int mv_udc_remove(struct platform_device *pdev)
+{
+       struct mv_udc *udc;
+
+       udc = platform_get_drvdata(pdev);
+
+       usb_del_gadget_udc(&udc->gadget);
+
+       if (udc->qwork) {
+               flush_workqueue(udc->qwork);
+               destroy_workqueue(udc->qwork);
+       }
+
+       /* free memory allocated in probe */
+       if (udc->dtd_pool)
+               dma_pool_destroy(udc->dtd_pool);
+
+       if (udc->ep_dqh)
+               dma_free_coherent(&pdev->dev, udc->ep_dqh_size,
+                       udc->ep_dqh, udc->ep_dqh_dma);
+
+       mv_udc_disable(udc);
+
+       /* free dev, wait for the release() finished */
+       wait_for_completion(udc->done);
+
+       return 0;
+}
+
+static int mv_udc_probe(struct platform_device *pdev)
+{
+       struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
+       struct mv_udc *udc;
+       int retval = 0;
+       struct resource *r;
+       size_t size;
+
+       if (pdata == NULL) {
+               dev_err(&pdev->dev, "missing platform_data\n");
+               return -ENODEV;
+       }
+
+       udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL);
+       if (udc == NULL) {
+               dev_err(&pdev->dev, "failed to allocate memory for udc\n");
+               return -ENOMEM;
+       }
+
+       udc->done = &release_done;
+       udc->pdata = dev_get_platdata(&pdev->dev);
+       spin_lock_init(&udc->lock);
+
+       udc->dev = pdev;
+
+       if (pdata->mode == MV_USB_MODE_OTG) {
+               udc->transceiver = devm_usb_get_phy(&pdev->dev,
+                                       USB_PHY_TYPE_USB2);
+               if (IS_ERR(udc->transceiver)) {
+                       retval = PTR_ERR(udc->transceiver);
+
+                       if (retval == -ENXIO)
+                               return retval;
+
+                       udc->transceiver = NULL;
+                       return -EPROBE_DEFER;
+               }
+       }
+
+       /* udc only have one sysclk. */
+       udc->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(udc->clk))
+               return PTR_ERR(udc->clk);
+
+       r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
+       if (r == NULL) {
+               dev_err(&pdev->dev, "no I/O memory resource defined\n");
+               return -ENODEV;
+       }
+
+       udc->cap_regs = (struct mv_cap_regs __iomem *)
+               devm_ioremap(&pdev->dev, r->start, resource_size(r));
+       if (udc->cap_regs == NULL) {
+               dev_err(&pdev->dev, "failed to map I/O memory\n");
+               return -EBUSY;
+       }
+
+       r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "phyregs");
+       if (r == NULL) {
+               dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
+               return -ENODEV;
+       }
+
+       udc->phy_regs = ioremap(r->start, resource_size(r));
+       if (udc->phy_regs == NULL) {
+               dev_err(&pdev->dev, "failed to map phy I/O memory\n");
+               return -EBUSY;
+       }
+
+       /* we will acces controller register, so enable the clk */
+       retval = mv_udc_enable_internal(udc);
+       if (retval)
+               return retval;
+
+       udc->op_regs =
+               (struct mv_op_regs __iomem *)((unsigned long)udc->cap_regs
+               + (readl(&udc->cap_regs->caplength_hciversion)
+                       & CAPLENGTH_MASK));
+       udc->max_eps = readl(&udc->cap_regs->dccparams) & DCCPARAMS_DEN_MASK;
+
+       /*
+        * some platform will use usb to download image, it may not disconnect
+        * usb gadget before loading kernel. So first stop udc here.
+        */
+       udc_stop(udc);
+       writel(0xFFFFFFFF, &udc->op_regs->usbsts);
+
+       size = udc->max_eps * sizeof(struct mv_dqh) *2;
+       size = (size + DQH_ALIGNMENT - 1) & ~(DQH_ALIGNMENT - 1);
+       udc->ep_dqh = dma_alloc_coherent(&pdev->dev, size,
+                                       &udc->ep_dqh_dma, GFP_KERNEL);
+
+       if (udc->ep_dqh == NULL) {
+               dev_err(&pdev->dev, "allocate dQH memory failed\n");
+               retval = -ENOMEM;
+               goto err_disable_clock;
+       }
+       udc->ep_dqh_size = size;
+
+       /* create dTD dma_pool resource */
+       udc->dtd_pool = dma_pool_create("mv_dtd",
+                       &pdev->dev,
+                       sizeof(struct mv_dtd),
+                       DTD_ALIGNMENT,
+                       DMA_BOUNDARY);
+
+       if (!udc->dtd_pool) {
+               retval = -ENOMEM;
+               goto err_free_dma;
+       }
+
+       size = udc->max_eps * sizeof(struct mv_ep) *2;
+       udc->eps = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+       if (udc->eps == NULL) {
+               dev_err(&pdev->dev, "allocate ep memory failed\n");
+               retval = -ENOMEM;
+               goto err_destroy_dma;
+       }
+
+       /* initialize ep0 status request structure */
+       udc->status_req = devm_kzalloc(&pdev->dev, sizeof(struct mv_req),
+                                       GFP_KERNEL);
+       if (!udc->status_req) {
+               dev_err(&pdev->dev, "allocate status_req memory failed\n");
+               retval = -ENOMEM;
+               goto err_destroy_dma;
+       }
+       INIT_LIST_HEAD(&udc->status_req->queue);
+
+       /* allocate a small amount of memory to get valid address */
+       udc->status_req->req.buf = kzalloc(8, GFP_KERNEL);
+       udc->status_req->req.dma = DMA_ADDR_INVALID;
+
+       udc->resume_state = USB_STATE_NOTATTACHED;
+       udc->usb_state = USB_STATE_POWERED;
+       udc->ep0_dir = EP_DIR_OUT;
+       udc->remote_wakeup = 0;
+
+       r = platform_get_resource(udc->dev, IORESOURCE_IRQ, 0);
+       if (r == NULL) {
+               dev_err(&pdev->dev, "no IRQ resource defined\n");
+               retval = -ENODEV;
+               goto err_destroy_dma;
+       }
+       udc->irq = r->start;
+       if (devm_request_irq(&pdev->dev, udc->irq, mv_udc_irq,
+               IRQF_SHARED, driver_name, udc)) {
+               dev_err(&pdev->dev, "Request irq %d for UDC failed\n",
+                       udc->irq);
+               retval = -ENODEV;
+               goto err_destroy_dma;
+       }
+
+       /* initialize gadget structure */
+       udc->gadget.ops = &mv_ops;      /* usb_gadget_ops */
+       udc->gadget.ep0 = &udc->eps[0].ep;      /* gadget ep0 */
+       INIT_LIST_HEAD(&udc->gadget.ep_list);   /* ep_list */
+       udc->gadget.speed = USB_SPEED_UNKNOWN;  /* speed */
+       udc->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */
+
+       /* the "gadget" abstracts/virtualizes the controller */
+       udc->gadget.name = driver_name;         /* gadget name */
+
+       eps_init(udc);
+
+       /* VBUS detect: we can disable/enable clock on demand.*/
+       if (udc->transceiver)
+               udc->clock_gating = 1;
+       else if (pdata->vbus) {
+               udc->clock_gating = 1;
+               retval = devm_request_threaded_irq(&pdev->dev,
+                               pdata->vbus->irq, NULL,
+                               mv_udc_vbus_irq, IRQF_ONESHOT, "vbus", udc);
+               if (retval) {
+                       dev_info(&pdev->dev,
+                               "Can not request irq for VBUS, "
+                               "disable clock gating\n");
+                       udc->clock_gating = 0;
+               }
+
+               udc->qwork = create_singlethread_workqueue("mv_udc_queue");
+               if (!udc->qwork) {
+                       dev_err(&pdev->dev, "cannot create workqueue\n");
+                       retval = -ENOMEM;
+                       goto err_destroy_dma;
+               }
+
+               INIT_WORK(&udc->vbus_work, mv_udc_vbus_work);
+       }
+
+       /*
+        * When clock gating is supported, we can disable clk and phy.
+        * If not, it means that VBUS detection is not supported, we
+        * have to enable vbus active all the time to let controller work.
+        */
+       if (udc->clock_gating)
+               mv_udc_disable_internal(udc);
+       else
+               udc->vbus_active = 1;
+
+       retval = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
+                       gadget_release);
+       if (retval)
+               goto err_create_workqueue;
+
+       platform_set_drvdata(pdev, udc);
+       dev_info(&pdev->dev, "successful probe UDC device %s clock gating.\n",
+               udc->clock_gating ? "with" : "without");
+
+       return 0;
+
+err_create_workqueue:
+       destroy_workqueue(udc->qwork);
+err_destroy_dma:
+       dma_pool_destroy(udc->dtd_pool);
+err_free_dma:
+       dma_free_coherent(&pdev->dev, udc->ep_dqh_size,
+                       udc->ep_dqh, udc->ep_dqh_dma);
+err_disable_clock:
+       mv_udc_disable_internal(udc);
+
+       return retval;
+}
+
+#ifdef CONFIG_PM
+static int mv_udc_suspend(struct device *dev)
+{
+       struct mv_udc *udc;
+
+       udc = dev_get_drvdata(dev);
+
+       /* if OTG is enabled, the following will be done in OTG driver*/
+       if (udc->transceiver)
+               return 0;
+
+       if (udc->pdata->vbus && udc->pdata->vbus->poll)
+               if (udc->pdata->vbus->poll() == VBUS_HIGH) {
+                       dev_info(&udc->dev->dev, "USB cable is connected!\n");
+                       return -EAGAIN;
+               }
+
+       /*
+        * only cable is unplugged, udc can suspend.
+        * So do not care about clock_gating == 1.
+        */
+       if (!udc->clock_gating) {
+               udc_stop(udc);
+
+               spin_lock_irq(&udc->lock);
+               /* stop all usb activities */
+               stop_activity(udc, udc->driver);
+               spin_unlock_irq(&udc->lock);
+
+               mv_udc_disable_internal(udc);
+       }
+
+       return 0;
+}
+
+static int mv_udc_resume(struct device *dev)
+{
+       struct mv_udc *udc;
+       int retval;
+
+       udc = dev_get_drvdata(dev);
+
+       /* if OTG is enabled, the following will be done in OTG driver*/
+       if (udc->transceiver)
+               return 0;
+
+       if (!udc->clock_gating) {
+               retval = mv_udc_enable_internal(udc);
+               if (retval)
+                       return retval;
+
+               if (udc->driver && udc->softconnect) {
+                       udc_reset(udc);
+                       ep0_reset(udc);
+                       udc_start(udc);
+               }
+       }
+
+       return 0;
+}
+
+static const struct dev_pm_ops mv_udc_pm_ops = {
+       .suspend        = mv_udc_suspend,
+       .resume         = mv_udc_resume,
+};
+#endif
+
+static void mv_udc_shutdown(struct platform_device *pdev)
+{
+       struct mv_udc *udc;
+       u32 mode;
+
+       udc = platform_get_drvdata(pdev);
+       /* reset controller mode to IDLE */
+       mv_udc_enable(udc);
+       mode = readl(&udc->op_regs->usbmode);
+       mode &= ~3;
+       writel(mode, &udc->op_regs->usbmode);
+       mv_udc_disable(udc);
+}
+
+static struct platform_driver udc_driver = {
+       .probe          = mv_udc_probe,
+       .remove         = mv_udc_remove,
+       .shutdown       = mv_udc_shutdown,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "mv-udc",
+#ifdef CONFIG_PM
+               .pm     = &mv_udc_pm_ops,
+#endif
+       },
+};
+
+module_platform_driver(udc_driver);
+MODULE_ALIAS("platform:mv-udc");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>");
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c
new file mode 100644 (file)
index 0000000..059cfe5
--- /dev/null
@@ -0,0 +1,2710 @@
+/*
+ * Driver for PLX NET2272 USB device controller
+ *
+ * Copyright (C) 2005-2006 PLX Technology, Inc.
+ * Copyright (C) 2006-2011 Analog Devices, Inc.
+ *
+ * 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 <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/prefetch.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+
+#include "net2272.h"
+
+#define DRIVER_DESC "PLX NET2272 USB Peripheral Controller"
+
+static const char driver_name[] = "net2272";
+static const char driver_vers[] = "2006 October 17/mainline";
+static const char driver_desc[] = DRIVER_DESC;
+
+static const char ep0name[] = "ep0";
+static const char * const ep_name[] = {
+       ep0name,
+       "ep-a", "ep-b", "ep-c",
+};
+
+#ifdef CONFIG_USB_NET2272_DMA
+/*
+ * use_dma: the NET2272 can use an external DMA controller.
+ * Note that since there is no generic DMA api, some functions,
+ * notably request_dma, start_dma, and cancel_dma will need to be
+ * modified for your platform's particular dma controller.
+ *
+ * If use_dma is disabled, pio will be used instead.
+ */
+static bool use_dma = 0;
+module_param(use_dma, bool, 0644);
+
+/*
+ * dma_ep: selects the endpoint for use with dma (1=ep-a, 2=ep-b)
+ * The NET2272 can only use dma for a single endpoint at a time.
+ * At some point this could be modified to allow either endpoint
+ * to take control of dma as it becomes available.
+ *
+ * Note that DMA should not be used on OUT endpoints unless it can
+ * be guaranteed that no short packets will arrive on an IN endpoint
+ * while the DMA operation is pending.  Otherwise the OUT DMA will
+ * terminate prematurely (See NET2272 Errata 630-0213-0101)
+ */
+static ushort dma_ep = 1;
+module_param(dma_ep, ushort, 0644);
+
+/*
+ * dma_mode: net2272 dma mode setting (see LOCCTL1 definiton):
+ *     mode 0 == Slow DREQ mode
+ *     mode 1 == Fast DREQ mode
+ *     mode 2 == Burst mode
+ */
+static ushort dma_mode = 2;
+module_param(dma_mode, ushort, 0644);
+#else
+#define use_dma 0
+#define dma_ep 1
+#define dma_mode 2
+#endif
+
+/*
+ * fifo_mode: net2272 buffer configuration:
+ *      mode 0 == ep-{a,b,c} 512db each
+ *      mode 1 == ep-a 1k, ep-{b,c} 512db
+ *      mode 2 == ep-a 1k, ep-b 1k, ep-c 512db
+ *      mode 3 == ep-a 1k, ep-b disabled, ep-c 512db
+ */
+static ushort fifo_mode = 0;
+module_param(fifo_mode, ushort, 0644);
+
+/*
+ * enable_suspend: When enabled, the driver will respond to
+ * USB suspend requests by powering down the NET2272.  Otherwise,
+ * USB suspend requests will be ignored.  This is acceptible for
+ * self-powered devices.  For bus powered devices set this to 1.
+ */
+static ushort enable_suspend = 0;
+module_param(enable_suspend, ushort, 0644);
+
+static void assert_out_naking(struct net2272_ep *ep, const char *where)
+{
+       u8 tmp;
+
+#ifndef DEBUG
+       return;
+#endif
+
+       tmp = net2272_ep_read(ep, EP_STAT0);
+       if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) {
+               dev_dbg(ep->dev->dev, "%s %s %02x !NAK\n",
+                       ep->ep.name, where, tmp);
+               net2272_ep_write(ep, EP_RSPSET, 1 << ALT_NAK_OUT_PACKETS);
+       }
+}
+#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep, __func__)
+
+static void stop_out_naking(struct net2272_ep *ep)
+{
+       u8 tmp = net2272_ep_read(ep, EP_STAT0);
+
+       if ((tmp & (1 << NAK_OUT_PACKETS)) != 0)
+               net2272_ep_write(ep, EP_RSPCLR, 1 << ALT_NAK_OUT_PACKETS);
+}
+
+#define PIPEDIR(bAddress) (usb_pipein(bAddress) ? "in" : "out")
+
+static char *type_string(u8 bmAttributes)
+{
+       switch ((bmAttributes) & USB_ENDPOINT_XFERTYPE_MASK) {
+       case USB_ENDPOINT_XFER_BULK: return "bulk";
+       case USB_ENDPOINT_XFER_ISOC: return "iso";
+       case USB_ENDPOINT_XFER_INT:  return "intr";
+       default:                     return "control";
+       }
+}
+
+static char *buf_state_string(unsigned state)
+{
+       switch (state) {
+       case BUFF_FREE:  return "free";
+       case BUFF_VALID: return "valid";
+       case BUFF_LCL:   return "local";
+       case BUFF_USB:   return "usb";
+       default:         return "unknown";
+       }
+}
+
+static char *dma_mode_string(void)
+{
+       if (!use_dma)
+               return "PIO";
+       switch (dma_mode) {
+       case 0:  return "SLOW DREQ";
+       case 1:  return "FAST DREQ";
+       case 2:  return "BURST";
+       default: return "invalid";
+       }
+}
+
+static void net2272_dequeue_all(struct net2272_ep *);
+static int net2272_kick_dma(struct net2272_ep *, struct net2272_request *);
+static int net2272_fifo_status(struct usb_ep *);
+
+static struct usb_ep_ops net2272_ep_ops;
+
+/*---------------------------------------------------------------------------*/
+
+static int
+net2272_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+{
+       struct net2272 *dev;
+       struct net2272_ep *ep;
+       u32 max;
+       u8 tmp;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct net2272_ep, ep);
+       if (!_ep || !desc || ep->desc || _ep->name == ep0name
+                       || desc->bDescriptorType != USB_DT_ENDPOINT)
+               return -EINVAL;
+       dev = ep->dev;
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       max = usb_endpoint_maxp(desc) & 0x1fff;
+
+       spin_lock_irqsave(&dev->lock, flags);
+       _ep->maxpacket = max & 0x7fff;
+       ep->desc = desc;
+
+       /* net2272_ep_reset() has already been called */
+       ep->stopped = 0;
+       ep->wedged = 0;
+
+       /* set speed-dependent max packet */
+       net2272_ep_write(ep, EP_MAXPKT0, max & 0xff);
+       net2272_ep_write(ep, EP_MAXPKT1, (max & 0xff00) >> 8);
+
+       /* set type, direction, address; reset fifo counters */
+       net2272_ep_write(ep, EP_STAT1, 1 << BUFFER_FLUSH);
+       tmp = usb_endpoint_type(desc);
+       if (usb_endpoint_xfer_bulk(desc)) {
+               /* catch some particularly blatant driver bugs */
+               if ((dev->gadget.speed == USB_SPEED_HIGH && max != 512) ||
+                   (dev->gadget.speed == USB_SPEED_FULL && max > 64)) {
+                       spin_unlock_irqrestore(&dev->lock, flags);
+                       return -ERANGE;
+               }
+       }
+       ep->is_iso = usb_endpoint_xfer_isoc(desc) ? 1 : 0;
+       tmp <<= ENDPOINT_TYPE;
+       tmp |= ((desc->bEndpointAddress & 0x0f) << ENDPOINT_NUMBER);
+       tmp |= usb_endpoint_dir_in(desc) << ENDPOINT_DIRECTION;
+       tmp |= (1 << ENDPOINT_ENABLE);
+
+       /* for OUT transfers, block the rx fifo until a read is posted */
+       ep->is_in = usb_endpoint_dir_in(desc);
+       if (!ep->is_in)
+               net2272_ep_write(ep, EP_RSPSET, 1 << ALT_NAK_OUT_PACKETS);
+
+       net2272_ep_write(ep, EP_CFG, tmp);
+
+       /* enable irqs */
+       tmp = (1 << ep->num) | net2272_read(dev, IRQENB0);
+       net2272_write(dev, IRQENB0, tmp);
+
+       tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
+               | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
+               | net2272_ep_read(ep, EP_IRQENB);
+       net2272_ep_write(ep, EP_IRQENB, tmp);
+
+       tmp = desc->bEndpointAddress;
+       dev_dbg(dev->dev, "enabled %s (ep%d%s-%s) max %04x cfg %02x\n",
+               _ep->name, tmp & 0x0f, PIPEDIR(tmp),
+               type_string(desc->bmAttributes), max,
+               net2272_ep_read(ep, EP_CFG));
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+       return 0;
+}
+
+static void net2272_ep_reset(struct net2272_ep *ep)
+{
+       u8 tmp;
+
+       ep->desc = NULL;
+       INIT_LIST_HEAD(&ep->queue);
+
+       usb_ep_set_maxpacket_limit(&ep->ep, ~0);
+       ep->ep.ops = &net2272_ep_ops;
+
+       /* disable irqs, endpoint */
+       net2272_ep_write(ep, EP_IRQENB, 0);
+
+       /* init to our chosen defaults, notably so that we NAK OUT
+        * packets until the driver queues a read.
+        */
+       tmp = (1 << NAK_OUT_PACKETS_MODE) | (1 << ALT_NAK_OUT_PACKETS);
+       net2272_ep_write(ep, EP_RSPSET, tmp);
+
+       tmp = (1 << INTERRUPT_MODE) | (1 << HIDE_STATUS_PHASE);
+       if (ep->num != 0)
+               tmp |= (1 << ENDPOINT_TOGGLE) | (1 << ENDPOINT_HALT);
+
+       net2272_ep_write(ep, EP_RSPCLR, tmp);
+
+       /* scrub most status bits, and flush any fifo state */
+       net2272_ep_write(ep, EP_STAT0,
+                         (1 << DATA_IN_TOKEN_INTERRUPT)
+                       | (1 << DATA_OUT_TOKEN_INTERRUPT)
+                       | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
+                       | (1 << DATA_PACKET_RECEIVED_INTERRUPT)
+                       | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT));
+
+       net2272_ep_write(ep, EP_STAT1,
+                           (1 << TIMEOUT)
+                         | (1 << USB_OUT_ACK_SENT)
+                         | (1 << USB_OUT_NAK_SENT)
+                         | (1 << USB_IN_ACK_RCVD)
+                         | (1 << USB_IN_NAK_SENT)
+                         | (1 << USB_STALL_SENT)
+                         | (1 << LOCAL_OUT_ZLP)
+                         | (1 << BUFFER_FLUSH));
+
+       /* fifo size is handled seperately */
+}
+
+static int net2272_disable(struct usb_ep *_ep)
+{
+       struct net2272_ep *ep;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct net2272_ep, ep);
+       if (!_ep || !ep->desc || _ep->name == ep0name)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->dev->lock, flags);
+       net2272_dequeue_all(ep);
+       net2272_ep_reset(ep);
+
+       dev_vdbg(ep->dev->dev, "disabled %s\n", _ep->name);
+
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+       return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static struct usb_request *
+net2272_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct net2272_ep *ep;
+       struct net2272_request *req;
+
+       if (!_ep)
+               return NULL;
+       ep = container_of(_ep, struct net2272_ep, ep);
+
+       req = kzalloc(sizeof(*req), gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void
+net2272_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct net2272_ep *ep;
+       struct net2272_request *req;
+
+       ep = container_of(_ep, struct net2272_ep, ep);
+       if (!_ep || !_req)
+               return;
+
+       req = container_of(_req, struct net2272_request, req);
+       WARN_ON(!list_empty(&req->queue));
+       kfree(req);
+}
+
+static void
+net2272_done(struct net2272_ep *ep, struct net2272_request *req, int status)
+{
+       struct net2272 *dev;
+       unsigned stopped = ep->stopped;
+
+       if (ep->num == 0) {
+               if (ep->dev->protocol_stall) {
+                       ep->stopped = 1;
+                       set_halt(ep);
+               }
+               allow_status(ep);
+       }
+
+       list_del_init(&req->queue);
+
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       dev = ep->dev;
+       if (use_dma && ep->dma)
+               usb_gadget_unmap_request(&dev->gadget, &req->req,
+                               ep->is_in);
+
+       if (status && status != -ESHUTDOWN)
+               dev_vdbg(dev->dev, "complete %s req %p stat %d len %u/%u buf %p\n",
+                       ep->ep.name, &req->req, status,
+                       req->req.actual, req->req.length, req->req.buf);
+
+       /* don't modify queue heads during completion callback */
+       ep->stopped = 1;
+       spin_unlock(&dev->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&dev->lock);
+       ep->stopped = stopped;
+}
+
+static int
+net2272_write_packet(struct net2272_ep *ep, u8 *buf,
+       struct net2272_request *req, unsigned max)
+{
+       u16 __iomem *ep_data = net2272_reg_addr(ep->dev, EP_DATA);
+       u16 *bufp;
+       unsigned length, count;
+       u8 tmp;
+
+       length = min(req->req.length - req->req.actual, max);
+       req->req.actual += length;
+
+       dev_vdbg(ep->dev->dev, "write packet %s req %p max %u len %u avail %u\n",
+               ep->ep.name, req, max, length,
+               (net2272_ep_read(ep, EP_AVAIL1) << 8) | net2272_ep_read(ep, EP_AVAIL0));
+
+       count = length;
+       bufp = (u16 *)buf;
+
+       while (likely(count >= 2)) {
+               /* no byte-swap required; chip endian set during init */
+               writew(*bufp++, ep_data);
+               count -= 2;
+       }
+       buf = (u8 *)bufp;
+
+       /* write final byte by placing the NET2272 into 8-bit mode */
+       if (unlikely(count)) {
+               tmp = net2272_read(ep->dev, LOCCTL);
+               net2272_write(ep->dev, LOCCTL, tmp & ~(1 << DATA_WIDTH));
+               writeb(*buf, ep_data);
+               net2272_write(ep->dev, LOCCTL, tmp);
+       }
+       return length;
+}
+
+/* returns: 0: still running, 1: completed, negative: errno */
+static int
+net2272_write_fifo(struct net2272_ep *ep, struct net2272_request *req)
+{
+       u8 *buf;
+       unsigned count, max;
+       int status;
+
+       dev_vdbg(ep->dev->dev, "write_fifo %s actual %d len %d\n",
+               ep->ep.name, req->req.actual, req->req.length);
+
+       /*
+        * Keep loading the endpoint until the final packet is loaded,
+        * or the endpoint buffer is full.
+        */
+ top:
+       /*
+        * Clear interrupt status
+        *  - Packet Transmitted interrupt will become set again when the
+        *    host successfully takes another packet
+        */
+       net2272_ep_write(ep, EP_STAT0, (1 << DATA_PACKET_TRANSMITTED_INTERRUPT));
+       while (!(net2272_ep_read(ep, EP_STAT0) & (1 << BUFFER_FULL))) {
+               buf = req->req.buf + req->req.actual;
+               prefetch(buf);
+
+               /* force pagesel */
+               net2272_ep_read(ep, EP_STAT0);
+
+               max = (net2272_ep_read(ep, EP_AVAIL1) << 8) |
+                       (net2272_ep_read(ep, EP_AVAIL0));
+
+               if (max < ep->ep.maxpacket)
+                       max = (net2272_ep_read(ep, EP_AVAIL1) << 8)
+                               | (net2272_ep_read(ep, EP_AVAIL0));
+
+               count = net2272_write_packet(ep, buf, req, max);
+               /* see if we are done */
+               if (req->req.length == req->req.actual) {
+                       /* validate short or zlp packet */
+                       if (count < ep->ep.maxpacket)
+                               set_fifo_bytecount(ep, 0);
+                       net2272_done(ep, req, 0);
+
+                       if (!list_empty(&ep->queue)) {
+                               req = list_entry(ep->queue.next,
+                                               struct net2272_request,
+                                               queue);
+                               status = net2272_kick_dma(ep, req);
+
+                               if (status < 0)
+                                       if ((net2272_ep_read(ep, EP_STAT0)
+                                                       & (1 << BUFFER_EMPTY)))
+                                               goto top;
+                       }
+                       return 1;
+               }
+               net2272_ep_write(ep, EP_STAT0, (1 << DATA_PACKET_TRANSMITTED_INTERRUPT));
+       }
+       return 0;
+}
+
+static void
+net2272_out_flush(struct net2272_ep *ep)
+{
+       ASSERT_OUT_NAKING(ep);
+
+       net2272_ep_write(ep, EP_STAT0, (1 << DATA_OUT_TOKEN_INTERRUPT)
+                       | (1 << DATA_PACKET_RECEIVED_INTERRUPT));
+       net2272_ep_write(ep, EP_STAT1, 1 << BUFFER_FLUSH);
+}
+
+static int
+net2272_read_packet(struct net2272_ep *ep, u8 *buf,
+       struct net2272_request *req, unsigned avail)
+{
+       u16 __iomem *ep_data = net2272_reg_addr(ep->dev, EP_DATA);
+       unsigned is_short;
+       u16 *bufp;
+
+       req->req.actual += avail;
+
+       dev_vdbg(ep->dev->dev, "read packet %s req %p len %u avail %u\n",
+               ep->ep.name, req, avail,
+               (net2272_ep_read(ep, EP_AVAIL1) << 8) | net2272_ep_read(ep, EP_AVAIL0));
+
+       is_short = (avail < ep->ep.maxpacket);
+
+       if (unlikely(avail == 0)) {
+               /* remove any zlp from the buffer */
+               (void)readw(ep_data);
+               return is_short;
+       }
+
+       /* Ensure we get the final byte */
+       if (unlikely(avail % 2))
+               avail++;
+       bufp = (u16 *)buf;
+
+       do {
+               *bufp++ = readw(ep_data);
+               avail -= 2;
+       } while (avail);
+
+       /*
+        * To avoid false endpoint available race condition must read
+        * ep stat0 twice in the case of a short transfer
+        */
+       if (net2272_ep_read(ep, EP_STAT0) & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT))
+               net2272_ep_read(ep, EP_STAT0);
+
+       return is_short;
+}
+
+static int
+net2272_read_fifo(struct net2272_ep *ep, struct net2272_request *req)
+{
+       u8 *buf;
+       unsigned is_short;
+       int count;
+       int tmp;
+       int cleanup = 0;
+       int status = -1;
+
+       dev_vdbg(ep->dev->dev, "read_fifo %s actual %d len %d\n",
+               ep->ep.name, req->req.actual, req->req.length);
+
+ top:
+       do {
+               buf = req->req.buf + req->req.actual;
+               prefetchw(buf);
+
+               count = (net2272_ep_read(ep, EP_AVAIL1) << 8)
+                       | net2272_ep_read(ep, EP_AVAIL0);
+
+               net2272_ep_write(ep, EP_STAT0,
+                       (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT) |
+                       (1 << DATA_PACKET_RECEIVED_INTERRUPT));
+
+               tmp = req->req.length - req->req.actual;
+
+               if (count > tmp) {
+                       if ((tmp % ep->ep.maxpacket) != 0) {
+                               dev_err(ep->dev->dev,
+                                       "%s out fifo %d bytes, expected %d\n",
+                                       ep->ep.name, count, tmp);
+                               cleanup = 1;
+                       }
+                       count = (tmp > 0) ? tmp : 0;
+               }
+
+               is_short = net2272_read_packet(ep, buf, req, count);
+
+               /* completion */
+               if (unlikely(cleanup || is_short ||
+                               ((req->req.actual == req->req.length)
+                                && !req->req.zero))) {
+
+                       if (cleanup) {
+                               net2272_out_flush(ep);
+                               net2272_done(ep, req, -EOVERFLOW);
+                       } else
+                               net2272_done(ep, req, 0);
+
+                       /* re-initialize endpoint transfer registers
+                        * otherwise they may result in erroneous pre-validation
+                        * for subsequent control reads
+                        */
+                       if (unlikely(ep->num == 0)) {
+                               net2272_ep_write(ep, EP_TRANSFER2, 0);
+                               net2272_ep_write(ep, EP_TRANSFER1, 0);
+                               net2272_ep_write(ep, EP_TRANSFER0, 0);
+                       }
+
+                       if (!list_empty(&ep->queue)) {
+                               req = list_entry(ep->queue.next,
+                                       struct net2272_request, queue);
+                               status = net2272_kick_dma(ep, req);
+                               if ((status < 0) &&
+                                   !(net2272_ep_read(ep, EP_STAT0) & (1 << BUFFER_EMPTY)))
+                                       goto top;
+                       }
+                       return 1;
+               }
+       } while (!(net2272_ep_read(ep, EP_STAT0) & (1 << BUFFER_EMPTY)));
+
+       return 0;
+}
+
+static void
+net2272_pio_advance(struct net2272_ep *ep)
+{
+       struct net2272_request *req;
+
+       if (unlikely(list_empty(&ep->queue)))
+               return;
+
+       req = list_entry(ep->queue.next, struct net2272_request, queue);
+       (ep->is_in ? net2272_write_fifo : net2272_read_fifo)(ep, req);
+}
+
+/* returns 0 on success, else negative errno */
+static int
+net2272_request_dma(struct net2272 *dev, unsigned ep, u32 buf,
+       unsigned len, unsigned dir)
+{
+       dev_vdbg(dev->dev, "request_dma ep %d buf %08x len %d dir %d\n",
+               ep, buf, len, dir);
+
+       /* The NET2272 only supports a single dma channel */
+       if (dev->dma_busy)
+               return -EBUSY;
+       /*
+        * EP_TRANSFER (used to determine the number of bytes received
+        * in an OUT transfer) is 24 bits wide; don't ask for more than that.
+        */
+       if ((dir == 1) && (len > 0x1000000))
+               return -EINVAL;
+
+       dev->dma_busy = 1;
+
+       /* initialize platform's dma */
+#ifdef CONFIG_PCI
+       /* NET2272 addr, buffer addr, length, etc. */
+       switch (dev->dev_id) {
+       case PCI_DEVICE_ID_RDK1:
+               /* Setup PLX 9054 DMA mode */
+               writel((1 << LOCAL_BUS_WIDTH) |
+                       (1 << TA_READY_INPUT_ENABLE) |
+                       (0 << LOCAL_BURST_ENABLE) |
+                       (1 << DONE_INTERRUPT_ENABLE) |
+                       (1 << LOCAL_ADDRESSING_MODE) |
+                       (1 << DEMAND_MODE) |
+                       (1 << DMA_EOT_ENABLE) |
+                       (1 << FAST_SLOW_TERMINATE_MODE_SELECT) |
+                       (1 << DMA_CHANNEL_INTERRUPT_SELECT),
+                       dev->rdk1.plx9054_base_addr + DMAMODE0);
+
+               writel(0x100000, dev->rdk1.plx9054_base_addr + DMALADR0);
+               writel(buf, dev->rdk1.plx9054_base_addr + DMAPADR0);
+               writel(len, dev->rdk1.plx9054_base_addr + DMASIZ0);
+               writel((dir << DIRECTION_OF_TRANSFER) |
+                       (1 << INTERRUPT_AFTER_TERMINAL_COUNT),
+                       dev->rdk1.plx9054_base_addr + DMADPR0);
+               writel((1 << LOCAL_DMA_CHANNEL_0_INTERRUPT_ENABLE) |
+                       readl(dev->rdk1.plx9054_base_addr + INTCSR),
+                       dev->rdk1.plx9054_base_addr + INTCSR);
+
+               break;
+       }
+#endif
+
+       net2272_write(dev, DMAREQ,
+               (0 << DMA_BUFFER_VALID) |
+               (1 << DMA_REQUEST_ENABLE) |
+               (1 << DMA_CONTROL_DACK) |
+               (dev->dma_eot_polarity << EOT_POLARITY) |
+               (dev->dma_dack_polarity << DACK_POLARITY) |
+               (dev->dma_dreq_polarity << DREQ_POLARITY) |
+               ((ep >> 1) << DMA_ENDPOINT_SELECT));
+
+       (void) net2272_read(dev, SCRATCH);
+
+       return 0;
+}
+
+static void
+net2272_start_dma(struct net2272 *dev)
+{
+       /* start platform's dma controller */
+#ifdef CONFIG_PCI
+       switch (dev->dev_id) {
+       case PCI_DEVICE_ID_RDK1:
+               writeb((1 << CHANNEL_ENABLE) | (1 << CHANNEL_START),
+                       dev->rdk1.plx9054_base_addr + DMACSR0);
+               break;
+       }
+#endif
+}
+
+/* returns 0 on success, else negative errno */
+static int
+net2272_kick_dma(struct net2272_ep *ep, struct net2272_request *req)
+{
+       unsigned size;
+       u8 tmp;
+
+       if (!use_dma || (ep->num < 1) || (ep->num > 2) || !ep->dma)
+               return -EINVAL;
+
+       /* don't use dma for odd-length transfers
+        * otherwise, we'd need to deal with the last byte with pio
+        */
+       if (req->req.length & 1)
+               return -EINVAL;
+
+       dev_vdbg(ep->dev->dev, "kick_dma %s req %p dma %08llx\n",
+               ep->ep.name, req, (unsigned long long) req->req.dma);
+
+       net2272_ep_write(ep, EP_RSPSET, 1 << ALT_NAK_OUT_PACKETS);
+
+       /* The NET2272 can only use DMA on one endpoint at a time */
+       if (ep->dev->dma_busy)
+               return -EBUSY;
+
+       /* Make sure we only DMA an even number of bytes (we'll use
+        * pio to complete the transfer)
+        */
+       size = req->req.length;
+       size &= ~1;
+
+       /* device-to-host transfer */
+       if (ep->is_in) {
+               /* initialize platform's dma controller */
+               if (net2272_request_dma(ep->dev, ep->num, req->req.dma, size, 0))
+                       /* unable to obtain DMA channel; return error and use pio mode */
+                       return -EBUSY;
+               req->req.actual += size;
+
+       /* host-to-device transfer */
+       } else {
+               tmp = net2272_ep_read(ep, EP_STAT0);
+
+               /* initialize platform's dma controller */
+               if (net2272_request_dma(ep->dev, ep->num, req->req.dma, size, 1))
+                       /* unable to obtain DMA channel; return error and use pio mode */
+                       return -EBUSY;
+
+               if (!(tmp & (1 << BUFFER_EMPTY)))
+                       ep->not_empty = 1;
+               else
+                       ep->not_empty = 0;
+
+
+               /* allow the endpoint's buffer to fill */
+               net2272_ep_write(ep, EP_RSPCLR, 1 << ALT_NAK_OUT_PACKETS);
+
+               /* this transfer completed and data's already in the fifo
+                * return error so pio gets used.
+                */
+               if (tmp & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
+
+                       /* deassert dreq */
+                       net2272_write(ep->dev, DMAREQ,
+                               (0 << DMA_BUFFER_VALID) |
+                               (0 << DMA_REQUEST_ENABLE) |
+                               (1 << DMA_CONTROL_DACK) |
+                               (ep->dev->dma_eot_polarity << EOT_POLARITY) |
+                               (ep->dev->dma_dack_polarity << DACK_POLARITY) |
+                               (ep->dev->dma_dreq_polarity << DREQ_POLARITY) |
+                               ((ep->num >> 1) << DMA_ENDPOINT_SELECT));
+
+                       return -EBUSY;
+               }
+       }
+
+       /* Don't use per-packet interrupts: use dma interrupts only */
+       net2272_ep_write(ep, EP_IRQENB, 0);
+
+       net2272_start_dma(ep->dev);
+
+       return 0;
+}
+
+static void net2272_cancel_dma(struct net2272 *dev)
+{
+#ifdef CONFIG_PCI
+       switch (dev->dev_id) {
+       case PCI_DEVICE_ID_RDK1:
+               writeb(0, dev->rdk1.plx9054_base_addr + DMACSR0);
+               writeb(1 << CHANNEL_ABORT, dev->rdk1.plx9054_base_addr + DMACSR0);
+               while (!(readb(dev->rdk1.plx9054_base_addr + DMACSR0) &
+                        (1 << CHANNEL_DONE)))
+                       continue;       /* wait for dma to stabalize */
+
+               /* dma abort generates an interrupt */
+               writeb(1 << CHANNEL_CLEAR_INTERRUPT,
+                       dev->rdk1.plx9054_base_addr + DMACSR0);
+               break;
+       }
+#endif
+
+       dev->dma_busy = 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static int
+net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+       struct net2272_request *req;
+       struct net2272_ep *ep;
+       struct net2272 *dev;
+       unsigned long flags;
+       int status = -1;
+       u8 s;
+
+       req = container_of(_req, struct net2272_request, req);
+       if (!_req || !_req->complete || !_req->buf
+                       || !list_empty(&req->queue))
+               return -EINVAL;
+       ep = container_of(_ep, struct net2272_ep, ep);
+       if (!_ep || (!ep->desc && ep->num != 0))
+               return -EINVAL;
+       dev = ep->dev;
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       /* set up dma mapping in case the caller didn't */
+       if (use_dma && ep->dma) {
+               status = usb_gadget_map_request(&dev->gadget, _req,
+                               ep->is_in);
+               if (status)
+                       return status;
+       }
+
+       dev_vdbg(dev->dev, "%s queue req %p, len %d buf %p dma %08llx %s\n",
+               _ep->name, _req, _req->length, _req->buf,
+               (unsigned long long) _req->dma, _req->zero ? "zero" : "!zero");
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       /* kickstart this i/o queue? */
+       if (list_empty(&ep->queue) && !ep->stopped) {
+               /* maybe there's no control data, just status ack */
+               if (ep->num == 0 && _req->length == 0) {
+                       net2272_done(ep, req, 0);
+                       dev_vdbg(dev->dev, "%s status ack\n", ep->ep.name);
+                       goto done;
+               }
+
+               /* Return zlp, don't let it block subsequent packets */
+               s = net2272_ep_read(ep, EP_STAT0);
+               if (s & (1 << BUFFER_EMPTY)) {
+                       /* Buffer is empty check for a blocking zlp, handle it */
+                       if ((s & (1 << NAK_OUT_PACKETS)) &&
+                           net2272_ep_read(ep, EP_STAT1) & (1 << LOCAL_OUT_ZLP)) {
+                               dev_dbg(dev->dev, "WARNING: returning ZLP short packet termination!\n");
+                               /*
+                                * Request is going to terminate with a short packet ...
+                                * hope the client is ready for it!
+                                */
+                               status = net2272_read_fifo(ep, req);
+                               /* clear short packet naking */
+                               net2272_ep_write(ep, EP_STAT0, (1 << NAK_OUT_PACKETS));
+                               goto done;
+                       }
+               }
+
+               /* try dma first */
+               status = net2272_kick_dma(ep, req);
+
+               if (status < 0) {
+                       /* dma failed (most likely in use by another endpoint)
+                        * fallback to pio
+                        */
+                       status = 0;
+
+                       if (ep->is_in)
+                               status = net2272_write_fifo(ep, req);
+                       else {
+                               s = net2272_ep_read(ep, EP_STAT0);
+                               if ((s & (1 << BUFFER_EMPTY)) == 0)
+                                       status = net2272_read_fifo(ep, req);
+                       }
+
+                       if (unlikely(status != 0)) {
+                               if (status > 0)
+                                       status = 0;
+                               req = NULL;
+                       }
+               }
+       }
+       if (likely(req))
+               list_add_tail(&req->queue, &ep->queue);
+
+       if (likely(!list_empty(&ep->queue)))
+               net2272_ep_write(ep, EP_RSPCLR, 1 << ALT_NAK_OUT_PACKETS);
+ done:
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return 0;
+}
+
+/* dequeue ALL requests */
+static void
+net2272_dequeue_all(struct net2272_ep *ep)
+{
+       struct net2272_request *req;
+
+       /* called with spinlock held */
+       ep->stopped = 1;
+
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next,
+                               struct net2272_request,
+                               queue);
+               net2272_done(ep, req, -ESHUTDOWN);
+       }
+}
+
+/* dequeue JUST ONE request */
+static int
+net2272_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct net2272_ep *ep;
+       struct net2272_request *req;
+       unsigned long flags;
+       int stopped;
+
+       ep = container_of(_ep, struct net2272_ep, ep);
+       if (!_ep || (!ep->desc && ep->num != 0) || !_req)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->dev->lock, flags);
+       stopped = ep->stopped;
+       ep->stopped = 1;
+
+       /* make sure it's still queued on this endpoint */
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req) {
+               spin_unlock_irqrestore(&ep->dev->lock, flags);
+               return -EINVAL;
+       }
+
+       /* queue head may be partially complete */
+       if (ep->queue.next == &req->queue) {
+               dev_dbg(ep->dev->dev, "unlink (%s) pio\n", _ep->name);
+               net2272_done(ep, req, -ECONNRESET);
+       }
+       req = NULL;
+       ep->stopped = stopped;
+
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+       return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static int
+net2272_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
+{
+       struct net2272_ep *ep;
+       unsigned long flags;
+       int ret = 0;
+
+       ep = container_of(_ep, struct net2272_ep, ep);
+       if (!_ep || (!ep->desc && ep->num != 0))
+               return -EINVAL;
+       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+       if (ep->desc /* not ep0 */ && usb_endpoint_xfer_isoc(ep->desc))
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->dev->lock, flags);
+       if (!list_empty(&ep->queue))
+               ret = -EAGAIN;
+       else if (ep->is_in && value && net2272_fifo_status(_ep) != 0)
+               ret = -EAGAIN;
+       else {
+               dev_vdbg(ep->dev->dev, "%s %s %s\n", _ep->name,
+                       value ? "set" : "clear",
+                       wedged ? "wedge" : "halt");
+               /* set/clear */
+               if (value) {
+                       if (ep->num == 0)
+                               ep->dev->protocol_stall = 1;
+                       else
+                               set_halt(ep);
+                       if (wedged)
+                               ep->wedged = 1;
+               } else {
+                       clear_halt(ep);
+                       ep->wedged = 0;
+               }
+       }
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+
+       return ret;
+}
+
+static int
+net2272_set_halt(struct usb_ep *_ep, int value)
+{
+       return net2272_set_halt_and_wedge(_ep, value, 0);
+}
+
+static int
+net2272_set_wedge(struct usb_ep *_ep)
+{
+       if (!_ep || _ep->name == ep0name)
+               return -EINVAL;
+       return net2272_set_halt_and_wedge(_ep, 1, 1);
+}
+
+static int
+net2272_fifo_status(struct usb_ep *_ep)
+{
+       struct net2272_ep *ep;
+       u16 avail;
+
+       ep = container_of(_ep, struct net2272_ep, ep);
+       if (!_ep || (!ep->desc && ep->num != 0))
+               return -ENODEV;
+       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       avail = net2272_ep_read(ep, EP_AVAIL1) << 8;
+       avail |= net2272_ep_read(ep, EP_AVAIL0);
+       if (avail > ep->fifo_size)
+               return -EOVERFLOW;
+       if (ep->is_in)
+               avail = ep->fifo_size - avail;
+       return avail;
+}
+
+static void
+net2272_fifo_flush(struct usb_ep *_ep)
+{
+       struct net2272_ep *ep;
+
+       ep = container_of(_ep, struct net2272_ep, ep);
+       if (!_ep || (!ep->desc && ep->num != 0))
+               return;
+       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return;
+
+       net2272_ep_write(ep, EP_STAT1, 1 << BUFFER_FLUSH);
+}
+
+static struct usb_ep_ops net2272_ep_ops = {
+       .enable        = net2272_enable,
+       .disable       = net2272_disable,
+
+       .alloc_request = net2272_alloc_request,
+       .free_request  = net2272_free_request,
+
+       .queue         = net2272_queue,
+       .dequeue       = net2272_dequeue,
+
+       .set_halt      = net2272_set_halt,
+       .set_wedge     = net2272_set_wedge,
+       .fifo_status   = net2272_fifo_status,
+       .fifo_flush    = net2272_fifo_flush,
+};
+
+/*---------------------------------------------------------------------------*/
+
+static int
+net2272_get_frame(struct usb_gadget *_gadget)
+{
+       struct net2272 *dev;
+       unsigned long flags;
+       u16 ret;
+
+       if (!_gadget)
+               return -ENODEV;
+       dev = container_of(_gadget, struct net2272, gadget);
+       spin_lock_irqsave(&dev->lock, flags);
+
+       ret = net2272_read(dev, FRAME1) << 8;
+       ret |= net2272_read(dev, FRAME0);
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+       return ret;
+}
+
+static int
+net2272_wakeup(struct usb_gadget *_gadget)
+{
+       struct net2272 *dev;
+       u8 tmp;
+       unsigned long flags;
+
+       if (!_gadget)
+               return 0;
+       dev = container_of(_gadget, struct net2272, gadget);
+
+       spin_lock_irqsave(&dev->lock, flags);
+       tmp = net2272_read(dev, USBCTL0);
+       if (tmp & (1 << IO_WAKEUP_ENABLE))
+               net2272_write(dev, USBCTL1, (1 << GENERATE_RESUME));
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return 0;
+}
+
+static int
+net2272_set_selfpowered(struct usb_gadget *_gadget, int value)
+{
+       struct net2272 *dev;
+
+       if (!_gadget)
+               return -ENODEV;
+       dev = container_of(_gadget, struct net2272, gadget);
+
+       dev->is_selfpowered = value;
+
+       return 0;
+}
+
+static int
+net2272_pullup(struct usb_gadget *_gadget, int is_on)
+{
+       struct net2272 *dev;
+       u8 tmp;
+       unsigned long flags;
+
+       if (!_gadget)
+               return -ENODEV;
+       dev = container_of(_gadget, struct net2272, gadget);
+
+       spin_lock_irqsave(&dev->lock, flags);
+       tmp = net2272_read(dev, USBCTL0);
+       dev->softconnect = (is_on != 0);
+       if (is_on)
+               tmp |= (1 << USB_DETECT_ENABLE);
+       else
+               tmp &= ~(1 << USB_DETECT_ENABLE);
+       net2272_write(dev, USBCTL0, tmp);
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return 0;
+}
+
+static int net2272_start(struct usb_gadget *_gadget,
+               struct usb_gadget_driver *driver);
+static int net2272_stop(struct usb_gadget *_gadget,
+               struct usb_gadget_driver *driver);
+
+static const struct usb_gadget_ops net2272_ops = {
+       .get_frame      = net2272_get_frame,
+       .wakeup         = net2272_wakeup,
+       .set_selfpowered = net2272_set_selfpowered,
+       .pullup         = net2272_pullup,
+       .udc_start      = net2272_start,
+       .udc_stop       = net2272_stop,
+};
+
+/*---------------------------------------------------------------------------*/
+
+static ssize_t
+registers_show(struct device *_dev, struct device_attribute *attr, char *buf)
+{
+       struct net2272 *dev;
+       char *next;
+       unsigned size, t;
+       unsigned long flags;
+       u8 t1, t2;
+       int i;
+       const char *s;
+
+       dev = dev_get_drvdata(_dev);
+       next = buf;
+       size = PAGE_SIZE;
+       spin_lock_irqsave(&dev->lock, flags);
+
+       if (dev->driver)
+               s = dev->driver->driver.name;
+       else
+               s = "(none)";
+
+       /* Main Control Registers */
+       t = scnprintf(next, size, "%s version %s,"
+               "chiprev %02x, locctl %02x\n"
+               "irqenb0 %02x irqenb1 %02x "
+               "irqstat0 %02x irqstat1 %02x\n",
+               driver_name, driver_vers, dev->chiprev,
+               net2272_read(dev, LOCCTL),
+               net2272_read(dev, IRQENB0),
+               net2272_read(dev, IRQENB1),
+               net2272_read(dev, IRQSTAT0),
+               net2272_read(dev, IRQSTAT1));
+       size -= t;
+       next += t;
+
+       /* DMA */
+       t1 = net2272_read(dev, DMAREQ);
+       t = scnprintf(next, size, "\ndmareq %02x: %s %s%s%s%s\n",
+               t1, ep_name[(t1 & 0x01) + 1],
+               t1 & (1 << DMA_CONTROL_DACK) ? "dack " : "",
+               t1 & (1 << DMA_REQUEST_ENABLE) ? "reqenb " : "",
+               t1 & (1 << DMA_REQUEST) ? "req " : "",
+               t1 & (1 << DMA_BUFFER_VALID) ? "valid " : "");
+       size -= t;
+       next += t;
+
+       /* USB Control Registers */
+       t1 = net2272_read(dev, USBCTL1);
+       if (t1 & (1 << VBUS_PIN)) {
+               if (t1 & (1 << USB_HIGH_SPEED))
+                       s = "high speed";
+               else if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+                       s = "powered";
+               else
+                       s = "full speed";
+       } else
+               s = "not attached";
+       t = scnprintf(next, size,
+               "usbctl0 %02x usbctl1 %02x addr 0x%02x (%s)\n",
+               net2272_read(dev, USBCTL0), t1,
+               net2272_read(dev, OURADDR), s);
+       size -= t;
+       next += t;
+
+       /* Endpoint Registers */
+       for (i = 0; i < 4; ++i) {
+               struct net2272_ep *ep;
+
+               ep = &dev->ep[i];
+               if (i && !ep->desc)
+                       continue;
+
+               t1 = net2272_ep_read(ep, EP_CFG);
+               t2 = net2272_ep_read(ep, EP_RSPSET);
+               t = scnprintf(next, size,
+                       "\n%s\tcfg %02x rsp (%02x) %s%s%s%s%s%s%s%s"
+                       "irqenb %02x\n",
+                       ep->ep.name, t1, t2,
+                       (t2 & (1 << ALT_NAK_OUT_PACKETS)) ? "NAK " : "",
+                       (t2 & (1 << HIDE_STATUS_PHASE)) ? "hide " : "",
+                       (t2 & (1 << AUTOVALIDATE)) ? "auto " : "",
+                       (t2 & (1 << INTERRUPT_MODE)) ? "interrupt " : "",
+                       (t2 & (1 << CONTROL_STATUS_PHASE_HANDSHAKE)) ? "status " : "",
+                       (t2 & (1 << NAK_OUT_PACKETS_MODE)) ? "NAKmode " : "",
+                       (t2 & (1 << ENDPOINT_TOGGLE)) ? "DATA1 " : "DATA0 ",
+                       (t2 & (1 << ENDPOINT_HALT)) ? "HALT " : "",
+                       net2272_ep_read(ep, EP_IRQENB));
+               size -= t;
+               next += t;
+
+               t = scnprintf(next, size,
+                       "\tstat0 %02x stat1 %02x avail %04x "
+                       "(ep%d%s-%s)%s\n",
+                       net2272_ep_read(ep, EP_STAT0),
+                       net2272_ep_read(ep, EP_STAT1),
+                       (net2272_ep_read(ep, EP_AVAIL1) << 8) | net2272_ep_read(ep, EP_AVAIL0),
+                       t1 & 0x0f,
+                       ep->is_in ? "in" : "out",
+                       type_string(t1 >> 5),
+                       ep->stopped ? "*" : "");
+               size -= t;
+               next += t;
+
+               t = scnprintf(next, size,
+                       "\tep_transfer %06x\n",
+                       ((net2272_ep_read(ep, EP_TRANSFER2) & 0xff) << 16) |
+                       ((net2272_ep_read(ep, EP_TRANSFER1) & 0xff) << 8) |
+                       ((net2272_ep_read(ep, EP_TRANSFER0) & 0xff)));
+               size -= t;
+               next += t;
+
+               t1 = net2272_ep_read(ep, EP_BUFF_STATES) & 0x03;
+               t2 = (net2272_ep_read(ep, EP_BUFF_STATES) >> 2) & 0x03;
+               t = scnprintf(next, size,
+                       "\tbuf-a %s buf-b %s\n",
+                       buf_state_string(t1),
+                       buf_state_string(t2));
+               size -= t;
+               next += t;
+       }
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return PAGE_SIZE - size;
+}
+static DEVICE_ATTR_RO(registers);
+
+/*---------------------------------------------------------------------------*/
+
+static void
+net2272_set_fifo_mode(struct net2272 *dev, int mode)
+{
+       u8 tmp;
+
+       tmp = net2272_read(dev, LOCCTL) & 0x3f;
+       tmp |= (mode << 6);
+       net2272_write(dev, LOCCTL, tmp);
+
+       INIT_LIST_HEAD(&dev->gadget.ep_list);
+
+       /* always ep-a, ep-c ... maybe not ep-b */
+       list_add_tail(&dev->ep[1].ep.ep_list, &dev->gadget.ep_list);
+
+       switch (mode) {
+       case 0:
+               list_add_tail(&dev->ep[2].ep.ep_list, &dev->gadget.ep_list);
+               dev->ep[1].fifo_size = dev->ep[2].fifo_size = 512;
+               break;
+       case 1:
+               list_add_tail(&dev->ep[2].ep.ep_list, &dev->gadget.ep_list);
+               dev->ep[1].fifo_size = 1024;
+               dev->ep[2].fifo_size = 512;
+               break;
+       case 2:
+               list_add_tail(&dev->ep[2].ep.ep_list, &dev->gadget.ep_list);
+               dev->ep[1].fifo_size = dev->ep[2].fifo_size = 1024;
+               break;
+       case 3:
+               dev->ep[1].fifo_size = 1024;
+               break;
+       }
+
+       /* ep-c is always 2 512 byte buffers */
+       list_add_tail(&dev->ep[3].ep.ep_list, &dev->gadget.ep_list);
+       dev->ep[3].fifo_size = 512;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void
+net2272_usb_reset(struct net2272 *dev)
+{
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+       net2272_cancel_dma(dev);
+
+       net2272_write(dev, IRQENB0, 0);
+       net2272_write(dev, IRQENB1, 0);
+
+       /* clear irq state */
+       net2272_write(dev, IRQSTAT0, 0xff);
+       net2272_write(dev, IRQSTAT1, ~(1 << SUSPEND_REQUEST_INTERRUPT));
+
+       net2272_write(dev, DMAREQ,
+               (0 << DMA_BUFFER_VALID) |
+               (0 << DMA_REQUEST_ENABLE) |
+               (1 << DMA_CONTROL_DACK) |
+               (dev->dma_eot_polarity << EOT_POLARITY) |
+               (dev->dma_dack_polarity << DACK_POLARITY) |
+               (dev->dma_dreq_polarity << DREQ_POLARITY) |
+               ((dma_ep >> 1) << DMA_ENDPOINT_SELECT));
+
+       net2272_cancel_dma(dev);
+       net2272_set_fifo_mode(dev, (fifo_mode <= 3) ? fifo_mode : 0);
+
+       /* Set the NET2272 ep fifo data width to 16-bit mode and for correct byte swapping
+        * note that the higher level gadget drivers are expected to convert data to little endian.
+        * Enable byte swap for your local bus/cpu if needed by setting BYTE_SWAP in LOCCTL here
+        */
+       net2272_write(dev, LOCCTL, net2272_read(dev, LOCCTL) | (1 << DATA_WIDTH));
+       net2272_write(dev, LOCCTL1, (dma_mode << DMA_MODE));
+}
+
+static void
+net2272_usb_reinit(struct net2272 *dev)
+{
+       int i;
+
+       /* basic endpoint init */
+       for (i = 0; i < 4; ++i) {
+               struct net2272_ep *ep = &dev->ep[i];
+
+               ep->ep.name = ep_name[i];
+               ep->dev = dev;
+               ep->num = i;
+               ep->not_empty = 0;
+
+               if (use_dma && ep->num == dma_ep)
+                       ep->dma = 1;
+
+               if (i > 0 && i <= 3)
+                       ep->fifo_size = 512;
+               else
+                       ep->fifo_size = 64;
+               net2272_ep_reset(ep);
+       }
+       usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 64);
+
+       dev->gadget.ep0 = &dev->ep[0].ep;
+       dev->ep[0].stopped = 0;
+       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+}
+
+static void
+net2272_ep0_start(struct net2272 *dev)
+{
+       struct net2272_ep *ep0 = &dev->ep[0];
+
+       net2272_ep_write(ep0, EP_RSPSET,
+               (1 << NAK_OUT_PACKETS_MODE) |
+               (1 << ALT_NAK_OUT_PACKETS));
+       net2272_ep_write(ep0, EP_RSPCLR,
+               (1 << HIDE_STATUS_PHASE) |
+               (1 << CONTROL_STATUS_PHASE_HANDSHAKE));
+       net2272_write(dev, USBCTL0,
+               (dev->softconnect << USB_DETECT_ENABLE) |
+               (1 << USB_ROOT_PORT_WAKEUP_ENABLE) |
+               (1 << IO_WAKEUP_ENABLE));
+       net2272_write(dev, IRQENB0,
+               (1 << SETUP_PACKET_INTERRUPT_ENABLE) |
+               (1 << ENDPOINT_0_INTERRUPT_ENABLE) |
+               (1 << DMA_DONE_INTERRUPT_ENABLE));
+       net2272_write(dev, IRQENB1,
+               (1 << VBUS_INTERRUPT_ENABLE) |
+               (1 << ROOT_PORT_RESET_INTERRUPT_ENABLE) |
+               (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE));
+}
+
+/* when a driver is successfully registered, it will receive
+ * control requests including set_configuration(), which enables
+ * non-control requests.  then usb traffic follows until a
+ * disconnect is reported.  then a host may connect again, or
+ * the driver might get unbound.
+ */
+static int net2272_start(struct usb_gadget *_gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct net2272 *dev;
+       unsigned i;
+
+       if (!driver || !driver->setup ||
+           driver->max_speed != USB_SPEED_HIGH)
+               return -EINVAL;
+
+       dev = container_of(_gadget, struct net2272, gadget);
+
+       for (i = 0; i < 4; ++i)
+               dev->ep[i].irqs = 0;
+       /* hook up the driver ... */
+       dev->softconnect = 1;
+       driver->driver.bus = NULL;
+       dev->driver = driver;
+
+       /* ... then enable host detection and ep0; and we're ready
+        * for set_configuration as well as eventual disconnect.
+        */
+       net2272_ep0_start(dev);
+
+       dev_dbg(dev->dev, "%s ready\n", driver->driver.name);
+
+       return 0;
+}
+
+static void
+stop_activity(struct net2272 *dev, struct usb_gadget_driver *driver)
+{
+       int i;
+
+       /* don't disconnect if it's not connected */
+       if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+               driver = NULL;
+
+       /* stop hardware; prevent new request submissions;
+        * and kill any outstanding requests.
+        */
+       net2272_usb_reset(dev);
+       for (i = 0; i < 4; ++i)
+               net2272_dequeue_all(&dev->ep[i]);
+
+       /* report disconnect; the driver is already quiesced */
+       if (driver) {
+               spin_unlock(&dev->lock);
+               driver->disconnect(&dev->gadget);
+               spin_lock(&dev->lock);
+       }
+
+       net2272_usb_reinit(dev);
+}
+
+static int net2272_stop(struct usb_gadget *_gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct net2272 *dev;
+       unsigned long flags;
+
+       dev = container_of(_gadget, struct net2272, gadget);
+
+       spin_lock_irqsave(&dev->lock, flags);
+       stop_activity(dev, driver);
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       dev->driver = NULL;
+
+       dev_dbg(dev->dev, "unregistered driver '%s'\n", driver->driver.name);
+       return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+/* handle ep-a/ep-b dma completions */
+static void
+net2272_handle_dma(struct net2272_ep *ep)
+{
+       struct net2272_request *req;
+       unsigned len;
+       int status;
+
+       if (!list_empty(&ep->queue))
+               req = list_entry(ep->queue.next,
+                               struct net2272_request, queue);
+       else
+               req = NULL;
+
+       dev_vdbg(ep->dev->dev, "handle_dma %s req %p\n", ep->ep.name, req);
+
+       /* Ensure DREQ is de-asserted */
+       net2272_write(ep->dev, DMAREQ,
+               (0 << DMA_BUFFER_VALID)
+             | (0 << DMA_REQUEST_ENABLE)
+             | (1 << DMA_CONTROL_DACK)
+             | (ep->dev->dma_eot_polarity << EOT_POLARITY)
+             | (ep->dev->dma_dack_polarity << DACK_POLARITY)
+             | (ep->dev->dma_dreq_polarity << DREQ_POLARITY)
+             | (ep->dma << DMA_ENDPOINT_SELECT));
+
+       ep->dev->dma_busy = 0;
+
+       net2272_ep_write(ep, EP_IRQENB,
+                 (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
+               | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
+               | net2272_ep_read(ep, EP_IRQENB));
+
+       /* device-to-host transfer completed */
+       if (ep->is_in) {
+               /* validate a short packet or zlp if necessary */
+               if ((req->req.length % ep->ep.maxpacket != 0) ||
+                               req->req.zero)
+                       set_fifo_bytecount(ep, 0);
+
+               net2272_done(ep, req, 0);
+               if (!list_empty(&ep->queue)) {
+                       req = list_entry(ep->queue.next,
+                                       struct net2272_request, queue);
+                       status = net2272_kick_dma(ep, req);
+                       if (status < 0)
+                               net2272_pio_advance(ep);
+               }
+
+       /* host-to-device transfer completed */
+       } else {
+               /* terminated with a short packet? */
+               if (net2272_read(ep->dev, IRQSTAT0) &
+                               (1 << DMA_DONE_INTERRUPT)) {
+                       /* abort system dma */
+                       net2272_cancel_dma(ep->dev);
+               }
+
+               /* EP_TRANSFER will contain the number of bytes
+                * actually received.
+                * NOTE: There is no overflow detection on EP_TRANSFER:
+                * We can't deal with transfers larger than 2^24 bytes!
+                */
+               len = (net2272_ep_read(ep, EP_TRANSFER2) << 16)
+                       | (net2272_ep_read(ep, EP_TRANSFER1) << 8)
+                       | (net2272_ep_read(ep, EP_TRANSFER0));
+
+               if (ep->not_empty)
+                       len += 4;
+
+               req->req.actual += len;
+
+               /* get any remaining data */
+               net2272_pio_advance(ep);
+       }
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void
+net2272_handle_ep(struct net2272_ep *ep)
+{
+       struct net2272_request *req;
+       u8 stat0, stat1;
+
+       if (!list_empty(&ep->queue))
+               req = list_entry(ep->queue.next,
+                       struct net2272_request, queue);
+       else
+               req = NULL;
+
+       /* ack all, and handle what we care about */
+       stat0 = net2272_ep_read(ep, EP_STAT0);
+       stat1 = net2272_ep_read(ep, EP_STAT1);
+       ep->irqs++;
+
+       dev_vdbg(ep->dev->dev, "%s ack ep_stat0 %02x, ep_stat1 %02x, req %p\n",
+               ep->ep.name, stat0, stat1, req ? &req->req : NULL);
+
+       net2272_ep_write(ep, EP_STAT0, stat0 &
+               ~((1 << NAK_OUT_PACKETS)
+               | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)));
+       net2272_ep_write(ep, EP_STAT1, stat1);
+
+       /* data packet(s) received (in the fifo, OUT)
+        * direction must be validated, otherwise control read status phase
+        * could be interpreted as a valid packet
+        */
+       if (!ep->is_in && (stat0 & (1 << DATA_PACKET_RECEIVED_INTERRUPT)))
+               net2272_pio_advance(ep);
+       /* data packet(s) transmitted (IN) */
+       else if (stat0 & (1 << DATA_PACKET_TRANSMITTED_INTERRUPT))
+               net2272_pio_advance(ep);
+}
+
+static struct net2272_ep *
+net2272_get_ep_by_addr(struct net2272 *dev, u16 wIndex)
+{
+       struct net2272_ep *ep;
+
+       if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
+               return &dev->ep[0];
+
+       list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
+               u8 bEndpointAddress;
+
+               if (!ep->desc)
+                       continue;
+               bEndpointAddress = ep->desc->bEndpointAddress;
+               if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
+                       continue;
+               if ((wIndex & 0x0f) == (bEndpointAddress & 0x0f))
+                       return ep;
+       }
+       return NULL;
+}
+
+/*
+ * USB Test Packet:
+ * JKJKJKJK * 9
+ * JJKKJJKK * 8
+ * JJJJKKKK * 8
+ * JJJJJJJKKKKKKK * 8
+ * JJJJJJJK * 8
+ * {JKKKKKKK * 10}, JK
+ */
+static const u8 net2272_test_packet[] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+       0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+       0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD,
+       0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFD, 0x7E
+};
+
+static void
+net2272_set_test_mode(struct net2272 *dev, int mode)
+{
+       int i;
+
+       /* Disable all net2272 interrupts:
+        * Nothing but a power cycle should stop the test.
+        */
+       net2272_write(dev, IRQENB0, 0x00);
+       net2272_write(dev, IRQENB1, 0x00);
+
+       /* Force tranceiver to high-speed */
+       net2272_write(dev, XCVRDIAG, 1 << FORCE_HIGH_SPEED);
+
+       net2272_write(dev, PAGESEL, 0);
+       net2272_write(dev, EP_STAT0, 1 << DATA_PACKET_TRANSMITTED_INTERRUPT);
+       net2272_write(dev, EP_RSPCLR,
+                         (1 << CONTROL_STATUS_PHASE_HANDSHAKE)
+                       | (1 << HIDE_STATUS_PHASE));
+       net2272_write(dev, EP_CFG, 1 << ENDPOINT_DIRECTION);
+       net2272_write(dev, EP_STAT1, 1 << BUFFER_FLUSH);
+
+       /* wait for status phase to complete */
+       while (!(net2272_read(dev, EP_STAT0) &
+                               (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)))
+               ;
+
+       /* Enable test mode */
+       net2272_write(dev, USBTEST, mode);
+
+       /* load test packet */
+       if (mode == TEST_PACKET) {
+               /* switch to 8 bit mode */
+               net2272_write(dev, LOCCTL, net2272_read(dev, LOCCTL) &
+                               ~(1 << DATA_WIDTH));
+
+               for (i = 0; i < sizeof(net2272_test_packet); ++i)
+                       net2272_write(dev, EP_DATA, net2272_test_packet[i]);
+
+               /* Validate test packet */
+               net2272_write(dev, EP_TRANSFER0, 0);
+       }
+}
+
+static void
+net2272_handle_stat0_irqs(struct net2272 *dev, u8 stat)
+{
+       struct net2272_ep *ep;
+       u8 num, scratch;
+
+       /* starting a control request? */
+       if (unlikely(stat & (1 << SETUP_PACKET_INTERRUPT))) {
+               union {
+                       u8 raw[8];
+                       struct usb_ctrlrequest  r;
+               } u;
+               int tmp = 0;
+               struct net2272_request *req;
+
+               if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
+                       if (net2272_read(dev, USBCTL1) & (1 << USB_HIGH_SPEED))
+                               dev->gadget.speed = USB_SPEED_HIGH;
+                       else
+                               dev->gadget.speed = USB_SPEED_FULL;
+                       dev_dbg(dev->dev, "%s\n",
+                               usb_speed_string(dev->gadget.speed));
+               }
+
+               ep = &dev->ep[0];
+               ep->irqs++;
+
+               /* make sure any leftover interrupt state is cleared */
+               stat &= ~(1 << ENDPOINT_0_INTERRUPT);
+               while (!list_empty(&ep->queue)) {
+                       req = list_entry(ep->queue.next,
+                               struct net2272_request, queue);
+                       net2272_done(ep, req,
+                               (req->req.actual == req->req.length) ? 0 : -EPROTO);
+               }
+               ep->stopped = 0;
+               dev->protocol_stall = 0;
+               net2272_ep_write(ep, EP_STAT0,
+                           (1 << DATA_IN_TOKEN_INTERRUPT)
+                         | (1 << DATA_OUT_TOKEN_INTERRUPT)
+                         | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
+                         | (1 << DATA_PACKET_RECEIVED_INTERRUPT)
+                         | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT));
+               net2272_ep_write(ep, EP_STAT1,
+                           (1 << TIMEOUT)
+                         | (1 << USB_OUT_ACK_SENT)
+                         | (1 << USB_OUT_NAK_SENT)
+                         | (1 << USB_IN_ACK_RCVD)
+                         | (1 << USB_IN_NAK_SENT)
+                         | (1 << USB_STALL_SENT)
+                         | (1 << LOCAL_OUT_ZLP));
+
+               /*
+                * Ensure Control Read pre-validation setting is beyond maximum size
+                *  - Control Writes can leave non-zero values in EP_TRANSFER. If
+                *    an EP0 transfer following the Control Write is a Control Read,
+                *    the NET2272 sees the non-zero EP_TRANSFER as an unexpected
+                *    pre-validation count.
+                *  - Setting EP_TRANSFER beyond the maximum EP0 transfer size ensures
+                *    the pre-validation count cannot cause an unexpected validatation
+                */
+               net2272_write(dev, PAGESEL, 0);
+               net2272_write(dev, EP_TRANSFER2, 0xff);
+               net2272_write(dev, EP_TRANSFER1, 0xff);
+               net2272_write(dev, EP_TRANSFER0, 0xff);
+
+               u.raw[0] = net2272_read(dev, SETUP0);
+               u.raw[1] = net2272_read(dev, SETUP1);
+               u.raw[2] = net2272_read(dev, SETUP2);
+               u.raw[3] = net2272_read(dev, SETUP3);
+               u.raw[4] = net2272_read(dev, SETUP4);
+               u.raw[5] = net2272_read(dev, SETUP5);
+               u.raw[6] = net2272_read(dev, SETUP6);
+               u.raw[7] = net2272_read(dev, SETUP7);
+               /*
+                * If you have a big endian cpu make sure le16_to_cpus
+                * performs the proper byte swapping here...
+                */
+               le16_to_cpus(&u.r.wValue);
+               le16_to_cpus(&u.r.wIndex);
+               le16_to_cpus(&u.r.wLength);
+
+               /* ack the irq */
+               net2272_write(dev, IRQSTAT0, 1 << SETUP_PACKET_INTERRUPT);
+               stat ^= (1 << SETUP_PACKET_INTERRUPT);
+
+               /* watch control traffic at the token level, and force
+                * synchronization before letting the status phase happen.
+                */
+               ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0;
+               if (ep->is_in) {
+                       scratch = (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
+                               | (1 << DATA_OUT_TOKEN_INTERRUPT_ENABLE)
+                               | (1 << DATA_IN_TOKEN_INTERRUPT_ENABLE);
+                       stop_out_naking(ep);
+               } else
+                       scratch = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
+                               | (1 << DATA_OUT_TOKEN_INTERRUPT_ENABLE)
+                               | (1 << DATA_IN_TOKEN_INTERRUPT_ENABLE);
+               net2272_ep_write(ep, EP_IRQENB, scratch);
+
+               if ((u.r.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD)
+                       goto delegate;
+               switch (u.r.bRequest) {
+               case USB_REQ_GET_STATUS: {
+                       struct net2272_ep *e;
+                       u16 status = 0;
+
+                       switch (u.r.bRequestType & USB_RECIP_MASK) {
+                       case USB_RECIP_ENDPOINT:
+                               e = net2272_get_ep_by_addr(dev, u.r.wIndex);
+                               if (!e || u.r.wLength > 2)
+                                       goto do_stall;
+                               if (net2272_ep_read(e, EP_RSPSET) & (1 << ENDPOINT_HALT))
+                                       status = __constant_cpu_to_le16(1);
+                               else
+                                       status = __constant_cpu_to_le16(0);
+
+                               /* don't bother with a request object! */
+                               net2272_ep_write(&dev->ep[0], EP_IRQENB, 0);
+                               writew(status, net2272_reg_addr(dev, EP_DATA));
+                               set_fifo_bytecount(&dev->ep[0], 0);
+                               allow_status(ep);
+                               dev_vdbg(dev->dev, "%s stat %02x\n",
+                                       ep->ep.name, status);
+                               goto next_endpoints;
+                       case USB_RECIP_DEVICE:
+                               if (u.r.wLength > 2)
+                                       goto do_stall;
+                               if (dev->is_selfpowered)
+                                       status = (1 << USB_DEVICE_SELF_POWERED);
+
+                               /* don't bother with a request object! */
+                               net2272_ep_write(&dev->ep[0], EP_IRQENB, 0);
+                               writew(status, net2272_reg_addr(dev, EP_DATA));
+                               set_fifo_bytecount(&dev->ep[0], 0);
+                               allow_status(ep);
+                               dev_vdbg(dev->dev, "device stat %02x\n", status);
+                               goto next_endpoints;
+                       case USB_RECIP_INTERFACE:
+                               if (u.r.wLength > 2)
+                                       goto do_stall;
+
+                               /* don't bother with a request object! */
+                               net2272_ep_write(&dev->ep[0], EP_IRQENB, 0);
+                               writew(status, net2272_reg_addr(dev, EP_DATA));
+                               set_fifo_bytecount(&dev->ep[0], 0);
+                               allow_status(ep);
+                               dev_vdbg(dev->dev, "interface status %02x\n", status);
+                               goto next_endpoints;
+                       }
+
+                       break;
+               }
+               case USB_REQ_CLEAR_FEATURE: {
+                       struct net2272_ep *e;
+
+                       if (u.r.bRequestType != USB_RECIP_ENDPOINT)
+                               goto delegate;
+                       if (u.r.wValue != USB_ENDPOINT_HALT ||
+                           u.r.wLength != 0)
+                               goto do_stall;
+                       e = net2272_get_ep_by_addr(dev, u.r.wIndex);
+                       if (!e)
+                               goto do_stall;
+                       if (e->wedged) {
+                               dev_vdbg(dev->dev, "%s wedged, halt not cleared\n",
+                                       ep->ep.name);
+                       } else {
+                               dev_vdbg(dev->dev, "%s clear halt\n", ep->ep.name);
+                               clear_halt(e);
+                       }
+                       allow_status(ep);
+                       goto next_endpoints;
+               }
+               case USB_REQ_SET_FEATURE: {
+                       struct net2272_ep *e;
+
+                       if (u.r.bRequestType == USB_RECIP_DEVICE) {
+                               if (u.r.wIndex != NORMAL_OPERATION)
+                                       net2272_set_test_mode(dev, (u.r.wIndex >> 8));
+                               allow_status(ep);
+                               dev_vdbg(dev->dev, "test mode: %d\n", u.r.wIndex);
+                               goto next_endpoints;
+                       } else if (u.r.bRequestType != USB_RECIP_ENDPOINT)
+                               goto delegate;
+                       if (u.r.wValue != USB_ENDPOINT_HALT ||
+                           u.r.wLength != 0)
+                               goto do_stall;
+                       e = net2272_get_ep_by_addr(dev, u.r.wIndex);
+                       if (!e)
+                               goto do_stall;
+                       set_halt(e);
+                       allow_status(ep);
+                       dev_vdbg(dev->dev, "%s set halt\n", ep->ep.name);
+                       goto next_endpoints;
+               }
+               case USB_REQ_SET_ADDRESS: {
+                       net2272_write(dev, OURADDR, u.r.wValue & 0xff);
+                       allow_status(ep);
+                       break;
+               }
+               default:
+ delegate:
+                       dev_vdbg(dev->dev, "setup %02x.%02x v%04x i%04x "
+                               "ep_cfg %08x\n",
+                               u.r.bRequestType, u.r.bRequest,
+                               u.r.wValue, u.r.wIndex,
+                               net2272_ep_read(ep, EP_CFG));
+                       spin_unlock(&dev->lock);
+                       tmp = dev->driver->setup(&dev->gadget, &u.r);
+                       spin_lock(&dev->lock);
+               }
+
+               /* stall ep0 on error */
+               if (tmp < 0) {
+ do_stall:
+                       dev_vdbg(dev->dev, "req %02x.%02x protocol STALL; stat %d\n",
+                               u.r.bRequestType, u.r.bRequest, tmp);
+                       dev->protocol_stall = 1;
+               }
+       /* endpoint dma irq? */
+       } else if (stat & (1 << DMA_DONE_INTERRUPT)) {
+               net2272_cancel_dma(dev);
+               net2272_write(dev, IRQSTAT0, 1 << DMA_DONE_INTERRUPT);
+               stat &= ~(1 << DMA_DONE_INTERRUPT);
+               num = (net2272_read(dev, DMAREQ) & (1 << DMA_ENDPOINT_SELECT))
+                       ? 2 : 1;
+
+               ep = &dev->ep[num];
+               net2272_handle_dma(ep);
+       }
+
+ next_endpoints:
+       /* endpoint data irq? */
+       scratch = stat & 0x0f;
+       stat &= ~0x0f;
+       for (num = 0; scratch; num++) {
+               u8 t;
+
+               /* does this endpoint's FIFO and queue need tending? */
+               t = 1 << num;
+               if ((scratch & t) == 0)
+                       continue;
+               scratch ^= t;
+
+               ep = &dev->ep[num];
+               net2272_handle_ep(ep);
+       }
+
+       /* some interrupts we can just ignore */
+       stat &= ~(1 << SOF_INTERRUPT);
+
+       if (stat)
+               dev_dbg(dev->dev, "unhandled irqstat0 %02x\n", stat);
+}
+
+static void
+net2272_handle_stat1_irqs(struct net2272 *dev, u8 stat)
+{
+       u8 tmp, mask;
+
+       /* after disconnect there's nothing else to do! */
+       tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT);
+       mask = (1 << USB_HIGH_SPEED) | (1 << USB_FULL_SPEED);
+
+       if (stat & tmp) {
+               net2272_write(dev, IRQSTAT1, tmp);
+               if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) &&
+                               ((net2272_read(dev, USBCTL1) & mask) == 0))
+                       || ((net2272_read(dev, USBCTL1) & (1 << VBUS_PIN))
+                               == 0))
+                               && (dev->gadget.speed != USB_SPEED_UNKNOWN)) {
+                       dev_dbg(dev->dev, "disconnect %s\n",
+                               dev->driver->driver.name);
+                       stop_activity(dev, dev->driver);
+                       net2272_ep0_start(dev);
+                       return;
+               }
+               stat &= ~tmp;
+
+               if (!stat)
+                       return;
+       }
+
+       tmp = (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT);
+       if (stat & tmp) {
+               net2272_write(dev, IRQSTAT1, tmp);
+               if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
+                       if (dev->driver->suspend)
+                               dev->driver->suspend(&dev->gadget);
+                       if (!enable_suspend) {
+                               stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
+                               dev_dbg(dev->dev, "Suspend disabled, ignoring\n");
+                       }
+               } else {
+                       if (dev->driver->resume)
+                               dev->driver->resume(&dev->gadget);
+               }
+               stat &= ~tmp;
+       }
+
+       /* clear any other status/irqs */
+       if (stat)
+               net2272_write(dev, IRQSTAT1, stat);
+
+       /* some status we can just ignore */
+       stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
+                       | (1 << SUSPEND_REQUEST_INTERRUPT)
+                       | (1 << RESUME_INTERRUPT));
+       if (!stat)
+               return;
+       else
+               dev_dbg(dev->dev, "unhandled irqstat1 %02x\n", stat);
+}
+
+static irqreturn_t net2272_irq(int irq, void *_dev)
+{
+       struct net2272 *dev = _dev;
+#if defined(PLX_PCI_RDK) || defined(PLX_PCI_RDK2)
+       u32 intcsr;
+#endif
+#if defined(PLX_PCI_RDK)
+       u8 dmareq;
+#endif
+       spin_lock(&dev->lock);
+#if defined(PLX_PCI_RDK)
+       intcsr = readl(dev->rdk1.plx9054_base_addr + INTCSR);
+
+       if ((intcsr & LOCAL_INTERRUPT_TEST) == LOCAL_INTERRUPT_TEST) {
+               writel(intcsr & ~(1 << PCI_INTERRUPT_ENABLE),
+                               dev->rdk1.plx9054_base_addr + INTCSR);
+               net2272_handle_stat1_irqs(dev, net2272_read(dev, IRQSTAT1));
+               net2272_handle_stat0_irqs(dev, net2272_read(dev, IRQSTAT0));
+               intcsr = readl(dev->rdk1.plx9054_base_addr + INTCSR);
+               writel(intcsr | (1 << PCI_INTERRUPT_ENABLE),
+                       dev->rdk1.plx9054_base_addr + INTCSR);
+       }
+       if ((intcsr & DMA_CHANNEL_0_TEST) == DMA_CHANNEL_0_TEST) {
+               writeb((1 << CHANNEL_CLEAR_INTERRUPT | (0 << CHANNEL_ENABLE)),
+                               dev->rdk1.plx9054_base_addr + DMACSR0);
+
+               dmareq = net2272_read(dev, DMAREQ);
+               if (dmareq & 0x01)
+                       net2272_handle_dma(&dev->ep[2]);
+               else
+                       net2272_handle_dma(&dev->ep[1]);
+       }
+#endif
+#if defined(PLX_PCI_RDK2)
+       /* see if PCI int for us by checking irqstat */
+       intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT);
+       if (!intcsr & (1 << NET2272_PCI_IRQ)) {
+               spin_unlock(&dev->lock);
+               return IRQ_NONE;
+       }
+       /* check dma interrupts */
+#endif
+       /* Platform/devcice interrupt handler */
+#if !defined(PLX_PCI_RDK)
+       net2272_handle_stat1_irqs(dev, net2272_read(dev, IRQSTAT1));
+       net2272_handle_stat0_irqs(dev, net2272_read(dev, IRQSTAT0));
+#endif
+       spin_unlock(&dev->lock);
+
+       return IRQ_HANDLED;
+}
+
+static int net2272_present(struct net2272 *dev)
+{
+       /*
+        * Quick test to see if CPU can communicate properly with the NET2272.
+        * Verifies connection using writes and reads to write/read and
+        * read-only registers.
+        *
+        * This routine is strongly recommended especially during early bring-up
+        * of new hardware, however for designs that do not apply Power On System
+        * Tests (POST) it may discarded (or perhaps minimized).
+        */
+       unsigned int ii;
+       u8 val, refval;
+
+       /* Verify NET2272 write/read SCRATCH register can write and read */
+       refval = net2272_read(dev, SCRATCH);
+       for (ii = 0; ii < 0x100; ii += 7) {
+               net2272_write(dev, SCRATCH, ii);
+               val = net2272_read(dev, SCRATCH);
+               if (val != ii) {
+                       dev_dbg(dev->dev,
+                               "%s: write/read SCRATCH register test failed: "
+                               "wrote:0x%2.2x, read:0x%2.2x\n",
+                               __func__, ii, val);
+                       return -EINVAL;
+               }
+       }
+       /* To be nice, we write the original SCRATCH value back: */
+       net2272_write(dev, SCRATCH, refval);
+
+       /* Verify NET2272 CHIPREV register is read-only: */
+       refval = net2272_read(dev, CHIPREV_2272);
+       for (ii = 0; ii < 0x100; ii += 7) {
+               net2272_write(dev, CHIPREV_2272, ii);
+               val = net2272_read(dev, CHIPREV_2272);
+               if (val != refval) {
+                       dev_dbg(dev->dev,
+                               "%s: write/read CHIPREV register test failed: "
+                               "wrote 0x%2.2x, read:0x%2.2x expected:0x%2.2x\n",
+                               __func__, ii, val, refval);
+                       return -EINVAL;
+               }
+       }
+
+       /*
+        * Verify NET2272's "NET2270 legacy revision" register
+        *  - NET2272 has two revision registers. The NET2270 legacy revision
+        *    register should read the same value, regardless of the NET2272
+        *    silicon revision.  The legacy register applies to NET2270
+        *    firmware being applied to the NET2272.
+        */
+       val = net2272_read(dev, CHIPREV_LEGACY);
+       if (val != NET2270_LEGACY_REV) {
+               /*
+                * Unexpected legacy revision value
+                * - Perhaps the chip is a NET2270?
+                */
+               dev_dbg(dev->dev,
+                       "%s: WARNING: UNEXPECTED NET2272 LEGACY REGISTER VALUE:\n"
+                       " - CHIPREV_LEGACY: expected 0x%2.2x, got:0x%2.2x. (Not NET2272?)\n",
+                       __func__, NET2270_LEGACY_REV, val);
+               return -EINVAL;
+       }
+
+       /*
+        * Verify NET2272 silicon revision
+        *  - This revision register is appropriate for the silicon version
+        *    of the NET2272
+        */
+       val = net2272_read(dev, CHIPREV_2272);
+       switch (val) {
+       case CHIPREV_NET2272_R1:
+               /*
+                * NET2272 Rev 1 has DMA related errata:
+                *  - Newer silicon (Rev 1A or better) required
+                */
+               dev_dbg(dev->dev,
+                       "%s: Rev 1 detected: newer silicon recommended for DMA support\n",
+                       __func__);
+               break;
+       case CHIPREV_NET2272_R1A:
+               break;
+       default:
+               /* NET2272 silicon version *may* not work with this firmware */
+               dev_dbg(dev->dev,
+                       "%s: unexpected silicon revision register value: "
+                       " CHIPREV_2272: 0x%2.2x\n",
+                       __func__, val);
+               /*
+                * Return Success, even though the chip rev is not an expected value
+                *  - Older, pre-built firmware can attempt to operate on newer silicon
+                *  - Often, new silicon is perfectly compatible
+                */
+       }
+
+       /* Success: NET2272 checks out OK */
+       return 0;
+}
+
+static void
+net2272_gadget_release(struct device *_dev)
+{
+       struct net2272 *dev = dev_get_drvdata(_dev);
+       kfree(dev);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void
+net2272_remove(struct net2272 *dev)
+{
+       usb_del_gadget_udc(&dev->gadget);
+
+       /* start with the driver above us */
+       if (dev->driver) {
+               /* should have been done already by driver model core */
+               dev_warn(dev->dev, "pci remove, driver '%s' is still registered\n",
+                       dev->driver->driver.name);
+               usb_gadget_unregister_driver(dev->driver);
+       }
+
+       free_irq(dev->irq, dev);
+       iounmap(dev->base_addr);
+
+       device_remove_file(dev->dev, &dev_attr_registers);
+
+       dev_info(dev->dev, "unbind\n");
+}
+
+static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq)
+{
+       struct net2272 *ret;
+
+       if (!irq) {
+               dev_dbg(dev, "No IRQ!\n");
+               return ERR_PTR(-ENODEV);
+       }
+
+       /* alloc, and start init */
+       ret = kzalloc(sizeof(*ret), GFP_KERNEL);
+       if (!ret)
+               return ERR_PTR(-ENOMEM);
+
+       spin_lock_init(&ret->lock);
+       ret->irq = irq;
+       ret->dev = dev;
+       ret->gadget.ops = &net2272_ops;
+       ret->gadget.max_speed = USB_SPEED_HIGH;
+
+       /* the "gadget" abstracts/virtualizes the controller */
+       ret->gadget.name = driver_name;
+
+       return ret;
+}
+
+static int
+net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
+{
+       int ret;
+
+       /* See if there... */
+       if (net2272_present(dev)) {
+               dev_warn(dev->dev, "2272 not found!\n");
+               ret = -ENODEV;
+               goto err;
+       }
+
+       net2272_usb_reset(dev);
+       net2272_usb_reinit(dev);
+
+       ret = request_irq(dev->irq, net2272_irq, irqflags, driver_name, dev);
+       if (ret) {
+               dev_err(dev->dev, "request interrupt %i failed\n", dev->irq);
+               goto err;
+       }
+
+       dev->chiprev = net2272_read(dev, CHIPREV_2272);
+
+       /* done */
+       dev_info(dev->dev, "%s\n", driver_desc);
+       dev_info(dev->dev, "irq %i, mem %p, chip rev %04x, dma %s\n",
+               dev->irq, dev->base_addr, dev->chiprev,
+               dma_mode_string());
+       dev_info(dev->dev, "version: %s\n", driver_vers);
+
+       ret = device_create_file(dev->dev, &dev_attr_registers);
+       if (ret)
+               goto err_irq;
+
+       ret = usb_add_gadget_udc_release(dev->dev, &dev->gadget,
+                       net2272_gadget_release);
+       if (ret)
+               goto err_add_udc;
+
+       return 0;
+
+err_add_udc:
+       device_remove_file(dev->dev, &dev_attr_registers);
+ err_irq:
+       free_irq(dev->irq, dev);
+ err:
+       return ret;
+}
+
+#ifdef CONFIG_PCI
+
+/*
+ * wrap this driver around the specified device, but
+ * don't respond over USB until a gadget driver binds to us
+ */
+
+static int
+net2272_rdk1_probe(struct pci_dev *pdev, struct net2272 *dev)
+{
+       unsigned long resource, len, tmp;
+       void __iomem *mem_mapped_addr[4];
+       int ret, i;
+
+       /*
+        * BAR 0 holds PLX 9054 config registers
+        * BAR 1 is i/o memory; unused here
+        * BAR 2 holds EPLD config registers
+        * BAR 3 holds NET2272 registers
+        */
+
+       /* Find and map all address spaces */
+       for (i = 0; i < 4; ++i) {
+               if (i == 1)
+                       continue;       /* BAR1 unused */
+
+               resource = pci_resource_start(pdev, i);
+               len = pci_resource_len(pdev, i);
+
+               if (!request_mem_region(resource, len, driver_name)) {
+                       dev_dbg(dev->dev, "controller already in use\n");
+                       ret = -EBUSY;
+                       goto err;
+               }
+
+               mem_mapped_addr[i] = ioremap_nocache(resource, len);
+               if (mem_mapped_addr[i] == NULL) {
+                       release_mem_region(resource, len);
+                       dev_dbg(dev->dev, "can't map memory\n");
+                       ret = -EFAULT;
+                       goto err;
+               }
+       }
+
+       dev->rdk1.plx9054_base_addr = mem_mapped_addr[0];
+       dev->rdk1.epld_base_addr = mem_mapped_addr[2];
+       dev->base_addr = mem_mapped_addr[3];
+
+       /* Set PLX 9054 bus width (16 bits) */
+       tmp = readl(dev->rdk1.plx9054_base_addr + LBRD1);
+       writel((tmp & ~(3 << MEMORY_SPACE_LOCAL_BUS_WIDTH)) | W16_BIT,
+                       dev->rdk1.plx9054_base_addr + LBRD1);
+
+       /* Enable PLX 9054 Interrupts */
+       writel(readl(dev->rdk1.plx9054_base_addr + INTCSR) |
+                       (1 << PCI_INTERRUPT_ENABLE) |
+                       (1 << LOCAL_INTERRUPT_INPUT_ENABLE),
+                       dev->rdk1.plx9054_base_addr + INTCSR);
+
+       writeb((1 << CHANNEL_CLEAR_INTERRUPT | (0 << CHANNEL_ENABLE)),
+                       dev->rdk1.plx9054_base_addr + DMACSR0);
+
+       /* reset */
+       writeb((1 << EPLD_DMA_ENABLE) |
+               (1 << DMA_CTL_DACK) |
+               (1 << DMA_TIMEOUT_ENABLE) |
+               (1 << USER) |
+               (0 << MPX_MODE) |
+               (1 << BUSWIDTH) |
+               (1 << NET2272_RESET),
+               dev->base_addr + EPLD_IO_CONTROL_REGISTER);
+
+       mb();
+       writeb(readb(dev->base_addr + EPLD_IO_CONTROL_REGISTER) &
+               ~(1 << NET2272_RESET),
+               dev->base_addr + EPLD_IO_CONTROL_REGISTER);
+       udelay(200);
+
+       return 0;
+
+ err:
+       while (--i >= 0) {
+               iounmap(mem_mapped_addr[i]);
+               release_mem_region(pci_resource_start(pdev, i),
+                       pci_resource_len(pdev, i));
+       }
+
+       return ret;
+}
+
+static int
+net2272_rdk2_probe(struct pci_dev *pdev, struct net2272 *dev)
+{
+       unsigned long resource, len;
+       void __iomem *mem_mapped_addr[2];
+       int ret, i;
+
+       /*
+        * BAR 0 holds FGPA config registers
+        * BAR 1 holds NET2272 registers
+        */
+
+       /* Find and map all address spaces, bar2-3 unused in rdk 2 */
+       for (i = 0; i < 2; ++i) {
+               resource = pci_resource_start(pdev, i);
+               len = pci_resource_len(pdev, i);
+
+               if (!request_mem_region(resource, len, driver_name)) {
+                       dev_dbg(dev->dev, "controller already in use\n");
+                       ret = -EBUSY;
+                       goto err;
+               }
+
+               mem_mapped_addr[i] = ioremap_nocache(resource, len);
+               if (mem_mapped_addr[i] == NULL) {
+                       release_mem_region(resource, len);
+                       dev_dbg(dev->dev, "can't map memory\n");
+                       ret = -EFAULT;
+                       goto err;
+               }
+       }
+
+       dev->rdk2.fpga_base_addr = mem_mapped_addr[0];
+       dev->base_addr = mem_mapped_addr[1];
+
+       mb();
+       /* Set 2272 bus width (16 bits) and reset */
+       writel((1 << CHIP_RESET), dev->rdk2.fpga_base_addr + RDK2_LOCCTLRDK);
+       udelay(200);
+       writel((1 << BUS_WIDTH), dev->rdk2.fpga_base_addr + RDK2_LOCCTLRDK);
+       /* Print fpga version number */
+       dev_info(dev->dev, "RDK2 FPGA version %08x\n",
+               readl(dev->rdk2.fpga_base_addr + RDK2_FPGAREV));
+       /* Enable FPGA Interrupts */
+       writel((1 << NET2272_PCI_IRQ), dev->rdk2.fpga_base_addr + RDK2_IRQENB);
+
+       return 0;
+
+ err:
+       while (--i >= 0) {
+               iounmap(mem_mapped_addr[i]);
+               release_mem_region(pci_resource_start(pdev, i),
+                       pci_resource_len(pdev, i));
+       }
+
+       return ret;
+}
+
+static int
+net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       struct net2272 *dev;
+       int ret;
+
+       dev = net2272_probe_init(&pdev->dev, pdev->irq);
+       if (IS_ERR(dev))
+               return PTR_ERR(dev);
+       dev->dev_id = pdev->device;
+
+       if (pci_enable_device(pdev) < 0) {
+               ret = -ENODEV;
+               goto err_free;
+       }
+
+       pci_set_master(pdev);
+
+       switch (pdev->device) {
+       case PCI_DEVICE_ID_RDK1: ret = net2272_rdk1_probe(pdev, dev); break;
+       case PCI_DEVICE_ID_RDK2: ret = net2272_rdk2_probe(pdev, dev); break;
+       default: BUG();
+       }
+       if (ret)
+               goto err_pci;
+
+       ret = net2272_probe_fin(dev, 0);
+       if (ret)
+               goto err_pci;
+
+       pci_set_drvdata(pdev, dev);
+
+       return 0;
+
+ err_pci:
+       pci_disable_device(pdev);
+ err_free:
+       kfree(dev);
+
+       return ret;
+}
+
+static void
+net2272_rdk1_remove(struct pci_dev *pdev, struct net2272 *dev)
+{
+       int i;
+
+       /* disable PLX 9054 interrupts */
+       writel(readl(dev->rdk1.plx9054_base_addr + INTCSR) &
+               ~(1 << PCI_INTERRUPT_ENABLE),
+               dev->rdk1.plx9054_base_addr + INTCSR);
+
+       /* clean up resources allocated during probe() */
+       iounmap(dev->rdk1.plx9054_base_addr);
+       iounmap(dev->rdk1.epld_base_addr);
+
+       for (i = 0; i < 4; ++i) {
+               if (i == 1)
+                       continue;       /* BAR1 unused */
+               release_mem_region(pci_resource_start(pdev, i),
+                       pci_resource_len(pdev, i));
+       }
+}
+
+static void
+net2272_rdk2_remove(struct pci_dev *pdev, struct net2272 *dev)
+{
+       int i;
+
+       /* disable fpga interrupts
+       writel(readl(dev->rdk1.plx9054_base_addr + INTCSR) &
+                       ~(1 << PCI_INTERRUPT_ENABLE),
+                       dev->rdk1.plx9054_base_addr + INTCSR);
+       */
+
+       /* clean up resources allocated during probe() */
+       iounmap(dev->rdk2.fpga_base_addr);
+
+       for (i = 0; i < 2; ++i)
+               release_mem_region(pci_resource_start(pdev, i),
+                       pci_resource_len(pdev, i));
+}
+
+static void
+net2272_pci_remove(struct pci_dev *pdev)
+{
+       struct net2272 *dev = pci_get_drvdata(pdev);
+
+       net2272_remove(dev);
+
+       switch (pdev->device) {
+       case PCI_DEVICE_ID_RDK1: net2272_rdk1_remove(pdev, dev); break;
+       case PCI_DEVICE_ID_RDK2: net2272_rdk2_remove(pdev, dev); break;
+       default: BUG();
+       }
+
+       pci_disable_device(pdev);
+
+       kfree(dev);
+}
+
+/* Table of matching PCI IDs */
+static struct pci_device_id pci_ids[] = {
+       {       /* RDK 1 card */
+               .class       = ((PCI_CLASS_BRIDGE_OTHER << 8) | 0xfe),
+               .class_mask  = 0,
+               .vendor      = PCI_VENDOR_ID_PLX,
+               .device      = PCI_DEVICE_ID_RDK1,
+               .subvendor   = PCI_ANY_ID,
+               .subdevice   = PCI_ANY_ID,
+       },
+       {       /* RDK 2 card */
+               .class       = ((PCI_CLASS_BRIDGE_OTHER << 8) | 0xfe),
+               .class_mask  = 0,
+               .vendor      = PCI_VENDOR_ID_PLX,
+               .device      = PCI_DEVICE_ID_RDK2,
+               .subvendor   = PCI_ANY_ID,
+               .subdevice   = PCI_ANY_ID,
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(pci, pci_ids);
+
+static struct pci_driver net2272_pci_driver = {
+       .name     = driver_name,
+       .id_table = pci_ids,
+
+       .probe    = net2272_pci_probe,
+       .remove   = net2272_pci_remove,
+};
+
+static int net2272_pci_register(void)
+{
+       return pci_register_driver(&net2272_pci_driver);
+}
+
+static void net2272_pci_unregister(void)
+{
+       pci_unregister_driver(&net2272_pci_driver);
+}
+
+#else
+static inline int net2272_pci_register(void) { return 0; }
+static inline void net2272_pci_unregister(void) { }
+#endif
+
+/*---------------------------------------------------------------------------*/
+
+static int
+net2272_plat_probe(struct platform_device *pdev)
+{
+       struct net2272 *dev;
+       int ret;
+       unsigned int irqflags;
+       resource_size_t base, len;
+       struct resource *iomem, *iomem_bus, *irq_res;
+
+       irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       iomem_bus = platform_get_resource(pdev, IORESOURCE_BUS, 0);
+       if (!irq_res || !iomem) {
+               dev_err(&pdev->dev, "must provide irq/base addr");
+               return -EINVAL;
+       }
+
+       dev = net2272_probe_init(&pdev->dev, irq_res->start);
+       if (IS_ERR(dev))
+               return PTR_ERR(dev);
+
+       irqflags = 0;
+       if (irq_res->flags & IORESOURCE_IRQ_HIGHEDGE)
+               irqflags |= IRQF_TRIGGER_RISING;
+       if (irq_res->flags & IORESOURCE_IRQ_LOWEDGE)
+               irqflags |= IRQF_TRIGGER_FALLING;
+       if (irq_res->flags & IORESOURCE_IRQ_HIGHLEVEL)
+               irqflags |= IRQF_TRIGGER_HIGH;
+       if (irq_res->flags & IORESOURCE_IRQ_LOWLEVEL)
+               irqflags |= IRQF_TRIGGER_LOW;
+
+       base = iomem->start;
+       len = resource_size(iomem);
+       if (iomem_bus)
+               dev->base_shift = iomem_bus->start;
+
+       if (!request_mem_region(base, len, driver_name)) {
+               dev_dbg(dev->dev, "get request memory region!\n");
+               ret = -EBUSY;
+               goto err;
+       }
+       dev->base_addr = ioremap_nocache(base, len);
+       if (!dev->base_addr) {
+               dev_dbg(dev->dev, "can't map memory\n");
+               ret = -EFAULT;
+               goto err_req;
+       }
+
+       ret = net2272_probe_fin(dev, IRQF_TRIGGER_LOW);
+       if (ret)
+               goto err_io;
+
+       platform_set_drvdata(pdev, dev);
+       dev_info(&pdev->dev, "running in 16-bit, %sbyte swap local bus mode\n",
+               (net2272_read(dev, LOCCTL) & (1 << BYTE_SWAP)) ? "" : "no ");
+
+       return 0;
+
+ err_io:
+       iounmap(dev->base_addr);
+ err_req:
+       release_mem_region(base, len);
+ err:
+       return ret;
+}
+
+static int
+net2272_plat_remove(struct platform_device *pdev)
+{
+       struct net2272 *dev = platform_get_drvdata(pdev);
+
+       net2272_remove(dev);
+
+       release_mem_region(pdev->resource[0].start,
+               resource_size(&pdev->resource[0]));
+
+       kfree(dev);
+
+       return 0;
+}
+
+static struct platform_driver net2272_plat_driver = {
+       .probe   = net2272_plat_probe,
+       .remove  = net2272_plat_remove,
+       .driver  = {
+               .name  = driver_name,
+               .owner = THIS_MODULE,
+       },
+       /* FIXME .suspend, .resume */
+};
+MODULE_ALIAS("platform:net2272");
+
+static int __init net2272_init(void)
+{
+       int ret;
+
+       ret = net2272_pci_register();
+       if (ret)
+               return ret;
+       ret = platform_driver_register(&net2272_plat_driver);
+       if (ret)
+               goto err_pci;
+       return ret;
+
+err_pci:
+       net2272_pci_unregister();
+       return ret;
+}
+module_init(net2272_init);
+
+static void __exit net2272_cleanup(void)
+{
+       net2272_pci_unregister();
+       platform_driver_unregister(&net2272_plat_driver);
+}
+module_exit(net2272_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("PLX Technology, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/udc/net2272.h b/drivers/usb/gadget/udc/net2272.h
new file mode 100644 (file)
index 0000000..e595057
--- /dev/null
@@ -0,0 +1,601 @@
+/*
+ * PLX NET2272 high/full speed USB device controller
+ *
+ * Copyright (C) 2005-2006 PLX Technology, Inc.
+ * Copyright (C) 2006-2011 Analog Devices, Inc.
+ *
+ * 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
+ */
+
+#ifndef __NET2272_H__
+#define __NET2272_H__
+
+/* Main Registers */
+#define REGADDRPTR                     0x00
+#define REGDATA                                0x01
+#define IRQSTAT0                       0x02
+#define        ENDPOINT_0_INTERRUPT                    0
+#define        ENDPOINT_A_INTERRUPT                    1
+#define        ENDPOINT_B_INTERRUPT                    2
+#define        ENDPOINT_C_INTERRUPT                    3
+#define        VIRTUALIZED_ENDPOINT_INTERRUPT          4
+#define        SETUP_PACKET_INTERRUPT                  5
+#define        DMA_DONE_INTERRUPT                      6
+#define        SOF_INTERRUPT                           7
+#define IRQSTAT1                       0x03
+#define        CONTROL_STATUS_INTERRUPT                1
+#define        VBUS_INTERRUPT                          2
+#define        SUSPEND_REQUEST_INTERRUPT               3
+#define        SUSPEND_REQUEST_CHANGE_INTERRUPT        4
+#define        RESUME_INTERRUPT                        5
+#define        ROOT_PORT_RESET_INTERRUPT               6
+#define        RESET_STATUS                            7
+#define PAGESEL                                0x04
+#define DMAREQ                         0x1c
+#define        DMA_ENDPOINT_SELECT                     0
+#define        DREQ_POLARITY                           1
+#define        DACK_POLARITY                           2
+#define        EOT_POLARITY                            3
+#define        DMA_CONTROL_DACK                        4
+#define        DMA_REQUEST_ENABLE                      5
+#define        DMA_REQUEST                             6
+#define        DMA_BUFFER_VALID                        7
+#define SCRATCH                                0x1d
+#define IRQENB0                                0x20
+#define        ENDPOINT_0_INTERRUPT_ENABLE             0
+#define        ENDPOINT_A_INTERRUPT_ENABLE             1
+#define        ENDPOINT_B_INTERRUPT_ENABLE             2
+#define        ENDPOINT_C_INTERRUPT_ENABLE             3
+#define        VIRTUALIZED_ENDPOINT_INTERRUPT_ENABLE   4
+#define        SETUP_PACKET_INTERRUPT_ENABLE           5
+#define        DMA_DONE_INTERRUPT_ENABLE               6
+#define        SOF_INTERRUPT_ENABLE                    7
+#define IRQENB1                                0x21
+#define        VBUS_INTERRUPT_ENABLE                   2
+#define        SUSPEND_REQUEST_INTERRUPT_ENABLE        3
+#define        SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 4
+#define        RESUME_INTERRUPT_ENABLE                 5
+#define        ROOT_PORT_RESET_INTERRUPT_ENABLE        6
+#define LOCCTL                         0x22
+#define        DATA_WIDTH                              0
+#define        LOCAL_CLOCK_OUTPUT                      1
+#define                LOCAL_CLOCK_OUTPUT_OFF                  0
+#define                LOCAL_CLOCK_OUTPUT_3_75MHZ              1
+#define                LOCAL_CLOCK_OUTPUT_7_5MHZ               2
+#define                LOCAL_CLOCK_OUTPUT_15MHZ                3
+#define                LOCAL_CLOCK_OUTPUT_30MHZ                4
+#define                LOCAL_CLOCK_OUTPUT_60MHZ                5
+#define        DMA_SPLIT_BUS_MODE                      4
+#define        BYTE_SWAP                               5
+#define        BUFFER_CONFIGURATION                    6
+#define                BUFFER_CONFIGURATION_EPA512_EPB512      0
+#define                BUFFER_CONFIGURATION_EPA1024_EPB512     1
+#define                BUFFER_CONFIGURATION_EPA1024_EPB1024    2
+#define                BUFFER_CONFIGURATION_EPA1024DB          3
+#define CHIPREV_LEGACY                 0x23
+#define                NET2270_LEGACY_REV                      0x40
+#define LOCCTL1                                0x24
+#define        DMA_MODE                                0
+#define                SLOW_DREQ                               0
+#define                FAST_DREQ                               1
+#define                BURST_MODE                              2
+#define        DMA_DACK_ENABLE                         2
+#define CHIPREV_2272                   0x25
+#define                CHIPREV_NET2272_R1                      0x10
+#define                CHIPREV_NET2272_R1A                     0x11
+/* USB Registers */
+#define USBCTL0                                0x18
+#define        IO_WAKEUP_ENABLE                        1
+#define        USB_DETECT_ENABLE                       3
+#define        USB_ROOT_PORT_WAKEUP_ENABLE             5
+#define USBCTL1                                0x19
+#define        VBUS_PIN                                0
+#define                USB_FULL_SPEED                          1
+#define                USB_HIGH_SPEED                          2
+#define        GENERATE_RESUME                         3
+#define        VIRTUAL_ENDPOINT_ENABLE                 4
+#define FRAME0                         0x1a
+#define FRAME1                         0x1b
+#define OURADDR                                0x30
+#define        FORCE_IMMEDIATE                         7
+#define USBDIAG                                0x31
+#define        FORCE_TRANSMIT_CRC_ERROR                0
+#define        PREVENT_TRANSMIT_BIT_STUFF              1
+#define        FORCE_RECEIVE_ERROR                     2
+#define        FAST_TIMES                              4
+#define USBTEST                                0x32
+#define        TEST_MODE_SELECT                        0
+#define                NORMAL_OPERATION                        0
+#define                TEST_J                                  1
+#define                TEST_K                                  2
+#define                TEST_SE0_NAK                            3
+#define                TEST_PACKET                             4
+#define                TEST_FORCE_ENABLE                       5
+#define XCVRDIAG                       0x33
+#define        FORCE_FULL_SPEED                        2
+#define        FORCE_HIGH_SPEED                        3
+#define        OPMODE                                  4
+#define                NORMAL_OPERATION                        0
+#define                NON_DRIVING                             1
+#define                DISABLE_BITSTUFF_AND_NRZI_ENCODE        2
+#define        LINESTATE                               6
+#define                SE0_STATE                               0
+#define                J_STATE                                 1
+#define                K_STATE                                 2
+#define                SE1_STATE                               3
+#define VIRTOUT0                       0x34
+#define VIRTOUT1                       0x35
+#define VIRTIN0                                0x36
+#define VIRTIN1                                0x37
+#define SETUP0                         0x40
+#define SETUP1                         0x41
+#define SETUP2                         0x42
+#define SETUP3                         0x43
+#define SETUP4                         0x44
+#define SETUP5                         0x45
+#define SETUP6                         0x46
+#define SETUP7                         0x47
+/* Endpoint Registers (Paged via PAGESEL) */
+#define EP_DATA                                0x05
+#define EP_STAT0                       0x06
+#define        DATA_IN_TOKEN_INTERRUPT                 0
+#define        DATA_OUT_TOKEN_INTERRUPT                1
+#define        DATA_PACKET_TRANSMITTED_INTERRUPT       2
+#define        DATA_PACKET_RECEIVED_INTERRUPT          3
+#define        SHORT_PACKET_TRANSFERRED_INTERRUPT      4
+#define        NAK_OUT_PACKETS                         5
+#define        BUFFER_EMPTY                            6
+#define        BUFFER_FULL                             7
+#define EP_STAT1                       0x07
+#define        TIMEOUT                                 0
+#define        USB_OUT_ACK_SENT                        1
+#define        USB_OUT_NAK_SENT                        2
+#define        USB_IN_ACK_RCVD                         3
+#define        USB_IN_NAK_SENT                         4
+#define        USB_STALL_SENT                          5
+#define        LOCAL_OUT_ZLP                           6
+#define        BUFFER_FLUSH                            7
+#define EP_TRANSFER0                   0x08
+#define EP_TRANSFER1                   0x09
+#define EP_TRANSFER2                   0x0a
+#define EP_IRQENB                      0x0b
+#define        DATA_IN_TOKEN_INTERRUPT_ENABLE          0
+#define        DATA_OUT_TOKEN_INTERRUPT_ENABLE         1
+#define        DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE        2
+#define        DATA_PACKET_RECEIVED_INTERRUPT_ENABLE   3
+#define        SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE       4
+#define EP_AVAIL0                      0x0c
+#define EP_AVAIL1                      0x0d
+#define EP_RSPCLR                      0x0e
+#define EP_RSPSET                      0x0f
+#define        ENDPOINT_HALT                           0
+#define        ENDPOINT_TOGGLE                         1
+#define        NAK_OUT_PACKETS_MODE                    2
+#define        CONTROL_STATUS_PHASE_HANDSHAKE          3
+#define        INTERRUPT_MODE                          4
+#define        AUTOVALIDATE                            5
+#define        HIDE_STATUS_PHASE                       6
+#define        ALT_NAK_OUT_PACKETS                     7
+#define EP_MAXPKT0                     0x28
+#define EP_MAXPKT1                     0x29
+#define        ADDITIONAL_TRANSACTION_OPPORTUNITIES    3
+#define                NONE_ADDITIONAL_TRANSACTION             0
+#define                ONE_ADDITIONAL_TRANSACTION              1
+#define                TWO_ADDITIONAL_TRANSACTION              2
+#define EP_CFG                         0x2a
+#define        ENDPOINT_NUMBER                         0
+#define        ENDPOINT_DIRECTION                      4
+#define        ENDPOINT_TYPE                           5
+#define        ENDPOINT_ENABLE                         7
+#define EP_HBW                         0x2b
+#define        HIGH_BANDWIDTH_OUT_TRANSACTION_PID      0
+#define                DATA0_PID                               0
+#define                DATA1_PID                               1
+#define                DATA2_PID                               2
+#define                MDATA_PID                               3
+#define EP_BUFF_STATES                 0x2c
+#define        BUFFER_A_STATE                          0
+#define        BUFFER_B_STATE                          2
+#define                BUFF_FREE                               0
+#define                BUFF_VALID                              1
+#define                BUFF_LCL                                2
+#define                BUFF_USB                                3
+
+/*---------------------------------------------------------------------------*/
+
+#define PCI_DEVICE_ID_RDK1     0x9054
+
+/* PCI-RDK EPLD Registers */
+#define RDK_EPLD_IO_REGISTER1          0x00000000
+#define        RDK_EPLD_USB_RESET                              0
+#define        RDK_EPLD_USB_POWERDOWN                          1
+#define        RDK_EPLD_USB_WAKEUP                             2
+#define        RDK_EPLD_USB_EOT                                3
+#define        RDK_EPLD_DPPULL                                 4
+#define RDK_EPLD_IO_REGISTER2          0x00000004
+#define        RDK_EPLD_BUSWIDTH                               0
+#define        RDK_EPLD_USER                                   2
+#define        RDK_EPLD_RESET_INTERRUPT_ENABLE                 3
+#define        RDK_EPLD_DMA_TIMEOUT_ENABLE                     4
+#define RDK_EPLD_STATUS_REGISTER       0x00000008
+#define        RDK_EPLD_USB_LRESET                             0
+#define RDK_EPLD_REVISION_REGISTER     0x0000000c
+
+/* PCI-RDK PLX 9054 Registers */
+#define INTCSR                         0x68
+#define        PCI_INTERRUPT_ENABLE                            8
+#define        LOCAL_INTERRUPT_INPUT_ENABLE                    11
+#define        LOCAL_INPUT_INTERRUPT_ACTIVE                    15
+#define        LOCAL_DMA_CHANNEL_0_INTERRUPT_ENABLE            18
+#define        LOCAL_DMA_CHANNEL_1_INTERRUPT_ENABLE            19
+#define        DMA_CHANNEL_0_INTERRUPT_ACTIVE                  21
+#define        DMA_CHANNEL_1_INTERRUPT_ACTIVE                  22
+#define CNTRL                          0x6C
+#define        RELOAD_CONFIGURATION_REGISTERS                  29
+#define        PCI_ADAPTER_SOFTWARE_RESET                      30
+#define DMAMODE0                       0x80
+#define        LOCAL_BUS_WIDTH                                 0
+#define        INTERNAL_WAIT_STATES                            2
+#define        TA_READY_INPUT_ENABLE                           6
+#define        LOCAL_BURST_ENABLE                              8
+#define        SCATTER_GATHER_MODE                             9
+#define        DONE_INTERRUPT_ENABLE                           10
+#define        LOCAL_ADDRESSING_MODE                           11
+#define        DEMAND_MODE                                     12
+#define        DMA_EOT_ENABLE                                  14
+#define        FAST_SLOW_TERMINATE_MODE_SELECT                 15
+#define        DMA_CHANNEL_INTERRUPT_SELECT                    17
+#define DMAPADR0                       0x84
+#define DMALADR0                       0x88
+#define DMASIZ0                                0x8c
+#define DMADPR0                                0x90
+#define        DESCRIPTOR_LOCATION                             0
+#define        END_OF_CHAIN                                    1
+#define        INTERRUPT_AFTER_TERMINAL_COUNT                  2
+#define        DIRECTION_OF_TRANSFER                           3
+#define DMACSR0                                0xa8
+#define        CHANNEL_ENABLE                                  0
+#define        CHANNEL_START                                   1
+#define        CHANNEL_ABORT                                   2
+#define        CHANNEL_CLEAR_INTERRUPT                         3
+#define        CHANNEL_DONE                                    4
+#define DMATHR                         0xb0
+#define LBRD1                          0xf8
+#define        MEMORY_SPACE_LOCAL_BUS_WIDTH                    0
+#define        W8_BIT                                          0
+#define        W16_BIT                                         1
+
+/* Special OR'ing of INTCSR bits */
+#define LOCAL_INTERRUPT_TEST \
+       ((1 << LOCAL_INPUT_INTERRUPT_ACTIVE) | \
+        (1 << LOCAL_INTERRUPT_INPUT_ENABLE))
+
+#define DMA_CHANNEL_0_TEST \
+       ((1 << DMA_CHANNEL_0_INTERRUPT_ACTIVE) | \
+        (1 << LOCAL_DMA_CHANNEL_0_INTERRUPT_ENABLE))
+
+#define DMA_CHANNEL_1_TEST \
+       ((1 << DMA_CHANNEL_1_INTERRUPT_ACTIVE) | \
+        (1 << LOCAL_DMA_CHANNEL_1_INTERRUPT_ENABLE))
+
+/* EPLD Registers */
+#define RDK_EPLD_IO_REGISTER1                  0x00000000
+#define        RDK_EPLD_USB_RESET                      0
+#define        RDK_EPLD_USB_POWERDOWN                  1
+#define        RDK_EPLD_USB_WAKEUP                     2
+#define        RDK_EPLD_USB_EOT                        3
+#define        RDK_EPLD_DPPULL                         4
+#define RDK_EPLD_IO_REGISTER2                  0x00000004
+#define        RDK_EPLD_BUSWIDTH                       0
+#define        RDK_EPLD_USER                           2
+#define        RDK_EPLD_RESET_INTERRUPT_ENABLE         3
+#define        RDK_EPLD_DMA_TIMEOUT_ENABLE             4
+#define RDK_EPLD_STATUS_REGISTER               0x00000008
+#define RDK_EPLD_USB_LRESET                            0
+#define RDK_EPLD_REVISION_REGISTER             0x0000000c
+
+#define EPLD_IO_CONTROL_REGISTER               0x400
+#define        NET2272_RESET                           0
+#define        BUSWIDTH                                1
+#define        MPX_MODE                                3
+#define        USER                                    4
+#define        DMA_TIMEOUT_ENABLE                      5
+#define        DMA_CTL_DACK                            6
+#define        EPLD_DMA_ENABLE                         7
+#define EPLD_DMA_CONTROL_REGISTER              0x800
+#define        SPLIT_DMA_MODE                          0
+#define        SPLIT_DMA_DIRECTION                     1
+#define        SPLIT_DMA_ENABLE                        2
+#define        SPLIT_DMA_INTERRUPT_ENABLE              3
+#define        SPLIT_DMA_INTERRUPT                     4
+#define        EPLD_DMA_MODE                           5
+#define        EPLD_DMA_CONTROLLER_ENABLE              7
+#define SPLIT_DMA_ADDRESS_LOW                  0xc00
+#define SPLIT_DMA_ADDRESS_HIGH                 0x1000
+#define SPLIT_DMA_BYTE_COUNT_LOW               0x1400
+#define SPLIT_DMA_BYTE_COUNT_HIGH              0x1800
+#define EPLD_REVISION_REGISTER                 0x1c00
+#define SPLIT_DMA_RAM                          0x4000
+#define DMA_RAM_SIZE                           0x1000
+
+/*---------------------------------------------------------------------------*/
+
+#define PCI_DEVICE_ID_RDK2     0x3272
+
+/* PCI-RDK version 2 registers */
+
+/* Main Control Registers */
+
+#define RDK2_IRQENB                    0x00
+#define RDK2_IRQSTAT                   0x04
+#define        PB7                             23
+#define        PB6                             22
+#define        PB5                             21
+#define        PB4                             20
+#define        PB3                             19
+#define        PB2                             18
+#define        PB1                             17
+#define        PB0                             16
+#define        GP3                             23
+#define        GP2                             23
+#define        GP1                             23
+#define        GP0                             23
+#define        DMA_RETRY_ABORT                 6
+#define        DMA_PAUSE_DONE                  5
+#define        DMA_ABORT_DONE                  4
+#define        DMA_OUT_FIFO_TRANSFER_DONE      3
+#define        DMA_LOCAL_DONE                  2
+#define        DMA_PCI_DONE                    1
+#define        NET2272_PCI_IRQ                 0
+
+#define RDK2_LOCCTLRDK                 0x08
+#define        CHIP_RESET                      3
+#define        SPLIT_DMA                       2
+#define        MULTIPLEX_MODE                  1
+#define        BUS_WIDTH                       0
+
+#define RDK2_GPIOCTL                   0x10
+#define        GP3_OUT_ENABLE                                  7
+#define        GP2_OUT_ENABLE                                  6
+#define        GP1_OUT_ENABLE                                  5
+#define        GP0_OUT_ENABLE                                  4
+#define        GP3_DATA                                        3
+#define        GP2_DATA                                        2
+#define        GP1_DATA                                        1
+#define        GP0_DATA                                        0
+
+#define RDK2_LEDSW                     0x14
+#define        LED3                            27
+#define        LED2                            26
+#define        LED1                            25
+#define        LED0                            24
+#define        PBUTTON                         16
+#define        DIPSW                           0
+
+#define RDK2_DIAG                      0x18
+#define        RDK2_FAST_TIMES                         2
+#define        FORCE_PCI_SERR                          1
+#define        FORCE_PCI_INT                           0
+#define RDK2_FPGAREV                   0x1C
+
+/* Dma Control registers */
+#define RDK2_DMACTL                    0x80
+#define        ADDR_HOLD                               24
+#define        RETRY_COUNT                             16      /* 23:16 */
+#define        FIFO_THRESHOLD                          11      /* 15:11 */
+#define        MEM_WRITE_INVALIDATE                    10
+#define        READ_MULTIPLE                           9
+#define        READ_LINE                               8
+#define        RDK2_DMA_MODE                           6       /* 7:6 */
+#define        CONTROL_DACK                            5
+#define        EOT_ENABLE                              4
+#define        EOT_POLARITY                            3
+#define        DACK_POLARITY                           2
+#define        DREQ_POLARITY                           1
+#define        DMA_ENABLE                              0
+
+#define RDK2_DMASTAT                   0x84
+#define        GATHER_COUNT                            12      /* 14:12 */
+#define        FIFO_COUNT                              6       /* 11:6 */
+#define        FIFO_FLUSH                              5
+#define        FIFO_TRANSFER                           4
+#define        PAUSE_DONE                              3
+#define        ABORT_DONE                              2
+#define        DMA_ABORT                               1
+#define        DMA_START                               0
+
+#define RDK2_DMAPCICOUNT               0x88
+#define        DMA_DIRECTION                           31
+#define        DMA_PCI_BYTE_COUNT                      0       /* 0:23 */
+
+#define RDK2_DMALOCCOUNT               0x8C    /* 0:23 dma local byte count */
+
+#define RDK2_DMAADDR                   0x90    /* 2:31 PCI bus starting address */
+
+/*---------------------------------------------------------------------------*/
+
+#define REG_INDEXED_THRESHOLD  (1 << 5)
+
+/* DRIVER DATA STRUCTURES and UTILITIES */
+struct net2272_ep {
+       struct usb_ep ep;
+       struct net2272 *dev;
+       unsigned long irqs;
+
+       /* analogous to a host-side qh */
+       struct list_head queue;
+       const struct usb_endpoint_descriptor *desc;
+       unsigned num:8,
+                fifo_size:12,
+                stopped:1,
+                wedged:1,
+                is_in:1,
+                is_iso:1,
+                dma:1,
+                not_empty:1;
+};
+
+struct net2272 {
+       /* each device provides one gadget, several endpoints */
+       struct usb_gadget gadget;
+       struct device *dev;
+       unsigned short dev_id;
+
+       spinlock_t lock;
+       struct net2272_ep ep[4];
+       struct usb_gadget_driver *driver;
+       unsigned protocol_stall:1,
+                softconnect:1,
+                is_selfpowered:1,
+                wakeup:1,
+                dma_eot_polarity:1,
+                dma_dack_polarity:1,
+                dma_dreq_polarity:1,
+                dma_busy:1;
+       u16 chiprev;
+       u8 pagesel;
+
+       unsigned int irq;
+       unsigned short fifo_mode;
+
+       unsigned int base_shift;
+       u16 __iomem *base_addr;
+       union {
+#ifdef CONFIG_PCI
+               struct {
+                       void __iomem *plx9054_base_addr;
+                       void __iomem *epld_base_addr;
+               } rdk1;
+               struct {
+                       /* Bar0, Bar1 is base_addr both mem-mapped */
+                       void __iomem *fpga_base_addr;
+               } rdk2;
+#endif
+       };
+};
+
+static void __iomem *
+net2272_reg_addr(struct net2272 *dev, unsigned int reg)
+{
+       return dev->base_addr + (reg << dev->base_shift);
+}
+
+static void
+net2272_write(struct net2272 *dev, unsigned int reg, u8 value)
+{
+       if (reg >= REG_INDEXED_THRESHOLD) {
+               /*
+                * Indexed register; use REGADDRPTR/REGDATA
+                *  - Save and restore REGADDRPTR. This prevents REGADDRPTR from
+                *    changes between other code sections, but it is time consuming.
+                *  - Performance tips: either do not save and restore REGADDRPTR (if it
+                *    is safe) or do save/restore operations only in critical sections.
+               u8 tmp = readb(dev->base_addr + REGADDRPTR);
+                */
+               writeb((u8)reg, net2272_reg_addr(dev, REGADDRPTR));
+               writeb(value, net2272_reg_addr(dev, REGDATA));
+               /* writeb(tmp, net2272_reg_addr(dev, REGADDRPTR)); */
+       } else
+               writeb(value, net2272_reg_addr(dev, reg));
+}
+
+static u8
+net2272_read(struct net2272 *dev, unsigned int reg)
+{
+       u8 ret;
+
+       if (reg >= REG_INDEXED_THRESHOLD) {
+               /*
+                * Indexed register; use REGADDRPTR/REGDATA
+                *  - Save and restore REGADDRPTR. This prevents REGADDRPTR from
+                *    changes between other code sections, but it is time consuming.
+                *  - Performance tips: either do not save and restore REGADDRPTR (if it
+                *    is safe) or do save/restore operations only in critical sections.
+               u8 tmp = readb(dev->base_addr + REGADDRPTR);
+                */
+               writeb((u8)reg, net2272_reg_addr(dev, REGADDRPTR));
+               ret = readb(net2272_reg_addr(dev, REGDATA));
+               /* writeb(tmp, net2272_reg_addr(dev, REGADDRPTR)); */
+       } else
+               ret = readb(net2272_reg_addr(dev, reg));
+
+       return ret;
+}
+
+static void
+net2272_ep_write(struct net2272_ep *ep, unsigned int reg, u8 value)
+{
+       struct net2272 *dev = ep->dev;
+
+       if (dev->pagesel != ep->num) {
+               net2272_write(dev, PAGESEL, ep->num);
+               dev->pagesel = ep->num;
+       }
+       net2272_write(dev, reg, value);
+}
+
+static u8
+net2272_ep_read(struct net2272_ep *ep, unsigned int reg)
+{
+       struct net2272 *dev = ep->dev;
+
+       if (dev->pagesel != ep->num) {
+               net2272_write(dev, PAGESEL, ep->num);
+               dev->pagesel = ep->num;
+       }
+       return net2272_read(dev, reg);
+}
+
+static void allow_status(struct net2272_ep *ep)
+{
+       /* ep0 only */
+       net2272_ep_write(ep, EP_RSPCLR,
+               (1 << CONTROL_STATUS_PHASE_HANDSHAKE) |
+               (1 << ALT_NAK_OUT_PACKETS) |
+               (1 << NAK_OUT_PACKETS_MODE));
+       ep->stopped = 1;
+}
+
+static void set_halt(struct net2272_ep *ep)
+{
+       /* ep0 and bulk/intr endpoints */
+       net2272_ep_write(ep, EP_RSPCLR, 1 << CONTROL_STATUS_PHASE_HANDSHAKE);
+       net2272_ep_write(ep, EP_RSPSET, 1 << ENDPOINT_HALT);
+}
+
+static void clear_halt(struct net2272_ep *ep)
+{
+       /* ep0 and bulk/intr endpoints */
+       net2272_ep_write(ep, EP_RSPCLR,
+               (1 << ENDPOINT_HALT) | (1 << ENDPOINT_TOGGLE));
+}
+
+/* count (<= 4) bytes in the next fifo write will be valid */
+static void set_fifo_bytecount(struct net2272_ep *ep, unsigned count)
+{
+       /* net2272_ep_write will truncate to u8 for us */
+       net2272_ep_write(ep, EP_TRANSFER2, count >> 16);
+       net2272_ep_write(ep, EP_TRANSFER1, count >> 8);
+       net2272_ep_write(ep, EP_TRANSFER0, count);
+}
+
+struct net2272_request {
+       struct usb_request req;
+       struct list_head queue;
+       unsigned mapped:1,
+                valid:1;
+};
+
+#endif
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
new file mode 100644 (file)
index 0000000..248dccb
--- /dev/null
@@ -0,0 +1,3827 @@
+/*
+ * Driver for the PLX NET2280 USB device controller.
+ * Specs and errata are available from <http://www.plxtech.com>.
+ *
+ * PLX Technology Inc. (formerly NetChip Technology) supported the
+ * development of this driver.
+ *
+ *
+ * CODE STATUS HIGHLIGHTS
+ *
+ * This driver should work well with most "gadget" drivers, including
+ * the Mass Storage, Serial, and Ethernet/RNDIS gadget drivers
+ * as well as Gadget Zero and Gadgetfs.
+ *
+ * DMA is enabled by default.  Drivers using transfer queues might use
+ * DMA chaining to remove IRQ latencies between transfers.  (Except when
+ * short OUT transfers happen.)  Drivers can use the req->no_interrupt
+ * hint to completely eliminate some IRQs, if a later IRQ is guaranteed
+ * and DMA chaining is enabled.
+ *
+ * MSI is enabled by default.  The legacy IRQ is used if MSI couldn't
+ * be enabled.
+ *
+ * Note that almost all the errata workarounds here are only needed for
+ * rev1 chips.  Rev1a silicon (0110) fixes almost all of them.
+ */
+
+/*
+ * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2003-2005 PLX Technology, Inc.
+ * Copyright (C) 2014 Ricardo Ribalda - Qtechnology/AS
+ *
+ * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility
+ *     with 2282 chip
+ *
+ * Modified Ricardo Ribalda Qtechnology AS  to provide compatibility
+ *     with usb 338x chip. Based on PLX driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/prefetch.h>
+#include <linux/io.h>
+
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/unaligned.h>
+
+#define        DRIVER_DESC             "PLX NET228x/USB338x USB Peripheral Controller"
+#define        DRIVER_VERSION          "2005 Sept 27/v3.0"
+
+#define        EP_DONTUSE              13      /* nonzero */
+
+#define USE_RDK_LEDS           /* GPIO pins control three LEDs */
+
+
+static const char driver_name[] = "net2280";
+static const char driver_desc[] = DRIVER_DESC;
+
+static const u32 ep_bit[9] = { 0, 17, 2, 19, 4, 1, 18, 3, 20 };
+static const char ep0name[] = "ep0";
+static const char *const ep_name[] = {
+       ep0name,
+       "ep-a", "ep-b", "ep-c", "ep-d",
+       "ep-e", "ep-f", "ep-g", "ep-h",
+};
+
+/* use_dma -- general goodness, fewer interrupts, less cpu load (vs PIO)
+ * use_dma_chaining -- dma descriptor queueing gives even more irq reduction
+ *
+ * The net2280 DMA engines are not tightly integrated with their FIFOs;
+ * not all cases are (yet) handled well in this driver or the silicon.
+ * Some gadget drivers work better with the dma support here than others.
+ * These two parameters let you use PIO or more aggressive DMA.
+ */
+static bool use_dma = true;
+static bool use_dma_chaining;
+static bool use_msi = true;
+
+/* "modprobe net2280 use_dma=n" etc */
+module_param(use_dma, bool, 0444);
+module_param(use_dma_chaining, bool, 0444);
+module_param(use_msi, bool, 0444);
+
+/* mode 0 == ep-{a,b,c,d} 1K fifo each
+ * mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable
+ * mode 2 == ep-a 2K fifo, ep-{b,c} 1K each, ep-d unavailable
+ */
+static ushort fifo_mode;
+
+/* "modprobe net2280 fifo_mode=1" etc */
+module_param(fifo_mode, ushort, 0644);
+
+/* enable_suspend -- When enabled, the driver will respond to
+ * USB suspend requests by powering down the NET2280.  Otherwise,
+ * USB suspend requests will be ignored.  This is acceptable for
+ * self-powered devices
+ */
+static bool enable_suspend;
+
+/* "modprobe net2280 enable_suspend=1" etc */
+module_param(enable_suspend, bool, 0444);
+
+/* force full-speed operation */
+static bool full_speed;
+module_param(full_speed, bool, 0444);
+MODULE_PARM_DESC(full_speed, "force full-speed mode -- for testing only!");
+
+#define        DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out")
+
+static char *type_string(u8 bmAttributes)
+{
+       switch ((bmAttributes) & USB_ENDPOINT_XFERTYPE_MASK) {
+       case USB_ENDPOINT_XFER_BULK:    return "bulk";
+       case USB_ENDPOINT_XFER_ISOC:    return "iso";
+       case USB_ENDPOINT_XFER_INT:     return "intr";
+       }
+       return "control";
+}
+
+#include "net2280.h"
+
+#define valid_bit      cpu_to_le32(BIT(VALID_BIT))
+#define dma_done_ie    cpu_to_le32(BIT(DMA_DONE_INTERRUPT_ENABLE))
+
+/*-------------------------------------------------------------------------*/
+static inline void enable_pciirqenb(struct net2280_ep *ep)
+{
+       u32 tmp = readl(&ep->dev->regs->pciirqenb0);
+
+       if (ep->dev->quirks & PLX_LEGACY)
+               tmp |= BIT(ep->num);
+       else
+               tmp |= BIT(ep_bit[ep->num]);
+       writel(tmp, &ep->dev->regs->pciirqenb0);
+
+       return;
+}
+
+static int
+net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+{
+       struct net2280          *dev;
+       struct net2280_ep       *ep;
+       u32                     max, tmp;
+       unsigned long           flags;
+       static const u32 ep_key[9] = { 1, 0, 1, 0, 1, 1, 0, 1, 0 };
+
+       ep = container_of(_ep, struct net2280_ep, ep);
+       if (!_ep || !desc || ep->desc || _ep->name == ep0name ||
+                       desc->bDescriptorType != USB_DT_ENDPOINT)
+               return -EINVAL;
+       dev = ep->dev;
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       /* erratum 0119 workaround ties up an endpoint number */
+       if ((desc->bEndpointAddress & 0x0f) == EP_DONTUSE)
+               return -EDOM;
+
+       if (dev->quirks & PLX_SUPERSPEED) {
+               if ((desc->bEndpointAddress & 0x0f) >= 0x0c)
+                       return -EDOM;
+               ep->is_in = !!usb_endpoint_dir_in(desc);
+               if (dev->enhanced_mode && ep->is_in && ep_key[ep->num])
+                       return -EINVAL;
+       }
+
+       /* sanity check ep-e/ep-f since their fifos are small */
+       max = usb_endpoint_maxp(desc) & 0x1fff;
+       if (ep->num > 4 && max > 64 && (dev->quirks & PLX_LEGACY))
+               return -ERANGE;
+
+       spin_lock_irqsave(&dev->lock, flags);
+       _ep->maxpacket = max & 0x7ff;
+       ep->desc = desc;
+
+       /* ep_reset() has already been called */
+       ep->stopped = 0;
+       ep->wedged = 0;
+       ep->out_overflow = 0;
+
+       /* set speed-dependent max packet; may kick in high bandwidth */
+       set_max_speed(ep, max);
+
+       /* FIFO lines can't go to different packets.  PIO is ok, so
+        * use it instead of troublesome (non-bulk) multi-packet DMA.
+        */
+       if (ep->dma && (max % 4) != 0 && use_dma_chaining) {
+               ep_dbg(ep->dev, "%s, no dma for maxpacket %d\n",
+                       ep->ep.name, ep->ep.maxpacket);
+               ep->dma = NULL;
+       }
+
+       /* set type, direction, address; reset fifo counters */
+       writel(BIT(FIFO_FLUSH), &ep->regs->ep_stat);
+       tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+       if (tmp == USB_ENDPOINT_XFER_INT) {
+               /* erratum 0105 workaround prevents hs NYET */
+               if (dev->chiprev == 0100 &&
+                               dev->gadget.speed == USB_SPEED_HIGH &&
+                               !(desc->bEndpointAddress & USB_DIR_IN))
+                       writel(BIT(CLEAR_NAK_OUT_PACKETS_MODE),
+                               &ep->regs->ep_rsp);
+       } else if (tmp == USB_ENDPOINT_XFER_BULK) {
+               /* catch some particularly blatant driver bugs */
+               if ((dev->gadget.speed == USB_SPEED_SUPER && max != 1024) ||
+                   (dev->gadget.speed == USB_SPEED_HIGH && max != 512) ||
+                   (dev->gadget.speed == USB_SPEED_FULL && max > 64)) {
+                       spin_unlock_irqrestore(&dev->lock, flags);
+                       return -ERANGE;
+               }
+       }
+       ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC);
+       /* Enable this endpoint */
+       if (dev->quirks & PLX_LEGACY) {
+               tmp <<= ENDPOINT_TYPE;
+               tmp |= desc->bEndpointAddress;
+               /* default full fifo lines */
+               tmp |= (4 << ENDPOINT_BYTE_COUNT);
+               tmp |= BIT(ENDPOINT_ENABLE);
+               ep->is_in = (tmp & USB_DIR_IN) != 0;
+       } else {
+               /* In Legacy mode, only OUT endpoints are used */
+               if (dev->enhanced_mode && ep->is_in) {
+                       tmp <<= IN_ENDPOINT_TYPE;
+                       tmp |= BIT(IN_ENDPOINT_ENABLE);
+                       /* Not applicable to Legacy */
+                       tmp |= BIT(ENDPOINT_DIRECTION);
+               } else {
+                       tmp <<= OUT_ENDPOINT_TYPE;
+                       tmp |= BIT(OUT_ENDPOINT_ENABLE);
+                       tmp |= (ep->is_in << ENDPOINT_DIRECTION);
+               }
+
+               tmp |= usb_endpoint_num(desc);
+               tmp |= (ep->ep.maxburst << MAX_BURST_SIZE);
+       }
+
+       /* Make sure all the registers are written before ep_rsp*/
+       wmb();
+
+       /* for OUT transfers, block the rx fifo until a read is posted */
+       if (!ep->is_in)
+               writel(BIT(SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
+       else if (!(dev->quirks & PLX_2280)) {
+               /* Added for 2282, Don't use nak packets on an in endpoint,
+                * this was ignored on 2280
+                */
+               writel(BIT(CLEAR_NAK_OUT_PACKETS) |
+                       BIT(CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
+       }
+
+       writel(tmp, &ep->cfg->ep_cfg);
+
+       /* enable irqs */
+       if (!ep->dma) {                         /* pio, per-packet */
+               enable_pciirqenb(ep);
+
+               tmp = BIT(DATA_PACKET_RECEIVED_INTERRUPT_ENABLE) |
+                       BIT(DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE);
+               if (dev->quirks & PLX_2280)
+                       tmp |= readl(&ep->regs->ep_irqenb);
+               writel(tmp, &ep->regs->ep_irqenb);
+       } else {                                /* dma, per-request */
+               tmp = BIT((8 + ep->num));       /* completion */
+               tmp |= readl(&dev->regs->pciirqenb1);
+               writel(tmp, &dev->regs->pciirqenb1);
+
+               /* for short OUT transfers, dma completions can't
+                * advance the queue; do it pio-style, by hand.
+                * NOTE erratum 0112 workaround #2
+                */
+               if ((desc->bEndpointAddress & USB_DIR_IN) == 0) {
+                       tmp = BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE);
+                       writel(tmp, &ep->regs->ep_irqenb);
+
+                       enable_pciirqenb(ep);
+               }
+       }
+
+       tmp = desc->bEndpointAddress;
+       ep_dbg(dev, "enabled %s (ep%d%s-%s) %s max %04x\n",
+               _ep->name, tmp & 0x0f, DIR_STRING(tmp),
+               type_string(desc->bmAttributes),
+               ep->dma ? "dma" : "pio", max);
+
+       /* pci writes may still be posted */
+       spin_unlock_irqrestore(&dev->lock, flags);
+       return 0;
+}
+
+static int handshake(u32 __iomem *ptr, u32 mask, u32 done, int usec)
+{
+       u32     result;
+
+       do {
+               result = readl(ptr);
+               if (result == ~(u32)0)          /* "device unplugged" */
+                       return -ENODEV;
+               result &= mask;
+               if (result == done)
+                       return 0;
+               udelay(1);
+               usec--;
+       } while (usec > 0);
+       return -ETIMEDOUT;
+}
+
+static const struct usb_ep_ops net2280_ep_ops;
+
+static void ep_reset_228x(struct net2280_regs __iomem *regs,
+                         struct net2280_ep *ep)
+{
+       u32             tmp;
+
+       ep->desc = NULL;
+       INIT_LIST_HEAD(&ep->queue);
+
+       usb_ep_set_maxpacket_limit(&ep->ep, ~0);
+       ep->ep.ops = &net2280_ep_ops;
+
+       /* disable the dma, irqs, endpoint... */
+       if (ep->dma) {
+               writel(0, &ep->dma->dmactl);
+               writel(BIT(DMA_SCATTER_GATHER_DONE_INTERRUPT) |
+                       BIT(DMA_TRANSACTION_DONE_INTERRUPT) |
+                       BIT(DMA_ABORT),
+                       &ep->dma->dmastat);
+
+               tmp = readl(&regs->pciirqenb0);
+               tmp &= ~BIT(ep->num);
+               writel(tmp, &regs->pciirqenb0);
+       } else {
+               tmp = readl(&regs->pciirqenb1);
+               tmp &= ~BIT((8 + ep->num));     /* completion */
+               writel(tmp, &regs->pciirqenb1);
+       }
+       writel(0, &ep->regs->ep_irqenb);
+
+       /* init to our chosen defaults, notably so that we NAK OUT
+        * packets until the driver queues a read (+note erratum 0112)
+        */
+       if (!ep->is_in || (ep->dev->quirks & PLX_2280)) {
+               tmp = BIT(SET_NAK_OUT_PACKETS_MODE) |
+               BIT(SET_NAK_OUT_PACKETS) |
+               BIT(CLEAR_EP_HIDE_STATUS_PHASE) |
+               BIT(CLEAR_INTERRUPT_MODE);
+       } else {
+               /* added for 2282 */
+               tmp = BIT(CLEAR_NAK_OUT_PACKETS_MODE) |
+               BIT(CLEAR_NAK_OUT_PACKETS) |
+               BIT(CLEAR_EP_HIDE_STATUS_PHASE) |
+               BIT(CLEAR_INTERRUPT_MODE);
+       }
+
+       if (ep->num != 0) {
+               tmp |= BIT(CLEAR_ENDPOINT_TOGGLE) |
+                       BIT(CLEAR_ENDPOINT_HALT);
+       }
+       writel(tmp, &ep->regs->ep_rsp);
+
+       /* scrub most status bits, and flush any fifo state */
+       if (ep->dev->quirks & PLX_2280)
+               tmp = BIT(FIFO_OVERFLOW) |
+                       BIT(FIFO_UNDERFLOW);
+       else
+               tmp = 0;
+
+       writel(tmp | BIT(TIMEOUT) |
+               BIT(USB_STALL_SENT) |
+               BIT(USB_IN_NAK_SENT) |
+               BIT(USB_IN_ACK_RCVD) |
+               BIT(USB_OUT_PING_NAK_SENT) |
+               BIT(USB_OUT_ACK_SENT) |
+               BIT(FIFO_FLUSH) |
+               BIT(SHORT_PACKET_OUT_DONE_INTERRUPT) |
+               BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT) |
+               BIT(DATA_PACKET_RECEIVED_INTERRUPT) |
+               BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
+               BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
+               BIT(DATA_IN_TOKEN_INTERRUPT),
+               &ep->regs->ep_stat);
+
+       /* fifo size is handled separately */
+}
+
+static void ep_reset_338x(struct net2280_regs __iomem *regs,
+                                       struct net2280_ep *ep)
+{
+       u32 tmp, dmastat;
+
+       ep->desc = NULL;
+       INIT_LIST_HEAD(&ep->queue);
+
+       usb_ep_set_maxpacket_limit(&ep->ep, ~0);
+       ep->ep.ops = &net2280_ep_ops;
+
+       /* disable the dma, irqs, endpoint... */
+       if (ep->dma) {
+               writel(0, &ep->dma->dmactl);
+               writel(BIT(DMA_ABORT_DONE_INTERRUPT) |
+                      BIT(DMA_PAUSE_DONE_INTERRUPT) |
+                      BIT(DMA_SCATTER_GATHER_DONE_INTERRUPT) |
+                      BIT(DMA_TRANSACTION_DONE_INTERRUPT),
+                      /* | BIT(DMA_ABORT), */
+                      &ep->dma->dmastat);
+
+               dmastat = readl(&ep->dma->dmastat);
+               if (dmastat == 0x5002) {
+                       ep_warn(ep->dev, "The dmastat return = %x!!\n",
+                              dmastat);
+                       writel(0x5a, &ep->dma->dmastat);
+               }
+
+               tmp = readl(&regs->pciirqenb0);
+               tmp &= ~BIT(ep_bit[ep->num]);
+               writel(tmp, &regs->pciirqenb0);
+       } else {
+               if (ep->num < 5) {
+                       tmp = readl(&regs->pciirqenb1);
+                       tmp &= ~BIT((8 + ep->num));     /* completion */
+                       writel(tmp, &regs->pciirqenb1);
+               }
+       }
+       writel(0, &ep->regs->ep_irqenb);
+
+       writel(BIT(SHORT_PACKET_OUT_DONE_INTERRUPT) |
+              BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT) |
+              BIT(FIFO_OVERFLOW) |
+              BIT(DATA_PACKET_RECEIVED_INTERRUPT) |
+              BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
+              BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
+              BIT(DATA_IN_TOKEN_INTERRUPT), &ep->regs->ep_stat);
+}
+
+static void nuke(struct net2280_ep *);
+
+static int net2280_disable(struct usb_ep *_ep)
+{
+       struct net2280_ep       *ep;
+       unsigned long           flags;
+
+       ep = container_of(_ep, struct net2280_ep, ep);
+       if (!_ep || !ep->desc || _ep->name == ep0name)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->dev->lock, flags);
+       nuke(ep);
+
+       if (ep->dev->quirks & PLX_SUPERSPEED)
+               ep_reset_338x(ep->dev->regs, ep);
+       else
+               ep_reset_228x(ep->dev->regs, ep);
+
+       ep_vdbg(ep->dev, "disabled %s %s\n",
+                       ep->dma ? "dma" : "pio", _ep->name);
+
+       /* synch memory views with the device */
+       (void)readl(&ep->cfg->ep_cfg);
+
+       if (use_dma && !ep->dma && ep->num >= 1 && ep->num <= 4)
+               ep->dma = &ep->dev->dma[ep->num - 1];
+
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_request
+*net2280_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct net2280_ep       *ep;
+       struct net2280_request  *req;
+
+       if (!_ep)
+               return NULL;
+       ep = container_of(_ep, struct net2280_ep, ep);
+
+       req = kzalloc(sizeof(*req), gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+
+       /* this dma descriptor may be swapped with the previous dummy */
+       if (ep->dma) {
+               struct net2280_dma      *td;
+
+               td = pci_pool_alloc(ep->dev->requests, gfp_flags,
+                               &req->td_dma);
+               if (!td) {
+                       kfree(req);
+                       return NULL;
+               }
+               td->dmacount = 0;       /* not VALID */
+               td->dmadesc = td->dmaaddr;
+               req->td = td;
+       }
+       return &req->req;
+}
+
+static void net2280_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct net2280_ep       *ep;
+       struct net2280_request  *req;
+
+       ep = container_of(_ep, struct net2280_ep, ep);
+       if (!_ep || !_req)
+               return;
+
+       req = container_of(_req, struct net2280_request, req);
+       WARN_ON(!list_empty(&req->queue));
+       if (req->td)
+               pci_pool_free(ep->dev->requests, req->td, req->td_dma);
+       kfree(req);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* load a packet into the fifo we use for usb IN transfers.
+ * works for all endpoints.
+ *
+ * NOTE: pio with ep-a..ep-d could stuff multiple packets into the fifo
+ * at a time, but this code is simpler because it knows it only writes
+ * one packet.  ep-a..ep-d should use dma instead.
+ */
+static void write_fifo(struct net2280_ep *ep, struct usb_request *req)
+{
+       struct net2280_ep_regs  __iomem *regs = ep->regs;
+       u8                      *buf;
+       u32                     tmp;
+       unsigned                count, total;
+
+       /* INVARIANT:  fifo is currently empty. (testable) */
+
+       if (req) {
+               buf = req->buf + req->actual;
+               prefetch(buf);
+               total = req->length - req->actual;
+       } else {
+               total = 0;
+               buf = NULL;
+       }
+
+       /* write just one packet at a time */
+       count = ep->ep.maxpacket;
+       if (count > total)      /* min() cannot be used on a bitfield */
+               count = total;
+
+       ep_vdbg(ep->dev, "write %s fifo (IN) %d bytes%s req %p\n",
+                       ep->ep.name, count,
+                       (count != ep->ep.maxpacket) ? " (short)" : "",
+                       req);
+       while (count >= 4) {
+               /* NOTE be careful if you try to align these. fifo lines
+                * should normally be full (4 bytes) and successive partial
+                * lines are ok only in certain cases.
+                */
+               tmp = get_unaligned((u32 *)buf);
+               cpu_to_le32s(&tmp);
+               writel(tmp, &regs->ep_data);
+               buf += 4;
+               count -= 4;
+       }
+
+       /* last fifo entry is "short" unless we wrote a full packet.
+        * also explicitly validate last word in (periodic) transfers
+        * when maxpacket is not a multiple of 4 bytes.
+        */
+       if (count || total < ep->ep.maxpacket) {
+               tmp = count ? get_unaligned((u32 *)buf) : count;
+               cpu_to_le32s(&tmp);
+               set_fifo_bytecount(ep, count & 0x03);
+               writel(tmp, &regs->ep_data);
+       }
+
+       /* pci writes may still be posted */
+}
+
+/* work around erratum 0106: PCI and USB race over the OUT fifo.
+ * caller guarantees chiprev 0100, out endpoint is NAKing, and
+ * there's no real data in the fifo.
+ *
+ * NOTE:  also used in cases where that erratum doesn't apply:
+ * where the host wrote "too much" data to us.
+ */
+static void out_flush(struct net2280_ep *ep)
+{
+       u32     __iomem *statp;
+       u32     tmp;
+
+       ASSERT_OUT_NAKING(ep);
+
+       statp = &ep->regs->ep_stat;
+       writel(BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
+               BIT(DATA_PACKET_RECEIVED_INTERRUPT),
+               statp);
+       writel(BIT(FIFO_FLUSH), statp);
+       /* Make sure that stap is written */
+       mb();
+       tmp = readl(statp);
+       if (tmp & BIT(DATA_OUT_PING_TOKEN_INTERRUPT) &&
+                       /* high speed did bulk NYET; fifo isn't filling */
+                       ep->dev->gadget.speed == USB_SPEED_FULL) {
+               unsigned        usec;
+
+               usec = 50;              /* 64 byte bulk/interrupt */
+               handshake(statp, BIT(USB_OUT_PING_NAK_SENT),
+                               BIT(USB_OUT_PING_NAK_SENT), usec);
+               /* NAK done; now CLEAR_NAK_OUT_PACKETS is safe */
+       }
+}
+
+/* unload packet(s) from the fifo we use for usb OUT transfers.
+ * returns true iff the request completed, because of short packet
+ * or the request buffer having filled with full packets.
+ *
+ * for ep-a..ep-d this will read multiple packets out when they
+ * have been accepted.
+ */
+static int read_fifo(struct net2280_ep *ep, struct net2280_request *req)
+{
+       struct net2280_ep_regs  __iomem *regs = ep->regs;
+       u8                      *buf = req->req.buf + req->req.actual;
+       unsigned                count, tmp, is_short;
+       unsigned                cleanup = 0, prevent = 0;
+
+       /* erratum 0106 ... packets coming in during fifo reads might
+        * be incompletely rejected.  not all cases have workarounds.
+        */
+       if (ep->dev->chiprev == 0x0100 &&
+                       ep->dev->gadget.speed == USB_SPEED_FULL) {
+               udelay(1);
+               tmp = readl(&ep->regs->ep_stat);
+               if ((tmp & BIT(NAK_OUT_PACKETS)))
+                       cleanup = 1;
+               else if ((tmp & BIT(FIFO_FULL))) {
+                       start_out_naking(ep);
+                       prevent = 1;
+               }
+               /* else: hope we don't see the problem */
+       }
+
+       /* never overflow the rx buffer. the fifo reads packets until
+        * it sees a short one; we might not be ready for them all.
+        */
+       prefetchw(buf);
+       count = readl(&regs->ep_avail);
+       if (unlikely(count == 0)) {
+               udelay(1);
+               tmp = readl(&ep->regs->ep_stat);
+               count = readl(&regs->ep_avail);
+               /* handled that data already? */
+               if (count == 0 && (tmp & BIT(NAK_OUT_PACKETS)) == 0)
+                       return 0;
+       }
+
+       tmp = req->req.length - req->req.actual;
+       if (count > tmp) {
+               /* as with DMA, data overflow gets flushed */
+               if ((tmp % ep->ep.maxpacket) != 0) {
+                       ep_err(ep->dev,
+                               "%s out fifo %d bytes, expected %d\n",
+                               ep->ep.name, count, tmp);
+                       req->req.status = -EOVERFLOW;
+                       cleanup = 1;
+                       /* NAK_OUT_PACKETS will be set, so flushing is safe;
+                        * the next read will start with the next packet
+                        */
+               } /* else it's a ZLP, no worries */
+               count = tmp;
+       }
+       req->req.actual += count;
+
+       is_short = (count == 0) || ((count % ep->ep.maxpacket) != 0);
+
+       ep_vdbg(ep->dev, "read %s fifo (OUT) %d bytes%s%s%s req %p %d/%d\n",
+                       ep->ep.name, count, is_short ? " (short)" : "",
+                       cleanup ? " flush" : "", prevent ? " nak" : "",
+                       req, req->req.actual, req->req.length);
+
+       while (count >= 4) {
+               tmp = readl(&regs->ep_data);
+               cpu_to_le32s(&tmp);
+               put_unaligned(tmp, (u32 *)buf);
+               buf += 4;
+               count -= 4;
+       }
+       if (count) {
+               tmp = readl(&regs->ep_data);
+               /* LE conversion is implicit here: */
+               do {
+                       *buf++ = (u8) tmp;
+                       tmp >>= 8;
+               } while (--count);
+       }
+       if (cleanup)
+               out_flush(ep);
+       if (prevent) {
+               writel(BIT(CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
+               (void) readl(&ep->regs->ep_rsp);
+       }
+
+       return is_short || ((req->req.actual == req->req.length) &&
+                       !req->req.zero);
+}
+
+/* fill out dma descriptor to match a given request */
+static void fill_dma_desc(struct net2280_ep *ep,
+                                       struct net2280_request *req, int valid)
+{
+       struct net2280_dma      *td = req->td;
+       u32                     dmacount = req->req.length;
+
+       /* don't let DMA continue after a short OUT packet,
+        * so overruns can't affect the next transfer.
+        * in case of overruns on max-size packets, we can't
+        * stop the fifo from filling but we can flush it.
+        */
+       if (ep->is_in)
+               dmacount |= BIT(DMA_DIRECTION);
+       if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) ||
+                                       !(ep->dev->quirks & PLX_2280))
+               dmacount |= BIT(END_OF_CHAIN);
+
+       req->valid = valid;
+       if (valid)
+               dmacount |= BIT(VALID_BIT);
+       if (likely(!req->req.no_interrupt || !use_dma_chaining))
+               dmacount |= BIT(DMA_DONE_INTERRUPT_ENABLE);
+
+       /* td->dmadesc = previously set by caller */
+       td->dmaaddr = cpu_to_le32 (req->req.dma);
+
+       /* 2280 may be polling VALID_BIT through ep->dma->dmadesc */
+       wmb();
+       td->dmacount = cpu_to_le32(dmacount);
+}
+
+static const u32 dmactl_default =
+               BIT(DMA_SCATTER_GATHER_DONE_INTERRUPT) |
+               BIT(DMA_CLEAR_COUNT_ENABLE) |
+               /* erratum 0116 workaround part 1 (use POLLING) */
+               (POLL_100_USEC << DESCRIPTOR_POLLING_RATE) |
+               BIT(DMA_VALID_BIT_POLLING_ENABLE) |
+               BIT(DMA_VALID_BIT_ENABLE) |
+               BIT(DMA_SCATTER_GATHER_ENABLE) |
+               /* erratum 0116 workaround part 2 (no AUTOSTART) */
+               BIT(DMA_ENABLE);
+
+static inline void spin_stop_dma(struct net2280_dma_regs __iomem *dma)
+{
+       handshake(&dma->dmactl, BIT(DMA_ENABLE), 0, 50);
+}
+
+static inline void stop_dma(struct net2280_dma_regs __iomem *dma)
+{
+       writel(readl(&dma->dmactl) & ~BIT(DMA_ENABLE), &dma->dmactl);
+       spin_stop_dma(dma);
+}
+
+static void start_queue(struct net2280_ep *ep, u32 dmactl, u32 td_dma)
+{
+       struct net2280_dma_regs __iomem *dma = ep->dma;
+       unsigned int tmp = BIT(VALID_BIT) | (ep->is_in << DMA_DIRECTION);
+
+       if (!(ep->dev->quirks & PLX_2280))
+               tmp |= BIT(END_OF_CHAIN);
+
+       writel(tmp, &dma->dmacount);
+       writel(readl(&dma->dmastat), &dma->dmastat);
+
+       writel(td_dma, &dma->dmadesc);
+       if (ep->dev->quirks & PLX_SUPERSPEED)
+               dmactl |= BIT(DMA_REQUEST_OUTSTANDING);
+       writel(dmactl, &dma->dmactl);
+
+       /* erratum 0116 workaround part 3:  pci arbiter away from net2280 */
+       (void) readl(&ep->dev->pci->pcimstctl);
+
+       writel(BIT(DMA_START), &dma->dmastat);
+
+       if (!ep->is_in)
+               stop_out_naking(ep);
+}
+
+static void start_dma(struct net2280_ep *ep, struct net2280_request *req)
+{
+       u32                     tmp;
+       struct net2280_dma_regs __iomem *dma = ep->dma;
+
+       /* FIXME can't use DMA for ZLPs */
+
+       /* on this path we "know" there's no dma active (yet) */
+       WARN_ON(readl(&dma->dmactl) & BIT(DMA_ENABLE));
+       writel(0, &ep->dma->dmactl);
+
+       /* previous OUT packet might have been short */
+       if (!ep->is_in && (readl(&ep->regs->ep_stat) &
+                               BIT(NAK_OUT_PACKETS))) {
+               writel(BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT),
+                       &ep->regs->ep_stat);
+
+               tmp = readl(&ep->regs->ep_avail);
+               if (tmp) {
+                       writel(readl(&dma->dmastat), &dma->dmastat);
+
+                       /* transfer all/some fifo data */
+                       writel(req->req.dma, &dma->dmaaddr);
+                       tmp = min(tmp, req->req.length);
+
+                       /* dma irq, faking scatterlist status */
+                       req->td->dmacount = cpu_to_le32(req->req.length - tmp);
+                       writel(BIT(DMA_DONE_INTERRUPT_ENABLE) | tmp,
+                                       &dma->dmacount);
+                       req->td->dmadesc = 0;
+                       req->valid = 1;
+
+                       writel(BIT(DMA_ENABLE), &dma->dmactl);
+                       writel(BIT(DMA_START), &dma->dmastat);
+                       return;
+               }
+       }
+
+       tmp = dmactl_default;
+
+       /* force packet boundaries between dma requests, but prevent the
+        * controller from automagically writing a last "short" packet
+        * (zero length) unless the driver explicitly said to do that.
+        */
+       if (ep->is_in) {
+               if (likely((req->req.length % ep->ep.maxpacket) ||
+                                                       req->req.zero)){
+                       tmp |= BIT(DMA_FIFO_VALIDATE);
+                       ep->in_fifo_validate = 1;
+               } else
+                       ep->in_fifo_validate = 0;
+       }
+
+       /* init req->td, pointing to the current dummy */
+       req->td->dmadesc = cpu_to_le32 (ep->td_dma);
+       fill_dma_desc(ep, req, 1);
+
+       if (!use_dma_chaining)
+               req->td->dmacount |= cpu_to_le32(BIT(END_OF_CHAIN));
+
+       start_queue(ep, tmp, req->td_dma);
+}
+
+static inline void resume_dma(struct net2280_ep *ep)
+{
+       writel(readl(&ep->dma->dmactl) | BIT(DMA_ENABLE), &ep->dma->dmactl);
+
+       ep->dma_started = true;
+}
+
+static inline void ep_stop_dma(struct net2280_ep *ep)
+{
+       writel(readl(&ep->dma->dmactl) & ~BIT(DMA_ENABLE), &ep->dma->dmactl);
+       spin_stop_dma(ep->dma);
+
+       ep->dma_started = false;
+}
+
+static inline void
+queue_dma(struct net2280_ep *ep, struct net2280_request *req, int valid)
+{
+       struct net2280_dma      *end;
+       dma_addr_t              tmp;
+
+       /* swap new dummy for old, link; fill and maybe activate */
+       end = ep->dummy;
+       ep->dummy = req->td;
+       req->td = end;
+
+       tmp = ep->td_dma;
+       ep->td_dma = req->td_dma;
+       req->td_dma = tmp;
+
+       end->dmadesc = cpu_to_le32 (ep->td_dma);
+
+       fill_dma_desc(ep, req, valid);
+}
+
+static void
+done(struct net2280_ep *ep, struct net2280_request *req, int status)
+{
+       struct net2280          *dev;
+       unsigned                stopped = ep->stopped;
+
+       list_del_init(&req->queue);
+
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       dev = ep->dev;
+       if (ep->dma)
+               usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
+
+       if (status && status != -ESHUTDOWN)
+               ep_vdbg(dev, "complete %s req %p stat %d len %u/%u\n",
+                       ep->ep.name, &req->req, status,
+                       req->req.actual, req->req.length);
+
+       /* don't modify queue heads during completion callback */
+       ep->stopped = 1;
+       spin_unlock(&dev->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&dev->lock);
+       ep->stopped = stopped;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+net2280_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+       struct net2280_request  *req;
+       struct net2280_ep       *ep;
+       struct net2280          *dev;
+       unsigned long           flags;
+
+       /* we always require a cpu-view buffer, so that we can
+        * always use pio (as fallback or whatever).
+        */
+       req = container_of(_req, struct net2280_request, req);
+       if (!_req || !_req->complete || !_req->buf ||
+                               !list_empty(&req->queue))
+               return -EINVAL;
+       if (_req->length > (~0 & DMA_BYTE_COUNT_MASK))
+               return -EDOM;
+       ep = container_of(_ep, struct net2280_ep, ep);
+       if (!_ep || (!ep->desc && ep->num != 0))
+               return -EINVAL;
+       dev = ep->dev;
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       /* FIXME implement PIO fallback for ZLPs with DMA */
+       if (ep->dma && _req->length == 0)
+               return -EOPNOTSUPP;
+
+       /* set up dma mapping in case the caller didn't */
+       if (ep->dma) {
+               int ret;
+
+               ret = usb_gadget_map_request(&dev->gadget, _req,
+                               ep->is_in);
+               if (ret)
+                       return ret;
+       }
+
+#if 0
+       ep_vdbg(dev, "%s queue req %p, len %d buf %p\n",
+                       _ep->name, _req, _req->length, _req->buf);
+#endif
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       /* kickstart this i/o queue? */
+       if (list_empty(&ep->queue) && !ep->stopped) {
+               /* DMA request while EP halted */
+               if (ep->dma &&
+                   (readl(&ep->regs->ep_rsp) & BIT(CLEAR_ENDPOINT_HALT)) &&
+                       (dev->quirks & PLX_SUPERSPEED)) {
+                       int valid = 1;
+                       if (ep->is_in) {
+                               int expect;
+                               expect = likely(req->req.zero ||
+                                               ((req->req.length %
+                                                 ep->ep.maxpacket) != 0));
+                               if (expect != ep->in_fifo_validate)
+                                       valid = 0;
+                       }
+                       queue_dma(ep, req, valid);
+               }
+               /* use DMA if the endpoint supports it, else pio */
+               else if (ep->dma)
+                       start_dma(ep, req);
+               else {
+                       /* maybe there's no control data, just status ack */
+                       if (ep->num == 0 && _req->length == 0) {
+                               allow_status(ep);
+                               done(ep, req, 0);
+                               ep_vdbg(dev, "%s status ack\n", ep->ep.name);
+                               goto done;
+                       }
+
+                       /* PIO ... stuff the fifo, or unblock it.  */
+                       if (ep->is_in)
+                               write_fifo(ep, _req);
+                       else if (list_empty(&ep->queue)) {
+                               u32     s;
+
+                               /* OUT FIFO might have packet(s) buffered */
+                               s = readl(&ep->regs->ep_stat);
+                               if ((s & BIT(FIFO_EMPTY)) == 0) {
+                                       /* note:  _req->short_not_ok is
+                                        * ignored here since PIO _always_
+                                        * stops queue advance here, and
+                                        * _req->status doesn't change for
+                                        * short reads (only _req->actual)
+                                        */
+                                       if (read_fifo(ep, req) &&
+                                                       ep->num == 0) {
+                                               done(ep, req, 0);
+                                               allow_status(ep);
+                                               /* don't queue it */
+                                               req = NULL;
+                                       } else if (read_fifo(ep, req) &&
+                                                       ep->num != 0) {
+                                               done(ep, req, 0);
+                                               req = NULL;
+                                       } else
+                                               s = readl(&ep->regs->ep_stat);
+                               }
+
+                               /* don't NAK, let the fifo fill */
+                               if (req && (s & BIT(NAK_OUT_PACKETS)))
+                                       writel(BIT(CLEAR_NAK_OUT_PACKETS),
+                                                       &ep->regs->ep_rsp);
+                       }
+               }
+
+       } else if (ep->dma) {
+               int     valid = 1;
+
+               if (ep->is_in) {
+                       int     expect;
+
+                       /* preventing magic zlps is per-engine state, not
+                        * per-transfer; irq logic must recover hiccups.
+                        */
+                       expect = likely(req->req.zero ||
+                               (req->req.length % ep->ep.maxpacket));
+                       if (expect != ep->in_fifo_validate)
+                               valid = 0;
+               }
+               queue_dma(ep, req, valid);
+
+       } /* else the irq handler advances the queue. */
+
+       ep->responded = 1;
+       if (req)
+               list_add_tail(&req->queue, &ep->queue);
+done:
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       /* pci writes may still be posted */
+       return 0;
+}
+
+static inline void
+dma_done(struct net2280_ep *ep,        struct net2280_request *req, u32 dmacount,
+               int status)
+{
+       req->req.actual = req->req.length - (DMA_BYTE_COUNT_MASK & dmacount);
+       done(ep, req, status);
+}
+
+static void restart_dma(struct net2280_ep *ep);
+
+static void scan_dma_completions(struct net2280_ep *ep)
+{
+       /* only look at descriptors that were "naturally" retired,
+        * so fifo and list head state won't matter
+        */
+       while (!list_empty(&ep->queue)) {
+               struct net2280_request  *req;
+               u32                     tmp;
+
+               req = list_entry(ep->queue.next,
+                               struct net2280_request, queue);
+               if (!req->valid)
+                       break;
+               rmb();
+               tmp = le32_to_cpup(&req->td->dmacount);
+               if ((tmp & BIT(VALID_BIT)) != 0)
+                       break;
+
+               /* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short"
+                * cases where DMA must be aborted; this code handles
+                * all non-abort DMA completions.
+                */
+               if (unlikely(req->td->dmadesc == 0)) {
+                       /* paranoia */
+                       tmp = readl(&ep->dma->dmacount);
+                       if (tmp & DMA_BYTE_COUNT_MASK)
+                               break;
+                       /* single transfer mode */
+                       dma_done(ep, req, tmp, 0);
+                       break;
+               } else if (!ep->is_in &&
+                               (req->req.length % ep->ep.maxpacket) != 0) {
+                       tmp = readl(&ep->regs->ep_stat);
+                       if (ep->dev->quirks & PLX_SUPERSPEED)
+                               return dma_done(ep, req, tmp, 0);
+
+                       /* AVOID TROUBLE HERE by not issuing short reads from
+                        * your gadget driver.  That helps avoids errata 0121,
+                        * 0122, and 0124; not all cases trigger the warning.
+                        */
+                       if ((tmp & BIT(NAK_OUT_PACKETS)) == 0) {
+                               ep_warn(ep->dev, "%s lost packet sync!\n",
+                                               ep->ep.name);
+                               req->req.status = -EOVERFLOW;
+                       } else {
+                               tmp = readl(&ep->regs->ep_avail);
+                               if (tmp) {
+                                       /* fifo gets flushed later */
+                                       ep->out_overflow = 1;
+                                       ep_dbg(ep->dev,
+                                               "%s dma, discard %d len %d\n",
+                                               ep->ep.name, tmp,
+                                               req->req.length);
+                                       req->req.status = -EOVERFLOW;
+                               }
+                       }
+               }
+               dma_done(ep, req, tmp, 0);
+       }
+}
+
+static void restart_dma(struct net2280_ep *ep)
+{
+       struct net2280_request  *req;
+       u32                     dmactl = dmactl_default;
+
+       if (ep->stopped)
+               return;
+       req = list_entry(ep->queue.next, struct net2280_request, queue);
+
+       if (!use_dma_chaining) {
+               start_dma(ep, req);
+               return;
+       }
+
+       /* the 2280 will be processing the queue unless queue hiccups after
+        * the previous transfer:
+        *  IN:   wanted automagic zlp, head doesn't (or vice versa)
+        *        DMA_FIFO_VALIDATE doesn't init from dma descriptors.
+        *  OUT:  was "usb-short", we must restart.
+        */
+       if (ep->is_in && !req->valid) {
+               struct net2280_request  *entry, *prev = NULL;
+               int                     reqmode, done = 0;
+
+               ep_dbg(ep->dev, "%s dma hiccup td %p\n", ep->ep.name, req->td);
+               ep->in_fifo_validate = likely(req->req.zero ||
+                               (req->req.length % ep->ep.maxpacket) != 0);
+               if (ep->in_fifo_validate)
+                       dmactl |= BIT(DMA_FIFO_VALIDATE);
+               list_for_each_entry(entry, &ep->queue, queue) {
+                       __le32          dmacount;
+
+                       if (entry == req)
+                               continue;
+                       dmacount = entry->td->dmacount;
+                       if (!done) {
+                               reqmode = likely(entry->req.zero ||
+                                  (entry->req.length % ep->ep.maxpacket));
+                               if (reqmode == ep->in_fifo_validate) {
+                                       entry->valid = 1;
+                                       dmacount |= valid_bit;
+                                       entry->td->dmacount = dmacount;
+                                       prev = entry;
+                                       continue;
+                               } else {
+                                       /* force a hiccup */
+                                       prev->td->dmacount |= dma_done_ie;
+                                       done = 1;
+                               }
+                       }
+
+                       /* walk the rest of the queue so unlinks behave */
+                       entry->valid = 0;
+                       dmacount &= ~valid_bit;
+                       entry->td->dmacount = dmacount;
+                       prev = entry;
+               }
+       }
+
+       writel(0, &ep->dma->dmactl);
+       start_queue(ep, dmactl, req->td_dma);
+}
+
+static void abort_dma_228x(struct net2280_ep *ep)
+{
+       /* abort the current transfer */
+       if (likely(!list_empty(&ep->queue))) {
+               /* FIXME work around errata 0121, 0122, 0124 */
+               writel(BIT(DMA_ABORT), &ep->dma->dmastat);
+               spin_stop_dma(ep->dma);
+       } else
+               stop_dma(ep->dma);
+       scan_dma_completions(ep);
+}
+
+static void abort_dma_338x(struct net2280_ep *ep)
+{
+       writel(BIT(DMA_ABORT), &ep->dma->dmastat);
+       spin_stop_dma(ep->dma);
+}
+
+static void abort_dma(struct net2280_ep *ep)
+{
+       if (ep->dev->quirks & PLX_LEGACY)
+               return abort_dma_228x(ep);
+       return abort_dma_338x(ep);
+}
+
+/* dequeue ALL requests */
+static void nuke(struct net2280_ep *ep)
+{
+       struct net2280_request  *req;
+
+       /* called with spinlock held */
+       ep->stopped = 1;
+       if (ep->dma)
+               abort_dma(ep);
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next,
+                               struct net2280_request,
+                               queue);
+               done(ep, req, -ESHUTDOWN);
+       }
+}
+
+/* dequeue JUST ONE request */
+static int net2280_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct net2280_ep       *ep;
+       struct net2280_request  *req;
+       unsigned long           flags;
+       u32                     dmactl;
+       int                     stopped;
+
+       ep = container_of(_ep, struct net2280_ep, ep);
+       if (!_ep || (!ep->desc && ep->num != 0) || !_req)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->dev->lock, flags);
+       stopped = ep->stopped;
+
+       /* quiesce dma while we patch the queue */
+       dmactl = 0;
+       ep->stopped = 1;
+       if (ep->dma) {
+               dmactl = readl(&ep->dma->dmactl);
+               /* WARNING erratum 0127 may kick in ... */
+               stop_dma(ep->dma);
+               scan_dma_completions(ep);
+       }
+
+       /* make sure it's still queued on this endpoint */
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req) {
+               spin_unlock_irqrestore(&ep->dev->lock, flags);
+               return -EINVAL;
+       }
+
+       /* queue head may be partially complete. */
+       if (ep->queue.next == &req->queue) {
+               if (ep->dma) {
+                       ep_dbg(ep->dev, "unlink (%s) dma\n", _ep->name);
+                       _req->status = -ECONNRESET;
+                       abort_dma(ep);
+                       if (likely(ep->queue.next == &req->queue)) {
+                               /* NOTE: misreports single-transfer mode*/
+                               req->td->dmacount = 0;  /* invalidate */
+                               dma_done(ep, req,
+                                       readl(&ep->dma->dmacount),
+                                       -ECONNRESET);
+                       }
+               } else {
+                       ep_dbg(ep->dev, "unlink (%s) pio\n", _ep->name);
+                       done(ep, req, -ECONNRESET);
+               }
+               req = NULL;
+
+       /* patch up hardware chaining data */
+       } else if (ep->dma && use_dma_chaining) {
+               if (req->queue.prev == ep->queue.next) {
+                       writel(le32_to_cpu(req->td->dmadesc),
+                               &ep->dma->dmadesc);
+                       if (req->td->dmacount & dma_done_ie)
+                               writel(readl(&ep->dma->dmacount) |
+                                               le32_to_cpu(dma_done_ie),
+                                       &ep->dma->dmacount);
+               } else {
+                       struct net2280_request  *prev;
+
+                       prev = list_entry(req->queue.prev,
+                               struct net2280_request, queue);
+                       prev->td->dmadesc = req->td->dmadesc;
+                       if (req->td->dmacount & dma_done_ie)
+                               prev->td->dmacount |= dma_done_ie;
+               }
+       }
+
+       if (req)
+               done(ep, req, -ECONNRESET);
+       ep->stopped = stopped;
+
+       if (ep->dma) {
+               /* turn off dma on inactive queues */
+               if (list_empty(&ep->queue))
+                       stop_dma(ep->dma);
+               else if (!ep->stopped) {
+                       /* resume current request, or start new one */
+                       if (req)
+                               writel(dmactl, &ep->dma->dmactl);
+                       else
+                               start_dma(ep, list_entry(ep->queue.next,
+                                       struct net2280_request, queue));
+               }
+       }
+
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int net2280_fifo_status(struct usb_ep *_ep);
+
+static int
+net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
+{
+       struct net2280_ep       *ep;
+       unsigned long           flags;
+       int                     retval = 0;
+
+       ep = container_of(_ep, struct net2280_ep, ep);
+       if (!_ep || (!ep->desc && ep->num != 0))
+               return -EINVAL;
+       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+       if (ep->desc /* not ep0 */ && (ep->desc->bmAttributes & 0x03)
+                                               == USB_ENDPOINT_XFER_ISOC)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->dev->lock, flags);
+       if (!list_empty(&ep->queue))
+               retval = -EAGAIN;
+       else if (ep->is_in && value && net2280_fifo_status(_ep) != 0)
+               retval = -EAGAIN;
+       else {
+               ep_vdbg(ep->dev, "%s %s %s\n", _ep->name,
+                               value ? "set" : "clear",
+                               wedged ? "wedge" : "halt");
+               /* set/clear, then synch memory views with the device */
+               if (value) {
+                       if (ep->num == 0)
+                               ep->dev->protocol_stall = 1;
+                       else
+                               set_halt(ep);
+                       if (wedged)
+                               ep->wedged = 1;
+               } else {
+                       clear_halt(ep);
+                       if (ep->dev->quirks & PLX_SUPERSPEED &&
+                               !list_empty(&ep->queue) && ep->td_dma)
+                                       restart_dma(ep);
+                       ep->wedged = 0;
+               }
+               (void) readl(&ep->regs->ep_rsp);
+       }
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+
+       return retval;
+}
+
+static int net2280_set_halt(struct usb_ep *_ep, int value)
+{
+       return net2280_set_halt_and_wedge(_ep, value, 0);
+}
+
+static int net2280_set_wedge(struct usb_ep *_ep)
+{
+       if (!_ep || _ep->name == ep0name)
+               return -EINVAL;
+       return net2280_set_halt_and_wedge(_ep, 1, 1);
+}
+
+static int net2280_fifo_status(struct usb_ep *_ep)
+{
+       struct net2280_ep       *ep;
+       u32                     avail;
+
+       ep = container_of(_ep, struct net2280_ep, ep);
+       if (!_ep || (!ep->desc && ep->num != 0))
+               return -ENODEV;
+       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       avail = readl(&ep->regs->ep_avail) & (BIT(12) - 1);
+       if (avail > ep->fifo_size)
+               return -EOVERFLOW;
+       if (ep->is_in)
+               avail = ep->fifo_size - avail;
+       return avail;
+}
+
+static void net2280_fifo_flush(struct usb_ep *_ep)
+{
+       struct net2280_ep       *ep;
+
+       ep = container_of(_ep, struct net2280_ep, ep);
+       if (!_ep || (!ep->desc && ep->num != 0))
+               return;
+       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return;
+
+       writel(BIT(FIFO_FLUSH), &ep->regs->ep_stat);
+       (void) readl(&ep->regs->ep_rsp);
+}
+
+static const struct usb_ep_ops net2280_ep_ops = {
+       .enable         = net2280_enable,
+       .disable        = net2280_disable,
+
+       .alloc_request  = net2280_alloc_request,
+       .free_request   = net2280_free_request,
+
+       .queue          = net2280_queue,
+       .dequeue        = net2280_dequeue,
+
+       .set_halt       = net2280_set_halt,
+       .set_wedge      = net2280_set_wedge,
+       .fifo_status    = net2280_fifo_status,
+       .fifo_flush     = net2280_fifo_flush,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int net2280_get_frame(struct usb_gadget *_gadget)
+{
+       struct net2280          *dev;
+       unsigned long           flags;
+       u16                     retval;
+
+       if (!_gadget)
+               return -ENODEV;
+       dev = container_of(_gadget, struct net2280, gadget);
+       spin_lock_irqsave(&dev->lock, flags);
+       retval = get_idx_reg(dev->regs, REG_FRAME) & 0x03ff;
+       spin_unlock_irqrestore(&dev->lock, flags);
+       return retval;
+}
+
+static int net2280_wakeup(struct usb_gadget *_gadget)
+{
+       struct net2280          *dev;
+       u32                     tmp;
+       unsigned long           flags;
+
+       if (!_gadget)
+               return 0;
+       dev = container_of(_gadget, struct net2280, gadget);
+
+       spin_lock_irqsave(&dev->lock, flags);
+       tmp = readl(&dev->usb->usbctl);
+       if (tmp & BIT(DEVICE_REMOTE_WAKEUP_ENABLE))
+               writel(BIT(GENERATE_RESUME), &dev->usb->usbstat);
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       /* pci writes may still be posted */
+       return 0;
+}
+
+static int net2280_set_selfpowered(struct usb_gadget *_gadget, int value)
+{
+       struct net2280          *dev;
+       u32                     tmp;
+       unsigned long           flags;
+
+       if (!_gadget)
+               return 0;
+       dev = container_of(_gadget, struct net2280, gadget);
+
+       spin_lock_irqsave(&dev->lock, flags);
+       tmp = readl(&dev->usb->usbctl);
+       if (value) {
+               tmp |= BIT(SELF_POWERED_STATUS);
+               dev->selfpowered = 1;
+       } else {
+               tmp &= ~BIT(SELF_POWERED_STATUS);
+               dev->selfpowered = 0;
+       }
+       writel(tmp, &dev->usb->usbctl);
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return 0;
+}
+
+static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
+{
+       struct net2280  *dev;
+       u32             tmp;
+       unsigned long   flags;
+
+       if (!_gadget)
+               return -ENODEV;
+       dev = container_of(_gadget, struct net2280, gadget);
+
+       spin_lock_irqsave(&dev->lock, flags);
+       tmp = readl(&dev->usb->usbctl);
+       dev->softconnect = (is_on != 0);
+       if (is_on)
+               tmp |= BIT(USB_DETECT_ENABLE);
+       else
+               tmp &= ~BIT(USB_DETECT_ENABLE);
+       writel(tmp, &dev->usb->usbctl);
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return 0;
+}
+
+static int net2280_start(struct usb_gadget *_gadget,
+               struct usb_gadget_driver *driver);
+static int net2280_stop(struct usb_gadget *_gadget,
+               struct usb_gadget_driver *driver);
+
+static const struct usb_gadget_ops net2280_ops = {
+       .get_frame      = net2280_get_frame,
+       .wakeup         = net2280_wakeup,
+       .set_selfpowered = net2280_set_selfpowered,
+       .pullup         = net2280_pullup,
+       .udc_start      = net2280_start,
+       .udc_stop       = net2280_stop,
+};
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+/* FIXME move these into procfs, and use seq_file.
+ * Sysfs _still_ doesn't behave for arbitrarily sized files,
+ * and also doesn't help products using this with 2.4 kernels.
+ */
+
+/* "function" sysfs attribute */
+static ssize_t function_show(struct device *_dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct net2280  *dev = dev_get_drvdata(_dev);
+
+       if (!dev->driver || !dev->driver->function ||
+                       strlen(dev->driver->function) > PAGE_SIZE)
+               return 0;
+       return scnprintf(buf, PAGE_SIZE, "%s\n", dev->driver->function);
+}
+static DEVICE_ATTR_RO(function);
+
+static ssize_t registers_show(struct device *_dev,
+                             struct device_attribute *attr, char *buf)
+{
+       struct net2280          *dev;
+       char                    *next;
+       unsigned                size, t;
+       unsigned long           flags;
+       int                     i;
+       u32                     t1, t2;
+       const char              *s;
+
+       dev = dev_get_drvdata(_dev);
+       next = buf;
+       size = PAGE_SIZE;
+       spin_lock_irqsave(&dev->lock, flags);
+
+       if (dev->driver)
+               s = dev->driver->driver.name;
+       else
+               s = "(none)";
+
+       /* Main Control Registers */
+       t = scnprintf(next, size, "%s version " DRIVER_VERSION
+                       ", chiprev %04x, dma %s\n\n"
+                       "devinit %03x fifoctl %08x gadget '%s'\n"
+                       "pci irqenb0 %02x irqenb1 %08x "
+                       "irqstat0 %04x irqstat1 %08x\n",
+                       driver_name, dev->chiprev,
+                       use_dma
+                               ? (use_dma_chaining ? "chaining" : "enabled")
+                               : "disabled",
+                       readl(&dev->regs->devinit),
+                       readl(&dev->regs->fifoctl),
+                       s,
+                       readl(&dev->regs->pciirqenb0),
+                       readl(&dev->regs->pciirqenb1),
+                       readl(&dev->regs->irqstat0),
+                       readl(&dev->regs->irqstat1));
+       size -= t;
+       next += t;
+
+       /* USB Control Registers */
+       t1 = readl(&dev->usb->usbctl);
+       t2 = readl(&dev->usb->usbstat);
+       if (t1 & BIT(VBUS_PIN)) {
+               if (t2 & BIT(HIGH_SPEED))
+                       s = "high speed";
+               else if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+                       s = "powered";
+               else
+                       s = "full speed";
+               /* full speed bit (6) not working?? */
+       } else
+                       s = "not attached";
+       t = scnprintf(next, size,
+                       "stdrsp %08x usbctl %08x usbstat %08x "
+                               "addr 0x%02x (%s)\n",
+                       readl(&dev->usb->stdrsp), t1, t2,
+                       readl(&dev->usb->ouraddr), s);
+       size -= t;
+       next += t;
+
+       /* PCI Master Control Registers */
+
+       /* DMA Control Registers */
+
+       /* Configurable EP Control Registers */
+       for (i = 0; i < dev->n_ep; i++) {
+               struct net2280_ep       *ep;
+
+               ep = &dev->ep[i];
+               if (i && !ep->desc)
+                       continue;
+
+               t1 = readl(&ep->cfg->ep_cfg);
+               t2 = readl(&ep->regs->ep_rsp) & 0xff;
+               t = scnprintf(next, size,
+                               "\n%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s"
+                                       "irqenb %02x\n",
+                               ep->ep.name, t1, t2,
+                               (t2 & BIT(CLEAR_NAK_OUT_PACKETS))
+                                       ? "NAK " : "",
+                               (t2 & BIT(CLEAR_EP_HIDE_STATUS_PHASE))
+                                       ? "hide " : "",
+                               (t2 & BIT(CLEAR_EP_FORCE_CRC_ERROR))
+                                       ? "CRC " : "",
+                               (t2 & BIT(CLEAR_INTERRUPT_MODE))
+                                       ? "interrupt " : "",
+                               (t2 & BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE))
+                                       ? "status " : "",
+                               (t2 & BIT(CLEAR_NAK_OUT_PACKETS_MODE))
+                                       ? "NAKmode " : "",
+                               (t2 & BIT(CLEAR_ENDPOINT_TOGGLE))
+                                       ? "DATA1 " : "DATA0 ",
+                               (t2 & BIT(CLEAR_ENDPOINT_HALT))
+                                       ? "HALT " : "",
+                               readl(&ep->regs->ep_irqenb));
+               size -= t;
+               next += t;
+
+               t = scnprintf(next, size,
+                               "\tstat %08x avail %04x "
+                               "(ep%d%s-%s)%s\n",
+                               readl(&ep->regs->ep_stat),
+                               readl(&ep->regs->ep_avail),
+                               t1 & 0x0f, DIR_STRING(t1),
+                               type_string(t1 >> 8),
+                               ep->stopped ? "*" : "");
+               size -= t;
+               next += t;
+
+               if (!ep->dma)
+                       continue;
+
+               t = scnprintf(next, size,
+                               "  dma\tctl %08x stat %08x count %08x\n"
+                               "\taddr %08x desc %08x\n",
+                               readl(&ep->dma->dmactl),
+                               readl(&ep->dma->dmastat),
+                               readl(&ep->dma->dmacount),
+                               readl(&ep->dma->dmaaddr),
+                               readl(&ep->dma->dmadesc));
+               size -= t;
+               next += t;
+
+       }
+
+       /* Indexed Registers (none yet) */
+
+       /* Statistics */
+       t = scnprintf(next, size, "\nirqs:  ");
+       size -= t;
+       next += t;
+       for (i = 0; i < dev->n_ep; i++) {
+               struct net2280_ep       *ep;
+
+               ep = &dev->ep[i];
+               if (i && !ep->irqs)
+                       continue;
+               t = scnprintf(next, size, " %s/%lu", ep->ep.name, ep->irqs);
+               size -= t;
+               next += t;
+
+       }
+       t = scnprintf(next, size, "\n");
+       size -= t;
+       next += t;
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return PAGE_SIZE - size;
+}
+static DEVICE_ATTR_RO(registers);
+
+static ssize_t queues_show(struct device *_dev, struct device_attribute *attr,
+                          char *buf)
+{
+       struct net2280          *dev;
+       char                    *next;
+       unsigned                size;
+       unsigned long           flags;
+       int                     i;
+
+       dev = dev_get_drvdata(_dev);
+       next = buf;
+       size = PAGE_SIZE;
+       spin_lock_irqsave(&dev->lock, flags);
+
+       for (i = 0; i < dev->n_ep; i++) {
+               struct net2280_ep               *ep = &dev->ep[i];
+               struct net2280_request          *req;
+               int                             t;
+
+               if (i != 0) {
+                       const struct usb_endpoint_descriptor    *d;
+
+                       d = ep->desc;
+                       if (!d)
+                               continue;
+                       t = d->bEndpointAddress;
+                       t = scnprintf(next, size,
+                               "\n%s (ep%d%s-%s) max %04x %s fifo %d\n",
+                               ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK,
+                               (t & USB_DIR_IN) ? "in" : "out",
+                               type_string(d->bmAttributes),
+                               usb_endpoint_maxp(d) & 0x1fff,
+                               ep->dma ? "dma" : "pio", ep->fifo_size
+                               );
+               } else /* ep0 should only have one transfer queued */
+                       t = scnprintf(next, size, "ep0 max 64 pio %s\n",
+                                       ep->is_in ? "in" : "out");
+               if (t <= 0 || t > size)
+                       goto done;
+               size -= t;
+               next += t;
+
+               if (list_empty(&ep->queue)) {
+                       t = scnprintf(next, size, "\t(nothing queued)\n");
+                       if (t <= 0 || t > size)
+                               goto done;
+                       size -= t;
+                       next += t;
+                       continue;
+               }
+               list_for_each_entry(req, &ep->queue, queue) {
+                       if (ep->dma && req->td_dma == readl(&ep->dma->dmadesc))
+                               t = scnprintf(next, size,
+                                       "\treq %p len %d/%d "
+                                       "buf %p (dmacount %08x)\n",
+                                       &req->req, req->req.actual,
+                                       req->req.length, req->req.buf,
+                                       readl(&ep->dma->dmacount));
+                       else
+                               t = scnprintf(next, size,
+                                       "\treq %p len %d/%d buf %p\n",
+                                       &req->req, req->req.actual,
+                                       req->req.length, req->req.buf);
+                       if (t <= 0 || t > size)
+                               goto done;
+                       size -= t;
+                       next += t;
+
+                       if (ep->dma) {
+                               struct net2280_dma      *td;
+
+                               td = req->td;
+                               t = scnprintf(next, size, "\t    td %08x "
+                                       " count %08x buf %08x desc %08x\n",
+                                       (u32) req->td_dma,
+                                       le32_to_cpu(td->dmacount),
+                                       le32_to_cpu(td->dmaaddr),
+                                       le32_to_cpu(td->dmadesc));
+                               if (t <= 0 || t > size)
+                                       goto done;
+                               size -= t;
+                               next += t;
+                       }
+               }
+       }
+
+done:
+       spin_unlock_irqrestore(&dev->lock, flags);
+       return PAGE_SIZE - size;
+}
+static DEVICE_ATTR_RO(queues);
+
+
+#else
+
+#define device_create_file(a, b)       (0)
+#define device_remove_file(a, b)       do { } while (0)
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* another driver-specific mode might be a request type doing dma
+ * to/from another device fifo instead of to/from memory.
+ */
+
+static void set_fifo_mode(struct net2280 *dev, int mode)
+{
+       /* keeping high bits preserves BAR2 */
+       writel((0xffff << PCI_BASE2_RANGE) | mode, &dev->regs->fifoctl);
+
+       /* always ep-{a,b,e,f} ... maybe not ep-c or ep-d */
+       INIT_LIST_HEAD(&dev->gadget.ep_list);
+       list_add_tail(&dev->ep[1].ep.ep_list, &dev->gadget.ep_list);
+       list_add_tail(&dev->ep[2].ep.ep_list, &dev->gadget.ep_list);
+       switch (mode) {
+       case 0:
+               list_add_tail(&dev->ep[3].ep.ep_list, &dev->gadget.ep_list);
+               list_add_tail(&dev->ep[4].ep.ep_list, &dev->gadget.ep_list);
+               dev->ep[1].fifo_size = dev->ep[2].fifo_size = 1024;
+               break;
+       case 1:
+               dev->ep[1].fifo_size = dev->ep[2].fifo_size = 2048;
+               break;
+       case 2:
+               list_add_tail(&dev->ep[3].ep.ep_list, &dev->gadget.ep_list);
+               dev->ep[1].fifo_size = 2048;
+               dev->ep[2].fifo_size = 1024;
+               break;
+       }
+       /* fifo sizes for ep0, ep-c, ep-d, ep-e, and ep-f never change */
+       list_add_tail(&dev->ep[5].ep.ep_list, &dev->gadget.ep_list);
+       list_add_tail(&dev->ep[6].ep.ep_list, &dev->gadget.ep_list);
+}
+
+static void defect7374_disable_data_eps(struct net2280 *dev)
+{
+       /*
+        * For Defect 7374, disable data EPs (and more):
+        *  - This phase undoes the earlier phase of the Defect 7374 workaround,
+        *    returing ep regs back to normal.
+        */
+       struct net2280_ep *ep;
+       int i;
+       unsigned char ep_sel;
+       u32 tmp_reg;
+
+       for (i = 1; i < 5; i++) {
+               ep = &dev->ep[i];
+               writel(0, &ep->cfg->ep_cfg);
+       }
+
+       /* CSROUT, CSRIN, PCIOUT, PCIIN, STATIN, RCIN */
+       for (i = 0; i < 6; i++)
+               writel(0, &dev->dep[i].dep_cfg);
+
+       for (ep_sel = 0; ep_sel <= 21; ep_sel++) {
+               /* Select an endpoint for subsequent operations: */
+               tmp_reg = readl(&dev->plregs->pl_ep_ctrl);
+               writel(((tmp_reg & ~0x1f) | ep_sel), &dev->plregs->pl_ep_ctrl);
+
+               if (ep_sel < 2 || (ep_sel > 9 && ep_sel < 14) ||
+                                       ep_sel == 18 || ep_sel == 20)
+                       continue;
+
+               /* Change settings on some selected endpoints */
+               tmp_reg = readl(&dev->plregs->pl_ep_cfg_4);
+               tmp_reg &= ~BIT(NON_CTRL_IN_TOLERATE_BAD_DIR);
+               writel(tmp_reg, &dev->plregs->pl_ep_cfg_4);
+               tmp_reg = readl(&dev->plregs->pl_ep_ctrl);
+               tmp_reg |= BIT(EP_INITIALIZED);
+               writel(tmp_reg, &dev->plregs->pl_ep_ctrl);
+       }
+}
+
+static void defect7374_enable_data_eps_zero(struct net2280 *dev)
+{
+       u32 tmp = 0, tmp_reg;
+       u32 fsmvalue, scratch;
+       int i;
+       unsigned char ep_sel;
+
+       scratch = get_idx_reg(dev->regs, SCRATCH);
+       fsmvalue = scratch & (0xf << DEFECT7374_FSM_FIELD);
+       scratch &= ~(0xf << DEFECT7374_FSM_FIELD);
+
+       /*See if firmware needs to set up for workaround*/
+       if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ) {
+               ep_warn(dev, "Operate Defect 7374 workaround soft this time");
+               ep_warn(dev, "It will operate on cold-reboot and SS connect");
+
+               /*GPEPs:*/
+               tmp = ((0 << ENDPOINT_NUMBER) | BIT(ENDPOINT_DIRECTION) |
+                      (2 << OUT_ENDPOINT_TYPE) | (2 << IN_ENDPOINT_TYPE) |
+                      ((dev->enhanced_mode) ?
+                      BIT(OUT_ENDPOINT_ENABLE) : BIT(ENDPOINT_ENABLE)) |
+                      BIT(IN_ENDPOINT_ENABLE));
+
+               for (i = 1; i < 5; i++)
+                       writel(tmp, &dev->ep[i].cfg->ep_cfg);
+
+               /* CSRIN, PCIIN, STATIN, RCIN*/
+               tmp = ((0 << ENDPOINT_NUMBER) | BIT(ENDPOINT_ENABLE));
+               writel(tmp, &dev->dep[1].dep_cfg);
+               writel(tmp, &dev->dep[3].dep_cfg);
+               writel(tmp, &dev->dep[4].dep_cfg);
+               writel(tmp, &dev->dep[5].dep_cfg);
+
+               /*Implemented for development and debug.
+                * Can be refined/tuned later.*/
+               for (ep_sel = 0; ep_sel <= 21; ep_sel++) {
+                       /* Select an endpoint for subsequent operations: */
+                       tmp_reg = readl(&dev->plregs->pl_ep_ctrl);
+                       writel(((tmp_reg & ~0x1f) | ep_sel),
+                              &dev->plregs->pl_ep_ctrl);
+
+                       if (ep_sel == 1) {
+                               tmp =
+                                   (readl(&dev->plregs->pl_ep_ctrl) |
+                                    BIT(CLEAR_ACK_ERROR_CODE) | 0);
+                               writel(tmp, &dev->plregs->pl_ep_ctrl);
+                               continue;
+                       }
+
+                       if (ep_sel == 0 || (ep_sel > 9 && ep_sel < 14) ||
+                                       ep_sel == 18  || ep_sel == 20)
+                               continue;
+
+                       tmp = (readl(&dev->plregs->pl_ep_cfg_4) |
+                                BIT(NON_CTRL_IN_TOLERATE_BAD_DIR) | 0);
+                       writel(tmp, &dev->plregs->pl_ep_cfg_4);
+
+                       tmp = readl(&dev->plregs->pl_ep_ctrl) &
+                               ~BIT(EP_INITIALIZED);
+                       writel(tmp, &dev->plregs->pl_ep_ctrl);
+
+               }
+
+               /* Set FSM to focus on the first Control Read:
+                * - Tip: Connection speed is known upon the first
+                * setup request.*/
+               scratch |= DEFECT7374_FSM_WAITING_FOR_CONTROL_READ;
+               set_idx_reg(dev->regs, SCRATCH, scratch);
+
+       } else{
+               ep_warn(dev, "Defect 7374 workaround soft will NOT operate");
+               ep_warn(dev, "It will operate on cold-reboot and SS connect");
+       }
+}
+
+/* keeping it simple:
+ * - one bus driver, initted first;
+ * - one function driver, initted second
+ *
+ * most of the work to support multiple net2280 controllers would
+ * be to associate this gadget driver (yes?) with all of them, or
+ * perhaps to bind specific drivers to specific devices.
+ */
+
+static void usb_reset_228x(struct net2280 *dev)
+{
+       u32     tmp;
+
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+       (void) readl(&dev->usb->usbctl);
+
+       net2280_led_init(dev);
+
+       /* disable automatic responses, and irqs */
+       writel(0, &dev->usb->stdrsp);
+       writel(0, &dev->regs->pciirqenb0);
+       writel(0, &dev->regs->pciirqenb1);
+
+       /* clear old dma and irq state */
+       for (tmp = 0; tmp < 4; tmp++) {
+               struct net2280_ep       *ep = &dev->ep[tmp + 1];
+               if (ep->dma)
+                       abort_dma(ep);
+       }
+
+       writel(~0, &dev->regs->irqstat0),
+       writel(~(u32)BIT(SUSPEND_REQUEST_INTERRUPT), &dev->regs->irqstat1),
+
+       /* reset, and enable pci */
+       tmp = readl(&dev->regs->devinit) |
+               BIT(PCI_ENABLE) |
+               BIT(FIFO_SOFT_RESET) |
+               BIT(USB_SOFT_RESET) |
+               BIT(M8051_RESET);
+       writel(tmp, &dev->regs->devinit);
+
+       /* standard fifo and endpoint allocations */
+       set_fifo_mode(dev, (fifo_mode <= 2) ? fifo_mode : 0);
+}
+
+static void usb_reset_338x(struct net2280 *dev)
+{
+       u32 tmp;
+       u32 fsmvalue;
+
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+       (void)readl(&dev->usb->usbctl);
+
+       net2280_led_init(dev);
+
+       fsmvalue = get_idx_reg(dev->regs, SCRATCH) &
+                       (0xf << DEFECT7374_FSM_FIELD);
+
+       /* See if firmware needs to set up for workaround: */
+       if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ) {
+               ep_info(dev, "%s: Defect 7374 FsmValue 0x%08x\n", __func__,
+                    fsmvalue);
+       } else {
+               /* disable automatic responses, and irqs */
+               writel(0, &dev->usb->stdrsp);
+               writel(0, &dev->regs->pciirqenb0);
+               writel(0, &dev->regs->pciirqenb1);
+       }
+
+       /* clear old dma and irq state */
+       for (tmp = 0; tmp < 4; tmp++) {
+               struct net2280_ep *ep = &dev->ep[tmp + 1];
+
+               if (ep->dma)
+                       abort_dma(ep);
+       }
+
+       writel(~0, &dev->regs->irqstat0), writel(~0, &dev->regs->irqstat1);
+
+       if (fsmvalue == DEFECT7374_FSM_SS_CONTROL_READ) {
+               /* reset, and enable pci */
+               tmp = readl(&dev->regs->devinit) |
+                   BIT(PCI_ENABLE) |
+                   BIT(FIFO_SOFT_RESET) |
+                   BIT(USB_SOFT_RESET) |
+                   BIT(M8051_RESET);
+
+               writel(tmp, &dev->regs->devinit);
+       }
+
+       /* always ep-{1,2,3,4} ... maybe not ep-3 or ep-4 */
+       INIT_LIST_HEAD(&dev->gadget.ep_list);
+
+       for (tmp = 1; tmp < dev->n_ep; tmp++)
+               list_add_tail(&dev->ep[tmp].ep.ep_list, &dev->gadget.ep_list);
+
+}
+
+static void usb_reset(struct net2280 *dev)
+{
+       if (dev->quirks & PLX_LEGACY)
+               return usb_reset_228x(dev);
+       return usb_reset_338x(dev);
+}
+
+static void usb_reinit_228x(struct net2280 *dev)
+{
+       u32     tmp;
+       int     init_dma;
+
+       /* use_dma changes are ignored till next device re-init */
+       init_dma = use_dma;
+
+       /* basic endpoint init */
+       for (tmp = 0; tmp < 7; tmp++) {
+               struct net2280_ep       *ep = &dev->ep[tmp];
+
+               ep->ep.name = ep_name[tmp];
+               ep->dev = dev;
+               ep->num = tmp;
+
+               if (tmp > 0 && tmp <= 4) {
+                       ep->fifo_size = 1024;
+                       if (init_dma)
+                               ep->dma = &dev->dma[tmp - 1];
+               } else
+                       ep->fifo_size = 64;
+               ep->regs = &dev->epregs[tmp];
+               ep->cfg = &dev->epregs[tmp];
+               ep_reset_228x(dev->regs, ep);
+       }
+       usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 64);
+       usb_ep_set_maxpacket_limit(&dev->ep[5].ep, 64);
+       usb_ep_set_maxpacket_limit(&dev->ep[6].ep, 64);
+
+       dev->gadget.ep0 = &dev->ep[0].ep;
+       dev->ep[0].stopped = 0;
+       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+
+       /* we want to prevent lowlevel/insecure access from the USB host,
+        * but erratum 0119 means this enable bit is ignored
+        */
+       for (tmp = 0; tmp < 5; tmp++)
+               writel(EP_DONTUSE, &dev->dep[tmp].dep_cfg);
+}
+
+static void usb_reinit_338x(struct net2280 *dev)
+{
+       int init_dma;
+       int i;
+       u32 tmp, val;
+       u32 fsmvalue;
+       static const u32 ne[9] = { 0, 1, 2, 3, 4, 1, 2, 3, 4 };
+       static const u32 ep_reg_addr[9] = { 0x00, 0xC0, 0x00, 0xC0, 0x00,
+                                               0x00, 0xC0, 0x00, 0xC0 };
+
+       /* use_dma changes are ignored till next device re-init */
+       init_dma = use_dma;
+
+       /* basic endpoint init */
+       for (i = 0; i < dev->n_ep; i++) {
+               struct net2280_ep *ep = &dev->ep[i];
+
+               ep->ep.name = ep_name[i];
+               ep->dev = dev;
+               ep->num = i;
+
+               if (i > 0 && i <= 4 && init_dma)
+                       ep->dma = &dev->dma[i - 1];
+
+               if (dev->enhanced_mode) {
+                       ep->cfg = &dev->epregs[ne[i]];
+                       ep->regs = (struct net2280_ep_regs __iomem *)
+                               (((void *)&dev->epregs[ne[i]]) +
+                               ep_reg_addr[i]);
+                       ep->fiforegs = &dev->fiforegs[i];
+               } else {
+                       ep->cfg = &dev->epregs[i];
+                       ep->regs = &dev->epregs[i];
+                       ep->fiforegs = &dev->fiforegs[i];
+               }
+
+               ep->fifo_size = (i != 0) ? 2048 : 512;
+
+               ep_reset_338x(dev->regs, ep);
+       }
+       usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 512);
+
+       dev->gadget.ep0 = &dev->ep[0].ep;
+       dev->ep[0].stopped = 0;
+
+       /* Link layer set up */
+       fsmvalue = get_idx_reg(dev->regs, SCRATCH) &
+                               (0xf << DEFECT7374_FSM_FIELD);
+
+       /* See if driver needs to set up for workaround: */
+       if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ)
+               ep_info(dev, "%s: Defect 7374 FsmValue %08x\n",
+                                               __func__, fsmvalue);
+       else {
+               tmp = readl(&dev->usb_ext->usbctl2) &
+                   ~(BIT(U1_ENABLE) | BIT(U2_ENABLE) | BIT(LTM_ENABLE));
+               writel(tmp, &dev->usb_ext->usbctl2);
+       }
+
+       /* Hardware Defect and Workaround */
+       val = readl(&dev->ll_lfps_regs->ll_lfps_5);
+       val &= ~(0xf << TIMER_LFPS_6US);
+       val |= 0x5 << TIMER_LFPS_6US;
+       writel(val, &dev->ll_lfps_regs->ll_lfps_5);
+
+       val = readl(&dev->ll_lfps_regs->ll_lfps_6);
+       val &= ~(0xffff << TIMER_LFPS_80US);
+       val |= 0x0100 << TIMER_LFPS_80US;
+       writel(val, &dev->ll_lfps_regs->ll_lfps_6);
+
+       /*
+        * AA_AB Errata. Issue 4. Workaround for SuperSpeed USB
+        * Hot Reset Exit Handshake may Fail in Specific Case using
+        * Default Register Settings. Workaround for Enumeration test.
+        */
+       val = readl(&dev->ll_tsn_regs->ll_tsn_counters_2);
+       val &= ~(0x1f << HOT_TX_NORESET_TS2);
+       val |= 0x10 << HOT_TX_NORESET_TS2;
+       writel(val, &dev->ll_tsn_regs->ll_tsn_counters_2);
+
+       val = readl(&dev->ll_tsn_regs->ll_tsn_counters_3);
+       val &= ~(0x1f << HOT_RX_RESET_TS2);
+       val |= 0x3 << HOT_RX_RESET_TS2;
+       writel(val, &dev->ll_tsn_regs->ll_tsn_counters_3);
+
+       /*
+        * Set Recovery Idle to Recover bit:
+        * - On SS connections, setting Recovery Idle to Recover Fmw improves
+        *   link robustness with various hosts and hubs.
+        * - It is safe to set for all connection speeds; all chip revisions.
+        * - R-M-W to leave other bits undisturbed.
+        * - Reference PLX TT-7372
+       */
+       val = readl(&dev->ll_chicken_reg->ll_tsn_chicken_bit);
+       val |= BIT(RECOVERY_IDLE_TO_RECOVER_FMW);
+       writel(val, &dev->ll_chicken_reg->ll_tsn_chicken_bit);
+
+       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+
+       /* disable dedicated endpoints */
+       writel(0x0D, &dev->dep[0].dep_cfg);
+       writel(0x0D, &dev->dep[1].dep_cfg);
+       writel(0x0E, &dev->dep[2].dep_cfg);
+       writel(0x0E, &dev->dep[3].dep_cfg);
+       writel(0x0F, &dev->dep[4].dep_cfg);
+       writel(0x0C, &dev->dep[5].dep_cfg);
+}
+
+static void usb_reinit(struct net2280 *dev)
+{
+       if (dev->quirks & PLX_LEGACY)
+               return usb_reinit_228x(dev);
+       return usb_reinit_338x(dev);
+}
+
+static void ep0_start_228x(struct net2280 *dev)
+{
+       writel(BIT(CLEAR_EP_HIDE_STATUS_PHASE) |
+               BIT(CLEAR_NAK_OUT_PACKETS) |
+               BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE),
+               &dev->epregs[0].ep_rsp);
+
+       /*
+        * hardware optionally handles a bunch of standard requests
+        * that the API hides from drivers anyway.  have it do so.
+        * endpoint status/features are handled in software, to
+        * help pass tests for some dubious behavior.
+        */
+       writel(BIT(SET_TEST_MODE) |
+               BIT(SET_ADDRESS) |
+               BIT(DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP) |
+               BIT(GET_DEVICE_STATUS) |
+               BIT(GET_INTERFACE_STATUS),
+               &dev->usb->stdrsp);
+       writel(BIT(USB_ROOT_PORT_WAKEUP_ENABLE) |
+               BIT(SELF_POWERED_USB_DEVICE) |
+               BIT(REMOTE_WAKEUP_SUPPORT) |
+               (dev->softconnect << USB_DETECT_ENABLE) |
+               BIT(SELF_POWERED_STATUS),
+               &dev->usb->usbctl);
+
+       /* enable irqs so we can see ep0 and general operation  */
+       writel(BIT(SETUP_PACKET_INTERRUPT_ENABLE) |
+               BIT(ENDPOINT_0_INTERRUPT_ENABLE),
+               &dev->regs->pciirqenb0);
+       writel(BIT(PCI_INTERRUPT_ENABLE) |
+               BIT(PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE) |
+               BIT(PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE) |
+               BIT(PCI_RETRY_ABORT_INTERRUPT_ENABLE) |
+               BIT(VBUS_INTERRUPT_ENABLE) |
+               BIT(ROOT_PORT_RESET_INTERRUPT_ENABLE) |
+               BIT(SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE),
+               &dev->regs->pciirqenb1);
+
+       /* don't leave any writes posted */
+       (void) readl(&dev->usb->usbctl);
+}
+
+static void ep0_start_338x(struct net2280 *dev)
+{
+       u32 fsmvalue;
+
+       fsmvalue = get_idx_reg(dev->regs, SCRATCH) &
+                       (0xf << DEFECT7374_FSM_FIELD);
+
+       if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ)
+               ep_info(dev, "%s: Defect 7374 FsmValue %08x\n", __func__,
+                    fsmvalue);
+       else
+               writel(BIT(CLEAR_NAK_OUT_PACKETS_MODE) |
+                      BIT(SET_EP_HIDE_STATUS_PHASE),
+                      &dev->epregs[0].ep_rsp);
+
+       /*
+        * hardware optionally handles a bunch of standard requests
+        * that the API hides from drivers anyway.  have it do so.
+        * endpoint status/features are handled in software, to
+        * help pass tests for some dubious behavior.
+        */
+       writel(BIT(SET_ISOCHRONOUS_DELAY) |
+              BIT(SET_SEL) |
+              BIT(SET_TEST_MODE) |
+              BIT(SET_ADDRESS) |
+              BIT(GET_INTERFACE_STATUS) |
+              BIT(GET_DEVICE_STATUS),
+               &dev->usb->stdrsp);
+       dev->wakeup_enable = 1;
+       writel(BIT(USB_ROOT_PORT_WAKEUP_ENABLE) |
+              (dev->softconnect << USB_DETECT_ENABLE) |
+              BIT(DEVICE_REMOTE_WAKEUP_ENABLE),
+              &dev->usb->usbctl);
+
+       /* enable irqs so we can see ep0 and general operation  */
+       writel(BIT(SETUP_PACKET_INTERRUPT_ENABLE) |
+              BIT(ENDPOINT_0_INTERRUPT_ENABLE),
+              &dev->regs->pciirqenb0);
+       writel(BIT(PCI_INTERRUPT_ENABLE) |
+              BIT(ROOT_PORT_RESET_INTERRUPT_ENABLE) |
+              BIT(SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE) |
+              BIT(VBUS_INTERRUPT_ENABLE),
+              &dev->regs->pciirqenb1);
+
+       /* don't leave any writes posted */
+       (void)readl(&dev->usb->usbctl);
+}
+
+static void ep0_start(struct net2280 *dev)
+{
+       if (dev->quirks & PLX_LEGACY)
+               return ep0_start_228x(dev);
+       return ep0_start_338x(dev);
+}
+
+/* when a driver is successfully registered, it will receive
+ * control requests including set_configuration(), which enables
+ * non-control requests.  then usb traffic follows until a
+ * disconnect is reported.  then a host may connect again, or
+ * the driver might get unbound.
+ */
+static int net2280_start(struct usb_gadget *_gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct net2280          *dev;
+       int                     retval;
+       unsigned                i;
+
+       /* insist on high speed support from the driver, since
+        * (dev->usb->xcvrdiag & FORCE_FULL_SPEED_MODE)
+        * "must not be used in normal operation"
+        */
+       if (!driver || driver->max_speed < USB_SPEED_HIGH ||
+                       !driver->setup)
+               return -EINVAL;
+
+       dev = container_of(_gadget, struct net2280, gadget);
+
+       for (i = 0; i < dev->n_ep; i++)
+               dev->ep[i].irqs = 0;
+
+       /* hook up the driver ... */
+       dev->softconnect = 1;
+       driver->driver.bus = NULL;
+       dev->driver = driver;
+
+       retval = device_create_file(&dev->pdev->dev, &dev_attr_function);
+       if (retval)
+               goto err_unbind;
+       retval = device_create_file(&dev->pdev->dev, &dev_attr_queues);
+       if (retval)
+               goto err_func;
+
+       /* Enable force-full-speed testing mode, if desired */
+       if (full_speed && (dev->quirks & PLX_LEGACY))
+               writel(BIT(FORCE_FULL_SPEED_MODE), &dev->usb->xcvrdiag);
+
+       /* ... then enable host detection and ep0; and we're ready
+        * for set_configuration as well as eventual disconnect.
+        */
+       net2280_led_active(dev, 1);
+
+       if (dev->quirks & PLX_SUPERSPEED)
+               defect7374_enable_data_eps_zero(dev);
+
+       ep0_start(dev);
+
+       ep_dbg(dev, "%s ready, usbctl %08x stdrsp %08x\n",
+                       driver->driver.name,
+                       readl(&dev->usb->usbctl),
+                       readl(&dev->usb->stdrsp));
+
+       /* pci writes may still be posted */
+       return 0;
+
+err_func:
+       device_remove_file(&dev->pdev->dev, &dev_attr_function);
+err_unbind:
+       dev->driver = NULL;
+       return retval;
+}
+
+static void stop_activity(struct net2280 *dev, struct usb_gadget_driver *driver)
+{
+       int                     i;
+
+       /* don't disconnect if it's not connected */
+       if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+               driver = NULL;
+
+       /* stop hardware; prevent new request submissions;
+        * and kill any outstanding requests.
+        */
+       usb_reset(dev);
+       for (i = 0; i < dev->n_ep; i++)
+               nuke(&dev->ep[i]);
+
+       /* report disconnect; the driver is already quiesced */
+       if (driver) {
+               spin_unlock(&dev->lock);
+               driver->disconnect(&dev->gadget);
+               spin_lock(&dev->lock);
+       }
+
+       usb_reinit(dev);
+}
+
+static int net2280_stop(struct usb_gadget *_gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct net2280  *dev;
+       unsigned long   flags;
+
+       dev = container_of(_gadget, struct net2280, gadget);
+
+       spin_lock_irqsave(&dev->lock, flags);
+       stop_activity(dev, driver);
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       dev->driver = NULL;
+
+       net2280_led_active(dev, 0);
+
+       /* Disable full-speed test mode */
+       if (dev->quirks & PLX_LEGACY)
+               writel(0, &dev->usb->xcvrdiag);
+
+       device_remove_file(&dev->pdev->dev, &dev_attr_function);
+       device_remove_file(&dev->pdev->dev, &dev_attr_queues);
+
+       ep_dbg(dev, "unregistered driver '%s'\n",
+                       driver ? driver->driver.name : "");
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* handle ep0, ep-e, ep-f with 64 byte packets: packet per irq.
+ * also works for dma-capable endpoints, in pio mode or just
+ * to manually advance the queue after short OUT transfers.
+ */
+static void handle_ep_small(struct net2280_ep *ep)
+{
+       struct net2280_request  *req;
+       u32                     t;
+       /* 0 error, 1 mid-data, 2 done */
+       int                     mode = 1;
+
+       if (!list_empty(&ep->queue))
+               req = list_entry(ep->queue.next,
+                       struct net2280_request, queue);
+       else
+               req = NULL;
+
+       /* ack all, and handle what we care about */
+       t = readl(&ep->regs->ep_stat);
+       ep->irqs++;
+#if 0
+       ep_vdbg(ep->dev, "%s ack ep_stat %08x, req %p\n",
+                       ep->ep.name, t, req ? &req->req : 0);
+#endif
+       if (!ep->is_in || (ep->dev->quirks & PLX_2280))
+               writel(t & ~BIT(NAK_OUT_PACKETS), &ep->regs->ep_stat);
+       else
+               /* Added for 2282 */
+               writel(t, &ep->regs->ep_stat);
+
+       /* for ep0, monitor token irqs to catch data stage length errors
+        * and to synchronize on status.
+        *
+        * also, to defer reporting of protocol stalls ... here's where
+        * data or status first appears, handling stalls here should never
+        * cause trouble on the host side..
+        *
+        * control requests could be slightly faster without token synch for
+        * status, but status can jam up that way.
+        */
+       if (unlikely(ep->num == 0)) {
+               if (ep->is_in) {
+                       /* status; stop NAKing */
+                       if (t & BIT(DATA_OUT_PING_TOKEN_INTERRUPT)) {
+                               if (ep->dev->protocol_stall) {
+                                       ep->stopped = 1;
+                                       set_halt(ep);
+                               }
+                               if (!req)
+                                       allow_status(ep);
+                               mode = 2;
+                       /* reply to extra IN data tokens with a zlp */
+                       } else if (t & BIT(DATA_IN_TOKEN_INTERRUPT)) {
+                               if (ep->dev->protocol_stall) {
+                                       ep->stopped = 1;
+                                       set_halt(ep);
+                                       mode = 2;
+                               } else if (ep->responded &&
+                                               !req && !ep->stopped)
+                                       write_fifo(ep, NULL);
+                       }
+               } else {
+                       /* status; stop NAKing */
+                       if (t & BIT(DATA_IN_TOKEN_INTERRUPT)) {
+                               if (ep->dev->protocol_stall) {
+                                       ep->stopped = 1;
+                                       set_halt(ep);
+                               }
+                               mode = 2;
+                       /* an extra OUT token is an error */
+                       } else if (((t & BIT(DATA_OUT_PING_TOKEN_INTERRUPT)) &&
+                                       req &&
+                                       req->req.actual == req->req.length) ||
+                                       (ep->responded && !req)) {
+                               ep->dev->protocol_stall = 1;
+                               set_halt(ep);
+                               ep->stopped = 1;
+                               if (req)
+                                       done(ep, req, -EOVERFLOW);
+                               req = NULL;
+                       }
+               }
+       }
+
+       if (unlikely(!req))
+               return;
+
+       /* manual DMA queue advance after short OUT */
+       if (likely(ep->dma)) {
+               if (t & BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
+                       u32     count;
+                       int     stopped = ep->stopped;
+
+                       /* TRANSFERRED works around OUT_DONE erratum 0112.
+                        * we expect (N <= maxpacket) bytes; host wrote M.
+                        * iff (M < N) we won't ever see a DMA interrupt.
+                        */
+                       ep->stopped = 1;
+                       for (count = 0; ; t = readl(&ep->regs->ep_stat)) {
+
+                               /* any preceding dma transfers must finish.
+                                * dma handles (M >= N), may empty the queue
+                                */
+                               scan_dma_completions(ep);
+                               if (unlikely(list_empty(&ep->queue) ||
+                                               ep->out_overflow)) {
+                                       req = NULL;
+                                       break;
+                               }
+                               req = list_entry(ep->queue.next,
+                                       struct net2280_request, queue);
+
+                               /* here either (M < N), a "real" short rx;
+                                * or (M == N) and the queue didn't empty
+                                */
+                               if (likely(t & BIT(FIFO_EMPTY))) {
+                                       count = readl(&ep->dma->dmacount);
+                                       count &= DMA_BYTE_COUNT_MASK;
+                                       if (readl(&ep->dma->dmadesc)
+                                                       != req->td_dma)
+                                               req = NULL;
+                                       break;
+                               }
+                               udelay(1);
+                       }
+
+                       /* stop DMA, leave ep NAKing */
+                       writel(BIT(DMA_ABORT), &ep->dma->dmastat);
+                       spin_stop_dma(ep->dma);
+
+                       if (likely(req)) {
+                               req->td->dmacount = 0;
+                               t = readl(&ep->regs->ep_avail);
+                               dma_done(ep, req, count,
+                                       (ep->out_overflow || t)
+                                               ? -EOVERFLOW : 0);
+                       }
+
+                       /* also flush to prevent erratum 0106 trouble */
+                       if (unlikely(ep->out_overflow ||
+                                       (ep->dev->chiprev == 0x0100 &&
+                                       ep->dev->gadget.speed
+                                       == USB_SPEED_FULL))) {
+                               out_flush(ep);
+                               ep->out_overflow = 0;
+                       }
+
+                       /* (re)start dma if needed, stop NAKing */
+                       ep->stopped = stopped;
+                       if (!list_empty(&ep->queue))
+                               restart_dma(ep);
+               } else
+                       ep_dbg(ep->dev, "%s dma ep_stat %08x ??\n",
+                                       ep->ep.name, t);
+               return;
+
+       /* data packet(s) received (in the fifo, OUT) */
+       } else if (t & BIT(DATA_PACKET_RECEIVED_INTERRUPT)) {
+               if (read_fifo(ep, req) && ep->num != 0)
+                       mode = 2;
+
+       /* data packet(s) transmitted (IN) */
+       } else if (t & BIT(DATA_PACKET_TRANSMITTED_INTERRUPT)) {
+               unsigned        len;
+
+               len = req->req.length - req->req.actual;
+               if (len > ep->ep.maxpacket)
+                       len = ep->ep.maxpacket;
+               req->req.actual += len;
+
+               /* if we wrote it all, we're usually done */
+               /* send zlps until the status stage */
+               if ((req->req.actual == req->req.length) &&
+                       (!req->req.zero || len != ep->ep.maxpacket) && ep->num)
+                               mode = 2;
+
+       /* there was nothing to do ...  */
+       } else if (mode == 1)
+               return;
+
+       /* done */
+       if (mode == 2) {
+               /* stream endpoints often resubmit/unlink in completion */
+               done(ep, req, 0);
+
+               /* maybe advance queue to next request */
+               if (ep->num == 0) {
+                       /* NOTE:  net2280 could let gadget driver start the
+                        * status stage later. since not all controllers let
+                        * them control that, the api doesn't (yet) allow it.
+                        */
+                       if (!ep->stopped)
+                               allow_status(ep);
+                       req = NULL;
+               } else {
+                       if (!list_empty(&ep->queue) && !ep->stopped)
+                               req = list_entry(ep->queue.next,
+                                       struct net2280_request, queue);
+                       else
+                               req = NULL;
+                       if (req && !ep->is_in)
+                               stop_out_naking(ep);
+               }
+       }
+
+       /* is there a buffer for the next packet?
+        * for best streaming performance, make sure there is one.
+        */
+       if (req && !ep->stopped) {
+
+               /* load IN fifo with next packet (may be zlp) */
+               if (t & BIT(DATA_PACKET_TRANSMITTED_INTERRUPT))
+                       write_fifo(ep, &req->req);
+       }
+}
+
+static struct net2280_ep *get_ep_by_addr(struct net2280 *dev, u16 wIndex)
+{
+       struct net2280_ep       *ep;
+
+       if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
+               return &dev->ep[0];
+       list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
+               u8      bEndpointAddress;
+
+               if (!ep->desc)
+                       continue;
+               bEndpointAddress = ep->desc->bEndpointAddress;
+               if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
+                       continue;
+               if ((wIndex & 0x0f) == (bEndpointAddress & 0x0f))
+                       return ep;
+       }
+       return NULL;
+}
+
+static void defect7374_workaround(struct net2280 *dev, struct usb_ctrlrequest r)
+{
+       u32 scratch, fsmvalue;
+       u32 ack_wait_timeout, state;
+
+       /* Workaround for Defect 7374 (U1/U2 erroneously rejected): */
+       scratch = get_idx_reg(dev->regs, SCRATCH);
+       fsmvalue = scratch & (0xf << DEFECT7374_FSM_FIELD);
+       scratch &= ~(0xf << DEFECT7374_FSM_FIELD);
+
+       if (!((fsmvalue == DEFECT7374_FSM_WAITING_FOR_CONTROL_READ) &&
+                               (r.bRequestType & USB_DIR_IN)))
+               return;
+
+       /* This is the first Control Read for this connection: */
+       if (!(readl(&dev->usb->usbstat) & BIT(SUPER_SPEED_MODE))) {
+               /*
+                * Connection is NOT SS:
+                * - Connection must be FS or HS.
+                * - This FSM state should allow workaround software to
+                * run after the next USB connection.
+                */
+               scratch |= DEFECT7374_FSM_NON_SS_CONTROL_READ;
+               goto restore_data_eps;
+       }
+
+       /* Connection is SS: */
+       for (ack_wait_timeout = 0;
+                       ack_wait_timeout < DEFECT_7374_NUMBEROF_MAX_WAIT_LOOPS;
+                       ack_wait_timeout++) {
+
+               state = readl(&dev->plregs->pl_ep_status_1)
+                       & (0xff << STATE);
+               if ((state >= (ACK_GOOD_NORMAL << STATE)) &&
+                       (state <= (ACK_GOOD_MORE_ACKS_TO_COME << STATE))) {
+                       scratch |= DEFECT7374_FSM_SS_CONTROL_READ;
+                       break;
+               }
+
+               /*
+                * We have not yet received host's Data Phase ACK
+                * - Wait and try again.
+                */
+               udelay(DEFECT_7374_PROCESSOR_WAIT_TIME);
+
+               continue;
+       }
+
+
+       if (ack_wait_timeout >= DEFECT_7374_NUMBEROF_MAX_WAIT_LOOPS) {
+               ep_err(dev, "FAIL: Defect 7374 workaround waited but failed "
+               "to detect SS host's data phase ACK.");
+               ep_err(dev, "PL_EP_STATUS_1(23:16):.Expected from 0x11 to 0x16"
+               "got 0x%2.2x.\n", state >> STATE);
+       } else {
+               ep_warn(dev, "INFO: Defect 7374 workaround waited about\n"
+               "%duSec for Control Read Data Phase ACK\n",
+                       DEFECT_7374_PROCESSOR_WAIT_TIME * ack_wait_timeout);
+       }
+
+restore_data_eps:
+       /*
+        * Restore data EPs to their pre-workaround settings (disabled,
+        * initialized, and other details).
+        */
+       defect7374_disable_data_eps(dev);
+
+       set_idx_reg(dev->regs, SCRATCH, scratch);
+
+       return;
+}
+
+static void ep_stall(struct net2280_ep *ep, int stall)
+{
+       struct net2280 *dev = ep->dev;
+       u32 val;
+       static const u32 ep_pl[9] = { 0, 3, 4, 7, 8, 2, 5, 6, 9 };
+
+       if (stall) {
+               writel(BIT(SET_ENDPOINT_HALT) |
+                      /* BIT(SET_NAK_PACKETS) | */
+                      BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE),
+                      &ep->regs->ep_rsp);
+               ep->is_halt = 1;
+       } else {
+               if (dev->gadget.speed == USB_SPEED_SUPER) {
+                       /*
+                        * Workaround for SS SeqNum not cleared via
+                        * Endpoint Halt (Clear) bit. select endpoint
+                        */
+                       val = readl(&dev->plregs->pl_ep_ctrl);
+                       val = (val & ~0x1f) | ep_pl[ep->num];
+                       writel(val, &dev->plregs->pl_ep_ctrl);
+
+                       val |= BIT(SEQUENCE_NUMBER_RESET);
+                       writel(val, &dev->plregs->pl_ep_ctrl);
+               }
+               val = readl(&ep->regs->ep_rsp);
+               val |= BIT(CLEAR_ENDPOINT_HALT) |
+                       BIT(CLEAR_ENDPOINT_TOGGLE);
+               writel(val,
+                      /* | BIT(CLEAR_NAK_PACKETS),*/
+                      &ep->regs->ep_rsp);
+               ep->is_halt = 0;
+               val = readl(&ep->regs->ep_rsp);
+       }
+}
+
+static void ep_stdrsp(struct net2280_ep *ep, int value, int wedged)
+{
+       /* set/clear, then synch memory views with the device */
+       if (value) {
+               ep->stopped = 1;
+               if (ep->num == 0)
+                       ep->dev->protocol_stall = 1;
+               else {
+                       if (ep->dma)
+                               ep_stop_dma(ep);
+                       ep_stall(ep, true);
+               }
+
+               if (wedged)
+                       ep->wedged = 1;
+       } else {
+               ep->stopped = 0;
+               ep->wedged = 0;
+
+               ep_stall(ep, false);
+
+               /* Flush the queue */
+               if (!list_empty(&ep->queue)) {
+                       struct net2280_request *req =
+                           list_entry(ep->queue.next, struct net2280_request,
+                                      queue);
+                       if (ep->dma)
+                               resume_dma(ep);
+                       else {
+                               if (ep->is_in)
+                                       write_fifo(ep, &req->req);
+                               else {
+                                       if (read_fifo(ep, req))
+                                               done(ep, req, 0);
+                               }
+                       }
+               }
+       }
+}
+
+static void handle_stat0_irqs_superspeed(struct net2280 *dev,
+               struct net2280_ep *ep, struct usb_ctrlrequest r)
+{
+       int tmp = 0;
+
+#define        w_value         le16_to_cpu(r.wValue)
+#define        w_index         le16_to_cpu(r.wIndex)
+#define        w_length        le16_to_cpu(r.wLength)
+
+       switch (r.bRequest) {
+               struct net2280_ep *e;
+               u16 status;
+
+       case USB_REQ_SET_CONFIGURATION:
+               dev->addressed_state = !w_value;
+               goto usb3_delegate;
+
+       case USB_REQ_GET_STATUS:
+               switch (r.bRequestType) {
+               case (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE):
+                       status = dev->wakeup_enable ? 0x02 : 0x00;
+                       if (dev->selfpowered)
+                               status |= BIT(0);
+                       status |= (dev->u1_enable << 2 | dev->u2_enable << 3 |
+                                                       dev->ltm_enable << 4);
+                       writel(0, &dev->epregs[0].ep_irqenb);
+                       set_fifo_bytecount(ep, sizeof(status));
+                       writel((__force u32) status, &dev->epregs[0].ep_data);
+                       allow_status_338x(ep);
+                       break;
+
+               case (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
+                       e = get_ep_by_addr(dev, w_index);
+                       if (!e)
+                               goto do_stall3;
+                       status = readl(&e->regs->ep_rsp) &
+                                               BIT(CLEAR_ENDPOINT_HALT);
+                       writel(0, &dev->epregs[0].ep_irqenb);
+                       set_fifo_bytecount(ep, sizeof(status));
+                       writel((__force u32) status, &dev->epregs[0].ep_data);
+                       allow_status_338x(ep);
+                       break;
+
+               default:
+                       goto usb3_delegate;
+               }
+               break;
+
+       case USB_REQ_CLEAR_FEATURE:
+               switch (r.bRequestType) {
+               case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE):
+                       if (!dev->addressed_state) {
+                               switch (w_value) {
+                               case USB_DEVICE_U1_ENABLE:
+                                       dev->u1_enable = 0;
+                                       writel(readl(&dev->usb_ext->usbctl2) &
+                                               ~BIT(U1_ENABLE),
+                                               &dev->usb_ext->usbctl2);
+                                       allow_status_338x(ep);
+                                       goto next_endpoints3;
+
+                               case USB_DEVICE_U2_ENABLE:
+                                       dev->u2_enable = 0;
+                                       writel(readl(&dev->usb_ext->usbctl2) &
+                                               ~BIT(U2_ENABLE),
+                                               &dev->usb_ext->usbctl2);
+                                       allow_status_338x(ep);
+                                       goto next_endpoints3;
+
+                               case USB_DEVICE_LTM_ENABLE:
+                                       dev->ltm_enable = 0;
+                                       writel(readl(&dev->usb_ext->usbctl2) &
+                                               ~BIT(LTM_ENABLE),
+                                               &dev->usb_ext->usbctl2);
+                                       allow_status_338x(ep);
+                                       goto next_endpoints3;
+
+                               default:
+                                       break;
+                               }
+                       }
+                       if (w_value == USB_DEVICE_REMOTE_WAKEUP) {
+                               dev->wakeup_enable = 0;
+                               writel(readl(&dev->usb->usbctl) &
+                                       ~BIT(DEVICE_REMOTE_WAKEUP_ENABLE),
+                                       &dev->usb->usbctl);
+                               allow_status_338x(ep);
+                               break;
+                       }
+                       goto usb3_delegate;
+
+               case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
+                       e = get_ep_by_addr(dev, w_index);
+                       if (!e)
+                               goto do_stall3;
+                       if (w_value != USB_ENDPOINT_HALT)
+                               goto do_stall3;
+                       ep_vdbg(dev, "%s clear halt\n", e->ep.name);
+                       ep_stall(e, false);
+                       if (!list_empty(&e->queue) && e->td_dma)
+                               restart_dma(e);
+                       allow_status(ep);
+                       ep->stopped = 1;
+                       break;
+
+               default:
+                       goto usb3_delegate;
+               }
+               break;
+       case USB_REQ_SET_FEATURE:
+               switch (r.bRequestType) {
+               case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE):
+                       if (!dev->addressed_state) {
+                               switch (w_value) {
+                               case USB_DEVICE_U1_ENABLE:
+                                       dev->u1_enable = 1;
+                                       writel(readl(&dev->usb_ext->usbctl2) |
+                                               BIT(U1_ENABLE),
+                                               &dev->usb_ext->usbctl2);
+                                       allow_status_338x(ep);
+                                       goto next_endpoints3;
+
+                               case USB_DEVICE_U2_ENABLE:
+                                       dev->u2_enable = 1;
+                                       writel(readl(&dev->usb_ext->usbctl2) |
+                                               BIT(U2_ENABLE),
+                                               &dev->usb_ext->usbctl2);
+                                       allow_status_338x(ep);
+                                       goto next_endpoints3;
+
+                               case USB_DEVICE_LTM_ENABLE:
+                                       dev->ltm_enable = 1;
+                                       writel(readl(&dev->usb_ext->usbctl2) |
+                                               BIT(LTM_ENABLE),
+                                               &dev->usb_ext->usbctl2);
+                                       allow_status_338x(ep);
+                                       goto next_endpoints3;
+                               default:
+                                       break;
+                               }
+                       }
+
+                       if (w_value == USB_DEVICE_REMOTE_WAKEUP) {
+                               dev->wakeup_enable = 1;
+                               writel(readl(&dev->usb->usbctl) |
+                                       BIT(DEVICE_REMOTE_WAKEUP_ENABLE),
+                                       &dev->usb->usbctl);
+                               allow_status_338x(ep);
+                               break;
+                       }
+                       goto usb3_delegate;
+
+               case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
+                       e = get_ep_by_addr(dev, w_index);
+                       if (!e || (w_value != USB_ENDPOINT_HALT))
+                               goto do_stall3;
+                       ep_stdrsp(e, true, false);
+                       allow_status_338x(ep);
+                       break;
+
+               default:
+                       goto usb3_delegate;
+               }
+
+               break;
+       default:
+
+usb3_delegate:
+               ep_vdbg(dev, "setup %02x.%02x v%04x i%04x l%04x ep_cfg %08x\n",
+                               r.bRequestType, r.bRequest,
+                               w_value, w_index, w_length,
+                               readl(&ep->cfg->ep_cfg));
+
+               ep->responded = 0;
+               spin_unlock(&dev->lock);
+               tmp = dev->driver->setup(&dev->gadget, &r);
+               spin_lock(&dev->lock);
+       }
+do_stall3:
+       if (tmp < 0) {
+               ep_vdbg(dev, "req %02x.%02x protocol STALL; stat %d\n",
+                               r.bRequestType, r.bRequest, tmp);
+               dev->protocol_stall = 1;
+               /* TD 9.9 Halt Endpoint test. TD 9.22 Set feature test */
+               ep_stall(ep, true);
+       }
+
+next_endpoints3:
+
+#undef w_value
+#undef w_index
+#undef w_length
+
+       return;
+}
+
+static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
+{
+       struct net2280_ep       *ep;
+       u32                     num, scratch;
+
+       /* most of these don't need individual acks */
+       stat &= ~BIT(INTA_ASSERTED);
+       if (!stat)
+               return;
+       /* ep_dbg(dev, "irqstat0 %04x\n", stat); */
+
+       /* starting a control request? */
+       if (unlikely(stat & BIT(SETUP_PACKET_INTERRUPT))) {
+               union {
+                       u32                     raw[2];
+                       struct usb_ctrlrequest  r;
+               } u;
+               int                             tmp;
+               struct net2280_request          *req;
+
+               if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
+                       u32 val = readl(&dev->usb->usbstat);
+                       if (val & BIT(SUPER_SPEED)) {
+                               dev->gadget.speed = USB_SPEED_SUPER;
+                               usb_ep_set_maxpacket_limit(&dev->ep[0].ep,
+                                               EP0_SS_MAX_PACKET_SIZE);
+                       } else if (val & BIT(HIGH_SPEED)) {
+                               dev->gadget.speed = USB_SPEED_HIGH;
+                               usb_ep_set_maxpacket_limit(&dev->ep[0].ep,
+                                               EP0_HS_MAX_PACKET_SIZE);
+                       } else {
+                               dev->gadget.speed = USB_SPEED_FULL;
+                               usb_ep_set_maxpacket_limit(&dev->ep[0].ep,
+                                               EP0_HS_MAX_PACKET_SIZE);
+                       }
+                       net2280_led_speed(dev, dev->gadget.speed);
+                       ep_dbg(dev, "%s\n",
+                                       usb_speed_string(dev->gadget.speed));
+               }
+
+               ep = &dev->ep[0];
+               ep->irqs++;
+
+               /* make sure any leftover request state is cleared */
+               stat &= ~BIT(ENDPOINT_0_INTERRUPT);
+               while (!list_empty(&ep->queue)) {
+                       req = list_entry(ep->queue.next,
+                                       struct net2280_request, queue);
+                       done(ep, req, (req->req.actual == req->req.length)
+                                               ? 0 : -EPROTO);
+               }
+               ep->stopped = 0;
+               dev->protocol_stall = 0;
+               if (dev->quirks & PLX_SUPERSPEED)
+                       ep->is_halt = 0;
+               else{
+                       if (ep->dev->quirks & PLX_2280)
+                               tmp = BIT(FIFO_OVERFLOW) |
+                                   BIT(FIFO_UNDERFLOW);
+                       else
+                               tmp = 0;
+
+                       writel(tmp | BIT(TIMEOUT) |
+                                  BIT(USB_STALL_SENT) |
+                                  BIT(USB_IN_NAK_SENT) |
+                                  BIT(USB_IN_ACK_RCVD) |
+                                  BIT(USB_OUT_PING_NAK_SENT) |
+                                  BIT(USB_OUT_ACK_SENT) |
+                                  BIT(SHORT_PACKET_OUT_DONE_INTERRUPT) |
+                                  BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT) |
+                                  BIT(DATA_PACKET_RECEIVED_INTERRUPT) |
+                                  BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
+                                  BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
+                                  BIT(DATA_IN_TOKEN_INTERRUPT),
+                                  &ep->regs->ep_stat);
+               }
+               u.raw[0] = readl(&dev->usb->setup0123);
+               u.raw[1] = readl(&dev->usb->setup4567);
+
+               cpu_to_le32s(&u.raw[0]);
+               cpu_to_le32s(&u.raw[1]);
+
+               if (dev->quirks & PLX_SUPERSPEED)
+                       defect7374_workaround(dev, u.r);
+
+               tmp = 0;
+
+#define        w_value         le16_to_cpu(u.r.wValue)
+#define        w_index         le16_to_cpu(u.r.wIndex)
+#define        w_length        le16_to_cpu(u.r.wLength)
+
+               /* ack the irq */
+               writel(BIT(SETUP_PACKET_INTERRUPT), &dev->regs->irqstat0);
+               stat ^= BIT(SETUP_PACKET_INTERRUPT);
+
+               /* watch control traffic at the token level, and force
+                * synchronization before letting the status stage happen.
+                * FIXME ignore tokens we'll NAK, until driver responds.
+                * that'll mean a lot less irqs for some drivers.
+                */
+               ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0;
+               if (ep->is_in) {
+                       scratch = BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
+                               BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
+                               BIT(DATA_IN_TOKEN_INTERRUPT);
+                       stop_out_naking(ep);
+               } else
+                       scratch = BIT(DATA_PACKET_RECEIVED_INTERRUPT) |
+                               BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
+                               BIT(DATA_IN_TOKEN_INTERRUPT);
+               writel(scratch, &dev->epregs[0].ep_irqenb);
+
+               /* we made the hardware handle most lowlevel requests;
+                * everything else goes uplevel to the gadget code.
+                */
+               ep->responded = 1;
+
+               if (dev->gadget.speed == USB_SPEED_SUPER) {
+                       handle_stat0_irqs_superspeed(dev, ep, u.r);
+                       goto next_endpoints;
+               }
+
+               switch (u.r.bRequest) {
+               case USB_REQ_GET_STATUS: {
+                       struct net2280_ep       *e;
+                       __le32                  status;
+
+                       /* hw handles device and interface status */
+                       if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
+                               goto delegate;
+                       e = get_ep_by_addr(dev, w_index);
+                       if (!e || w_length > 2)
+                               goto do_stall;
+
+                       if (readl(&e->regs->ep_rsp) & BIT(SET_ENDPOINT_HALT))
+                               status = cpu_to_le32(1);
+                       else
+                               status = cpu_to_le32(0);
+
+                       /* don't bother with a request object! */
+                       writel(0, &dev->epregs[0].ep_irqenb);
+                       set_fifo_bytecount(ep, w_length);
+                       writel((__force u32)status, &dev->epregs[0].ep_data);
+                       allow_status(ep);
+                       ep_vdbg(dev, "%s stat %02x\n", ep->ep.name, status);
+                       goto next_endpoints;
+                       }
+                       break;
+               case USB_REQ_CLEAR_FEATURE: {
+                       struct net2280_ep       *e;
+
+                       /* hw handles device features */
+                       if (u.r.bRequestType != USB_RECIP_ENDPOINT)
+                               goto delegate;
+                       if (w_value != USB_ENDPOINT_HALT || w_length != 0)
+                               goto do_stall;
+                       e = get_ep_by_addr(dev, w_index);
+                       if (!e)
+                               goto do_stall;
+                       if (e->wedged) {
+                               ep_vdbg(dev, "%s wedged, halt not cleared\n",
+                                               ep->ep.name);
+                       } else {
+                               ep_vdbg(dev, "%s clear halt\n", e->ep.name);
+                               clear_halt(e);
+                               if ((ep->dev->quirks & PLX_SUPERSPEED) &&
+                                       !list_empty(&e->queue) && e->td_dma)
+                                               restart_dma(e);
+                       }
+                       allow_status(ep);
+                       goto next_endpoints;
+                       }
+                       break;
+               case USB_REQ_SET_FEATURE: {
+                       struct net2280_ep       *e;
+
+                       /* hw handles device features */
+                       if (u.r.bRequestType != USB_RECIP_ENDPOINT)
+                               goto delegate;
+                       if (w_value != USB_ENDPOINT_HALT || w_length != 0)
+                               goto do_stall;
+                       e = get_ep_by_addr(dev, w_index);
+                       if (!e)
+                               goto do_stall;
+                       if (e->ep.name == ep0name)
+                               goto do_stall;
+                       set_halt(e);
+                       if ((dev->quirks & PLX_SUPERSPEED) && e->dma)
+                               abort_dma(e);
+                       allow_status(ep);
+                       ep_vdbg(dev, "%s set halt\n", ep->ep.name);
+                       goto next_endpoints;
+                       }
+                       break;
+               default:
+delegate:
+                       ep_vdbg(dev, "setup %02x.%02x v%04x i%04x l%04x "
+                               "ep_cfg %08x\n",
+                               u.r.bRequestType, u.r.bRequest,
+                               w_value, w_index, w_length,
+                               readl(&ep->cfg->ep_cfg));
+                       ep->responded = 0;
+                       spin_unlock(&dev->lock);
+                       tmp = dev->driver->setup(&dev->gadget, &u.r);
+                       spin_lock(&dev->lock);
+               }
+
+               /* stall ep0 on error */
+               if (tmp < 0) {
+do_stall:
+                       ep_vdbg(dev, "req %02x.%02x protocol STALL; stat %d\n",
+                                       u.r.bRequestType, u.r.bRequest, tmp);
+                       dev->protocol_stall = 1;
+               }
+
+               /* some in/out token irq should follow; maybe stall then.
+                * driver must queue a request (even zlp) or halt ep0
+                * before the host times out.
+                */
+       }
+
+#undef w_value
+#undef w_index
+#undef w_length
+
+next_endpoints:
+       /* endpoint data irq ? */
+       scratch = stat & 0x7f;
+       stat &= ~0x7f;
+       for (num = 0; scratch; num++) {
+               u32             t;
+
+               /* do this endpoint's FIFO and queue need tending? */
+               t = BIT(num);
+               if ((scratch & t) == 0)
+                       continue;
+               scratch ^= t;
+
+               ep = &dev->ep[num];
+               handle_ep_small(ep);
+       }
+
+       if (stat)
+               ep_dbg(dev, "unhandled irqstat0 %08x\n", stat);
+}
+
+#define DMA_INTERRUPTS (BIT(DMA_D_INTERRUPT) | \
+               BIT(DMA_C_INTERRUPT) | \
+               BIT(DMA_B_INTERRUPT) | \
+               BIT(DMA_A_INTERRUPT))
+#define        PCI_ERROR_INTERRUPTS ( \
+               BIT(PCI_MASTER_ABORT_RECEIVED_INTERRUPT) | \
+               BIT(PCI_TARGET_ABORT_RECEIVED_INTERRUPT) | \
+               BIT(PCI_RETRY_ABORT_INTERRUPT))
+
+static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
+{
+       struct net2280_ep       *ep;
+       u32                     tmp, num, mask, scratch;
+
+       /* after disconnect there's nothing else to do! */
+       tmp = BIT(VBUS_INTERRUPT) | BIT(ROOT_PORT_RESET_INTERRUPT);
+       mask = BIT(SUPER_SPEED) | BIT(HIGH_SPEED) | BIT(FULL_SPEED);
+
+       /* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
+        * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRUPT set and
+        * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT
+        * only indicates a change in the reset state).
+        */
+       if (stat & tmp) {
+               writel(tmp, &dev->regs->irqstat1);
+               if ((((stat & BIT(ROOT_PORT_RESET_INTERRUPT)) &&
+                               (readl(&dev->usb->usbstat) & mask)) ||
+                               ((readl(&dev->usb->usbctl) &
+                                       BIT(VBUS_PIN)) == 0)) &&
+                               (dev->gadget.speed != USB_SPEED_UNKNOWN)) {
+                       ep_dbg(dev, "disconnect %s\n",
+                                       dev->driver->driver.name);
+                       stop_activity(dev, dev->driver);
+                       ep0_start(dev);
+                       return;
+               }
+               stat &= ~tmp;
+
+               /* vBUS can bounce ... one of many reasons to ignore the
+                * notion of hotplug events on bus connect/disconnect!
+                */
+               if (!stat)
+                       return;
+       }
+
+       /* NOTE: chip stays in PCI D0 state for now, but it could
+        * enter D1 to save more power
+        */
+       tmp = BIT(SUSPEND_REQUEST_CHANGE_INTERRUPT);
+       if (stat & tmp) {
+               writel(tmp, &dev->regs->irqstat1);
+               if (stat & BIT(SUSPEND_REQUEST_INTERRUPT)) {
+                       if (dev->driver->suspend)
+                               dev->driver->suspend(&dev->gadget);
+                       if (!enable_suspend)
+                               stat &= ~BIT(SUSPEND_REQUEST_INTERRUPT);
+               } else {
+                       if (dev->driver->resume)
+                               dev->driver->resume(&dev->gadget);
+                       /* at high speed, note erratum 0133 */
+               }
+               stat &= ~tmp;
+       }
+
+       /* clear any other status/irqs */
+       if (stat)
+               writel(stat, &dev->regs->irqstat1);
+
+       /* some status we can just ignore */
+       if (dev->quirks & PLX_2280)
+               stat &= ~(BIT(CONTROL_STATUS_INTERRUPT) |
+                         BIT(SUSPEND_REQUEST_INTERRUPT) |
+                         BIT(RESUME_INTERRUPT) |
+                         BIT(SOF_INTERRUPT));
+       else
+               stat &= ~(BIT(CONTROL_STATUS_INTERRUPT) |
+                         BIT(RESUME_INTERRUPT) |
+                         BIT(SOF_DOWN_INTERRUPT) |
+                         BIT(SOF_INTERRUPT));
+
+       if (!stat)
+               return;
+       /* ep_dbg(dev, "irqstat1 %08x\n", stat);*/
+
+       /* DMA status, for ep-{a,b,c,d} */
+       scratch = stat & DMA_INTERRUPTS;
+       stat &= ~DMA_INTERRUPTS;
+       scratch >>= 9;
+       for (num = 0; scratch; num++) {
+               struct net2280_dma_regs __iomem *dma;
+
+               tmp = BIT(num);
+               if ((tmp & scratch) == 0)
+                       continue;
+               scratch ^= tmp;
+
+               ep = &dev->ep[num + 1];
+               dma = ep->dma;
+
+               if (!dma)
+                       continue;
+
+               /* clear ep's dma status */
+               tmp = readl(&dma->dmastat);
+               writel(tmp, &dma->dmastat);
+
+               /* dma sync*/
+               if (dev->quirks & PLX_SUPERSPEED) {
+                       u32 r_dmacount = readl(&dma->dmacount);
+                       if (!ep->is_in &&  (r_dmacount & 0x00FFFFFF) &&
+                           (tmp & BIT(DMA_TRANSACTION_DONE_INTERRUPT)))
+                               continue;
+               }
+
+               /* chaining should stop on abort, short OUT from fifo,
+                * or (stat0 codepath) short OUT transfer.
+                */
+               if (!use_dma_chaining) {
+                       if (!(tmp & BIT(DMA_TRANSACTION_DONE_INTERRUPT))) {
+                               ep_dbg(ep->dev, "%s no xact done? %08x\n",
+                                       ep->ep.name, tmp);
+                               continue;
+                       }
+                       stop_dma(ep->dma);
+               }
+
+               /* OUT transfers terminate when the data from the
+                * host is in our memory.  Process whatever's done.
+                * On this path, we know transfer's last packet wasn't
+                * less than req->length. NAK_OUT_PACKETS may be set,
+                * or the FIFO may already be holding new packets.
+                *
+                * IN transfers can linger in the FIFO for a very
+                * long time ... we ignore that for now, accounting
+                * precisely (like PIO does) needs per-packet irqs
+                */
+               scan_dma_completions(ep);
+
+               /* disable dma on inactive queues; else maybe restart */
+               if (list_empty(&ep->queue)) {
+                       if (use_dma_chaining)
+                               stop_dma(ep->dma);
+               } else {
+                       tmp = readl(&dma->dmactl);
+                       if (!use_dma_chaining || (tmp & BIT(DMA_ENABLE)) == 0)
+                               restart_dma(ep);
+                       else if (ep->is_in && use_dma_chaining) {
+                               struct net2280_request  *req;
+                               __le32                  dmacount;
+
+                               /* the descriptor at the head of the chain
+                                * may still have VALID_BIT clear; that's
+                                * used to trigger changing DMA_FIFO_VALIDATE
+                                * (affects automagic zlp writes).
+                                */
+                               req = list_entry(ep->queue.next,
+                                               struct net2280_request, queue);
+                               dmacount = req->td->dmacount;
+                               dmacount &= cpu_to_le32(BIT(VALID_BIT) |
+                                               DMA_BYTE_COUNT_MASK);
+                               if (dmacount && (dmacount & valid_bit) == 0)
+                                       restart_dma(ep);
+                       }
+               }
+               ep->irqs++;
+       }
+
+       /* NOTE:  there are other PCI errors we might usefully notice.
+        * if they appear very often, here's where to try recovering.
+        */
+       if (stat & PCI_ERROR_INTERRUPTS) {
+               ep_err(dev, "pci dma error; stat %08x\n", stat);
+               stat &= ~PCI_ERROR_INTERRUPTS;
+               /* these are fatal errors, but "maybe" they won't
+                * happen again ...
+                */
+               stop_activity(dev, dev->driver);
+               ep0_start(dev);
+               stat = 0;
+       }
+
+       if (stat)
+               ep_dbg(dev, "unhandled irqstat1 %08x\n", stat);
+}
+
+static irqreturn_t net2280_irq(int irq, void *_dev)
+{
+       struct net2280          *dev = _dev;
+
+       /* shared interrupt, not ours */
+       if ((dev->quirks & PLX_LEGACY) &&
+               (!(readl(&dev->regs->irqstat0) & BIT(INTA_ASSERTED))))
+               return IRQ_NONE;
+
+       spin_lock(&dev->lock);
+
+       /* handle disconnect, dma, and more */
+       handle_stat1_irqs(dev, readl(&dev->regs->irqstat1));
+
+       /* control requests and PIO */
+       handle_stat0_irqs(dev, readl(&dev->regs->irqstat0));
+
+       if (dev->quirks & PLX_SUPERSPEED) {
+               /* re-enable interrupt to trigger any possible new interrupt */
+               u32 pciirqenb1 = readl(&dev->regs->pciirqenb1);
+               writel(pciirqenb1 & 0x7FFFFFFF, &dev->regs->pciirqenb1);
+               writel(pciirqenb1, &dev->regs->pciirqenb1);
+       }
+
+       spin_unlock(&dev->lock);
+
+       return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void gadget_release(struct device *_dev)
+{
+       struct net2280  *dev = dev_get_drvdata(_dev);
+
+       kfree(dev);
+}
+
+/* tear down the binding between this driver and the pci device */
+
+static void net2280_remove(struct pci_dev *pdev)
+{
+       struct net2280          *dev = pci_get_drvdata(pdev);
+
+       usb_del_gadget_udc(&dev->gadget);
+
+       BUG_ON(dev->driver);
+
+       /* then clean up the resources we allocated during probe() */
+       net2280_led_shutdown(dev);
+       if (dev->requests) {
+               int             i;
+               for (i = 1; i < 5; i++) {
+                       if (!dev->ep[i].dummy)
+                               continue;
+                       pci_pool_free(dev->requests, dev->ep[i].dummy,
+                                       dev->ep[i].td_dma);
+               }
+               pci_pool_destroy(dev->requests);
+       }
+       if (dev->got_irq)
+               free_irq(pdev->irq, dev);
+       if (use_msi && dev->quirks & PLX_SUPERSPEED)
+               pci_disable_msi(pdev);
+       if (dev->regs)
+               iounmap(dev->regs);
+       if (dev->region)
+               release_mem_region(pci_resource_start(pdev, 0),
+                               pci_resource_len(pdev, 0));
+       if (dev->enabled)
+               pci_disable_device(pdev);
+       device_remove_file(&pdev->dev, &dev_attr_registers);
+
+       ep_info(dev, "unbind\n");
+}
+
+/* wrap this driver around the specified device, but
+ * don't respond over USB until a gadget driver binds to us.
+ */
+
+static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       struct net2280          *dev;
+       unsigned long           resource, len;
+       void                    __iomem *base = NULL;
+       int                     retval, i;
+
+       if (!use_dma)
+               use_dma_chaining = 0;
+
+       /* alloc, and start init */
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               retval = -ENOMEM;
+               goto done;
+       }
+
+       pci_set_drvdata(pdev, dev);
+       spin_lock_init(&dev->lock);
+       dev->quirks = id->driver_data;
+       dev->pdev = pdev;
+       dev->gadget.ops = &net2280_ops;
+       dev->gadget.max_speed = (dev->quirks & PLX_SUPERSPEED) ?
+                               USB_SPEED_SUPER : USB_SPEED_HIGH;
+
+       /* the "gadget" abstracts/virtualizes the controller */
+       dev->gadget.name = driver_name;
+
+       /* now all the pci goodies ... */
+       if (pci_enable_device(pdev) < 0) {
+               retval = -ENODEV;
+               goto done;
+       }
+       dev->enabled = 1;
+
+       /* BAR 0 holds all the registers
+        * BAR 1 is 8051 memory; unused here (note erratum 0103)
+        * BAR 2 is fifo memory; unused here
+        */
+       resource = pci_resource_start(pdev, 0);
+       len = pci_resource_len(pdev, 0);
+       if (!request_mem_region(resource, len, driver_name)) {
+               ep_dbg(dev, "controller already in use\n");
+               retval = -EBUSY;
+               goto done;
+       }
+       dev->region = 1;
+
+       /* FIXME provide firmware download interface to put
+        * 8051 code into the chip, e.g. to turn on PCI PM.
+        */
+
+       base = ioremap_nocache(resource, len);
+       if (base == NULL) {
+               ep_dbg(dev, "can't map memory\n");
+               retval = -EFAULT;
+               goto done;
+       }
+       dev->regs = (struct net2280_regs __iomem *) base;
+       dev->usb = (struct net2280_usb_regs __iomem *) (base + 0x0080);
+       dev->pci = (struct net2280_pci_regs __iomem *) (base + 0x0100);
+       dev->dma = (struct net2280_dma_regs __iomem *) (base + 0x0180);
+       dev->dep = (struct net2280_dep_regs __iomem *) (base + 0x0200);
+       dev->epregs = (struct net2280_ep_regs __iomem *) (base + 0x0300);
+
+       if (dev->quirks & PLX_SUPERSPEED) {
+               u32 fsmvalue;
+               u32 usbstat;
+               dev->usb_ext = (struct usb338x_usb_ext_regs __iomem *)
+                                                       (base + 0x00b4);
+               dev->fiforegs = (struct usb338x_fifo_regs __iomem *)
+                                                       (base + 0x0500);
+               dev->llregs = (struct usb338x_ll_regs __iomem *)
+                                                       (base + 0x0700);
+               dev->ll_lfps_regs = (struct usb338x_ll_lfps_regs __iomem *)
+                                                       (base + 0x0748);
+               dev->ll_tsn_regs = (struct usb338x_ll_tsn_regs __iomem *)
+                                                       (base + 0x077c);
+               dev->ll_chicken_reg = (struct usb338x_ll_chi_regs __iomem *)
+                                                       (base + 0x079c);
+               dev->plregs = (struct usb338x_pl_regs __iomem *)
+                                                       (base + 0x0800);
+               usbstat = readl(&dev->usb->usbstat);
+               dev->enhanced_mode = !!(usbstat & BIT(11));
+               dev->n_ep = (dev->enhanced_mode) ? 9 : 5;
+               /* put into initial config, link up all endpoints */
+               fsmvalue = get_idx_reg(dev->regs, SCRATCH) &
+                                       (0xf << DEFECT7374_FSM_FIELD);
+               /* See if firmware needs to set up for workaround: */
+               if (fsmvalue == DEFECT7374_FSM_SS_CONTROL_READ)
+                       writel(0, &dev->usb->usbctl);
+       } else{
+               dev->enhanced_mode = 0;
+               dev->n_ep = 7;
+               /* put into initial config, link up all endpoints */
+               writel(0, &dev->usb->usbctl);
+       }
+
+       usb_reset(dev);
+       usb_reinit(dev);
+
+       /* irq setup after old hardware is cleaned up */
+       if (!pdev->irq) {
+               ep_err(dev, "No IRQ.  Check PCI setup!\n");
+               retval = -ENODEV;
+               goto done;
+       }
+
+       if (use_msi && (dev->quirks & PLX_SUPERSPEED))
+               if (pci_enable_msi(pdev))
+                       ep_err(dev, "Failed to enable MSI mode\n");
+
+       if (request_irq(pdev->irq, net2280_irq, IRQF_SHARED,
+                                                       driver_name, dev)) {
+               ep_err(dev, "request interrupt %d failed\n", pdev->irq);
+               retval = -EBUSY;
+               goto done;
+       }
+       dev->got_irq = 1;
+
+       /* DMA setup */
+       /* NOTE:  we know only the 32 LSBs of dma addresses may be nonzero */
+       dev->requests = pci_pool_create("requests", pdev,
+               sizeof(struct net2280_dma),
+               0 /* no alignment requirements */,
+               0 /* or page-crossing issues */);
+       if (!dev->requests) {
+               ep_dbg(dev, "can't get request pool\n");
+               retval = -ENOMEM;
+               goto done;
+       }
+       for (i = 1; i < 5; i++) {
+               struct net2280_dma      *td;
+
+               td = pci_pool_alloc(dev->requests, GFP_KERNEL,
+                               &dev->ep[i].td_dma);
+               if (!td) {
+                       ep_dbg(dev, "can't get dummy %d\n", i);
+                       retval = -ENOMEM;
+                       goto done;
+               }
+               td->dmacount = 0;       /* not VALID */
+               td->dmadesc = td->dmaaddr;
+               dev->ep[i].dummy = td;
+       }
+
+       /* enable lower-overhead pci memory bursts during DMA */
+       if (dev->quirks & PLX_LEGACY)
+               writel(BIT(DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE) |
+                       /*
+                        * 256 write retries may not be enough...
+                          BIT(PCI_RETRY_ABORT_ENABLE) |
+                       */
+                       BIT(DMA_READ_MULTIPLE_ENABLE) |
+                       BIT(DMA_READ_LINE_ENABLE),
+                       &dev->pci->pcimstctl);
+       /* erratum 0115 shouldn't appear: Linux inits PCI_LATENCY_TIMER */
+       pci_set_master(pdev);
+       pci_try_set_mwi(pdev);
+
+       /* ... also flushes any posted pci writes */
+       dev->chiprev = get_idx_reg(dev->regs, REG_CHIPREV) & 0xffff;
+
+       /* done */
+       ep_info(dev, "%s\n", driver_desc);
+       ep_info(dev, "irq %d, pci mem %p, chip rev %04x\n",
+                       pdev->irq, base, dev->chiprev);
+       ep_info(dev, "version: " DRIVER_VERSION "; dma %s %s\n",
+               use_dma ? (use_dma_chaining ? "chaining" : "enabled")
+                       : "disabled",
+               dev->enhanced_mode ? "enhanced mode" : "legacy mode");
+       retval = device_create_file(&pdev->dev, &dev_attr_registers);
+       if (retval)
+               goto done;
+
+       retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+                       gadget_release);
+       if (retval)
+               goto done;
+       return 0;
+
+done:
+       if (dev)
+               net2280_remove(pdev);
+       return retval;
+}
+
+/* make sure the board is quiescent; otherwise it will continue
+ * generating IRQs across the upcoming reboot.
+ */
+
+static void net2280_shutdown(struct pci_dev *pdev)
+{
+       struct net2280          *dev = pci_get_drvdata(pdev);
+
+       /* disable IRQs */
+       writel(0, &dev->regs->pciirqenb0);
+       writel(0, &dev->regs->pciirqenb1);
+
+       /* disable the pullup so the host will think we're gone */
+       writel(0, &dev->usb->usbctl);
+
+       /* Disable full-speed test mode */
+       if (dev->quirks & PLX_LEGACY)
+               writel(0, &dev->usb->xcvrdiag);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static const struct pci_device_id pci_ids[] = { {
+       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class_mask =   ~0,
+       .vendor =       PCI_VENDOR_ID_PLX_LEGACY,
+       .device =       0x2280,
+       .subvendor =    PCI_ANY_ID,
+       .subdevice =    PCI_ANY_ID,
+       .driver_data =  PLX_LEGACY | PLX_2280,
+       }, {
+       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class_mask =   ~0,
+       .vendor =       PCI_VENDOR_ID_PLX_LEGACY,
+       .device =       0x2282,
+       .subvendor =    PCI_ANY_ID,
+       .subdevice =    PCI_ANY_ID,
+       .driver_data =  PLX_LEGACY,
+       },
+       {
+       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class_mask =   ~0,
+       .vendor =       PCI_VENDOR_ID_PLX,
+       .device =       0x3380,
+       .subvendor =    PCI_ANY_ID,
+       .subdevice =    PCI_ANY_ID,
+       .driver_data =  PLX_SUPERSPEED,
+        },
+       {
+       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class_mask =   ~0,
+       .vendor =       PCI_VENDOR_ID_PLX,
+       .device =       0x3382,
+       .subvendor =    PCI_ANY_ID,
+       .subdevice =    PCI_ANY_ID,
+       .driver_data =  PLX_SUPERSPEED,
+        },
+{ /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE(pci, pci_ids);
+
+/* pci driver glue; this is a "new style" PCI driver module */
+static struct pci_driver net2280_pci_driver = {
+       .name =         (char *) driver_name,
+       .id_table =     pci_ids,
+
+       .probe =        net2280_probe,
+       .remove =       net2280_remove,
+       .shutdown =     net2280_shutdown,
+
+       /* FIXME add power management support */
+};
+
+module_pci_driver(net2280_pci_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/udc/net2280.h b/drivers/usb/gadget/udc/net2280.h
new file mode 100644 (file)
index 0000000..03f1524
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * NetChip 2280 high/full speed USB device controller.
+ * Unlike many such controllers, this one talks PCI.
+ */
+
+/*
+ * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
+ * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2014 Ricardo Ribalda - Qtechnology/AS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/usb/net2280.h>
+#include <linux/usb/usb338x.h>
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef __KERNEL__
+
+/* indexed registers [11.10] are accessed indirectly
+ * caller must own the device lock.
+ */
+
+static inline u32 get_idx_reg(struct net2280_regs __iomem *regs, u32 index)
+{
+       writel(index, &regs->idxaddr);
+       /* NOTE:  synchs device/cpu memory views */
+       return readl(&regs->idxdata);
+}
+
+static inline void
+set_idx_reg(struct net2280_regs __iomem *regs, u32 index, u32 value)
+{
+       writel(index, &regs->idxaddr);
+       writel(value, &regs->idxdata);
+       /* posted, may not be visible yet */
+}
+
+#endif /* __KERNEL__ */
+
+#define PCI_VENDOR_ID_PLX_LEGACY 0x17cc
+
+#define PLX_LEGACY             BIT(0)
+#define PLX_2280               BIT(1)
+#define PLX_SUPERSPEED         BIT(2)
+
+#define REG_DIAG               0x0
+#define     RETRY_COUNTER                                       16
+#define     FORCE_PCI_SERR                                      11
+#define     FORCE_PCI_INTERRUPT                                 10
+#define     FORCE_USB_INTERRUPT                                 9
+#define     FORCE_CPU_INTERRUPT                                 8
+#define     ILLEGAL_BYTE_ENABLES                                5
+#define     FAST_TIMES                                          4
+#define     FORCE_RECEIVE_ERROR                                 2
+#define     FORCE_TRANSMIT_CRC_ERROR                            0
+#define REG_FRAME              0x02    /* from last sof */
+#define REG_CHIPREV            0x03    /* in bcd */
+#define        REG_HS_NAK_RATE         0x0a    /* NAK per N uframes */
+
+#define        CHIPREV_1       0x0100
+#define        CHIPREV_1A      0x0110
+
+/* DEFECT 7374 */
+#define DEFECT_7374_NUMBEROF_MAX_WAIT_LOOPS         200
+#define DEFECT_7374_PROCESSOR_WAIT_TIME             10
+
+/* ep0 max packet size */
+#define EP0_SS_MAX_PACKET_SIZE  0x200
+#define EP0_HS_MAX_PACKET_SIZE  0x40
+#ifdef __KERNEL__
+
+/*-------------------------------------------------------------------------*/
+
+/* [8.3] for scatter/gather i/o
+ * use struct net2280_dma_regs bitfields
+ */
+struct net2280_dma {
+       __le32          dmacount;
+       __le32          dmaaddr;                /* the buffer */
+       __le32          dmadesc;                /* next dma descriptor */
+       __le32          _reserved;
+} __aligned(16);
+
+/*-------------------------------------------------------------------------*/
+
+/* DRIVER DATA STRUCTURES and UTILITIES */
+
+struct net2280_ep {
+       struct usb_ep                           ep;
+       struct net2280_ep_regs __iomem *cfg;
+       struct net2280_ep_regs                  __iomem *regs;
+       struct net2280_dma_regs                 __iomem *dma;
+       struct net2280_dma                      *dummy;
+       struct usb338x_fifo_regs __iomem *fiforegs;
+       dma_addr_t                              td_dma; /* of dummy */
+       struct net2280                          *dev;
+       unsigned long                           irqs;
+       unsigned is_halt:1, dma_started:1;
+
+       /* analogous to a host-side qh */
+       struct list_head                        queue;
+       const struct usb_endpoint_descriptor    *desc;
+       unsigned                                num : 8,
+                                               fifo_size : 12,
+                                               in_fifo_validate : 1,
+                                               out_overflow : 1,
+                                               stopped : 1,
+                                               wedged : 1,
+                                               is_in : 1,
+                                               is_iso : 1,
+                                               responded : 1;
+};
+
+static inline void allow_status(struct net2280_ep *ep)
+{
+       /* ep0 only */
+       writel(BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE) |
+               BIT(CLEAR_NAK_OUT_PACKETS) |
+               BIT(CLEAR_NAK_OUT_PACKETS_MODE),
+               &ep->regs->ep_rsp);
+       ep->stopped = 1;
+}
+
+static void allow_status_338x(struct net2280_ep *ep)
+{
+       /*
+        * Control Status Phase Handshake was set by the chip when the setup
+        * packet arrived. While set, the chip automatically NAKs the host's
+        * Status Phase tokens.
+        */
+       writel(BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE), &ep->regs->ep_rsp);
+
+       ep->stopped = 1;
+
+       /* TD 9.9 Halt Endpoint test.  TD 9.22 set feature test. */
+       ep->responded = 0;
+}
+
+struct net2280_request {
+       struct usb_request              req;
+       struct net2280_dma              *td;
+       dma_addr_t                      td_dma;
+       struct list_head                queue;
+       unsigned                        mapped : 1,
+                                       valid : 1;
+};
+
+struct net2280 {
+       /* each pci device provides one gadget, several endpoints */
+       struct usb_gadget               gadget;
+       spinlock_t                      lock;
+       struct net2280_ep               ep[9];
+       struct usb_gadget_driver        *driver;
+       unsigned                        enabled : 1,
+                                       protocol_stall : 1,
+                                       softconnect : 1,
+                                       got_irq : 1,
+                                       region:1,
+                                       u1_enable:1,
+                                       u2_enable:1,
+                                       ltm_enable:1,
+                                       wakeup_enable:1,
+                                       selfpowered:1,
+                                       addressed_state:1;
+       u16                             chiprev;
+       int enhanced_mode;
+       int n_ep;
+       kernel_ulong_t                  quirks;
+
+
+       /* pci state used to access those endpoints */
+       struct pci_dev                  *pdev;
+       struct net2280_regs             __iomem *regs;
+       struct net2280_usb_regs         __iomem *usb;
+       struct usb338x_usb_ext_regs     __iomem *usb_ext;
+       struct net2280_pci_regs         __iomem *pci;
+       struct net2280_dma_regs         __iomem *dma;
+       struct net2280_dep_regs         __iomem *dep;
+       struct net2280_ep_regs          __iomem *epregs;
+       struct usb338x_fifo_regs        __iomem *fiforegs;
+       struct usb338x_ll_regs          __iomem *llregs;
+       struct usb338x_ll_lfps_regs     __iomem *ll_lfps_regs;
+       struct usb338x_ll_tsn_regs      __iomem *ll_tsn_regs;
+       struct usb338x_ll_chi_regs      __iomem *ll_chicken_reg;
+       struct usb338x_pl_regs          __iomem *plregs;
+
+       struct pci_pool                 *requests;
+       /* statistics...*/
+};
+
+static inline void set_halt(struct net2280_ep *ep)
+{
+       /* ep0 and bulk/intr endpoints */
+       writel(BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE) |
+               /* set NAK_OUT for erratum 0114 */
+               ((ep->dev->chiprev == CHIPREV_1) << SET_NAK_OUT_PACKETS) |
+               BIT(SET_ENDPOINT_HALT),
+               &ep->regs->ep_rsp);
+}
+
+static inline void clear_halt(struct net2280_ep *ep)
+{
+       /* ep0 and bulk/intr endpoints */
+       writel(BIT(CLEAR_ENDPOINT_HALT) |
+               BIT(CLEAR_ENDPOINT_TOGGLE) |
+                   /*
+                    * unless the gadget driver left a short packet in the
+                    * fifo, this reverses the erratum 0114 workaround.
+                    */
+               ((ep->dev->chiprev == CHIPREV_1) << CLEAR_NAK_OUT_PACKETS),
+               &ep->regs->ep_rsp);
+}
+
+/*
+ * FSM value for Defect 7374 (U1U2 Test) is managed in
+ * chip's SCRATCH register:
+ */
+#define DEFECT7374_FSM_FIELD    28
+
+/* Waiting for Control Read:
+ *  - A transition to this state indicates a fresh USB connection,
+ *    before the first Setup Packet. The connection speed is not
+ *    known. Firmware is waiting for the first Control Read.
+ *  - Starting state: This state can be thought of as the FSM's typical
+ *    starting state.
+ *  - Tip: Upon the first SS Control Read the FSM never
+ *    returns to this state.
+ */
+#define DEFECT7374_FSM_WAITING_FOR_CONTROL_READ BIT(DEFECT7374_FSM_FIELD)
+
+/* Non-SS Control Read:
+ *  - A transition to this state indicates detection of the first HS
+ *    or FS Control Read.
+ *  - Tip: Upon the first SS Control Read the FSM never
+ *    returns to this state.
+ */
+#define        DEFECT7374_FSM_NON_SS_CONTROL_READ (2 << DEFECT7374_FSM_FIELD)
+
+/* SS Control Read:
+ *  - A transition to this state indicates detection of the
+ *    first SS Control Read.
+ *  - This state indicates workaround completion. Workarounds no longer
+ *    need to be applied (as long as the chip remains powered up).
+ *  - Tip: Once in this state the FSM state does not change (until
+ *    the chip's power is lost and restored).
+ *  - This can be thought of as the final state of the FSM;
+ *    the FSM 'locks-up' in this state until the chip loses power.
+ */
+#define DEFECT7374_FSM_SS_CONTROL_READ (3 << DEFECT7374_FSM_FIELD)
+
+#ifdef USE_RDK_LEDS
+
+static inline void net2280_led_init(struct net2280 *dev)
+{
+       /* LED3 (green) is on during USB activity. note erratum 0113. */
+       writel(BIT(GPIO3_LED_SELECT) |
+               BIT(GPIO3_OUTPUT_ENABLE) |
+               BIT(GPIO2_OUTPUT_ENABLE) |
+               BIT(GPIO1_OUTPUT_ENABLE) |
+               BIT(GPIO0_OUTPUT_ENABLE),
+               &dev->regs->gpioctl);
+}
+
+/* indicate speed with bi-color LED 0/1 */
+static inline
+void net2280_led_speed(struct net2280 *dev, enum usb_device_speed speed)
+{
+       u32     val = readl(&dev->regs->gpioctl);
+       switch (speed) {
+       case USB_SPEED_SUPER:           /* green + red */
+               val |= BIT(GPIO0_DATA) | BIT(GPIO1_DATA);
+               break;
+       case USB_SPEED_HIGH:            /* green */
+               val &= ~BIT(GPIO0_DATA);
+               val |= BIT(GPIO1_DATA);
+               break;
+       case USB_SPEED_FULL:            /* red */
+               val &= ~BIT(GPIO1_DATA);
+               val |= BIT(GPIO0_DATA);
+               break;
+       default:                        /* (off/black) */
+               val &= ~(BIT(GPIO1_DATA) | BIT(GPIO0_DATA));
+               break;
+       }
+       writel(val, &dev->regs->gpioctl);
+}
+
+/* indicate power with LED 2 */
+static inline void net2280_led_active(struct net2280 *dev, int is_active)
+{
+       u32     val = readl(&dev->regs->gpioctl);
+
+       /* FIXME this LED never seems to turn on.*/
+       if (is_active)
+               val |= GPIO2_DATA;
+       else
+               val &= ~GPIO2_DATA;
+       writel(val, &dev->regs->gpioctl);
+}
+
+static inline void net2280_led_shutdown(struct net2280 *dev)
+{
+       /* turn off all four GPIO*_DATA bits */
+       writel(readl(&dev->regs->gpioctl) & ~0x0f,
+                       &dev->regs->gpioctl);
+}
+
+#else
+
+#define net2280_led_init(dev)          do { } while (0)
+#define net2280_led_speed(dev, speed)  do { } while (0)
+#define net2280_led_shutdown(dev)      do { } while (0)
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#define ep_dbg(ndev, fmt, args...) \
+       dev_dbg((&((ndev)->pdev->dev)), fmt, ##args)
+
+#define ep_vdbg(ndev, fmt, args...) \
+       dev_vdbg((&((ndev)->pdev->dev)), fmt, ##args)
+
+#define ep_info(ndev, fmt, args...) \
+       dev_info((&((ndev)->pdev->dev)), fmt, ##args)
+
+#define ep_warn(ndev, fmt, args...) \
+       dev_warn((&((ndev)->pdev->dev)), fmt, ##args)
+
+#define ep_err(ndev, fmt, args...) \
+       dev_err((&((ndev)->pdev->dev)), fmt, ##args)
+
+/*-------------------------------------------------------------------------*/
+
+static inline void set_fifo_bytecount(struct net2280_ep *ep, unsigned count)
+{
+       if (ep->dev->pdev->vendor == 0x17cc)
+               writeb(count, 2 + (u8 __iomem *) &ep->regs->ep_cfg);
+       else{
+               u32 tmp = readl(&ep->cfg->ep_cfg) &
+                                       (~(0x07 << EP_FIFO_BYTE_COUNT));
+               writel(tmp | (count << EP_FIFO_BYTE_COUNT), &ep->cfg->ep_cfg);
+       }
+}
+
+static inline void start_out_naking(struct net2280_ep *ep)
+{
+       /* NOTE:  hardware races lurk here, and PING protocol issues */
+       writel(BIT(SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
+       /* synch with device */
+       readl(&ep->regs->ep_rsp);
+}
+
+#ifdef DEBUG
+static inline void assert_out_naking(struct net2280_ep *ep, const char *where)
+{
+       u32     tmp = readl(&ep->regs->ep_stat);
+
+       if ((tmp & BIT(NAK_OUT_PACKETS)) == 0) {
+               ep_dbg(ep->dev, "%s %s %08x !NAK\n",
+                               ep->ep.name, where, tmp);
+               writel(BIT(SET_NAK_OUT_PACKETS),
+                       &ep->regs->ep_rsp);
+       }
+}
+#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep, __func__)
+#else
+#define ASSERT_OUT_NAKING(ep) do {} while (0)
+#endif
+
+static inline void stop_out_naking(struct net2280_ep *ep)
+{
+       u32     tmp;
+
+       tmp = readl(&ep->regs->ep_stat);
+       if ((tmp & BIT(NAK_OUT_PACKETS)) != 0)
+               writel(BIT(CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
+}
+
+
+static inline void set_max_speed(struct net2280_ep *ep, u32 max)
+{
+       u32 reg;
+       static const u32 ep_enhanced[9] = { 0x10, 0x60, 0x30, 0x80,
+                                         0x50, 0x20, 0x70, 0x40, 0x90 };
+
+       if (ep->dev->enhanced_mode)
+               reg = ep_enhanced[ep->num];
+       else{
+               reg = (ep->num + 1) * 0x10;
+               if (ep->dev->gadget.speed != USB_SPEED_HIGH)
+                       reg += 1;
+       }
+
+       set_idx_reg(ep->dev->regs, reg, max);
+}
+
+#endif /* __KERNEL__ */
diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c
new file mode 100644 (file)
index 0000000..e731373
--- /dev/null
@@ -0,0 +1,3038 @@
+/*
+ * omap_udc.c -- for OMAP full speed udc; most chips support OTG.
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ * Copyright (C) 2004-2005 David Brownell
+ *
+ * OMAP2 & DMA support by Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#undef DEBUG
+#undef VERBOSE
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/mm.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/prefetch.h>
+#include <linux/io.h>
+
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/unaligned.h>
+#include <asm/mach-types.h>
+
+#include <linux/omap-dma.h>
+
+#include <mach/usb.h>
+
+#include "omap_udc.h"
+
+#undef USB_TRACE
+
+/* bulk DMA seems to be behaving for both IN and OUT */
+#define        USE_DMA
+
+/* ISO too */
+#define        USE_ISO
+
+#define        DRIVER_DESC     "OMAP UDC driver"
+#define        DRIVER_VERSION  "4 October 2004"
+
+#define OMAP_DMA_USB_W2FC_TX0          29
+#define OMAP_DMA_USB_W2FC_RX0          26
+
+/*
+ * The OMAP UDC needs _very_ early endpoint setup:  before enabling the
+ * D+ pullup to allow enumeration.  That's too early for the gadget
+ * framework to use from usb_endpoint_enable(), which happens after
+ * enumeration as part of activating an interface.  (But if we add an
+ * optional new "UDC not yet running" state to the gadget driver model,
+ * even just during driver binding, the endpoint autoconfig logic is the
+ * natural spot to manufacture new endpoints.)
+ *
+ * So instead of using endpoint enable calls to control the hardware setup,
+ * this driver defines a "fifo mode" parameter.  It's used during driver
+ * initialization to choose among a set of pre-defined endpoint configs.
+ * See omap_udc_setup() for available modes, or to add others.  That code
+ * lives in an init section, so use this driver as a module if you need
+ * to change the fifo mode after the kernel boots.
+ *
+ * Gadget drivers normally ignore endpoints they don't care about, and
+ * won't include them in configuration descriptors.  That means only
+ * misbehaving hosts would even notice they exist.
+ */
+#ifdef USE_ISO
+static unsigned fifo_mode = 3;
+#else
+static unsigned fifo_mode;
+#endif
+
+/* "modprobe omap_udc fifo_mode=42", or else as a kernel
+ * boot parameter "omap_udc:fifo_mode=42"
+ */
+module_param(fifo_mode, uint, 0);
+MODULE_PARM_DESC(fifo_mode, "endpoint configuration");
+
+#ifdef USE_DMA
+static bool use_dma = 1;
+
+/* "modprobe omap_udc use_dma=y", or else as a kernel
+ * boot parameter "omap_udc:use_dma=y"
+ */
+module_param(use_dma, bool, 0);
+MODULE_PARM_DESC(use_dma, "enable/disable DMA");
+#else  /* !USE_DMA */
+
+/* save a bit of code */
+#define        use_dma         0
+#endif /* !USE_DMA */
+
+
+static const char driver_name[] = "omap_udc";
+static const char driver_desc[] = DRIVER_DESC;
+
+/*-------------------------------------------------------------------------*/
+
+/* there's a notion of "current endpoint" for modifying endpoint
+ * state, and PIO access to its FIFO.
+ */
+
+static void use_ep(struct omap_ep *ep, u16 select)
+{
+       u16     num = ep->bEndpointAddress & 0x0f;
+
+       if (ep->bEndpointAddress & USB_DIR_IN)
+               num |= UDC_EP_DIR;
+       omap_writew(num | select, UDC_EP_NUM);
+       /* when select, MUST deselect later !! */
+}
+
+static inline void deselect_ep(void)
+{
+       u16 w;
+
+       w = omap_readw(UDC_EP_NUM);
+       w &= ~UDC_EP_SEL;
+       omap_writew(w, UDC_EP_NUM);
+       /* 6 wait states before TX will happen */
+}
+
+static void dma_channel_claim(struct omap_ep *ep, unsigned preferred);
+
+/*-------------------------------------------------------------------------*/
+
+static int omap_ep_enable(struct usb_ep *_ep,
+               const struct usb_endpoint_descriptor *desc)
+{
+       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
+       struct omap_udc *udc;
+       unsigned long   flags;
+       u16             maxp;
+
+       /* catch various bogus parameters */
+       if (!_ep || !desc
+                       || desc->bDescriptorType != USB_DT_ENDPOINT
+                       || ep->bEndpointAddress != desc->bEndpointAddress
+                       || ep->maxpacket < usb_endpoint_maxp(desc)) {
+               DBG("%s, bad ep or descriptor\n", __func__);
+               return -EINVAL;
+       }
+       maxp = usb_endpoint_maxp(desc);
+       if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+                               && maxp != ep->maxpacket)
+                       || usb_endpoint_maxp(desc) > ep->maxpacket
+                       || !desc->wMaxPacketSize) {
+               DBG("%s, bad %s maxpacket\n", __func__, _ep->name);
+               return -ERANGE;
+       }
+
+#ifdef USE_ISO
+       if ((desc->bmAttributes == USB_ENDPOINT_XFER_ISOC
+                               && desc->bInterval != 1)) {
+               /* hardware wants period = 1; USB allows 2^(Interval-1) */
+               DBG("%s, unsupported ISO period %dms\n", _ep->name,
+                               1 << (desc->bInterval - 1));
+               return -EDOM;
+       }
+#else
+       if (desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+               DBG("%s, ISO nyet\n", _ep->name);
+               return -EDOM;
+       }
+#endif
+
+       /* xfer types must match, except that interrupt ~= bulk */
+       if (ep->bmAttributes != desc->bmAttributes
+                       && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+                       && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+               DBG("%s, %s type mismatch\n", __func__, _ep->name);
+               return -EINVAL;
+       }
+
+       udc = ep->udc;
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+               DBG("%s, bogus device state\n", __func__);
+               return -ESHUTDOWN;
+       }
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       ep->ep.desc = desc;
+       ep->irqs = 0;
+       ep->stopped = 0;
+       ep->ep.maxpacket = maxp;
+
+       /* set endpoint to initial state */
+       ep->dma_channel = 0;
+       ep->has_dma = 0;
+       ep->lch = -1;
+       use_ep(ep, UDC_EP_SEL);
+       omap_writew(udc->clr_halt, UDC_CTRL);
+       ep->ackwait = 0;
+       deselect_ep();
+
+       if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
+               list_add(&ep->iso, &udc->iso);
+
+       /* maybe assign a DMA channel to this endpoint */
+       if (use_dma && desc->bmAttributes == USB_ENDPOINT_XFER_BULK)
+               /* FIXME ISO can dma, but prefers first channel */
+               dma_channel_claim(ep, 0);
+
+       /* PIO OUT may RX packets */
+       if (desc->bmAttributes != USB_ENDPOINT_XFER_ISOC
+                       && !ep->has_dma
+                       && !(ep->bEndpointAddress & USB_DIR_IN)) {
+               omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+               ep->ackwait = 1 + ep->double_buf;
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       VDBG("%s enabled\n", _ep->name);
+       return 0;
+}
+
+static void nuke(struct omap_ep *, int status);
+
+static int omap_ep_disable(struct usb_ep *_ep)
+{
+       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
+       unsigned long   flags;
+
+       if (!_ep || !ep->ep.desc) {
+               DBG("%s, %s not enabled\n", __func__,
+                       _ep ? ep->ep.name : NULL);
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+       ep->ep.desc = NULL;
+       nuke(ep, -ESHUTDOWN);
+       ep->ep.maxpacket = ep->maxpacket;
+       ep->has_dma = 0;
+       omap_writew(UDC_SET_HALT, UDC_CTRL);
+       list_del_init(&ep->iso);
+       del_timer(&ep->timer);
+
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+
+       VDBG("%s disabled\n", _ep->name);
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_request *
+omap_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
+{
+       struct omap_req *req;
+
+       req = kzalloc(sizeof(*req), gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void
+omap_free_request(struct usb_ep *ep, struct usb_request *_req)
+{
+       struct omap_req *req = container_of(_req, struct omap_req, req);
+
+       kfree(req);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+done(struct omap_ep *ep, struct omap_req *req, int status)
+{
+       struct omap_udc         *udc = ep->udc;
+       unsigned                stopped = ep->stopped;
+
+       list_del_init(&req->queue);
+
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       if (use_dma && ep->has_dma)
+               usb_gadget_unmap_request(&udc->gadget, &req->req,
+                               (ep->bEndpointAddress & USB_DIR_IN));
+
+#ifndef        USB_TRACE
+       if (status && status != -ESHUTDOWN)
+#endif
+               VDBG("complete %s req %p stat %d len %u/%u\n",
+                       ep->ep.name, &req->req, status,
+                       req->req.actual, req->req.length);
+
+       /* don't modify queue heads during completion callback */
+       ep->stopped = 1;
+       spin_unlock(&ep->udc->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&ep->udc->lock);
+       ep->stopped = stopped;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define UDC_FIFO_FULL          (UDC_NON_ISO_FIFO_FULL | UDC_ISO_FIFO_FULL)
+#define UDC_FIFO_UNWRITABLE    (UDC_EP_HALTED | UDC_FIFO_FULL)
+
+#define FIFO_EMPTY     (UDC_NON_ISO_FIFO_EMPTY | UDC_ISO_FIFO_EMPTY)
+#define FIFO_UNREADABLE (UDC_EP_HALTED | FIFO_EMPTY)
+
+static inline int
+write_packet(u8 *buf, struct omap_req *req, unsigned max)
+{
+       unsigned        len;
+       u16             *wp;
+
+       len = min(req->req.length - req->req.actual, max);
+       req->req.actual += len;
+
+       max = len;
+       if (likely((((int)buf) & 1) == 0)) {
+               wp = (u16 *)buf;
+               while (max >= 2) {
+                       omap_writew(*wp++, UDC_DATA);
+                       max -= 2;
+               }
+               buf = (u8 *)wp;
+       }
+       while (max--)
+               omap_writeb(*buf++, UDC_DATA);
+       return len;
+}
+
+/* FIXME change r/w fifo calling convention */
+
+
+/* return:  0 = still running, 1 = completed, negative = errno */
+static int write_fifo(struct omap_ep *ep, struct omap_req *req)
+{
+       u8              *buf;
+       unsigned        count;
+       int             is_last;
+       u16             ep_stat;
+
+       buf = req->req.buf + req->req.actual;
+       prefetch(buf);
+
+       /* PIO-IN isn't double buffered except for iso */
+       ep_stat = omap_readw(UDC_STAT_FLG);
+       if (ep_stat & UDC_FIFO_UNWRITABLE)
+               return 0;
+
+       count = ep->ep.maxpacket;
+       count = write_packet(buf, req, count);
+       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+       ep->ackwait = 1;
+
+       /* last packet is often short (sometimes a zlp) */
+       if (count != ep->ep.maxpacket)
+               is_last = 1;
+       else if (req->req.length == req->req.actual
+                       && !req->req.zero)
+               is_last = 1;
+       else
+               is_last = 0;
+
+       /* NOTE:  requests complete when all IN data is in a
+        * FIFO (or sometimes later, if a zlp was needed).
+        * Use usb_ep_fifo_status() where needed.
+        */
+       if (is_last)
+               done(ep, req, 0);
+       return is_last;
+}
+
+static inline int
+read_packet(u8 *buf, struct omap_req *req, unsigned avail)
+{
+       unsigned        len;
+       u16             *wp;
+
+       len = min(req->req.length - req->req.actual, avail);
+       req->req.actual += len;
+       avail = len;
+
+       if (likely((((int)buf) & 1) == 0)) {
+               wp = (u16 *)buf;
+               while (avail >= 2) {
+                       *wp++ = omap_readw(UDC_DATA);
+                       avail -= 2;
+               }
+               buf = (u8 *)wp;
+       }
+       while (avail--)
+               *buf++ = omap_readb(UDC_DATA);
+       return len;
+}
+
+/* return:  0 = still running, 1 = queue empty, negative = errno */
+static int read_fifo(struct omap_ep *ep, struct omap_req *req)
+{
+       u8              *buf;
+       unsigned        count, avail;
+       int             is_last;
+
+       buf = req->req.buf + req->req.actual;
+       prefetchw(buf);
+
+       for (;;) {
+               u16     ep_stat = omap_readw(UDC_STAT_FLG);
+
+               is_last = 0;
+               if (ep_stat & FIFO_EMPTY) {
+                       if (!ep->double_buf)
+                               break;
+                       ep->fnf = 1;
+               }
+               if (ep_stat & UDC_EP_HALTED)
+                       break;
+
+               if (ep_stat & UDC_FIFO_FULL)
+                       avail = ep->ep.maxpacket;
+               else  {
+                       avail = omap_readw(UDC_RXFSTAT);
+                       ep->fnf = ep->double_buf;
+               }
+               count = read_packet(buf, req, avail);
+
+               /* partial packet reads may not be errors */
+               if (count < ep->ep.maxpacket) {
+                       is_last = 1;
+                       /* overflowed this request?  flush extra data */
+                       if (count != avail) {
+                               req->req.status = -EOVERFLOW;
+                               avail -= count;
+                               while (avail--)
+                                       omap_readw(UDC_DATA);
+                       }
+               } else if (req->req.length == req->req.actual)
+                       is_last = 1;
+               else
+                       is_last = 0;
+
+               if (!ep->bEndpointAddress)
+                       break;
+               if (is_last)
+                       done(ep, req, 0);
+               break;
+       }
+       return is_last;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start)
+{
+       dma_addr_t      end;
+
+       /* IN-DMA needs this on fault/cancel paths, so 15xx misreports
+        * the last transfer's bytecount by more than a FIFO's worth.
+        */
+       if (cpu_is_omap15xx())
+               return 0;
+
+       end = omap_get_dma_src_pos(ep->lch);
+       if (end == ep->dma_counter)
+               return 0;
+
+       end |= start & (0xffff << 16);
+       if (end < start)
+               end += 0x10000;
+       return end - start;
+}
+
+static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start)
+{
+       dma_addr_t      end;
+
+       end = omap_get_dma_dst_pos(ep->lch);
+       if (end == ep->dma_counter)
+               return 0;
+
+       end |= start & (0xffff << 16);
+       if (cpu_is_omap15xx())
+               end++;
+       if (end < start)
+               end += 0x10000;
+       return end - start;
+}
+
+
+/* Each USB transfer request using DMA maps to one or more DMA transfers.
+ * When DMA completion isn't request completion, the UDC continues with
+ * the next DMA transfer for that USB transfer.
+ */
+
+static void next_in_dma(struct omap_ep *ep, struct omap_req *req)
+{
+       u16             txdma_ctrl, w;
+       unsigned        length = req->req.length - req->req.actual;
+       const int       sync_mode = cpu_is_omap15xx()
+                               ? OMAP_DMA_SYNC_FRAME
+                               : OMAP_DMA_SYNC_ELEMENT;
+       int             dma_trigger = 0;
+
+       /* measure length in either bytes or packets */
+       if ((cpu_is_omap16xx() && length <= UDC_TXN_TSC)
+                       || (cpu_is_omap15xx() && length < ep->maxpacket)) {
+               txdma_ctrl = UDC_TXN_EOT | length;
+               omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
+                               length, 1, sync_mode, dma_trigger, 0);
+       } else {
+               length = min(length / ep->maxpacket,
+                               (unsigned) UDC_TXN_TSC + 1);
+               txdma_ctrl = length;
+               omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
+                               ep->ep.maxpacket >> 1, length, sync_mode,
+                               dma_trigger, 0);
+               length *= ep->maxpacket;
+       }
+       omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
+               OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
+               0, 0);
+
+       omap_start_dma(ep->lch);
+       ep->dma_counter = omap_get_dma_src_pos(ep->lch);
+       w = omap_readw(UDC_DMA_IRQ_EN);
+       w |= UDC_TX_DONE_IE(ep->dma_channel);
+       omap_writew(w, UDC_DMA_IRQ_EN);
+       omap_writew(UDC_TXN_START | txdma_ctrl, UDC_TXDMA(ep->dma_channel));
+       req->dma_bytes = length;
+}
+
+static void finish_in_dma(struct omap_ep *ep, struct omap_req *req, int status)
+{
+       u16 w;
+
+       if (status == 0) {
+               req->req.actual += req->dma_bytes;
+
+               /* return if this request needs to send data or zlp */
+               if (req->req.actual < req->req.length)
+                       return;
+               if (req->req.zero
+                               && req->dma_bytes != 0
+                               && (req->req.actual % ep->maxpacket) == 0)
+                       return;
+       } else
+               req->req.actual += dma_src_len(ep, req->req.dma
+                                                       + req->req.actual);
+
+       /* tx completion */
+       omap_stop_dma(ep->lch);
+       w = omap_readw(UDC_DMA_IRQ_EN);
+       w &= ~UDC_TX_DONE_IE(ep->dma_channel);
+       omap_writew(w, UDC_DMA_IRQ_EN);
+       done(ep, req, status);
+}
+
+static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
+{
+       unsigned packets = req->req.length - req->req.actual;
+       int dma_trigger = 0;
+       u16 w;
+
+       /* set up this DMA transfer, enable the fifo, start */
+       packets /= ep->ep.maxpacket;
+       packets = min(packets, (unsigned)UDC_RXN_TC + 1);
+       req->dma_bytes = packets * ep->ep.maxpacket;
+       omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
+                       ep->ep.maxpacket >> 1, packets,
+                       OMAP_DMA_SYNC_ELEMENT,
+                       dma_trigger, 0);
+       omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
+               OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
+               0, 0);
+       ep->dma_counter = omap_get_dma_dst_pos(ep->lch);
+
+       omap_writew(UDC_RXN_STOP | (packets - 1), UDC_RXDMA(ep->dma_channel));
+       w = omap_readw(UDC_DMA_IRQ_EN);
+       w |= UDC_RX_EOT_IE(ep->dma_channel);
+       omap_writew(w, UDC_DMA_IRQ_EN);
+       omap_writew(ep->bEndpointAddress & 0xf, UDC_EP_NUM);
+       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+
+       omap_start_dma(ep->lch);
+}
+
+static void
+finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status, int one)
+{
+       u16     count, w;
+
+       if (status == 0)
+               ep->dma_counter = (u16) (req->req.dma + req->req.actual);
+       count = dma_dest_len(ep, req->req.dma + req->req.actual);
+       count += req->req.actual;
+       if (one)
+               count--;
+       if (count <= req->req.length)
+               req->req.actual = count;
+
+       if (count != req->dma_bytes || status)
+               omap_stop_dma(ep->lch);
+
+       /* if this wasn't short, request may need another transfer */
+       else if (req->req.actual < req->req.length)
+               return;
+
+       /* rx completion */
+       w = omap_readw(UDC_DMA_IRQ_EN);
+       w &= ~UDC_RX_EOT_IE(ep->dma_channel);
+       omap_writew(w, UDC_DMA_IRQ_EN);
+       done(ep, req, status);
+}
+
+static void dma_irq(struct omap_udc *udc, u16 irq_src)
+{
+       u16             dman_stat = omap_readw(UDC_DMAN_STAT);
+       struct omap_ep  *ep;
+       struct omap_req *req;
+
+       /* IN dma: tx to host */
+       if (irq_src & UDC_TXN_DONE) {
+               ep = &udc->ep[16 + UDC_DMA_TX_SRC(dman_stat)];
+               ep->irqs++;
+               /* can see TXN_DONE after dma abort */
+               if (!list_empty(&ep->queue)) {
+                       req = container_of(ep->queue.next,
+                                               struct omap_req, queue);
+                       finish_in_dma(ep, req, 0);
+               }
+               omap_writew(UDC_TXN_DONE, UDC_IRQ_SRC);
+
+               if (!list_empty(&ep->queue)) {
+                       req = container_of(ep->queue.next,
+                                       struct omap_req, queue);
+                       next_in_dma(ep, req);
+               }
+       }
+
+       /* OUT dma: rx from host */
+       if (irq_src & UDC_RXN_EOT) {
+               ep = &udc->ep[UDC_DMA_RX_SRC(dman_stat)];
+               ep->irqs++;
+               /* can see RXN_EOT after dma abort */
+               if (!list_empty(&ep->queue)) {
+                       req = container_of(ep->queue.next,
+                                       struct omap_req, queue);
+                       finish_out_dma(ep, req, 0, dman_stat & UDC_DMA_RX_SB);
+               }
+               omap_writew(UDC_RXN_EOT, UDC_IRQ_SRC);
+
+               if (!list_empty(&ep->queue)) {
+                       req = container_of(ep->queue.next,
+                                       struct omap_req, queue);
+                       next_out_dma(ep, req);
+               }
+       }
+
+       if (irq_src & UDC_RXN_CNT) {
+               ep = &udc->ep[UDC_DMA_RX_SRC(dman_stat)];
+               ep->irqs++;
+               /* omap15xx does this unasked... */
+               VDBG("%s, RX_CNT irq?\n", ep->ep.name);
+               omap_writew(UDC_RXN_CNT, UDC_IRQ_SRC);
+       }
+}
+
+static void dma_error(int lch, u16 ch_status, void *data)
+{
+       struct omap_ep  *ep = data;
+
+       /* if ch_status & OMAP_DMA_DROP_IRQ ... */
+       /* if ch_status & OMAP1_DMA_TOUT_IRQ ... */
+       ERR("%s dma error, lch %d status %02x\n", ep->ep.name, lch, ch_status);
+
+       /* complete current transfer ... */
+}
+
+static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
+{
+       u16     reg;
+       int     status, restart, is_in;
+       int     dma_channel;
+
+       is_in = ep->bEndpointAddress & USB_DIR_IN;
+       if (is_in)
+               reg = omap_readw(UDC_TXDMA_CFG);
+       else
+               reg = omap_readw(UDC_RXDMA_CFG);
+       reg |= UDC_DMA_REQ;             /* "pulse" activated */
+
+       ep->dma_channel = 0;
+       ep->lch = -1;
+       if (channel == 0 || channel > 3) {
+               if ((reg & 0x0f00) == 0)
+                       channel = 3;
+               else if ((reg & 0x00f0) == 0)
+                       channel = 2;
+               else if ((reg & 0x000f) == 0)   /* preferred for ISO */
+                       channel = 1;
+               else {
+                       status = -EMLINK;
+                       goto just_restart;
+               }
+       }
+       reg |= (0x0f & ep->bEndpointAddress) << (4 * (channel - 1));
+       ep->dma_channel = channel;
+
+       if (is_in) {
+               dma_channel = OMAP_DMA_USB_W2FC_TX0 - 1 + channel;
+               status = omap_request_dma(dma_channel,
+                       ep->ep.name, dma_error, ep, &ep->lch);
+               if (status == 0) {
+                       omap_writew(reg, UDC_TXDMA_CFG);
+                       /* EMIFF or SDRC */
+                       omap_set_dma_src_burst_mode(ep->lch,
+                                               OMAP_DMA_DATA_BURST_4);
+                       omap_set_dma_src_data_pack(ep->lch, 1);
+                       /* TIPB */
+                       omap_set_dma_dest_params(ep->lch,
+                               OMAP_DMA_PORT_TIPB,
+                               OMAP_DMA_AMODE_CONSTANT,
+                               UDC_DATA_DMA,
+                               0, 0);
+               }
+       } else {
+               dma_channel = OMAP_DMA_USB_W2FC_RX0 - 1 + channel;
+               status = omap_request_dma(dma_channel,
+                       ep->ep.name, dma_error, ep, &ep->lch);
+               if (status == 0) {
+                       omap_writew(reg, UDC_RXDMA_CFG);
+                       /* TIPB */
+                       omap_set_dma_src_params(ep->lch,
+                               OMAP_DMA_PORT_TIPB,
+                               OMAP_DMA_AMODE_CONSTANT,
+                               UDC_DATA_DMA,
+                               0, 0);
+                       /* EMIFF or SDRC */
+                       omap_set_dma_dest_burst_mode(ep->lch,
+                                               OMAP_DMA_DATA_BURST_4);
+                       omap_set_dma_dest_data_pack(ep->lch, 1);
+               }
+       }
+       if (status)
+               ep->dma_channel = 0;
+       else {
+               ep->has_dma = 1;
+               omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ);
+
+               /* channel type P: hw synch (fifo) */
+               if (!cpu_is_omap15xx())
+                       omap_set_dma_channel_mode(ep->lch, OMAP_DMA_LCH_P);
+       }
+
+just_restart:
+       /* restart any queue, even if the claim failed  */
+       restart = !ep->stopped && !list_empty(&ep->queue);
+
+       if (status)
+               DBG("%s no dma channel: %d%s\n", ep->ep.name, status,
+                       restart ? " (restart)" : "");
+       else
+               DBG("%s claimed %cxdma%d lch %d%s\n", ep->ep.name,
+                       is_in ? 't' : 'r',
+                       ep->dma_channel - 1, ep->lch,
+                       restart ? " (restart)" : "");
+
+       if (restart) {
+               struct omap_req *req;
+               req = container_of(ep->queue.next, struct omap_req, queue);
+               if (ep->has_dma)
+                       (is_in ? next_in_dma : next_out_dma)(ep, req);
+               else {
+                       use_ep(ep, UDC_EP_SEL);
+                       (is_in ? write_fifo : read_fifo)(ep, req);
+                       deselect_ep();
+                       if (!is_in) {
+                               omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+                               ep->ackwait = 1 + ep->double_buf;
+                       }
+                       /* IN: 6 wait states before it'll tx */
+               }
+       }
+}
+
+static void dma_channel_release(struct omap_ep *ep)
+{
+       int             shift = 4 * (ep->dma_channel - 1);
+       u16             mask = 0x0f << shift;
+       struct omap_req *req;
+       int             active;
+
+       /* abort any active usb transfer request */
+       if (!list_empty(&ep->queue))
+               req = container_of(ep->queue.next, struct omap_req, queue);
+       else
+               req = NULL;
+
+       active = omap_get_dma_active_status(ep->lch);
+
+       DBG("%s release %s %cxdma%d %p\n", ep->ep.name,
+                       active ? "active" : "idle",
+                       (ep->bEndpointAddress & USB_DIR_IN) ? 't' : 'r',
+                       ep->dma_channel - 1, req);
+
+       /* NOTE: re-setting RX_REQ/TX_REQ because of a chip bug (before
+        * OMAP 1710 ES2.0) where reading the DMA_CFG can clear them.
+        */
+
+       /* wait till current packet DMA finishes, and fifo empties */
+       if (ep->bEndpointAddress & USB_DIR_IN) {
+               omap_writew((omap_readw(UDC_TXDMA_CFG) & ~mask) | UDC_DMA_REQ,
+                                       UDC_TXDMA_CFG);
+
+               if (req) {
+                       finish_in_dma(ep, req, -ECONNRESET);
+
+                       /* clear FIFO; hosts probably won't empty it */
+                       use_ep(ep, UDC_EP_SEL);
+                       omap_writew(UDC_CLR_EP, UDC_CTRL);
+                       deselect_ep();
+               }
+               while (omap_readw(UDC_TXDMA_CFG) & mask)
+                       udelay(10);
+       } else {
+               omap_writew((omap_readw(UDC_RXDMA_CFG) & ~mask) | UDC_DMA_REQ,
+                                       UDC_RXDMA_CFG);
+
+               /* dma empties the fifo */
+               while (omap_readw(UDC_RXDMA_CFG) & mask)
+                       udelay(10);
+               if (req)
+                       finish_out_dma(ep, req, -ECONNRESET, 0);
+       }
+       omap_free_dma(ep->lch);
+       ep->dma_channel = 0;
+       ep->lch = -1;
+       /* has_dma still set, till endpoint is fully quiesced */
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static int
+omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
+       struct omap_req *req = container_of(_req, struct omap_req, req);
+       struct omap_udc *udc;
+       unsigned long   flags;
+       int             is_iso = 0;
+
+       /* catch various bogus parameters */
+       if (!_req || !req->req.complete || !req->req.buf
+                       || !list_empty(&req->queue)) {
+               DBG("%s, bad params\n", __func__);
+               return -EINVAL;
+       }
+       if (!_ep || (!ep->ep.desc && ep->bEndpointAddress)) {
+               DBG("%s, bad ep\n", __func__);
+               return -EINVAL;
+       }
+       if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+               if (req->req.length > ep->ep.maxpacket)
+                       return -EMSGSIZE;
+               is_iso = 1;
+       }
+
+       /* this isn't bogus, but OMAP DMA isn't the only hardware to
+        * have a hard time with partial packet reads...  reject it.
+        */
+       if (use_dma
+                       && ep->has_dma
+                       && ep->bEndpointAddress != 0
+                       && (ep->bEndpointAddress & USB_DIR_IN) == 0
+                       && (req->req.length % ep->ep.maxpacket) != 0) {
+               DBG("%s, no partial packet OUT reads\n", __func__);
+               return -EMSGSIZE;
+       }
+
+       udc = ep->udc;
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       if (use_dma && ep->has_dma)
+               usb_gadget_map_request(&udc->gadget, &req->req,
+                               (ep->bEndpointAddress & USB_DIR_IN));
+
+       VDBG("%s queue req %p, len %d buf %p\n",
+               ep->ep.name, _req, _req->length, _req->buf);
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       req->req.status = -EINPROGRESS;
+       req->req.actual = 0;
+
+       /* maybe kickstart non-iso i/o queues */
+       if (is_iso) {
+               u16 w;
+
+               w = omap_readw(UDC_IRQ_EN);
+               w |= UDC_SOF_IE;
+               omap_writew(w, UDC_IRQ_EN);
+       } else if (list_empty(&ep->queue) && !ep->stopped && !ep->ackwait) {
+               int     is_in;
+
+               if (ep->bEndpointAddress == 0) {
+                       if (!udc->ep0_pending || !list_empty(&ep->queue)) {
+                               spin_unlock_irqrestore(&udc->lock, flags);
+                               return -EL2HLT;
+                       }
+
+                       /* empty DATA stage? */
+                       is_in = udc->ep0_in;
+                       if (!req->req.length) {
+
+                               /* chip became CONFIGURED or ADDRESSED
+                                * earlier; drivers may already have queued
+                                * requests to non-control endpoints
+                                */
+                               if (udc->ep0_set_config) {
+                                       u16     irq_en = omap_readw(UDC_IRQ_EN);
+
+                                       irq_en |= UDC_DS_CHG_IE | UDC_EP0_IE;
+                                       if (!udc->ep0_reset_config)
+                                               irq_en |= UDC_EPN_RX_IE
+                                                       | UDC_EPN_TX_IE;
+                                       omap_writew(irq_en, UDC_IRQ_EN);
+                               }
+
+                               /* STATUS for zero length DATA stages is
+                                * always an IN ... even for IN transfers,
+                                * a weird case which seem to stall OMAP.
+                                */
+                               omap_writew(UDC_EP_SEL | UDC_EP_DIR,
+                                               UDC_EP_NUM);
+                               omap_writew(UDC_CLR_EP, UDC_CTRL);
+                               omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+                               omap_writew(UDC_EP_DIR, UDC_EP_NUM);
+
+                               /* cleanup */
+                               udc->ep0_pending = 0;
+                               done(ep, req, 0);
+                               req = NULL;
+
+                       /* non-empty DATA stage */
+                       } else if (is_in) {
+                               omap_writew(UDC_EP_SEL | UDC_EP_DIR,
+                                               UDC_EP_NUM);
+                       } else {
+                               if (udc->ep0_setup)
+                                       goto irq_wait;
+                               omap_writew(UDC_EP_SEL, UDC_EP_NUM);
+                       }
+               } else {
+                       is_in = ep->bEndpointAddress & USB_DIR_IN;
+                       if (!ep->has_dma)
+                               use_ep(ep, UDC_EP_SEL);
+                       /* if ISO: SOF IRQs must be enabled/disabled! */
+               }
+
+               if (ep->has_dma)
+                       (is_in ? next_in_dma : next_out_dma)(ep, req);
+               else if (req) {
+                       if ((is_in ? write_fifo : read_fifo)(ep, req) == 1)
+                               req = NULL;
+                       deselect_ep();
+                       if (!is_in) {
+                               omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+                               ep->ackwait = 1 + ep->double_buf;
+                       }
+                       /* IN: 6 wait states before it'll tx */
+               }
+       }
+
+irq_wait:
+       /* irq handler advances the queue */
+       if (req != NULL)
+               list_add_tail(&req->queue, &ep->queue);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static int omap_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
+       struct omap_req *req;
+       unsigned long   flags;
+
+       if (!_ep || !_req)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req) {
+               spin_unlock_irqrestore(&ep->udc->lock, flags);
+               return -EINVAL;
+       }
+
+       if (use_dma && ep->dma_channel && ep->queue.next == &req->queue) {
+               int channel = ep->dma_channel;
+
+               /* releasing the channel cancels the request,
+                * reclaiming the channel restarts the queue
+                */
+               dma_channel_release(ep);
+               dma_channel_claim(ep, channel);
+       } else
+               done(ep, req, -ECONNRESET);
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int omap_ep_set_halt(struct usb_ep *_ep, int value)
+{
+       struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
+       unsigned long   flags;
+       int             status = -EOPNOTSUPP;
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+
+       /* just use protocol stalls for ep0; real halts are annoying */
+       if (ep->bEndpointAddress == 0) {
+               if (!ep->udc->ep0_pending)
+                       status = -EINVAL;
+               else if (value) {
+                       if (ep->udc->ep0_set_config) {
+                               WARNING("error changing config?\n");
+                               omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
+                       }
+                       omap_writew(UDC_STALL_CMD, UDC_SYSCON2);
+                       ep->udc->ep0_pending = 0;
+                       status = 0;
+               } else /* NOP */
+                       status = 0;
+
+       /* otherwise, all active non-ISO endpoints can halt */
+       } else if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC && ep->ep.desc) {
+
+               /* IN endpoints must already be idle */
+               if ((ep->bEndpointAddress & USB_DIR_IN)
+                               && !list_empty(&ep->queue)) {
+                       status = -EAGAIN;
+                       goto done;
+               }
+
+               if (value) {
+                       int     channel;
+
+                       if (use_dma && ep->dma_channel
+                                       && !list_empty(&ep->queue)) {
+                               channel = ep->dma_channel;
+                               dma_channel_release(ep);
+                       } else
+                               channel = 0;
+
+                       use_ep(ep, UDC_EP_SEL);
+                       if (omap_readw(UDC_STAT_FLG) & UDC_NON_ISO_FIFO_EMPTY) {
+                               omap_writew(UDC_SET_HALT, UDC_CTRL);
+                               status = 0;
+                       } else
+                               status = -EAGAIN;
+                       deselect_ep();
+
+                       if (channel)
+                               dma_channel_claim(ep, channel);
+               } else {
+                       use_ep(ep, 0);
+                       omap_writew(ep->udc->clr_halt, UDC_CTRL);
+                       ep->ackwait = 0;
+                       if (!(ep->bEndpointAddress & USB_DIR_IN)) {
+                               omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+                               ep->ackwait = 1 + ep->double_buf;
+                       }
+               }
+       }
+done:
+       VDBG("%s %s halt stat %d\n", ep->ep.name,
+               value ? "set" : "clear", status);
+
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+       return status;
+}
+
+static struct usb_ep_ops omap_ep_ops = {
+       .enable         = omap_ep_enable,
+       .disable        = omap_ep_disable,
+
+       .alloc_request  = omap_alloc_request,
+       .free_request   = omap_free_request,
+
+       .queue          = omap_ep_queue,
+       .dequeue        = omap_ep_dequeue,
+
+       .set_halt       = omap_ep_set_halt,
+       /* fifo_status ... report bytes in fifo */
+       /* fifo_flush ... flush fifo */
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int omap_get_frame(struct usb_gadget *gadget)
+{
+       u16     sof = omap_readw(UDC_SOF);
+       return (sof & UDC_TS_OK) ? (sof & UDC_TS) : -EL2NSYNC;
+}
+
+static int omap_wakeup(struct usb_gadget *gadget)
+{
+       struct omap_udc *udc;
+       unsigned long   flags;
+       int             retval = -EHOSTUNREACH;
+
+       udc = container_of(gadget, struct omap_udc, gadget);
+
+       spin_lock_irqsave(&udc->lock, flags);
+       if (udc->devstat & UDC_SUS) {
+               /* NOTE:  OTG spec erratum says that OTG devices may
+                * issue wakeups without host enable.
+                */
+               if (udc->devstat & (UDC_B_HNP_ENABLE|UDC_R_WK_OK)) {
+                       DBG("remote wakeup...\n");
+                       omap_writew(UDC_RMT_WKP, UDC_SYSCON2);
+                       retval = 0;
+               }
+
+       /* NOTE:  non-OTG systems may use SRP TOO... */
+       } else if (!(udc->devstat & UDC_ATT)) {
+               if (!IS_ERR_OR_NULL(udc->transceiver))
+                       retval = otg_start_srp(udc->transceiver->otg);
+       }
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return retval;
+}
+
+static int
+omap_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
+{
+       struct omap_udc *udc;
+       unsigned long   flags;
+       u16             syscon1;
+
+       udc = container_of(gadget, struct omap_udc, gadget);
+       spin_lock_irqsave(&udc->lock, flags);
+       syscon1 = omap_readw(UDC_SYSCON1);
+       if (is_selfpowered)
+               syscon1 |= UDC_SELF_PWR;
+       else
+               syscon1 &= ~UDC_SELF_PWR;
+       omap_writew(syscon1, UDC_SYSCON1);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static int can_pullup(struct omap_udc *udc)
+{
+       return udc->driver && udc->softconnect && udc->vbus_active;
+}
+
+static void pullup_enable(struct omap_udc *udc)
+{
+       u16 w;
+
+       w = omap_readw(UDC_SYSCON1);
+       w |= UDC_PULLUP_EN;
+       omap_writew(w, UDC_SYSCON1);
+       if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) {
+               u32 l;
+
+               l = omap_readl(OTG_CTRL);
+               l |= OTG_BSESSVLD;
+               omap_writel(l, OTG_CTRL);
+       }
+       omap_writew(UDC_DS_CHG_IE, UDC_IRQ_EN);
+}
+
+static void pullup_disable(struct omap_udc *udc)
+{
+       u16 w;
+
+       if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) {
+               u32 l;
+
+               l = omap_readl(OTG_CTRL);
+               l &= ~OTG_BSESSVLD;
+               omap_writel(l, OTG_CTRL);
+       }
+       omap_writew(UDC_DS_CHG_IE, UDC_IRQ_EN);
+       w = omap_readw(UDC_SYSCON1);
+       w &= ~UDC_PULLUP_EN;
+       omap_writew(w, UDC_SYSCON1);
+}
+
+static struct omap_udc *udc;
+
+static void omap_udc_enable_clock(int enable)
+{
+       if (udc == NULL || udc->dc_clk == NULL || udc->hhc_clk == NULL)
+               return;
+
+       if (enable) {
+               clk_enable(udc->dc_clk);
+               clk_enable(udc->hhc_clk);
+               udelay(100);
+       } else {
+               clk_disable(udc->hhc_clk);
+               clk_disable(udc->dc_clk);
+       }
+}
+
+/*
+ * Called by whatever detects VBUS sessions:  external transceiver
+ * driver, or maybe GPIO0 VBUS IRQ.  May request 48 MHz clock.
+ */
+static int omap_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+       struct omap_udc *udc;
+       unsigned long   flags;
+       u32 l;
+
+       udc = container_of(gadget, struct omap_udc, gadget);
+       spin_lock_irqsave(&udc->lock, flags);
+       VDBG("VBUS %s\n", is_active ? "on" : "off");
+       udc->vbus_active = (is_active != 0);
+       if (cpu_is_omap15xx()) {
+               /* "software" detect, ignored if !VBUS_MODE_1510 */
+               l = omap_readl(FUNC_MUX_CTRL_0);
+               if (is_active)
+                       l |= VBUS_CTRL_1510;
+               else
+                       l &= ~VBUS_CTRL_1510;
+               omap_writel(l, FUNC_MUX_CTRL_0);
+       }
+       if (udc->dc_clk != NULL && is_active) {
+               if (!udc->clk_requested) {
+                       omap_udc_enable_clock(1);
+                       udc->clk_requested = 1;
+               }
+       }
+       if (can_pullup(udc))
+               pullup_enable(udc);
+       else
+               pullup_disable(udc);
+       if (udc->dc_clk != NULL && !is_active) {
+               if (udc->clk_requested) {
+                       omap_udc_enable_clock(0);
+                       udc->clk_requested = 0;
+               }
+       }
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int omap_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+       struct omap_udc *udc;
+
+       udc = container_of(gadget, struct omap_udc, gadget);
+       if (!IS_ERR_OR_NULL(udc->transceiver))
+               return usb_phy_set_power(udc->transceiver, mA);
+       return -EOPNOTSUPP;
+}
+
+static int omap_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct omap_udc *udc;
+       unsigned long   flags;
+
+       udc = container_of(gadget, struct omap_udc, gadget);
+       spin_lock_irqsave(&udc->lock, flags);
+       udc->softconnect = (is_on != 0);
+       if (can_pullup(udc))
+               pullup_enable(udc);
+       else
+               pullup_disable(udc);
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int omap_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+static int omap_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+
+static const struct usb_gadget_ops omap_gadget_ops = {
+       .get_frame              = omap_get_frame,
+       .wakeup                 = omap_wakeup,
+       .set_selfpowered        = omap_set_selfpowered,
+       .vbus_session           = omap_vbus_session,
+       .vbus_draw              = omap_vbus_draw,
+       .pullup                 = omap_pullup,
+       .udc_start              = omap_udc_start,
+       .udc_stop               = omap_udc_stop,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* dequeue ALL requests; caller holds udc->lock */
+static void nuke(struct omap_ep *ep, int status)
+{
+       struct omap_req *req;
+
+       ep->stopped = 1;
+
+       if (use_dma && ep->dma_channel)
+               dma_channel_release(ep);
+
+       use_ep(ep, 0);
+       omap_writew(UDC_CLR_EP, UDC_CTRL);
+       if (ep->bEndpointAddress && ep->bmAttributes != USB_ENDPOINT_XFER_ISOC)
+               omap_writew(UDC_SET_HALT, UDC_CTRL);
+
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct omap_req, queue);
+               done(ep, req, status);
+       }
+}
+
+/* caller holds udc->lock */
+static void udc_quiesce(struct omap_udc *udc)
+{
+       struct omap_ep  *ep;
+
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       nuke(&udc->ep[0], -ESHUTDOWN);
+       list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list)
+               nuke(ep, -ESHUTDOWN);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void update_otg(struct omap_udc *udc)
+{
+       u16     devstat;
+
+       if (!gadget_is_otg(&udc->gadget))
+               return;
+
+       if (omap_readl(OTG_CTRL) & OTG_ID)
+               devstat = omap_readw(UDC_DEVSTAT);
+       else
+               devstat = 0;
+
+       udc->gadget.b_hnp_enable = !!(devstat & UDC_B_HNP_ENABLE);
+       udc->gadget.a_hnp_support = !!(devstat & UDC_A_HNP_SUPPORT);
+       udc->gadget.a_alt_hnp_support = !!(devstat & UDC_A_ALT_HNP_SUPPORT);
+
+       /* Enable HNP early, avoiding races on suspend irq path.
+        * ASSUMES OTG state machine B_BUS_REQ input is true.
+        */
+       if (udc->gadget.b_hnp_enable) {
+               u32 l;
+
+               l = omap_readl(OTG_CTRL);
+               l |= OTG_B_HNPEN | OTG_B_BUSREQ;
+               l &= ~OTG_PULLUP;
+               omap_writel(l, OTG_CTRL);
+       }
+}
+
+static void ep0_irq(struct omap_udc *udc, u16 irq_src)
+{
+       struct omap_ep  *ep0 = &udc->ep[0];
+       struct omap_req *req = NULL;
+
+       ep0->irqs++;
+
+       /* Clear any pending requests and then scrub any rx/tx state
+        * before starting to handle the SETUP request.
+        */
+       if (irq_src & UDC_SETUP) {
+               u16     ack = irq_src & (UDC_EP0_TX|UDC_EP0_RX);
+
+               nuke(ep0, 0);
+               if (ack) {
+                       omap_writew(ack, UDC_IRQ_SRC);
+                       irq_src = UDC_SETUP;
+               }
+       }
+
+       /* IN/OUT packets mean we're in the DATA or STATUS stage.
+        * This driver uses only uses protocol stalls (ep0 never halts),
+        * and if we got this far the gadget driver already had a
+        * chance to stall.  Tries to be forgiving of host oddities.
+        *
+        * NOTE:  the last chance gadget drivers have to stall control
+        * requests is during their request completion callback.
+        */
+       if (!list_empty(&ep0->queue))
+               req = container_of(ep0->queue.next, struct omap_req, queue);
+
+       /* IN == TX to host */
+       if (irq_src & UDC_EP0_TX) {
+               int     stat;
+
+               omap_writew(UDC_EP0_TX, UDC_IRQ_SRC);
+               omap_writew(UDC_EP_SEL|UDC_EP_DIR, UDC_EP_NUM);
+               stat = omap_readw(UDC_STAT_FLG);
+               if (stat & UDC_ACK) {
+                       if (udc->ep0_in) {
+                               /* write next IN packet from response,
+                                * or set up the status stage.
+                                */
+                               if (req)
+                                       stat = write_fifo(ep0, req);
+                               omap_writew(UDC_EP_DIR, UDC_EP_NUM);
+                               if (!req && udc->ep0_pending) {
+                                       omap_writew(UDC_EP_SEL, UDC_EP_NUM);
+                                       omap_writew(UDC_CLR_EP, UDC_CTRL);
+                                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+                                       omap_writew(0, UDC_EP_NUM);
+                                       udc->ep0_pending = 0;
+                               } /* else:  6 wait states before it'll tx */
+                       } else {
+                               /* ack status stage of OUT transfer */
+                               omap_writew(UDC_EP_DIR, UDC_EP_NUM);
+                               if (req)
+                                       done(ep0, req, 0);
+                       }
+                       req = NULL;
+               } else if (stat & UDC_STALL) {
+                       omap_writew(UDC_CLR_HALT, UDC_CTRL);
+                       omap_writew(UDC_EP_DIR, UDC_EP_NUM);
+               } else {
+                       omap_writew(UDC_EP_DIR, UDC_EP_NUM);
+               }
+       }
+
+       /* OUT == RX from host */
+       if (irq_src & UDC_EP0_RX) {
+               int     stat;
+
+               omap_writew(UDC_EP0_RX, UDC_IRQ_SRC);
+               omap_writew(UDC_EP_SEL, UDC_EP_NUM);
+               stat = omap_readw(UDC_STAT_FLG);
+               if (stat & UDC_ACK) {
+                       if (!udc->ep0_in) {
+                               stat = 0;
+                               /* read next OUT packet of request, maybe
+                                * reactiviting the fifo; stall on errors.
+                                */
+                               stat = read_fifo(ep0, req);
+                               if (!req || stat < 0) {
+                                       omap_writew(UDC_STALL_CMD, UDC_SYSCON2);
+                                       udc->ep0_pending = 0;
+                                       stat = 0;
+                               } else if (stat == 0)
+                                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+                               omap_writew(0, UDC_EP_NUM);
+
+                               /* activate status stage */
+                               if (stat == 1) {
+                                       done(ep0, req, 0);
+                                       /* that may have STALLed ep0... */
+                                       omap_writew(UDC_EP_SEL | UDC_EP_DIR,
+                                                       UDC_EP_NUM);
+                                       omap_writew(UDC_CLR_EP, UDC_CTRL);
+                                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+                                       omap_writew(UDC_EP_DIR, UDC_EP_NUM);
+                                       udc->ep0_pending = 0;
+                               }
+                       } else {
+                               /* ack status stage of IN transfer */
+                               omap_writew(0, UDC_EP_NUM);
+                               if (req)
+                                       done(ep0, req, 0);
+                       }
+               } else if (stat & UDC_STALL) {
+                       omap_writew(UDC_CLR_HALT, UDC_CTRL);
+                       omap_writew(0, UDC_EP_NUM);
+               } else {
+                       omap_writew(0, UDC_EP_NUM);
+               }
+       }
+
+       /* SETUP starts all control transfers */
+       if (irq_src & UDC_SETUP) {
+               union u {
+                       u16                     word[4];
+                       struct usb_ctrlrequest  r;
+               } u;
+               int                     status = -EINVAL;
+               struct omap_ep          *ep;
+
+               /* read the (latest) SETUP message */
+               do {
+                       omap_writew(UDC_SETUP_SEL, UDC_EP_NUM);
+                       /* two bytes at a time */
+                       u.word[0] = omap_readw(UDC_DATA);
+                       u.word[1] = omap_readw(UDC_DATA);
+                       u.word[2] = omap_readw(UDC_DATA);
+                       u.word[3] = omap_readw(UDC_DATA);
+                       omap_writew(0, UDC_EP_NUM);
+               } while (omap_readw(UDC_IRQ_SRC) & UDC_SETUP);
+
+#define        w_value         le16_to_cpu(u.r.wValue)
+#define        w_index         le16_to_cpu(u.r.wIndex)
+#define        w_length        le16_to_cpu(u.r.wLength)
+
+               /* Delegate almost all control requests to the gadget driver,
+                * except for a handful of ch9 status/feature requests that
+                * hardware doesn't autodecode _and_ the gadget API hides.
+                */
+               udc->ep0_in = (u.r.bRequestType & USB_DIR_IN) != 0;
+               udc->ep0_set_config = 0;
+               udc->ep0_pending = 1;
+               ep0->stopped = 0;
+               ep0->ackwait = 0;
+               switch (u.r.bRequest) {
+               case USB_REQ_SET_CONFIGURATION:
+                       /* udc needs to know when ep != 0 is valid */
+                       if (u.r.bRequestType != USB_RECIP_DEVICE)
+                               goto delegate;
+                       if (w_length != 0)
+                               goto do_stall;
+                       udc->ep0_set_config = 1;
+                       udc->ep0_reset_config = (w_value == 0);
+                       VDBG("set config %d\n", w_value);
+
+                       /* update udc NOW since gadget driver may start
+                        * queueing requests immediately; clear config
+                        * later if it fails the request.
+                        */
+                       if (udc->ep0_reset_config)
+                               omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
+                       else
+                               omap_writew(UDC_DEV_CFG, UDC_SYSCON2);
+                       update_otg(udc);
+                       goto delegate;
+               case USB_REQ_CLEAR_FEATURE:
+                       /* clear endpoint halt */
+                       if (u.r.bRequestType != USB_RECIP_ENDPOINT)
+                               goto delegate;
+                       if (w_value != USB_ENDPOINT_HALT
+                                       || w_length != 0)
+                               goto do_stall;
+                       ep = &udc->ep[w_index & 0xf];
+                       if (ep != ep0) {
+                               if (w_index & USB_DIR_IN)
+                                       ep += 16;
+                               if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
+                                               || !ep->ep.desc)
+                                       goto do_stall;
+                               use_ep(ep, 0);
+                               omap_writew(udc->clr_halt, UDC_CTRL);
+                               ep->ackwait = 0;
+                               if (!(ep->bEndpointAddress & USB_DIR_IN)) {
+                                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+                                       ep->ackwait = 1 + ep->double_buf;
+                               }
+                               /* NOTE:  assumes the host behaves sanely,
+                                * only clearing real halts.  Else we may
+                                * need to kill pending transfers and then
+                                * restart the queue... very messy for DMA!
+                                */
+                       }
+                       VDBG("%s halt cleared by host\n", ep->name);
+                       goto ep0out_status_stage;
+               case USB_REQ_SET_FEATURE:
+                       /* set endpoint halt */
+                       if (u.r.bRequestType != USB_RECIP_ENDPOINT)
+                               goto delegate;
+                       if (w_value != USB_ENDPOINT_HALT
+                                       || w_length != 0)
+                               goto do_stall;
+                       ep = &udc->ep[w_index & 0xf];
+                       if (w_index & USB_DIR_IN)
+                               ep += 16;
+                       if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
+                                       || ep == ep0 || !ep->ep.desc)
+                               goto do_stall;
+                       if (use_dma && ep->has_dma) {
+                               /* this has rude side-effects (aborts) and
+                                * can't really work if DMA-IN is active
+                                */
+                               DBG("%s host set_halt, NYET\n", ep->name);
+                               goto do_stall;
+                       }
+                       use_ep(ep, 0);
+                       /* can't halt if fifo isn't empty... */
+                       omap_writew(UDC_CLR_EP, UDC_CTRL);
+                       omap_writew(UDC_SET_HALT, UDC_CTRL);
+                       VDBG("%s halted by host\n", ep->name);
+ep0out_status_stage:
+                       status = 0;
+                       omap_writew(UDC_EP_SEL|UDC_EP_DIR, UDC_EP_NUM);
+                       omap_writew(UDC_CLR_EP, UDC_CTRL);
+                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+                       omap_writew(UDC_EP_DIR, UDC_EP_NUM);
+                       udc->ep0_pending = 0;
+                       break;
+               case USB_REQ_GET_STATUS:
+                       /* USB_ENDPOINT_HALT status? */
+                       if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
+                               goto intf_status;
+
+                       /* ep0 never stalls */
+                       if (!(w_index & 0xf))
+                               goto zero_status;
+
+                       /* only active endpoints count */
+                       ep = &udc->ep[w_index & 0xf];
+                       if (w_index & USB_DIR_IN)
+                               ep += 16;
+                       if (!ep->ep.desc)
+                               goto do_stall;
+
+                       /* iso never stalls */
+                       if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
+                               goto zero_status;
+
+                       /* FIXME don't assume non-halted endpoints!! */
+                       ERR("%s status, can't report\n", ep->ep.name);
+                       goto do_stall;
+
+intf_status:
+                       /* return interface status.  if we were pedantic,
+                        * we'd detect non-existent interfaces, and stall.
+                        */
+                       if (u.r.bRequestType
+                                       != (USB_DIR_IN|USB_RECIP_INTERFACE))
+                               goto delegate;
+
+zero_status:
+                       /* return two zero bytes */
+                       omap_writew(UDC_EP_SEL|UDC_EP_DIR, UDC_EP_NUM);
+                       omap_writew(0, UDC_DATA);
+                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+                       omap_writew(UDC_EP_DIR, UDC_EP_NUM);
+                       status = 0;
+                       VDBG("GET_STATUS, interface %d\n", w_index);
+                       /* next, status stage */
+                       break;
+               default:
+delegate:
+                       /* activate the ep0out fifo right away */
+                       if (!udc->ep0_in && w_length) {
+                               omap_writew(0, UDC_EP_NUM);
+                               omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+                       }
+
+                       /* gadget drivers see class/vendor specific requests,
+                        * {SET,GET}_{INTERFACE,DESCRIPTOR,CONFIGURATION},
+                        * and more
+                        */
+                       VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n",
+                               u.r.bRequestType, u.r.bRequest,
+                               w_value, w_index, w_length);
+
+#undef w_value
+#undef w_index
+#undef w_length
+
+                       /* The gadget driver may return an error here,
+                        * causing an immediate protocol stall.
+                        *
+                        * Else it must issue a response, either queueing a
+                        * response buffer for the DATA stage, or halting ep0
+                        * (causing a protocol stall, not a real halt).  A
+                        * zero length buffer means no DATA stage.
+                        *
+                        * It's fine to issue that response after the setup()
+                        * call returns, and this IRQ was handled.
+                        */
+                       udc->ep0_setup = 1;
+                       spin_unlock(&udc->lock);
+                       status = udc->driver->setup(&udc->gadget, &u.r);
+                       spin_lock(&udc->lock);
+                       udc->ep0_setup = 0;
+               }
+
+               if (status < 0) {
+do_stall:
+                       VDBG("req %02x.%02x protocol STALL; stat %d\n",
+                                       u.r.bRequestType, u.r.bRequest, status);
+                       if (udc->ep0_set_config) {
+                               if (udc->ep0_reset_config)
+                                       WARNING("error resetting config?\n");
+                               else
+                                       omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
+                       }
+                       omap_writew(UDC_STALL_CMD, UDC_SYSCON2);
+                       udc->ep0_pending = 0;
+               }
+       }
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define OTG_FLAGS (UDC_B_HNP_ENABLE|UDC_A_HNP_SUPPORT|UDC_A_ALT_HNP_SUPPORT)
+
+static void devstate_irq(struct omap_udc *udc, u16 irq_src)
+{
+       u16     devstat, change;
+
+       devstat = omap_readw(UDC_DEVSTAT);
+       change = devstat ^ udc->devstat;
+       udc->devstat = devstat;
+
+       if (change & (UDC_USB_RESET|UDC_ATT)) {
+               udc_quiesce(udc);
+
+               if (change & UDC_ATT) {
+                       /* driver for any external transceiver will
+                        * have called omap_vbus_session() already
+                        */
+                       if (devstat & UDC_ATT) {
+                               udc->gadget.speed = USB_SPEED_FULL;
+                               VDBG("connect\n");
+                               if (IS_ERR_OR_NULL(udc->transceiver))
+                                       pullup_enable(udc);
+                               /* if (driver->connect) call it */
+                       } else if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+                               udc->gadget.speed = USB_SPEED_UNKNOWN;
+                               if (IS_ERR_OR_NULL(udc->transceiver))
+                                       pullup_disable(udc);
+                               DBG("disconnect, gadget %s\n",
+                                       udc->driver->driver.name);
+                               if (udc->driver->disconnect) {
+                                       spin_unlock(&udc->lock);
+                                       udc->driver->disconnect(&udc->gadget);
+                                       spin_lock(&udc->lock);
+                               }
+                       }
+                       change &= ~UDC_ATT;
+               }
+
+               if (change & UDC_USB_RESET) {
+                       if (devstat & UDC_USB_RESET) {
+                               VDBG("RESET=1\n");
+                       } else {
+                               udc->gadget.speed = USB_SPEED_FULL;
+                               INFO("USB reset done, gadget %s\n",
+                                       udc->driver->driver.name);
+                               /* ep0 traffic is legal from now on */
+                               omap_writew(UDC_DS_CHG_IE | UDC_EP0_IE,
+                                               UDC_IRQ_EN);
+                       }
+                       change &= ~UDC_USB_RESET;
+               }
+       }
+       if (change & UDC_SUS) {
+               if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+                       /* FIXME tell isp1301 to suspend/resume (?) */
+                       if (devstat & UDC_SUS) {
+                               VDBG("suspend\n");
+                               update_otg(udc);
+                               /* HNP could be under way already */
+                               if (udc->gadget.speed == USB_SPEED_FULL
+                                               && udc->driver->suspend) {
+                                       spin_unlock(&udc->lock);
+                                       udc->driver->suspend(&udc->gadget);
+                                       spin_lock(&udc->lock);
+                               }
+                               if (!IS_ERR_OR_NULL(udc->transceiver))
+                                       usb_phy_set_suspend(
+                                                       udc->transceiver, 1);
+                       } else {
+                               VDBG("resume\n");
+                               if (!IS_ERR_OR_NULL(udc->transceiver))
+                                       usb_phy_set_suspend(
+                                                       udc->transceiver, 0);
+                               if (udc->gadget.speed == USB_SPEED_FULL
+                                               && udc->driver->resume) {
+                                       spin_unlock(&udc->lock);
+                                       udc->driver->resume(&udc->gadget);
+                                       spin_lock(&udc->lock);
+                               }
+                       }
+               }
+               change &= ~UDC_SUS;
+       }
+       if (!cpu_is_omap15xx() && (change & OTG_FLAGS)) {
+               update_otg(udc);
+               change &= ~OTG_FLAGS;
+       }
+
+       change &= ~(UDC_CFG|UDC_DEF|UDC_ADD);
+       if (change)
+               VDBG("devstat %03x, ignore change %03x\n",
+                       devstat,  change);
+
+       omap_writew(UDC_DS_CHG, UDC_IRQ_SRC);
+}
+
+static irqreturn_t omap_udc_irq(int irq, void *_udc)
+{
+       struct omap_udc *udc = _udc;
+       u16             irq_src;
+       irqreturn_t     status = IRQ_NONE;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       irq_src = omap_readw(UDC_IRQ_SRC);
+
+       /* Device state change (usb ch9 stuff) */
+       if (irq_src & UDC_DS_CHG) {
+               devstate_irq(_udc, irq_src);
+               status = IRQ_HANDLED;
+               irq_src &= ~UDC_DS_CHG;
+       }
+
+       /* EP0 control transfers */
+       if (irq_src & (UDC_EP0_RX|UDC_SETUP|UDC_EP0_TX)) {
+               ep0_irq(_udc, irq_src);
+               status = IRQ_HANDLED;
+               irq_src &= ~(UDC_EP0_RX|UDC_SETUP|UDC_EP0_TX);
+       }
+
+       /* DMA transfer completion */
+       if (use_dma && (irq_src & (UDC_TXN_DONE|UDC_RXN_CNT|UDC_RXN_EOT))) {
+               dma_irq(_udc, irq_src);
+               status = IRQ_HANDLED;
+               irq_src &= ~(UDC_TXN_DONE|UDC_RXN_CNT|UDC_RXN_EOT);
+       }
+
+       irq_src &= ~(UDC_IRQ_SOF | UDC_EPN_TX|UDC_EPN_RX);
+       if (irq_src)
+               DBG("udc_irq, unhandled %03x\n", irq_src);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return status;
+}
+
+/* workaround for seemingly-lost IRQs for RX ACKs... */
+#define PIO_OUT_TIMEOUT        (jiffies + HZ/3)
+#define HALF_FULL(f)   (!((f)&(UDC_NON_ISO_FIFO_FULL|UDC_NON_ISO_FIFO_EMPTY)))
+
+static void pio_out_timer(unsigned long _ep)
+{
+       struct omap_ep  *ep = (void *) _ep;
+       unsigned long   flags;
+       u16             stat_flg;
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+       if (!list_empty(&ep->queue) && ep->ackwait) {
+               use_ep(ep, UDC_EP_SEL);
+               stat_flg = omap_readw(UDC_STAT_FLG);
+
+               if ((stat_flg & UDC_ACK) && (!(stat_flg & UDC_FIFO_EN)
+                               || (ep->double_buf && HALF_FULL(stat_flg)))) {
+                       struct omap_req *req;
+
+                       VDBG("%s: lose, %04x\n", ep->ep.name, stat_flg);
+                       req = container_of(ep->queue.next,
+                                       struct omap_req, queue);
+                       (void) read_fifo(ep, req);
+                       omap_writew(ep->bEndpointAddress, UDC_EP_NUM);
+                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+                       ep->ackwait = 1 + ep->double_buf;
+               } else
+                       deselect_ep();
+       }
+       mod_timer(&ep->timer, PIO_OUT_TIMEOUT);
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+}
+
+static irqreturn_t omap_udc_pio_irq(int irq, void *_dev)
+{
+       u16             epn_stat, irq_src;
+       irqreturn_t     status = IRQ_NONE;
+       struct omap_ep  *ep;
+       int             epnum;
+       struct omap_udc *udc = _dev;
+       struct omap_req *req;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       epn_stat = omap_readw(UDC_EPN_STAT);
+       irq_src = omap_readw(UDC_IRQ_SRC);
+
+       /* handle OUT first, to avoid some wasteful NAKs */
+       if (irq_src & UDC_EPN_RX) {
+               epnum = (epn_stat >> 8) & 0x0f;
+               omap_writew(UDC_EPN_RX, UDC_IRQ_SRC);
+               status = IRQ_HANDLED;
+               ep = &udc->ep[epnum];
+               ep->irqs++;
+
+               omap_writew(epnum | UDC_EP_SEL, UDC_EP_NUM);
+               ep->fnf = 0;
+               if (omap_readw(UDC_STAT_FLG) & UDC_ACK) {
+                       ep->ackwait--;
+                       if (!list_empty(&ep->queue)) {
+                               int stat;
+                               req = container_of(ep->queue.next,
+                                               struct omap_req, queue);
+                               stat = read_fifo(ep, req);
+                               if (!ep->double_buf)
+                                       ep->fnf = 1;
+                       }
+               }
+               /* min 6 clock delay before clearing EP_SEL ... */
+               epn_stat = omap_readw(UDC_EPN_STAT);
+               epn_stat = omap_readw(UDC_EPN_STAT);
+               omap_writew(epnum, UDC_EP_NUM);
+
+               /* enabling fifo _after_ clearing ACK, contrary to docs,
+                * reduces lossage; timer still needed though (sigh).
+                */
+               if (ep->fnf) {
+                       omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+                       ep->ackwait = 1 + ep->double_buf;
+               }
+               mod_timer(&ep->timer, PIO_OUT_TIMEOUT);
+       }
+
+       /* then IN transfers */
+       else if (irq_src & UDC_EPN_TX) {
+               epnum = epn_stat & 0x0f;
+               omap_writew(UDC_EPN_TX, UDC_IRQ_SRC);
+               status = IRQ_HANDLED;
+               ep = &udc->ep[16 + epnum];
+               ep->irqs++;
+
+               omap_writew(epnum | UDC_EP_DIR | UDC_EP_SEL, UDC_EP_NUM);
+               if (omap_readw(UDC_STAT_FLG) & UDC_ACK) {
+                       ep->ackwait = 0;
+                       if (!list_empty(&ep->queue)) {
+                               req = container_of(ep->queue.next,
+                                               struct omap_req, queue);
+                               (void) write_fifo(ep, req);
+                       }
+               }
+               /* min 6 clock delay before clearing EP_SEL ... */
+               epn_stat = omap_readw(UDC_EPN_STAT);
+               epn_stat = omap_readw(UDC_EPN_STAT);
+               omap_writew(epnum | UDC_EP_DIR, UDC_EP_NUM);
+               /* then 6 clocks before it'd tx */
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return status;
+}
+
+#ifdef USE_ISO
+static irqreturn_t omap_udc_iso_irq(int irq, void *_dev)
+{
+       struct omap_udc *udc = _dev;
+       struct omap_ep  *ep;
+       int             pending = 0;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /* handle all non-DMA ISO transfers */
+       list_for_each_entry(ep, &udc->iso, iso) {
+               u16             stat;
+               struct omap_req *req;
+
+               if (ep->has_dma || list_empty(&ep->queue))
+                       continue;
+               req = list_entry(ep->queue.next, struct omap_req, queue);
+
+               use_ep(ep, UDC_EP_SEL);
+               stat = omap_readw(UDC_STAT_FLG);
+
+               /* NOTE: like the other controller drivers, this isn't
+                * currently reporting lost or damaged frames.
+                */
+               if (ep->bEndpointAddress & USB_DIR_IN) {
+                       if (stat & UDC_MISS_IN)
+                               /* done(ep, req, -EPROTO) */;
+                       else
+                               write_fifo(ep, req);
+               } else {
+                       int     status = 0;
+
+                       if (stat & UDC_NO_RXPACKET)
+                               status = -EREMOTEIO;
+                       else if (stat & UDC_ISO_ERR)
+                               status = -EILSEQ;
+                       else if (stat & UDC_DATA_FLUSH)
+                               status = -ENOSR;
+
+                       if (status)
+                               /* done(ep, req, status) */;
+                       else
+                               read_fifo(ep, req);
+               }
+               deselect_ep();
+               /* 6 wait states before next EP */
+
+               ep->irqs++;
+               if (!list_empty(&ep->queue))
+                       pending = 1;
+       }
+       if (!pending) {
+               u16 w;
+
+               w = omap_readw(UDC_IRQ_EN);
+               w &= ~UDC_SOF_IE;
+               omap_writew(w, UDC_IRQ_EN);
+       }
+       omap_writew(UDC_IRQ_SOF, UDC_IRQ_SRC);
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return IRQ_HANDLED;
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static inline int machine_without_vbus_sense(void)
+{
+       return machine_is_omap_innovator()
+               || machine_is_omap_osk()
+               || machine_is_sx1()
+               /* No known omap7xx boards with vbus sense */
+               || cpu_is_omap7xx();
+}
+
+static int omap_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       int             status = -ENODEV;
+       struct omap_ep  *ep;
+       unsigned long   flags;
+
+
+       spin_lock_irqsave(&udc->lock, flags);
+       /* reset state */
+       list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
+               ep->irqs = 0;
+               if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
+                       continue;
+               use_ep(ep, 0);
+               omap_writew(UDC_SET_HALT, UDC_CTRL);
+       }
+       udc->ep0_pending = 0;
+       udc->ep[0].irqs = 0;
+       udc->softconnect = 1;
+
+       /* hook up the driver */
+       driver->driver.bus = NULL;
+       udc->driver = driver;
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       if (udc->dc_clk != NULL)
+               omap_udc_enable_clock(1);
+
+       omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
+
+       /* connect to bus through transceiver */
+       if (!IS_ERR_OR_NULL(udc->transceiver)) {
+               status = otg_set_peripheral(udc->transceiver->otg,
+                                               &udc->gadget);
+               if (status < 0) {
+                       ERR("can't bind to transceiver\n");
+                       udc->driver = NULL;
+                       goto done;
+               }
+       } else {
+               if (can_pullup(udc))
+                       pullup_enable(udc);
+               else
+                       pullup_disable(udc);
+       }
+
+       /* boards that don't have VBUS sensing can't autogate 48MHz;
+        * can't enter deep sleep while a gadget driver is active.
+        */
+       if (machine_without_vbus_sense())
+               omap_vbus_session(&udc->gadget, 1);
+
+done:
+       if (udc->dc_clk != NULL)
+               omap_udc_enable_clock(0);
+
+       return status;
+}
+
+static int omap_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       unsigned long   flags;
+       int             status = -ENODEV;
+
+       if (udc->dc_clk != NULL)
+               omap_udc_enable_clock(1);
+
+       if (machine_without_vbus_sense())
+               omap_vbus_session(&udc->gadget, 0);
+
+       if (!IS_ERR_OR_NULL(udc->transceiver))
+               (void) otg_set_peripheral(udc->transceiver->otg, NULL);
+       else
+               pullup_disable(udc);
+
+       spin_lock_irqsave(&udc->lock, flags);
+       udc_quiesce(udc);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       udc->driver = NULL;
+
+       if (udc->dc_clk != NULL)
+               omap_udc_enable_clock(0);
+
+       return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+#include <linux/seq_file.h>
+
+static const char proc_filename[] = "driver/udc";
+
+#define FOURBITS "%s%s%s%s"
+#define EIGHTBITS "%s%s%s%s%s%s%s%s"
+
+static void proc_ep_show(struct seq_file *s, struct omap_ep *ep)
+{
+       u16             stat_flg;
+       struct omap_req *req;
+       char            buf[20];
+
+       use_ep(ep, 0);
+
+       if (use_dma && ep->has_dma)
+               snprintf(buf, sizeof buf, "(%cxdma%d lch%d) ",
+                       (ep->bEndpointAddress & USB_DIR_IN) ? 't' : 'r',
+                       ep->dma_channel - 1, ep->lch);
+       else
+               buf[0] = 0;
+
+       stat_flg = omap_readw(UDC_STAT_FLG);
+       seq_printf(s,
+               "\n%s %s%s%sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n",
+               ep->name, buf,
+               ep->double_buf ? "dbuf " : "",
+               ({ char *s;
+               switch (ep->ackwait) {
+               case 0:
+                       s = "";
+                       break;
+               case 1:
+                       s = "(ackw) ";
+                       break;
+               case 2:
+                       s = "(ackw2) ";
+                       break;
+               default:
+                       s = "(?) ";
+                       break;
+               } s; }),
+               ep->irqs, stat_flg,
+               (stat_flg & UDC_NO_RXPACKET) ? "no_rxpacket " : "",
+               (stat_flg & UDC_MISS_IN) ? "miss_in " : "",
+               (stat_flg & UDC_DATA_FLUSH) ? "data_flush " : "",
+               (stat_flg & UDC_ISO_ERR) ? "iso_err " : "",
+               (stat_flg & UDC_ISO_FIFO_EMPTY) ? "iso_fifo_empty " : "",
+               (stat_flg & UDC_ISO_FIFO_FULL) ? "iso_fifo_full " : "",
+               (stat_flg & UDC_EP_HALTED) ? "HALT " : "",
+               (stat_flg & UDC_STALL) ? "STALL " : "",
+               (stat_flg & UDC_NAK) ? "NAK " : "",
+               (stat_flg & UDC_ACK) ? "ACK " : "",
+               (stat_flg & UDC_FIFO_EN) ? "fifo_en " : "",
+               (stat_flg & UDC_NON_ISO_FIFO_EMPTY) ? "fifo_empty " : "",
+               (stat_flg & UDC_NON_ISO_FIFO_FULL) ? "fifo_full " : "");
+
+       if (list_empty(&ep->queue))
+               seq_printf(s, "\t(queue empty)\n");
+       else
+               list_for_each_entry(req, &ep->queue, queue) {
+                       unsigned        length = req->req.actual;
+
+                       if (use_dma && buf[0]) {
+                               length += ((ep->bEndpointAddress & USB_DIR_IN)
+                                               ? dma_src_len : dma_dest_len)
+                                       (ep, req->req.dma + length);
+                               buf[0] = 0;
+                       }
+                       seq_printf(s, "\treq %p len %d/%d buf %p\n",
+                                       &req->req, length,
+                                       req->req.length, req->req.buf);
+               }
+}
+
+static char *trx_mode(unsigned m, int enabled)
+{
+       switch (m) {
+       case 0:
+               return enabled ? "*6wire" : "unused";
+       case 1:
+               return "4wire";
+       case 2:
+               return "3wire";
+       case 3:
+               return "6wire";
+       default:
+               return "unknown";
+       }
+}
+
+static int proc_otg_show(struct seq_file *s)
+{
+       u32             tmp;
+       u32             trans = 0;
+       char            *ctrl_name = "(UNKNOWN)";
+
+       tmp = omap_readl(OTG_REV);
+       ctrl_name = "tranceiver_ctrl";
+       trans = omap_readw(USB_TRANSCEIVER_CTRL);
+       seq_printf(s, "\nOTG rev %d.%d, %s %05x\n",
+               tmp >> 4, tmp & 0xf, ctrl_name, trans);
+       tmp = omap_readw(OTG_SYSCON_1);
+       seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s,"
+                       FOURBITS "\n", tmp,
+               trx_mode(USB2_TRX_MODE(tmp), trans & CONF_USB2_UNI_R),
+               trx_mode(USB1_TRX_MODE(tmp), trans & CONF_USB1_UNI_R),
+               (USB0_TRX_MODE(tmp) == 0 && !cpu_is_omap1710())
+                       ? "internal"
+                       : trx_mode(USB0_TRX_MODE(tmp), 1),
+               (tmp & OTG_IDLE_EN) ? " !otg" : "",
+               (tmp & HST_IDLE_EN) ? " !host" : "",
+               (tmp & DEV_IDLE_EN) ? " !dev" : "",
+               (tmp & OTG_RESET_DONE) ? " reset_done" : " reset_active");
+       tmp = omap_readl(OTG_SYSCON_2);
+       seq_printf(s, "otg_syscon2 %08x%s" EIGHTBITS
+                       " b_ase_brst=%d hmc=%d\n", tmp,
+               (tmp & OTG_EN) ? " otg_en" : "",
+               (tmp & USBX_SYNCHRO) ? " synchro" : "",
+               /* much more SRP stuff */
+               (tmp & SRP_DATA) ? " srp_data" : "",
+               (tmp & SRP_VBUS) ? " srp_vbus" : "",
+               (tmp & OTG_PADEN) ? " otg_paden" : "",
+               (tmp & HMC_PADEN) ? " hmc_paden" : "",
+               (tmp & UHOST_EN) ? " uhost_en" : "",
+               (tmp & HMC_TLLSPEED) ? " tllspeed" : "",
+               (tmp & HMC_TLLATTACH) ? " tllattach" : "",
+               B_ASE_BRST(tmp),
+               OTG_HMC(tmp));
+       tmp = omap_readl(OTG_CTRL);
+       seq_printf(s, "otg_ctrl    %06x" EIGHTBITS EIGHTBITS "%s\n", tmp,
+               (tmp & OTG_ASESSVLD) ? " asess" : "",
+               (tmp & OTG_BSESSEND) ? " bsess_end" : "",
+               (tmp & OTG_BSESSVLD) ? " bsess" : "",
+               (tmp & OTG_VBUSVLD) ? " vbus" : "",
+               (tmp & OTG_ID) ? " id" : "",
+               (tmp & OTG_DRIVER_SEL) ? " DEVICE" : " HOST",
+               (tmp & OTG_A_SETB_HNPEN) ? " a_setb_hnpen" : "",
+               (tmp & OTG_A_BUSREQ) ? " a_bus" : "",
+               (tmp & OTG_B_HNPEN) ? " b_hnpen" : "",
+               (tmp & OTG_B_BUSREQ) ? " b_bus" : "",
+               (tmp & OTG_BUSDROP) ? " busdrop" : "",
+               (tmp & OTG_PULLDOWN) ? " down" : "",
+               (tmp & OTG_PULLUP) ? " up" : "",
+               (tmp & OTG_DRV_VBUS) ? " drv" : "",
+               (tmp & OTG_PD_VBUS) ? " pd_vb" : "",
+               (tmp & OTG_PU_VBUS) ? " pu_vb" : "",
+               (tmp & OTG_PU_ID) ? " pu_id" : ""
+               );
+       tmp = omap_readw(OTG_IRQ_EN);
+       seq_printf(s, "otg_irq_en  %04x" "\n", tmp);
+       tmp = omap_readw(OTG_IRQ_SRC);
+       seq_printf(s, "otg_irq_src %04x" "\n", tmp);
+       tmp = omap_readw(OTG_OUTCTRL);
+       seq_printf(s, "otg_outctrl %04x" "\n", tmp);
+       tmp = omap_readw(OTG_TEST);
+       seq_printf(s, "otg_test    %04x" "\n", tmp);
+       return 0;
+}
+
+static int proc_udc_show(struct seq_file *s, void *_)
+{
+       u32             tmp;
+       struct omap_ep  *ep;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       seq_printf(s, "%s, version: " DRIVER_VERSION
+#ifdef USE_ISO
+               " (iso)"
+#endif
+               "%s\n",
+               driver_desc,
+               use_dma ?  " (dma)" : "");
+
+       tmp = omap_readw(UDC_REV) & 0xff;
+       seq_printf(s,
+               "UDC rev %d.%d, fifo mode %d, gadget %s\n"
+               "hmc %d, transceiver %s\n",
+               tmp >> 4, tmp & 0xf,
+               fifo_mode,
+               udc->driver ? udc->driver->driver.name : "(none)",
+               HMC,
+               udc->transceiver
+                       ? udc->transceiver->label
+                       : (cpu_is_omap1710()
+                               ? "external" : "(none)"));
+       seq_printf(s, "ULPD control %04x req %04x status %04x\n",
+               omap_readw(ULPD_CLOCK_CTRL),
+               omap_readw(ULPD_SOFT_REQ),
+               omap_readw(ULPD_STATUS_REQ));
+
+       /* OTG controller registers */
+       if (!cpu_is_omap15xx())
+               proc_otg_show(s);
+
+       tmp = omap_readw(UDC_SYSCON1);
+       seq_printf(s, "\nsyscon1     %04x" EIGHTBITS "\n", tmp,
+               (tmp & UDC_CFG_LOCK) ? " cfg_lock" : "",
+               (tmp & UDC_DATA_ENDIAN) ? " data_endian" : "",
+               (tmp & UDC_DMA_ENDIAN) ? " dma_endian" : "",
+               (tmp & UDC_NAK_EN) ? " nak" : "",
+               (tmp & UDC_AUTODECODE_DIS) ? " autodecode_dis" : "",
+               (tmp & UDC_SELF_PWR) ? " self_pwr" : "",
+               (tmp & UDC_SOFF_DIS) ? " soff_dis" : "",
+               (tmp & UDC_PULLUP_EN) ? " PULLUP" : "");
+       /* syscon2 is write-only */
+
+       /* UDC controller registers */
+       if (!(tmp & UDC_PULLUP_EN)) {
+               seq_printf(s, "(suspended)\n");
+               spin_unlock_irqrestore(&udc->lock, flags);
+               return 0;
+       }
+
+       tmp = omap_readw(UDC_DEVSTAT);
+       seq_printf(s, "devstat     %04x" EIGHTBITS "%s%s\n", tmp,
+               (tmp & UDC_B_HNP_ENABLE) ? " b_hnp" : "",
+               (tmp & UDC_A_HNP_SUPPORT) ? " a_hnp" : "",
+               (tmp & UDC_A_ALT_HNP_SUPPORT) ? " a_alt_hnp" : "",
+               (tmp & UDC_R_WK_OK) ? " r_wk_ok" : "",
+               (tmp & UDC_USB_RESET) ? " usb_reset" : "",
+               (tmp & UDC_SUS) ? " SUS" : "",
+               (tmp & UDC_CFG) ? " CFG" : "",
+               (tmp & UDC_ADD) ? " ADD" : "",
+               (tmp & UDC_DEF) ? " DEF" : "",
+               (tmp & UDC_ATT) ? " ATT" : "");
+       seq_printf(s, "sof         %04x\n", omap_readw(UDC_SOF));
+       tmp = omap_readw(UDC_IRQ_EN);
+       seq_printf(s, "irq_en      %04x" FOURBITS "%s\n", tmp,
+               (tmp & UDC_SOF_IE) ? " sof" : "",
+               (tmp & UDC_EPN_RX_IE) ? " epn_rx" : "",
+               (tmp & UDC_EPN_TX_IE) ? " epn_tx" : "",
+               (tmp & UDC_DS_CHG_IE) ? " ds_chg" : "",
+               (tmp & UDC_EP0_IE) ? " ep0" : "");
+       tmp = omap_readw(UDC_IRQ_SRC);
+       seq_printf(s, "irq_src     %04x" EIGHTBITS "%s%s\n", tmp,
+               (tmp & UDC_TXN_DONE) ? " txn_done" : "",
+               (tmp & UDC_RXN_CNT) ? " rxn_cnt" : "",
+               (tmp & UDC_RXN_EOT) ? " rxn_eot" : "",
+               (tmp & UDC_IRQ_SOF) ? " sof" : "",
+               (tmp & UDC_EPN_RX) ? " epn_rx" : "",
+               (tmp & UDC_EPN_TX) ? " epn_tx" : "",
+               (tmp & UDC_DS_CHG) ? " ds_chg" : "",
+               (tmp & UDC_SETUP) ? " setup" : "",
+               (tmp & UDC_EP0_RX) ? " ep0out" : "",
+               (tmp & UDC_EP0_TX) ? " ep0in" : "");
+       if (use_dma) {
+               unsigned i;
+
+               tmp = omap_readw(UDC_DMA_IRQ_EN);
+               seq_printf(s, "dma_irq_en  %04x%s" EIGHTBITS "\n", tmp,
+                       (tmp & UDC_TX_DONE_IE(3)) ? " tx2_done" : "",
+                       (tmp & UDC_RX_CNT_IE(3)) ? " rx2_cnt" : "",
+                       (tmp & UDC_RX_EOT_IE(3)) ? " rx2_eot" : "",
+
+                       (tmp & UDC_TX_DONE_IE(2)) ? " tx1_done" : "",
+                       (tmp & UDC_RX_CNT_IE(2)) ? " rx1_cnt" : "",
+                       (tmp & UDC_RX_EOT_IE(2)) ? " rx1_eot" : "",
+
+                       (tmp & UDC_TX_DONE_IE(1)) ? " tx0_done" : "",
+                       (tmp & UDC_RX_CNT_IE(1)) ? " rx0_cnt" : "",
+                       (tmp & UDC_RX_EOT_IE(1)) ? " rx0_eot" : "");
+
+               tmp = omap_readw(UDC_RXDMA_CFG);
+               seq_printf(s, "rxdma_cfg   %04x\n", tmp);
+               if (tmp) {
+                       for (i = 0; i < 3; i++) {
+                               if ((tmp & (0x0f << (i * 4))) == 0)
+                                       continue;
+                               seq_printf(s, "rxdma[%d]    %04x\n", i,
+                                               omap_readw(UDC_RXDMA(i + 1)));
+                       }
+               }
+               tmp = omap_readw(UDC_TXDMA_CFG);
+               seq_printf(s, "txdma_cfg   %04x\n", tmp);
+               if (tmp) {
+                       for (i = 0; i < 3; i++) {
+                               if (!(tmp & (0x0f << (i * 4))))
+                                       continue;
+                               seq_printf(s, "txdma[%d]    %04x\n", i,
+                                               omap_readw(UDC_TXDMA(i + 1)));
+                       }
+               }
+       }
+
+       tmp = omap_readw(UDC_DEVSTAT);
+       if (tmp & UDC_ATT) {
+               proc_ep_show(s, &udc->ep[0]);
+               if (tmp & UDC_ADD) {
+                       list_for_each_entry(ep, &udc->gadget.ep_list,
+                                       ep.ep_list) {
+                               if (ep->ep.desc)
+                                       proc_ep_show(s, ep);
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int proc_udc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, proc_udc_show, NULL);
+}
+
+static const struct file_operations proc_ops = {
+       .owner          = THIS_MODULE,
+       .open           = proc_udc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static void create_proc_file(void)
+{
+       proc_create(proc_filename, 0, NULL, &proc_ops);
+}
+
+static void remove_proc_file(void)
+{
+       remove_proc_entry(proc_filename, NULL);
+}
+
+#else
+
+static inline void create_proc_file(void) {}
+static inline void remove_proc_file(void) {}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* Before this controller can enumerate, we need to pick an endpoint
+ * configuration, or "fifo_mode"  That involves allocating 2KB of packet
+ * buffer space among the endpoints we'll be operating.
+ *
+ * NOTE: as of OMAP 1710 ES2.0, writing a new endpoint config when
+ * UDC_SYSCON_1.CFG_LOCK is set can now work.  We won't use that
+ * capability yet though.
+ */
+static unsigned
+omap_ep_setup(char *name, u8 addr, u8 type,
+               unsigned buf, unsigned maxp, int dbuf)
+{
+       struct omap_ep  *ep;
+       u16             epn_rxtx = 0;
+
+       /* OUT endpoints first, then IN */
+       ep = &udc->ep[addr & 0xf];
+       if (addr & USB_DIR_IN)
+               ep += 16;
+
+       /* in case of ep init table bugs */
+       BUG_ON(ep->name[0]);
+
+       /* chip setup ... bit values are same for IN, OUT */
+       if (type == USB_ENDPOINT_XFER_ISOC) {
+               switch (maxp) {
+               case 8:
+                       epn_rxtx = 0 << 12;
+                       break;
+               case 16:
+                       epn_rxtx = 1 << 12;
+                       break;
+               case 32:
+                       epn_rxtx = 2 << 12;
+                       break;
+               case 64:
+                       epn_rxtx = 3 << 12;
+                       break;
+               case 128:
+                       epn_rxtx = 4 << 12;
+                       break;
+               case 256:
+                       epn_rxtx = 5 << 12;
+                       break;
+               case 512:
+                       epn_rxtx = 6 << 12;
+                       break;
+               default:
+                       BUG();
+               }
+               epn_rxtx |= UDC_EPN_RX_ISO;
+               dbuf = 1;
+       } else {
+               /* double-buffering "not supported" on 15xx,
+                * and ignored for PIO-IN on newer chips
+                * (for more reliable behavior)
+                */
+               if (!use_dma || cpu_is_omap15xx())
+                       dbuf = 0;
+
+               switch (maxp) {
+               case 8:
+                       epn_rxtx = 0 << 12;
+                       break;
+               case 16:
+                       epn_rxtx = 1 << 12;
+                       break;
+               case 32:
+                       epn_rxtx = 2 << 12;
+                       break;
+               case 64:
+                       epn_rxtx = 3 << 12;
+                       break;
+               default:
+                       BUG();
+               }
+               if (dbuf && addr)
+                       epn_rxtx |= UDC_EPN_RX_DB;
+               init_timer(&ep->timer);
+               ep->timer.function = pio_out_timer;
+               ep->timer.data = (unsigned long) ep;
+       }
+       if (addr)
+               epn_rxtx |= UDC_EPN_RX_VALID;
+       BUG_ON(buf & 0x07);
+       epn_rxtx |= buf >> 3;
+
+       DBG("%s addr %02x rxtx %04x maxp %d%s buf %d\n",
+               name, addr, epn_rxtx, maxp, dbuf ? "x2" : "", buf);
+
+       if (addr & USB_DIR_IN)
+               omap_writew(epn_rxtx, UDC_EP_TX(addr & 0xf));
+       else
+               omap_writew(epn_rxtx, UDC_EP_RX(addr));
+
+       /* next endpoint's buffer starts after this one's */
+       buf += maxp;
+       if (dbuf)
+               buf += maxp;
+       BUG_ON(buf > 2048);
+
+       /* set up driver data structures */
+       BUG_ON(strlen(name) >= sizeof ep->name);
+       strlcpy(ep->name, name, sizeof ep->name);
+       INIT_LIST_HEAD(&ep->queue);
+       INIT_LIST_HEAD(&ep->iso);
+       ep->bEndpointAddress = addr;
+       ep->bmAttributes = type;
+       ep->double_buf = dbuf;
+       ep->udc = udc;
+
+       ep->ep.name = ep->name;
+       ep->ep.ops = &omap_ep_ops;
+       ep->maxpacket = maxp;
+       usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
+       list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+
+       return buf;
+}
+
+static void omap_udc_release(struct device *dev)
+{
+       complete(udc->done);
+       kfree(udc);
+       udc = NULL;
+}
+
+static int
+omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
+{
+       unsigned        tmp, buf;
+
+       /* abolish any previous hardware state */
+       omap_writew(0, UDC_SYSCON1);
+       omap_writew(0, UDC_IRQ_EN);
+       omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
+       omap_writew(0, UDC_DMA_IRQ_EN);
+       omap_writew(0, UDC_RXDMA_CFG);
+       omap_writew(0, UDC_TXDMA_CFG);
+
+       /* UDC_PULLUP_EN gates the chip clock */
+       /* OTG_SYSCON_1 |= DEV_IDLE_EN; */
+
+       udc = kzalloc(sizeof(*udc), GFP_KERNEL);
+       if (!udc)
+               return -ENOMEM;
+
+       spin_lock_init(&udc->lock);
+
+       udc->gadget.ops = &omap_gadget_ops;
+       udc->gadget.ep0 = &udc->ep[0].ep;
+       INIT_LIST_HEAD(&udc->gadget.ep_list);
+       INIT_LIST_HEAD(&udc->iso);
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       udc->gadget.max_speed = USB_SPEED_FULL;
+       udc->gadget.name = driver_name;
+       udc->transceiver = xceiv;
+
+       /* ep0 is special; put it right after the SETUP buffer */
+       buf = omap_ep_setup("ep0", 0, USB_ENDPOINT_XFER_CONTROL,
+                       8 /* after SETUP */, 64 /* maxpacket */, 0);
+       list_del_init(&udc->ep[0].ep.ep_list);
+
+       /* initially disable all non-ep0 endpoints */
+       for (tmp = 1; tmp < 15; tmp++) {
+               omap_writew(0, UDC_EP_RX(tmp));
+               omap_writew(0, UDC_EP_TX(tmp));
+       }
+
+#define OMAP_BULK_EP(name, addr) \
+       buf = omap_ep_setup(name "-bulk", addr, \
+                       USB_ENDPOINT_XFER_BULK, buf, 64, 1);
+#define OMAP_INT_EP(name, addr, maxp) \
+       buf = omap_ep_setup(name "-int", addr, \
+                       USB_ENDPOINT_XFER_INT, buf, maxp, 0);
+#define OMAP_ISO_EP(name, addr, maxp) \
+       buf = omap_ep_setup(name "-iso", addr, \
+                       USB_ENDPOINT_XFER_ISOC, buf, maxp, 1);
+
+       switch (fifo_mode) {
+       case 0:
+               OMAP_BULK_EP("ep1in",  USB_DIR_IN  | 1);
+               OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2);
+               OMAP_INT_EP("ep3in",   USB_DIR_IN  | 3, 16);
+               break;
+       case 1:
+               OMAP_BULK_EP("ep1in",  USB_DIR_IN  | 1);
+               OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2);
+               OMAP_INT_EP("ep9in",   USB_DIR_IN  | 9, 16);
+
+               OMAP_BULK_EP("ep3in",  USB_DIR_IN  | 3);
+               OMAP_BULK_EP("ep4out", USB_DIR_OUT | 4);
+               OMAP_INT_EP("ep10in",  USB_DIR_IN  | 10, 16);
+
+               OMAP_BULK_EP("ep5in",  USB_DIR_IN  | 5);
+               OMAP_BULK_EP("ep5out", USB_DIR_OUT | 5);
+               OMAP_INT_EP("ep11in",  USB_DIR_IN  | 11, 16);
+
+               OMAP_BULK_EP("ep6in",  USB_DIR_IN  | 6);
+               OMAP_BULK_EP("ep6out", USB_DIR_OUT | 6);
+               OMAP_INT_EP("ep12in",  USB_DIR_IN  | 12, 16);
+
+               OMAP_BULK_EP("ep7in",  USB_DIR_IN  | 7);
+               OMAP_BULK_EP("ep7out", USB_DIR_OUT | 7);
+               OMAP_INT_EP("ep13in",  USB_DIR_IN  | 13, 16);
+               OMAP_INT_EP("ep13out", USB_DIR_OUT | 13, 16);
+
+               OMAP_BULK_EP("ep8in",  USB_DIR_IN  | 8);
+               OMAP_BULK_EP("ep8out", USB_DIR_OUT | 8);
+               OMAP_INT_EP("ep14in",  USB_DIR_IN  | 14, 16);
+               OMAP_INT_EP("ep14out", USB_DIR_OUT | 14, 16);
+
+               OMAP_BULK_EP("ep15in",  USB_DIR_IN  | 15);
+               OMAP_BULK_EP("ep15out", USB_DIR_OUT | 15);
+
+               break;
+
+#ifdef USE_ISO
+       case 2:                 /* mixed iso/bulk */
+               OMAP_ISO_EP("ep1in",   USB_DIR_IN  | 1, 256);
+               OMAP_ISO_EP("ep2out",  USB_DIR_OUT | 2, 256);
+               OMAP_ISO_EP("ep3in",   USB_DIR_IN  | 3, 128);
+               OMAP_ISO_EP("ep4out",  USB_DIR_OUT | 4, 128);
+
+               OMAP_INT_EP("ep5in",   USB_DIR_IN  | 5, 16);
+
+               OMAP_BULK_EP("ep6in",  USB_DIR_IN  | 6);
+               OMAP_BULK_EP("ep7out", USB_DIR_OUT | 7);
+               OMAP_INT_EP("ep8in",   USB_DIR_IN  | 8, 16);
+               break;
+       case 3:                 /* mixed bulk/iso */
+               OMAP_BULK_EP("ep1in",  USB_DIR_IN  | 1);
+               OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2);
+               OMAP_INT_EP("ep3in",   USB_DIR_IN  | 3, 16);
+
+               OMAP_BULK_EP("ep4in",  USB_DIR_IN  | 4);
+               OMAP_BULK_EP("ep5out", USB_DIR_OUT | 5);
+               OMAP_INT_EP("ep6in",   USB_DIR_IN  | 6, 16);
+
+               OMAP_ISO_EP("ep7in",   USB_DIR_IN  | 7, 256);
+               OMAP_ISO_EP("ep8out",  USB_DIR_OUT | 8, 256);
+               OMAP_INT_EP("ep9in",   USB_DIR_IN  | 9, 16);
+               break;
+#endif
+
+       /* add more modes as needed */
+
+       default:
+               ERR("unsupported fifo_mode #%d\n", fifo_mode);
+               return -ENODEV;
+       }
+       omap_writew(UDC_CFG_LOCK|UDC_SELF_PWR, UDC_SYSCON1);
+       INFO("fifo mode %d, %d bytes not used\n", fifo_mode, 2048 - buf);
+       return 0;
+}
+
+static int omap_udc_probe(struct platform_device *pdev)
+{
+       int                     status = -ENODEV;
+       int                     hmc;
+       struct usb_phy          *xceiv = NULL;
+       const char              *type = NULL;
+       struct omap_usb_config  *config = dev_get_platdata(&pdev->dev);
+       struct clk              *dc_clk = NULL;
+       struct clk              *hhc_clk = NULL;
+
+       if (cpu_is_omap7xx())
+               use_dma = 0;
+
+       /* NOTE:  "knows" the order of the resources! */
+       if (!request_mem_region(pdev->resource[0].start,
+                       pdev->resource[0].end - pdev->resource[0].start + 1,
+                       driver_name)) {
+               DBG("request_mem_region failed\n");
+               return -EBUSY;
+       }
+
+       if (cpu_is_omap16xx()) {
+               dc_clk = clk_get(&pdev->dev, "usb_dc_ck");
+               hhc_clk = clk_get(&pdev->dev, "usb_hhc_ck");
+               BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
+               /* can't use omap_udc_enable_clock yet */
+               clk_enable(dc_clk);
+               clk_enable(hhc_clk);
+               udelay(100);
+       }
+
+       if (cpu_is_omap7xx()) {
+               dc_clk = clk_get(&pdev->dev, "usb_dc_ck");
+               hhc_clk = clk_get(&pdev->dev, "l3_ocpi_ck");
+               BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
+               /* can't use omap_udc_enable_clock yet */
+               clk_enable(dc_clk);
+               clk_enable(hhc_clk);
+               udelay(100);
+       }
+
+       INFO("OMAP UDC rev %d.%d%s\n",
+               omap_readw(UDC_REV) >> 4, omap_readw(UDC_REV) & 0xf,
+               config->otg ? ", Mini-AB" : "");
+
+       /* use the mode given to us by board init code */
+       if (cpu_is_omap15xx()) {
+               hmc = HMC_1510;
+               type = "(unknown)";
+
+               if (machine_without_vbus_sense()) {
+                       /* just set up software VBUS detect, and then
+                        * later rig it so we always report VBUS.
+                        * FIXME without really sensing VBUS, we can't
+                        * know when to turn PULLUP_EN on/off; and that
+                        * means we always "need" the 48MHz clock.
+                        */
+                       u32 tmp = omap_readl(FUNC_MUX_CTRL_0);
+                       tmp &= ~VBUS_CTRL_1510;
+                       omap_writel(tmp, FUNC_MUX_CTRL_0);
+                       tmp |= VBUS_MODE_1510;
+                       tmp &= ~VBUS_CTRL_1510;
+                       omap_writel(tmp, FUNC_MUX_CTRL_0);
+               }
+       } else {
+               /* The transceiver may package some GPIO logic or handle
+                * loopback and/or transceiverless setup; if we find one,
+                * use it.  Except for OTG, we don't _need_ to talk to one;
+                * but not having one probably means no VBUS detection.
+                */
+               xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+               if (!IS_ERR_OR_NULL(xceiv))
+                       type = xceiv->label;
+               else if (config->otg) {
+                       DBG("OTG requires external transceiver!\n");
+                       goto cleanup0;
+               }
+
+               hmc = HMC_1610;
+
+               switch (hmc) {
+               case 0:                 /* POWERUP DEFAULT == 0 */
+               case 4:
+               case 12:
+               case 20:
+                       if (!cpu_is_omap1710()) {
+                               type = "integrated";
+                               break;
+                       }
+                       /* FALL THROUGH */
+               case 3:
+               case 11:
+               case 16:
+               case 19:
+               case 25:
+                       if (IS_ERR_OR_NULL(xceiv)) {
+                               DBG("external transceiver not registered!\n");
+                               type = "unknown";
+                       }
+                       break;
+               case 21:                        /* internal loopback */
+                       type = "loopback";
+                       break;
+               case 14:                        /* transceiverless */
+                       if (cpu_is_omap1710())
+                               goto bad_on_1710;
+                       /* FALL THROUGH */
+               case 13:
+               case 15:
+                       type = "no";
+                       break;
+
+               default:
+bad_on_1710:
+                       ERR("unrecognized UDC HMC mode %d\n", hmc);
+                       goto cleanup0;
+               }
+       }
+
+       INFO("hmc mode %d, %s transceiver\n", hmc, type);
+
+       /* a "gadget" abstracts/virtualizes the controller */
+       status = omap_udc_setup(pdev, xceiv);
+       if (status)
+               goto cleanup0;
+
+       xceiv = NULL;
+       /* "udc" is now valid */
+       pullup_disable(udc);
+#if    defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+       udc->gadget.is_otg = (config->otg != 0);
+#endif
+
+       /* starting with omap1710 es2.0, clear toggle is a separate bit */
+       if (omap_readw(UDC_REV) >= 0x61)
+               udc->clr_halt = UDC_RESET_EP | UDC_CLRDATA_TOGGLE;
+       else
+               udc->clr_halt = UDC_RESET_EP;
+
+       /* USB general purpose IRQ:  ep0, state changes, dma, etc */
+       status = request_irq(pdev->resource[1].start, omap_udc_irq,
+                       0, driver_name, udc);
+       if (status != 0) {
+               ERR("can't get irq %d, err %d\n",
+                       (int) pdev->resource[1].start, status);
+               goto cleanup1;
+       }
+
+       /* USB "non-iso" IRQ (PIO for all but ep0) */
+       status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
+                       0, "omap_udc pio", udc);
+       if (status != 0) {
+               ERR("can't get irq %d, err %d\n",
+                       (int) pdev->resource[2].start, status);
+               goto cleanup2;
+       }
+#ifdef USE_ISO
+       status = request_irq(pdev->resource[3].start, omap_udc_iso_irq,
+                       0, "omap_udc iso", udc);
+       if (status != 0) {
+               ERR("can't get irq %d, err %d\n",
+                       (int) pdev->resource[3].start, status);
+               goto cleanup3;
+       }
+#endif
+       if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
+               udc->dc_clk = dc_clk;
+               udc->hhc_clk = hhc_clk;
+               clk_disable(hhc_clk);
+               clk_disable(dc_clk);
+       }
+
+       create_proc_file();
+       status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
+                       omap_udc_release);
+       if (status)
+               goto cleanup4;
+
+       return 0;
+
+cleanup4:
+       remove_proc_file();
+
+#ifdef USE_ISO
+cleanup3:
+       free_irq(pdev->resource[2].start, udc);
+#endif
+
+cleanup2:
+       free_irq(pdev->resource[1].start, udc);
+
+cleanup1:
+       kfree(udc);
+       udc = NULL;
+
+cleanup0:
+       if (!IS_ERR_OR_NULL(xceiv))
+               usb_put_phy(xceiv);
+
+       if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
+               clk_disable(hhc_clk);
+               clk_disable(dc_clk);
+               clk_put(hhc_clk);
+               clk_put(dc_clk);
+       }
+
+       release_mem_region(pdev->resource[0].start,
+                       pdev->resource[0].end - pdev->resource[0].start + 1);
+
+       return status;
+}
+
+static int omap_udc_remove(struct platform_device *pdev)
+{
+       DECLARE_COMPLETION_ONSTACK(done);
+
+       if (!udc)
+               return -ENODEV;
+
+       usb_del_gadget_udc(&udc->gadget);
+       if (udc->driver)
+               return -EBUSY;
+
+       udc->done = &done;
+
+       pullup_disable(udc);
+       if (!IS_ERR_OR_NULL(udc->transceiver)) {
+               usb_put_phy(udc->transceiver);
+               udc->transceiver = NULL;
+       }
+       omap_writew(0, UDC_SYSCON1);
+
+       remove_proc_file();
+
+#ifdef USE_ISO
+       free_irq(pdev->resource[3].start, udc);
+#endif
+       free_irq(pdev->resource[2].start, udc);
+       free_irq(pdev->resource[1].start, udc);
+
+       if (udc->dc_clk) {
+               if (udc->clk_requested)
+                       omap_udc_enable_clock(0);
+               clk_put(udc->hhc_clk);
+               clk_put(udc->dc_clk);
+       }
+
+       release_mem_region(pdev->resource[0].start,
+                       pdev->resource[0].end - pdev->resource[0].start + 1);
+
+       wait_for_completion(&done);
+
+       return 0;
+}
+
+/* suspend/resume/wakeup from sysfs (echo > power/state) or when the
+ * system is forced into deep sleep
+ *
+ * REVISIT we should probably reject suspend requests when there's a host
+ * session active, rather than disconnecting, at least on boards that can
+ * report VBUS irqs (UDC_DEVSTAT.UDC_ATT).  And in any case, we need to
+ * make host resumes and VBUS detection trigger OMAP wakeup events; that
+ * may involve talking to an external transceiver (e.g. isp1301).
+ */
+
+static int omap_udc_suspend(struct platform_device *dev, pm_message_t message)
+{
+       u32     devstat;
+
+       devstat = omap_readw(UDC_DEVSTAT);
+
+       /* we're requesting 48 MHz clock if the pullup is enabled
+        * (== we're attached to the host) and we're not suspended,
+        * which would prevent entry to deep sleep...
+        */
+       if ((devstat & UDC_ATT) != 0 && (devstat & UDC_SUS) == 0) {
+               WARNING("session active; suspend requires disconnect\n");
+               omap_pullup(&udc->gadget, 0);
+       }
+
+       return 0;
+}
+
+static int omap_udc_resume(struct platform_device *dev)
+{
+       DBG("resume + wakeup/SRP\n");
+       omap_pullup(&udc->gadget, 1);
+
+       /* maybe the host would enumerate us if we nudged it */
+       msleep(100);
+       return omap_wakeup(&udc->gadget);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct platform_driver udc_driver = {
+       .probe          = omap_udc_probe,
+       .remove         = omap_udc_remove,
+       .suspend        = omap_udc_suspend,
+       .resume         = omap_udc_resume,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = (char *) driver_name,
+       },
+};
+
+module_platform_driver(udc_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:omap_udc");
diff --git a/drivers/usb/gadget/udc/omap_udc.h b/drivers/usb/gadget/udc/omap_udc.h
new file mode 100644 (file)
index 0000000..cfadeb5
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * omap_udc.h -- for omap 3.2 udc, with OTG support
+ *
+ * 2004 (C) Texas Instruments, Inc.
+ * 2004 (C) David Brownell
+ */
+
+/*
+ * USB device/endpoint management registers
+ */
+
+#define        UDC_REV                         (UDC_BASE + 0x0)        /* Revision */
+#define        UDC_EP_NUM                      (UDC_BASE + 0x4)        /* Which endpoint */
+#      define  UDC_SETUP_SEL           (1 << 6)
+#      define  UDC_EP_SEL              (1 << 5)
+#      define  UDC_EP_DIR              (1 << 4)
+       /* low 4 bits for endpoint number */
+#define        UDC_DATA                        (UDC_BASE + 0x08)       /* Endpoint FIFO */
+#define        UDC_CTRL                        (UDC_BASE + 0x0C)       /* Endpoint control */
+#      define  UDC_CLR_HALT            (1 << 7)
+#      define  UDC_SET_HALT            (1 << 6)
+#      define  UDC_CLRDATA_TOGGLE      (1 << 3)
+#      define  UDC_SET_FIFO_EN         (1 << 2)
+#      define  UDC_CLR_EP              (1 << 1)
+#      define  UDC_RESET_EP            (1 << 0)
+#define        UDC_STAT_FLG                    (UDC_BASE + 0x10)       /* Endpoint status */
+#      define  UDC_NO_RXPACKET         (1 << 15)
+#      define  UDC_MISS_IN             (1 << 14)
+#      define  UDC_DATA_FLUSH          (1 << 13)
+#      define  UDC_ISO_ERR             (1 << 12)
+#      define  UDC_ISO_FIFO_EMPTY      (1 << 9)
+#      define  UDC_ISO_FIFO_FULL       (1 << 8)
+#      define  UDC_EP_HALTED           (1 << 6)
+#      define  UDC_STALL               (1 << 5)
+#      define  UDC_NAK                 (1 << 4)
+#      define  UDC_ACK                 (1 << 3)
+#      define  UDC_FIFO_EN             (1 << 2)
+#      define  UDC_NON_ISO_FIFO_EMPTY  (1 << 1)
+#      define  UDC_NON_ISO_FIFO_FULL   (1 << 0)
+#define        UDC_RXFSTAT                     (UDC_BASE + 0x14)       /* OUT bytecount */
+#define        UDC_SYSCON1                     (UDC_BASE + 0x18)       /* System config 1 */
+#      define  UDC_CFG_LOCK            (1 << 8)
+#      define  UDC_DATA_ENDIAN         (1 << 7)
+#      define  UDC_DMA_ENDIAN          (1 << 6)
+#      define  UDC_NAK_EN              (1 << 4)
+#      define  UDC_AUTODECODE_DIS      (1 << 3)
+#      define  UDC_SELF_PWR            (1 << 2)
+#      define  UDC_SOFF_DIS            (1 << 1)
+#      define  UDC_PULLUP_EN           (1 << 0)
+#define        UDC_SYSCON2                     (UDC_BASE + 0x1C)       /* System config 2 */
+#      define  UDC_RMT_WKP             (1 << 6)
+#      define  UDC_STALL_CMD           (1 << 5)
+#      define  UDC_DEV_CFG             (1 << 3)
+#      define  UDC_CLR_CFG             (1 << 2)
+#define        UDC_DEVSTAT                     (UDC_BASE + 0x20)       /* Device status */
+#      define  UDC_B_HNP_ENABLE        (1 << 9)
+#      define  UDC_A_HNP_SUPPORT       (1 << 8)
+#      define  UDC_A_ALT_HNP_SUPPORT   (1 << 7)
+#      define  UDC_R_WK_OK             (1 << 6)
+#      define  UDC_USB_RESET           (1 << 5)
+#      define  UDC_SUS                 (1 << 4)
+#      define  UDC_CFG                 (1 << 3)
+#      define  UDC_ADD                 (1 << 2)
+#      define  UDC_DEF                 (1 << 1)
+#      define  UDC_ATT                 (1 << 0)
+#define        UDC_SOF                         (UDC_BASE + 0x24)       /* Start of frame */
+#      define  UDC_FT_LOCK             (1 << 12)
+#      define  UDC_TS_OK               (1 << 11)
+#      define  UDC_TS                  0x03ff
+#define        UDC_IRQ_EN                      (UDC_BASE + 0x28)       /* Interrupt enable */
+#      define  UDC_SOF_IE              (1 << 7)
+#      define  UDC_EPN_RX_IE           (1 << 5)
+#      define  UDC_EPN_TX_IE           (1 << 4)
+#      define  UDC_DS_CHG_IE           (1 << 3)
+#      define  UDC_EP0_IE              (1 << 0)
+#define        UDC_DMA_IRQ_EN                  (UDC_BASE + 0x2C)       /* DMA irq enable */
+       /* rx/tx dma channels numbered 1-3 not 0-2 */
+#      define  UDC_TX_DONE_IE(n)       (1 << (4 * (n) - 2))
+#      define  UDC_RX_CNT_IE(n)        (1 << (4 * (n) - 3))
+#      define  UDC_RX_EOT_IE(n)        (1 << (4 * (n) - 4))
+#define        UDC_IRQ_SRC                     (UDC_BASE + 0x30)       /* Interrupt source */
+#      define  UDC_TXN_DONE            (1 << 10)
+#      define  UDC_RXN_CNT             (1 << 9)
+#      define  UDC_RXN_EOT             (1 << 8)
+#      define  UDC_IRQ_SOF             (1 << 7)
+#      define  UDC_EPN_RX              (1 << 5)
+#      define  UDC_EPN_TX              (1 << 4)
+#      define  UDC_DS_CHG              (1 << 3)
+#      define  UDC_SETUP               (1 << 2)
+#      define  UDC_EP0_RX              (1 << 1)
+#      define  UDC_EP0_TX              (1 << 0)
+#      define  UDC_IRQ_SRC_MASK        0x7bf
+#define        UDC_EPN_STAT                    (UDC_BASE + 0x34)       /* EP irq status */
+#define        UDC_DMAN_STAT                   (UDC_BASE + 0x38)       /* DMA irq status */
+#      define  UDC_DMA_RX_SB           (1 << 12)
+#      define  UDC_DMA_RX_SRC(x)       (((x)>>8) & 0xf)
+#      define  UDC_DMA_TX_SRC(x)       (((x)>>0) & 0xf)
+
+
+/* DMA configuration registers:  up to three channels in each direction.  */
+#define        UDC_RXDMA_CFG                   (UDC_BASE + 0x40)       /* 3 eps for RX DMA */
+#      define  UDC_DMA_REQ             (1 << 12)
+#define        UDC_TXDMA_CFG                   (UDC_BASE + 0x44)       /* 3 eps for TX DMA */
+#define        UDC_DATA_DMA                    (UDC_BASE + 0x48)       /* rx/tx fifo addr */
+
+/* rx/tx dma control, numbering channels 1-3 not 0-2 */
+#define        UDC_TXDMA(chan)                 (UDC_BASE + 0x50 - 4 + 4 * (chan))
+#      define UDC_TXN_EOT              (1 << 15)       /* bytes vs packets */
+#      define UDC_TXN_START            (1 << 14)       /* start transfer */
+#      define UDC_TXN_TSC              0x03ff          /* units in xfer */
+#define        UDC_RXDMA(chan)                 (UDC_BASE + 0x60 - 4 + 4 * (chan))
+#      define UDC_RXN_STOP             (1 << 15)       /* enable EOT irq */
+#      define UDC_RXN_TC               0x00ff          /* packets in xfer */
+
+
+/*
+ * Endpoint configuration registers (used before CFG_LOCK is set)
+ * UDC_EP_TX(0) is unused
+ */
+#define        UDC_EP_RX(endpoint)             (UDC_BASE + 0x80 + (endpoint)*4)
+#      define  UDC_EPN_RX_VALID        (1 << 15)
+#      define  UDC_EPN_RX_DB           (1 << 14)
+       /* buffer size in bits 13, 12 */
+#      define  UDC_EPN_RX_ISO          (1 << 11)
+       /* buffer pointer in low 11 bits */
+#define        UDC_EP_TX(endpoint)             (UDC_BASE + 0xc0 + (endpoint)*4)
+       /* same bitfields as in RX */
+
+/*-------------------------------------------------------------------------*/
+
+struct omap_req {
+       struct usb_request              req;
+       struct list_head                queue;
+       unsigned                        dma_bytes;
+       unsigned                        mapped:1;
+};
+
+struct omap_ep {
+       struct usb_ep                   ep;
+       struct list_head                queue;
+       unsigned long                   irqs;
+       struct list_head                iso;
+       char                            name[14];
+       u16                             maxpacket;
+       u8                              bEndpointAddress;
+       u8                              bmAttributes;
+       unsigned                        double_buf:1;
+       unsigned                        stopped:1;
+       unsigned                        fnf:1;
+       unsigned                        has_dma:1;
+       u8                              ackwait;
+       u8                              dma_channel;
+       u16                             dma_counter;
+       int                             lch;
+       struct omap_udc                 *udc;
+       struct timer_list               timer;
+};
+
+struct omap_udc {
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+       spinlock_t                      lock;
+       struct omap_ep                  ep[32];
+       u16                             devstat;
+       u16                             clr_halt;
+       struct usb_phy                  *transceiver;
+       struct list_head                iso;
+       unsigned                        softconnect:1;
+       unsigned                        vbus_active:1;
+       unsigned                        ep0_pending:1;
+       unsigned                        ep0_in:1;
+       unsigned                        ep0_set_config:1;
+       unsigned                        ep0_reset_config:1;
+       unsigned                        ep0_setup:1;
+       struct completion               *done;
+       struct clk                      *dc_clk;
+       struct clk                      *hhc_clk;
+       unsigned                        clk_requested:1;
+};
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef VERBOSE
+#    define VDBG               DBG
+#else
+#    define VDBG(stuff...)     do{}while(0)
+#endif
+
+#define ERR(stuff...)          pr_err("udc: " stuff)
+#define WARNING(stuff...)      pr_warning("udc: " stuff)
+#define INFO(stuff...)         pr_info("udc: " stuff)
+#define DBG(stuff...)          pr_debug("udc: " stuff)
+
+/*-------------------------------------------------------------------------*/
+
+/* MOD_CONF_CTRL_0 */
+#define VBUS_W2FC_1510         (1 << 17)       /* 0 gpio0, 1 dvdd2 pin */
+
+/* FUNC_MUX_CTRL_0 */
+#define        VBUS_CTRL_1510          (1 << 19)       /* 1 connected (software) */
+#define        VBUS_MODE_1510          (1 << 18)       /* 0 hardware, 1 software */
+
+#define        HMC_1510        ((omap_readl(MOD_CONF_CTRL_0) >> 1) & 0x3f)
+#define        HMC_1610        (omap_readl(OTG_SYSCON_2) & 0x3f)
+#define        HMC             (cpu_is_omap15xx() ? HMC_1510 : HMC_1610)
+
diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c
new file mode 100644 (file)
index 0000000..eb8c3be
--- /dev/null
@@ -0,0 +1,3248 @@
+/*
+ * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
+ *
+ * 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; version 2 of the License.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+
+/* GPIO port for VBUS detecting */
+static int vbus_gpio_port = -1;                /* GPIO port number (-1:Not used) */
+
+#define PCH_VBUS_PERIOD                3000    /* VBUS polling period (msec) */
+#define PCH_VBUS_INTERVAL      10      /* VBUS polling interval (msec) */
+
+/* Address offset of Registers */
+#define UDC_EP_REG_SHIFT       0x20    /* Offset to next EP */
+
+#define UDC_EPCTL_ADDR         0x00    /* Endpoint control */
+#define UDC_EPSTS_ADDR         0x04    /* Endpoint status */
+#define UDC_BUFIN_FRAMENUM_ADDR        0x08    /* buffer size in / frame number out */
+#define UDC_BUFOUT_MAXPKT_ADDR 0x0C    /* buffer size out / maxpkt in */
+#define UDC_SUBPTR_ADDR                0x10    /* setup buffer pointer */
+#define UDC_DESPTR_ADDR                0x14    /* Data descriptor pointer */
+#define UDC_CONFIRM_ADDR       0x18    /* Write/Read confirmation */
+
+#define UDC_DEVCFG_ADDR                0x400   /* Device configuration */
+#define UDC_DEVCTL_ADDR                0x404   /* Device control */
+#define UDC_DEVSTS_ADDR                0x408   /* Device status */
+#define UDC_DEVIRQSTS_ADDR     0x40C   /* Device irq status */
+#define UDC_DEVIRQMSK_ADDR     0x410   /* Device irq mask */
+#define UDC_EPIRQSTS_ADDR      0x414   /* Endpoint irq status */
+#define UDC_EPIRQMSK_ADDR      0x418   /* Endpoint irq mask */
+#define UDC_DEVLPM_ADDR                0x41C   /* LPM control / status */
+#define UDC_CSR_BUSY_ADDR      0x4f0   /* UDC_CSR_BUSY Status register */
+#define UDC_SRST_ADDR          0x4fc   /* SOFT RESET register */
+#define UDC_CSR_ADDR           0x500   /* USB_DEVICE endpoint register */
+
+/* Endpoint control register */
+/* Bit position */
+#define UDC_EPCTL_MRXFLUSH             (1 << 12)
+#define UDC_EPCTL_RRDY                 (1 << 9)
+#define UDC_EPCTL_CNAK                 (1 << 8)
+#define UDC_EPCTL_SNAK                 (1 << 7)
+#define UDC_EPCTL_NAK                  (1 << 6)
+#define UDC_EPCTL_P                    (1 << 3)
+#define UDC_EPCTL_F                    (1 << 1)
+#define UDC_EPCTL_S                    (1 << 0)
+#define UDC_EPCTL_ET_SHIFT             4
+/* Mask patern */
+#define UDC_EPCTL_ET_MASK              0x00000030
+/* Value for ET field */
+#define UDC_EPCTL_ET_CONTROL           0
+#define UDC_EPCTL_ET_ISO               1
+#define UDC_EPCTL_ET_BULK              2
+#define UDC_EPCTL_ET_INTERRUPT         3
+
+/* Endpoint status register */
+/* Bit position */
+#define UDC_EPSTS_XFERDONE             (1 << 27)
+#define UDC_EPSTS_RSS                  (1 << 26)
+#define UDC_EPSTS_RCS                  (1 << 25)
+#define UDC_EPSTS_TXEMPTY              (1 << 24)
+#define UDC_EPSTS_TDC                  (1 << 10)
+#define UDC_EPSTS_HE                   (1 << 9)
+#define UDC_EPSTS_MRXFIFO_EMP          (1 << 8)
+#define UDC_EPSTS_BNA                  (1 << 7)
+#define UDC_EPSTS_IN                   (1 << 6)
+#define UDC_EPSTS_OUT_SHIFT            4
+/* Mask patern */
+#define UDC_EPSTS_OUT_MASK             0x00000030
+#define UDC_EPSTS_ALL_CLR_MASK         0x1F0006F0
+/* Value for OUT field */
+#define UDC_EPSTS_OUT_SETUP            2
+#define UDC_EPSTS_OUT_DATA             1
+
+/* Device configuration register */
+/* Bit position */
+#define UDC_DEVCFG_CSR_PRG             (1 << 17)
+#define UDC_DEVCFG_SP                  (1 << 3)
+/* SPD Valee */
+#define UDC_DEVCFG_SPD_HS              0x0
+#define UDC_DEVCFG_SPD_FS              0x1
+#define UDC_DEVCFG_SPD_LS              0x2
+
+/* Device control register */
+/* Bit position */
+#define UDC_DEVCTL_THLEN_SHIFT         24
+#define UDC_DEVCTL_BRLEN_SHIFT         16
+#define UDC_DEVCTL_CSR_DONE            (1 << 13)
+#define UDC_DEVCTL_SD                  (1 << 10)
+#define UDC_DEVCTL_MODE                        (1 << 9)
+#define UDC_DEVCTL_BREN                        (1 << 8)
+#define UDC_DEVCTL_THE                 (1 << 7)
+#define UDC_DEVCTL_DU                  (1 << 4)
+#define UDC_DEVCTL_TDE                 (1 << 3)
+#define UDC_DEVCTL_RDE                 (1 << 2)
+#define UDC_DEVCTL_RES                 (1 << 0)
+
+/* Device status register */
+/* Bit position */
+#define UDC_DEVSTS_TS_SHIFT            18
+#define UDC_DEVSTS_ENUM_SPEED_SHIFT    13
+#define UDC_DEVSTS_ALT_SHIFT           8
+#define UDC_DEVSTS_INTF_SHIFT          4
+#define UDC_DEVSTS_CFG_SHIFT           0
+/* Mask patern */
+#define UDC_DEVSTS_TS_MASK             0xfffc0000
+#define UDC_DEVSTS_ENUM_SPEED_MASK     0x00006000
+#define UDC_DEVSTS_ALT_MASK            0x00000f00
+#define UDC_DEVSTS_INTF_MASK           0x000000f0
+#define UDC_DEVSTS_CFG_MASK            0x0000000f
+/* value for maximum speed for SPEED field */
+#define UDC_DEVSTS_ENUM_SPEED_FULL     1
+#define UDC_DEVSTS_ENUM_SPEED_HIGH     0
+#define UDC_DEVSTS_ENUM_SPEED_LOW      2
+#define UDC_DEVSTS_ENUM_SPEED_FULLX    3
+
+/* Device irq register */
+/* Bit position */
+#define UDC_DEVINT_RWKP                        (1 << 7)
+#define UDC_DEVINT_ENUM                        (1 << 6)
+#define UDC_DEVINT_SOF                 (1 << 5)
+#define UDC_DEVINT_US                  (1 << 4)
+#define UDC_DEVINT_UR                  (1 << 3)
+#define UDC_DEVINT_ES                  (1 << 2)
+#define UDC_DEVINT_SI                  (1 << 1)
+#define UDC_DEVINT_SC                  (1 << 0)
+/* Mask patern */
+#define UDC_DEVINT_MSK                 0x7f
+
+/* Endpoint irq register */
+/* Bit position */
+#define UDC_EPINT_IN_SHIFT             0
+#define UDC_EPINT_OUT_SHIFT            16
+#define UDC_EPINT_IN_EP0               (1 << 0)
+#define UDC_EPINT_OUT_EP0              (1 << 16)
+/* Mask patern */
+#define UDC_EPINT_MSK_DISABLE_ALL      0xffffffff
+
+/* UDC_CSR_BUSY Status register */
+/* Bit position */
+#define UDC_CSR_BUSY                   (1 << 0)
+
+/* SOFT RESET register */
+/* Bit position */
+#define UDC_PSRST                      (1 << 1)
+#define UDC_SRST                       (1 << 0)
+
+/* USB_DEVICE endpoint register */
+/* Bit position */
+#define UDC_CSR_NE_NUM_SHIFT           0
+#define UDC_CSR_NE_DIR_SHIFT           4
+#define UDC_CSR_NE_TYPE_SHIFT          5
+#define UDC_CSR_NE_CFG_SHIFT           7
+#define UDC_CSR_NE_INTF_SHIFT          11
+#define UDC_CSR_NE_ALT_SHIFT           15
+#define UDC_CSR_NE_MAX_PKT_SHIFT       19
+/* Mask patern */
+#define UDC_CSR_NE_NUM_MASK            0x0000000f
+#define UDC_CSR_NE_DIR_MASK            0x00000010
+#define UDC_CSR_NE_TYPE_MASK           0x00000060
+#define UDC_CSR_NE_CFG_MASK            0x00000780
+#define UDC_CSR_NE_INTF_MASK           0x00007800
+#define UDC_CSR_NE_ALT_MASK            0x00078000
+#define UDC_CSR_NE_MAX_PKT_MASK                0x3ff80000
+
+#define PCH_UDC_CSR(ep)        (UDC_CSR_ADDR + ep*4)
+#define PCH_UDC_EPINT(in, num)\
+               (1 << (num + (in ? UDC_EPINT_IN_SHIFT : UDC_EPINT_OUT_SHIFT)))
+
+/* Index of endpoint */
+#define UDC_EP0IN_IDX          0
+#define UDC_EP0OUT_IDX         1
+#define UDC_EPIN_IDX(ep)       (ep * 2)
+#define UDC_EPOUT_IDX(ep)      (ep * 2 + 1)
+#define PCH_UDC_EP0            0
+#define PCH_UDC_EP1            1
+#define PCH_UDC_EP2            2
+#define PCH_UDC_EP3            3
+
+/* Number of endpoint */
+#define PCH_UDC_EP_NUM         32      /* Total number of EPs (16 IN,16 OUT) */
+#define PCH_UDC_USED_EP_NUM    4       /* EP number of EP's really used */
+/* Length Value */
+#define PCH_UDC_BRLEN          0x0F    /* Burst length */
+#define PCH_UDC_THLEN          0x1F    /* Threshold length */
+/* Value of EP Buffer Size */
+#define UDC_EP0IN_BUFF_SIZE    16
+#define UDC_EPIN_BUFF_SIZE     256
+#define UDC_EP0OUT_BUFF_SIZE   16
+#define UDC_EPOUT_BUFF_SIZE    256
+/* Value of EP maximum packet size */
+#define UDC_EP0IN_MAX_PKT_SIZE 64
+#define UDC_EP0OUT_MAX_PKT_SIZE        64
+#define UDC_BULK_MAX_PKT_SIZE  512
+
+/* DMA */
+#define DMA_DIR_RX             1       /* DMA for data receive */
+#define DMA_DIR_TX             2       /* DMA for data transmit */
+#define DMA_ADDR_INVALID       (~(dma_addr_t)0)
+#define UDC_DMA_MAXPACKET      65536   /* maximum packet size for DMA */
+
+/**
+ * struct pch_udc_data_dma_desc - Structure to hold DMA descriptor information
+ *                               for data
+ * @status:            Status quadlet
+ * @reserved:          Reserved
+ * @dataptr:           Buffer descriptor
+ * @next:              Next descriptor
+ */
+struct pch_udc_data_dma_desc {
+       u32 status;
+       u32 reserved;
+       u32 dataptr;
+       u32 next;
+};
+
+/**
+ * struct pch_udc_stp_dma_desc - Structure to hold DMA descriptor information
+ *                              for control data
+ * @status:    Status
+ * @reserved:  Reserved
+ * @data12:    First setup word
+ * @data34:    Second setup word
+ */
+struct pch_udc_stp_dma_desc {
+       u32 status;
+       u32 reserved;
+       struct usb_ctrlrequest request;
+} __attribute((packed));
+
+/* DMA status definitions */
+/* Buffer status */
+#define PCH_UDC_BUFF_STS       0xC0000000
+#define PCH_UDC_BS_HST_RDY     0x00000000
+#define PCH_UDC_BS_DMA_BSY     0x40000000
+#define PCH_UDC_BS_DMA_DONE    0x80000000
+#define PCH_UDC_BS_HST_BSY     0xC0000000
+/*  Rx/Tx Status */
+#define PCH_UDC_RXTX_STS       0x30000000
+#define PCH_UDC_RTS_SUCC       0x00000000
+#define PCH_UDC_RTS_DESERR     0x10000000
+#define PCH_UDC_RTS_BUFERR     0x30000000
+/* Last Descriptor Indication */
+#define PCH_UDC_DMA_LAST       0x08000000
+/* Number of Rx/Tx Bytes Mask */
+#define PCH_UDC_RXTX_BYTES     0x0000ffff
+
+/**
+ * struct pch_udc_cfg_data - Structure to hold current configuration
+ *                          and interface information
+ * @cur_cfg:   current configuration in use
+ * @cur_intf:  current interface in use
+ * @cur_alt:   current alt interface in use
+ */
+struct pch_udc_cfg_data {
+       u16 cur_cfg;
+       u16 cur_intf;
+       u16 cur_alt;
+};
+
+/**
+ * struct pch_udc_ep - Structure holding a PCH USB device Endpoint information
+ * @ep:                        embedded ep request
+ * @td_stp_phys:       for setup request
+ * @td_data_phys:      for data request
+ * @td_stp:            for setup request
+ * @td_data:           for data request
+ * @dev:               reference to device struct
+ * @offset_addr:       offset address of ep register
+ * @desc:              for this ep
+ * @queue:             queue for requests
+ * @num:               endpoint number
+ * @in:                        endpoint is IN
+ * @halted:            endpoint halted?
+ * @epsts:             Endpoint status
+ */
+struct pch_udc_ep {
+       struct usb_ep                   ep;
+       dma_addr_t                      td_stp_phys;
+       dma_addr_t                      td_data_phys;
+       struct pch_udc_stp_dma_desc     *td_stp;
+       struct pch_udc_data_dma_desc    *td_data;
+       struct pch_udc_dev              *dev;
+       unsigned long                   offset_addr;
+       struct list_head                queue;
+       unsigned                        num:5,
+                                       in:1,
+                                       halted:1;
+       unsigned long                   epsts;
+};
+
+/**
+ * struct pch_vbus_gpio_data - Structure holding GPIO informaton
+ *                                     for detecting VBUS
+ * @port:              gpio port number
+ * @intr:              gpio interrupt number
+ * @irq_work_fall      Structure for WorkQueue
+ * @irq_work_rise      Structure for WorkQueue
+ */
+struct pch_vbus_gpio_data {
+       int                     port;
+       int                     intr;
+       struct work_struct      irq_work_fall;
+       struct work_struct      irq_work_rise;
+};
+
+/**
+ * struct pch_udc_dev - Structure holding complete information
+ *                     of the PCH USB device
+ * @gadget:            gadget driver data
+ * @driver:            reference to gadget driver bound
+ * @pdev:              reference to the PCI device
+ * @ep:                        array of endpoints
+ * @lock:              protects all state
+ * @active:            enabled the PCI device
+ * @stall:             stall requested
+ * @prot_stall:                protcol stall requested
+ * @irq_registered:    irq registered with system
+ * @mem_region:                device memory mapped
+ * @registered:                driver regsitered with system
+ * @suspended:         driver in suspended state
+ * @connected:         gadget driver associated
+ * @vbus_session:      required vbus_session state
+ * @set_cfg_not_acked: pending acknowledgement 4 setup
+ * @waiting_zlp_ack:   pending acknowledgement 4 ZLP
+ * @data_requests:     DMA pool for data requests
+ * @stp_requests:      DMA pool for setup requests
+ * @dma_addr:          DMA pool for received
+ * @ep0out_buf:                Buffer for DMA
+ * @setup_data:                Received setup data
+ * @phys_addr:         of device memory
+ * @base_addr:         for mapped device memory
+ * @irq:               IRQ line for the device
+ * @cfg_data:          current cfg, intf, and alt in use
+ * @vbus_gpio:         GPIO informaton for detecting VBUS
+ */
+struct pch_udc_dev {
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+       struct pci_dev                  *pdev;
+       struct pch_udc_ep               ep[PCH_UDC_EP_NUM];
+       spinlock_t                      lock; /* protects all state */
+       unsigned        active:1,
+                       stall:1,
+                       prot_stall:1,
+                       irq_registered:1,
+                       mem_region:1,
+                       suspended:1,
+                       connected:1,
+                       vbus_session:1,
+                       set_cfg_not_acked:1,
+                       waiting_zlp_ack:1;
+       struct pci_pool         *data_requests;
+       struct pci_pool         *stp_requests;
+       dma_addr_t                      dma_addr;
+       void                            *ep0out_buf;
+       struct usb_ctrlrequest          setup_data;
+       unsigned long                   phys_addr;
+       void __iomem                    *base_addr;
+       unsigned                        irq;
+       struct pch_udc_cfg_data         cfg_data;
+       struct pch_vbus_gpio_data       vbus_gpio;
+};
+#define to_pch_udc(g)  (container_of((g), struct pch_udc_dev, gadget))
+
+#define PCH_UDC_PCI_BAR                        1
+#define PCI_DEVICE_ID_INTEL_EG20T_UDC  0x8808
+#define PCI_VENDOR_ID_ROHM             0x10DB
+#define PCI_DEVICE_ID_ML7213_IOH_UDC   0x801D
+#define PCI_DEVICE_ID_ML7831_IOH_UDC   0x8808
+
+static const char      ep0_string[] = "ep0in";
+static DEFINE_SPINLOCK(udc_stall_spinlock);    /* stall spin lock */
+static bool speed_fs;
+module_param_named(speed_fs, speed_fs, bool, S_IRUGO);
+MODULE_PARM_DESC(speed_fs, "true for Full speed operation");
+
+/**
+ * struct pch_udc_request - Structure holding a PCH USB device request packet
+ * @req:               embedded ep request
+ * @td_data_phys:      phys. address
+ * @td_data:           first dma desc. of chain
+ * @td_data_last:      last dma desc. of chain
+ * @queue:             associated queue
+ * @dma_going:         DMA in progress for request
+ * @dma_mapped:                DMA memory mapped for request
+ * @dma_done:          DMA completed for request
+ * @chain_len:         chain length
+ * @buf:               Buffer memory for align adjustment
+ * @dma:               DMA memory for align adjustment
+ */
+struct pch_udc_request {
+       struct usb_request              req;
+       dma_addr_t                      td_data_phys;
+       struct pch_udc_data_dma_desc    *td_data;
+       struct pch_udc_data_dma_desc    *td_data_last;
+       struct list_head                queue;
+       unsigned                        dma_going:1,
+                                       dma_mapped:1,
+                                       dma_done:1;
+       unsigned                        chain_len;
+       void                            *buf;
+       dma_addr_t                      dma;
+};
+
+static inline u32 pch_udc_readl(struct pch_udc_dev *dev, unsigned long reg)
+{
+       return ioread32(dev->base_addr + reg);
+}
+
+static inline void pch_udc_writel(struct pch_udc_dev *dev,
+                                   unsigned long val, unsigned long reg)
+{
+       iowrite32(val, dev->base_addr + reg);
+}
+
+static inline void pch_udc_bit_set(struct pch_udc_dev *dev,
+                                    unsigned long reg,
+                                    unsigned long bitmask)
+{
+       pch_udc_writel(dev, pch_udc_readl(dev, reg) | bitmask, reg);
+}
+
+static inline void pch_udc_bit_clr(struct pch_udc_dev *dev,
+                                    unsigned long reg,
+                                    unsigned long bitmask)
+{
+       pch_udc_writel(dev, pch_udc_readl(dev, reg) & ~(bitmask), reg);
+}
+
+static inline u32 pch_udc_ep_readl(struct pch_udc_ep *ep, unsigned long reg)
+{
+       return ioread32(ep->dev->base_addr + ep->offset_addr + reg);
+}
+
+static inline void pch_udc_ep_writel(struct pch_udc_ep *ep,
+                                   unsigned long val, unsigned long reg)
+{
+       iowrite32(val, ep->dev->base_addr + ep->offset_addr + reg);
+}
+
+static inline void pch_udc_ep_bit_set(struct pch_udc_ep *ep,
+                                    unsigned long reg,
+                                    unsigned long bitmask)
+{
+       pch_udc_ep_writel(ep, pch_udc_ep_readl(ep, reg) | bitmask, reg);
+}
+
+static inline void pch_udc_ep_bit_clr(struct pch_udc_ep *ep,
+                                    unsigned long reg,
+                                    unsigned long bitmask)
+{
+       pch_udc_ep_writel(ep, pch_udc_ep_readl(ep, reg) & ~(bitmask), reg);
+}
+
+/**
+ * pch_udc_csr_busy() - Wait till idle.
+ * @dev:       Reference to pch_udc_dev structure
+ */
+static void pch_udc_csr_busy(struct pch_udc_dev *dev)
+{
+       unsigned int count = 200;
+
+       /* Wait till idle */
+       while ((pch_udc_readl(dev, UDC_CSR_BUSY_ADDR) & UDC_CSR_BUSY)
+               && --count)
+               cpu_relax();
+       if (!count)
+               dev_err(&dev->pdev->dev, "%s: wait error\n", __func__);
+}
+
+/**
+ * pch_udc_write_csr() - Write the command and status registers.
+ * @dev:       Reference to pch_udc_dev structure
+ * @val:       value to be written to CSR register
+ * @addr:      address of CSR register
+ */
+static void pch_udc_write_csr(struct pch_udc_dev *dev, unsigned long val,
+                              unsigned int ep)
+{
+       unsigned long reg = PCH_UDC_CSR(ep);
+
+       pch_udc_csr_busy(dev);          /* Wait till idle */
+       pch_udc_writel(dev, val, reg);
+       pch_udc_csr_busy(dev);          /* Wait till idle */
+}
+
+/**
+ * pch_udc_read_csr() - Read the command and status registers.
+ * @dev:       Reference to pch_udc_dev structure
+ * @addr:      address of CSR register
+ *
+ * Return codes:       content of CSR register
+ */
+static u32 pch_udc_read_csr(struct pch_udc_dev *dev, unsigned int ep)
+{
+       unsigned long reg = PCH_UDC_CSR(ep);
+
+       pch_udc_csr_busy(dev);          /* Wait till idle */
+       pch_udc_readl(dev, reg);        /* Dummy read */
+       pch_udc_csr_busy(dev);          /* Wait till idle */
+       return pch_udc_readl(dev, reg);
+}
+
+/**
+ * pch_udc_rmt_wakeup() - Initiate for remote wakeup
+ * @dev:       Reference to pch_udc_dev structure
+ */
+static inline void pch_udc_rmt_wakeup(struct pch_udc_dev *dev)
+{
+       pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+       mdelay(1);
+       pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+}
+
+/**
+ * pch_udc_get_frame() - Get the current frame from device status register
+ * @dev:       Reference to pch_udc_dev structure
+ * Retern      current frame
+ */
+static inline int pch_udc_get_frame(struct pch_udc_dev *dev)
+{
+       u32 frame = pch_udc_readl(dev, UDC_DEVSTS_ADDR);
+       return (frame & UDC_DEVSTS_TS_MASK) >> UDC_DEVSTS_TS_SHIFT;
+}
+
+/**
+ * pch_udc_clear_selfpowered() - Clear the self power control
+ * @dev:       Reference to pch_udc_regs structure
+ */
+static inline void pch_udc_clear_selfpowered(struct pch_udc_dev *dev)
+{
+       pch_udc_bit_clr(dev, UDC_DEVCFG_ADDR, UDC_DEVCFG_SP);
+}
+
+/**
+ * pch_udc_set_selfpowered() - Set the self power control
+ * @dev:       Reference to pch_udc_regs structure
+ */
+static inline void pch_udc_set_selfpowered(struct pch_udc_dev *dev)
+{
+       pch_udc_bit_set(dev, UDC_DEVCFG_ADDR, UDC_DEVCFG_SP);
+}
+
+/**
+ * pch_udc_set_disconnect() - Set the disconnect status.
+ * @dev:       Reference to pch_udc_regs structure
+ */
+static inline void pch_udc_set_disconnect(struct pch_udc_dev *dev)
+{
+       pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD);
+}
+
+/**
+ * pch_udc_clear_disconnect() - Clear the disconnect status.
+ * @dev:       Reference to pch_udc_regs structure
+ */
+static void pch_udc_clear_disconnect(struct pch_udc_dev *dev)
+{
+       /* Clear the disconnect */
+       pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+       pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD);
+       mdelay(1);
+       /* Resume USB signalling */
+       pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+}
+
+/**
+ * pch_udc_reconnect() - This API initializes usb device controller,
+ *                                             and clear the disconnect status.
+ * @dev:               Reference to pch_udc_regs structure
+ */
+static void pch_udc_init(struct pch_udc_dev *dev);
+static void pch_udc_reconnect(struct pch_udc_dev *dev)
+{
+       pch_udc_init(dev);
+
+       /* enable device interrupts */
+       /* pch_udc_enable_interrupts() */
+       pch_udc_bit_clr(dev, UDC_DEVIRQMSK_ADDR,
+                       UDC_DEVINT_UR | UDC_DEVINT_ENUM);
+
+       /* Clear the disconnect */
+       pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+       pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD);
+       mdelay(1);
+       /* Resume USB signalling */
+       pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+}
+
+/**
+ * pch_udc_vbus_session() - set or clearr the disconnect status.
+ * @dev:       Reference to pch_udc_regs structure
+ * @is_active: Parameter specifying the action
+ *               0:   indicating VBUS power is ending
+ *               !0:  indicating VBUS power is starting
+ */
+static inline void pch_udc_vbus_session(struct pch_udc_dev *dev,
+                                         int is_active)
+{
+       if (is_active) {
+               pch_udc_reconnect(dev);
+               dev->vbus_session = 1;
+       } else {
+               if (dev->driver && dev->driver->disconnect) {
+                       spin_unlock(&dev->lock);
+                       dev->driver->disconnect(&dev->gadget);
+                       spin_lock(&dev->lock);
+               }
+               pch_udc_set_disconnect(dev);
+               dev->vbus_session = 0;
+       }
+}
+
+/**
+ * pch_udc_ep_set_stall() - Set the stall of endpoint
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ */
+static void pch_udc_ep_set_stall(struct pch_udc_ep *ep)
+{
+       if (ep->in) {
+               pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_F);
+               pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_S);
+       } else {
+               pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_S);
+       }
+}
+
+/**
+ * pch_udc_ep_clear_stall() - Clear the stall of endpoint
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ */
+static inline void pch_udc_ep_clear_stall(struct pch_udc_ep *ep)
+{
+       /* Clear the stall */
+       pch_udc_ep_bit_clr(ep, UDC_EPCTL_ADDR, UDC_EPCTL_S);
+       /* Clear NAK by writing CNAK */
+       pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_CNAK);
+}
+
+/**
+ * pch_udc_ep_set_trfr_type() - Set the transfer type of endpoint
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ * @type:      Type of endpoint
+ */
+static inline void pch_udc_ep_set_trfr_type(struct pch_udc_ep *ep,
+                                       u8 type)
+{
+       pch_udc_ep_writel(ep, ((type << UDC_EPCTL_ET_SHIFT) &
+                               UDC_EPCTL_ET_MASK), UDC_EPCTL_ADDR);
+}
+
+/**
+ * pch_udc_ep_set_bufsz() - Set the maximum packet size for the endpoint
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ * @buf_size:  The buffer word size
+ */
+static void pch_udc_ep_set_bufsz(struct pch_udc_ep *ep,
+                                                u32 buf_size, u32 ep_in)
+{
+       u32 data;
+       if (ep_in) {
+               data = pch_udc_ep_readl(ep, UDC_BUFIN_FRAMENUM_ADDR);
+               data = (data & 0xffff0000) | (buf_size & 0xffff);
+               pch_udc_ep_writel(ep, data, UDC_BUFIN_FRAMENUM_ADDR);
+       } else {
+               data = pch_udc_ep_readl(ep, UDC_BUFOUT_MAXPKT_ADDR);
+               data = (buf_size << 16) | (data & 0xffff);
+               pch_udc_ep_writel(ep, data, UDC_BUFOUT_MAXPKT_ADDR);
+       }
+}
+
+/**
+ * pch_udc_ep_set_maxpkt() - Set the Max packet size for the endpoint
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ * @pkt_size:  The packet byte size
+ */
+static void pch_udc_ep_set_maxpkt(struct pch_udc_ep *ep, u32 pkt_size)
+{
+       u32 data = pch_udc_ep_readl(ep, UDC_BUFOUT_MAXPKT_ADDR);
+       data = (data & 0xffff0000) | (pkt_size & 0xffff);
+       pch_udc_ep_writel(ep, data, UDC_BUFOUT_MAXPKT_ADDR);
+}
+
+/**
+ * pch_udc_ep_set_subptr() - Set the Setup buffer pointer for the endpoint
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ * @addr:      Address of the register
+ */
+static inline void pch_udc_ep_set_subptr(struct pch_udc_ep *ep, u32 addr)
+{
+       pch_udc_ep_writel(ep, addr, UDC_SUBPTR_ADDR);
+}
+
+/**
+ * pch_udc_ep_set_ddptr() - Set the Data descriptor pointer for the endpoint
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ * @addr:      Address of the register
+ */
+static inline void pch_udc_ep_set_ddptr(struct pch_udc_ep *ep, u32 addr)
+{
+       pch_udc_ep_writel(ep, addr, UDC_DESPTR_ADDR);
+}
+
+/**
+ * pch_udc_ep_set_pd() - Set the poll demand bit for the endpoint
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ */
+static inline void pch_udc_ep_set_pd(struct pch_udc_ep *ep)
+{
+       pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_P);
+}
+
+/**
+ * pch_udc_ep_set_rrdy() - Set the receive ready bit for the endpoint
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ */
+static inline void pch_udc_ep_set_rrdy(struct pch_udc_ep *ep)
+{
+       pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_RRDY);
+}
+
+/**
+ * pch_udc_ep_clear_rrdy() - Clear the receive ready bit for the endpoint
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ */
+static inline void pch_udc_ep_clear_rrdy(struct pch_udc_ep *ep)
+{
+       pch_udc_ep_bit_clr(ep, UDC_EPCTL_ADDR, UDC_EPCTL_RRDY);
+}
+
+/**
+ * pch_udc_set_dma() - Set the 'TDE' or RDE bit of device control
+ *                     register depending on the direction specified
+ * @dev:       Reference to structure of type pch_udc_regs
+ * @dir:       whether Tx or Rx
+ *               DMA_DIR_RX: Receive
+ *               DMA_DIR_TX: Transmit
+ */
+static inline void pch_udc_set_dma(struct pch_udc_dev *dev, int dir)
+{
+       if (dir == DMA_DIR_RX)
+               pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RDE);
+       else if (dir == DMA_DIR_TX)
+               pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_TDE);
+}
+
+/**
+ * pch_udc_clear_dma() - Clear the 'TDE' or RDE bit of device control
+ *                              register depending on the direction specified
+ * @dev:       Reference to structure of type pch_udc_regs
+ * @dir:       Whether Tx or Rx
+ *               DMA_DIR_RX: Receive
+ *               DMA_DIR_TX: Transmit
+ */
+static inline void pch_udc_clear_dma(struct pch_udc_dev *dev, int dir)
+{
+       if (dir == DMA_DIR_RX)
+               pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RDE);
+       else if (dir == DMA_DIR_TX)
+               pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_TDE);
+}
+
+/**
+ * pch_udc_set_csr_done() - Set the device control register
+ *                             CSR done field (bit 13)
+ * @dev:       reference to structure of type pch_udc_regs
+ */
+static inline void pch_udc_set_csr_done(struct pch_udc_dev *dev)
+{
+       pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_CSR_DONE);
+}
+
+/**
+ * pch_udc_disable_interrupts() - Disables the specified interrupts
+ * @dev:       Reference to structure of type pch_udc_regs
+ * @mask:      Mask to disable interrupts
+ */
+static inline void pch_udc_disable_interrupts(struct pch_udc_dev *dev,
+                                           u32 mask)
+{
+       pch_udc_bit_set(dev, UDC_DEVIRQMSK_ADDR, mask);
+}
+
+/**
+ * pch_udc_enable_interrupts() - Enable the specified interrupts
+ * @dev:       Reference to structure of type pch_udc_regs
+ * @mask:      Mask to enable interrupts
+ */
+static inline void pch_udc_enable_interrupts(struct pch_udc_dev *dev,
+                                          u32 mask)
+{
+       pch_udc_bit_clr(dev, UDC_DEVIRQMSK_ADDR, mask);
+}
+
+/**
+ * pch_udc_disable_ep_interrupts() - Disable endpoint interrupts
+ * @dev:       Reference to structure of type pch_udc_regs
+ * @mask:      Mask to disable interrupts
+ */
+static inline void pch_udc_disable_ep_interrupts(struct pch_udc_dev *dev,
+                                               u32 mask)
+{
+       pch_udc_bit_set(dev, UDC_EPIRQMSK_ADDR, mask);
+}
+
+/**
+ * pch_udc_enable_ep_interrupts() - Enable endpoint interrupts
+ * @dev:       Reference to structure of type pch_udc_regs
+ * @mask:      Mask to enable interrupts
+ */
+static inline void pch_udc_enable_ep_interrupts(struct pch_udc_dev *dev,
+                                             u32 mask)
+{
+       pch_udc_bit_clr(dev, UDC_EPIRQMSK_ADDR, mask);
+}
+
+/**
+ * pch_udc_read_device_interrupts() - Read the device interrupts
+ * @dev:       Reference to structure of type pch_udc_regs
+ * Retern      The device interrupts
+ */
+static inline u32 pch_udc_read_device_interrupts(struct pch_udc_dev *dev)
+{
+       return pch_udc_readl(dev, UDC_DEVIRQSTS_ADDR);
+}
+
+/**
+ * pch_udc_write_device_interrupts() - Write device interrupts
+ * @dev:       Reference to structure of type pch_udc_regs
+ * @val:       The value to be written to interrupt register
+ */
+static inline void pch_udc_write_device_interrupts(struct pch_udc_dev *dev,
+                                                    u32 val)
+{
+       pch_udc_writel(dev, val, UDC_DEVIRQSTS_ADDR);
+}
+
+/**
+ * pch_udc_read_ep_interrupts() - Read the endpoint interrupts
+ * @dev:       Reference to structure of type pch_udc_regs
+ * Retern      The endpoint interrupt
+ */
+static inline u32 pch_udc_read_ep_interrupts(struct pch_udc_dev *dev)
+{
+       return pch_udc_readl(dev, UDC_EPIRQSTS_ADDR);
+}
+
+/**
+ * pch_udc_write_ep_interrupts() - Clear endpoint interupts
+ * @dev:       Reference to structure of type pch_udc_regs
+ * @val:       The value to be written to interrupt register
+ */
+static inline void pch_udc_write_ep_interrupts(struct pch_udc_dev *dev,
+                                            u32 val)
+{
+       pch_udc_writel(dev, val, UDC_EPIRQSTS_ADDR);
+}
+
+/**
+ * pch_udc_read_device_status() - Read the device status
+ * @dev:       Reference to structure of type pch_udc_regs
+ * Retern      The device status
+ */
+static inline u32 pch_udc_read_device_status(struct pch_udc_dev *dev)
+{
+       return pch_udc_readl(dev, UDC_DEVSTS_ADDR);
+}
+
+/**
+ * pch_udc_read_ep_control() - Read the endpoint control
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ * Retern      The endpoint control register value
+ */
+static inline u32 pch_udc_read_ep_control(struct pch_udc_ep *ep)
+{
+       return pch_udc_ep_readl(ep, UDC_EPCTL_ADDR);
+}
+
+/**
+ * pch_udc_clear_ep_control() - Clear the endpoint control register
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ * Retern      The endpoint control register value
+ */
+static inline void pch_udc_clear_ep_control(struct pch_udc_ep *ep)
+{
+       return pch_udc_ep_writel(ep, 0, UDC_EPCTL_ADDR);
+}
+
+/**
+ * pch_udc_read_ep_status() - Read the endpoint status
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ * Retern      The endpoint status
+ */
+static inline u32 pch_udc_read_ep_status(struct pch_udc_ep *ep)
+{
+       return pch_udc_ep_readl(ep, UDC_EPSTS_ADDR);
+}
+
+/**
+ * pch_udc_clear_ep_status() - Clear the endpoint status
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ * @stat:      Endpoint status
+ */
+static inline void pch_udc_clear_ep_status(struct pch_udc_ep *ep,
+                                        u32 stat)
+{
+       return pch_udc_ep_writel(ep, stat, UDC_EPSTS_ADDR);
+}
+
+/**
+ * pch_udc_ep_set_nak() - Set the bit 7 (SNAK field)
+ *                             of the endpoint control register
+ * @ep:                Reference to structure of type pch_udc_ep_regs
+ */
+static inline void pch_udc_ep_set_nak(struct pch_udc_ep *ep)
+{
+       pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_SNAK);
+}
+
+/**
+ * pch_udc_ep_clear_nak() - Set the bit 8 (CNAK field)
+ *                             of the endpoint control register
+ * @ep:                reference to structure of type pch_udc_ep_regs
+ */
+static void pch_udc_ep_clear_nak(struct pch_udc_ep *ep)
+{
+       unsigned int loopcnt = 0;
+       struct pch_udc_dev *dev = ep->dev;
+
+       if (!(pch_udc_ep_readl(ep, UDC_EPCTL_ADDR) & UDC_EPCTL_NAK))
+               return;
+       if (!ep->in) {
+               loopcnt = 10000;
+               while (!(pch_udc_read_ep_status(ep) & UDC_EPSTS_MRXFIFO_EMP) &&
+                       --loopcnt)
+                       udelay(5);
+               if (!loopcnt)
+                       dev_err(&dev->pdev->dev, "%s: RxFIFO not Empty\n",
+                               __func__);
+       }
+       loopcnt = 10000;
+       while ((pch_udc_read_ep_control(ep) & UDC_EPCTL_NAK) && --loopcnt) {
+               pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_CNAK);
+               udelay(5);
+       }
+       if (!loopcnt)
+               dev_err(&dev->pdev->dev, "%s: Clear NAK not set for ep%d%s\n",
+                       __func__, ep->num, (ep->in ? "in" : "out"));
+}
+
+/**
+ * pch_udc_ep_fifo_flush() - Flush the endpoint fifo
+ * @ep:        reference to structure of type pch_udc_ep_regs
+ * @dir:       direction of endpoint
+ *               0:  endpoint is OUT
+ *               !0: endpoint is IN
+ */
+static void pch_udc_ep_fifo_flush(struct pch_udc_ep *ep, int dir)
+{
+       if (dir) {      /* IN ep */
+               pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_F);
+               return;
+       }
+}
+
+/**
+ * pch_udc_ep_enable() - This api enables endpoint
+ * @regs:      Reference to structure pch_udc_ep_regs
+ * @desc:      endpoint descriptor
+ */
+static void pch_udc_ep_enable(struct pch_udc_ep *ep,
+                              struct pch_udc_cfg_data *cfg,
+                              const struct usb_endpoint_descriptor *desc)
+{
+       u32 val = 0;
+       u32 buff_size = 0;
+
+       pch_udc_ep_set_trfr_type(ep, desc->bmAttributes);
+       if (ep->in)
+               buff_size = UDC_EPIN_BUFF_SIZE;
+       else
+               buff_size = UDC_EPOUT_BUFF_SIZE;
+       pch_udc_ep_set_bufsz(ep, buff_size, ep->in);
+       pch_udc_ep_set_maxpkt(ep, usb_endpoint_maxp(desc));
+       pch_udc_ep_set_nak(ep);
+       pch_udc_ep_fifo_flush(ep, ep->in);
+       /* Configure the endpoint */
+       val = ep->num << UDC_CSR_NE_NUM_SHIFT | ep->in << UDC_CSR_NE_DIR_SHIFT |
+             ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) <<
+               UDC_CSR_NE_TYPE_SHIFT) |
+             (cfg->cur_cfg << UDC_CSR_NE_CFG_SHIFT) |
+             (cfg->cur_intf << UDC_CSR_NE_INTF_SHIFT) |
+             (cfg->cur_alt << UDC_CSR_NE_ALT_SHIFT) |
+             usb_endpoint_maxp(desc) << UDC_CSR_NE_MAX_PKT_SHIFT;
+
+       if (ep->in)
+               pch_udc_write_csr(ep->dev, val, UDC_EPIN_IDX(ep->num));
+       else
+               pch_udc_write_csr(ep->dev, val, UDC_EPOUT_IDX(ep->num));
+}
+
+/**
+ * pch_udc_ep_disable() - This api disables endpoint
+ * @regs:      Reference to structure pch_udc_ep_regs
+ */
+static void pch_udc_ep_disable(struct pch_udc_ep *ep)
+{
+       if (ep->in) {
+               /* flush the fifo */
+               pch_udc_ep_writel(ep, UDC_EPCTL_F, UDC_EPCTL_ADDR);
+               /* set NAK */
+               pch_udc_ep_writel(ep, UDC_EPCTL_SNAK, UDC_EPCTL_ADDR);
+               pch_udc_ep_bit_set(ep, UDC_EPSTS_ADDR, UDC_EPSTS_IN);
+       } else {
+               /* set NAK */
+               pch_udc_ep_writel(ep, UDC_EPCTL_SNAK, UDC_EPCTL_ADDR);
+       }
+       /* reset desc pointer */
+       pch_udc_ep_writel(ep, 0, UDC_DESPTR_ADDR);
+}
+
+/**
+ * pch_udc_wait_ep_stall() - Wait EP stall.
+ * @dev:       Reference to pch_udc_dev structure
+ */
+static void pch_udc_wait_ep_stall(struct pch_udc_ep *ep)
+{
+       unsigned int count = 10000;
+
+       /* Wait till idle */
+       while ((pch_udc_read_ep_control(ep) & UDC_EPCTL_S) && --count)
+               udelay(5);
+       if (!count)
+               dev_err(&ep->dev->pdev->dev, "%s: wait error\n", __func__);
+}
+
+/**
+ * pch_udc_init() - This API initializes usb device controller
+ * @dev:       Rreference to pch_udc_regs structure
+ */
+static void pch_udc_init(struct pch_udc_dev *dev)
+{
+       if (NULL == dev) {
+               pr_err("%s: Invalid address\n", __func__);
+               return;
+       }
+       /* Soft Reset and Reset PHY */
+       pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
+       pch_udc_writel(dev, UDC_SRST | UDC_PSRST, UDC_SRST_ADDR);
+       mdelay(1);
+       pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
+       pch_udc_writel(dev, 0x00, UDC_SRST_ADDR);
+       mdelay(1);
+       /* mask and clear all device interrupts */
+       pch_udc_bit_set(dev, UDC_DEVIRQMSK_ADDR, UDC_DEVINT_MSK);
+       pch_udc_bit_set(dev, UDC_DEVIRQSTS_ADDR, UDC_DEVINT_MSK);
+
+       /* mask and clear all ep interrupts */
+       pch_udc_bit_set(dev, UDC_EPIRQMSK_ADDR, UDC_EPINT_MSK_DISABLE_ALL);
+       pch_udc_bit_set(dev, UDC_EPIRQSTS_ADDR, UDC_EPINT_MSK_DISABLE_ALL);
+
+       /* enable dynamic CSR programmingi, self powered and device speed */
+       if (speed_fs)
+               pch_udc_bit_set(dev, UDC_DEVCFG_ADDR, UDC_DEVCFG_CSR_PRG |
+                               UDC_DEVCFG_SP | UDC_DEVCFG_SPD_FS);
+       else /* defaul high speed */
+               pch_udc_bit_set(dev, UDC_DEVCFG_ADDR, UDC_DEVCFG_CSR_PRG |
+                               UDC_DEVCFG_SP | UDC_DEVCFG_SPD_HS);
+       pch_udc_bit_set(dev, UDC_DEVCTL_ADDR,
+                       (PCH_UDC_THLEN << UDC_DEVCTL_THLEN_SHIFT) |
+                       (PCH_UDC_BRLEN << UDC_DEVCTL_BRLEN_SHIFT) |
+                       UDC_DEVCTL_MODE | UDC_DEVCTL_BREN |
+                       UDC_DEVCTL_THE);
+}
+
+/**
+ * pch_udc_exit() - This API exit usb device controller
+ * @dev:       Reference to pch_udc_regs structure
+ */
+static void pch_udc_exit(struct pch_udc_dev *dev)
+{
+       /* mask all device interrupts */
+       pch_udc_bit_set(dev, UDC_DEVIRQMSK_ADDR, UDC_DEVINT_MSK);
+       /* mask all ep interrupts */
+       pch_udc_bit_set(dev, UDC_EPIRQMSK_ADDR, UDC_EPINT_MSK_DISABLE_ALL);
+       /* put device in disconnected state */
+       pch_udc_set_disconnect(dev);
+}
+
+/**
+ * pch_udc_pcd_get_frame() - This API is invoked to get the current frame number
+ * @gadget:    Reference to the gadget driver
+ *
+ * Return codes:
+ *     0:              Success
+ *     -EINVAL:        If the gadget passed is NULL
+ */
+static int pch_udc_pcd_get_frame(struct usb_gadget *gadget)
+{
+       struct pch_udc_dev      *dev;
+
+       if (!gadget)
+               return -EINVAL;
+       dev = container_of(gadget, struct pch_udc_dev, gadget);
+       return pch_udc_get_frame(dev);
+}
+
+/**
+ * pch_udc_pcd_wakeup() - This API is invoked to initiate a remote wakeup
+ * @gadget:    Reference to the gadget driver
+ *
+ * Return codes:
+ *     0:              Success
+ *     -EINVAL:        If the gadget passed is NULL
+ */
+static int pch_udc_pcd_wakeup(struct usb_gadget *gadget)
+{
+       struct pch_udc_dev      *dev;
+       unsigned long           flags;
+
+       if (!gadget)
+               return -EINVAL;
+       dev = container_of(gadget, struct pch_udc_dev, gadget);
+       spin_lock_irqsave(&dev->lock, flags);
+       pch_udc_rmt_wakeup(dev);
+       spin_unlock_irqrestore(&dev->lock, flags);
+       return 0;
+}
+
+/**
+ * pch_udc_pcd_selfpowered() - This API is invoked to specify whether the device
+ *                             is self powered or not
+ * @gadget:    Reference to the gadget driver
+ * @value:     Specifies self powered or not
+ *
+ * Return codes:
+ *     0:              Success
+ *     -EINVAL:        If the gadget passed is NULL
+ */
+static int pch_udc_pcd_selfpowered(struct usb_gadget *gadget, int value)
+{
+       struct pch_udc_dev      *dev;
+
+       if (!gadget)
+               return -EINVAL;
+       dev = container_of(gadget, struct pch_udc_dev, gadget);
+       if (value)
+               pch_udc_set_selfpowered(dev);
+       else
+               pch_udc_clear_selfpowered(dev);
+       return 0;
+}
+
+/**
+ * pch_udc_pcd_pullup() - This API is invoked to make the device
+ *                             visible/invisible to the host
+ * @gadget:    Reference to the gadget driver
+ * @is_on:     Specifies whether the pull up is made active or inactive
+ *
+ * Return codes:
+ *     0:              Success
+ *     -EINVAL:        If the gadget passed is NULL
+ */
+static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct pch_udc_dev      *dev;
+
+       if (!gadget)
+               return -EINVAL;
+       dev = container_of(gadget, struct pch_udc_dev, gadget);
+       if (is_on) {
+               pch_udc_reconnect(dev);
+       } else {
+               if (dev->driver && dev->driver->disconnect) {
+                       spin_unlock(&dev->lock);
+                       dev->driver->disconnect(&dev->gadget);
+                       spin_lock(&dev->lock);
+               }
+               pch_udc_set_disconnect(dev);
+       }
+
+       return 0;
+}
+
+/**
+ * pch_udc_pcd_vbus_session() - This API is used by a driver for an external
+ *                             transceiver (or GPIO) that
+ *                             detects a VBUS power session starting/ending
+ * @gadget:    Reference to the gadget driver
+ * @is_active: specifies whether the session is starting or ending
+ *
+ * Return codes:
+ *     0:              Success
+ *     -EINVAL:        If the gadget passed is NULL
+ */
+static int pch_udc_pcd_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+       struct pch_udc_dev      *dev;
+
+       if (!gadget)
+               return -EINVAL;
+       dev = container_of(gadget, struct pch_udc_dev, gadget);
+       pch_udc_vbus_session(dev, is_active);
+       return 0;
+}
+
+/**
+ * pch_udc_pcd_vbus_draw() - This API is used by gadget drivers during
+ *                             SET_CONFIGURATION calls to
+ *                             specify how much power the device can consume
+ * @gadget:    Reference to the gadget driver
+ * @mA:                specifies the current limit in 2mA unit
+ *
+ * Return codes:
+ *     -EINVAL:        If the gadget passed is NULL
+ *     -EOPNOTSUPP:
+ */
+static int pch_udc_pcd_vbus_draw(struct usb_gadget *gadget, unsigned int mA)
+{
+       return -EOPNOTSUPP;
+}
+
+static int pch_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+static int pch_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+static const struct usb_gadget_ops pch_udc_ops = {
+       .get_frame = pch_udc_pcd_get_frame,
+       .wakeup = pch_udc_pcd_wakeup,
+       .set_selfpowered = pch_udc_pcd_selfpowered,
+       .pullup = pch_udc_pcd_pullup,
+       .vbus_session = pch_udc_pcd_vbus_session,
+       .vbus_draw = pch_udc_pcd_vbus_draw,
+       .udc_start = pch_udc_start,
+       .udc_stop = pch_udc_stop,
+};
+
+/**
+ * pch_vbus_gpio_get_value() - This API gets value of GPIO port as VBUS status.
+ * @dev:       Reference to the driver structure
+ *
+ * Return value:
+ *     1: VBUS is high
+ *     0: VBUS is low
+ *     -1: It is not enable to detect VBUS using GPIO
+ */
+static int pch_vbus_gpio_get_value(struct pch_udc_dev *dev)
+{
+       int vbus = 0;
+
+       if (dev->vbus_gpio.port)
+               vbus = gpio_get_value(dev->vbus_gpio.port) ? 1 : 0;
+       else
+               vbus = -1;
+
+       return vbus;
+}
+
+/**
+ * pch_vbus_gpio_work_fall() - This API keeps watch on VBUS becoming Low.
+ *                             If VBUS is Low, disconnect is processed
+ * @irq_work:  Structure for WorkQueue
+ *
+ */
+static void pch_vbus_gpio_work_fall(struct work_struct *irq_work)
+{
+       struct pch_vbus_gpio_data *vbus_gpio = container_of(irq_work,
+               struct pch_vbus_gpio_data, irq_work_fall);
+       struct pch_udc_dev *dev =
+               container_of(vbus_gpio, struct pch_udc_dev, vbus_gpio);
+       int vbus_saved = -1;
+       int vbus;
+       int count;
+
+       if (!dev->vbus_gpio.port)
+               return;
+
+       for (count = 0; count < (PCH_VBUS_PERIOD / PCH_VBUS_INTERVAL);
+               count++) {
+               vbus = pch_vbus_gpio_get_value(dev);
+
+               if ((vbus_saved == vbus) && (vbus == 0)) {
+                       dev_dbg(&dev->pdev->dev, "VBUS fell");
+                       if (dev->driver
+                               && dev->driver->disconnect) {
+                               dev->driver->disconnect(
+                                       &dev->gadget);
+                       }
+                       if (dev->vbus_gpio.intr)
+                               pch_udc_init(dev);
+                       else
+                               pch_udc_reconnect(dev);
+                       return;
+               }
+               vbus_saved = vbus;
+               mdelay(PCH_VBUS_INTERVAL);
+       }
+}
+
+/**
+ * pch_vbus_gpio_work_rise() - This API checks VBUS is High.
+ *                             If VBUS is High, connect is processed
+ * @irq_work:  Structure for WorkQueue
+ *
+ */
+static void pch_vbus_gpio_work_rise(struct work_struct *irq_work)
+{
+       struct pch_vbus_gpio_data *vbus_gpio = container_of(irq_work,
+               struct pch_vbus_gpio_data, irq_work_rise);
+       struct pch_udc_dev *dev =
+               container_of(vbus_gpio, struct pch_udc_dev, vbus_gpio);
+       int vbus;
+
+       if (!dev->vbus_gpio.port)
+               return;
+
+       mdelay(PCH_VBUS_INTERVAL);
+       vbus = pch_vbus_gpio_get_value(dev);
+
+       if (vbus == 1) {
+               dev_dbg(&dev->pdev->dev, "VBUS rose");
+               pch_udc_reconnect(dev);
+               return;
+       }
+}
+
+/**
+ * pch_vbus_gpio_irq() - IRQ handler for GPIO intrerrupt for changing VBUS
+ * @irq:       Interrupt request number
+ * @dev:       Reference to the device structure
+ *
+ * Return codes:
+ *     0: Success
+ *     -EINVAL: GPIO port is invalid or can't be initialized.
+ */
+static irqreturn_t pch_vbus_gpio_irq(int irq, void *data)
+{
+       struct pch_udc_dev *dev = (struct pch_udc_dev *)data;
+
+       if (!dev->vbus_gpio.port || !dev->vbus_gpio.intr)
+               return IRQ_NONE;
+
+       if (pch_vbus_gpio_get_value(dev))
+               schedule_work(&dev->vbus_gpio.irq_work_rise);
+       else
+               schedule_work(&dev->vbus_gpio.irq_work_fall);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * pch_vbus_gpio_init() - This API initializes GPIO port detecting VBUS.
+ * @dev:       Reference to the driver structure
+ * @vbus_gpio  Number of GPIO port to detect gpio
+ *
+ * Return codes:
+ *     0: Success
+ *     -EINVAL: GPIO port is invalid or can't be initialized.
+ */
+static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port)
+{
+       int err;
+       int irq_num = 0;
+
+       dev->vbus_gpio.port = 0;
+       dev->vbus_gpio.intr = 0;
+
+       if (vbus_gpio_port <= -1)
+               return -EINVAL;
+
+       err = gpio_is_valid(vbus_gpio_port);
+       if (!err) {
+               pr_err("%s: gpio port %d is invalid\n",
+                       __func__, vbus_gpio_port);
+               return -EINVAL;
+       }
+
+       err = gpio_request(vbus_gpio_port, "pch_vbus");
+       if (err) {
+               pr_err("%s: can't request gpio port %d, err: %d\n",
+                       __func__, vbus_gpio_port, err);
+               return -EINVAL;
+       }
+
+       dev->vbus_gpio.port = vbus_gpio_port;
+       gpio_direction_input(vbus_gpio_port);
+       INIT_WORK(&dev->vbus_gpio.irq_work_fall, pch_vbus_gpio_work_fall);
+
+       irq_num = gpio_to_irq(vbus_gpio_port);
+       if (irq_num > 0) {
+               irq_set_irq_type(irq_num, IRQ_TYPE_EDGE_BOTH);
+               err = request_irq(irq_num, pch_vbus_gpio_irq, 0,
+                       "vbus_detect", dev);
+               if (!err) {
+                       dev->vbus_gpio.intr = irq_num;
+                       INIT_WORK(&dev->vbus_gpio.irq_work_rise,
+                               pch_vbus_gpio_work_rise);
+               } else {
+                       pr_err("%s: can't request irq %d, err: %d\n",
+                               __func__, irq_num, err);
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * pch_vbus_gpio_free() - This API frees resources of GPIO port
+ * @dev:       Reference to the driver structure
+ */
+static void pch_vbus_gpio_free(struct pch_udc_dev *dev)
+{
+       if (dev->vbus_gpio.intr)
+               free_irq(dev->vbus_gpio.intr, dev);
+
+       if (dev->vbus_gpio.port)
+               gpio_free(dev->vbus_gpio.port);
+}
+
+/**
+ * complete_req() - This API is invoked from the driver when processing
+ *                     of a request is complete
+ * @ep:                Reference to the endpoint structure
+ * @req:       Reference to the request structure
+ * @status:    Indicates the success/failure of completion
+ */
+static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
+                                                                int status)
+       __releases(&dev->lock)
+       __acquires(&dev->lock)
+{
+       struct pch_udc_dev      *dev;
+       unsigned halted = ep->halted;
+
+       list_del_init(&req->queue);
+
+       /* set new status if pending */
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       dev = ep->dev;
+       if (req->dma_mapped) {
+               if (req->dma == DMA_ADDR_INVALID) {
+                       if (ep->in)
+                               dma_unmap_single(&dev->pdev->dev, req->req.dma,
+                                                req->req.length,
+                                                DMA_TO_DEVICE);
+                       else
+                               dma_unmap_single(&dev->pdev->dev, req->req.dma,
+                                                req->req.length,
+                                                DMA_FROM_DEVICE);
+                       req->req.dma = DMA_ADDR_INVALID;
+               } else {
+                       if (ep->in)
+                               dma_unmap_single(&dev->pdev->dev, req->dma,
+                                                req->req.length,
+                                                DMA_TO_DEVICE);
+                       else {
+                               dma_unmap_single(&dev->pdev->dev, req->dma,
+                                                req->req.length,
+                                                DMA_FROM_DEVICE);
+                               memcpy(req->req.buf, req->buf, req->req.length);
+                       }
+                       kfree(req->buf);
+                       req->dma = DMA_ADDR_INVALID;
+               }
+               req->dma_mapped = 0;
+       }
+       ep->halted = 1;
+       spin_unlock(&dev->lock);
+       if (!ep->in)
+               pch_udc_ep_clear_rrdy(ep);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&dev->lock);
+       ep->halted = halted;
+}
+
+/**
+ * empty_req_queue() - This API empties the request queue of an endpoint
+ * @ep:                Reference to the endpoint structure
+ */
+static void empty_req_queue(struct pch_udc_ep *ep)
+{
+       struct pch_udc_request  *req;
+
+       ep->halted = 1;
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct pch_udc_request, queue);
+               complete_req(ep, req, -ESHUTDOWN);      /* Remove from list */
+       }
+}
+
+/**
+ * pch_udc_free_dma_chain() - This function frees the DMA chain created
+ *                             for the request
+ * @dev                Reference to the driver structure
+ * @req                Reference to the request to be freed
+ *
+ * Return codes:
+ *     0: Success
+ */
+static void pch_udc_free_dma_chain(struct pch_udc_dev *dev,
+                                  struct pch_udc_request *req)
+{
+       struct pch_udc_data_dma_desc *td = req->td_data;
+       unsigned i = req->chain_len;
+
+       dma_addr_t addr2;
+       dma_addr_t addr = (dma_addr_t)td->next;
+       td->next = 0x00;
+       for (; i > 1; --i) {
+               /* do not free first desc., will be done by free for request */
+               td = phys_to_virt(addr);
+               addr2 = (dma_addr_t)td->next;
+               pci_pool_free(dev->data_requests, td, addr);
+               td->next = 0x00;
+               addr = addr2;
+       }
+       req->chain_len = 1;
+}
+
+/**
+ * pch_udc_create_dma_chain() - This function creates or reinitializes
+ *                             a DMA chain
+ * @ep:                Reference to the endpoint structure
+ * @req:       Reference to the request
+ * @buf_len:   The buffer length
+ * @gfp_flags: Flags to be used while mapping the data buffer
+ *
+ * Return codes:
+ *     0:              success,
+ *     -ENOMEM:        pci_pool_alloc invocation fails
+ */
+static int pch_udc_create_dma_chain(struct pch_udc_ep *ep,
+                                   struct pch_udc_request *req,
+                                   unsigned long buf_len,
+                                   gfp_t gfp_flags)
+{
+       struct pch_udc_data_dma_desc *td = req->td_data, *last;
+       unsigned long bytes = req->req.length, i = 0;
+       dma_addr_t dma_addr;
+       unsigned len = 1;
+
+       if (req->chain_len > 1)
+               pch_udc_free_dma_chain(ep->dev, req);
+
+       if (req->dma == DMA_ADDR_INVALID)
+               td->dataptr = req->req.dma;
+       else
+               td->dataptr = req->dma;
+
+       td->status = PCH_UDC_BS_HST_BSY;
+       for (; ; bytes -= buf_len, ++len) {
+               td->status = PCH_UDC_BS_HST_BSY | min(buf_len, bytes);
+               if (bytes <= buf_len)
+                       break;
+               last = td;
+               td = pci_pool_alloc(ep->dev->data_requests, gfp_flags,
+                                   &dma_addr);
+               if (!td)
+                       goto nomem;
+               i += buf_len;
+               td->dataptr = req->td_data->dataptr + i;
+               last->next = dma_addr;
+       }
+
+       req->td_data_last = td;
+       td->status |= PCH_UDC_DMA_LAST;
+       td->next = req->td_data_phys;
+       req->chain_len = len;
+       return 0;
+
+nomem:
+       if (len > 1) {
+               req->chain_len = len;
+               pch_udc_free_dma_chain(ep->dev, req);
+       }
+       req->chain_len = 1;
+       return -ENOMEM;
+}
+
+/**
+ * prepare_dma() - This function creates and initializes the DMA chain
+ *                     for the request
+ * @ep:                Reference to the endpoint structure
+ * @req:       Reference to the request
+ * @gfp:       Flag to be used while mapping the data buffer
+ *
+ * Return codes:
+ *     0:              Success
+ *     Other 0:        linux error number on failure
+ */
+static int prepare_dma(struct pch_udc_ep *ep, struct pch_udc_request *req,
+                         gfp_t gfp)
+{
+       int     retval;
+
+       /* Allocate and create a DMA chain */
+       retval = pch_udc_create_dma_chain(ep, req, ep->ep.maxpacket, gfp);
+       if (retval) {
+               pr_err("%s: could not create DMA chain:%d\n", __func__, retval);
+               return retval;
+       }
+       if (ep->in)
+               req->td_data->status = (req->td_data->status &
+                               ~PCH_UDC_BUFF_STS) | PCH_UDC_BS_HST_RDY;
+       return 0;
+}
+
+/**
+ * process_zlp() - This function process zero length packets
+ *                     from the gadget driver
+ * @ep:                Reference to the endpoint structure
+ * @req:       Reference to the request
+ */
+static void process_zlp(struct pch_udc_ep *ep, struct pch_udc_request *req)
+{
+       struct pch_udc_dev      *dev = ep->dev;
+
+       /* IN zlp's are handled by hardware */
+       complete_req(ep, req, 0);
+
+       /* if set_config or set_intf is waiting for ack by zlp
+        * then set CSR_DONE
+        */
+       if (dev->set_cfg_not_acked) {
+               pch_udc_set_csr_done(dev);
+               dev->set_cfg_not_acked = 0;
+       }
+       /* setup command is ACK'ed now by zlp */
+       if (!dev->stall && dev->waiting_zlp_ack) {
+               pch_udc_ep_clear_nak(&(dev->ep[UDC_EP0IN_IDX]));
+               dev->waiting_zlp_ack = 0;
+       }
+}
+
+/**
+ * pch_udc_start_rxrequest() - This function starts the receive requirement.
+ * @ep:                Reference to the endpoint structure
+ * @req:       Reference to the request structure
+ */
+static void pch_udc_start_rxrequest(struct pch_udc_ep *ep,
+                                        struct pch_udc_request *req)
+{
+       struct pch_udc_data_dma_desc *td_data;
+
+       pch_udc_clear_dma(ep->dev, DMA_DIR_RX);
+       td_data = req->td_data;
+       /* Set the status bits for all descriptors */
+       while (1) {
+               td_data->status = (td_data->status & ~PCH_UDC_BUFF_STS) |
+                                   PCH_UDC_BS_HST_RDY;
+               if ((td_data->status & PCH_UDC_DMA_LAST) ==  PCH_UDC_DMA_LAST)
+                       break;
+               td_data = phys_to_virt(td_data->next);
+       }
+       /* Write the descriptor pointer */
+       pch_udc_ep_set_ddptr(ep, req->td_data_phys);
+       req->dma_going = 1;
+       pch_udc_enable_ep_interrupts(ep->dev, UDC_EPINT_OUT_EP0 << ep->num);
+       pch_udc_set_dma(ep->dev, DMA_DIR_RX);
+       pch_udc_ep_clear_nak(ep);
+       pch_udc_ep_set_rrdy(ep);
+}
+
+/**
+ * pch_udc_pcd_ep_enable() - This API enables the endpoint. It is called
+ *                             from gadget driver
+ * @usbep:     Reference to the USB endpoint structure
+ * @desc:      Reference to the USB endpoint descriptor structure
+ *
+ * Return codes:
+ *     0:              Success
+ *     -EINVAL:
+ *     -ESHUTDOWN:
+ */
+static int pch_udc_pcd_ep_enable(struct usb_ep *usbep,
+                                   const struct usb_endpoint_descriptor *desc)
+{
+       struct pch_udc_ep       *ep;
+       struct pch_udc_dev      *dev;
+       unsigned long           iflags;
+
+       if (!usbep || (usbep->name == ep0_string) || !desc ||
+           (desc->bDescriptorType != USB_DT_ENDPOINT) || !desc->wMaxPacketSize)
+               return -EINVAL;
+
+       ep = container_of(usbep, struct pch_udc_ep, ep);
+       dev = ep->dev;
+       if (!dev->driver || (dev->gadget.speed == USB_SPEED_UNKNOWN))
+               return -ESHUTDOWN;
+       spin_lock_irqsave(&dev->lock, iflags);
+       ep->ep.desc = desc;
+       ep->halted = 0;
+       pch_udc_ep_enable(ep, &ep->dev->cfg_data, desc);
+       ep->ep.maxpacket = usb_endpoint_maxp(desc);
+       pch_udc_enable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
+       spin_unlock_irqrestore(&dev->lock, iflags);
+       return 0;
+}
+
+/**
+ * pch_udc_pcd_ep_disable() - This API disables endpoint and is called
+ *                             from gadget driver
+ * @usbep      Reference to the USB endpoint structure
+ *
+ * Return codes:
+ *     0:              Success
+ *     -EINVAL:
+ */
+static int pch_udc_pcd_ep_disable(struct usb_ep *usbep)
+{
+       struct pch_udc_ep       *ep;
+       struct pch_udc_dev      *dev;
+       unsigned long   iflags;
+
+       if (!usbep)
+               return -EINVAL;
+
+       ep = container_of(usbep, struct pch_udc_ep, ep);
+       dev = ep->dev;
+       if ((usbep->name == ep0_string) || !ep->ep.desc)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->dev->lock, iflags);
+       empty_req_queue(ep);
+       ep->halted = 1;
+       pch_udc_ep_disable(ep);
+       pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
+       ep->ep.desc = NULL;
+       INIT_LIST_HEAD(&ep->queue);
+       spin_unlock_irqrestore(&ep->dev->lock, iflags);
+       return 0;
+}
+
+/**
+ * pch_udc_alloc_request() - This function allocates request structure.
+ *                             It is called by gadget driver
+ * @usbep:     Reference to the USB endpoint structure
+ * @gfp:       Flag to be used while allocating memory
+ *
+ * Return codes:
+ *     NULL:                   Failure
+ *     Allocated address:      Success
+ */
+static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep,
+                                                 gfp_t gfp)
+{
+       struct pch_udc_request          *req;
+       struct pch_udc_ep               *ep;
+       struct pch_udc_data_dma_desc    *dma_desc;
+       struct pch_udc_dev              *dev;
+
+       if (!usbep)
+               return NULL;
+       ep = container_of(usbep, struct pch_udc_ep, ep);
+       dev = ep->dev;
+       req = kzalloc(sizeof *req, gfp);
+       if (!req)
+               return NULL;
+       req->req.dma = DMA_ADDR_INVALID;
+       req->dma = DMA_ADDR_INVALID;
+       INIT_LIST_HEAD(&req->queue);
+       if (!ep->dev->dma_addr)
+               return &req->req;
+       /* ep0 in requests are allocated from data pool here */
+       dma_desc = pci_pool_alloc(ep->dev->data_requests, gfp,
+                                 &req->td_data_phys);
+       if (NULL == dma_desc) {
+               kfree(req);
+               return NULL;
+       }
+       /* prevent from using desc. - set HOST BUSY */
+       dma_desc->status |= PCH_UDC_BS_HST_BSY;
+       dma_desc->dataptr = __constant_cpu_to_le32(DMA_ADDR_INVALID);
+       req->td_data = dma_desc;
+       req->td_data_last = dma_desc;
+       req->chain_len = 1;
+       return &req->req;
+}
+
+/**
+ * pch_udc_free_request() - This function frees request structure.
+ *                             It is called by gadget driver
+ * @usbep:     Reference to the USB endpoint structure
+ * @usbreq:    Reference to the USB request
+ */
+static void pch_udc_free_request(struct usb_ep *usbep,
+                                 struct usb_request *usbreq)
+{
+       struct pch_udc_ep       *ep;
+       struct pch_udc_request  *req;
+       struct pch_udc_dev      *dev;
+
+       if (!usbep || !usbreq)
+               return;
+       ep = container_of(usbep, struct pch_udc_ep, ep);
+       req = container_of(usbreq, struct pch_udc_request, req);
+       dev = ep->dev;
+       if (!list_empty(&req->queue))
+               dev_err(&dev->pdev->dev, "%s: %s req=0x%p queue not empty\n",
+                       __func__, usbep->name, req);
+       if (req->td_data != NULL) {
+               if (req->chain_len > 1)
+                       pch_udc_free_dma_chain(ep->dev, req);
+               pci_pool_free(ep->dev->data_requests, req->td_data,
+                             req->td_data_phys);
+       }
+       kfree(req);
+}
+
+/**
+ * pch_udc_pcd_queue() - This function queues a request packet. It is called
+ *                     by gadget driver
+ * @usbep:     Reference to the USB endpoint structure
+ * @usbreq:    Reference to the USB request
+ * @gfp:       Flag to be used while mapping the data buffer
+ *
+ * Return codes:
+ *     0:                      Success
+ *     linux error number:     Failure
+ */
+static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq,
+                                                                gfp_t gfp)
+{
+       int retval = 0;
+       struct pch_udc_ep       *ep;
+       struct pch_udc_dev      *dev;
+       struct pch_udc_request  *req;
+       unsigned long   iflags;
+
+       if (!usbep || !usbreq || !usbreq->complete || !usbreq->buf)
+               return -EINVAL;
+       ep = container_of(usbep, struct pch_udc_ep, ep);
+       dev = ep->dev;
+       if (!ep->ep.desc && ep->num)
+               return -EINVAL;
+       req = container_of(usbreq, struct pch_udc_request, req);
+       if (!list_empty(&req->queue))
+               return -EINVAL;
+       if (!dev->driver || (dev->gadget.speed == USB_SPEED_UNKNOWN))
+               return -ESHUTDOWN;
+       spin_lock_irqsave(&dev->lock, iflags);
+       /* map the buffer for dma */
+       if (usbreq->length &&
+           ((usbreq->dma == DMA_ADDR_INVALID) || !usbreq->dma)) {
+               if (!((unsigned long)(usbreq->buf) & 0x03)) {
+                       if (ep->in)
+                               usbreq->dma = dma_map_single(&dev->pdev->dev,
+                                                            usbreq->buf,
+                                                            usbreq->length,
+                                                            DMA_TO_DEVICE);
+                       else
+                               usbreq->dma = dma_map_single(&dev->pdev->dev,
+                                                            usbreq->buf,
+                                                            usbreq->length,
+                                                            DMA_FROM_DEVICE);
+               } else {
+                       req->buf = kzalloc(usbreq->length, GFP_ATOMIC);
+                       if (!req->buf) {
+                               retval = -ENOMEM;
+                               goto probe_end;
+                       }
+                       if (ep->in) {
+                               memcpy(req->buf, usbreq->buf, usbreq->length);
+                               req->dma = dma_map_single(&dev->pdev->dev,
+                                                         req->buf,
+                                                         usbreq->length,
+                                                         DMA_TO_DEVICE);
+                       } else
+                               req->dma = dma_map_single(&dev->pdev->dev,
+                                                         req->buf,
+                                                         usbreq->length,
+                                                         DMA_FROM_DEVICE);
+               }
+               req->dma_mapped = 1;
+       }
+       if (usbreq->length > 0) {
+               retval = prepare_dma(ep, req, GFP_ATOMIC);
+               if (retval)
+                       goto probe_end;
+       }
+       usbreq->actual = 0;
+       usbreq->status = -EINPROGRESS;
+       req->dma_done = 0;
+       if (list_empty(&ep->queue) && !ep->halted) {
+               /* no pending transfer, so start this req */
+               if (!usbreq->length) {
+                       process_zlp(ep, req);
+                       retval = 0;
+                       goto probe_end;
+               }
+               if (!ep->in) {
+                       pch_udc_start_rxrequest(ep, req);
+               } else {
+                       /*
+                       * For IN trfr the descriptors will be programmed and
+                       * P bit will be set when
+                       * we get an IN token
+                       */
+                       pch_udc_wait_ep_stall(ep);
+                       pch_udc_ep_clear_nak(ep);
+                       pch_udc_enable_ep_interrupts(ep->dev, (1 << ep->num));
+               }
+       }
+       /* Now add this request to the ep's pending requests */
+       if (req != NULL)
+               list_add_tail(&req->queue, &ep->queue);
+
+probe_end:
+       spin_unlock_irqrestore(&dev->lock, iflags);
+       return retval;
+}
+
+/**
+ * pch_udc_pcd_dequeue() - This function de-queues a request packet.
+ *                             It is called by gadget driver
+ * @usbep:     Reference to the USB endpoint structure
+ * @usbreq:    Reference to the USB request
+ *
+ * Return codes:
+ *     0:                      Success
+ *     linux error number:     Failure
+ */
+static int pch_udc_pcd_dequeue(struct usb_ep *usbep,
+                               struct usb_request *usbreq)
+{
+       struct pch_udc_ep       *ep;
+       struct pch_udc_request  *req;
+       struct pch_udc_dev      *dev;
+       unsigned long           flags;
+       int ret = -EINVAL;
+
+       ep = container_of(usbep, struct pch_udc_ep, ep);
+       dev = ep->dev;
+       if (!usbep || !usbreq || (!ep->ep.desc && ep->num))
+               return ret;
+       req = container_of(usbreq, struct pch_udc_request, req);
+       spin_lock_irqsave(&ep->dev->lock, flags);
+       /* make sure it's still queued on this endpoint */
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == usbreq) {
+                       pch_udc_ep_set_nak(ep);
+                       if (!list_empty(&req->queue))
+                               complete_req(ep, req, -ECONNRESET);
+                       ret = 0;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+       return ret;
+}
+
+/**
+ * pch_udc_pcd_set_halt() - This function Sets or clear the endpoint halt
+ *                         feature
+ * @usbep:     Reference to the USB endpoint structure
+ * @halt:      Specifies whether to set or clear the feature
+ *
+ * Return codes:
+ *     0:                      Success
+ *     linux error number:     Failure
+ */
+static int pch_udc_pcd_set_halt(struct usb_ep *usbep, int halt)
+{
+       struct pch_udc_ep       *ep;
+       struct pch_udc_dev      *dev;
+       unsigned long iflags;
+       int ret;
+
+       if (!usbep)
+               return -EINVAL;
+       ep = container_of(usbep, struct pch_udc_ep, ep);
+       dev = ep->dev;
+       if (!ep->ep.desc && !ep->num)
+               return -EINVAL;
+       if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN))
+               return -ESHUTDOWN;
+       spin_lock_irqsave(&udc_stall_spinlock, iflags);
+       if (list_empty(&ep->queue)) {
+               if (halt) {
+                       if (ep->num == PCH_UDC_EP0)
+                               ep->dev->stall = 1;
+                       pch_udc_ep_set_stall(ep);
+                       pch_udc_enable_ep_interrupts(ep->dev,
+                                                    PCH_UDC_EPINT(ep->in,
+                                                                  ep->num));
+               } else {
+                       pch_udc_ep_clear_stall(ep);
+               }
+               ret = 0;
+       } else {
+               ret = -EAGAIN;
+       }
+       spin_unlock_irqrestore(&udc_stall_spinlock, iflags);
+       return ret;
+}
+
+/**
+ * pch_udc_pcd_set_wedge() - This function Sets or clear the endpoint
+ *                             halt feature
+ * @usbep:     Reference to the USB endpoint structure
+ * @halt:      Specifies whether to set or clear the feature
+ *
+ * Return codes:
+ *     0:                      Success
+ *     linux error number:     Failure
+ */
+static int pch_udc_pcd_set_wedge(struct usb_ep *usbep)
+{
+       struct pch_udc_ep       *ep;
+       struct pch_udc_dev      *dev;
+       unsigned long iflags;
+       int ret;
+
+       if (!usbep)
+               return -EINVAL;
+       ep = container_of(usbep, struct pch_udc_ep, ep);
+       dev = ep->dev;
+       if (!ep->ep.desc && !ep->num)
+               return -EINVAL;
+       if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN))
+               return -ESHUTDOWN;
+       spin_lock_irqsave(&udc_stall_spinlock, iflags);
+       if (!list_empty(&ep->queue)) {
+               ret = -EAGAIN;
+       } else {
+               if (ep->num == PCH_UDC_EP0)
+                       ep->dev->stall = 1;
+               pch_udc_ep_set_stall(ep);
+               pch_udc_enable_ep_interrupts(ep->dev,
+                                            PCH_UDC_EPINT(ep->in, ep->num));
+               ep->dev->prot_stall = 1;
+               ret = 0;
+       }
+       spin_unlock_irqrestore(&udc_stall_spinlock, iflags);
+       return ret;
+}
+
+/**
+ * pch_udc_pcd_fifo_flush() - This function Flush the FIFO of specified endpoint
+ * @usbep:     Reference to the USB endpoint structure
+ */
+static void pch_udc_pcd_fifo_flush(struct usb_ep *usbep)
+{
+       struct pch_udc_ep  *ep;
+
+       if (!usbep)
+               return;
+
+       ep = container_of(usbep, struct pch_udc_ep, ep);
+       if (ep->ep.desc || !ep->num)
+               pch_udc_ep_fifo_flush(ep, ep->in);
+}
+
+static const struct usb_ep_ops pch_udc_ep_ops = {
+       .enable         = pch_udc_pcd_ep_enable,
+       .disable        = pch_udc_pcd_ep_disable,
+       .alloc_request  = pch_udc_alloc_request,
+       .free_request   = pch_udc_free_request,
+       .queue          = pch_udc_pcd_queue,
+       .dequeue        = pch_udc_pcd_dequeue,
+       .set_halt       = pch_udc_pcd_set_halt,
+       .set_wedge      = pch_udc_pcd_set_wedge,
+       .fifo_status    = NULL,
+       .fifo_flush     = pch_udc_pcd_fifo_flush,
+};
+
+/**
+ * pch_udc_init_setup_buff() - This function initializes the SETUP buffer
+ * @td_stp:    Reference to the SETP buffer structure
+ */
+static void pch_udc_init_setup_buff(struct pch_udc_stp_dma_desc *td_stp)
+{
+       static u32      pky_marker;
+
+       if (!td_stp)
+               return;
+       td_stp->reserved = ++pky_marker;
+       memset(&td_stp->request, 0xFF, sizeof td_stp->request);
+       td_stp->status = PCH_UDC_BS_HST_RDY;
+}
+
+/**
+ * pch_udc_start_next_txrequest() - This function starts
+ *                                     the next transmission requirement
+ * @ep:        Reference to the endpoint structure
+ */
+static void pch_udc_start_next_txrequest(struct pch_udc_ep *ep)
+{
+       struct pch_udc_request *req;
+       struct pch_udc_data_dma_desc *td_data;
+
+       if (pch_udc_read_ep_control(ep) & UDC_EPCTL_P)
+               return;
+
+       if (list_empty(&ep->queue))
+               return;
+
+       /* next request */
+       req = list_entry(ep->queue.next, struct pch_udc_request, queue);
+       if (req->dma_going)
+               return;
+       if (!req->td_data)
+               return;
+       pch_udc_wait_ep_stall(ep);
+       req->dma_going = 1;
+       pch_udc_ep_set_ddptr(ep, 0);
+       td_data = req->td_data;
+       while (1) {
+               td_data->status = (td_data->status & ~PCH_UDC_BUFF_STS) |
+                                  PCH_UDC_BS_HST_RDY;
+               if ((td_data->status & PCH_UDC_DMA_LAST) == PCH_UDC_DMA_LAST)
+                       break;
+               td_data = phys_to_virt(td_data->next);
+       }
+       pch_udc_ep_set_ddptr(ep, req->td_data_phys);
+       pch_udc_set_dma(ep->dev, DMA_DIR_TX);
+       pch_udc_ep_set_pd(ep);
+       pch_udc_enable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
+       pch_udc_ep_clear_nak(ep);
+}
+
+/**
+ * pch_udc_complete_transfer() - This function completes a transfer
+ * @ep:                Reference to the endpoint structure
+ */
+static void pch_udc_complete_transfer(struct pch_udc_ep *ep)
+{
+       struct pch_udc_request *req;
+       struct pch_udc_dev *dev = ep->dev;
+
+       if (list_empty(&ep->queue))
+               return;
+       req = list_entry(ep->queue.next, struct pch_udc_request, queue);
+       if ((req->td_data_last->status & PCH_UDC_BUFF_STS) !=
+           PCH_UDC_BS_DMA_DONE)
+               return;
+       if ((req->td_data_last->status & PCH_UDC_RXTX_STS) !=
+            PCH_UDC_RTS_SUCC) {
+               dev_err(&dev->pdev->dev, "Invalid RXTX status (0x%08x) "
+                       "epstatus=0x%08x\n",
+                      (req->td_data_last->status & PCH_UDC_RXTX_STS),
+                      (int)(ep->epsts));
+               return;
+       }
+
+       req->req.actual = req->req.length;
+       req->td_data_last->status = PCH_UDC_BS_HST_BSY | PCH_UDC_DMA_LAST;
+       req->td_data->status = PCH_UDC_BS_HST_BSY | PCH_UDC_DMA_LAST;
+       complete_req(ep, req, 0);
+       req->dma_going = 0;
+       if (!list_empty(&ep->queue)) {
+               pch_udc_wait_ep_stall(ep);
+               pch_udc_ep_clear_nak(ep);
+               pch_udc_enable_ep_interrupts(ep->dev,
+                                            PCH_UDC_EPINT(ep->in, ep->num));
+       } else {
+               pch_udc_disable_ep_interrupts(ep->dev,
+                                             PCH_UDC_EPINT(ep->in, ep->num));
+       }
+}
+
+/**
+ * pch_udc_complete_receiver() - This function completes a receiver
+ * @ep:                Reference to the endpoint structure
+ */
+static void pch_udc_complete_receiver(struct pch_udc_ep *ep)
+{
+       struct pch_udc_request *req;
+       struct pch_udc_dev *dev = ep->dev;
+       unsigned int count;
+       struct pch_udc_data_dma_desc *td;
+       dma_addr_t addr;
+
+       if (list_empty(&ep->queue))
+               return;
+       /* next request */
+       req = list_entry(ep->queue.next, struct pch_udc_request, queue);
+       pch_udc_clear_dma(ep->dev, DMA_DIR_RX);
+       pch_udc_ep_set_ddptr(ep, 0);
+       if ((req->td_data_last->status & PCH_UDC_BUFF_STS) ==
+           PCH_UDC_BS_DMA_DONE)
+               td = req->td_data_last;
+       else
+               td = req->td_data;
+
+       while (1) {
+               if ((td->status & PCH_UDC_RXTX_STS) != PCH_UDC_RTS_SUCC) {
+                       dev_err(&dev->pdev->dev, "Invalid RXTX status=0x%08x "
+                               "epstatus=0x%08x\n",
+                               (req->td_data->status & PCH_UDC_RXTX_STS),
+                               (int)(ep->epsts));
+                       return;
+               }
+               if ((td->status & PCH_UDC_BUFF_STS) == PCH_UDC_BS_DMA_DONE)
+                       if (td->status & PCH_UDC_DMA_LAST) {
+                               count = td->status & PCH_UDC_RXTX_BYTES;
+                               break;
+                       }
+               if (td == req->td_data_last) {
+                       dev_err(&dev->pdev->dev, "Not complete RX descriptor");
+                       return;
+               }
+               addr = (dma_addr_t)td->next;
+               td = phys_to_virt(addr);
+       }
+       /* on 64k packets the RXBYTES field is zero */
+       if (!count && (req->req.length == UDC_DMA_MAXPACKET))
+               count = UDC_DMA_MAXPACKET;
+       req->td_data->status |= PCH_UDC_DMA_LAST;
+       td->status |= PCH_UDC_BS_HST_BSY;
+
+       req->dma_going = 0;
+       req->req.actual = count;
+       complete_req(ep, req, 0);
+       /* If there is a new/failed requests try that now */
+       if (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct pch_udc_request, queue);
+               pch_udc_start_rxrequest(ep, req);
+       }
+}
+
+/**
+ * pch_udc_svc_data_in() - This function process endpoint interrupts
+ *                             for IN endpoints
+ * @dev:       Reference to the device structure
+ * @ep_num:    Endpoint that generated the interrupt
+ */
+static void pch_udc_svc_data_in(struct pch_udc_dev *dev, int ep_num)
+{
+       u32     epsts;
+       struct pch_udc_ep       *ep;
+
+       ep = &dev->ep[UDC_EPIN_IDX(ep_num)];
+       epsts = ep->epsts;
+       ep->epsts = 0;
+
+       if (!(epsts & (UDC_EPSTS_IN | UDC_EPSTS_BNA  | UDC_EPSTS_HE |
+                      UDC_EPSTS_TDC | UDC_EPSTS_RCS | UDC_EPSTS_TXEMPTY |
+                      UDC_EPSTS_RSS | UDC_EPSTS_XFERDONE)))
+               return;
+       if ((epsts & UDC_EPSTS_BNA))
+               return;
+       if (epsts & UDC_EPSTS_HE)
+               return;
+       if (epsts & UDC_EPSTS_RSS) {
+               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 (!dev->prot_stall) {
+                       pch_udc_ep_clear_stall(ep);
+               } else {
+                       pch_udc_ep_set_stall(ep);
+                       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 */
+       if ((epsts & UDC_EPSTS_IN) && !(epsts & UDC_EPSTS_RSS) &&
+           !(epsts & UDC_EPSTS_TDC) && !(epsts & UDC_EPSTS_TXEMPTY))
+               pch_udc_start_next_txrequest(ep);
+}
+
+/**
+ * pch_udc_svc_data_out() - Handles interrupts from OUT endpoint
+ * @dev:       Reference to the device structure
+ * @ep_num:    Endpoint that generated the interrupt
+ */
+static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num)
+{
+       u32                     epsts;
+       struct pch_udc_ep               *ep;
+       struct pch_udc_request          *req = NULL;
+
+       ep = &dev->ep[UDC_EPOUT_IDX(ep_num)];
+       epsts = ep->epsts;
+       ep->epsts = 0;
+
+       if ((epsts & UDC_EPSTS_BNA) && (!list_empty(&ep->queue))) {
+               /* next request */
+               req = list_entry(ep->queue.next, struct pch_udc_request,
+                                queue);
+               if ((req->td_data_last->status & PCH_UDC_BUFF_STS) !=
+                    PCH_UDC_BS_DMA_DONE) {
+                       if (!req->dma_going)
+                               pch_udc_start_rxrequest(ep, req);
+                       return;
+               }
+       }
+       if (epsts & UDC_EPSTS_HE)
+               return;
+       if (epsts & UDC_EPSTS_RSS) {
+               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 (!dev->prot_stall) {
+                       pch_udc_ep_clear_stall(ep);
+               } else {
+                       pch_udc_ep_set_stall(ep);
+                       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) {
+                       pch_udc_ep_set_stall(ep);
+                       pch_udc_enable_ep_interrupts(ep->dev,
+                                               PCH_UDC_EPINT(ep->in, ep->num));
+               } else {
+                       pch_udc_complete_receiver(ep);
+               }
+       }
+       if (list_empty(&ep->queue))
+               pch_udc_set_dma(dev, DMA_DIR_RX);
+}
+
+/**
+ * pch_udc_svc_control_in() - Handle Control IN endpoint interrupts
+ * @dev:       Reference to the device structure
+ */
+static void pch_udc_svc_control_in(struct pch_udc_dev *dev)
+{
+       u32     epsts;
+       struct pch_udc_ep       *ep;
+       struct pch_udc_ep       *ep_out;
+
+       ep = &dev->ep[UDC_EP0IN_IDX];
+       ep_out = &dev->ep[UDC_EP0OUT_IDX];
+       epsts = ep->epsts;
+       ep->epsts = 0;
+
+       if (!(epsts & (UDC_EPSTS_IN | UDC_EPSTS_BNA | UDC_EPSTS_HE |
+                      UDC_EPSTS_TDC | UDC_EPSTS_RCS | UDC_EPSTS_TXEMPTY |
+                      UDC_EPSTS_XFERDONE)))
+               return;
+       if ((epsts & UDC_EPSTS_BNA))
+               return;
+       if (epsts & UDC_EPSTS_HE)
+               return;
+       if ((epsts & UDC_EPSTS_TDC) && (!dev->stall)) {
+               pch_udc_complete_transfer(ep);
+               pch_udc_clear_dma(dev, DMA_DIR_RX);
+               ep_out->td_data->status = (ep_out->td_data->status &
+                                       ~PCH_UDC_BUFF_STS) |
+                                       PCH_UDC_BS_HST_RDY;
+               pch_udc_ep_clear_nak(ep_out);
+               pch_udc_set_dma(dev, DMA_DIR_RX);
+               pch_udc_ep_set_rrdy(ep_out);
+       }
+       /* On IN interrupt, provide data if we have any */
+       if ((epsts & UDC_EPSTS_IN) && !(epsts & UDC_EPSTS_TDC) &&
+            !(epsts & UDC_EPSTS_TXEMPTY))
+               pch_udc_start_next_txrequest(ep);
+}
+
+/**
+ * pch_udc_svc_control_out() - Routine that handle Control
+ *                                     OUT endpoint interrupts
+ * @dev:       Reference to the device structure
+ */
+static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
+       __releases(&dev->lock)
+       __acquires(&dev->lock)
+{
+       u32     stat;
+       int setup_supported;
+       struct pch_udc_ep       *ep;
+
+       ep = &dev->ep[UDC_EP0OUT_IDX];
+       stat = ep->epsts;
+       ep->epsts = 0;
+
+       /* If setup data */
+       if (((stat & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_SHIFT) ==
+           UDC_EPSTS_OUT_SETUP) {
+               dev->stall = 0;
+               dev->ep[UDC_EP0IN_IDX].halted = 0;
+               dev->ep[UDC_EP0OUT_IDX].halted = 0;
+               dev->setup_data = ep->td_stp->request;
+               pch_udc_init_setup_buff(ep->td_stp);
+               pch_udc_clear_dma(dev, DMA_DIR_RX);
+               pch_udc_ep_fifo_flush(&(dev->ep[UDC_EP0IN_IDX]),
+                                     dev->ep[UDC_EP0IN_IDX].in);
+               if ((dev->setup_data.bRequestType & USB_DIR_IN))
+                       dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep;
+               else /* OUT */
+                       dev->gadget.ep0 = &ep->ep;
+               spin_unlock(&dev->lock);
+               /* If Mass storage Reset */
+               if ((dev->setup_data.bRequestType == 0x21) &&
+                   (dev->setup_data.bRequest == 0xFF))
+                       dev->prot_stall = 0;
+               /* call gadget with setup data received */
+               setup_supported = dev->driver->setup(&dev->gadget,
+                                                    &dev->setup_data);
+               spin_lock(&dev->lock);
+
+               if (dev->setup_data.bRequestType & USB_DIR_IN) {
+                       ep->td_data->status = (ep->td_data->status &
+                                               ~PCH_UDC_BUFF_STS) |
+                                               PCH_UDC_BS_HST_RDY;
+                       pch_udc_ep_set_ddptr(ep, ep->td_data_phys);
+               }
+               /* ep0 in returns data on IN phase */
+               if (setup_supported >= 0 && setup_supported <
+                                           UDC_EP0IN_MAX_PKT_SIZE) {
+                       pch_udc_ep_clear_nak(&(dev->ep[UDC_EP0IN_IDX]));
+                       /* Gadget would have queued a request when
+                        * we called the setup */
+                       if (!(dev->setup_data.bRequestType & USB_DIR_IN)) {
+                               pch_udc_set_dma(dev, DMA_DIR_RX);
+                               pch_udc_ep_clear_nak(ep);
+                       }
+               } else if (setup_supported < 0) {
+                       /* if unsupported request, then stall */
+                       pch_udc_ep_set_stall(&(dev->ep[UDC_EP0IN_IDX]));
+                       pch_udc_enable_ep_interrupts(ep->dev,
+                                               PCH_UDC_EPINT(ep->in, ep->num));
+                       dev->stall = 0;
+                       pch_udc_set_dma(dev, DMA_DIR_RX);
+               } else {
+                       dev->waiting_zlp_ack = 1;
+               }
+       } else if ((((stat & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_SHIFT) ==
+                    UDC_EPSTS_OUT_DATA) && !dev->stall) {
+               pch_udc_clear_dma(dev, DMA_DIR_RX);
+               pch_udc_ep_set_ddptr(ep, 0);
+               if (!list_empty(&ep->queue)) {
+                       ep->epsts = stat;
+                       pch_udc_svc_data_out(dev, PCH_UDC_EP0);
+               }
+               pch_udc_set_dma(dev, DMA_DIR_RX);
+       }
+       pch_udc_ep_set_rrdy(ep);
+}
+
+
+/**
+ * pch_udc_postsvc_epinters() - This function enables end point interrupts
+ *                             and clears NAK status
+ * @dev:       Reference to the device structure
+ * @ep_num:    End point number
+ */
+static void pch_udc_postsvc_epinters(struct pch_udc_dev *dev, int ep_num)
+{
+       struct pch_udc_ep       *ep;
+       struct pch_udc_request *req;
+
+       ep = &dev->ep[UDC_EPIN_IDX(ep_num)];
+       if (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct pch_udc_request, queue);
+               pch_udc_enable_ep_interrupts(ep->dev,
+                                            PCH_UDC_EPINT(ep->in, ep->num));
+               pch_udc_ep_clear_nak(ep);
+       }
+}
+
+/**
+ * pch_udc_read_all_epstatus() - This function read all endpoint status
+ * @dev:       Reference to the device structure
+ * @ep_intr:   Status of endpoint interrupt
+ */
+static void pch_udc_read_all_epstatus(struct pch_udc_dev *dev, u32 ep_intr)
+{
+       int i;
+       struct pch_udc_ep       *ep;
+
+       for (i = 0; i < PCH_UDC_USED_EP_NUM; i++) {
+               /* IN */
+               if (ep_intr & (0x1 << i)) {
+                       ep = &dev->ep[UDC_EPIN_IDX(i)];
+                       ep->epsts = pch_udc_read_ep_status(ep);
+                       pch_udc_clear_ep_status(ep, ep->epsts);
+               }
+               /* OUT */
+               if (ep_intr & (0x10000 << i)) {
+                       ep = &dev->ep[UDC_EPOUT_IDX(i)];
+                       ep->epsts = pch_udc_read_ep_status(ep);
+                       pch_udc_clear_ep_status(ep, ep->epsts);
+               }
+       }
+}
+
+/**
+ * pch_udc_activate_control_ep() - This function enables the control endpoints
+ *                                     for traffic after a reset
+ * @dev:       Reference to the device structure
+ */
+static void pch_udc_activate_control_ep(struct pch_udc_dev *dev)
+{
+       struct pch_udc_ep       *ep;
+       u32 val;
+
+       /* Setup the IN endpoint */
+       ep = &dev->ep[UDC_EP0IN_IDX];
+       pch_udc_clear_ep_control(ep);
+       pch_udc_ep_fifo_flush(ep, ep->in);
+       pch_udc_ep_set_bufsz(ep, UDC_EP0IN_BUFF_SIZE, ep->in);
+       pch_udc_ep_set_maxpkt(ep, UDC_EP0IN_MAX_PKT_SIZE);
+       /* Initialize the IN EP Descriptor */
+       ep->td_data      = NULL;
+       ep->td_stp       = NULL;
+       ep->td_data_phys = 0;
+       ep->td_stp_phys  = 0;
+
+       /* Setup the OUT endpoint */
+       ep = &dev->ep[UDC_EP0OUT_IDX];
+       pch_udc_clear_ep_control(ep);
+       pch_udc_ep_fifo_flush(ep, ep->in);
+       pch_udc_ep_set_bufsz(ep, UDC_EP0OUT_BUFF_SIZE, ep->in);
+       pch_udc_ep_set_maxpkt(ep, UDC_EP0OUT_MAX_PKT_SIZE);
+       val = UDC_EP0OUT_MAX_PKT_SIZE << UDC_CSR_NE_MAX_PKT_SHIFT;
+       pch_udc_write_csr(ep->dev, val, UDC_EP0OUT_IDX);
+
+       /* Initialize the SETUP buffer */
+       pch_udc_init_setup_buff(ep->td_stp);
+       /* Write the pointer address of dma descriptor */
+       pch_udc_ep_set_subptr(ep, ep->td_stp_phys);
+       /* Write the pointer address of Setup descriptor */
+       pch_udc_ep_set_ddptr(ep, ep->td_data_phys);
+
+       /* Initialize the dma descriptor */
+       ep->td_data->status  = PCH_UDC_DMA_LAST;
+       ep->td_data->dataptr = dev->dma_addr;
+       ep->td_data->next    = ep->td_data_phys;
+
+       pch_udc_ep_clear_nak(ep);
+}
+
+
+/**
+ * pch_udc_svc_ur_interrupt() - This function handles a USB reset interrupt
+ * @dev:       Reference to driver structure
+ */
+static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev)
+{
+       struct pch_udc_ep       *ep;
+       int i;
+
+       pch_udc_clear_dma(dev, DMA_DIR_TX);
+       pch_udc_clear_dma(dev, DMA_DIR_RX);
+       /* Mask all endpoint interrupts */
+       pch_udc_disable_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL);
+       /* clear all endpoint interrupts */
+       pch_udc_write_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL);
+
+       for (i = 0; i < PCH_UDC_EP_NUM; i++) {
+               ep = &dev->ep[i];
+               pch_udc_clear_ep_status(ep, UDC_EPSTS_ALL_CLR_MASK);
+               pch_udc_clear_ep_control(ep);
+               pch_udc_ep_set_ddptr(ep, 0);
+               pch_udc_write_csr(ep->dev, 0x00, i);
+       }
+       dev->stall = 0;
+       dev->prot_stall = 0;
+       dev->waiting_zlp_ack = 0;
+       dev->set_cfg_not_acked = 0;
+
+       /* disable ep to empty req queue. Skip the control EP's */
+       for (i = 0; i < (PCH_UDC_USED_EP_NUM*2); i++) {
+               ep = &dev->ep[i];
+               pch_udc_ep_set_nak(ep);
+               pch_udc_ep_fifo_flush(ep, ep->in);
+               /* Complete request queue */
+               empty_req_queue(ep);
+       }
+       if (dev->driver && dev->driver->disconnect) {
+               spin_unlock(&dev->lock);
+               dev->driver->disconnect(&dev->gadget);
+               spin_lock(&dev->lock);
+       }
+}
+
+/**
+ * pch_udc_svc_enum_interrupt() - This function handles a USB speed enumeration
+ *                             done interrupt
+ * @dev:       Reference to driver structure
+ */
+static void pch_udc_svc_enum_interrupt(struct pch_udc_dev *dev)
+{
+       u32 dev_stat, dev_speed;
+       u32 speed = USB_SPEED_FULL;
+
+       dev_stat = pch_udc_read_device_status(dev);
+       dev_speed = (dev_stat & UDC_DEVSTS_ENUM_SPEED_MASK) >>
+                                                UDC_DEVSTS_ENUM_SPEED_SHIFT;
+       switch (dev_speed) {
+       case UDC_DEVSTS_ENUM_SPEED_HIGH:
+               speed = USB_SPEED_HIGH;
+               break;
+       case  UDC_DEVSTS_ENUM_SPEED_FULL:
+               speed = USB_SPEED_FULL;
+               break;
+       case  UDC_DEVSTS_ENUM_SPEED_LOW:
+               speed = USB_SPEED_LOW;
+               break;
+       default:
+               BUG();
+       }
+       dev->gadget.speed = speed;
+       pch_udc_activate_control_ep(dev);
+       pch_udc_enable_ep_interrupts(dev, UDC_EPINT_IN_EP0 | UDC_EPINT_OUT_EP0);
+       pch_udc_set_dma(dev, DMA_DIR_TX);
+       pch_udc_set_dma(dev, DMA_DIR_RX);
+       pch_udc_ep_set_rrdy(&(dev->ep[UDC_EP0OUT_IDX]));
+
+       /* enable device interrupts */
+       pch_udc_enable_interrupts(dev, UDC_DEVINT_UR | UDC_DEVINT_US |
+                                       UDC_DEVINT_ES | UDC_DEVINT_ENUM |
+                                       UDC_DEVINT_SI | UDC_DEVINT_SC);
+}
+
+/**
+ * pch_udc_svc_intf_interrupt() - This function handles a set interface
+ *                               interrupt
+ * @dev:       Reference to driver structure
+ */
+static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev)
+{
+       u32 reg, dev_stat = 0;
+       int i, ret;
+
+       dev_stat = pch_udc_read_device_status(dev);
+       dev->cfg_data.cur_intf = (dev_stat & UDC_DEVSTS_INTF_MASK) >>
+                                                        UDC_DEVSTS_INTF_SHIFT;
+       dev->cfg_data.cur_alt = (dev_stat & UDC_DEVSTS_ALT_MASK) >>
+                                                        UDC_DEVSTS_ALT_SHIFT;
+       dev->set_cfg_not_acked = 1;
+       /* Construct the usb request for gadget driver and inform it */
+       memset(&dev->setup_data, 0 , sizeof dev->setup_data);
+       dev->setup_data.bRequest = USB_REQ_SET_INTERFACE;
+       dev->setup_data.bRequestType = USB_RECIP_INTERFACE;
+       dev->setup_data.wValue = cpu_to_le16(dev->cfg_data.cur_alt);
+       dev->setup_data.wIndex = cpu_to_le16(dev->cfg_data.cur_intf);
+       /* programm the Endpoint Cfg registers */
+       /* Only one end point cfg register */
+       reg = pch_udc_read_csr(dev, UDC_EP0OUT_IDX);
+       reg = (reg & ~UDC_CSR_NE_INTF_MASK) |
+             (dev->cfg_data.cur_intf << UDC_CSR_NE_INTF_SHIFT);
+       reg = (reg & ~UDC_CSR_NE_ALT_MASK) |
+             (dev->cfg_data.cur_alt << UDC_CSR_NE_ALT_SHIFT);
+       pch_udc_write_csr(dev, reg, UDC_EP0OUT_IDX);
+       for (i = 0; i < PCH_UDC_USED_EP_NUM * 2; i++) {
+               /* clear stall bits */
+               pch_udc_ep_clear_stall(&(dev->ep[i]));
+               dev->ep[i].halted = 0;
+       }
+       dev->stall = 0;
+       spin_unlock(&dev->lock);
+       ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
+       spin_lock(&dev->lock);
+}
+
+/**
+ * pch_udc_svc_cfg_interrupt() - This function handles a set configuration
+ *                             interrupt
+ * @dev:       Reference to driver structure
+ */
+static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev)
+{
+       int i, ret;
+       u32 reg, dev_stat = 0;
+
+       dev_stat = pch_udc_read_device_status(dev);
+       dev->set_cfg_not_acked = 1;
+       dev->cfg_data.cur_cfg = (dev_stat & UDC_DEVSTS_CFG_MASK) >>
+                               UDC_DEVSTS_CFG_SHIFT;
+       /* make usb request for gadget driver */
+       memset(&dev->setup_data, 0 , sizeof dev->setup_data);
+       dev->setup_data.bRequest = USB_REQ_SET_CONFIGURATION;
+       dev->setup_data.wValue = cpu_to_le16(dev->cfg_data.cur_cfg);
+       /* program the NE registers */
+       /* Only one end point cfg register */
+       reg = pch_udc_read_csr(dev, UDC_EP0OUT_IDX);
+       reg = (reg & ~UDC_CSR_NE_CFG_MASK) |
+             (dev->cfg_data.cur_cfg << UDC_CSR_NE_CFG_SHIFT);
+       pch_udc_write_csr(dev, reg, UDC_EP0OUT_IDX);
+       for (i = 0; i < PCH_UDC_USED_EP_NUM * 2; i++) {
+               /* clear stall bits */
+               pch_udc_ep_clear_stall(&(dev->ep[i]));
+               dev->ep[i].halted = 0;
+       }
+       dev->stall = 0;
+
+       /* call gadget zero with setup data received */
+       spin_unlock(&dev->lock);
+       ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
+       spin_lock(&dev->lock);
+}
+
+/**
+ * pch_udc_dev_isr() - This function services device interrupts
+ *                     by invoking appropriate routines.
+ * @dev:       Reference to the device structure
+ * @dev_intr:  The Device interrupt status.
+ */
+static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
+{
+       int vbus;
+
+       /* USB Reset Interrupt */
+       if (dev_intr & UDC_DEVINT_UR) {
+               pch_udc_svc_ur_interrupt(dev);
+               dev_dbg(&dev->pdev->dev, "USB_RESET\n");
+       }
+       /* Enumeration Done Interrupt */
+       if (dev_intr & UDC_DEVINT_ENUM) {
+               pch_udc_svc_enum_interrupt(dev);
+               dev_dbg(&dev->pdev->dev, "USB_ENUM\n");
+       }
+       /* Set Interface Interrupt */
+       if (dev_intr & UDC_DEVINT_SI)
+               pch_udc_svc_intf_interrupt(dev);
+       /* Set Config Interrupt */
+       if (dev_intr & UDC_DEVINT_SC)
+               pch_udc_svc_cfg_interrupt(dev);
+       /* USB Suspend interrupt */
+       if (dev_intr & UDC_DEVINT_US) {
+               if (dev->driver
+                       && dev->driver->suspend) {
+                       spin_unlock(&dev->lock);
+                       dev->driver->suspend(&dev->gadget);
+                       spin_lock(&dev->lock);
+               }
+
+               vbus = pch_vbus_gpio_get_value(dev);
+               if ((dev->vbus_session == 0)
+                       && (vbus != 1)) {
+                       if (dev->driver && dev->driver->disconnect) {
+                               spin_unlock(&dev->lock);
+                               dev->driver->disconnect(&dev->gadget);
+                               spin_lock(&dev->lock);
+                       }
+                       pch_udc_reconnect(dev);
+               } else if ((dev->vbus_session == 0)
+                       && (vbus == 1)
+                       && !dev->vbus_gpio.intr)
+                       schedule_work(&dev->vbus_gpio.irq_work_fall);
+
+               dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n");
+       }
+       /* Clear the SOF interrupt, if enabled */
+       if (dev_intr & UDC_DEVINT_SOF)
+               dev_dbg(&dev->pdev->dev, "SOF\n");
+       /* ES interrupt, IDLE > 3ms on the USB */
+       if (dev_intr & UDC_DEVINT_ES)
+               dev_dbg(&dev->pdev->dev, "ES\n");
+       /* RWKP interrupt */
+       if (dev_intr & UDC_DEVINT_RWKP)
+               dev_dbg(&dev->pdev->dev, "RWKP\n");
+}
+
+/**
+ * pch_udc_isr() - This function handles interrupts from the PCH USB Device
+ * @irq:       Interrupt request number
+ * @dev:       Reference to the device structure
+ */
+static irqreturn_t pch_udc_isr(int irq, void *pdev)
+{
+       struct pch_udc_dev *dev = (struct pch_udc_dev *) pdev;
+       u32 dev_intr, ep_intr;
+       int i;
+
+       dev_intr = pch_udc_read_device_interrupts(dev);
+       ep_intr = pch_udc_read_ep_interrupts(dev);
+
+       /* For a hot plug, this find that the controller is hung up. */
+       if (dev_intr == ep_intr)
+               if (dev_intr == pch_udc_readl(dev, UDC_DEVCFG_ADDR)) {
+                       dev_dbg(&dev->pdev->dev, "UDC: Hung up\n");
+                       /* The controller is reset */
+                       pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
+                       return IRQ_HANDLED;
+               }
+       if (dev_intr)
+               /* Clear device interrupts */
+               pch_udc_write_device_interrupts(dev, dev_intr);
+       if (ep_intr)
+               /* Clear ep interrupts */
+               pch_udc_write_ep_interrupts(dev, ep_intr);
+       if (!dev_intr && !ep_intr)
+               return IRQ_NONE;
+       spin_lock(&dev->lock);
+       if (dev_intr)
+               pch_udc_dev_isr(dev, dev_intr);
+       if (ep_intr) {
+               pch_udc_read_all_epstatus(dev, ep_intr);
+               /* Process Control In interrupts, if present */
+               if (ep_intr & UDC_EPINT_IN_EP0) {
+                       pch_udc_svc_control_in(dev);
+                       pch_udc_postsvc_epinters(dev, 0);
+               }
+               /* Process Control Out interrupts, if present */
+               if (ep_intr & UDC_EPINT_OUT_EP0)
+                       pch_udc_svc_control_out(dev);
+               /* Process data in end point interrupts */
+               for (i = 1; i < PCH_UDC_USED_EP_NUM; i++) {
+                       if (ep_intr & (1 <<  i)) {
+                               pch_udc_svc_data_in(dev, i);
+                               pch_udc_postsvc_epinters(dev, i);
+                       }
+               }
+               /* Process data out end point interrupts */
+               for (i = UDC_EPINT_OUT_SHIFT + 1; i < (UDC_EPINT_OUT_SHIFT +
+                                                PCH_UDC_USED_EP_NUM); i++)
+                       if (ep_intr & (1 <<  i))
+                               pch_udc_svc_data_out(dev, i -
+                                                        UDC_EPINT_OUT_SHIFT);
+       }
+       spin_unlock(&dev->lock);
+       return IRQ_HANDLED;
+}
+
+/**
+ * pch_udc_setup_ep0() - This function enables control endpoint for traffic
+ * @dev:       Reference to the device structure
+ */
+static void pch_udc_setup_ep0(struct pch_udc_dev *dev)
+{
+       /* enable ep0 interrupts */
+       pch_udc_enable_ep_interrupts(dev, UDC_EPINT_IN_EP0 |
+                                               UDC_EPINT_OUT_EP0);
+       /* enable device interrupts */
+       pch_udc_enable_interrupts(dev, UDC_DEVINT_UR | UDC_DEVINT_US |
+                                      UDC_DEVINT_ES | UDC_DEVINT_ENUM |
+                                      UDC_DEVINT_SI | UDC_DEVINT_SC);
+}
+
+/**
+ * gadget_release() - Free the gadget driver private data
+ * @pdev       reference to struct pci_dev
+ */
+static void gadget_release(struct device *pdev)
+{
+       struct pch_udc_dev *dev = dev_get_drvdata(pdev);
+
+       kfree(dev);
+}
+
+/**
+ * pch_udc_pcd_reinit() - This API initializes the endpoint structures
+ * @dev:       Reference to the driver structure
+ */
+static void pch_udc_pcd_reinit(struct pch_udc_dev *dev)
+{
+       const char *const ep_string[] = {
+               ep0_string, "ep0out", "ep1in", "ep1out", "ep2in", "ep2out",
+               "ep3in", "ep3out", "ep4in", "ep4out", "ep5in", "ep5out",
+               "ep6in", "ep6out", "ep7in", "ep7out", "ep8in", "ep8out",
+               "ep9in", "ep9out", "ep10in", "ep10out", "ep11in", "ep11out",
+               "ep12in", "ep12out", "ep13in", "ep13out", "ep14in", "ep14out",
+               "ep15in", "ep15out",
+       };
+       int i;
+
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+       INIT_LIST_HEAD(&dev->gadget.ep_list);
+
+       /* Initialize the endpoints structures */
+       memset(dev->ep, 0, sizeof dev->ep);
+       for (i = 0; i < PCH_UDC_EP_NUM; i++) {
+               struct pch_udc_ep *ep = &dev->ep[i];
+               ep->dev = dev;
+               ep->halted = 1;
+               ep->num = i / 2;
+               ep->in = ~i & 1;
+               ep->ep.name = ep_string[i];
+               ep->ep.ops = &pch_udc_ep_ops;
+               if (ep->in)
+                       ep->offset_addr = ep->num * UDC_EP_REG_SHIFT;
+               else
+                       ep->offset_addr = (UDC_EPINT_OUT_SHIFT + ep->num) *
+                                         UDC_EP_REG_SHIFT;
+               /* need to set ep->ep.maxpacket and set Default Configuration?*/
+               usb_ep_set_maxpacket_limit(&ep->ep, UDC_BULK_MAX_PKT_SIZE);
+               list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+               INIT_LIST_HEAD(&ep->queue);
+       }
+       usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0IN_IDX].ep, UDC_EP0IN_MAX_PKT_SIZE);
+       usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0OUT_IDX].ep, UDC_EP0OUT_MAX_PKT_SIZE);
+
+       /* remove ep0 in and out from the list.  They have own pointer */
+       list_del_init(&dev->ep[UDC_EP0IN_IDX].ep.ep_list);
+       list_del_init(&dev->ep[UDC_EP0OUT_IDX].ep.ep_list);
+
+       dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep;
+       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+}
+
+/**
+ * pch_udc_pcd_init() - This API initializes the driver structure
+ * @dev:       Reference to the driver structure
+ *
+ * Return codes:
+ *     0: Success
+ */
+static int pch_udc_pcd_init(struct pch_udc_dev *dev)
+{
+       pch_udc_init(dev);
+       pch_udc_pcd_reinit(dev);
+       pch_vbus_gpio_init(dev, vbus_gpio_port);
+       return 0;
+}
+
+/**
+ * init_dma_pools() - create dma pools during initialization
+ * @pdev:      reference to struct pci_dev
+ */
+static int init_dma_pools(struct pch_udc_dev *dev)
+{
+       struct pch_udc_stp_dma_desc     *td_stp;
+       struct pch_udc_data_dma_desc    *td_data;
+
+       /* DMA setup */
+       dev->data_requests = pci_pool_create("data_requests", dev->pdev,
+               sizeof(struct pch_udc_data_dma_desc), 0, 0);
+       if (!dev->data_requests) {
+               dev_err(&dev->pdev->dev, "%s: can't get request data pool\n",
+                       __func__);
+               return -ENOMEM;
+       }
+
+       /* dma desc for setup data */
+       dev->stp_requests = pci_pool_create("setup requests", dev->pdev,
+               sizeof(struct pch_udc_stp_dma_desc), 0, 0);
+       if (!dev->stp_requests) {
+               dev_err(&dev->pdev->dev, "%s: can't get setup request pool\n",
+                       __func__);
+               return -ENOMEM;
+       }
+       /* setup */
+       td_stp = pci_pool_alloc(dev->stp_requests, GFP_KERNEL,
+                               &dev->ep[UDC_EP0OUT_IDX].td_stp_phys);
+       if (!td_stp) {
+               dev_err(&dev->pdev->dev,
+                       "%s: can't allocate setup dma descriptor\n", __func__);
+               return -ENOMEM;
+       }
+       dev->ep[UDC_EP0OUT_IDX].td_stp = td_stp;
+
+       /* data: 0 packets !? */
+       td_data = pci_pool_alloc(dev->data_requests, GFP_KERNEL,
+                               &dev->ep[UDC_EP0OUT_IDX].td_data_phys);
+       if (!td_data) {
+               dev_err(&dev->pdev->dev,
+                       "%s: can't allocate data dma descriptor\n", __func__);
+               return -ENOMEM;
+       }
+       dev->ep[UDC_EP0OUT_IDX].td_data = td_data;
+       dev->ep[UDC_EP0IN_IDX].td_stp = NULL;
+       dev->ep[UDC_EP0IN_IDX].td_stp_phys = 0;
+       dev->ep[UDC_EP0IN_IDX].td_data = NULL;
+       dev->ep[UDC_EP0IN_IDX].td_data_phys = 0;
+
+       dev->ep0out_buf = kzalloc(UDC_EP0OUT_BUFF_SIZE * 4, GFP_KERNEL);
+       if (!dev->ep0out_buf)
+               return -ENOMEM;
+       dev->dma_addr = dma_map_single(&dev->pdev->dev, dev->ep0out_buf,
+                                      UDC_EP0OUT_BUFF_SIZE * 4,
+                                      DMA_FROM_DEVICE);
+       return 0;
+}
+
+static int pch_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct pch_udc_dev      *dev = to_pch_udc(g);
+
+       driver->driver.bus = NULL;
+       dev->driver = driver;
+
+       /* get ready for ep0 traffic */
+       pch_udc_setup_ep0(dev);
+
+       /* clear SD */
+       if ((pch_vbus_gpio_get_value(dev) != 0) || !dev->vbus_gpio.intr)
+               pch_udc_clear_disconnect(dev);
+
+       dev->connected = 1;
+       return 0;
+}
+
+static int pch_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct pch_udc_dev      *dev = to_pch_udc(g);
+
+       pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
+
+       /* Assures that there are no pending requests with this driver */
+       dev->driver = NULL;
+       dev->connected = 0;
+
+       /* set SD */
+       pch_udc_set_disconnect(dev);
+
+       return 0;
+}
+
+static void pch_udc_shutdown(struct pci_dev *pdev)
+{
+       struct pch_udc_dev *dev = pci_get_drvdata(pdev);
+
+       pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
+       pch_udc_disable_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL);
+
+       /* disable the pullup so the host will think we're gone */
+       pch_udc_set_disconnect(dev);
+}
+
+static void pch_udc_remove(struct pci_dev *pdev)
+{
+       struct pch_udc_dev      *dev = pci_get_drvdata(pdev);
+
+       usb_del_gadget_udc(&dev->gadget);
+
+       /* gadget driver must not be registered */
+       if (dev->driver)
+               dev_err(&pdev->dev,
+                       "%s: gadget driver still bound!!!\n", __func__);
+       /* dma pool cleanup */
+       if (dev->data_requests)
+               pci_pool_destroy(dev->data_requests);
+
+       if (dev->stp_requests) {
+               /* cleanup DMA desc's for ep0in */
+               if (dev->ep[UDC_EP0OUT_IDX].td_stp) {
+                       pci_pool_free(dev->stp_requests,
+                               dev->ep[UDC_EP0OUT_IDX].td_stp,
+                               dev->ep[UDC_EP0OUT_IDX].td_stp_phys);
+               }
+               if (dev->ep[UDC_EP0OUT_IDX].td_data) {
+                       pci_pool_free(dev->stp_requests,
+                               dev->ep[UDC_EP0OUT_IDX].td_data,
+                               dev->ep[UDC_EP0OUT_IDX].td_data_phys);
+               }
+               pci_pool_destroy(dev->stp_requests);
+       }
+
+       if (dev->dma_addr)
+               dma_unmap_single(&dev->pdev->dev, dev->dma_addr,
+                                UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE);
+       kfree(dev->ep0out_buf);
+
+       pch_vbus_gpio_free(dev);
+
+       pch_udc_exit(dev);
+
+       if (dev->irq_registered)
+               free_irq(pdev->irq, dev);
+       if (dev->base_addr)
+               iounmap(dev->base_addr);
+       if (dev->mem_region)
+               release_mem_region(dev->phys_addr,
+                                  pci_resource_len(pdev, PCH_UDC_PCI_BAR));
+       if (dev->active)
+               pci_disable_device(pdev);
+       kfree(dev);
+}
+
+#ifdef CONFIG_PM
+static int pch_udc_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct pch_udc_dev *dev = pci_get_drvdata(pdev);
+
+       pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
+       pch_udc_disable_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL);
+
+       pci_disable_device(pdev);
+       pci_enable_wake(pdev, PCI_D3hot, 0);
+
+       if (pci_save_state(pdev)) {
+               dev_err(&pdev->dev,
+                       "%s: could not save PCI config state\n", __func__);
+               return -ENOMEM;
+       }
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+       return 0;
+}
+
+static int pch_udc_resume(struct pci_dev *pdev)
+{
+       int ret;
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       ret = pci_enable_device(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "%s: pci_enable_device failed\n", __func__);
+               return ret;
+       }
+       pci_enable_wake(pdev, PCI_D3hot, 0);
+       return 0;
+}
+#else
+#define pch_udc_suspend        NULL
+#define pch_udc_resume NULL
+#endif /* CONFIG_PM */
+
+static int pch_udc_probe(struct pci_dev *pdev,
+                         const struct pci_device_id *id)
+{
+       unsigned long           resource;
+       unsigned long           len;
+       int                     retval;
+       struct pch_udc_dev      *dev;
+
+       /* init */
+       dev = kzalloc(sizeof *dev, GFP_KERNEL);
+       if (!dev) {
+               pr_err("%s: no memory for device structure\n", __func__);
+               return -ENOMEM;
+       }
+       /* pci setup */
+       if (pci_enable_device(pdev) < 0) {
+               kfree(dev);
+               pr_err("%s: pci_enable_device failed\n", __func__);
+               return -ENODEV;
+       }
+       dev->active = 1;
+       pci_set_drvdata(pdev, dev);
+
+       /* PCI resource allocation */
+       resource = pci_resource_start(pdev, 1);
+       len = pci_resource_len(pdev, 1);
+
+       if (!request_mem_region(resource, len, KBUILD_MODNAME)) {
+               dev_err(&pdev->dev, "%s: pci device used already\n", __func__);
+               retval = -EBUSY;
+               goto finished;
+       }
+       dev->phys_addr = resource;
+       dev->mem_region = 1;
+
+       dev->base_addr = ioremap_nocache(resource, len);
+       if (!dev->base_addr) {
+               pr_err("%s: device memory cannot be mapped\n", __func__);
+               retval = -ENOMEM;
+               goto finished;
+       }
+       if (!pdev->irq) {
+               dev_err(&pdev->dev, "%s: irq not set\n", __func__);
+               retval = -ENODEV;
+               goto finished;
+       }
+       /* initialize the hardware */
+       if (pch_udc_pcd_init(dev)) {
+               retval = -ENODEV;
+               goto finished;
+       }
+       if (request_irq(pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME,
+                       dev)) {
+               dev_err(&pdev->dev, "%s: request_irq(%d) fail\n", __func__,
+                       pdev->irq);
+               retval = -ENODEV;
+               goto finished;
+       }
+       dev->irq = pdev->irq;
+       dev->irq_registered = 1;
+
+       pci_set_master(pdev);
+       pci_try_set_mwi(pdev);
+
+       /* device struct setup */
+       spin_lock_init(&dev->lock);
+       dev->pdev = pdev;
+       dev->gadget.ops = &pch_udc_ops;
+
+       retval = init_dma_pools(dev);
+       if (retval)
+               goto finished;
+
+       dev->gadget.name = KBUILD_MODNAME;
+       dev->gadget.max_speed = USB_SPEED_HIGH;
+
+       /* Put the device in disconnected state till a driver is bound */
+       pch_udc_set_disconnect(dev);
+       retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+                       gadget_release);
+       if (retval)
+               goto finished;
+       return 0;
+
+finished:
+       pch_udc_remove(pdev);
+       return retval;
+}
+
+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,
+               .class_mask = 0xffffffff,
+       },
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7213_IOH_UDC),
+               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class_mask = 0xffffffff,
+       },
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7831_IOH_UDC),
+               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class_mask = 0xffffffff,
+       },
+       { 0 },
+};
+
+MODULE_DEVICE_TABLE(pci, pch_udc_pcidev_id);
+
+static struct pci_driver pch_udc_driver = {
+       .name = KBUILD_MODNAME,
+       .id_table =     pch_udc_pcidev_id,
+       .probe =        pch_udc_probe,
+       .remove =       pch_udc_remove,
+       .suspend =      pch_udc_suspend,
+       .resume =       pch_udc_resume,
+       .shutdown =     pch_udc_shutdown,
+};
+
+module_pci_driver(pch_udc_driver);
+
+MODULE_DESCRIPTION("Intel EG20T USB Device Controller");
+MODULE_AUTHOR("LAPIS Semiconductor, <tomoya-linux@dsn.lapis-semi.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c
new file mode 100644 (file)
index 0000000..251e4d5
--- /dev/null
@@ -0,0 +1,2284 @@
+/*
+ * Intel PXA25x and IXP4xx on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker)
+ * Copyright (C) 2003 Robert Schwebel, Pengutronix
+ * Copyright (C) 2003 Benedikt Spranger, Pengutronix
+ * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2003 Joshua Wise
+ *
+ * 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.
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/platform_data/pxa2xx_udc.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/io.h>
+#include <linux/prefetch.h>
+
+#include <asm/byteorder.h>
+#include <asm/dma.h>
+#include <asm/mach-types.h>
+#include <asm/unaligned.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+
+/*
+ * This driver is PXA25x only.  Grab the right register definitions.
+ */
+#ifdef CONFIG_ARCH_PXA
+#include <mach/pxa25x-udc.h>
+#include <mach/hardware.h>
+#endif
+
+#ifdef CONFIG_ARCH_LUBBOCK
+#include <mach/lubbock.h>
+#endif
+
+/*
+ * This driver handles the USB Device Controller (UDC) in Intel's PXA 25x
+ * series processors.  The UDC for the IXP 4xx series is very similar.
+ * There are fifteen endpoints, in addition to ep0.
+ *
+ * Such controller drivers work with a gadget driver.  The gadget driver
+ * returns descriptors, implements configuration and data protocols used
+ * by the host to interact with this device, and allocates endpoints to
+ * the different protocol interfaces.  The controller driver virtualizes
+ * usb hardware so that the gadget drivers will be more portable.
+ *
+ * This UDC hardware wants to implement a bit too much USB protocol, so
+ * it constrains the sorts of USB configuration change events that work.
+ * The errata for these chips are misleading; some "fixed" bugs from
+ * pxa250 a0/a1 b0/b1/b2 sure act like they're still there.
+ *
+ * Note that the UDC hardware supports DMA (except on IXP) but that's
+ * not used here.  IN-DMA (to host) is simple enough, when the data is
+ * suitably aligned (16 bytes) ... the network stack doesn't do that,
+ * other software can.  OUT-DMA is buggy in most chip versions, as well
+ * as poorly designed (data toggle not automatic).  So this driver won't
+ * bother using DMA.  (Mostly-working IN-DMA support was available in
+ * kernels before 2.6.23, but was never enabled or well tested.)
+ */
+
+#define        DRIVER_VERSION  "30-June-2007"
+#define        DRIVER_DESC     "PXA 25x USB Device Controller driver"
+
+
+static const char driver_name [] = "pxa25x_udc";
+
+static const char ep0name [] = "ep0";
+
+
+#ifdef CONFIG_ARCH_IXP4XX
+
+/* cpu-specific register addresses are compiled in to this code */
+#ifdef CONFIG_ARCH_PXA
+#error "Can't configure both IXP and PXA"
+#endif
+
+/* IXP doesn't yet support <linux/clk.h> */
+#define clk_get(dev,name)      NULL
+#define clk_enable(clk)                do { } while (0)
+#define clk_disable(clk)       do { } while (0)
+#define clk_put(clk)           do { } while (0)
+
+#endif
+
+#include "pxa25x_udc.h"
+
+
+#ifdef CONFIG_USB_PXA25X_SMALL
+#define SIZE_STR       " (small)"
+#else
+#define SIZE_STR       ""
+#endif
+
+/* ---------------------------------------------------------------------------
+ *     endpoint related parts of the api to the usb controller hardware,
+ *     used by gadget driver; and the inner talker-to-hardware core.
+ * ---------------------------------------------------------------------------
+ */
+
+static void pxa25x_ep_fifo_flush (struct usb_ep *ep);
+static void nuke (struct pxa25x_ep *, int status);
+
+/* one GPIO should control a D+ pullup, so host sees this device (or not) */
+static void pullup_off(void)
+{
+       struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
+       int off_level = mach->gpio_pullup_inverted;
+
+       if (gpio_is_valid(mach->gpio_pullup))
+               gpio_set_value(mach->gpio_pullup, off_level);
+       else if (mach->udc_command)
+               mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+}
+
+static void pullup_on(void)
+{
+       struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
+       int on_level = !mach->gpio_pullup_inverted;
+
+       if (gpio_is_valid(mach->gpio_pullup))
+               gpio_set_value(mach->gpio_pullup, on_level);
+       else if (mach->udc_command)
+               mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+}
+
+static void pio_irq_enable(int bEndpointAddress)
+{
+        bEndpointAddress &= 0xf;
+        if (bEndpointAddress < 8)
+                UICR0 &= ~(1 << bEndpointAddress);
+        else {
+                bEndpointAddress -= 8;
+                UICR1 &= ~(1 << bEndpointAddress);
+       }
+}
+
+static void pio_irq_disable(int bEndpointAddress)
+{
+        bEndpointAddress &= 0xf;
+        if (bEndpointAddress < 8)
+                UICR0 |= 1 << bEndpointAddress;
+        else {
+                bEndpointAddress -= 8;
+                UICR1 |= 1 << bEndpointAddress;
+        }
+}
+
+/* The UDCCR reg contains mask and interrupt status bits,
+ * so using '|=' isn't safe as it may ack an interrupt.
+ */
+#define UDCCR_MASK_BITS         (UDCCR_REM | UDCCR_SRM | UDCCR_UDE)
+
+static inline void udc_set_mask_UDCCR(int mask)
+{
+       UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS);
+}
+
+static inline void udc_clear_mask_UDCCR(int mask)
+{
+       UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS);
+}
+
+static inline void udc_ack_int_UDCCR(int mask)
+{
+       /* udccr contains the bits we dont want to change */
+       __u32 udccr = UDCCR & UDCCR_MASK_BITS;
+
+       UDCCR = udccr | (mask & ~UDCCR_MASK_BITS);
+}
+
+/*
+ * endpoint enable/disable
+ *
+ * we need to verify the descriptors used to enable endpoints.  since pxa25x
+ * endpoint configurations are fixed, and are pretty much always enabled,
+ * there's not a lot to manage here.
+ *
+ * because pxa25x can't selectively initialize bulk (or interrupt) endpoints,
+ * (resetting endpoint halt and toggle), SET_INTERFACE is unusable except
+ * for a single interface (with only the default altsetting) and for gadget
+ * drivers that don't halt endpoints (not reset by set_interface).  that also
+ * means that if you use ISO, you must violate the USB spec rule that all
+ * iso endpoints must be in non-default altsettings.
+ */
+static int pxa25x_ep_enable (struct usb_ep *_ep,
+               const struct usb_endpoint_descriptor *desc)
+{
+       struct pxa25x_ep        *ep;
+       struct pxa25x_udc       *dev;
+
+       ep = container_of (_ep, struct pxa25x_ep, ep);
+       if (!_ep || !desc || _ep->name == ep0name
+                       || desc->bDescriptorType != USB_DT_ENDPOINT
+                       || ep->bEndpointAddress != desc->bEndpointAddress
+                       || ep->fifo_size < usb_endpoint_maxp (desc)) {
+               DMSG("%s, bad ep or descriptor\n", __func__);
+               return -EINVAL;
+       }
+
+       /* xfer types must match, except that interrupt ~= bulk */
+       if (ep->bmAttributes != desc->bmAttributes
+                       && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+                       && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+               DMSG("%s, %s type mismatch\n", __func__, _ep->name);
+               return -EINVAL;
+       }
+
+       /* hardware _could_ do smaller, but driver doesn't */
+       if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+                               && usb_endpoint_maxp (desc)
+                                               != BULK_FIFO_SIZE)
+                       || !desc->wMaxPacketSize) {
+               DMSG("%s, bad %s maxpacket\n", __func__, _ep->name);
+               return -ERANGE;
+       }
+
+       dev = ep->dev;
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+               DMSG("%s, bogus device state\n", __func__);
+               return -ESHUTDOWN;
+       }
+
+       ep->ep.desc = desc;
+       ep->stopped = 0;
+       ep->pio_irqs = 0;
+       ep->ep.maxpacket = usb_endpoint_maxp (desc);
+
+       /* flush fifo (mostly for OUT buffers) */
+       pxa25x_ep_fifo_flush (_ep);
+
+       /* ... reset halt state too, if we could ... */
+
+       DBG(DBG_VERBOSE, "enabled %s\n", _ep->name);
+       return 0;
+}
+
+static int pxa25x_ep_disable (struct usb_ep *_ep)
+{
+       struct pxa25x_ep        *ep;
+       unsigned long           flags;
+
+       ep = container_of (_ep, struct pxa25x_ep, ep);
+       if (!_ep || !ep->ep.desc) {
+               DMSG("%s, %s not enabled\n", __func__,
+                       _ep ? ep->ep.name : NULL);
+               return -EINVAL;
+       }
+       local_irq_save(flags);
+
+       nuke (ep, -ESHUTDOWN);
+
+       /* flush fifo (mostly for IN buffers) */
+       pxa25x_ep_fifo_flush (_ep);
+
+       ep->ep.desc = NULL;
+       ep->stopped = 1;
+
+       local_irq_restore(flags);
+       DBG(DBG_VERBOSE, "%s disabled\n", _ep->name);
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* for the pxa25x, these can just wrap kmalloc/kfree.  gadget drivers
+ * must still pass correctly initialized endpoints, since other controller
+ * drivers may care about how it's currently set up (dma issues etc).
+ */
+
+/*
+ *     pxa25x_ep_alloc_request - allocate a request data structure
+ */
+static struct usb_request *
+pxa25x_ep_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct pxa25x_request *req;
+
+       req = kzalloc(sizeof(*req), gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD (&req->queue);
+       return &req->req;
+}
+
+
+/*
+ *     pxa25x_ep_free_request - deallocate a request data structure
+ */
+static void
+pxa25x_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct pxa25x_request   *req;
+
+       req = container_of (_req, struct pxa25x_request, req);
+       WARN_ON(!list_empty (&req->queue));
+       kfree(req);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ *     done - retire a request; caller blocked irqs
+ */
+static void done(struct pxa25x_ep *ep, struct pxa25x_request *req, int status)
+{
+       unsigned                stopped = ep->stopped;
+
+       list_del_init(&req->queue);
+
+       if (likely (req->req.status == -EINPROGRESS))
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       if (status && status != -ESHUTDOWN)
+               DBG(DBG_VERBOSE, "complete %s req %p stat %d len %u/%u\n",
+                       ep->ep.name, &req->req, status,
+                       req->req.actual, req->req.length);
+
+       /* don't modify queue heads during completion callback */
+       ep->stopped = 1;
+       req->req.complete(&ep->ep, &req->req);
+       ep->stopped = stopped;
+}
+
+
+static inline void ep0_idle (struct pxa25x_udc *dev)
+{
+       dev->ep0state = EP0_IDLE;
+}
+
+static int
+write_packet(volatile u32 *uddr, struct pxa25x_request *req, unsigned max)
+{
+       u8              *buf;
+       unsigned        length, count;
+
+       buf = req->req.buf + req->req.actual;
+       prefetch(buf);
+
+       /* how big will this packet be? */
+       length = min(req->req.length - req->req.actual, max);
+       req->req.actual += length;
+
+       count = length;
+       while (likely(count--))
+               *uddr = *buf++;
+
+       return length;
+}
+
+/*
+ * write to an IN endpoint fifo, as many packets as possible.
+ * irqs will use this to write the rest later.
+ * caller guarantees at least one packet buffer is ready (or a zlp).
+ */
+static int
+write_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
+{
+       unsigned                max;
+
+       max = usb_endpoint_maxp(ep->ep.desc);
+       do {
+               unsigned        count;
+               int             is_last, is_short;
+
+               count = write_packet(ep->reg_uddr, req, max);
+
+               /* last packet is usually short (or a zlp) */
+               if (unlikely (count != max))
+                       is_last = is_short = 1;
+               else {
+                       if (likely(req->req.length != req->req.actual)
+                                       || req->req.zero)
+                               is_last = 0;
+                       else
+                               is_last = 1;
+                       /* interrupt/iso maxpacket may not fill the fifo */
+                       is_short = unlikely (max < ep->fifo_size);
+               }
+
+               DBG(DBG_VERY_NOISY, "wrote %s %d bytes%s%s %d left %p\n",
+                       ep->ep.name, count,
+                       is_last ? "/L" : "", is_short ? "/S" : "",
+                       req->req.length - req->req.actual, req);
+
+               /* let loose that packet. maybe try writing another one,
+                * double buffering might work.  TSP, TPC, and TFS
+                * bit values are the same for all normal IN endpoints.
+                */
+               *ep->reg_udccs = UDCCS_BI_TPC;
+               if (is_short)
+                       *ep->reg_udccs = UDCCS_BI_TSP;
+
+               /* requests complete when all IN data is in the FIFO */
+               if (is_last) {
+                       done (ep, req, 0);
+                       if (list_empty(&ep->queue))
+                               pio_irq_disable (ep->bEndpointAddress);
+                       return 1;
+               }
+
+               // TODO experiment: how robust can fifo mode tweaking be?
+               // double buffering is off in the default fifo mode, which
+               // prevents TFS from being set here.
+
+       } while (*ep->reg_udccs & UDCCS_BI_TFS);
+       return 0;
+}
+
+/* caller asserts req->pending (ep0 irq status nyet cleared); starts
+ * ep0 data stage.  these chips want very simple state transitions.
+ */
+static inline
+void ep0start(struct pxa25x_udc *dev, u32 flags, const char *tag)
+{
+       UDCCS0 = flags|UDCCS0_SA|UDCCS0_OPR;
+       USIR0 = USIR0_IR0;
+       dev->req_pending = 0;
+       DBG(DBG_VERY_NOISY, "%s %s, %02x/%02x\n",
+               __func__, tag, UDCCS0, flags);
+}
+
+static int
+write_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
+{
+       unsigned        count;
+       int             is_short;
+
+       count = write_packet(&UDDR0, req, EP0_FIFO_SIZE);
+       ep->dev->stats.write.bytes += count;
+
+       /* last packet "must be" short (or a zlp) */
+       is_short = (count != EP0_FIFO_SIZE);
+
+       DBG(DBG_VERY_NOISY, "ep0in %d bytes %d left %p\n", count,
+               req->req.length - req->req.actual, req);
+
+       if (unlikely (is_short)) {
+               if (ep->dev->req_pending)
+                       ep0start(ep->dev, UDCCS0_IPR, "short IN");
+               else
+                       UDCCS0 = UDCCS0_IPR;
+
+               count = req->req.length;
+               done (ep, req, 0);
+               ep0_idle(ep->dev);
+#ifndef CONFIG_ARCH_IXP4XX
+#if 1
+               /* This seems to get rid of lost status irqs in some cases:
+                * host responds quickly, or next request involves config
+                * change automagic, or should have been hidden, or ...
+                *
+                * FIXME get rid of all udelays possible...
+                */
+               if (count >= EP0_FIFO_SIZE) {
+                       count = 100;
+                       do {
+                               if ((UDCCS0 & UDCCS0_OPR) != 0) {
+                                       /* clear OPR, generate ack */
+                                       UDCCS0 = UDCCS0_OPR;
+                                       break;
+                               }
+                               count--;
+                               udelay(1);
+                       } while (count);
+               }
+#endif
+#endif
+       } else if (ep->dev->req_pending)
+               ep0start(ep->dev, 0, "IN");
+       return is_short;
+}
+
+
+/*
+ * read_fifo -  unload packet(s) from the fifo we use for usb OUT
+ * transfers and put them into the request.  caller should have made
+ * sure there's at least one packet ready.
+ *
+ * returns true if the request completed because of short packet or the
+ * request buffer having filled (and maybe overran till end-of-packet).
+ */
+static int
+read_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
+{
+       for (;;) {
+               u32             udccs;
+               u8              *buf;
+               unsigned        bufferspace, count, is_short;
+
+               /* make sure there's a packet in the FIFO.
+                * UDCCS_{BO,IO}_RPC are all the same bit value.
+                * UDCCS_{BO,IO}_RNE are all the same bit value.
+                */
+               udccs = *ep->reg_udccs;
+               if (unlikely ((udccs & UDCCS_BO_RPC) == 0))
+                       break;
+               buf = req->req.buf + req->req.actual;
+               prefetchw(buf);
+               bufferspace = req->req.length - req->req.actual;
+
+               /* read all bytes from this packet */
+               if (likely (udccs & UDCCS_BO_RNE)) {
+                       count = 1 + (0x0ff & *ep->reg_ubcr);
+                       req->req.actual += min (count, bufferspace);
+               } else /* zlp */
+                       count = 0;
+               is_short = (count < ep->ep.maxpacket);
+               DBG(DBG_VERY_NOISY, "read %s %02x, %d bytes%s req %p %d/%d\n",
+                       ep->ep.name, udccs, count,
+                       is_short ? "/S" : "",
+                       req, req->req.actual, req->req.length);
+               while (likely (count-- != 0)) {
+                       u8      byte = (u8) *ep->reg_uddr;
+
+                       if (unlikely (bufferspace == 0)) {
+                               /* this happens when the driver's buffer
+                                * is smaller than what the host sent.
+                                * discard the extra data.
+                                */
+                               if (req->req.status != -EOVERFLOW)
+                                       DMSG("%s overflow %d\n",
+                                               ep->ep.name, count);
+                               req->req.status = -EOVERFLOW;
+                       } else {
+                               *buf++ = byte;
+                               bufferspace--;
+                       }
+               }
+               *ep->reg_udccs =  UDCCS_BO_RPC;
+               /* RPC/RSP/RNE could now reflect the other packet buffer */
+
+               /* iso is one request per packet */
+               if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+                       if (udccs & UDCCS_IO_ROF)
+                               req->req.status = -EHOSTUNREACH;
+                       /* more like "is_done" */
+                       is_short = 1;
+               }
+
+               /* completion */
+               if (is_short || req->req.actual == req->req.length) {
+                       done (ep, req, 0);
+                       if (list_empty(&ep->queue))
+                               pio_irq_disable (ep->bEndpointAddress);
+                       return 1;
+               }
+
+               /* finished that packet.  the next one may be waiting... */
+       }
+       return 0;
+}
+
+/*
+ * special ep0 version of the above.  no UBCR0 or double buffering; status
+ * handshaking is magic.  most device protocols don't need control-OUT.
+ * CDC vendor commands (and RNDIS), mass storage CB/CBI, and some other
+ * protocols do use them.
+ */
+static int
+read_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
+{
+       u8              *buf, byte;
+       unsigned        bufferspace;
+
+       buf = req->req.buf + req->req.actual;
+       bufferspace = req->req.length - req->req.actual;
+
+       while (UDCCS0 & UDCCS0_RNE) {
+               byte = (u8) UDDR0;
+
+               if (unlikely (bufferspace == 0)) {
+                       /* this happens when the driver's buffer
+                        * is smaller than what the host sent.
+                        * discard the extra data.
+                        */
+                       if (req->req.status != -EOVERFLOW)
+                               DMSG("%s overflow\n", ep->ep.name);
+                       req->req.status = -EOVERFLOW;
+               } else {
+                       *buf++ = byte;
+                       req->req.actual++;
+                       bufferspace--;
+               }
+       }
+
+       UDCCS0 = UDCCS0_OPR | UDCCS0_IPR;
+
+       /* completion */
+       if (req->req.actual >= req->req.length)
+               return 1;
+
+       /* finished that packet.  the next one may be waiting... */
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+       struct pxa25x_request   *req;
+       struct pxa25x_ep        *ep;
+       struct pxa25x_udc       *dev;
+       unsigned long           flags;
+
+       req = container_of(_req, struct pxa25x_request, req);
+       if (unlikely (!_req || !_req->complete || !_req->buf
+                       || !list_empty(&req->queue))) {
+               DMSG("%s, bad params\n", __func__);
+               return -EINVAL;
+       }
+
+       ep = container_of(_ep, struct pxa25x_ep, ep);
+       if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) {
+               DMSG("%s, bad ep\n", __func__);
+               return -EINVAL;
+       }
+
+       dev = ep->dev;
+       if (unlikely (!dev->driver
+                       || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+               DMSG("%s, bogus device state\n", __func__);
+               return -ESHUTDOWN;
+       }
+
+       /* iso is always one packet per request, that's the only way
+        * we can report per-packet status.  that also helps with dma.
+        */
+       if (unlikely (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
+                       && req->req.length > usb_endpoint_maxp(ep->ep.desc)))
+               return -EMSGSIZE;
+
+       DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n",
+               _ep->name, _req, _req->length, _req->buf);
+
+       local_irq_save(flags);
+
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       /* kickstart this i/o queue? */
+       if (list_empty(&ep->queue) && !ep->stopped) {
+               if (ep->ep.desc == NULL/* ep0 */) {
+                       unsigned        length = _req->length;
+
+                       switch (dev->ep0state) {
+                       case EP0_IN_DATA_PHASE:
+                               dev->stats.write.ops++;
+                               if (write_ep0_fifo(ep, req))
+                                       req = NULL;
+                               break;
+
+                       case EP0_OUT_DATA_PHASE:
+                               dev->stats.read.ops++;
+                               /* messy ... */
+                               if (dev->req_config) {
+                                       DBG(DBG_VERBOSE, "ep0 config ack%s\n",
+                                               dev->has_cfr ?  "" : " raced");
+                                       if (dev->has_cfr)
+                                               UDCCFR = UDCCFR_AREN|UDCCFR_ACM
+                                                       |UDCCFR_MB1;
+                                       done(ep, req, 0);
+                                       dev->ep0state = EP0_END_XFER;
+                                       local_irq_restore (flags);
+                                       return 0;
+                               }
+                               if (dev->req_pending)
+                                       ep0start(dev, UDCCS0_IPR, "OUT");
+                               if (length == 0 || ((UDCCS0 & UDCCS0_RNE) != 0
+                                               && read_ep0_fifo(ep, req))) {
+                                       ep0_idle(dev);
+                                       done(ep, req, 0);
+                                       req = NULL;
+                               }
+                               break;
+
+                       default:
+                               DMSG("ep0 i/o, odd state %d\n", dev->ep0state);
+                               local_irq_restore (flags);
+                               return -EL2HLT;
+                       }
+               /* can the FIFO can satisfy the request immediately? */
+               } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
+                       if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0
+                                       && write_fifo(ep, req))
+                               req = NULL;
+               } else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0
+                               && read_fifo(ep, req)) {
+                       req = NULL;
+               }
+
+               if (likely(req && ep->ep.desc))
+                       pio_irq_enable(ep->bEndpointAddress);
+       }
+
+       /* pio or dma irq handler advances the queue. */
+       if (likely(req != NULL))
+               list_add_tail(&req->queue, &ep->queue);
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+
+/*
+ *     nuke - dequeue ALL requests
+ */
+static void nuke(struct pxa25x_ep *ep, int status)
+{
+       struct pxa25x_request *req;
+
+       /* called with irqs blocked */
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next,
+                               struct pxa25x_request,
+                               queue);
+               done(ep, req, status);
+       }
+       if (ep->ep.desc)
+               pio_irq_disable (ep->bEndpointAddress);
+}
+
+
+/* dequeue JUST ONE request */
+static int pxa25x_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct pxa25x_ep        *ep;
+       struct pxa25x_request   *req;
+       unsigned long           flags;
+
+       ep = container_of(_ep, struct pxa25x_ep, ep);
+       if (!_ep || ep->ep.name == ep0name)
+               return -EINVAL;
+
+       local_irq_save(flags);
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry (req, &ep->queue, queue) {
+               if (&req->req == _req)
+                       break;
+       }
+       if (&req->req != _req) {
+               local_irq_restore(flags);
+               return -EINVAL;
+       }
+
+       done(ep, req, -ECONNRESET);
+
+       local_irq_restore(flags);
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value)
+{
+       struct pxa25x_ep        *ep;
+       unsigned long           flags;
+
+       ep = container_of(_ep, struct pxa25x_ep, ep);
+       if (unlikely (!_ep
+                       || (!ep->ep.desc && ep->ep.name != ep0name))
+                       || ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+               DMSG("%s, bad ep\n", __func__);
+               return -EINVAL;
+       }
+       if (value == 0) {
+               /* this path (reset toggle+halt) is needed to implement
+                * SET_INTERFACE on normal hardware.  but it can't be
+                * done from software on the PXA UDC, and the hardware
+                * forgets to do it as part of SET_INTERFACE automagic.
+                */
+               DMSG("only host can clear %s halt\n", _ep->name);
+               return -EROFS;
+       }
+
+       local_irq_save(flags);
+
+       if ((ep->bEndpointAddress & USB_DIR_IN) != 0
+                       && ((*ep->reg_udccs & UDCCS_BI_TFS) == 0
+                          || !list_empty(&ep->queue))) {
+               local_irq_restore(flags);
+               return -EAGAIN;
+       }
+
+       /* FST bit is the same for control, bulk in, bulk out, interrupt in */
+       *ep->reg_udccs = UDCCS_BI_FST|UDCCS_BI_FTF;
+
+       /* ep0 needs special care */
+       if (!ep->ep.desc) {
+               start_watchdog(ep->dev);
+               ep->dev->req_pending = 0;
+               ep->dev->ep0state = EP0_STALL;
+
+       /* and bulk/intr endpoints like dropping stalls too */
+       } else {
+               unsigned i;
+               for (i = 0; i < 1000; i += 20) {
+                       if (*ep->reg_udccs & UDCCS_BI_SST)
+                               break;
+                       udelay(20);
+               }
+       }
+       local_irq_restore(flags);
+
+       DBG(DBG_VERBOSE, "%s halt\n", _ep->name);
+       return 0;
+}
+
+static int pxa25x_ep_fifo_status(struct usb_ep *_ep)
+{
+       struct pxa25x_ep        *ep;
+
+       ep = container_of(_ep, struct pxa25x_ep, ep);
+       if (!_ep) {
+               DMSG("%s, bad ep\n", __func__);
+               return -ENODEV;
+       }
+       /* pxa can't report unclaimed bytes from IN fifos */
+       if ((ep->bEndpointAddress & USB_DIR_IN) != 0)
+               return -EOPNOTSUPP;
+       if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN
+                       || (*ep->reg_udccs & UDCCS_BO_RFS) == 0)
+               return 0;
+       else
+               return (*ep->reg_ubcr & 0xfff) + 1;
+}
+
+static void pxa25x_ep_fifo_flush(struct usb_ep *_ep)
+{
+       struct pxa25x_ep        *ep;
+
+       ep = container_of(_ep, struct pxa25x_ep, ep);
+       if (!_ep || ep->ep.name == ep0name || !list_empty(&ep->queue)) {
+               DMSG("%s, bad ep\n", __func__);
+               return;
+       }
+
+       /* toggle and halt bits stay unchanged */
+
+       /* for OUT, just read and discard the FIFO contents. */
+       if ((ep->bEndpointAddress & USB_DIR_IN) == 0) {
+               while (((*ep->reg_udccs) & UDCCS_BO_RNE) != 0)
+                       (void) *ep->reg_uddr;
+               return;
+       }
+
+       /* most IN status is the same, but ISO can't stall */
+       *ep->reg_udccs = UDCCS_BI_TPC|UDCCS_BI_FTF|UDCCS_BI_TUR
+               | (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
+                       ? 0 : UDCCS_BI_SST);
+}
+
+
+static struct usb_ep_ops pxa25x_ep_ops = {
+       .enable         = pxa25x_ep_enable,
+       .disable        = pxa25x_ep_disable,
+
+       .alloc_request  = pxa25x_ep_alloc_request,
+       .free_request   = pxa25x_ep_free_request,
+
+       .queue          = pxa25x_ep_queue,
+       .dequeue        = pxa25x_ep_dequeue,
+
+       .set_halt       = pxa25x_ep_set_halt,
+       .fifo_status    = pxa25x_ep_fifo_status,
+       .fifo_flush     = pxa25x_ep_fifo_flush,
+};
+
+
+/* ---------------------------------------------------------------------------
+ *     device-scoped parts of the api to the usb controller hardware
+ * ---------------------------------------------------------------------------
+ */
+
+static int pxa25x_udc_get_frame(struct usb_gadget *_gadget)
+{
+       return ((UFNRH & 0x07) << 8) | (UFNRL & 0xff);
+}
+
+static int pxa25x_udc_wakeup(struct usb_gadget *_gadget)
+{
+       /* host may not have enabled remote wakeup */
+       if ((UDCCS0 & UDCCS0_DRWF) == 0)
+               return -EHOSTUNREACH;
+       udc_set_mask_UDCCR(UDCCR_RSM);
+       return 0;
+}
+
+static void stop_activity(struct pxa25x_udc *, struct usb_gadget_driver *);
+static void udc_enable (struct pxa25x_udc *);
+static void udc_disable(struct pxa25x_udc *);
+
+/* We disable the UDC -- and its 48 MHz clock -- whenever it's not
+ * in active use.
+ */
+static int pullup(struct pxa25x_udc *udc)
+{
+       int is_active = udc->vbus && udc->pullup && !udc->suspended;
+       DMSG("%s\n", is_active ? "active" : "inactive");
+       if (is_active) {
+               if (!udc->active) {
+                       udc->active = 1;
+                       /* Enable clock for USB device */
+                       clk_enable(udc->clk);
+                       udc_enable(udc);
+               }
+       } else {
+               if (udc->active) {
+                       if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+                               DMSG("disconnect %s\n", udc->driver
+                                       ? udc->driver->driver.name
+                                       : "(no driver)");
+                               stop_activity(udc, udc->driver);
+                       }
+                       udc_disable(udc);
+                       /* Disable clock for USB device */
+                       clk_disable(udc->clk);
+                       udc->active = 0;
+               }
+
+       }
+       return 0;
+}
+
+/* VBUS reporting logically comes from a transceiver */
+static int pxa25x_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
+{
+       struct pxa25x_udc       *udc;
+
+       udc = container_of(_gadget, struct pxa25x_udc, gadget);
+       udc->vbus = is_active;
+       DMSG("vbus %s\n", is_active ? "supplied" : "inactive");
+       pullup(udc);
+       return 0;
+}
+
+/* drivers may have software control over D+ pullup */
+static int pxa25x_udc_pullup(struct usb_gadget *_gadget, int is_active)
+{
+       struct pxa25x_udc       *udc;
+
+       udc = container_of(_gadget, struct pxa25x_udc, gadget);
+
+       /* not all boards support pullup control */
+       if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
+               return -EOPNOTSUPP;
+
+       udc->pullup = (is_active != 0);
+       pullup(udc);
+       return 0;
+}
+
+/* boards may consume current from VBUS, up to 100-500mA based on config.
+ * the 500uA suspend ceiling means that exclusively vbus-powered PXA designs
+ * violate USB specs.
+ */
+static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
+{
+       struct pxa25x_udc       *udc;
+
+       udc = container_of(_gadget, struct pxa25x_udc, gadget);
+
+       if (!IS_ERR_OR_NULL(udc->transceiver))
+               return usb_phy_set_power(udc->transceiver, mA);
+       return -EOPNOTSUPP;
+}
+
+static int pxa25x_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+static int pxa25x_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+
+static const struct usb_gadget_ops pxa25x_udc_ops = {
+       .get_frame      = pxa25x_udc_get_frame,
+       .wakeup         = pxa25x_udc_wakeup,
+       .vbus_session   = pxa25x_udc_vbus_session,
+       .pullup         = pxa25x_udc_pullup,
+       .vbus_draw      = pxa25x_udc_vbus_draw,
+       .udc_start      = pxa25x_udc_start,
+       .udc_stop       = pxa25x_udc_stop,
+};
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+
+static int
+udc_seq_show(struct seq_file *m, void *_d)
+{
+       struct pxa25x_udc       *dev = m->private;
+       unsigned long           flags;
+       int                     i;
+       u32                     tmp;
+
+       local_irq_save(flags);
+
+       /* basic device status */
+       seq_printf(m, DRIVER_DESC "\n"
+               "%s version: %s\nGadget driver: %s\nHost %s\n\n",
+               driver_name, DRIVER_VERSION SIZE_STR "(pio)",
+               dev->driver ? dev->driver->driver.name : "(none)",
+               dev->gadget.speed == USB_SPEED_FULL ? "full speed" : "disconnected");
+
+       /* registers for device and ep0 */
+       seq_printf(m,
+               "uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
+               UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
+
+       tmp = UDCCR;
+       seq_printf(m,
+               "udccr %02X =%s%s%s%s%s%s%s%s\n", tmp,
+               (tmp & UDCCR_REM) ? " rem" : "",
+               (tmp & UDCCR_RSTIR) ? " rstir" : "",
+               (tmp & UDCCR_SRM) ? " srm" : "",
+               (tmp & UDCCR_SUSIR) ? " susir" : "",
+               (tmp & UDCCR_RESIR) ? " resir" : "",
+               (tmp & UDCCR_RSM) ? " rsm" : "",
+               (tmp & UDCCR_UDA) ? " uda" : "",
+               (tmp & UDCCR_UDE) ? " ude" : "");
+
+       tmp = UDCCS0;
+       seq_printf(m,
+               "udccs0 %02X =%s%s%s%s%s%s%s%s\n", tmp,
+               (tmp & UDCCS0_SA) ? " sa" : "",
+               (tmp & UDCCS0_RNE) ? " rne" : "",
+               (tmp & UDCCS0_FST) ? " fst" : "",
+               (tmp & UDCCS0_SST) ? " sst" : "",
+               (tmp & UDCCS0_DRWF) ? " dwrf" : "",
+               (tmp & UDCCS0_FTF) ? " ftf" : "",
+               (tmp & UDCCS0_IPR) ? " ipr" : "",
+               (tmp & UDCCS0_OPR) ? " opr" : "");
+
+       if (dev->has_cfr) {
+               tmp = UDCCFR;
+               seq_printf(m,
+                       "udccfr %02X =%s%s\n", tmp,
+                       (tmp & UDCCFR_AREN) ? " aren" : "",
+                       (tmp & UDCCFR_ACM) ? " acm" : "");
+       }
+
+       if (dev->gadget.speed != USB_SPEED_FULL || !dev->driver)
+               goto done;
+
+       seq_printf(m, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
+               dev->stats.write.bytes, dev->stats.write.ops,
+               dev->stats.read.bytes, dev->stats.read.ops,
+               dev->stats.irqs);
+
+       /* dump endpoint queues */
+       for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
+               struct pxa25x_ep        *ep = &dev->ep [i];
+               struct pxa25x_request   *req;
+
+               if (i != 0) {
+                       const struct usb_endpoint_descriptor    *desc;
+
+                       desc = ep->ep.desc;
+                       if (!desc)
+                               continue;
+                       tmp = *dev->ep [i].reg_udccs;
+                       seq_printf(m,
+                               "%s max %d %s udccs %02x irqs %lu\n",
+                               ep->ep.name, usb_endpoint_maxp(desc),
+                               "pio", tmp, ep->pio_irqs);
+                       /* TODO translate all five groups of udccs bits! */
+
+               } else /* ep0 should only have one transfer queued */
+                       seq_printf(m, "ep0 max 16 pio irqs %lu\n",
+                               ep->pio_irqs);
+
+               if (list_empty(&ep->queue)) {
+                       seq_printf(m, "\t(nothing queued)\n");
+                       continue;
+               }
+               list_for_each_entry(req, &ep->queue, queue) {
+                       seq_printf(m,
+                                       "\treq %p len %d/%d buf %p\n",
+                                       &req->req, req->req.actual,
+                                       req->req.length, req->req.buf);
+               }
+       }
+
+done:
+       local_irq_restore(flags);
+       return 0;
+}
+
+static int
+udc_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, udc_seq_show, inode->i_private);
+}
+
+static const struct file_operations debug_fops = {
+       .open           = udc_debugfs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .owner          = THIS_MODULE,
+};
+
+#define create_debug_files(dev) \
+       do { \
+               dev->debugfs_udc = debugfs_create_file(dev->gadget.name, \
+                       S_IRUGO, NULL, dev, &debug_fops); \
+       } while (0)
+#define remove_debug_files(dev) \
+       do { \
+               if (dev->debugfs_udc) \
+                       debugfs_remove(dev->debugfs_udc); \
+       } while (0)
+
+#else  /* !CONFIG_USB_GADGET_DEBUG_FILES */
+
+#define create_debug_files(dev) do {} while (0)
+#define remove_debug_files(dev) do {} while (0)
+
+#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ *     udc_disable - disable USB device controller
+ */
+static void udc_disable(struct pxa25x_udc *dev)
+{
+       /* block all irqs */
+       udc_set_mask_UDCCR(UDCCR_SRM|UDCCR_REM);
+       UICR0 = UICR1 = 0xff;
+       UFNRH = UFNRH_SIM;
+
+       /* if hardware supports it, disconnect from usb */
+       pullup_off();
+
+       udc_clear_mask_UDCCR(UDCCR_UDE);
+
+       ep0_idle (dev);
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+}
+
+
+/*
+ *     udc_reinit - initialize software state
+ */
+static void udc_reinit(struct pxa25x_udc *dev)
+{
+       u32     i;
+
+       /* device/ep0 records init */
+       INIT_LIST_HEAD (&dev->gadget.ep_list);
+       INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
+       dev->ep0state = EP0_IDLE;
+
+       /* basic endpoint records init */
+       for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
+               struct pxa25x_ep *ep = &dev->ep[i];
+
+               if (i != 0)
+                       list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
+
+               ep->ep.desc = NULL;
+               ep->stopped = 0;
+               INIT_LIST_HEAD (&ep->queue);
+               ep->pio_irqs = 0;
+               usb_ep_set_maxpacket_limit(&ep->ep, ep->ep.maxpacket);
+       }
+
+       /* the rest was statically initialized, and is read-only */
+}
+
+/* until it's enabled, this UDC should be completely invisible
+ * to any USB host.
+ */
+static void udc_enable (struct pxa25x_udc *dev)
+{
+       udc_clear_mask_UDCCR(UDCCR_UDE);
+
+       /* try to clear these bits before we enable the udc */
+       udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR);
+
+       ep0_idle(dev);
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+       dev->stats.irqs = 0;
+
+       /*
+        * sequence taken from chapter 12.5.10, PXA250 AppProcDevManual:
+        * - enable UDC
+        * - if RESET is already in progress, ack interrupt
+        * - unmask reset interrupt
+        */
+       udc_set_mask_UDCCR(UDCCR_UDE);
+       if (!(UDCCR & UDCCR_UDA))
+               udc_ack_int_UDCCR(UDCCR_RSTIR);
+
+       if (dev->has_cfr /* UDC_RES2 is defined */) {
+               /* pxa255 (a0+) can avoid a set_config race that could
+                * prevent gadget drivers from configuring correctly
+                */
+               UDCCFR = UDCCFR_ACM | UDCCFR_MB1;
+       } else {
+               /* "USB test mode" for pxa250 errata 40-42 (stepping a0, a1)
+                * which could result in missing packets and interrupts.
+                * supposedly one bit per endpoint, controlling whether it
+                * double buffers or not; ACM/AREN bits fit into the holes.
+                * zero bits (like USIR0_IRx) disable double buffering.
+                */
+               UDC_RES1 = 0x00;
+               UDC_RES2 = 0x00;
+       }
+
+       /* enable suspend/resume and reset irqs */
+       udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
+
+       /* enable ep0 irqs */
+       UICR0 &= ~UICR0_IM0;
+
+       /* if hardware supports it, pullup D+ and wait for reset */
+       pullup_on();
+}
+
+
+/* when a driver is successfully registered, it will receive
+ * control requests including set_configuration(), which enables
+ * non-control requests.  then usb traffic follows until a
+ * disconnect is reported.  then a host may connect again, or
+ * the driver might get unbound.
+ */
+static int pxa25x_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct pxa25x_udc       *dev = to_pxa25x(g);
+       int                     retval;
+
+       /* first hook up the driver ... */
+       dev->driver = driver;
+       dev->pullup = 1;
+
+       /* ... then enable host detection and ep0; and we're ready
+        * for set_configuration as well as eventual disconnect.
+        */
+       /* connect to bus through transceiver */
+       if (!IS_ERR_OR_NULL(dev->transceiver)) {
+               retval = otg_set_peripheral(dev->transceiver->otg,
+                                               &dev->gadget);
+               if (retval)
+                       goto bind_fail;
+       }
+
+       pullup(dev);
+       dump_state(dev);
+       return 0;
+bind_fail:
+       return retval;
+}
+
+static void
+stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
+{
+       int i;
+
+       /* don't disconnect drivers more than once */
+       if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+               driver = NULL;
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+       /* prevent new request submissions, kill any outstanding requests  */
+       for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
+               struct pxa25x_ep *ep = &dev->ep[i];
+
+               ep->stopped = 1;
+               nuke(ep, -ESHUTDOWN);
+       }
+       del_timer_sync(&dev->timer);
+
+       /* report disconnect; the driver is already quiesced */
+       if (driver)
+               driver->disconnect(&dev->gadget);
+
+       /* re-init driver-visible data structures */
+       udc_reinit(dev);
+}
+
+static int pxa25x_udc_stop(struct usb_gadget*g,
+               struct usb_gadget_driver *driver)
+{
+       struct pxa25x_udc       *dev = to_pxa25x(g);
+
+       local_irq_disable();
+       dev->pullup = 0;
+       pullup(dev);
+       stop_activity(dev, driver);
+       local_irq_enable();
+
+       if (!IS_ERR_OR_NULL(dev->transceiver))
+               (void) otg_set_peripheral(dev->transceiver->otg, NULL);
+
+       dev->driver = NULL;
+
+       dump_state(dev);
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_ARCH_LUBBOCK
+
+/* Lubbock has separate connect and disconnect irqs.  More typical designs
+ * use one GPIO as the VBUS IRQ, and another to control the D+ pullup.
+ */
+
+static irqreturn_t
+lubbock_vbus_irq(int irq, void *_dev)
+{
+       struct pxa25x_udc       *dev = _dev;
+       int                     vbus;
+
+       dev->stats.irqs++;
+       switch (irq) {
+       case LUBBOCK_USB_IRQ:
+               vbus = 1;
+               disable_irq(LUBBOCK_USB_IRQ);
+               enable_irq(LUBBOCK_USB_DISC_IRQ);
+               break;
+       case LUBBOCK_USB_DISC_IRQ:
+               vbus = 0;
+               disable_irq(LUBBOCK_USB_DISC_IRQ);
+               enable_irq(LUBBOCK_USB_IRQ);
+               break;
+       default:
+               return IRQ_NONE;
+       }
+
+       pxa25x_udc_vbus_session(&dev->gadget, vbus);
+       return IRQ_HANDLED;
+}
+
+#endif
+
+
+/*-------------------------------------------------------------------------*/
+
+static inline void clear_ep_state (struct pxa25x_udc *dev)
+{
+       unsigned i;
+
+       /* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
+        * fifos, and pending transactions mustn't be continued in any case.
+        */
+       for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++)
+               nuke(&dev->ep[i], -ECONNABORTED);
+}
+
+static void udc_watchdog(unsigned long _dev)
+{
+       struct pxa25x_udc       *dev = (void *)_dev;
+
+       local_irq_disable();
+       if (dev->ep0state == EP0_STALL
+                       && (UDCCS0 & UDCCS0_FST) == 0
+                       && (UDCCS0 & UDCCS0_SST) == 0) {
+               UDCCS0 = UDCCS0_FST|UDCCS0_FTF;
+               DBG(DBG_VERBOSE, "ep0 re-stall\n");
+               start_watchdog(dev);
+       }
+       local_irq_enable();
+}
+
+static void handle_ep0 (struct pxa25x_udc *dev)
+{
+       u32                     udccs0 = UDCCS0;
+       struct pxa25x_ep        *ep = &dev->ep [0];
+       struct pxa25x_request   *req;
+       union {
+               struct usb_ctrlrequest  r;
+               u8                      raw [8];
+               u32                     word [2];
+       } u;
+
+       if (list_empty(&ep->queue))
+               req = NULL;
+       else
+               req = list_entry(ep->queue.next, struct pxa25x_request, queue);
+
+       /* clear stall status */
+       if (udccs0 & UDCCS0_SST) {
+               nuke(ep, -EPIPE);
+               UDCCS0 = UDCCS0_SST;
+               del_timer(&dev->timer);
+               ep0_idle(dev);
+       }
+
+       /* previous request unfinished?  non-error iff back-to-back ... */
+       if ((udccs0 & UDCCS0_SA) != 0 && dev->ep0state != EP0_IDLE) {
+               nuke(ep, 0);
+               del_timer(&dev->timer);
+               ep0_idle(dev);
+       }
+
+       switch (dev->ep0state) {
+       case EP0_IDLE:
+               /* late-breaking status? */
+               udccs0 = UDCCS0;
+
+               /* start control request? */
+               if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE))
+                               == (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE))) {
+                       int i;
+
+                       nuke (ep, -EPROTO);
+
+                       /* read SETUP packet */
+                       for (i = 0; i < 8; i++) {
+                               if (unlikely(!(UDCCS0 & UDCCS0_RNE))) {
+bad_setup:
+                                       DMSG("SETUP %d!\n", i);
+                                       goto stall;
+                               }
+                               u.raw [i] = (u8) UDDR0;
+                       }
+                       if (unlikely((UDCCS0 & UDCCS0_RNE) != 0))
+                               goto bad_setup;
+
+got_setup:
+                       DBG(DBG_VERBOSE, "SETUP %02x.%02x v%04x i%04x l%04x\n",
+                               u.r.bRequestType, u.r.bRequest,
+                               le16_to_cpu(u.r.wValue),
+                               le16_to_cpu(u.r.wIndex),
+                               le16_to_cpu(u.r.wLength));
+
+                       /* cope with automagic for some standard requests. */
+                       dev->req_std = (u.r.bRequestType & USB_TYPE_MASK)
+                                               == USB_TYPE_STANDARD;
+                       dev->req_config = 0;
+                       dev->req_pending = 1;
+                       switch (u.r.bRequest) {
+                       /* hardware restricts gadget drivers here! */
+                       case USB_REQ_SET_CONFIGURATION:
+                               if (u.r.bRequestType == USB_RECIP_DEVICE) {
+                                       /* reflect hardware's automagic
+                                        * up to the gadget driver.
+                                        */
+config_change:
+                                       dev->req_config = 1;
+                                       clear_ep_state(dev);
+                                       /* if !has_cfr, there's no synch
+                                        * else use AREN (later) not SA|OPR
+                                        * USIR0_IR0 acts edge sensitive
+                                        */
+                               }
+                               break;
+                       /* ... and here, even more ... */
+                       case USB_REQ_SET_INTERFACE:
+                               if (u.r.bRequestType == USB_RECIP_INTERFACE) {
+                                       /* udc hardware is broken by design:
+                                        *  - altsetting may only be zero;
+                                        *  - hw resets all interfaces' eps;
+                                        *  - ep reset doesn't include halt(?).
+                                        */
+                                       DMSG("broken set_interface (%d/%d)\n",
+                                               le16_to_cpu(u.r.wIndex),
+                                               le16_to_cpu(u.r.wValue));
+                                       goto config_change;
+                               }
+                               break;
+                       /* hardware was supposed to hide this */
+                       case USB_REQ_SET_ADDRESS:
+                               if (u.r.bRequestType == USB_RECIP_DEVICE) {
+                                       ep0start(dev, 0, "address");
+                                       return;
+                               }
+                               break;
+                       }
+
+                       if (u.r.bRequestType & USB_DIR_IN)
+                               dev->ep0state = EP0_IN_DATA_PHASE;
+                       else
+                               dev->ep0state = EP0_OUT_DATA_PHASE;
+
+                       i = dev->driver->setup(&dev->gadget, &u.r);
+                       if (i < 0) {
+                               /* hardware automagic preventing STALL... */
+                               if (dev->req_config) {
+                                       /* hardware sometimes neglects to tell
+                                        * tell us about config change events,
+                                        * so later ones may fail...
+                                        */
+                                       WARNING("config change %02x fail %d?\n",
+                                               u.r.bRequest, i);
+                                       return;
+                                       /* TODO experiment:  if has_cfr,
+                                        * hardware didn't ACK; maybe we
+                                        * could actually STALL!
+                                        */
+                               }
+                               DBG(DBG_VERBOSE, "protocol STALL, "
+                                       "%02x err %d\n", UDCCS0, i);
+stall:
+                               /* the watchdog timer helps deal with cases
+                                * where udc seems to clear FST wrongly, and
+                                * then NAKs instead of STALLing.
+                                */
+                               ep0start(dev, UDCCS0_FST|UDCCS0_FTF, "stall");
+                               start_watchdog(dev);
+                               dev->ep0state = EP0_STALL;
+
+                       /* deferred i/o == no response yet */
+                       } else if (dev->req_pending) {
+                               if (likely(dev->ep0state == EP0_IN_DATA_PHASE
+                                               || dev->req_std || u.r.wLength))
+                                       ep0start(dev, 0, "defer");
+                               else
+                                       ep0start(dev, UDCCS0_IPR, "defer/IPR");
+                       }
+
+                       /* expect at least one data or status stage irq */
+                       return;
+
+               } else if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA))
+                               == (UDCCS0_OPR|UDCCS0_SA))) {
+                       unsigned i;
+
+                       /* pxa210/250 erratum 131 for B0/B1 says RNE lies.
+                        * still observed on a pxa255 a0.
+                        */
+                       DBG(DBG_VERBOSE, "e131\n");
+                       nuke(ep, -EPROTO);
+
+                       /* read SETUP data, but don't trust it too much */
+                       for (i = 0; i < 8; i++)
+                               u.raw [i] = (u8) UDDR0;
+                       if ((u.r.bRequestType & USB_RECIP_MASK)
+                                       > USB_RECIP_OTHER)
+                               goto stall;
+                       if (u.word [0] == 0 && u.word [1] == 0)
+                               goto stall;
+                       goto got_setup;
+               } else {
+                       /* some random early IRQ:
+                        * - we acked FST
+                        * - IPR cleared
+                        * - OPR got set, without SA (likely status stage)
+                        */
+                       UDCCS0 = udccs0 & (UDCCS0_SA|UDCCS0_OPR);
+               }
+               break;
+       case EP0_IN_DATA_PHASE:                 /* GET_DESCRIPTOR etc */
+               if (udccs0 & UDCCS0_OPR) {
+                       UDCCS0 = UDCCS0_OPR|UDCCS0_FTF;
+                       DBG(DBG_VERBOSE, "ep0in premature status\n");
+                       if (req)
+                               done(ep, req, 0);
+                       ep0_idle(dev);
+               } else /* irq was IPR clearing */ {
+                       if (req) {
+                               /* this IN packet might finish the request */
+                               (void) write_ep0_fifo(ep, req);
+                       } /* else IN token before response was written */
+               }
+               break;
+       case EP0_OUT_DATA_PHASE:                /* SET_DESCRIPTOR etc */
+               if (udccs0 & UDCCS0_OPR) {
+                       if (req) {
+                               /* this OUT packet might finish the request */
+                               if (read_ep0_fifo(ep, req))
+                                       done(ep, req, 0);
+                               /* else more OUT packets expected */
+                       } /* else OUT token before read was issued */
+               } else /* irq was IPR clearing */ {
+                       DBG(DBG_VERBOSE, "ep0out premature status\n");
+                       if (req)
+                               done(ep, req, 0);
+                       ep0_idle(dev);
+               }
+               break;
+       case EP0_END_XFER:
+               if (req)
+                       done(ep, req, 0);
+               /* ack control-IN status (maybe in-zlp was skipped)
+                * also appears after some config change events.
+                */
+               if (udccs0 & UDCCS0_OPR)
+                       UDCCS0 = UDCCS0_OPR;
+               ep0_idle(dev);
+               break;
+       case EP0_STALL:
+               UDCCS0 = UDCCS0_FST;
+               break;
+       }
+       USIR0 = USIR0_IR0;
+}
+
+static void handle_ep(struct pxa25x_ep *ep)
+{
+       struct pxa25x_request   *req;
+       int                     is_in = ep->bEndpointAddress & USB_DIR_IN;
+       int                     completed;
+       u32                     udccs, tmp;
+
+       do {
+               completed = 0;
+               if (likely (!list_empty(&ep->queue)))
+                       req = list_entry(ep->queue.next,
+                                       struct pxa25x_request, queue);
+               else
+                       req = NULL;
+
+               // TODO check FST handling
+
+               udccs = *ep->reg_udccs;
+               if (unlikely(is_in)) {  /* irq from TPC, SST, or (ISO) TUR */
+                       tmp = UDCCS_BI_TUR;
+                       if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK))
+                               tmp |= UDCCS_BI_SST;
+                       tmp &= udccs;
+                       if (likely (tmp))
+                               *ep->reg_udccs = tmp;
+                       if (req && likely ((udccs & UDCCS_BI_TFS) != 0))
+                               completed = write_fifo(ep, req);
+
+               } else {        /* irq from RPC (or for ISO, ROF) */
+                       if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK))
+                               tmp = UDCCS_BO_SST | UDCCS_BO_DME;
+                       else
+                               tmp = UDCCS_IO_ROF | UDCCS_IO_DME;
+                       tmp &= udccs;
+                       if (likely(tmp))
+                               *ep->reg_udccs = tmp;
+
+                       /* fifos can hold packets, ready for reading... */
+                       if (likely(req)) {
+                               completed = read_fifo(ep, req);
+                       } else
+                               pio_irq_disable (ep->bEndpointAddress);
+               }
+               ep->pio_irqs++;
+       } while (completed);
+}
+
+/*
+ *     pxa25x_udc_irq - interrupt handler
+ *
+ * avoid delays in ep0 processing. the control handshaking isn't always
+ * under software control (pxa250c0 and the pxa255 are better), and delays
+ * could cause usb protocol errors.
+ */
+static irqreturn_t
+pxa25x_udc_irq(int irq, void *_dev)
+{
+       struct pxa25x_udc       *dev = _dev;
+       int                     handled;
+
+       dev->stats.irqs++;
+       do {
+               u32             udccr = UDCCR;
+
+               handled = 0;
+
+               /* SUSpend Interrupt Request */
+               if (unlikely(udccr & UDCCR_SUSIR)) {
+                       udc_ack_int_UDCCR(UDCCR_SUSIR);
+                       handled = 1;
+                       DBG(DBG_VERBOSE, "USB suspend\n");
+
+                       if (dev->gadget.speed != USB_SPEED_UNKNOWN
+                                       && dev->driver
+                                       && dev->driver->suspend)
+                               dev->driver->suspend(&dev->gadget);
+                       ep0_idle (dev);
+               }
+
+               /* RESume Interrupt Request */
+               if (unlikely(udccr & UDCCR_RESIR)) {
+                       udc_ack_int_UDCCR(UDCCR_RESIR);
+                       handled = 1;
+                       DBG(DBG_VERBOSE, "USB resume\n");
+
+                       if (dev->gadget.speed != USB_SPEED_UNKNOWN
+                                       && dev->driver
+                                       && dev->driver->resume)
+                               dev->driver->resume(&dev->gadget);
+               }
+
+               /* ReSeT Interrupt Request - USB reset */
+               if (unlikely(udccr & UDCCR_RSTIR)) {
+                       udc_ack_int_UDCCR(UDCCR_RSTIR);
+                       handled = 1;
+
+                       if ((UDCCR & UDCCR_UDA) == 0) {
+                               DBG(DBG_VERBOSE, "USB reset start\n");
+
+                               /* reset driver and endpoints,
+                                * in case that's not yet done
+                                */
+                               stop_activity (dev, dev->driver);
+
+                       } else {
+                               DBG(DBG_VERBOSE, "USB reset end\n");
+                               dev->gadget.speed = USB_SPEED_FULL;
+                               memset(&dev->stats, 0, sizeof dev->stats);
+                               /* driver and endpoints are still reset */
+                       }
+
+               } else {
+                       u32     usir0 = USIR0 & ~UICR0;
+                       u32     usir1 = USIR1 & ~UICR1;
+                       int     i;
+
+                       if (unlikely (!usir0 && !usir1))
+                               continue;
+
+                       DBG(DBG_VERY_NOISY, "irq %02x.%02x\n", usir1, usir0);
+
+                       /* control traffic */
+                       if (usir0 & USIR0_IR0) {
+                               dev->ep[0].pio_irqs++;
+                               handle_ep0(dev);
+                               handled = 1;
+                       }
+
+                       /* endpoint data transfers */
+                       for (i = 0; i < 8; i++) {
+                               u32     tmp = 1 << i;
+
+                               if (i && (usir0 & tmp)) {
+                                       handle_ep(&dev->ep[i]);
+                                       USIR0 |= tmp;
+                                       handled = 1;
+                               }
+#ifndef        CONFIG_USB_PXA25X_SMALL
+                               if (usir1 & tmp) {
+                                       handle_ep(&dev->ep[i+8]);
+                                       USIR1 |= tmp;
+                                       handled = 1;
+                               }
+#endif
+                       }
+               }
+
+               /* we could also ask for 1 msec SOF (SIR) interrupts */
+
+       } while (handled);
+       return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void nop_release (struct device *dev)
+{
+       DMSG("%s %s\n", __func__, dev_name(dev));
+}
+
+/* this uses load-time allocation and initialization (instead of
+ * doing it at run-time) to save code, eliminate fault paths, and
+ * be more obviously correct.
+ */
+static struct pxa25x_udc memory = {
+       .gadget = {
+               .ops            = &pxa25x_udc_ops,
+               .ep0            = &memory.ep[0].ep,
+               .name           = driver_name,
+               .dev = {
+                       .init_name      = "gadget",
+                       .release        = nop_release,
+               },
+       },
+
+       /* control endpoint */
+       .ep[0] = {
+               .ep = {
+                       .name           = ep0name,
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = EP0_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .reg_udccs      = &UDCCS0,
+               .reg_uddr       = &UDDR0,
+       },
+
+       /* first group of endpoints */
+       .ep[1] = {
+               .ep = {
+                       .name           = "ep1in-bulk",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = BULK_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = BULK_FIFO_SIZE,
+               .bEndpointAddress = USB_DIR_IN | 1,
+               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
+               .reg_udccs      = &UDCCS1,
+               .reg_uddr       = &UDDR1,
+       },
+       .ep[2] = {
+               .ep = {
+                       .name           = "ep2out-bulk",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = BULK_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = BULK_FIFO_SIZE,
+               .bEndpointAddress = 2,
+               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
+               .reg_udccs      = &UDCCS2,
+               .reg_ubcr       = &UBCR2,
+               .reg_uddr       = &UDDR2,
+       },
+#ifndef CONFIG_USB_PXA25X_SMALL
+       .ep[3] = {
+               .ep = {
+                       .name           = "ep3in-iso",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = ISO_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = ISO_FIFO_SIZE,
+               .bEndpointAddress = USB_DIR_IN | 3,
+               .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
+               .reg_udccs      = &UDCCS3,
+               .reg_uddr       = &UDDR3,
+       },
+       .ep[4] = {
+               .ep = {
+                       .name           = "ep4out-iso",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = ISO_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = ISO_FIFO_SIZE,
+               .bEndpointAddress = 4,
+               .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
+               .reg_udccs      = &UDCCS4,
+               .reg_ubcr       = &UBCR4,
+               .reg_uddr       = &UDDR4,
+       },
+       .ep[5] = {
+               .ep = {
+                       .name           = "ep5in-int",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = INT_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = INT_FIFO_SIZE,
+               .bEndpointAddress = USB_DIR_IN | 5,
+               .bmAttributes   = USB_ENDPOINT_XFER_INT,
+               .reg_udccs      = &UDCCS5,
+               .reg_uddr       = &UDDR5,
+       },
+
+       /* second group of endpoints */
+       .ep[6] = {
+               .ep = {
+                       .name           = "ep6in-bulk",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = BULK_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = BULK_FIFO_SIZE,
+               .bEndpointAddress = USB_DIR_IN | 6,
+               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
+               .reg_udccs      = &UDCCS6,
+               .reg_uddr       = &UDDR6,
+       },
+       .ep[7] = {
+               .ep = {
+                       .name           = "ep7out-bulk",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = BULK_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = BULK_FIFO_SIZE,
+               .bEndpointAddress = 7,
+               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
+               .reg_udccs      = &UDCCS7,
+               .reg_ubcr       = &UBCR7,
+               .reg_uddr       = &UDDR7,
+       },
+       .ep[8] = {
+               .ep = {
+                       .name           = "ep8in-iso",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = ISO_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = ISO_FIFO_SIZE,
+               .bEndpointAddress = USB_DIR_IN | 8,
+               .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
+               .reg_udccs      = &UDCCS8,
+               .reg_uddr       = &UDDR8,
+       },
+       .ep[9] = {
+               .ep = {
+                       .name           = "ep9out-iso",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = ISO_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = ISO_FIFO_SIZE,
+               .bEndpointAddress = 9,
+               .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
+               .reg_udccs      = &UDCCS9,
+               .reg_ubcr       = &UBCR9,
+               .reg_uddr       = &UDDR9,
+       },
+       .ep[10] = {
+               .ep = {
+                       .name           = "ep10in-int",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = INT_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = INT_FIFO_SIZE,
+               .bEndpointAddress = USB_DIR_IN | 10,
+               .bmAttributes   = USB_ENDPOINT_XFER_INT,
+               .reg_udccs      = &UDCCS10,
+               .reg_uddr       = &UDDR10,
+       },
+
+       /* third group of endpoints */
+       .ep[11] = {
+               .ep = {
+                       .name           = "ep11in-bulk",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = BULK_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = BULK_FIFO_SIZE,
+               .bEndpointAddress = USB_DIR_IN | 11,
+               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
+               .reg_udccs      = &UDCCS11,
+               .reg_uddr       = &UDDR11,
+       },
+       .ep[12] = {
+               .ep = {
+                       .name           = "ep12out-bulk",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = BULK_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = BULK_FIFO_SIZE,
+               .bEndpointAddress = 12,
+               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
+               .reg_udccs      = &UDCCS12,
+               .reg_ubcr       = &UBCR12,
+               .reg_uddr       = &UDDR12,
+       },
+       .ep[13] = {
+               .ep = {
+                       .name           = "ep13in-iso",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = ISO_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = ISO_FIFO_SIZE,
+               .bEndpointAddress = USB_DIR_IN | 13,
+               .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
+               .reg_udccs      = &UDCCS13,
+               .reg_uddr       = &UDDR13,
+       },
+       .ep[14] = {
+               .ep = {
+                       .name           = "ep14out-iso",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = ISO_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = ISO_FIFO_SIZE,
+               .bEndpointAddress = 14,
+               .bmAttributes   = USB_ENDPOINT_XFER_ISOC,
+               .reg_udccs      = &UDCCS14,
+               .reg_ubcr       = &UBCR14,
+               .reg_uddr       = &UDDR14,
+       },
+       .ep[15] = {
+               .ep = {
+                       .name           = "ep15in-int",
+                       .ops            = &pxa25x_ep_ops,
+                       .maxpacket      = INT_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = INT_FIFO_SIZE,
+               .bEndpointAddress = USB_DIR_IN | 15,
+               .bmAttributes   = USB_ENDPOINT_XFER_INT,
+               .reg_udccs      = &UDCCS15,
+               .reg_uddr       = &UDDR15,
+       },
+#endif /* !CONFIG_USB_PXA25X_SMALL */
+};
+
+#define CP15R0_VENDOR_MASK     0xffffe000
+
+#if    defined(CONFIG_ARCH_PXA)
+#define CP15R0_XSCALE_VALUE    0x69052000      /* intel/arm/xscale */
+
+#elif  defined(CONFIG_ARCH_IXP4XX)
+#define CP15R0_XSCALE_VALUE    0x69054000      /* intel/arm/ixp4xx */
+
+#endif
+
+#define CP15R0_PROD_MASK       0x000003f0
+#define PXA25x                 0x00000100      /* and PXA26x */
+#define PXA210                 0x00000120
+
+#define CP15R0_REV_MASK                0x0000000f
+
+#define CP15R0_PRODREV_MASK    (CP15R0_PROD_MASK | CP15R0_REV_MASK)
+
+#define PXA255_A0              0x00000106      /* or PXA260_B1 */
+#define PXA250_C0              0x00000105      /* or PXA26x_B0 */
+#define PXA250_B2              0x00000104
+#define PXA250_B1              0x00000103      /* or PXA260_A0 */
+#define PXA250_B0              0x00000102
+#define PXA250_A1              0x00000101
+#define PXA250_A0              0x00000100
+
+#define PXA210_C0              0x00000125
+#define PXA210_B2              0x00000124
+#define PXA210_B1              0x00000123
+#define PXA210_B0              0x00000122
+#define IXP425_A0              0x000001c1
+#define IXP425_B0              0x000001f1
+#define IXP465_AD              0x00000200
+
+/*
+ *     probe - binds to the platform device
+ */
+static int pxa25x_udc_probe(struct platform_device *pdev)
+{
+       struct pxa25x_udc *dev = &memory;
+       int retval, irq;
+       u32 chiprev;
+
+       pr_info("%s: version %s\n", driver_name, DRIVER_VERSION);
+
+       /* insist on Intel/ARM/XScale */
+       asm("mrc%? p15, 0, %0, c0, c0" : "=r" (chiprev));
+       if ((chiprev & CP15R0_VENDOR_MASK) != CP15R0_XSCALE_VALUE) {
+               pr_err("%s: not XScale!\n", driver_name);
+               return -ENODEV;
+       }
+
+       /* trigger chiprev-specific logic */
+       switch (chiprev & CP15R0_PRODREV_MASK) {
+#if    defined(CONFIG_ARCH_PXA)
+       case PXA255_A0:
+               dev->has_cfr = 1;
+               break;
+       case PXA250_A0:
+       case PXA250_A1:
+               /* A0/A1 "not released"; ep 13, 15 unusable */
+               /* fall through */
+       case PXA250_B2: case PXA210_B2:
+       case PXA250_B1: case PXA210_B1:
+       case PXA250_B0: case PXA210_B0:
+               /* OUT-DMA is broken ... */
+               /* fall through */
+       case PXA250_C0: case PXA210_C0:
+               break;
+#elif  defined(CONFIG_ARCH_IXP4XX)
+       case IXP425_A0:
+       case IXP425_B0:
+       case IXP465_AD:
+               dev->has_cfr = 1;
+               break;
+#endif
+       default:
+               pr_err("%s: unrecognized processor: %08x\n",
+                       driver_name, chiprev);
+               /* iop3xx, ixp4xx, ... */
+               return -ENODEV;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return -ENODEV;
+
+       dev->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(dev->clk))
+               return PTR_ERR(dev->clk);
+
+       pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
+               dev->has_cfr ? "" : " (!cfr)",
+               SIZE_STR "(pio)"
+               );
+
+       /* other non-static parts of init */
+       dev->dev = &pdev->dev;
+       dev->mach = dev_get_platdata(&pdev->dev);
+
+       dev->transceiver = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
+
+       if (gpio_is_valid(dev->mach->gpio_pullup)) {
+               retval = devm_gpio_request(&pdev->dev, dev->mach->gpio_pullup,
+                                          "pca25x_udc GPIO PULLUP");
+               if (retval) {
+                       dev_dbg(&pdev->dev,
+                               "can't get pullup gpio %d, err: %d\n",
+                               dev->mach->gpio_pullup, retval);
+                       goto err;
+               }
+               gpio_direction_output(dev->mach->gpio_pullup, 0);
+       }
+
+       init_timer(&dev->timer);
+       dev->timer.function = udc_watchdog;
+       dev->timer.data = (unsigned long) dev;
+
+       the_controller = dev;
+       platform_set_drvdata(pdev, dev);
+
+       udc_disable(dev);
+       udc_reinit(dev);
+
+       dev->vbus = 0;
+
+       /* irq setup after old hardware state is cleaned up */
+       retval = devm_request_irq(&pdev->dev, irq, pxa25x_udc_irq, 0,
+                                 driver_name, dev);
+       if (retval != 0) {
+               pr_err("%s: can't get irq %d, err %d\n",
+                       driver_name, irq, retval);
+               goto err;
+       }
+       dev->got_irq = 1;
+
+#ifdef CONFIG_ARCH_LUBBOCK
+       if (machine_is_lubbock()) {
+               retval = devm_request_irq(&pdev->dev, LUBBOCK_USB_DISC_IRQ,
+                                         lubbock_vbus_irq, 0, driver_name,
+                                         dev);
+               if (retval != 0) {
+                       pr_err("%s: can't get irq %i, err %d\n",
+                               driver_name, LUBBOCK_USB_DISC_IRQ, retval);
+                       goto err;
+               }
+               retval = devm_request_irq(&pdev->dev, LUBBOCK_USB_IRQ,
+                                         lubbock_vbus_irq, 0, driver_name,
+                                         dev);
+               if (retval != 0) {
+                       pr_err("%s: can't get irq %i, err %d\n",
+                               driver_name, LUBBOCK_USB_IRQ, retval);
+                       goto err;
+               }
+       } else
+#endif
+       create_debug_files(dev);
+
+       retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+       if (!retval)
+               return retval;
+
+       remove_debug_files(dev);
+ err:
+       if (!IS_ERR_OR_NULL(dev->transceiver))
+               dev->transceiver = NULL;
+       return retval;
+}
+
+static void pxa25x_udc_shutdown(struct platform_device *_dev)
+{
+       pullup_off();
+}
+
+static int pxa25x_udc_remove(struct platform_device *pdev)
+{
+       struct pxa25x_udc *dev = platform_get_drvdata(pdev);
+
+       if (dev->driver)
+               return -EBUSY;
+
+       usb_del_gadget_udc(&dev->gadget);
+       dev->pullup = 0;
+       pullup(dev);
+
+       remove_debug_files(dev);
+
+       if (!IS_ERR_OR_NULL(dev->transceiver))
+               dev->transceiver = NULL;
+
+       the_controller = NULL;
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PM
+
+/* USB suspend (controlled by the host) and system suspend (controlled
+ * by the PXA) don't necessarily work well together.  If USB is active,
+ * the 48 MHz clock is required; so the system can't enter 33 MHz idle
+ * mode, or any deeper PM saving state.
+ *
+ * For now, we punt and forcibly disconnect from the USB host when PXA
+ * enters any suspend state.  While we're disconnected, we always disable
+ * the 48MHz USB clock ... allowing PXA sleep and/or 33 MHz idle states.
+ * Boards without software pullup control shouldn't use those states.
+ * VBUS IRQs should probably be ignored so that the PXA device just acts
+ * "dead" to USB hosts until system resume.
+ */
+static int pxa25x_udc_suspend(struct platform_device *dev, pm_message_t state)
+{
+       struct pxa25x_udc       *udc = platform_get_drvdata(dev);
+       unsigned long flags;
+
+       if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
+               WARNING("USB host won't detect disconnect!\n");
+       udc->suspended = 1;
+
+       local_irq_save(flags);
+       pullup(udc);
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+static int pxa25x_udc_resume(struct platform_device *dev)
+{
+       struct pxa25x_udc       *udc = platform_get_drvdata(dev);
+       unsigned long flags;
+
+       udc->suspended = 0;
+       local_irq_save(flags);
+       pullup(udc);
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+#else
+#define        pxa25x_udc_suspend      NULL
+#define        pxa25x_udc_resume       NULL
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static struct platform_driver udc_driver = {
+       .shutdown       = pxa25x_udc_shutdown,
+       .probe          = pxa25x_udc_probe,
+       .remove         = pxa25x_udc_remove,
+       .suspend        = pxa25x_udc_suspend,
+       .resume         = pxa25x_udc_resume,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "pxa25x-udc",
+       },
+};
+
+module_platform_driver(udc_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Frank Becker, Robert Schwebel, David Brownell");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa25x-udc");
diff --git a/drivers/usb/gadget/udc/pxa25x_udc.h b/drivers/usb/gadget/udc/pxa25x_udc.h
new file mode 100644 (file)
index 0000000..3fe5931
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Intel PXA25x on-chip full speed USB device controller
+ *
+ * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ * Copyright (C) 2003 David Brownell
+ *
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_USB_GADGET_PXA25X_H
+#define __LINUX_USB_GADGET_PXA25X_H
+
+#include <linux/types.h>
+
+/*-------------------------------------------------------------------------*/
+
+/* pxa25x has this (move to include/asm-arm/arch-pxa/pxa-regs.h) */
+#define UFNRH_SIR      (1 << 7)        /* SOF interrupt request */
+#define UFNRH_SIM      (1 << 6)        /* SOF interrupt mask */
+#define UFNRH_IPE14    (1 << 5)        /* ISO packet error, ep14 */
+#define UFNRH_IPE9     (1 << 4)        /* ISO packet error, ep9 */
+#define UFNRH_IPE4     (1 << 3)        /* ISO packet error, ep4 */
+
+/* pxa255 has this (move to include/asm-arm/arch-pxa/pxa-regs.h) */
+#define        UDCCFR          UDC_RES2        /* UDC Control Function Register */
+#define UDCCFR_AREN    (1 << 7)        /* ACK response enable (now) */
+#define UDCCFR_ACM     (1 << 2)        /* ACK control mode (wait for AREN) */
+
+/* latest pxa255 errata define new "must be one" bits in UDCCFR */
+#define        UDCCFR_MB1      (0xff & ~(UDCCFR_AREN|UDCCFR_ACM))
+
+/*-------------------------------------------------------------------------*/
+
+struct pxa25x_udc;
+
+struct pxa25x_ep {
+       struct usb_ep                           ep;
+       struct pxa25x_udc                       *dev;
+
+       struct list_head                        queue;
+       unsigned long                           pio_irqs;
+
+       unsigned short                          fifo_size;
+       u8                                      bEndpointAddress;
+       u8                                      bmAttributes;
+
+       unsigned                                stopped : 1;
+       unsigned                                dma_fixup : 1;
+
+       /* UDCCS = UDC Control/Status for this EP
+        * UBCR = UDC Byte Count Remaining (contents of OUT fifo)
+        * UDDR = UDC Endpoint Data Register (the fifo)
+        * DRCM = DMA Request Channel Map
+        */
+       volatile u32                            *reg_udccs;
+       volatile u32                            *reg_ubcr;
+       volatile u32                            *reg_uddr;
+};
+
+struct pxa25x_request {
+       struct usb_request                      req;
+       struct list_head                        queue;
+};
+
+enum ep0_state {
+       EP0_IDLE,
+       EP0_IN_DATA_PHASE,
+       EP0_OUT_DATA_PHASE,
+       EP0_END_XFER,
+       EP0_STALL,
+};
+
+#define EP0_FIFO_SIZE  ((unsigned)16)
+#define BULK_FIFO_SIZE ((unsigned)64)
+#define ISO_FIFO_SIZE  ((unsigned)256)
+#define INT_FIFO_SIZE  ((unsigned)8)
+
+struct udc_stats {
+       struct ep0stats {
+               unsigned long           ops;
+               unsigned long           bytes;
+       } read, write;
+       unsigned long                   irqs;
+};
+
+#ifdef CONFIG_USB_PXA25X_SMALL
+/* when memory's tight, SMALL config saves code+data.  */
+#define        PXA_UDC_NUM_ENDPOINTS   3
+#endif
+
+#ifndef        PXA_UDC_NUM_ENDPOINTS
+#define        PXA_UDC_NUM_ENDPOINTS   16
+#endif
+
+struct pxa25x_udc {
+       struct usb_gadget                       gadget;
+       struct usb_gadget_driver                *driver;
+
+       enum ep0_state                          ep0state;
+       struct udc_stats                        stats;
+       unsigned                                got_irq : 1,
+                                               vbus : 1,
+                                               pullup : 1,
+                                               has_cfr : 1,
+                                               req_pending : 1,
+                                               req_std : 1,
+                                               req_config : 1,
+                                               suspended : 1,
+                                               active : 1;
+
+#define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200))
+       struct timer_list                       timer;
+
+       struct device                           *dev;
+       struct clk                              *clk;
+       struct pxa2xx_udc_mach_info             *mach;
+       struct usb_phy                          *transceiver;
+       u64                                     dma_mask;
+       struct pxa25x_ep                        ep [PXA_UDC_NUM_ENDPOINTS];
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+       struct dentry                           *debugfs_udc;
+#endif
+};
+#define to_pxa25x(g)   (container_of((g), struct pxa25x_udc, gadget))
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_ARCH_LUBBOCK
+#include <mach/lubbock.h>
+/* lubbock can also report usb connect/disconnect irqs */
+#endif
+
+static struct pxa25x_udc *the_controller;
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Debugging support vanishes in non-debug builds.  DBG_NORMAL should be
+ * mostly silent during normal use/testing, with no timing side-effects.
+ */
+#define DBG_NORMAL     1       /* error paths, device state transitions */
+#define DBG_VERBOSE    2       /* add some success path trace info */
+#define DBG_NOISY      3       /* ... even more: request level */
+#define DBG_VERY_NOISY 4       /* ... even more: packet level */
+
+#define DMSG(stuff...) pr_debug("udc: " stuff)
+
+#ifdef DEBUG
+
+static const char *state_name[] = {
+       "EP0_IDLE",
+       "EP0_IN_DATA_PHASE", "EP0_OUT_DATA_PHASE",
+       "EP0_END_XFER", "EP0_STALL"
+};
+
+#ifdef VERBOSE_DEBUG
+#    define UDC_DEBUG DBG_VERBOSE
+#else
+#    define UDC_DEBUG DBG_NORMAL
+#endif
+
+static void __maybe_unused
+dump_udccr(const char *label)
+{
+       u32     udccr = UDCCR;
+       DMSG("%s %02X =%s%s%s%s%s%s%s%s\n",
+               label, udccr,
+               (udccr & UDCCR_REM) ? " rem" : "",
+               (udccr & UDCCR_RSTIR) ? " rstir" : "",
+               (udccr & UDCCR_SRM) ? " srm" : "",
+               (udccr & UDCCR_SUSIR) ? " susir" : "",
+               (udccr & UDCCR_RESIR) ? " resir" : "",
+               (udccr & UDCCR_RSM) ? " rsm" : "",
+               (udccr & UDCCR_UDA) ? " uda" : "",
+               (udccr & UDCCR_UDE) ? " ude" : "");
+}
+
+static void __maybe_unused
+dump_udccs0(const char *label)
+{
+       u32             udccs0 = UDCCS0;
+
+       DMSG("%s %s %02X =%s%s%s%s%s%s%s%s\n",
+               label, state_name[the_controller->ep0state], udccs0,
+               (udccs0 & UDCCS0_SA) ? " sa" : "",
+               (udccs0 & UDCCS0_RNE) ? " rne" : "",
+               (udccs0 & UDCCS0_FST) ? " fst" : "",
+               (udccs0 & UDCCS0_SST) ? " sst" : "",
+               (udccs0 & UDCCS0_DRWF) ? " dwrf" : "",
+               (udccs0 & UDCCS0_FTF) ? " ftf" : "",
+               (udccs0 & UDCCS0_IPR) ? " ipr" : "",
+               (udccs0 & UDCCS0_OPR) ? " opr" : "");
+}
+
+static void __maybe_unused
+dump_state(struct pxa25x_udc *dev)
+{
+       u32             tmp;
+       unsigned        i;
+
+       DMSG("%s, uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
+               state_name[dev->ep0state],
+               UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
+       dump_udccr("udccr");
+       if (dev->has_cfr) {
+               tmp = UDCCFR;
+               DMSG("udccfr %02X =%s%s\n", tmp,
+                       (tmp & UDCCFR_AREN) ? " aren" : "",
+                       (tmp & UDCCFR_ACM) ? " acm" : "");
+       }
+
+       if (!dev->driver) {
+               DMSG("no gadget driver bound\n");
+               return;
+       } else
+               DMSG("ep0 driver '%s'\n", dev->driver->driver.name);
+
+       dump_udccs0 ("udccs0");
+       DMSG("ep0 IN %lu/%lu, OUT %lu/%lu\n",
+               dev->stats.write.bytes, dev->stats.write.ops,
+               dev->stats.read.bytes, dev->stats.read.ops);
+
+       for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) {
+               if (dev->ep[i].ep.desc == NULL)
+                       continue;
+               DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccs);
+       }
+}
+
+#else
+
+#define        dump_udccr(x)   do{}while(0)
+#define        dump_udccs0(x)  do{}while(0)
+#define        dump_state(x)   do{}while(0)
+
+#define UDC_DEBUG ((unsigned)0)
+
+#endif
+
+#define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
+
+#define ERR(stuff...)          pr_err("udc: " stuff)
+#define WARNING(stuff...)      pr_warning("udc: " stuff)
+#define INFO(stuff...)         pr_info("udc: " stuff)
+
+
+#endif /* __LINUX_USB_GADGET_PXA25X_H */
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c
new file mode 100644 (file)
index 0000000..597d39f
--- /dev/null
@@ -0,0 +1,2632 @@
+/*
+ * Handles the Intel 27x USB Device Controller (UDC)
+ *
+ * Inspired by original driver by Frank Becker, David Brownell, and others.
+ * Copyright (C) 2008 Robert Jarzmik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/prefetch.h>
+#include <linux/byteorder/generic.h>
+#include <linux/platform_data/pxa2xx_udc.h>
+
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#include "pxa27x_udc.h"
+
+/*
+ * This driver handles the USB Device Controller (UDC) in Intel's PXA 27x
+ * series processors.
+ *
+ * Such controller drivers work with a gadget driver.  The gadget driver
+ * returns descriptors, implements configuration and data protocols used
+ * by the host to interact with this device, and allocates endpoints to
+ * the different protocol interfaces.  The controller driver virtualizes
+ * usb hardware so that the gadget drivers will be more portable.
+ *
+ * This UDC hardware wants to implement a bit too much USB protocol. The
+ * biggest issues are:  that the endpoints have to be set up before the
+ * controller can be enabled (minor, and not uncommon); and each endpoint
+ * can only have one configuration, interface and alternative interface
+ * number (major, and very unusual). Once set up, these cannot be changed
+ * without a controller reset.
+ *
+ * The workaround is to setup all combinations necessary for the gadgets which
+ * will work with this driver. This is done in pxa_udc structure, statically.
+ * See pxa_udc, udc_usb_ep versus pxa_ep, and matching function find_pxa_ep.
+ * (You could modify this if needed.  Some drivers have a "fifo_mode" module
+ * parameter to facilitate such changes.)
+ *
+ * The combinations have been tested with these gadgets :
+ *  - zero gadget
+ *  - file storage gadget
+ *  - ether gadget
+ *
+ * The driver doesn't use DMA, only IO access and IRQ callbacks. No use is
+ * made of UDC's double buffering either. USB "On-The-Go" is not implemented.
+ *
+ * All the requests are handled the same way :
+ *  - the drivers tries to handle the request directly to the IO
+ *  - if the IO fifo is not big enough, the remaining is send/received in
+ *    interrupt handling.
+ */
+
+#define        DRIVER_VERSION  "2008-04-18"
+#define        DRIVER_DESC     "PXA 27x USB Device Controller driver"
+
+static const char driver_name[] = "pxa27x_udc";
+static struct pxa_udc *the_controller;
+
+static void handle_ep(struct pxa_ep *ep);
+
+/*
+ * Debug filesystem
+ */
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/seq_file.h>
+
+static int state_dbg_show(struct seq_file *s, void *p)
+{
+       struct pxa_udc *udc = s->private;
+       int pos = 0, ret;
+       u32 tmp;
+
+       ret = -ENODEV;
+       if (!udc->driver)
+               goto out;
+
+       /* basic device status */
+       pos += seq_printf(s, DRIVER_DESC "\n"
+                        "%s version: %s\nGadget driver: %s\n",
+                        driver_name, DRIVER_VERSION,
+                        udc->driver ? udc->driver->driver.name : "(none)");
+
+       tmp = udc_readl(udc, UDCCR);
+       pos += seq_printf(s,
+                        "udccr=0x%0x(%s%s%s%s%s%s%s%s%s%s), "
+                        "con=%d,inter=%d,altinter=%d\n", tmp,
+                        (tmp & UDCCR_OEN) ? " oen":"",
+                        (tmp & UDCCR_AALTHNP) ? " aalthnp":"",
+                        (tmp & UDCCR_AHNP) ? " rem" : "",
+                        (tmp & UDCCR_BHNP) ? " rstir" : "",
+                        (tmp & UDCCR_DWRE) ? " dwre" : "",
+                        (tmp & UDCCR_SMAC) ? " smac" : "",
+                        (tmp & UDCCR_EMCE) ? " emce" : "",
+                        (tmp & UDCCR_UDR) ? " udr" : "",
+                        (tmp & UDCCR_UDA) ? " uda" : "",
+                        (tmp & UDCCR_UDE) ? " ude" : "",
+                        (tmp & UDCCR_ACN) >> UDCCR_ACN_S,
+                        (tmp & UDCCR_AIN) >> UDCCR_AIN_S,
+                        (tmp & UDCCR_AAISN) >> UDCCR_AAISN_S);
+       /* registers for device and ep0 */
+       pos += seq_printf(s, "udcicr0=0x%08x udcicr1=0x%08x\n",
+                       udc_readl(udc, UDCICR0), udc_readl(udc, UDCICR1));
+       pos += seq_printf(s, "udcisr0=0x%08x udcisr1=0x%08x\n",
+                       udc_readl(udc, UDCISR0), udc_readl(udc, UDCISR1));
+       pos += seq_printf(s, "udcfnr=%d\n", udc_readl(udc, UDCFNR));
+       pos += seq_printf(s, "irqs: reset=%lu, suspend=%lu, resume=%lu, "
+                       "reconfig=%lu\n",
+                       udc->stats.irqs_reset, udc->stats.irqs_suspend,
+                       udc->stats.irqs_resume, udc->stats.irqs_reconfig);
+
+       ret = 0;
+out:
+       return ret;
+}
+
+static int queues_dbg_show(struct seq_file *s, void *p)
+{
+       struct pxa_udc *udc = s->private;
+       struct pxa_ep *ep;
+       struct pxa27x_request *req;
+       int pos = 0, i, maxpkt, ret;
+
+       ret = -ENODEV;
+       if (!udc->driver)
+               goto out;
+
+       /* dump endpoint queues */
+       for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
+               ep = &udc->pxa_ep[i];
+               maxpkt = ep->fifo_size;
+               pos += seq_printf(s,  "%-12s max_pkt=%d %s\n",
+                               EPNAME(ep), maxpkt, "pio");
+
+               if (list_empty(&ep->queue)) {
+                       pos += seq_printf(s, "\t(nothing queued)\n");
+                       continue;
+               }
+
+               list_for_each_entry(req, &ep->queue, queue) {
+                       pos += seq_printf(s,  "\treq %p len %d/%d buf %p\n",
+                                       &req->req, req->req.actual,
+                                       req->req.length, req->req.buf);
+               }
+       }
+
+       ret = 0;
+out:
+       return ret;
+}
+
+static int eps_dbg_show(struct seq_file *s, void *p)
+{
+       struct pxa_udc *udc = s->private;
+       struct pxa_ep *ep;
+       int pos = 0, i, ret;
+       u32 tmp;
+
+       ret = -ENODEV;
+       if (!udc->driver)
+               goto out;
+
+       ep = &udc->pxa_ep[0];
+       tmp = udc_ep_readl(ep, UDCCSR);
+       pos += seq_printf(s, "udccsr0=0x%03x(%s%s%s%s%s%s%s)\n", tmp,
+                        (tmp & UDCCSR0_SA) ? " sa" : "",
+                        (tmp & UDCCSR0_RNE) ? " rne" : "",
+                        (tmp & UDCCSR0_FST) ? " fst" : "",
+                        (tmp & UDCCSR0_SST) ? " sst" : "",
+                        (tmp & UDCCSR0_DME) ? " dme" : "",
+                        (tmp & UDCCSR0_IPR) ? " ipr" : "",
+                        (tmp & UDCCSR0_OPC) ? " opc" : "");
+       for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
+               ep = &udc->pxa_ep[i];
+               tmp = i? udc_ep_readl(ep, UDCCR) : udc_readl(udc, UDCCR);
+               pos += seq_printf(s, "%-12s: "
+                               "IN %lu(%lu reqs), OUT %lu(%lu reqs), "
+                               "irqs=%lu, udccr=0x%08x, udccsr=0x%03x, "
+                               "udcbcr=%d\n",
+                               EPNAME(ep),
+                               ep->stats.in_bytes, ep->stats.in_ops,
+                               ep->stats.out_bytes, ep->stats.out_ops,
+                               ep->stats.irqs,
+                               tmp, udc_ep_readl(ep, UDCCSR),
+                               udc_ep_readl(ep, UDCBCR));
+       }
+
+       ret = 0;
+out:
+       return ret;
+}
+
+static int eps_dbg_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, eps_dbg_show, inode->i_private);
+}
+
+static int queues_dbg_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, queues_dbg_show, inode->i_private);
+}
+
+static int state_dbg_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, state_dbg_show, inode->i_private);
+}
+
+static const struct file_operations state_dbg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = state_dbg_open,
+       .llseek         = seq_lseek,
+       .read           = seq_read,
+       .release        = single_release,
+};
+
+static const struct file_operations queues_dbg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = queues_dbg_open,
+       .llseek         = seq_lseek,
+       .read           = seq_read,
+       .release        = single_release,
+};
+
+static const struct file_operations eps_dbg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = eps_dbg_open,
+       .llseek         = seq_lseek,
+       .read           = seq_read,
+       .release        = single_release,
+};
+
+static void pxa_init_debugfs(struct pxa_udc *udc)
+{
+       struct dentry *root, *state, *queues, *eps;
+
+       root = debugfs_create_dir(udc->gadget.name, NULL);
+       if (IS_ERR(root) || !root)
+               goto err_root;
+
+       state = debugfs_create_file("udcstate", 0400, root, udc,
+                       &state_dbg_fops);
+       if (!state)
+               goto err_state;
+       queues = debugfs_create_file("queues", 0400, root, udc,
+                       &queues_dbg_fops);
+       if (!queues)
+               goto err_queues;
+       eps = debugfs_create_file("epstate", 0400, root, udc,
+                       &eps_dbg_fops);
+       if (!eps)
+               goto err_eps;
+
+       udc->debugfs_root = root;
+       udc->debugfs_state = state;
+       udc->debugfs_queues = queues;
+       udc->debugfs_eps = eps;
+       return;
+err_eps:
+       debugfs_remove(eps);
+err_queues:
+       debugfs_remove(queues);
+err_state:
+       debugfs_remove(root);
+err_root:
+       dev_err(udc->dev, "debugfs is not available\n");
+}
+
+static void pxa_cleanup_debugfs(struct pxa_udc *udc)
+{
+       debugfs_remove(udc->debugfs_eps);
+       debugfs_remove(udc->debugfs_queues);
+       debugfs_remove(udc->debugfs_state);
+       debugfs_remove(udc->debugfs_root);
+       udc->debugfs_eps = NULL;
+       udc->debugfs_queues = NULL;
+       udc->debugfs_state = NULL;
+       udc->debugfs_root = NULL;
+}
+
+#else
+static inline void pxa_init_debugfs(struct pxa_udc *udc)
+{
+}
+
+static inline void pxa_cleanup_debugfs(struct pxa_udc *udc)
+{
+}
+#endif
+
+/**
+ * is_match_usb_pxa - check if usb_ep and pxa_ep match
+ * @udc_usb_ep: usb endpoint
+ * @ep: pxa endpoint
+ * @config: configuration required in pxa_ep
+ * @interface: interface required in pxa_ep
+ * @altsetting: altsetting required in pxa_ep
+ *
+ * Returns 1 if all criteria match between pxa and usb endpoint, 0 otherwise
+ */
+static int is_match_usb_pxa(struct udc_usb_ep *udc_usb_ep, struct pxa_ep *ep,
+               int config, int interface, int altsetting)
+{
+       if (usb_endpoint_num(&udc_usb_ep->desc) != ep->addr)
+               return 0;
+       if (usb_endpoint_dir_in(&udc_usb_ep->desc) != ep->dir_in)
+               return 0;
+       if (usb_endpoint_type(&udc_usb_ep->desc) != ep->type)
+               return 0;
+       if ((ep->config != config) || (ep->interface != interface)
+                       || (ep->alternate != altsetting))
+               return 0;
+       return 1;
+}
+
+/**
+ * find_pxa_ep - find pxa_ep structure matching udc_usb_ep
+ * @udc: pxa udc
+ * @udc_usb_ep: udc_usb_ep structure
+ *
+ * Match udc_usb_ep and all pxa_ep available, to see if one matches.
+ * This is necessary because of the strong pxa hardware restriction requiring
+ * that once pxa endpoints are initialized, their configuration is freezed, and
+ * no change can be made to their address, direction, or in which configuration,
+ * interface or altsetting they are active ... which differs from more usual
+ * models which have endpoints be roughly just addressable fifos, and leave
+ * configuration events up to gadget drivers (like all control messages).
+ *
+ * Note that there is still a blurred point here :
+ *   - we rely on UDCCR register "active interface" and "active altsetting".
+ *     This is a nonsense in regard of USB spec, where multiple interfaces are
+ *     active at the same time.
+ *   - if we knew for sure that the pxa can handle multiple interface at the
+ *     same time, assuming Intel's Developer Guide is wrong, this function
+ *     should be reviewed, and a cache of couples (iface, altsetting) should
+ *     be kept in the pxa_udc structure. In this case this function would match
+ *     against the cache of couples instead of the "last altsetting" set up.
+ *
+ * Returns the matched pxa_ep structure or NULL if none found
+ */
+static struct pxa_ep *find_pxa_ep(struct pxa_udc *udc,
+               struct udc_usb_ep *udc_usb_ep)
+{
+       int i;
+       struct pxa_ep *ep;
+       int cfg = udc->config;
+       int iface = udc->last_interface;
+       int alt = udc->last_alternate;
+
+       if (udc_usb_ep == &udc->udc_usb_ep[0])
+               return &udc->pxa_ep[0];
+
+       for (i = 1; i < NR_PXA_ENDPOINTS; i++) {
+               ep = &udc->pxa_ep[i];
+               if (is_match_usb_pxa(udc_usb_ep, ep, cfg, iface, alt))
+                       return ep;
+       }
+       return NULL;
+}
+
+/**
+ * update_pxa_ep_matches - update pxa_ep cached values in all udc_usb_ep
+ * @udc: pxa udc
+ *
+ * Context: in_interrupt()
+ *
+ * Updates all pxa_ep fields in udc_usb_ep structures, if this field was
+ * previously set up (and is not NULL). The update is necessary is a
+ * configuration change or altsetting change was issued by the USB host.
+ */
+static void update_pxa_ep_matches(struct pxa_udc *udc)
+{
+       int i;
+       struct udc_usb_ep *udc_usb_ep;
+
+       for (i = 1; i < NR_USB_ENDPOINTS; i++) {
+               udc_usb_ep = &udc->udc_usb_ep[i];
+               if (udc_usb_ep->pxa_ep)
+                       udc_usb_ep->pxa_ep = find_pxa_ep(udc, udc_usb_ep);
+       }
+}
+
+/**
+ * pio_irq_enable - Enables irq generation for one endpoint
+ * @ep: udc endpoint
+ */
+static void pio_irq_enable(struct pxa_ep *ep)
+{
+       struct pxa_udc *udc = ep->dev;
+       int index = EPIDX(ep);
+       u32 udcicr0 = udc_readl(udc, UDCICR0);
+       u32 udcicr1 = udc_readl(udc, UDCICR1);
+
+       if (index < 16)
+               udc_writel(udc, UDCICR0, udcicr0 | (3 << (index * 2)));
+       else
+               udc_writel(udc, UDCICR1, udcicr1 | (3 << ((index - 16) * 2)));
+}
+
+/**
+ * pio_irq_disable - Disables irq generation for one endpoint
+ * @ep: udc endpoint
+ */
+static void pio_irq_disable(struct pxa_ep *ep)
+{
+       struct pxa_udc *udc = ep->dev;
+       int index = EPIDX(ep);
+       u32 udcicr0 = udc_readl(udc, UDCICR0);
+       u32 udcicr1 = udc_readl(udc, UDCICR1);
+
+       if (index < 16)
+               udc_writel(udc, UDCICR0, udcicr0 & ~(3 << (index * 2)));
+       else
+               udc_writel(udc, UDCICR1, udcicr1 & ~(3 << ((index - 16) * 2)));
+}
+
+/**
+ * udc_set_mask_UDCCR - set bits in UDCCR
+ * @udc: udc device
+ * @mask: bits to set in UDCCR
+ *
+ * Sets bits in UDCCR, leaving DME and FST bits as they were.
+ */
+static inline void udc_set_mask_UDCCR(struct pxa_udc *udc, int mask)
+{
+       u32 udccr = udc_readl(udc, UDCCR);
+       udc_writel(udc, UDCCR,
+                       (udccr & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS));
+}
+
+/**
+ * udc_clear_mask_UDCCR - clears bits in UDCCR
+ * @udc: udc device
+ * @mask: bit to clear in UDCCR
+ *
+ * Clears bits in UDCCR, leaving DME and FST bits as they were.
+ */
+static inline void udc_clear_mask_UDCCR(struct pxa_udc *udc, int mask)
+{
+       u32 udccr = udc_readl(udc, UDCCR);
+       udc_writel(udc, UDCCR,
+                       (udccr & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS));
+}
+
+/**
+ * ep_write_UDCCSR - set bits in UDCCSR
+ * @udc: udc device
+ * @mask: bits to set in UDCCR
+ *
+ * Sets bits in UDCCSR (UDCCSR0 and UDCCSR*).
+ *
+ * A specific case is applied to ep0 : the ACM bit is always set to 1, for
+ * SET_INTERFACE and SET_CONFIGURATION.
+ */
+static inline void ep_write_UDCCSR(struct pxa_ep *ep, int mask)
+{
+       if (is_ep0(ep))
+               mask |= UDCCSR0_ACM;
+       udc_ep_writel(ep, UDCCSR, mask);
+}
+
+/**
+ * ep_count_bytes_remain - get how many bytes in udc endpoint
+ * @ep: udc endpoint
+ *
+ * Returns number of bytes in OUT fifos. Broken for IN fifos (-EOPNOTSUPP)
+ */
+static int ep_count_bytes_remain(struct pxa_ep *ep)
+{
+       if (ep->dir_in)
+               return -EOPNOTSUPP;
+       return udc_ep_readl(ep, UDCBCR) & 0x3ff;
+}
+
+/**
+ * ep_is_empty - checks if ep has byte ready for reading
+ * @ep: udc endpoint
+ *
+ * If endpoint is the control endpoint, checks if there are bytes in the
+ * control endpoint fifo. If endpoint is a data endpoint, checks if bytes
+ * are ready for reading on OUT endpoint.
+ *
+ * Returns 0 if ep not empty, 1 if ep empty, -EOPNOTSUPP if IN endpoint
+ */
+static int ep_is_empty(struct pxa_ep *ep)
+{
+       int ret;
+
+       if (!is_ep0(ep) && ep->dir_in)
+               return -EOPNOTSUPP;
+       if (is_ep0(ep))
+               ret = !(udc_ep_readl(ep, UDCCSR) & UDCCSR0_RNE);
+       else
+               ret = !(udc_ep_readl(ep, UDCCSR) & UDCCSR_BNE);
+       return ret;
+}
+
+/**
+ * ep_is_full - checks if ep has place to write bytes
+ * @ep: udc endpoint
+ *
+ * If endpoint is not the control endpoint and is an IN endpoint, checks if
+ * there is place to write bytes into the endpoint.
+ *
+ * Returns 0 if ep not full, 1 if ep full, -EOPNOTSUPP if OUT endpoint
+ */
+static int ep_is_full(struct pxa_ep *ep)
+{
+       if (is_ep0(ep))
+               return (udc_ep_readl(ep, UDCCSR) & UDCCSR0_IPR);
+       if (!ep->dir_in)
+               return -EOPNOTSUPP;
+       return (!(udc_ep_readl(ep, UDCCSR) & UDCCSR_BNF));
+}
+
+/**
+ * epout_has_pkt - checks if OUT endpoint fifo has a packet available
+ * @ep: pxa endpoint
+ *
+ * Returns 1 if a complete packet is available, 0 if not, -EOPNOTSUPP for IN ep.
+ */
+static int epout_has_pkt(struct pxa_ep *ep)
+{
+       if (!is_ep0(ep) && ep->dir_in)
+               return -EOPNOTSUPP;
+       if (is_ep0(ep))
+               return (udc_ep_readl(ep, UDCCSR) & UDCCSR0_OPC);
+       return (udc_ep_readl(ep, UDCCSR) & UDCCSR_PC);
+}
+
+/**
+ * set_ep0state - Set ep0 automata state
+ * @dev: udc device
+ * @state: state
+ */
+static void set_ep0state(struct pxa_udc *udc, int state)
+{
+       struct pxa_ep *ep = &udc->pxa_ep[0];
+       char *old_stname = EP0_STNAME(udc);
+
+       udc->ep0state = state;
+       ep_dbg(ep, "state=%s->%s, udccsr0=0x%03x, udcbcr=%d\n", old_stname,
+               EP0_STNAME(udc), udc_ep_readl(ep, UDCCSR),
+               udc_ep_readl(ep, UDCBCR));
+}
+
+/**
+ * ep0_idle - Put control endpoint into idle state
+ * @dev: udc device
+ */
+static void ep0_idle(struct pxa_udc *dev)
+{
+       set_ep0state(dev, WAIT_FOR_SETUP);
+}
+
+/**
+ * inc_ep_stats_reqs - Update ep stats counts
+ * @ep: physical endpoint
+ * @req: usb request
+ * @is_in: ep direction (USB_DIR_IN or 0)
+ *
+ */
+static void inc_ep_stats_reqs(struct pxa_ep *ep, int is_in)
+{
+       if (is_in)
+               ep->stats.in_ops++;
+       else
+               ep->stats.out_ops++;
+}
+
+/**
+ * inc_ep_stats_bytes - Update ep stats counts
+ * @ep: physical endpoint
+ * @count: bytes transferred on endpoint
+ * @is_in: ep direction (USB_DIR_IN or 0)
+ */
+static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in)
+{
+       if (is_in)
+               ep->stats.in_bytes += count;
+       else
+               ep->stats.out_bytes += count;
+}
+
+/**
+ * pxa_ep_setup - Sets up an usb physical endpoint
+ * @ep: pxa27x physical endpoint
+ *
+ * Find the physical pxa27x ep, and setup its UDCCR
+ */
+static void pxa_ep_setup(struct pxa_ep *ep)
+{
+       u32 new_udccr;
+
+       new_udccr = ((ep->config << UDCCONR_CN_S) & UDCCONR_CN)
+               | ((ep->interface << UDCCONR_IN_S) & UDCCONR_IN)
+               | ((ep->alternate << UDCCONR_AISN_S) & UDCCONR_AISN)
+               | ((EPADDR(ep) << UDCCONR_EN_S) & UDCCONR_EN)
+               | ((EPXFERTYPE(ep) << UDCCONR_ET_S) & UDCCONR_ET)
+               | ((ep->dir_in) ? UDCCONR_ED : 0)
+               | ((ep->fifo_size << UDCCONR_MPS_S) & UDCCONR_MPS)
+               | UDCCONR_EE;
+
+       udc_ep_writel(ep, UDCCR, new_udccr);
+}
+
+/**
+ * pxa_eps_setup - Sets up all usb physical endpoints
+ * @dev: udc device
+ *
+ * Setup all pxa physical endpoints, except ep0
+ */
+static void pxa_eps_setup(struct pxa_udc *dev)
+{
+       unsigned int i;
+
+       dev_dbg(dev->dev, "%s: dev=%p\n", __func__, dev);
+
+       for (i = 1; i < NR_PXA_ENDPOINTS; i++)
+               pxa_ep_setup(&dev->pxa_ep[i]);
+}
+
+/**
+ * pxa_ep_alloc_request - Allocate usb request
+ * @_ep: usb endpoint
+ * @gfp_flags:
+ *
+ * For the pxa27x, these can just wrap kmalloc/kfree.  gadget drivers
+ * must still pass correctly initialized endpoints, since other controller
+ * drivers may care about how it's currently set up (dma issues etc).
+  */
+static struct usb_request *
+pxa_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct pxa27x_request *req;
+
+       req = kzalloc(sizeof *req, gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+       req->in_use = 0;
+       req->udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+
+       return &req->req;
+}
+
+/**
+ * pxa_ep_free_request - Free usb request
+ * @_ep: usb endpoint
+ * @_req: usb request
+ *
+ * Wrapper around kfree to free _req
+ */
+static void pxa_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct pxa27x_request *req;
+
+       req = container_of(_req, struct pxa27x_request, req);
+       WARN_ON(!list_empty(&req->queue));
+       kfree(req);
+}
+
+/**
+ * ep_add_request - add a request to the endpoint's queue
+ * @ep: usb endpoint
+ * @req: usb request
+ *
+ * Context: ep->lock held
+ *
+ * Queues the request in the endpoint's queue, and enables the interrupts
+ * on the endpoint.
+ */
+static void ep_add_request(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       if (unlikely(!req))
+               return;
+       ep_vdbg(ep, "req:%p, lg=%d, udccsr=0x%03x\n", req,
+               req->req.length, udc_ep_readl(ep, UDCCSR));
+
+       req->in_use = 1;
+       list_add_tail(&req->queue, &ep->queue);
+       pio_irq_enable(ep);
+}
+
+/**
+ * ep_del_request - removes a request from the endpoint's queue
+ * @ep: usb endpoint
+ * @req: usb request
+ *
+ * Context: ep->lock held
+ *
+ * Unqueue the request from the endpoint's queue. If there are no more requests
+ * on the endpoint, and if it's not the control endpoint, interrupts are
+ * disabled on the endpoint.
+ */
+static void ep_del_request(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       if (unlikely(!req))
+               return;
+       ep_vdbg(ep, "req:%p, lg=%d, udccsr=0x%03x\n", req,
+               req->req.length, udc_ep_readl(ep, UDCCSR));
+
+       list_del_init(&req->queue);
+       req->in_use = 0;
+       if (!is_ep0(ep) && list_empty(&ep->queue))
+               pio_irq_disable(ep);
+}
+
+/**
+ * req_done - Complete an usb request
+ * @ep: pxa physical endpoint
+ * @req: pxa request
+ * @status: usb request status sent to gadget API
+ * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
+ *
+ * Context: ep->lock held if flags not NULL, else ep->lock released
+ *
+ * Retire a pxa27x usb request. Endpoint must be locked.
+ */
+static void req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status,
+       unsigned long *pflags)
+{
+       unsigned long   flags;
+
+       ep_del_request(ep, req);
+       if (likely(req->req.status == -EINPROGRESS))
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       if (status && status != -ESHUTDOWN)
+               ep_dbg(ep, "complete req %p stat %d len %u/%u\n",
+                       &req->req, status,
+                       req->req.actual, req->req.length);
+
+       if (pflags)
+               spin_unlock_irqrestore(&ep->lock, *pflags);
+       local_irq_save(flags);
+       req->req.complete(&req->udc_usb_ep->usb_ep, &req->req);
+       local_irq_restore(flags);
+       if (pflags)
+               spin_lock_irqsave(&ep->lock, *pflags);
+}
+
+/**
+ * ep_end_out_req - Ends endpoint OUT request
+ * @ep: physical endpoint
+ * @req: pxa request
+ * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
+ *
+ * Context: ep->lock held or released (see req_done())
+ *
+ * Ends endpoint OUT request (completes usb request).
+ */
+static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req,
+       unsigned long *pflags)
+{
+       inc_ep_stats_reqs(ep, !USB_DIR_IN);
+       req_done(ep, req, 0, pflags);
+}
+
+/**
+ * ep0_end_out_req - Ends control endpoint OUT request (ends data stage)
+ * @ep: physical endpoint
+ * @req: pxa request
+ * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
+ *
+ * Context: ep->lock held or released (see req_done())
+ *
+ * Ends control endpoint OUT request (completes usb request), and puts
+ * control endpoint into idle state
+ */
+static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req,
+       unsigned long *pflags)
+{
+       set_ep0state(ep->dev, OUT_STATUS_STAGE);
+       ep_end_out_req(ep, req, pflags);
+       ep0_idle(ep->dev);
+}
+
+/**
+ * ep_end_in_req - Ends endpoint IN request
+ * @ep: physical endpoint
+ * @req: pxa request
+ * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
+ *
+ * Context: ep->lock held or released (see req_done())
+ *
+ * Ends endpoint IN request (completes usb request).
+ */
+static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req,
+       unsigned long *pflags)
+{
+       inc_ep_stats_reqs(ep, USB_DIR_IN);
+       req_done(ep, req, 0, pflags);
+}
+
+/**
+ * ep0_end_in_req - Ends control endpoint IN request (ends data stage)
+ * @ep: physical endpoint
+ * @req: pxa request
+ * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
+ *
+ * Context: ep->lock held or released (see req_done())
+ *
+ * Ends control endpoint IN request (completes usb request), and puts
+ * control endpoint into status state
+ */
+static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req,
+       unsigned long *pflags)
+{
+       set_ep0state(ep->dev, IN_STATUS_STAGE);
+       ep_end_in_req(ep, req, pflags);
+}
+
+/**
+ * nuke - Dequeue all requests
+ * @ep: pxa endpoint
+ * @status: usb request status
+ *
+ * Context: ep->lock released
+ *
+ * Dequeues all requests on an endpoint. As a side effect, interrupts will be
+ * disabled on that endpoint (because no more requests).
+ */
+static void nuke(struct pxa_ep *ep, int status)
+{
+       struct pxa27x_request   *req;
+       unsigned long           flags;
+
+       spin_lock_irqsave(&ep->lock, flags);
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct pxa27x_request, queue);
+               req_done(ep, req, status, &flags);
+       }
+       spin_unlock_irqrestore(&ep->lock, flags);
+}
+
+/**
+ * read_packet - transfer 1 packet from an OUT endpoint into request
+ * @ep: pxa physical endpoint
+ * @req: usb request
+ *
+ * Takes bytes from OUT endpoint and transfers them info the usb request.
+ * If there is less space in request than bytes received in OUT endpoint,
+ * bytes are left in the OUT endpoint.
+ *
+ * Returns how many bytes were actually transferred
+ */
+static int read_packet(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       u32 *buf;
+       int bytes_ep, bufferspace, count, i;
+
+       bytes_ep = ep_count_bytes_remain(ep);
+       bufferspace = req->req.length - req->req.actual;
+
+       buf = (u32 *)(req->req.buf + req->req.actual);
+       prefetchw(buf);
+
+       if (likely(!ep_is_empty(ep)))
+               count = min(bytes_ep, bufferspace);
+       else /* zlp */
+               count = 0;
+
+       for (i = count; i > 0; i -= 4)
+               *buf++ = udc_ep_readl(ep, UDCDR);
+       req->req.actual += count;
+
+       ep_write_UDCCSR(ep, UDCCSR_PC);
+
+       return count;
+}
+
+/**
+ * write_packet - transfer 1 packet from request into an IN endpoint
+ * @ep: pxa physical endpoint
+ * @req: usb request
+ * @max: max bytes that fit into endpoint
+ *
+ * Takes bytes from usb request, and transfers them into the physical
+ * endpoint. If there are no bytes to transfer, doesn't write anything
+ * to physical endpoint.
+ *
+ * Returns how many bytes were actually transferred.
+ */
+static int write_packet(struct pxa_ep *ep, struct pxa27x_request *req,
+                       unsigned int max)
+{
+       int length, count, remain, i;
+       u32 *buf;
+       u8 *buf_8;
+
+       buf = (u32 *)(req->req.buf + req->req.actual);
+       prefetch(buf);
+
+       length = min(req->req.length - req->req.actual, max);
+       req->req.actual += length;
+
+       remain = length & 0x3;
+       count = length & ~(0x3);
+       for (i = count; i > 0 ; i -= 4)
+               udc_ep_writel(ep, UDCDR, *buf++);
+
+       buf_8 = (u8 *)buf;
+       for (i = remain; i > 0; i--)
+               udc_ep_writeb(ep, UDCDR, *buf_8++);
+
+       ep_vdbg(ep, "length=%d+%d, udccsr=0x%03x\n", count, remain,
+               udc_ep_readl(ep, UDCCSR));
+
+       return length;
+}
+
+/**
+ * read_fifo - Transfer packets from OUT endpoint into usb request
+ * @ep: pxa physical endpoint
+ * @req: usb request
+ *
+ * Context: callable when in_interrupt()
+ *
+ * Unload as many packets as possible from the fifo we use for usb OUT
+ * transfers and put them into the request. Caller should have made sure
+ * there's at least one packet ready.
+ * Doesn't complete the request, that's the caller's job
+ *
+ * Returns 1 if the request completed, 0 otherwise
+ */
+static int read_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       int count, is_short, completed = 0;
+
+       while (epout_has_pkt(ep)) {
+               count = read_packet(ep, req);
+               inc_ep_stats_bytes(ep, count, !USB_DIR_IN);
+
+               is_short = (count < ep->fifo_size);
+               ep_dbg(ep, "read udccsr:%03x, count:%d bytes%s req %p %d/%d\n",
+                       udc_ep_readl(ep, UDCCSR), count, is_short ? "/S" : "",
+                       &req->req, req->req.actual, req->req.length);
+
+               /* completion */
+               if (is_short || req->req.actual == req->req.length) {
+                       completed = 1;
+                       break;
+               }
+               /* finished that packet.  the next one may be waiting... */
+       }
+       return completed;
+}
+
+/**
+ * write_fifo - transfer packets from usb request into an IN endpoint
+ * @ep: pxa physical endpoint
+ * @req: pxa usb request
+ *
+ * Write to an IN endpoint fifo, as many packets as possible.
+ * irqs will use this to write the rest later.
+ * caller guarantees at least one packet buffer is ready (or a zlp).
+ * Doesn't complete the request, that's the caller's job
+ *
+ * Returns 1 if request fully transferred, 0 if partial transfer
+ */
+static int write_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       unsigned max;
+       int count, is_short, is_last = 0, completed = 0, totcount = 0;
+       u32 udccsr;
+
+       max = ep->fifo_size;
+       do {
+               is_short = 0;
+
+               udccsr = udc_ep_readl(ep, UDCCSR);
+               if (udccsr & UDCCSR_PC) {
+                       ep_vdbg(ep, "Clearing Transmit Complete, udccsr=%x\n",
+                               udccsr);
+                       ep_write_UDCCSR(ep, UDCCSR_PC);
+               }
+               if (udccsr & UDCCSR_TRN) {
+                       ep_vdbg(ep, "Clearing Underrun on, udccsr=%x\n",
+                               udccsr);
+                       ep_write_UDCCSR(ep, UDCCSR_TRN);
+               }
+
+               count = write_packet(ep, req, max);
+               inc_ep_stats_bytes(ep, count, USB_DIR_IN);
+               totcount += count;
+
+               /* last packet is usually short (or a zlp) */
+               if (unlikely(count < max)) {
+                       is_last = 1;
+                       is_short = 1;
+               } else {
+                       if (likely(req->req.length > req->req.actual)
+                                       || req->req.zero)
+                               is_last = 0;
+                       else
+                               is_last = 1;
+                       /* interrupt/iso maxpacket may not fill the fifo */
+                       is_short = unlikely(max < ep->fifo_size);
+               }
+
+               if (is_short)
+                       ep_write_UDCCSR(ep, UDCCSR_SP);
+
+               /* requests complete when all IN data is in the FIFO */
+               if (is_last) {
+                       completed = 1;
+                       break;
+               }
+       } while (!ep_is_full(ep));
+
+       ep_dbg(ep, "wrote count:%d bytes%s%s, left:%d req=%p\n",
+                       totcount, is_last ? "/L" : "", is_short ? "/S" : "",
+                       req->req.length - req->req.actual, &req->req);
+
+       return completed;
+}
+
+/**
+ * read_ep0_fifo - Transfer packets from control endpoint into usb request
+ * @ep: control endpoint
+ * @req: pxa usb request
+ *
+ * Special ep0 version of the above read_fifo. Reads as many bytes from control
+ * endpoint as can be read, and stores them into usb request (limited by request
+ * maximum length).
+ *
+ * Returns 0 if usb request only partially filled, 1 if fully filled
+ */
+static int read_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       int count, is_short, completed = 0;
+
+       while (epout_has_pkt(ep)) {
+               count = read_packet(ep, req);
+               ep_write_UDCCSR(ep, UDCCSR0_OPC);
+               inc_ep_stats_bytes(ep, count, !USB_DIR_IN);
+
+               is_short = (count < ep->fifo_size);
+               ep_dbg(ep, "read udccsr:%03x, count:%d bytes%s req %p %d/%d\n",
+                       udc_ep_readl(ep, UDCCSR), count, is_short ? "/S" : "",
+                       &req->req, req->req.actual, req->req.length);
+
+               if (is_short || req->req.actual >= req->req.length) {
+                       completed = 1;
+                       break;
+               }
+       }
+
+       return completed;
+}
+
+/**
+ * write_ep0_fifo - Send a request to control endpoint (ep0 in)
+ * @ep: control endpoint
+ * @req: request
+ *
+ * Context: callable when in_interrupt()
+ *
+ * Sends a request (or a part of the request) to the control endpoint (ep0 in).
+ * If the request doesn't fit, the remaining part will be sent from irq.
+ * The request is considered fully written only if either :
+ *   - last write transferred all remaining bytes, but fifo was not fully filled
+ *   - last write was a 0 length write
+ *
+ * Returns 1 if request fully written, 0 if request only partially sent
+ */
+static int write_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
+{
+       unsigned        count;
+       int             is_last, is_short;
+
+       count = write_packet(ep, req, EP0_FIFO_SIZE);
+       inc_ep_stats_bytes(ep, count, USB_DIR_IN);
+
+       is_short = (count < EP0_FIFO_SIZE);
+       is_last = ((count == 0) || (count < EP0_FIFO_SIZE));
+
+       /* Sends either a short packet or a 0 length packet */
+       if (unlikely(is_short))
+               ep_write_UDCCSR(ep, UDCCSR0_IPR);
+
+       ep_dbg(ep, "in %d bytes%s%s, %d left, req=%p, udccsr0=0x%03x\n",
+               count, is_short ? "/S" : "", is_last ? "/L" : "",
+               req->req.length - req->req.actual,
+               &req->req, udc_ep_readl(ep, UDCCSR));
+
+       return is_last;
+}
+
+/**
+ * pxa_ep_queue - Queue a request into an IN endpoint
+ * @_ep: usb endpoint
+ * @_req: usb request
+ * @gfp_flags: flags
+ *
+ * Context: normally called when !in_interrupt, but callable when in_interrupt()
+ * in the special case of ep0 setup :
+ *   (irq->handle_ep0_ctrl_req->gadget_setup->pxa_ep_queue)
+ *
+ * Returns 0 if succedeed, error otherwise
+ */
+static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
+                       gfp_t gfp_flags)
+{
+       struct udc_usb_ep       *udc_usb_ep;
+       struct pxa_ep           *ep;
+       struct pxa27x_request   *req;
+       struct pxa_udc          *dev;
+       unsigned long           flags;
+       int                     rc = 0;
+       int                     is_first_req;
+       unsigned                length;
+       int                     recursion_detected;
+
+       req = container_of(_req, struct pxa27x_request, req);
+       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+
+       if (unlikely(!_req || !_req->complete || !_req->buf))
+               return -EINVAL;
+
+       if (unlikely(!_ep))
+               return -EINVAL;
+
+       dev = udc_usb_ep->dev;
+       ep = udc_usb_ep->pxa_ep;
+       if (unlikely(!ep))
+               return -EINVAL;
+
+       dev = ep->dev;
+       if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+               ep_dbg(ep, "bogus device state\n");
+               return -ESHUTDOWN;
+       }
+
+       /* iso is always one packet per request, that's the only way
+        * we can report per-packet status.  that also helps with dma.
+        */
+       if (unlikely(EPXFERTYPE_is_ISO(ep)
+                       && req->req.length > ep->fifo_size))
+               return -EMSGSIZE;
+
+       spin_lock_irqsave(&ep->lock, flags);
+       recursion_detected = ep->in_handle_ep;
+
+       is_first_req = list_empty(&ep->queue);
+       ep_dbg(ep, "queue req %p(first=%s), len %d buf %p\n",
+                       _req, is_first_req ? "yes" : "no",
+                       _req->length, _req->buf);
+
+       if (!ep->enabled) {
+               _req->status = -ESHUTDOWN;
+               rc = -ESHUTDOWN;
+               goto out_locked;
+       }
+
+       if (req->in_use) {
+               ep_err(ep, "refusing to queue req %p (already queued)\n", req);
+               goto out_locked;
+       }
+
+       length = _req->length;
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       ep_add_request(ep, req);
+       spin_unlock_irqrestore(&ep->lock, flags);
+
+       if (is_ep0(ep)) {
+               switch (dev->ep0state) {
+               case WAIT_ACK_SET_CONF_INTERF:
+                       if (length == 0) {
+                               ep_end_in_req(ep, req, NULL);
+                       } else {
+                               ep_err(ep, "got a request of %d bytes while"
+                                       "in state WAIT_ACK_SET_CONF_INTERF\n",
+                                       length);
+                               ep_del_request(ep, req);
+                               rc = -EL2HLT;
+                       }
+                       ep0_idle(ep->dev);
+                       break;
+               case IN_DATA_STAGE:
+                       if (!ep_is_full(ep))
+                               if (write_ep0_fifo(ep, req))
+                                       ep0_end_in_req(ep, req, NULL);
+                       break;
+               case OUT_DATA_STAGE:
+                       if ((length == 0) || !epout_has_pkt(ep))
+                               if (read_ep0_fifo(ep, req))
+                                       ep0_end_out_req(ep, req, NULL);
+                       break;
+               default:
+                       ep_err(ep, "odd state %s to send me a request\n",
+                               EP0_STNAME(ep->dev));
+                       ep_del_request(ep, req);
+                       rc = -EL2HLT;
+                       break;
+               }
+       } else {
+               if (!recursion_detected)
+                       handle_ep(ep);
+       }
+
+out:
+       return rc;
+out_locked:
+       spin_unlock_irqrestore(&ep->lock, flags);
+       goto out;
+}
+
+/**
+ * pxa_ep_dequeue - Dequeue one request
+ * @_ep: usb endpoint
+ * @_req: usb request
+ *
+ * Return 0 if no error, -EINVAL or -ECONNRESET otherwise
+ */
+static int pxa_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct pxa_ep           *ep;
+       struct udc_usb_ep       *udc_usb_ep;
+       struct pxa27x_request   *req;
+       unsigned long           flags;
+       int                     rc = -EINVAL;
+
+       if (!_ep)
+               return rc;
+       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+       ep = udc_usb_ep->pxa_ep;
+       if (!ep || is_ep0(ep))
+               return rc;
+
+       spin_lock_irqsave(&ep->lock, flags);
+
+       /* make sure it's actually queued on this endpoint */
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req) {
+                       rc = 0;
+                       break;
+               }
+       }
+
+       spin_unlock_irqrestore(&ep->lock, flags);
+       if (!rc)
+               req_done(ep, req, -ECONNRESET, NULL);
+       return rc;
+}
+
+/**
+ * pxa_ep_set_halt - Halts operations on one endpoint
+ * @_ep: usb endpoint
+ * @value:
+ *
+ * Returns 0 if no error, -EINVAL, -EROFS, -EAGAIN otherwise
+ */
+static int pxa_ep_set_halt(struct usb_ep *_ep, int value)
+{
+       struct pxa_ep           *ep;
+       struct udc_usb_ep       *udc_usb_ep;
+       unsigned long flags;
+       int rc;
+
+
+       if (!_ep)
+               return -EINVAL;
+       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+       ep = udc_usb_ep->pxa_ep;
+       if (!ep || is_ep0(ep))
+               return -EINVAL;
+
+       if (value == 0) {
+               /*
+                * This path (reset toggle+halt) is needed to implement
+                * SET_INTERFACE on normal hardware.  but it can't be
+                * done from software on the PXA UDC, and the hardware
+                * forgets to do it as part of SET_INTERFACE automagic.
+                */
+               ep_dbg(ep, "only host can clear halt\n");
+               return -EROFS;
+       }
+
+       spin_lock_irqsave(&ep->lock, flags);
+
+       rc = -EAGAIN;
+       if (ep->dir_in  && (ep_is_full(ep) || !list_empty(&ep->queue)))
+               goto out;
+
+       /* FST, FEF bits are the same for control and non control endpoints */
+       rc = 0;
+       ep_write_UDCCSR(ep, UDCCSR_FST | UDCCSR_FEF);
+       if (is_ep0(ep))
+               set_ep0state(ep->dev, STALL);
+
+out:
+       spin_unlock_irqrestore(&ep->lock, flags);
+       return rc;
+}
+
+/**
+ * pxa_ep_fifo_status - Get how many bytes in physical endpoint
+ * @_ep: usb endpoint
+ *
+ * Returns number of bytes in OUT fifos. Broken for IN fifos.
+ */
+static int pxa_ep_fifo_status(struct usb_ep *_ep)
+{
+       struct pxa_ep           *ep;
+       struct udc_usb_ep       *udc_usb_ep;
+
+       if (!_ep)
+               return -ENODEV;
+       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+       ep = udc_usb_ep->pxa_ep;
+       if (!ep || is_ep0(ep))
+               return -ENODEV;
+
+       if (ep->dir_in)
+               return -EOPNOTSUPP;
+       if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN || ep_is_empty(ep))
+               return 0;
+       else
+               return ep_count_bytes_remain(ep) + 1;
+}
+
+/**
+ * pxa_ep_fifo_flush - Flushes one endpoint
+ * @_ep: usb endpoint
+ *
+ * Discards all data in one endpoint(IN or OUT), except control endpoint.
+ */
+static void pxa_ep_fifo_flush(struct usb_ep *_ep)
+{
+       struct pxa_ep           *ep;
+       struct udc_usb_ep       *udc_usb_ep;
+       unsigned long           flags;
+
+       if (!_ep)
+               return;
+       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+       ep = udc_usb_ep->pxa_ep;
+       if (!ep || is_ep0(ep))
+               return;
+
+       spin_lock_irqsave(&ep->lock, flags);
+
+       if (unlikely(!list_empty(&ep->queue)))
+               ep_dbg(ep, "called while queue list not empty\n");
+       ep_dbg(ep, "called\n");
+
+       /* for OUT, just read and discard the FIFO contents. */
+       if (!ep->dir_in) {
+               while (!ep_is_empty(ep))
+                       udc_ep_readl(ep, UDCDR);
+       } else {
+               /* most IN status is the same, but ISO can't stall */
+               ep_write_UDCCSR(ep,
+                               UDCCSR_PC | UDCCSR_FEF | UDCCSR_TRN
+                               | (EPXFERTYPE_is_ISO(ep) ? 0 : UDCCSR_SST));
+       }
+
+       spin_unlock_irqrestore(&ep->lock, flags);
+}
+
+/**
+ * pxa_ep_enable - Enables usb endpoint
+ * @_ep: usb endpoint
+ * @desc: usb endpoint descriptor
+ *
+ * Nothing much to do here, as ep configuration is done once and for all
+ * before udc is enabled. After udc enable, no physical endpoint configuration
+ * can be changed.
+ * Function makes sanity checks and flushes the endpoint.
+ */
+static int pxa_ep_enable(struct usb_ep *_ep,
+       const struct usb_endpoint_descriptor *desc)
+{
+       struct pxa_ep           *ep;
+       struct udc_usb_ep       *udc_usb_ep;
+       struct pxa_udc          *udc;
+
+       if (!_ep || !desc)
+               return -EINVAL;
+
+       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+       if (udc_usb_ep->pxa_ep) {
+               ep = udc_usb_ep->pxa_ep;
+               ep_warn(ep, "usb_ep %s already enabled, doing nothing\n",
+                       _ep->name);
+       } else {
+               ep = find_pxa_ep(udc_usb_ep->dev, udc_usb_ep);
+       }
+
+       if (!ep || is_ep0(ep)) {
+               dev_err(udc_usb_ep->dev->dev,
+                       "unable to match pxa_ep for ep %s\n",
+                       _ep->name);
+               return -EINVAL;
+       }
+
+       if ((desc->bDescriptorType != USB_DT_ENDPOINT)
+                       || (ep->type != usb_endpoint_type(desc))) {
+               ep_err(ep, "type mismatch\n");
+               return -EINVAL;
+       }
+
+       if (ep->fifo_size < usb_endpoint_maxp(desc)) {
+               ep_err(ep, "bad maxpacket\n");
+               return -ERANGE;
+       }
+
+       udc_usb_ep->pxa_ep = ep;
+       udc = ep->dev;
+
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+               ep_err(ep, "bogus device state\n");
+               return -ESHUTDOWN;
+       }
+
+       ep->enabled = 1;
+
+       /* flush fifo (mostly for OUT buffers) */
+       pxa_ep_fifo_flush(_ep);
+
+       ep_dbg(ep, "enabled\n");
+       return 0;
+}
+
+/**
+ * pxa_ep_disable - Disable usb endpoint
+ * @_ep: usb endpoint
+ *
+ * Same as for pxa_ep_enable, no physical endpoint configuration can be
+ * changed.
+ * Function flushes the endpoint and related requests.
+ */
+static int pxa_ep_disable(struct usb_ep *_ep)
+{
+       struct pxa_ep           *ep;
+       struct udc_usb_ep       *udc_usb_ep;
+
+       if (!_ep)
+               return -EINVAL;
+
+       udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
+       ep = udc_usb_ep->pxa_ep;
+       if (!ep || is_ep0(ep) || !list_empty(&ep->queue))
+               return -EINVAL;
+
+       ep->enabled = 0;
+       nuke(ep, -ESHUTDOWN);
+
+       pxa_ep_fifo_flush(_ep);
+       udc_usb_ep->pxa_ep = NULL;
+
+       ep_dbg(ep, "disabled\n");
+       return 0;
+}
+
+static struct usb_ep_ops pxa_ep_ops = {
+       .enable         = pxa_ep_enable,
+       .disable        = pxa_ep_disable,
+
+       .alloc_request  = pxa_ep_alloc_request,
+       .free_request   = pxa_ep_free_request,
+
+       .queue          = pxa_ep_queue,
+       .dequeue        = pxa_ep_dequeue,
+
+       .set_halt       = pxa_ep_set_halt,
+       .fifo_status    = pxa_ep_fifo_status,
+       .fifo_flush     = pxa_ep_fifo_flush,
+};
+
+/**
+ * dplus_pullup - Connect or disconnect pullup resistor to D+ pin
+ * @udc: udc device
+ * @on: 0 if disconnect pullup resistor, 1 otherwise
+ * Context: any
+ *
+ * Handle D+ pullup resistor, make the device visible to the usb bus, and
+ * declare it as a full speed usb device
+ */
+static void dplus_pullup(struct pxa_udc *udc, int on)
+{
+       if (on) {
+               if (gpio_is_valid(udc->mach->gpio_pullup))
+                       gpio_set_value(udc->mach->gpio_pullup,
+                                      !udc->mach->gpio_pullup_inverted);
+               if (udc->mach->udc_command)
+                       udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+       } else {
+               if (gpio_is_valid(udc->mach->gpio_pullup))
+                       gpio_set_value(udc->mach->gpio_pullup,
+                                      udc->mach->gpio_pullup_inverted);
+               if (udc->mach->udc_command)
+                       udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+       }
+       udc->pullup_on = on;
+}
+
+/**
+ * pxa_udc_get_frame - Returns usb frame number
+ * @_gadget: usb gadget
+ */
+static int pxa_udc_get_frame(struct usb_gadget *_gadget)
+{
+       struct pxa_udc *udc = to_gadget_udc(_gadget);
+
+       return (udc_readl(udc, UDCFNR) & 0x7ff);
+}
+
+/**
+ * pxa_udc_wakeup - Force udc device out of suspend
+ * @_gadget: usb gadget
+ *
+ * Returns 0 if successful, error code otherwise
+ */
+static int pxa_udc_wakeup(struct usb_gadget *_gadget)
+{
+       struct pxa_udc *udc = to_gadget_udc(_gadget);
+
+       /* host may not have enabled remote wakeup */
+       if ((udc_readl(udc, UDCCR) & UDCCR_DWRE) == 0)
+               return -EHOSTUNREACH;
+       udc_set_mask_UDCCR(udc, UDCCR_UDR);
+       return 0;
+}
+
+static void udc_enable(struct pxa_udc *udc);
+static void udc_disable(struct pxa_udc *udc);
+
+/**
+ * should_enable_udc - Tells if UDC should be enabled
+ * @udc: udc device
+ * Context: any
+ *
+ * The UDC should be enabled if :
+
+ *  - the pullup resistor is connected
+ *  - and a gadget driver is bound
+ *  - and vbus is sensed (or no vbus sense is available)
+ *
+ * Returns 1 if UDC should be enabled, 0 otherwise
+ */
+static int should_enable_udc(struct pxa_udc *udc)
+{
+       int put_on;
+
+       put_on = ((udc->pullup_on) && (udc->driver));
+       put_on &= ((udc->vbus_sensed) || (IS_ERR_OR_NULL(udc->transceiver)));
+       return put_on;
+}
+
+/**
+ * should_disable_udc - Tells if UDC should be disabled
+ * @udc: udc device
+ * Context: any
+ *
+ * The UDC should be disabled if :
+ *  - the pullup resistor is not connected
+ *  - or no gadget driver is bound
+ *  - or no vbus is sensed (when vbus sesing is available)
+ *
+ * Returns 1 if UDC should be disabled
+ */
+static int should_disable_udc(struct pxa_udc *udc)
+{
+       int put_off;
+
+       put_off = ((!udc->pullup_on) || (!udc->driver));
+       put_off |= ((!udc->vbus_sensed) && (!IS_ERR_OR_NULL(udc->transceiver)));
+       return put_off;
+}
+
+/**
+ * pxa_udc_pullup - Offer manual D+ pullup control
+ * @_gadget: usb gadget using the control
+ * @is_active: 0 if disconnect, else connect D+ pullup resistor
+ * Context: !in_interrupt()
+ *
+ * Returns 0 if OK, -EOPNOTSUPP if udc driver doesn't handle D+ pullup
+ */
+static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active)
+{
+       struct pxa_udc *udc = to_gadget_udc(_gadget);
+
+       if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
+               return -EOPNOTSUPP;
+
+       dplus_pullup(udc, is_active);
+
+       if (should_enable_udc(udc))
+               udc_enable(udc);
+       if (should_disable_udc(udc))
+               udc_disable(udc);
+       return 0;
+}
+
+static void udc_enable(struct pxa_udc *udc);
+static void udc_disable(struct pxa_udc *udc);
+
+/**
+ * pxa_udc_vbus_session - Called by external transceiver to enable/disable udc
+ * @_gadget: usb gadget
+ * @is_active: 0 if should disable the udc, 1 if should enable
+ *
+ * Enables the udc, and optionnaly activates D+ pullup resistor. Or disables the
+ * udc, and deactivates D+ pullup resistor.
+ *
+ * Returns 0
+ */
+static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
+{
+       struct pxa_udc *udc = to_gadget_udc(_gadget);
+
+       udc->vbus_sensed = is_active;
+       if (should_enable_udc(udc))
+               udc_enable(udc);
+       if (should_disable_udc(udc))
+               udc_disable(udc);
+
+       return 0;
+}
+
+/**
+ * pxa_udc_vbus_draw - Called by gadget driver after SET_CONFIGURATION completed
+ * @_gadget: usb gadget
+ * @mA: current drawn
+ *
+ * Context: !in_interrupt()
+ *
+ * Called after a configuration was chosen by a USB host, to inform how much
+ * current can be drawn by the device from VBus line.
+ *
+ * Returns 0 or -EOPNOTSUPP if no transceiver is handling the udc
+ */
+static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
+{
+       struct pxa_udc *udc;
+
+       udc = to_gadget_udc(_gadget);
+       if (!IS_ERR_OR_NULL(udc->transceiver))
+               return usb_phy_set_power(udc->transceiver, mA);
+       return -EOPNOTSUPP;
+}
+
+static int pxa27x_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+static int pxa27x_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+
+static const struct usb_gadget_ops pxa_udc_ops = {
+       .get_frame      = pxa_udc_get_frame,
+       .wakeup         = pxa_udc_wakeup,
+       .pullup         = pxa_udc_pullup,
+       .vbus_session   = pxa_udc_vbus_session,
+       .vbus_draw      = pxa_udc_vbus_draw,
+       .udc_start      = pxa27x_udc_start,
+       .udc_stop       = pxa27x_udc_stop,
+};
+
+/**
+ * udc_disable - disable udc device controller
+ * @udc: udc device
+ * Context: any
+ *
+ * Disables the udc device : disables clocks, udc interrupts, control endpoint
+ * interrupts.
+ */
+static void udc_disable(struct pxa_udc *udc)
+{
+       if (!udc->enabled)
+               return;
+
+       udc_writel(udc, UDCICR0, 0);
+       udc_writel(udc, UDCICR1, 0);
+
+       udc_clear_mask_UDCCR(udc, UDCCR_UDE);
+       clk_disable(udc->clk);
+
+       ep0_idle(udc);
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+
+       udc->enabled = 0;
+}
+
+/**
+ * udc_init_data - Initialize udc device data structures
+ * @dev: udc device
+ *
+ * Initializes gadget endpoint list, endpoints locks. No action is taken
+ * on the hardware.
+ */
+static void udc_init_data(struct pxa_udc *dev)
+{
+       int i;
+       struct pxa_ep *ep;
+
+       /* device/ep0 records init */
+       INIT_LIST_HEAD(&dev->gadget.ep_list);
+       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+       dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0];
+       ep0_idle(dev);
+
+       /* PXA endpoints init */
+       for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
+               ep = &dev->pxa_ep[i];
+
+               ep->enabled = is_ep0(ep);
+               INIT_LIST_HEAD(&ep->queue);
+               spin_lock_init(&ep->lock);
+       }
+
+       /* USB endpoints init */
+       for (i = 1; i < NR_USB_ENDPOINTS; i++) {
+               list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list,
+                               &dev->gadget.ep_list);
+               usb_ep_set_maxpacket_limit(&dev->udc_usb_ep[i].usb_ep,
+                                          dev->udc_usb_ep[i].usb_ep.maxpacket);
+       }
+}
+
+/**
+ * udc_enable - Enables the udc device
+ * @dev: udc device
+ *
+ * Enables the udc device : enables clocks, udc interrupts, control endpoint
+ * interrupts, sets usb as UDC client and setups endpoints.
+ */
+static void udc_enable(struct pxa_udc *udc)
+{
+       if (udc->enabled)
+               return;
+
+       udc_writel(udc, UDCICR0, 0);
+       udc_writel(udc, UDCICR1, 0);
+       udc_clear_mask_UDCCR(udc, UDCCR_UDE);
+
+       clk_enable(udc->clk);
+
+       ep0_idle(udc);
+       udc->gadget.speed = USB_SPEED_FULL;
+       memset(&udc->stats, 0, sizeof(udc->stats));
+
+       udc_set_mask_UDCCR(udc, UDCCR_UDE);
+       ep_write_UDCCSR(&udc->pxa_ep[0], UDCCSR0_ACM);
+       udelay(2);
+       if (udc_readl(udc, UDCCR) & UDCCR_EMCE)
+               dev_err(udc->dev, "Configuration errors, udc disabled\n");
+
+       /*
+        * Caller must be able to sleep in order to cope with startup transients
+        */
+       msleep(100);
+
+       /* enable suspend/resume and reset irqs */
+       udc_writel(udc, UDCICR1,
+                       UDCICR1_IECC | UDCICR1_IERU
+                       | UDCICR1_IESU | UDCICR1_IERS);
+
+       /* enable ep0 irqs */
+       pio_irq_enable(&udc->pxa_ep[0]);
+
+       udc->enabled = 1;
+}
+
+/**
+ * pxa27x_start - Register gadget driver
+ * @driver: gadget driver
+ * @bind: bind function
+ *
+ * When a driver is successfully registered, it will receive control requests
+ * including set_configuration(), which enables non-control requests.  Then
+ * usb traffic follows until a disconnect is reported.  Then a host may connect
+ * again, or the driver might get unbound.
+ *
+ * Note that the udc is not automatically enabled. Check function
+ * should_enable_udc().
+ *
+ * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
+ */
+static int pxa27x_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct pxa_udc *udc = to_pxa(g);
+       int retval;
+
+       /* first hook up the driver ... */
+       udc->driver = driver;
+       dplus_pullup(udc, 1);
+
+       if (!IS_ERR_OR_NULL(udc->transceiver)) {
+               retval = otg_set_peripheral(udc->transceiver->otg,
+                                               &udc->gadget);
+               if (retval) {
+                       dev_err(udc->dev, "can't bind to transceiver\n");
+                       goto fail;
+               }
+       }
+
+       if (should_enable_udc(udc))
+               udc_enable(udc);
+       return 0;
+
+fail:
+       udc->driver = NULL;
+       return retval;
+}
+
+/**
+ * stop_activity - Stops udc endpoints
+ * @udc: udc device
+ * @driver: gadget driver
+ *
+ * Disables all udc endpoints (even control endpoint), report disconnect to
+ * the gadget user.
+ */
+static void stop_activity(struct pxa_udc *udc, struct usb_gadget_driver *driver)
+{
+       int i;
+
+       /* don't disconnect drivers more than once */
+       if (udc->gadget.speed == USB_SPEED_UNKNOWN)
+               driver = NULL;
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+
+       for (i = 0; i < NR_USB_ENDPOINTS; i++)
+               pxa_ep_disable(&udc->udc_usb_ep[i].usb_ep);
+}
+
+/**
+ * pxa27x_udc_stop - Unregister the gadget driver
+ * @driver: gadget driver
+ *
+ * Returns 0 if no error, -ENODEV, -EINVAL otherwise
+ */
+static int pxa27x_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct pxa_udc *udc = to_pxa(g);
+
+       stop_activity(udc, driver);
+       udc_disable(udc);
+       dplus_pullup(udc, 0);
+
+       udc->driver = NULL;
+
+       if (!IS_ERR_OR_NULL(udc->transceiver))
+               return otg_set_peripheral(udc->transceiver->otg, NULL);
+       return 0;
+}
+
+/**
+ * handle_ep0_ctrl_req - handle control endpoint control request
+ * @udc: udc device
+ * @req: control request
+ */
+static void handle_ep0_ctrl_req(struct pxa_udc *udc,
+                               struct pxa27x_request *req)
+{
+       struct pxa_ep *ep = &udc->pxa_ep[0];
+       union {
+               struct usb_ctrlrequest  r;
+               u32                     word[2];
+       } u;
+       int i;
+       int have_extrabytes = 0;
+       unsigned long flags;
+
+       nuke(ep, -EPROTO);
+       spin_lock_irqsave(&ep->lock, flags);
+
+       /*
+        * In the PXA320 manual, in the section about Back-to-Back setup
+        * packets, it describes this situation.  The solution is to set OPC to
+        * get rid of the status packet, and then continue with the setup
+        * packet. Generalize to pxa27x CPUs.
+        */
+       if (epout_has_pkt(ep) && (ep_count_bytes_remain(ep) == 0))
+               ep_write_UDCCSR(ep, UDCCSR0_OPC);
+
+       /* read SETUP packet */
+       for (i = 0; i < 2; i++) {
+               if (unlikely(ep_is_empty(ep)))
+                       goto stall;
+               u.word[i] = udc_ep_readl(ep, UDCDR);
+       }
+
+       have_extrabytes = !ep_is_empty(ep);
+       while (!ep_is_empty(ep)) {
+               i = udc_ep_readl(ep, UDCDR);
+               ep_err(ep, "wrong to have extra bytes for setup : 0x%08x\n", i);
+       }
+
+       ep_dbg(ep, "SETUP %02x.%02x v%04x i%04x l%04x\n",
+               u.r.bRequestType, u.r.bRequest,
+               le16_to_cpu(u.r.wValue), le16_to_cpu(u.r.wIndex),
+               le16_to_cpu(u.r.wLength));
+       if (unlikely(have_extrabytes))
+               goto stall;
+
+       if (u.r.bRequestType & USB_DIR_IN)
+               set_ep0state(udc, IN_DATA_STAGE);
+       else
+               set_ep0state(udc, OUT_DATA_STAGE);
+
+       /* Tell UDC to enter Data Stage */
+       ep_write_UDCCSR(ep, UDCCSR0_SA | UDCCSR0_OPC);
+
+       spin_unlock_irqrestore(&ep->lock, flags);
+       i = udc->driver->setup(&udc->gadget, &u.r);
+       spin_lock_irqsave(&ep->lock, flags);
+       if (i < 0)
+               goto stall;
+out:
+       spin_unlock_irqrestore(&ep->lock, flags);
+       return;
+stall:
+       ep_dbg(ep, "protocol STALL, udccsr0=%03x err %d\n",
+               udc_ep_readl(ep, UDCCSR), i);
+       ep_write_UDCCSR(ep, UDCCSR0_FST | UDCCSR0_FTF);
+       set_ep0state(udc, STALL);
+       goto out;
+}
+
+/**
+ * handle_ep0 - Handle control endpoint data transfers
+ * @udc: udc device
+ * @fifo_irq: 1 if triggered by fifo service type irq
+ * @opc_irq: 1 if triggered by output packet complete type irq
+ *
+ * Context : when in_interrupt() or with ep->lock held
+ *
+ * Tries to transfer all pending request data into the endpoint and/or
+ * transfer all pending data in the endpoint into usb requests.
+ * Handles states of ep0 automata.
+ *
+ * PXA27x hardware handles several standard usb control requests without
+ * driver notification.  The requests fully handled by hardware are :
+ *  SET_ADDRESS, SET_FEATURE, CLEAR_FEATURE, GET_CONFIGURATION, GET_INTERFACE,
+ *  GET_STATUS
+ * The requests handled by hardware, but with irq notification are :
+ *  SYNCH_FRAME, SET_CONFIGURATION, SET_INTERFACE
+ * The remaining standard requests really handled by handle_ep0 are :
+ *  GET_DESCRIPTOR, SET_DESCRIPTOR, specific requests.
+ * Requests standardized outside of USB 2.0 chapter 9 are handled more
+ * uniformly, by gadget drivers.
+ *
+ * The control endpoint state machine is _not_ USB spec compliant, it's even
+ * hardly compliant with Intel PXA270 developers guide.
+ * The key points which inferred this state machine are :
+ *   - on every setup token, bit UDCCSR0_SA is raised and held until cleared by
+ *     software.
+ *   - on every OUT packet received, UDCCSR0_OPC is raised and held until
+ *     cleared by software.
+ *   - clearing UDCCSR0_OPC always flushes ep0. If in setup stage, never do it
+ *     before reading ep0.
+ *     This is true only for PXA27x. This is not true anymore for PXA3xx family
+ *     (check Back-to-Back setup packet in developers guide).
+ *   - irq can be called on a "packet complete" event (opc_irq=1), while
+ *     UDCCSR0_OPC is not yet raised (delta can be as big as 100ms
+ *     from experimentation).
+ *   - as UDCCSR0_SA can be activated while in irq handling, and clearing
+ *     UDCCSR0_OPC would flush the setup data, we almost never clear UDCCSR0_OPC
+ *     => we never actually read the "status stage" packet of an IN data stage
+ *     => this is not documented in Intel documentation
+ *   - hardware as no idea of STATUS STAGE, it only handle SETUP STAGE and DATA
+ *     STAGE. The driver add STATUS STAGE to send last zero length packet in
+ *     OUT_STATUS_STAGE.
+ *   - special attention was needed for IN_STATUS_STAGE. If a packet complete
+ *     event is detected, we terminate the status stage without ackowledging the
+ *     packet (not to risk to loose a potential SETUP packet)
+ */
+static void handle_ep0(struct pxa_udc *udc, int fifo_irq, int opc_irq)
+{
+       u32                     udccsr0;
+       struct pxa_ep           *ep = &udc->pxa_ep[0];
+       struct pxa27x_request   *req = NULL;
+       int                     completed = 0;
+
+       if (!list_empty(&ep->queue))
+               req = list_entry(ep->queue.next, struct pxa27x_request, queue);
+
+       udccsr0 = udc_ep_readl(ep, UDCCSR);
+       ep_dbg(ep, "state=%s, req=%p, udccsr0=0x%03x, udcbcr=%d, irq_msk=%x\n",
+               EP0_STNAME(udc), req, udccsr0, udc_ep_readl(ep, UDCBCR),
+               (fifo_irq << 1 | opc_irq));
+
+       if (udccsr0 & UDCCSR0_SST) {
+               ep_dbg(ep, "clearing stall status\n");
+               nuke(ep, -EPIPE);
+               ep_write_UDCCSR(ep, UDCCSR0_SST);
+               ep0_idle(udc);
+       }
+
+       if (udccsr0 & UDCCSR0_SA) {
+               nuke(ep, 0);
+               set_ep0state(udc, SETUP_STAGE);
+       }
+
+       switch (udc->ep0state) {
+       case WAIT_FOR_SETUP:
+               /*
+                * Hardware bug : beware, we cannot clear OPC, since we would
+                * miss a potential OPC irq for a setup packet.
+                * So, we only do ... nothing, and hope for a next irq with
+                * UDCCSR0_SA set.
+                */
+               break;
+       case SETUP_STAGE:
+               udccsr0 &= UDCCSR0_CTRL_REQ_MASK;
+               if (likely(udccsr0 == UDCCSR0_CTRL_REQ_MASK))
+                       handle_ep0_ctrl_req(udc, req);
+               break;
+       case IN_DATA_STAGE:                     /* GET_DESCRIPTOR */
+               if (epout_has_pkt(ep))
+                       ep_write_UDCCSR(ep, UDCCSR0_OPC);
+               if (req && !ep_is_full(ep))
+                       completed = write_ep0_fifo(ep, req);
+               if (completed)
+                       ep0_end_in_req(ep, req, NULL);
+               break;
+       case OUT_DATA_STAGE:                    /* SET_DESCRIPTOR */
+               if (epout_has_pkt(ep) && req)
+                       completed = read_ep0_fifo(ep, req);
+               if (completed)
+                       ep0_end_out_req(ep, req, NULL);
+               break;
+       case STALL:
+               ep_write_UDCCSR(ep, UDCCSR0_FST);
+               break;
+       case IN_STATUS_STAGE:
+               /*
+                * Hardware bug : beware, we cannot clear OPC, since we would
+                * miss a potential PC irq for a setup packet.
+                * So, we only put the ep0 into WAIT_FOR_SETUP state.
+                */
+               if (opc_irq)
+                       ep0_idle(udc);
+               break;
+       case OUT_STATUS_STAGE:
+       case WAIT_ACK_SET_CONF_INTERF:
+               ep_warn(ep, "should never get in %s state here!!!\n",
+                               EP0_STNAME(ep->dev));
+               ep0_idle(udc);
+               break;
+       }
+}
+
+/**
+ * handle_ep - Handle endpoint data tranfers
+ * @ep: pxa physical endpoint
+ *
+ * Tries to transfer all pending request data into the endpoint and/or
+ * transfer all pending data in the endpoint into usb requests.
+ *
+ * Is always called when in_interrupt() and with ep->lock released.
+ */
+static void handle_ep(struct pxa_ep *ep)
+{
+       struct pxa27x_request   *req;
+       int completed;
+       u32 udccsr;
+       int is_in = ep->dir_in;
+       int loop = 0;
+       unsigned long           flags;
+
+       spin_lock_irqsave(&ep->lock, flags);
+       if (ep->in_handle_ep)
+               goto recursion_detected;
+       ep->in_handle_ep = 1;
+
+       do {
+               completed = 0;
+               udccsr = udc_ep_readl(ep, UDCCSR);
+
+               if (likely(!list_empty(&ep->queue)))
+                       req = list_entry(ep->queue.next,
+                                       struct pxa27x_request, queue);
+               else
+                       req = NULL;
+
+               ep_dbg(ep, "req:%p, udccsr 0x%03x loop=%d\n",
+                               req, udccsr, loop++);
+
+               if (unlikely(udccsr & (UDCCSR_SST | UDCCSR_TRN)))
+                       udc_ep_writel(ep, UDCCSR,
+                                       udccsr & (UDCCSR_SST | UDCCSR_TRN));
+               if (!req)
+                       break;
+
+               if (unlikely(is_in)) {
+                       if (likely(!ep_is_full(ep)))
+                               completed = write_fifo(ep, req);
+               } else {
+                       if (likely(epout_has_pkt(ep)))
+                               completed = read_fifo(ep, req);
+               }
+
+               if (completed) {
+                       if (is_in)
+                               ep_end_in_req(ep, req, &flags);
+                       else
+                               ep_end_out_req(ep, req, &flags);
+               }
+       } while (completed);
+
+       ep->in_handle_ep = 0;
+recursion_detected:
+       spin_unlock_irqrestore(&ep->lock, flags);
+}
+
+/**
+ * pxa27x_change_configuration - Handle SET_CONF usb request notification
+ * @udc: udc device
+ * @config: usb configuration
+ *
+ * Post the request to upper level.
+ * Don't use any pxa specific harware configuration capabilities
+ */
+static void pxa27x_change_configuration(struct pxa_udc *udc, int config)
+{
+       struct usb_ctrlrequest req ;
+
+       dev_dbg(udc->dev, "config=%d\n", config);
+
+       udc->config = config;
+       udc->last_interface = 0;
+       udc->last_alternate = 0;
+
+       req.bRequestType = 0;
+       req.bRequest = USB_REQ_SET_CONFIGURATION;
+       req.wValue = config;
+       req.wIndex = 0;
+       req.wLength = 0;
+
+       set_ep0state(udc, WAIT_ACK_SET_CONF_INTERF);
+       udc->driver->setup(&udc->gadget, &req);
+       ep_write_UDCCSR(&udc->pxa_ep[0], UDCCSR0_AREN);
+}
+
+/**
+ * pxa27x_change_interface - Handle SET_INTERF usb request notification
+ * @udc: udc device
+ * @iface: interface number
+ * @alt: alternate setting number
+ *
+ * Post the request to upper level.
+ * Don't use any pxa specific harware configuration capabilities
+ */
+static void pxa27x_change_interface(struct pxa_udc *udc, int iface, int alt)
+{
+       struct usb_ctrlrequest  req;
+
+       dev_dbg(udc->dev, "interface=%d, alternate setting=%d\n", iface, alt);
+
+       udc->last_interface = iface;
+       udc->last_alternate = alt;
+
+       req.bRequestType = USB_RECIP_INTERFACE;
+       req.bRequest = USB_REQ_SET_INTERFACE;
+       req.wValue = alt;
+       req.wIndex = iface;
+       req.wLength = 0;
+
+       set_ep0state(udc, WAIT_ACK_SET_CONF_INTERF);
+       udc->driver->setup(&udc->gadget, &req);
+       ep_write_UDCCSR(&udc->pxa_ep[0], UDCCSR0_AREN);
+}
+
+/*
+ * irq_handle_data - Handle data transfer
+ * @irq: irq IRQ number
+ * @udc: dev pxa_udc device structure
+ *
+ * Called from irq handler, transferts data to or from endpoint to queue
+ */
+static void irq_handle_data(int irq, struct pxa_udc *udc)
+{
+       int i;
+       struct pxa_ep *ep;
+       u32 udcisr0 = udc_readl(udc, UDCISR0) & UDCCISR0_EP_MASK;
+       u32 udcisr1 = udc_readl(udc, UDCISR1) & UDCCISR1_EP_MASK;
+
+       if (udcisr0 & UDCISR_INT_MASK) {
+               udc->pxa_ep[0].stats.irqs++;
+               udc_writel(udc, UDCISR0, UDCISR_INT(0, UDCISR_INT_MASK));
+               handle_ep0(udc, !!(udcisr0 & UDCICR_FIFOERR),
+                               !!(udcisr0 & UDCICR_PKTCOMPL));
+       }
+
+       udcisr0 >>= 2;
+       for (i = 1; udcisr0 != 0 && i < 16; udcisr0 >>= 2, i++) {
+               if (!(udcisr0 & UDCISR_INT_MASK))
+                       continue;
+
+               udc_writel(udc, UDCISR0, UDCISR_INT(i, UDCISR_INT_MASK));
+
+               WARN_ON(i >= ARRAY_SIZE(udc->pxa_ep));
+               if (i < ARRAY_SIZE(udc->pxa_ep)) {
+                       ep = &udc->pxa_ep[i];
+                       ep->stats.irqs++;
+                       handle_ep(ep);
+               }
+       }
+
+       for (i = 16; udcisr1 != 0 && i < 24; udcisr1 >>= 2, i++) {
+               udc_writel(udc, UDCISR1, UDCISR_INT(i - 16, UDCISR_INT_MASK));
+               if (!(udcisr1 & UDCISR_INT_MASK))
+                       continue;
+
+               WARN_ON(i >= ARRAY_SIZE(udc->pxa_ep));
+               if (i < ARRAY_SIZE(udc->pxa_ep)) {
+                       ep = &udc->pxa_ep[i];
+                       ep->stats.irqs++;
+                       handle_ep(ep);
+               }
+       }
+
+}
+
+/**
+ * irq_udc_suspend - Handle IRQ "UDC Suspend"
+ * @udc: udc device
+ */
+static void irq_udc_suspend(struct pxa_udc *udc)
+{
+       udc_writel(udc, UDCISR1, UDCISR1_IRSU);
+       udc->stats.irqs_suspend++;
+
+       if (udc->gadget.speed != USB_SPEED_UNKNOWN
+                       && udc->driver && udc->driver->suspend)
+               udc->driver->suspend(&udc->gadget);
+       ep0_idle(udc);
+}
+
+/**
+  * irq_udc_resume - Handle IRQ "UDC Resume"
+  * @udc: udc device
+  */
+static void irq_udc_resume(struct pxa_udc *udc)
+{
+       udc_writel(udc, UDCISR1, UDCISR1_IRRU);
+       udc->stats.irqs_resume++;
+
+       if (udc->gadget.speed != USB_SPEED_UNKNOWN
+                       && udc->driver && udc->driver->resume)
+               udc->driver->resume(&udc->gadget);
+}
+
+/**
+ * irq_udc_reconfig - Handle IRQ "UDC Change Configuration"
+ * @udc: udc device
+ */
+static void irq_udc_reconfig(struct pxa_udc *udc)
+{
+       unsigned config, interface, alternate, config_change;
+       u32 udccr = udc_readl(udc, UDCCR);
+
+       udc_writel(udc, UDCISR1, UDCISR1_IRCC);
+       udc->stats.irqs_reconfig++;
+
+       config = (udccr & UDCCR_ACN) >> UDCCR_ACN_S;
+       config_change = (config != udc->config);
+       pxa27x_change_configuration(udc, config);
+
+       interface = (udccr & UDCCR_AIN) >> UDCCR_AIN_S;
+       alternate = (udccr & UDCCR_AAISN) >> UDCCR_AAISN_S;
+       pxa27x_change_interface(udc, interface, alternate);
+
+       if (config_change)
+               update_pxa_ep_matches(udc);
+       udc_set_mask_UDCCR(udc, UDCCR_SMAC);
+}
+
+/**
+ * irq_udc_reset - Handle IRQ "UDC Reset"
+ * @udc: udc device
+ */
+static void irq_udc_reset(struct pxa_udc *udc)
+{
+       u32 udccr = udc_readl(udc, UDCCR);
+       struct pxa_ep *ep = &udc->pxa_ep[0];
+
+       dev_info(udc->dev, "USB reset\n");
+       udc_writel(udc, UDCISR1, UDCISR1_IRRS);
+       udc->stats.irqs_reset++;
+
+       if ((udccr & UDCCR_UDA) == 0) {
+               dev_dbg(udc->dev, "USB reset start\n");
+               stop_activity(udc, udc->driver);
+       }
+       udc->gadget.speed = USB_SPEED_FULL;
+       memset(&udc->stats, 0, sizeof udc->stats);
+
+       nuke(ep, -EPROTO);
+       ep_write_UDCCSR(ep, UDCCSR0_FTF | UDCCSR0_OPC);
+       ep0_idle(udc);
+}
+
+/**
+ * pxa_udc_irq - Main irq handler
+ * @irq: irq number
+ * @_dev: udc device
+ *
+ * Handles all udc interrupts
+ */
+static irqreturn_t pxa_udc_irq(int irq, void *_dev)
+{
+       struct pxa_udc *udc = _dev;
+       u32 udcisr0 = udc_readl(udc, UDCISR0);
+       u32 udcisr1 = udc_readl(udc, UDCISR1);
+       u32 udccr = udc_readl(udc, UDCCR);
+       u32 udcisr1_spec;
+
+       dev_vdbg(udc->dev, "Interrupt, UDCISR0:0x%08x, UDCISR1:0x%08x, "
+                "UDCCR:0x%08x\n", udcisr0, udcisr1, udccr);
+
+       udcisr1_spec = udcisr1 & 0xf8000000;
+       if (unlikely(udcisr1_spec & UDCISR1_IRSU))
+               irq_udc_suspend(udc);
+       if (unlikely(udcisr1_spec & UDCISR1_IRRU))
+               irq_udc_resume(udc);
+       if (unlikely(udcisr1_spec & UDCISR1_IRCC))
+               irq_udc_reconfig(udc);
+       if (unlikely(udcisr1_spec & UDCISR1_IRRS))
+               irq_udc_reset(udc);
+
+       if ((udcisr0 & UDCCISR0_EP_MASK) | (udcisr1 & UDCCISR1_EP_MASK))
+               irq_handle_data(irq, udc);
+
+       return IRQ_HANDLED;
+}
+
+static struct pxa_udc memory = {
+       .gadget = {
+               .ops            = &pxa_udc_ops,
+               .ep0            = &memory.udc_usb_ep[0].usb_ep,
+               .name           = driver_name,
+               .dev = {
+                       .init_name      = "gadget",
+               },
+       },
+
+       .udc_usb_ep = {
+               USB_EP_CTRL,
+               USB_EP_OUT_BULK(1),
+               USB_EP_IN_BULK(2),
+               USB_EP_IN_ISO(3),
+               USB_EP_OUT_ISO(4),
+               USB_EP_IN_INT(5),
+       },
+
+       .pxa_ep = {
+               PXA_EP_CTRL,
+               /* Endpoints for gadget zero */
+               PXA_EP_OUT_BULK(1, 1, 3, 0, 0),
+               PXA_EP_IN_BULK(2,  2, 3, 0, 0),
+               /* Endpoints for ether gadget, file storage gadget */
+               PXA_EP_OUT_BULK(3, 1, 1, 0, 0),
+               PXA_EP_IN_BULK(4,  2, 1, 0, 0),
+               PXA_EP_IN_ISO(5,   3, 1, 0, 0),
+               PXA_EP_OUT_ISO(6,  4, 1, 0, 0),
+               PXA_EP_IN_INT(7,   5, 1, 0, 0),
+               /* Endpoints for RNDIS, serial */
+               PXA_EP_OUT_BULK(8, 1, 2, 0, 0),
+               PXA_EP_IN_BULK(9,  2, 2, 0, 0),
+               PXA_EP_IN_INT(10,  5, 2, 0, 0),
+               /*
+                * All the following endpoints are only for completion.  They
+                * won't never work, as multiple interfaces are really broken on
+                * the pxa.
+               */
+               PXA_EP_OUT_BULK(11, 1, 2, 1, 0),
+               PXA_EP_IN_BULK(12,  2, 2, 1, 0),
+               /* Endpoint for CDC Ether */
+               PXA_EP_OUT_BULK(13, 1, 1, 1, 1),
+               PXA_EP_IN_BULK(14,  2, 1, 1, 1),
+       }
+};
+
+/**
+ * pxa_udc_probe - probes the udc device
+ * @_dev: platform device
+ *
+ * Perform basic init : allocates udc clock, creates sysfs files, requests
+ * irq.
+ */
+static int pxa_udc_probe(struct platform_device *pdev)
+{
+       struct resource *regs;
+       struct pxa_udc *udc = &memory;
+       int retval = 0, gpio;
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!regs)
+               return -ENXIO;
+       udc->irq = platform_get_irq(pdev, 0);
+       if (udc->irq < 0)
+               return udc->irq;
+
+       udc->dev = &pdev->dev;
+       udc->mach = dev_get_platdata(&pdev->dev);
+       udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+
+       gpio = udc->mach->gpio_pullup;
+       if (gpio_is_valid(gpio)) {
+               retval = gpio_request(gpio, "USB D+ pullup");
+               if (retval == 0)
+                       gpio_direction_output(gpio,
+                                      udc->mach->gpio_pullup_inverted);
+       }
+       if (retval) {
+               dev_err(&pdev->dev, "Couldn't request gpio %d : %d\n",
+                       gpio, retval);
+               return retval;
+       }
+
+       udc->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(udc->clk)) {
+               retval = PTR_ERR(udc->clk);
+               goto err_clk;
+       }
+       retval = clk_prepare(udc->clk);
+       if (retval)
+               goto err_clk_prepare;
+
+       retval = -ENOMEM;
+       udc->regs = ioremap(regs->start, resource_size(regs));
+       if (!udc->regs) {
+               dev_err(&pdev->dev, "Unable to map UDC I/O memory\n");
+               goto err_map;
+       }
+
+       udc->vbus_sensed = 0;
+
+       the_controller = udc;
+       platform_set_drvdata(pdev, udc);
+       udc_init_data(udc);
+       pxa_eps_setup(udc);
+
+       /* irq setup after old hardware state is cleaned up */
+       retval = request_irq(udc->irq, pxa_udc_irq,
+                       IRQF_SHARED, driver_name, udc);
+       if (retval != 0) {
+               dev_err(udc->dev, "%s: can't get irq %i, err %d\n",
+                       driver_name, udc->irq, retval);
+               goto err_irq;
+       }
+
+       retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
+       if (retval)
+               goto err_add_udc;
+
+       pxa_init_debugfs(udc);
+
+       return 0;
+
+err_add_udc:
+       free_irq(udc->irq, udc);
+err_irq:
+       iounmap(udc->regs);
+err_map:
+       clk_unprepare(udc->clk);
+err_clk_prepare:
+       clk_put(udc->clk);
+       udc->clk = NULL;
+err_clk:
+       return retval;
+}
+
+/**
+ * pxa_udc_remove - removes the udc device driver
+ * @_dev: platform device
+ */
+static int pxa_udc_remove(struct platform_device *_dev)
+{
+       struct pxa_udc *udc = platform_get_drvdata(_dev);
+       int gpio = udc->mach->gpio_pullup;
+
+       usb_del_gadget_udc(&udc->gadget);
+       usb_gadget_unregister_driver(udc->driver);
+       free_irq(udc->irq, udc);
+       pxa_cleanup_debugfs(udc);
+       if (gpio_is_valid(gpio))
+               gpio_free(gpio);
+
+       usb_put_phy(udc->transceiver);
+
+       udc->transceiver = NULL;
+       the_controller = NULL;
+       clk_unprepare(udc->clk);
+       clk_put(udc->clk);
+       iounmap(udc->regs);
+
+       return 0;
+}
+
+static void pxa_udc_shutdown(struct platform_device *_dev)
+{
+       struct pxa_udc *udc = platform_get_drvdata(_dev);
+
+       if (udc_readl(udc, UDCCR) & UDCCR_UDE)
+               udc_disable(udc);
+}
+
+#ifdef CONFIG_PXA27x
+extern void pxa27x_clear_otgph(void);
+#else
+#define pxa27x_clear_otgph()   do {} while (0)
+#endif
+
+#ifdef CONFIG_PM
+/**
+ * pxa_udc_suspend - Suspend udc device
+ * @_dev: platform device
+ * @state: suspend state
+ *
+ * Suspends udc : saves configuration registers (UDCCR*), then disables the udc
+ * device.
+ */
+static int pxa_udc_suspend(struct platform_device *_dev, pm_message_t state)
+{
+       int i;
+       struct pxa_udc *udc = platform_get_drvdata(_dev);
+       struct pxa_ep *ep;
+
+       ep = &udc->pxa_ep[0];
+       udc->udccsr0 = udc_ep_readl(ep, UDCCSR);
+       for (i = 1; i < NR_PXA_ENDPOINTS; i++) {
+               ep = &udc->pxa_ep[i];
+               ep->udccsr_value = udc_ep_readl(ep, UDCCSR);
+               ep->udccr_value  = udc_ep_readl(ep, UDCCR);
+               ep_dbg(ep, "udccsr:0x%03x, udccr:0x%x\n",
+                               ep->udccsr_value, ep->udccr_value);
+       }
+
+       udc_disable(udc);
+       udc->pullup_resume = udc->pullup_on;
+       dplus_pullup(udc, 0);
+
+       return 0;
+}
+
+/**
+ * pxa_udc_resume - Resume udc device
+ * @_dev: platform device
+ *
+ * Resumes udc : restores configuration registers (UDCCR*), then enables the udc
+ * device.
+ */
+static int pxa_udc_resume(struct platform_device *_dev)
+{
+       int i;
+       struct pxa_udc *udc = platform_get_drvdata(_dev);
+       struct pxa_ep *ep;
+
+       ep = &udc->pxa_ep[0];
+       udc_ep_writel(ep, UDCCSR, udc->udccsr0 & (UDCCSR0_FST | UDCCSR0_DME));
+       for (i = 1; i < NR_PXA_ENDPOINTS; i++) {
+               ep = &udc->pxa_ep[i];
+               udc_ep_writel(ep, UDCCSR, ep->udccsr_value);
+               udc_ep_writel(ep, UDCCR,  ep->udccr_value);
+               ep_dbg(ep, "udccsr:0x%03x, udccr:0x%x\n",
+                               ep->udccsr_value, ep->udccr_value);
+       }
+
+       dplus_pullup(udc, udc->pullup_resume);
+       if (should_enable_udc(udc))
+               udc_enable(udc);
+       /*
+        * We do not handle OTG yet.
+        *
+        * OTGPH bit is set when sleep mode is entered.
+        * it indicates that OTG pad is retaining its state.
+        * Upon exit from sleep mode and before clearing OTGPH,
+        * Software must configure the USB OTG pad, UDC, and UHC
+        * to the state they were in before entering sleep mode.
+        */
+       pxa27x_clear_otgph();
+
+       return 0;
+}
+#endif
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:pxa27x-udc");
+
+static struct platform_driver udc_driver = {
+       .driver         = {
+               .name   = "pxa27x-udc",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = pxa_udc_probe,
+       .remove         = pxa_udc_remove,
+       .shutdown       = pxa_udc_shutdown,
+#ifdef CONFIG_PM
+       .suspend        = pxa_udc_suspend,
+       .resume         = pxa_udc_resume
+#endif
+};
+
+module_platform_driver(udc_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Robert Jarzmik");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.h b/drivers/usb/gadget/udc/pxa27x_udc.h
new file mode 100644 (file)
index 0000000..28f2b53
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+ * linux/drivers/usb/gadget/pxa27x_udc.h
+ * Intel PXA27x on-chip full speed USB device controller
+ *
+ * Inspired by original driver by Frank Becker, David Brownell, and others.
+ * Copyright (C) 2008 Robert Jarzmik
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_USB_GADGET_PXA27X_H
+#define __LINUX_USB_GADGET_PXA27X_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/usb/otg.h>
+
+/*
+ * Register definitions
+ */
+/* Offsets */
+#define UDCCR          0x0000          /* UDC Control Register */
+#define UDCICR0                0x0004          /* UDC Interrupt Control Register0 */
+#define UDCICR1                0x0008          /* UDC Interrupt Control Register1 */
+#define UDCISR0                0x000C          /* UDC Interrupt Status Register 0 */
+#define UDCISR1                0x0010          /* UDC Interrupt Status Register 1 */
+#define UDCFNR         0x0014          /* UDC Frame Number Register */
+#define UDCOTGICR      0x0018          /* UDC On-The-Go interrupt control */
+#define UP2OCR         0x0020          /* USB Port 2 Output Control register */
+#define UP3OCR         0x0024          /* USB Port 3 Output Control register */
+#define UDCCSRn(x)     (0x0100 + ((x)<<2)) /* UDC Control/Status register */
+#define UDCBCRn(x)     (0x0200 + ((x)<<2)) /* UDC Byte Count Register */
+#define UDCDRn(x)      (0x0300 + ((x)<<2)) /* UDC Data Register  */
+#define UDCCRn(x)      (0x0400 + ((x)<<2)) /* UDC Control Register */
+
+#define UDCCR_OEN      (1 << 31)       /* On-the-Go Enable */
+#define UDCCR_AALTHNP  (1 << 30)       /* A-device Alternate Host Negotiation
+                                          Protocol Port Support */
+#define UDCCR_AHNP     (1 << 29)       /* A-device Host Negotiation Protocol
+                                          Support */
+#define UDCCR_BHNP     (1 << 28)       /* B-device Host Negotiation Protocol
+                                          Enable */
+#define UDCCR_DWRE     (1 << 16)       /* Device Remote Wake-up Enable */
+#define UDCCR_ACN      (0x03 << 11)    /* Active UDC configuration Number */
+#define UDCCR_ACN_S    11
+#define UDCCR_AIN      (0x07 << 8)     /* Active UDC interface Number */
+#define UDCCR_AIN_S    8
+#define UDCCR_AAISN    (0x07 << 5)     /* Active UDC Alternate Interface
+                                          Setting Number */
+#define UDCCR_AAISN_S  5
+#define UDCCR_SMAC     (1 << 4)        /* Switch Endpoint Memory to Active
+                                          Configuration */
+#define UDCCR_EMCE     (1 << 3)        /* Endpoint Memory Configuration
+                                          Error */
+#define UDCCR_UDR      (1 << 2)        /* UDC Resume */
+#define UDCCR_UDA      (1 << 1)        /* UDC Active */
+#define UDCCR_UDE      (1 << 0)        /* UDC Enable */
+
+#define UDCICR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
+#define UDCICR1_IECC   (1 << 31)       /* IntEn - Configuration Change */
+#define UDCICR1_IESOF  (1 << 30)       /* IntEn - Start of Frame */
+#define UDCICR1_IERU   (1 << 29)       /* IntEn - Resume */
+#define UDCICR1_IESU   (1 << 28)       /* IntEn - Suspend */
+#define UDCICR1_IERS   (1 << 27)       /* IntEn - Reset */
+#define UDCICR_FIFOERR (1 << 1)        /* FIFO Error interrupt for EP */
+#define UDCICR_PKTCOMPL        (1 << 0)        /* Packet Complete interrupt for EP */
+#define UDCICR_INT_MASK        (UDCICR_FIFOERR | UDCICR_PKTCOMPL)
+
+#define UDCISR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
+#define UDCISR1_IRCC   (1 << 31)       /* IntReq - Configuration Change */
+#define UDCISR1_IRSOF  (1 << 30)       /* IntReq - Start of Frame */
+#define UDCISR1_IRRU   (1 << 29)       /* IntReq - Resume */
+#define UDCISR1_IRSU   (1 << 28)       /* IntReq - Suspend */
+#define UDCISR1_IRRS   (1 << 27)       /* IntReq - Reset */
+#define UDCISR_INT_MASK        (UDCICR_FIFOERR | UDCICR_PKTCOMPL)
+
+#define UDCOTGICR_IESF (1 << 24)       /* OTG SET_FEATURE command recvd */
+#define UDCOTGICR_IEXR (1 << 17)       /* Extra Transceiver Interrupt
+                                          Rising Edge Interrupt Enable */
+#define UDCOTGICR_IEXF (1 << 16)       /* Extra Transceiver Interrupt
+                                          Falling Edge Interrupt Enable */
+#define UDCOTGICR_IEVV40R (1 << 9)     /* OTG Vbus Valid 4.0V Rising Edge
+                                          Interrupt Enable */
+#define UDCOTGICR_IEVV40F (1 << 8)     /* OTG Vbus Valid 4.0V Falling Edge
+                                          Interrupt Enable */
+#define UDCOTGICR_IEVV44R (1 << 7)     /* OTG Vbus Valid 4.4V Rising Edge
+                                          Interrupt Enable */
+#define UDCOTGICR_IEVV44F (1 << 6)     /* OTG Vbus Valid 4.4V Falling Edge
+                                          Interrupt Enable */
+#define UDCOTGICR_IESVR        (1 << 5)        /* OTG Session Valid Rising Edge
+                                          Interrupt Enable */
+#define UDCOTGICR_IESVF        (1 << 4)        /* OTG Session Valid Falling Edge
+                                          Interrupt Enable */
+#define UDCOTGICR_IESDR        (1 << 3)        /* OTG A-Device SRP Detect Rising
+                                          Edge Interrupt Enable */
+#define UDCOTGICR_IESDF        (1 << 2)        /* OTG A-Device SRP Detect Falling
+                                          Edge Interrupt Enable */
+#define UDCOTGICR_IEIDR        (1 << 1)        /* OTG ID Change Rising Edge
+                                          Interrupt Enable */
+#define UDCOTGICR_IEIDF        (1 << 0)        /* OTG ID Change Falling Edge
+                                          Interrupt Enable */
+
+/* Host Port 2 field bits */
+#define UP2OCR_CPVEN   (1 << 0)        /* Charge Pump Vbus Enable */
+#define UP2OCR_CPVPE   (1 << 1)        /* Charge Pump Vbus Pulse Enable */
+                                       /* Transceiver enablers */
+#define UP2OCR_DPPDE   (1 << 2)        /*   D+ Pull Down Enable */
+#define UP2OCR_DMPDE   (1 << 3)        /*   D- Pull Down Enable */
+#define UP2OCR_DPPUE   (1 << 4)        /*   D+ Pull Up Enable */
+#define UP2OCR_DMPUE   (1 << 5)        /*   D- Pull Up Enable */
+#define UP2OCR_DPPUBE  (1 << 6)        /*   D+ Pull Up Bypass Enable */
+#define UP2OCR_DMPUBE  (1 << 7)        /*   D- Pull Up Bypass Enable */
+#define UP2OCR_EXSP    (1 << 8)        /* External Transceiver Speed Control */
+#define UP2OCR_EXSUS   (1 << 9)        /* External Transceiver Speed Enable */
+#define UP2OCR_IDON    (1 << 10)       /* OTG ID Read Enable */
+#define UP2OCR_HXS     (1 << 16)       /* Transceiver Output Select */
+#define UP2OCR_HXOE    (1 << 17)       /* Transceiver Output Enable */
+#define UP2OCR_SEOS    (1 << 24)       /* Single-Ended Output Select */
+
+#define UDCCSR0_ACM    (1 << 9)        /* Ack Control Mode */
+#define UDCCSR0_AREN   (1 << 8)        /* Ack Response Enable */
+#define UDCCSR0_SA     (1 << 7)        /* Setup Active */
+#define UDCCSR0_RNE    (1 << 6)        /* Receive FIFO Not Empty */
+#define UDCCSR0_FST    (1 << 5)        /* Force Stall */
+#define UDCCSR0_SST    (1 << 4)        /* Sent Stall */
+#define UDCCSR0_DME    (1 << 3)        /* DMA Enable */
+#define UDCCSR0_FTF    (1 << 2)        /* Flush Transmit FIFO */
+#define UDCCSR0_IPR    (1 << 1)        /* IN Packet Ready */
+#define UDCCSR0_OPC    (1 << 0)        /* OUT Packet Complete */
+
+#define UDCCSR_DPE     (1 << 9)        /* Data Packet Error */
+#define UDCCSR_FEF     (1 << 8)        /* Flush Endpoint FIFO */
+#define UDCCSR_SP      (1 << 7)        /* Short Packet Control/Status */
+#define UDCCSR_BNE     (1 << 6)        /* Buffer Not Empty (IN endpoints) */
+#define UDCCSR_BNF     (1 << 6)        /* Buffer Not Full (OUT endpoints) */
+#define UDCCSR_FST     (1 << 5)        /* Force STALL */
+#define UDCCSR_SST     (1 << 4)        /* Sent STALL */
+#define UDCCSR_DME     (1 << 3)        /* DMA Enable */
+#define UDCCSR_TRN     (1 << 2)        /* Tx/Rx NAK */
+#define UDCCSR_PC      (1 << 1)        /* Packet Complete */
+#define UDCCSR_FS      (1 << 0)        /* FIFO needs service */
+
+#define UDCCONR_CN     (0x03 << 25)    /* Configuration Number */
+#define UDCCONR_CN_S   25
+#define UDCCONR_IN     (0x07 << 22)    /* Interface Number */
+#define UDCCONR_IN_S   22
+#define UDCCONR_AISN   (0x07 << 19)    /* Alternate Interface Number */
+#define UDCCONR_AISN_S 19
+#define UDCCONR_EN     (0x0f << 15)    /* Endpoint Number */
+#define UDCCONR_EN_S   15
+#define UDCCONR_ET     (0x03 << 13)    /* Endpoint Type: */
+#define UDCCONR_ET_S   13
+#define UDCCONR_ET_INT (0x03 << 13)    /*   Interrupt */
+#define UDCCONR_ET_BULK        (0x02 << 13)    /*   Bulk */
+#define UDCCONR_ET_ISO (0x01 << 13)    /*   Isochronous */
+#define UDCCONR_ET_NU  (0x00 << 13)    /*   Not used */
+#define UDCCONR_ED     (1 << 12)       /* Endpoint Direction */
+#define UDCCONR_MPS    (0x3ff << 2)    /* Maximum Packet Size */
+#define UDCCONR_MPS_S  2
+#define UDCCONR_DE     (1 << 1)        /* Double Buffering Enable */
+#define UDCCONR_EE     (1 << 0)        /* Endpoint Enable */
+
+#define UDCCR_MASK_BITS (UDCCR_OEN | UDCCR_SMAC | UDCCR_UDR | UDCCR_UDE)
+#define UDCCSR_WR_MASK (UDCCSR_DME | UDCCSR_FST)
+#define UDC_FNR_MASK   (0x7ff)
+#define UDC_BCR_MASK   (0x3ff)
+
+/*
+ * UDCCR = UDC Endpoint Configuration Registers
+ * UDCCSR = UDC Control/Status Register for this EP
+ * UDCBCR = UDC Byte Count Remaining (contents of OUT fifo)
+ * UDCDR = UDC Endpoint Data Register (the fifo)
+ */
+#define ofs_UDCCR(ep)  (UDCCRn(ep->idx))
+#define ofs_UDCCSR(ep) (UDCCSRn(ep->idx))
+#define ofs_UDCBCR(ep) (UDCBCRn(ep->idx))
+#define ofs_UDCDR(ep)  (UDCDRn(ep->idx))
+
+/* Register access macros */
+#define udc_ep_readl(ep, reg)  \
+       __raw_readl((ep)->dev->regs + ofs_##reg(ep))
+#define udc_ep_writel(ep, reg, value)  \
+       __raw_writel((value), ep->dev->regs + ofs_##reg(ep))
+#define udc_ep_readb(ep, reg)  \
+       __raw_readb((ep)->dev->regs + ofs_##reg(ep))
+#define udc_ep_writeb(ep, reg, value)  \
+       __raw_writeb((value), ep->dev->regs + ofs_##reg(ep))
+#define udc_readl(dev, reg)    \
+       __raw_readl((dev)->regs + (reg))
+#define udc_writel(udc, reg, value)    \
+       __raw_writel((value), (udc)->regs + (reg))
+
+#define UDCCSR_MASK            (UDCCSR_FST | UDCCSR_DME)
+#define UDCCISR0_EP_MASK       ~0
+#define UDCCISR1_EP_MASK       0xffff
+#define UDCCSR0_CTRL_REQ_MASK  (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE)
+
+#define EPIDX(ep)      (ep->idx)
+#define EPADDR(ep)     (ep->addr)
+#define EPXFERTYPE(ep) (ep->type)
+#define EPNAME(ep)     (ep->name)
+#define is_ep0(ep)     (!ep->idx)
+#define EPXFERTYPE_is_ISO(ep) (EPXFERTYPE(ep) == USB_ENDPOINT_XFER_ISOC)
+
+/*
+ * Endpoint definitions
+ *
+ * Once enabled, pxa endpoint configuration is freezed, and cannot change
+ * unless a reset happens or the udc is disabled.
+ * Therefore, we must define all pxa potential endpoint definitions needed for
+ * all gadget and set them up before the udc is enabled.
+ *
+ * As the architecture chosen is fully static, meaning the pxa endpoint
+ * configurations are set up once and for all, we must provide a way to match
+ * one usb endpoint (usb_ep) to several pxa endpoints. The reason is that gadget
+ * layer autoconf doesn't choose the usb_ep endpoint on (config, interface, alt)
+ * criteria, while the pxa architecture requires that.
+ *
+ * The solution is to define several pxa endpoints matching one usb_ep. Ex:
+ *   - "ep1-in" matches pxa endpoint EPA (which is an IN ep at addr 1, when
+ *     the udc talks on (config=3, interface=0, alt=0)
+ *   - "ep1-in" matches pxa endpoint EPB (which is an IN ep at addr 1, when
+ *     the udc talks on (config=3, interface=0, alt=1)
+ *   - "ep1-in" matches pxa endpoint EPC (which is an IN ep at addr 1, when
+ *     the udc talks on (config=2, interface=0, alt=0)
+ *
+ * We'll define the pxa endpoint by its index (EPA => idx=1, EPB => idx=2, ...)
+ */
+
+/*
+ * Endpoint definition helpers
+ */
+#define USB_EP_DEF(addr, bname, dir, type, maxpkt) \
+{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, }, \
+  .desc = {    .bEndpointAddress = addr | (dir ? USB_DIR_IN : 0), \
+               .bmAttributes = type, \
+               .wMaxPacketSize = maxpkt, }, \
+  .dev = &memory \
+}
+#define USB_EP_BULK(addr, bname, dir) \
+  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE)
+#define USB_EP_ISO(addr, bname, dir) \
+  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE)
+#define USB_EP_INT(addr, bname, dir) \
+  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE)
+#define USB_EP_IN_BULK(n)      USB_EP_BULK(n, "ep" #n "in-bulk", 1)
+#define USB_EP_OUT_BULK(n)     USB_EP_BULK(n, "ep" #n "out-bulk", 0)
+#define USB_EP_IN_ISO(n)       USB_EP_ISO(n,  "ep" #n "in-iso", 1)
+#define USB_EP_OUT_ISO(n)      USB_EP_ISO(n,  "ep" #n "out-iso", 0)
+#define USB_EP_IN_INT(n)       USB_EP_INT(n,  "ep" #n "in-int", 1)
+#define USB_EP_CTRL            USB_EP_DEF(0,  "ep0", 0, 0, EP0_FIFO_SIZE)
+
+#define PXA_EP_DEF(_idx, _addr, dir, _type, maxpkt, _config, iface, altset) \
+{ \
+       .dev = &memory, \
+       .name = "ep" #_idx, \
+       .idx = _idx, .enabled = 0, \
+       .dir_in = dir, .addr = _addr, \
+       .config = _config, .interface = iface, .alternate = altset, \
+       .type = _type, .fifo_size = maxpkt, \
+}
+#define PXA_EP_BULK(_idx, addr, dir, config, iface, alt) \
+  PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE, \
+               config, iface, alt)
+#define PXA_EP_ISO(_idx, addr, dir, config, iface, alt) \
+  PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE, \
+               config, iface, alt)
+#define PXA_EP_INT(_idx, addr, dir, config, iface, alt) \
+  PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE, \
+               config, iface, alt)
+#define PXA_EP_IN_BULK(i, adr, c, f, a)                PXA_EP_BULK(i, adr, 1, c, f, a)
+#define PXA_EP_OUT_BULK(i, adr, c, f, a)       PXA_EP_BULK(i, adr, 0, c, f, a)
+#define PXA_EP_IN_ISO(i, adr, c, f, a)         PXA_EP_ISO(i, adr, 1, c, f, a)
+#define PXA_EP_OUT_ISO(i, adr, c, f, a)                PXA_EP_ISO(i, adr, 0, c, f, a)
+#define PXA_EP_IN_INT(i, adr, c, f, a)         PXA_EP_INT(i, adr, 1, c, f, a)
+#define PXA_EP_CTRL    PXA_EP_DEF(0, 0, 0, 0, EP0_FIFO_SIZE, 0, 0, 0)
+
+struct pxa27x_udc;
+
+struct stats {
+       unsigned long in_ops;
+       unsigned long out_ops;
+       unsigned long in_bytes;
+       unsigned long out_bytes;
+       unsigned long irqs;
+};
+
+/**
+ * struct udc_usb_ep - container of each usb_ep structure
+ * @usb_ep: usb endpoint
+ * @desc: usb descriptor, especially type and address
+ * @dev: udc managing this endpoint
+ * @pxa_ep: matching pxa_ep (cache of find_pxa_ep() call)
+ */
+struct udc_usb_ep {
+       struct usb_ep usb_ep;
+       struct usb_endpoint_descriptor desc;
+       struct pxa_udc *dev;
+       struct pxa_ep *pxa_ep;
+};
+
+/**
+ * struct pxa_ep - pxa endpoint
+ * @dev: udc device
+ * @queue: requests queue
+ * @lock: lock to pxa_ep data (queues and stats)
+ * @enabled: true when endpoint enabled (not stopped by gadget layer)
+ * @in_handle_ep: number of recursions of handle_ep() function
+ *     Prevents deadlocks or infinite recursions of types :
+ *       irq->handle_ep()->req_done()->req.complete()->pxa_ep_queue()->handle_ep()
+ *      or
+ *        pxa_ep_queue()->handle_ep()->req_done()->req.complete()->pxa_ep_queue()
+ * @idx: endpoint index (1 => epA, 2 => epB, ..., 24 => epX)
+ * @name: endpoint name (for trace/debug purpose)
+ * @dir_in: 1 if IN endpoint, 0 if OUT endpoint
+ * @addr: usb endpoint number
+ * @config: configuration in which this endpoint is active
+ * @interface: interface in which this endpoint is active
+ * @alternate: altsetting in which this endpoitn is active
+ * @fifo_size: max packet size in the endpoint fifo
+ * @type: endpoint type (bulk, iso, int, ...)
+ * @udccsr_value: save register of UDCCSR0 for suspend/resume
+ * @udccr_value: save register of UDCCR for suspend/resume
+ * @stats: endpoint statistics
+ *
+ * The *PROBLEM* is that pxa's endpoint configuration scheme is both misdesigned
+ * (cares about config/interface/altsetting, thus placing needless limits on
+ * device capability) and full of implementation bugs forcing it to be set up
+ * for use more or less like a pxa255.
+ *
+ * As we define the pxa_ep statically, we must guess all needed pxa_ep for all
+ * gadget which may work with this udc driver.
+ */
+struct pxa_ep {
+       struct pxa_udc          *dev;
+
+       struct list_head        queue;
+       spinlock_t              lock;           /* Protects this structure */
+                                               /* (queues, stats) */
+       unsigned                enabled:1;
+       unsigned                in_handle_ep:1;
+
+       unsigned                idx:5;
+       char                    *name;
+
+       /*
+        * Specific pxa endpoint data, needed for hardware initialization
+        */
+       unsigned                dir_in:1;
+       unsigned                addr:4;
+       unsigned                config:2;
+       unsigned                interface:3;
+       unsigned                alternate:3;
+       unsigned                fifo_size;
+       unsigned                type;
+
+#ifdef CONFIG_PM
+       u32                     udccsr_value;
+       u32                     udccr_value;
+#endif
+       struct stats            stats;
+};
+
+/**
+ * struct pxa27x_request - container of each usb_request structure
+ * @req: usb request
+ * @udc_usb_ep: usb endpoint the request was submitted on
+ * @in_use: sanity check if request already queued on an pxa_ep
+ * @queue: linked list of requests, linked on pxa_ep->queue
+ */
+struct pxa27x_request {
+       struct usb_request                      req;
+       struct udc_usb_ep                       *udc_usb_ep;
+       unsigned                                in_use:1;
+       struct list_head                        queue;
+};
+
+enum ep0_state {
+       WAIT_FOR_SETUP,
+       SETUP_STAGE,
+       IN_DATA_STAGE,
+       OUT_DATA_STAGE,
+       IN_STATUS_STAGE,
+       OUT_STATUS_STAGE,
+       STALL,
+       WAIT_ACK_SET_CONF_INTERF
+};
+
+static char *ep0_state_name[] = {
+       "WAIT_FOR_SETUP", "SETUP_STAGE", "IN_DATA_STAGE", "OUT_DATA_STAGE",
+       "IN_STATUS_STAGE", "OUT_STATUS_STAGE", "STALL",
+       "WAIT_ACK_SET_CONF_INTERF"
+};
+#define EP0_STNAME(udc) ep0_state_name[(udc)->ep0state]
+
+#define EP0_FIFO_SIZE  16U
+#define BULK_FIFO_SIZE 64U
+#define ISO_FIFO_SIZE  256U
+#define INT_FIFO_SIZE  16U
+
+struct udc_stats {
+       unsigned long   irqs_reset;
+       unsigned long   irqs_suspend;
+       unsigned long   irqs_resume;
+       unsigned long   irqs_reconfig;
+};
+
+#define NR_USB_ENDPOINTS (1 + 5)       /* ep0 + ep1in-bulk + .. + ep3in-iso */
+#define NR_PXA_ENDPOINTS (1 + 14)      /* ep0 + epA + epB + .. + epX */
+
+/**
+ * struct pxa_udc - udc structure
+ * @regs: mapped IO space
+ * @irq: udc irq
+ * @clk: udc clock
+ * @usb_gadget: udc gadget structure
+ * @driver: bound gadget (zero, g_ether, g_mass_storage, ...)
+ * @dev: device
+ * @mach: machine info, used to activate specific GPIO
+ * @transceiver: external transceiver to handle vbus sense and D+ pullup
+ * @ep0state: control endpoint state machine state
+ * @stats: statistics on udc usage
+ * @udc_usb_ep: array of usb endpoints offered by the gadget
+ * @pxa_ep: array of pxa available endpoints
+ * @enabled: UDC was enabled by a previous udc_enable()
+ * @pullup_on: if pullup resistor connected to D+ pin
+ * @pullup_resume: if pullup resistor should be connected to D+ pin on resume
+ * @config: UDC active configuration
+ * @last_interface: UDC interface of the last SET_INTERFACE host request
+ * @last_alternate: UDC altsetting of the last SET_INTERFACE host request
+ * @udccsr0: save of udccsr0 in case of suspend
+ * @debugfs_root: root entry of debug filesystem
+ * @debugfs_state: debugfs entry for "udcstate"
+ * @debugfs_queues: debugfs entry for "queues"
+ * @debugfs_eps: debugfs entry for "epstate"
+ */
+struct pxa_udc {
+       void __iomem                            *regs;
+       int                                     irq;
+       struct clk                              *clk;
+
+       struct usb_gadget                       gadget;
+       struct usb_gadget_driver                *driver;
+       struct device                           *dev;
+       struct pxa2xx_udc_mach_info             *mach;
+       struct usb_phy                          *transceiver;
+
+       enum ep0_state                          ep0state;
+       struct udc_stats                        stats;
+
+       struct udc_usb_ep                       udc_usb_ep[NR_USB_ENDPOINTS];
+       struct pxa_ep                           pxa_ep[NR_PXA_ENDPOINTS];
+
+       unsigned                                enabled:1;
+       unsigned                                pullup_on:1;
+       unsigned                                pullup_resume:1;
+       unsigned                                vbus_sensed:1;
+       unsigned                                config:2;
+       unsigned                                last_interface:3;
+       unsigned                                last_alternate:3;
+
+#ifdef CONFIG_PM
+       unsigned                                udccsr0;
+#endif
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+       struct dentry                           *debugfs_root;
+       struct dentry                           *debugfs_state;
+       struct dentry                           *debugfs_queues;
+       struct dentry                           *debugfs_eps;
+#endif
+};
+#define to_pxa(g)      (container_of((g), struct pxa_udc, gadget))
+
+static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget)
+{
+       return container_of(gadget, struct pxa_udc, gadget);
+}
+
+/*
+ * Debugging/message support
+ */
+#define ep_dbg(ep, fmt, arg...) \
+       dev_dbg(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
+#define ep_vdbg(ep, fmt, arg...) \
+       dev_vdbg(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
+#define ep_err(ep, fmt, arg...) \
+       dev_err(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
+#define ep_info(ep, fmt, arg...) \
+       dev_info(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
+#define ep_warn(ep, fmt, arg...) \
+       dev_warn(ep->dev->dev, "%s:%s:" fmt, EPNAME(ep), __func__, ## arg)
+
+#endif /* __LINUX_USB_GADGET_PXA27X_H */
diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c
new file mode 100644 (file)
index 0000000..4600842
--- /dev/null
@@ -0,0 +1,1993 @@
+/*
+ * R8A66597 UDC (USB gadget)
+ *
+ * Copyright (C) 2006-2009 Renesas Solutions Corp.
+ *
+ * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#include "r8a66597-udc.h"
+
+#define DRIVER_VERSION "2011-09-26"
+
+static const char udc_name[] = "r8a66597_udc";
+static const char *r8a66597_ep_name[] = {
+       "ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7",
+       "ep8", "ep9",
+};
+
+static void init_controller(struct r8a66597 *r8a66597);
+static void disable_controller(struct r8a66597 *r8a66597);
+static void irq_ep0_write(struct r8a66597_ep *ep, struct r8a66597_request *req);
+static void irq_packet_write(struct r8a66597_ep *ep,
+                               struct r8a66597_request *req);
+static int r8a66597_queue(struct usb_ep *_ep, struct usb_request *_req,
+                       gfp_t gfp_flags);
+
+static void transfer_complete(struct r8a66597_ep *ep,
+               struct r8a66597_request *req, int status);
+
+/*-------------------------------------------------------------------------*/
+static inline u16 get_usb_speed(struct r8a66597 *r8a66597)
+{
+       return r8a66597_read(r8a66597, DVSTCTR0) & RHST;
+}
+
+static void enable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum,
+               unsigned long reg)
+{
+       u16 tmp;
+
+       tmp = r8a66597_read(r8a66597, INTENB0);
+       r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE,
+                       INTENB0);
+       r8a66597_bset(r8a66597, (1 << pipenum), reg);
+       r8a66597_write(r8a66597, tmp, INTENB0);
+}
+
+static void disable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum,
+               unsigned long reg)
+{
+       u16 tmp;
+
+       tmp = r8a66597_read(r8a66597, INTENB0);
+       r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE,
+                       INTENB0);
+       r8a66597_bclr(r8a66597, (1 << pipenum), reg);
+       r8a66597_write(r8a66597, tmp, INTENB0);
+}
+
+static void r8a66597_usb_connect(struct r8a66597 *r8a66597)
+{
+       r8a66597_bset(r8a66597, CTRE, INTENB0);
+       r8a66597_bset(r8a66597, BEMPE | BRDYE, INTENB0);
+
+       r8a66597_bset(r8a66597, DPRPU, SYSCFG0);
+}
+
+static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597)
+__releases(r8a66597->lock)
+__acquires(r8a66597->lock)
+{
+       r8a66597_bclr(r8a66597, CTRE, INTENB0);
+       r8a66597_bclr(r8a66597, BEMPE | BRDYE, INTENB0);
+       r8a66597_bclr(r8a66597, DPRPU, SYSCFG0);
+
+       r8a66597->gadget.speed = USB_SPEED_UNKNOWN;
+       spin_unlock(&r8a66597->lock);
+       r8a66597->driver->disconnect(&r8a66597->gadget);
+       spin_lock(&r8a66597->lock);
+
+       disable_controller(r8a66597);
+       init_controller(r8a66597);
+       r8a66597_bset(r8a66597, VBSE, INTENB0);
+       INIT_LIST_HEAD(&r8a66597->ep[0].queue);
+}
+
+static inline u16 control_reg_get_pid(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       u16 pid = 0;
+       unsigned long offset;
+
+       if (pipenum == 0) {
+               pid = r8a66597_read(r8a66597, DCPCTR) & PID;
+       } else if (pipenum < R8A66597_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               pid = r8a66597_read(r8a66597, offset) & PID;
+       } else {
+               dev_err(r8a66597_to_dev(r8a66597), "unexpect pipe num (%d)\n",
+                       pipenum);
+       }
+
+       return pid;
+}
+
+static inline void control_reg_set_pid(struct r8a66597 *r8a66597, u16 pipenum,
+               u16 pid)
+{
+       unsigned long offset;
+
+       if (pipenum == 0) {
+               r8a66597_mdfy(r8a66597, pid, PID, DCPCTR);
+       } else if (pipenum < R8A66597_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               r8a66597_mdfy(r8a66597, pid, PID, offset);
+       } else {
+               dev_err(r8a66597_to_dev(r8a66597), "unexpect pipe num (%d)\n",
+                       pipenum);
+       }
+}
+
+static inline void pipe_start(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       control_reg_set_pid(r8a66597, pipenum, PID_BUF);
+}
+
+static inline void pipe_stop(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       control_reg_set_pid(r8a66597, pipenum, PID_NAK);
+}
+
+static inline void pipe_stall(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       control_reg_set_pid(r8a66597, pipenum, PID_STALL);
+}
+
+static inline u16 control_reg_get(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       u16 ret = 0;
+       unsigned long offset;
+
+       if (pipenum == 0) {
+               ret = r8a66597_read(r8a66597, DCPCTR);
+       } else if (pipenum < R8A66597_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               ret = r8a66597_read(r8a66597, offset);
+       } else {
+               dev_err(r8a66597_to_dev(r8a66597), "unexpect pipe num (%d)\n",
+                       pipenum);
+       }
+
+       return ret;
+}
+
+static inline void control_reg_sqclr(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       unsigned long offset;
+
+       pipe_stop(r8a66597, pipenum);
+
+       if (pipenum == 0) {
+               r8a66597_bset(r8a66597, SQCLR, DCPCTR);
+       } else if (pipenum < R8A66597_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               r8a66597_bset(r8a66597, SQCLR, offset);
+       } else {
+               dev_err(r8a66597_to_dev(r8a66597), "unexpect pipe num (%d)\n",
+                       pipenum);
+       }
+}
+
+static void control_reg_sqset(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       unsigned long offset;
+
+       pipe_stop(r8a66597, pipenum);
+
+       if (pipenum == 0) {
+               r8a66597_bset(r8a66597, SQSET, DCPCTR);
+       } else if (pipenum < R8A66597_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               r8a66597_bset(r8a66597, SQSET, offset);
+       } else {
+               dev_err(r8a66597_to_dev(r8a66597),
+                       "unexpect pipe num(%d)\n", pipenum);
+       }
+}
+
+static u16 control_reg_sqmon(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       unsigned long offset;
+
+       if (pipenum == 0) {
+               return r8a66597_read(r8a66597, DCPCTR) & SQMON;
+       } else if (pipenum < R8A66597_MAX_NUM_PIPE) {
+               offset = get_pipectr_addr(pipenum);
+               return r8a66597_read(r8a66597, offset) & SQMON;
+       } else {
+               dev_err(r8a66597_to_dev(r8a66597),
+                       "unexpect pipe num(%d)\n", pipenum);
+       }
+
+       return 0;
+}
+
+static u16 save_usb_toggle(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       return control_reg_sqmon(r8a66597, pipenum);
+}
+
+static void restore_usb_toggle(struct r8a66597 *r8a66597, u16 pipenum,
+                              u16 toggle)
+{
+       if (toggle)
+               control_reg_sqset(r8a66597, pipenum);
+       else
+               control_reg_sqclr(r8a66597, pipenum);
+}
+
+static inline int get_buffer_size(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       u16 tmp;
+       int size;
+
+       if (pipenum == 0) {
+               tmp = r8a66597_read(r8a66597, DCPCFG);
+               if ((tmp & R8A66597_CNTMD) != 0)
+                       size = 256;
+               else {
+                       tmp = r8a66597_read(r8a66597, DCPMAXP);
+                       size = tmp & MAXP;
+               }
+       } else {
+               r8a66597_write(r8a66597, pipenum, PIPESEL);
+               tmp = r8a66597_read(r8a66597, PIPECFG);
+               if ((tmp & R8A66597_CNTMD) != 0) {
+                       tmp = r8a66597_read(r8a66597, PIPEBUF);
+                       size = ((tmp >> 10) + 1) * 64;
+               } else {
+                       tmp = r8a66597_read(r8a66597, PIPEMAXP);
+                       size = tmp & MXPS;
+               }
+       }
+
+       return size;
+}
+
+static inline unsigned short mbw_value(struct r8a66597 *r8a66597)
+{
+       if (r8a66597->pdata->on_chip)
+               return MBW_32;
+       else
+               return MBW_16;
+}
+
+static void r8a66597_change_curpipe(struct r8a66597 *r8a66597, u16 pipenum,
+                                   u16 isel, u16 fifosel)
+{
+       u16 tmp, mask, loop;
+       int i = 0;
+
+       if (!pipenum) {
+               mask = ISEL | CURPIPE;
+               loop = isel;
+       } else {
+               mask = CURPIPE;
+               loop = pipenum;
+       }
+       r8a66597_mdfy(r8a66597, loop, mask, fifosel);
+
+       do {
+               tmp = r8a66597_read(r8a66597, fifosel);
+               if (i++ > 1000000) {
+                       dev_err(r8a66597_to_dev(r8a66597),
+                               "r8a66597: register%x, loop %x "
+                               "is timeout\n", fifosel, loop);
+                       break;
+               }
+               ndelay(1);
+       } while ((tmp & mask) != loop);
+}
+
+static inline void pipe_change(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       struct r8a66597_ep *ep = r8a66597->pipenum2ep[pipenum];
+
+       if (ep->use_dma)
+               r8a66597_bclr(r8a66597, DREQE, ep->fifosel);
+
+       r8a66597_mdfy(r8a66597, pipenum, CURPIPE, ep->fifosel);
+
+       ndelay(450);
+
+       if (r8a66597_is_sudmac(r8a66597) && ep->use_dma)
+               r8a66597_bclr(r8a66597, mbw_value(r8a66597), ep->fifosel);
+       else
+               r8a66597_bset(r8a66597, mbw_value(r8a66597), ep->fifosel);
+
+       if (ep->use_dma)
+               r8a66597_bset(r8a66597, DREQE, ep->fifosel);
+}
+
+static int pipe_buffer_setting(struct r8a66597 *r8a66597,
+               struct r8a66597_pipe_info *info)
+{
+       u16 bufnum = 0, buf_bsize = 0;
+       u16 pipecfg = 0;
+
+       if (info->pipe == 0)
+               return -EINVAL;
+
+       r8a66597_write(r8a66597, info->pipe, PIPESEL);
+
+       if (info->dir_in)
+               pipecfg |= R8A66597_DIR;
+       pipecfg |= info->type;
+       pipecfg |= info->epnum;
+       switch (info->type) {
+       case R8A66597_INT:
+               bufnum = 4 + (info->pipe - R8A66597_BASE_PIPENUM_INT);
+               buf_bsize = 0;
+               break;
+       case R8A66597_BULK:
+               /* isochronous pipes may be used as bulk pipes */
+               if (info->pipe >= R8A66597_BASE_PIPENUM_BULK)
+                       bufnum = info->pipe - R8A66597_BASE_PIPENUM_BULK;
+               else
+                       bufnum = info->pipe - R8A66597_BASE_PIPENUM_ISOC;
+
+               bufnum = R8A66597_BASE_BUFNUM + (bufnum * 16);
+               buf_bsize = 7;
+               pipecfg |= R8A66597_DBLB;
+               if (!info->dir_in)
+                       pipecfg |= R8A66597_SHTNAK;
+               break;
+       case R8A66597_ISO:
+               bufnum = R8A66597_BASE_BUFNUM +
+                        (info->pipe - R8A66597_BASE_PIPENUM_ISOC) * 16;
+               buf_bsize = 7;
+               break;
+       }
+
+       if (buf_bsize && ((bufnum + 16) >= R8A66597_MAX_BUFNUM)) {
+               pr_err("r8a66597 pipe memory is insufficient\n");
+               return -ENOMEM;
+       }
+
+       r8a66597_write(r8a66597, pipecfg, PIPECFG);
+       r8a66597_write(r8a66597, (buf_bsize << 10) | (bufnum), PIPEBUF);
+       r8a66597_write(r8a66597, info->maxpacket, PIPEMAXP);
+       if (info->interval)
+               info->interval--;
+       r8a66597_write(r8a66597, info->interval, PIPEPERI);
+
+       return 0;
+}
+
+static void pipe_buffer_release(struct r8a66597 *r8a66597,
+                               struct r8a66597_pipe_info *info)
+{
+       if (info->pipe == 0)
+               return;
+
+       if (is_bulk_pipe(info->pipe)) {
+               r8a66597->bulk--;
+       } else if (is_interrupt_pipe(info->pipe)) {
+               r8a66597->interrupt--;
+       } else if (is_isoc_pipe(info->pipe)) {
+               r8a66597->isochronous--;
+               if (info->type == R8A66597_BULK)
+                       r8a66597->bulk--;
+       } else {
+               dev_err(r8a66597_to_dev(r8a66597),
+                       "ep_release: unexpect pipenum (%d)\n", info->pipe);
+       }
+}
+
+static void pipe_initialize(struct r8a66597_ep *ep)
+{
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+
+       r8a66597_mdfy(r8a66597, 0, CURPIPE, ep->fifosel);
+
+       r8a66597_write(r8a66597, ACLRM, ep->pipectr);
+       r8a66597_write(r8a66597, 0, ep->pipectr);
+       r8a66597_write(r8a66597, SQCLR, ep->pipectr);
+       if (ep->use_dma) {
+               r8a66597_mdfy(r8a66597, ep->pipenum, CURPIPE, ep->fifosel);
+
+               ndelay(450);
+
+               r8a66597_bset(r8a66597, mbw_value(r8a66597), ep->fifosel);
+       }
+}
+
+static void r8a66597_ep_setting(struct r8a66597 *r8a66597,
+                               struct r8a66597_ep *ep,
+                               const struct usb_endpoint_descriptor *desc,
+                               u16 pipenum, int dma)
+{
+       ep->use_dma = 0;
+       ep->fifoaddr = CFIFO;
+       ep->fifosel = CFIFOSEL;
+       ep->fifoctr = CFIFOCTR;
+
+       ep->pipectr = get_pipectr_addr(pipenum);
+       if (is_bulk_pipe(pipenum) || is_isoc_pipe(pipenum)) {
+               ep->pipetre = get_pipetre_addr(pipenum);
+               ep->pipetrn = get_pipetrn_addr(pipenum);
+       } else {
+               ep->pipetre = 0;
+               ep->pipetrn = 0;
+       }
+       ep->pipenum = pipenum;
+       ep->ep.maxpacket = usb_endpoint_maxp(desc);
+       r8a66597->pipenum2ep[pipenum] = ep;
+       r8a66597->epaddr2ep[desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK]
+               = ep;
+       INIT_LIST_HEAD(&ep->queue);
+}
+
+static void r8a66597_ep_release(struct r8a66597_ep *ep)
+{
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+       u16 pipenum = ep->pipenum;
+
+       if (pipenum == 0)
+               return;
+
+       if (ep->use_dma)
+               r8a66597->num_dma--;
+       ep->pipenum = 0;
+       ep->busy = 0;
+       ep->use_dma = 0;
+}
+
+static int alloc_pipe_config(struct r8a66597_ep *ep,
+               const struct usb_endpoint_descriptor *desc)
+{
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+       struct r8a66597_pipe_info info;
+       int dma = 0;
+       unsigned char *counter;
+       int ret;
+
+       ep->ep.desc = desc;
+
+       if (ep->pipenum)        /* already allocated pipe  */
+               return 0;
+
+       switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+       case USB_ENDPOINT_XFER_BULK:
+               if (r8a66597->bulk >= R8A66597_MAX_NUM_BULK) {
+                       if (r8a66597->isochronous >= R8A66597_MAX_NUM_ISOC) {
+                               dev_err(r8a66597_to_dev(r8a66597),
+                                       "bulk pipe is insufficient\n");
+                               return -ENODEV;
+                       } else {
+                               info.pipe = R8A66597_BASE_PIPENUM_ISOC
+                                               + r8a66597->isochronous;
+                               counter = &r8a66597->isochronous;
+                       }
+               } else {
+                       info.pipe = R8A66597_BASE_PIPENUM_BULK + r8a66597->bulk;
+                       counter = &r8a66597->bulk;
+               }
+               info.type = R8A66597_BULK;
+               dma = 1;
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               if (r8a66597->interrupt >= R8A66597_MAX_NUM_INT) {
+                       dev_err(r8a66597_to_dev(r8a66597),
+                               "interrupt pipe is insufficient\n");
+                       return -ENODEV;
+               }
+               info.pipe = R8A66597_BASE_PIPENUM_INT + r8a66597->interrupt;
+               info.type = R8A66597_INT;
+               counter = &r8a66597->interrupt;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               if (r8a66597->isochronous >= R8A66597_MAX_NUM_ISOC) {
+                       dev_err(r8a66597_to_dev(r8a66597),
+                               "isochronous pipe is insufficient\n");
+                       return -ENODEV;
+               }
+               info.pipe = R8A66597_BASE_PIPENUM_ISOC + r8a66597->isochronous;
+               info.type = R8A66597_ISO;
+               counter = &r8a66597->isochronous;
+               break;
+       default:
+               dev_err(r8a66597_to_dev(r8a66597), "unexpect xfer type\n");
+               return -EINVAL;
+       }
+       ep->type = info.type;
+
+       info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+       info.maxpacket = usb_endpoint_maxp(desc);
+       info.interval = desc->bInterval;
+       if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+               info.dir_in = 1;
+       else
+               info.dir_in = 0;
+
+       ret = pipe_buffer_setting(r8a66597, &info);
+       if (ret < 0) {
+               dev_err(r8a66597_to_dev(r8a66597),
+                       "pipe_buffer_setting fail\n");
+               return ret;
+       }
+
+       (*counter)++;
+       if ((counter == &r8a66597->isochronous) && info.type == R8A66597_BULK)
+               r8a66597->bulk++;
+
+       r8a66597_ep_setting(r8a66597, ep, desc, info.pipe, dma);
+       pipe_initialize(ep);
+
+       return 0;
+}
+
+static int free_pipe_config(struct r8a66597_ep *ep)
+{
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+       struct r8a66597_pipe_info info;
+
+       info.pipe = ep->pipenum;
+       info.type = ep->type;
+       pipe_buffer_release(r8a66597, &info);
+       r8a66597_ep_release(ep);
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static void pipe_irq_enable(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       enable_irq_ready(r8a66597, pipenum);
+       enable_irq_nrdy(r8a66597, pipenum);
+}
+
+static void pipe_irq_disable(struct r8a66597 *r8a66597, u16 pipenum)
+{
+       disable_irq_ready(r8a66597, pipenum);
+       disable_irq_nrdy(r8a66597, pipenum);
+}
+
+/* if complete is true, gadget driver complete function is not call */
+static void control_end(struct r8a66597 *r8a66597, unsigned ccpl)
+{
+       r8a66597->ep[0].internal_ccpl = ccpl;
+       pipe_start(r8a66597, 0);
+       r8a66597_bset(r8a66597, CCPL, DCPCTR);
+}
+
+static void start_ep0_write(struct r8a66597_ep *ep,
+                               struct r8a66597_request *req)
+{
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+
+       pipe_change(r8a66597, ep->pipenum);
+       r8a66597_mdfy(r8a66597, ISEL, (ISEL | CURPIPE), CFIFOSEL);
+       r8a66597_write(r8a66597, BCLR, ep->fifoctr);
+       if (req->req.length == 0) {
+               r8a66597_bset(r8a66597, BVAL, ep->fifoctr);
+               pipe_start(r8a66597, 0);
+               transfer_complete(ep, req, 0);
+       } else {
+               r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
+               irq_ep0_write(ep, req);
+       }
+}
+
+static void disable_fifosel(struct r8a66597 *r8a66597, u16 pipenum,
+                           u16 fifosel)
+{
+       u16 tmp;
+
+       tmp = r8a66597_read(r8a66597, fifosel) & CURPIPE;
+       if (tmp == pipenum)
+               r8a66597_change_curpipe(r8a66597, 0, 0, fifosel);
+}
+
+static void change_bfre_mode(struct r8a66597 *r8a66597, u16 pipenum,
+                            int enable)
+{
+       struct r8a66597_ep *ep = r8a66597->pipenum2ep[pipenum];
+       u16 tmp, toggle;
+
+       /* check current BFRE bit */
+       r8a66597_write(r8a66597, pipenum, PIPESEL);
+       tmp = r8a66597_read(r8a66597, PIPECFG) & R8A66597_BFRE;
+       if ((enable && tmp) || (!enable && !tmp))
+               return;
+
+       /* change BFRE bit */
+       pipe_stop(r8a66597, pipenum);
+       disable_fifosel(r8a66597, pipenum, CFIFOSEL);
+       disable_fifosel(r8a66597, pipenum, D0FIFOSEL);
+       disable_fifosel(r8a66597, pipenum, D1FIFOSEL);
+
+       toggle = save_usb_toggle(r8a66597, pipenum);
+
+       r8a66597_write(r8a66597, pipenum, PIPESEL);
+       if (enable)
+               r8a66597_bset(r8a66597, R8A66597_BFRE, PIPECFG);
+       else
+               r8a66597_bclr(r8a66597, R8A66597_BFRE, PIPECFG);
+
+       /* initialize for internal BFRE flag */
+       r8a66597_bset(r8a66597, ACLRM, ep->pipectr);
+       r8a66597_bclr(r8a66597, ACLRM, ep->pipectr);
+
+       restore_usb_toggle(r8a66597, pipenum, toggle);
+}
+
+static int sudmac_alloc_channel(struct r8a66597 *r8a66597,
+                               struct r8a66597_ep *ep,
+                               struct r8a66597_request *req)
+{
+       struct r8a66597_dma *dma;
+
+       if (!r8a66597_is_sudmac(r8a66597))
+               return -ENODEV;
+
+       /* Check transfer type */
+       if (!is_bulk_pipe(ep->pipenum))
+               return -EIO;
+
+       if (r8a66597->dma.used)
+               return -EBUSY;
+
+       /* set SUDMAC parameters */
+       dma = &r8a66597->dma;
+       dma->used = 1;
+       if (ep->ep.desc->bEndpointAddress & USB_DIR_IN) {
+               dma->dir = 1;
+       } else {
+               dma->dir = 0;
+               change_bfre_mode(r8a66597, ep->pipenum, 1);
+       }
+
+       /* set r8a66597_ep paramters */
+       ep->use_dma = 1;
+       ep->dma = dma;
+       ep->fifoaddr = D0FIFO;
+       ep->fifosel = D0FIFOSEL;
+       ep->fifoctr = D0FIFOCTR;
+
+       /* dma mapping */
+       return usb_gadget_map_request(&r8a66597->gadget, &req->req, dma->dir);
+}
+
+static void sudmac_free_channel(struct r8a66597 *r8a66597,
+                               struct r8a66597_ep *ep,
+                               struct r8a66597_request *req)
+{
+       if (!r8a66597_is_sudmac(r8a66597))
+               return;
+
+       usb_gadget_unmap_request(&r8a66597->gadget, &req->req, ep->dma->dir);
+
+       r8a66597_bclr(r8a66597, DREQE, ep->fifosel);
+       r8a66597_change_curpipe(r8a66597, 0, 0, ep->fifosel);
+
+       ep->dma->used = 0;
+       ep->use_dma = 0;
+       ep->fifoaddr = CFIFO;
+       ep->fifosel = CFIFOSEL;
+       ep->fifoctr = CFIFOCTR;
+}
+
+static void sudmac_start(struct r8a66597 *r8a66597, struct r8a66597_ep *ep,
+                        struct r8a66597_request *req)
+{
+       BUG_ON(req->req.length == 0);
+
+       r8a66597_sudmac_write(r8a66597, LBA_WAIT, CH0CFG);
+       r8a66597_sudmac_write(r8a66597, req->req.dma, CH0BA);
+       r8a66597_sudmac_write(r8a66597, req->req.length, CH0BBC);
+       r8a66597_sudmac_write(r8a66597, CH0ENDE, DINTCTRL);
+
+       r8a66597_sudmac_write(r8a66597, DEN, CH0DEN);
+}
+
+static void start_packet_write(struct r8a66597_ep *ep,
+                               struct r8a66597_request *req)
+{
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+       u16 tmp;
+
+       pipe_change(r8a66597, ep->pipenum);
+       disable_irq_empty(r8a66597, ep->pipenum);
+       pipe_start(r8a66597, ep->pipenum);
+
+       if (req->req.length == 0) {
+               transfer_complete(ep, req, 0);
+       } else {
+               r8a66597_write(r8a66597, ~(1 << ep->pipenum), BRDYSTS);
+               if (sudmac_alloc_channel(r8a66597, ep, req) < 0) {
+                       /* PIO mode */
+                       pipe_change(r8a66597, ep->pipenum);
+                       disable_irq_empty(r8a66597, ep->pipenum);
+                       pipe_start(r8a66597, ep->pipenum);
+                       tmp = r8a66597_read(r8a66597, ep->fifoctr);
+                       if (unlikely((tmp & FRDY) == 0))
+                               pipe_irq_enable(r8a66597, ep->pipenum);
+                       else
+                               irq_packet_write(ep, req);
+               } else {
+                       /* DMA mode */
+                       pipe_change(r8a66597, ep->pipenum);
+                       disable_irq_nrdy(r8a66597, ep->pipenum);
+                       pipe_start(r8a66597, ep->pipenum);
+                       enable_irq_nrdy(r8a66597, ep->pipenum);
+                       sudmac_start(r8a66597, ep, req);
+               }
+       }
+}
+
+static void start_packet_read(struct r8a66597_ep *ep,
+                               struct r8a66597_request *req)
+{
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+       u16 pipenum = ep->pipenum;
+
+       if (ep->pipenum == 0) {
+               r8a66597_mdfy(r8a66597, 0, (ISEL | CURPIPE), CFIFOSEL);
+               r8a66597_write(r8a66597, BCLR, ep->fifoctr);
+               pipe_start(r8a66597, pipenum);
+               pipe_irq_enable(r8a66597, pipenum);
+       } else {
+               pipe_stop(r8a66597, pipenum);
+               if (ep->pipetre) {
+                       enable_irq_nrdy(r8a66597, pipenum);
+                       r8a66597_write(r8a66597, TRCLR, ep->pipetre);
+                       r8a66597_write(r8a66597,
+                               DIV_ROUND_UP(req->req.length, ep->ep.maxpacket),
+                               ep->pipetrn);
+                       r8a66597_bset(r8a66597, TRENB, ep->pipetre);
+               }
+
+               if (sudmac_alloc_channel(r8a66597, ep, req) < 0) {
+                       /* PIO mode */
+                       change_bfre_mode(r8a66597, ep->pipenum, 0);
+                       pipe_start(r8a66597, pipenum);  /* trigger once */
+                       pipe_irq_enable(r8a66597, pipenum);
+               } else {
+                       pipe_change(r8a66597, pipenum);
+                       sudmac_start(r8a66597, ep, req);
+                       pipe_start(r8a66597, pipenum);  /* trigger once */
+               }
+       }
+}
+
+static void start_packet(struct r8a66597_ep *ep, struct r8a66597_request *req)
+{
+       if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
+               start_packet_write(ep, req);
+       else
+               start_packet_read(ep, req);
+}
+
+static void start_ep0(struct r8a66597_ep *ep, struct r8a66597_request *req)
+{
+       u16 ctsq;
+
+       ctsq = r8a66597_read(ep->r8a66597, INTSTS0) & CTSQ;
+
+       switch (ctsq) {
+       case CS_RDDS:
+               start_ep0_write(ep, req);
+               break;
+       case CS_WRDS:
+               start_packet_read(ep, req);
+               break;
+
+       case CS_WRND:
+               control_end(ep->r8a66597, 0);
+               break;
+       default:
+               dev_err(r8a66597_to_dev(ep->r8a66597),
+                       "start_ep0: unexpect ctsq(%x)\n", ctsq);
+               break;
+       }
+}
+
+static void init_controller(struct r8a66597 *r8a66597)
+{
+       u16 vif = r8a66597->pdata->vif ? LDRV : 0;
+       u16 irq_sense = r8a66597->irq_sense_low ? INTL : 0;
+       u16 endian = r8a66597->pdata->endian ? BIGEND : 0;
+
+       if (r8a66597->pdata->on_chip) {
+               if (r8a66597->pdata->buswait)
+                       r8a66597_write(r8a66597, r8a66597->pdata->buswait,
+                                       SYSCFG1);
+               else
+                       r8a66597_write(r8a66597, 0x0f, SYSCFG1);
+               r8a66597_bset(r8a66597, HSE, SYSCFG0);
+
+               r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+               r8a66597_bclr(r8a66597, DPRPU, SYSCFG0);
+               r8a66597_bset(r8a66597, USBE, SYSCFG0);
+
+               r8a66597_bset(r8a66597, SCKE, SYSCFG0);
+
+               r8a66597_bset(r8a66597, irq_sense, INTENB1);
+               r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR,
+                               DMA0CFG);
+       } else {
+               r8a66597_bset(r8a66597, vif | endian, PINCFG);
+               r8a66597_bset(r8a66597, HSE, SYSCFG0);          /* High spd */
+               r8a66597_mdfy(r8a66597, get_xtal_from_pdata(r8a66597->pdata),
+                               XTAL, SYSCFG0);
+
+               r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+               r8a66597_bclr(r8a66597, DPRPU, SYSCFG0);
+               r8a66597_bset(r8a66597, USBE, SYSCFG0);
+
+               r8a66597_bset(r8a66597, XCKE, SYSCFG0);
+
+               msleep(3);
+
+               r8a66597_bset(r8a66597, PLLC, SYSCFG0);
+
+               msleep(1);
+
+               r8a66597_bset(r8a66597, SCKE, SYSCFG0);
+
+               r8a66597_bset(r8a66597, irq_sense, INTENB1);
+               r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR,
+                              DMA0CFG);
+       }
+}
+
+static void disable_controller(struct r8a66597 *r8a66597)
+{
+       if (r8a66597->pdata->on_chip) {
+               r8a66597_bset(r8a66597, SCKE, SYSCFG0);
+               r8a66597_bclr(r8a66597, UTST, TESTMODE);
+
+               /* disable interrupts */
+               r8a66597_write(r8a66597, 0, INTENB0);
+               r8a66597_write(r8a66597, 0, INTENB1);
+               r8a66597_write(r8a66597, 0, BRDYENB);
+               r8a66597_write(r8a66597, 0, BEMPENB);
+               r8a66597_write(r8a66597, 0, NRDYENB);
+
+               /* clear status */
+               r8a66597_write(r8a66597, 0, BRDYSTS);
+               r8a66597_write(r8a66597, 0, NRDYSTS);
+               r8a66597_write(r8a66597, 0, BEMPSTS);
+
+               r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+               r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
+
+       } else {
+               r8a66597_bclr(r8a66597, UTST, TESTMODE);
+               r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
+               udelay(1);
+               r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
+               udelay(1);
+               udelay(1);
+               r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
+       }
+}
+
+static void r8a66597_start_xclock(struct r8a66597 *r8a66597)
+{
+       u16 tmp;
+
+       if (!r8a66597->pdata->on_chip) {
+               tmp = r8a66597_read(r8a66597, SYSCFG0);
+               if (!(tmp & XCKE))
+                       r8a66597_bset(r8a66597, XCKE, SYSCFG0);
+       }
+}
+
+static struct r8a66597_request *get_request_from_ep(struct r8a66597_ep *ep)
+{
+       return list_entry(ep->queue.next, struct r8a66597_request, queue);
+}
+
+/*-------------------------------------------------------------------------*/
+static void transfer_complete(struct r8a66597_ep *ep,
+               struct r8a66597_request *req, int status)
+__releases(r8a66597->lock)
+__acquires(r8a66597->lock)
+{
+       int restart = 0;
+
+       if (unlikely(ep->pipenum == 0)) {
+               if (ep->internal_ccpl) {
+                       ep->internal_ccpl = 0;
+                       return;
+               }
+       }
+
+       list_del_init(&req->queue);
+       if (ep->r8a66597->gadget.speed == USB_SPEED_UNKNOWN)
+               req->req.status = -ESHUTDOWN;
+       else
+               req->req.status = status;
+
+       if (!list_empty(&ep->queue))
+               restart = 1;
+
+       if (ep->use_dma)
+               sudmac_free_channel(ep->r8a66597, ep, req);
+
+       spin_unlock(&ep->r8a66597->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&ep->r8a66597->lock);
+
+       if (restart) {
+               req = get_request_from_ep(ep);
+               if (ep->ep.desc)
+                       start_packet(ep, req);
+       }
+}
+
+static void irq_ep0_write(struct r8a66597_ep *ep, struct r8a66597_request *req)
+{
+       int i;
+       u16 tmp;
+       unsigned bufsize;
+       size_t size;
+       void *buf;
+       u16 pipenum = ep->pipenum;
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+
+       pipe_change(r8a66597, pipenum);
+       r8a66597_bset(r8a66597, ISEL, ep->fifosel);
+
+       i = 0;
+       do {
+               tmp = r8a66597_read(r8a66597, ep->fifoctr);
+               if (i++ > 100000) {
+                       dev_err(r8a66597_to_dev(r8a66597),
+                               "pipe0 is busy. maybe cpu i/o bus "
+                               "conflict. please power off this controller.");
+                       return;
+               }
+               ndelay(1);
+       } while ((tmp & FRDY) == 0);
+
+       /* prepare parameters */
+       bufsize = get_buffer_size(r8a66597, pipenum);
+       buf = req->req.buf + req->req.actual;
+       size = min(bufsize, req->req.length - req->req.actual);
+
+       /* write fifo */
+       if (req->req.buf) {
+               if (size > 0)
+                       r8a66597_write_fifo(r8a66597, ep, buf, size);
+               if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
+                       r8a66597_bset(r8a66597, BVAL, ep->fifoctr);
+       }
+
+       /* update parameters */
+       req->req.actual += size;
+
+       /* check transfer finish */
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
+               disable_irq_ready(r8a66597, pipenum);
+               disable_irq_empty(r8a66597, pipenum);
+       } else {
+               disable_irq_ready(r8a66597, pipenum);
+               enable_irq_empty(r8a66597, pipenum);
+       }
+       pipe_start(r8a66597, pipenum);
+}
+
+static void irq_packet_write(struct r8a66597_ep *ep,
+                               struct r8a66597_request *req)
+{
+       u16 tmp;
+       unsigned bufsize;
+       size_t size;
+       void *buf;
+       u16 pipenum = ep->pipenum;
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+
+       pipe_change(r8a66597, pipenum);
+       tmp = r8a66597_read(r8a66597, ep->fifoctr);
+       if (unlikely((tmp & FRDY) == 0)) {
+               pipe_stop(r8a66597, pipenum);
+               pipe_irq_disable(r8a66597, pipenum);
+               dev_err(r8a66597_to_dev(r8a66597),
+                       "write fifo not ready. pipnum=%d\n", pipenum);
+               return;
+       }
+
+       /* prepare parameters */
+       bufsize = get_buffer_size(r8a66597, pipenum);
+       buf = req->req.buf + req->req.actual;
+       size = min(bufsize, req->req.length - req->req.actual);
+
+       /* write fifo */
+       if (req->req.buf) {
+               r8a66597_write_fifo(r8a66597, ep, buf, size);
+               if ((size == 0)
+                               || ((size % ep->ep.maxpacket) != 0)
+                               || ((bufsize != ep->ep.maxpacket)
+                                       && (bufsize > size)))
+                       r8a66597_bset(r8a66597, BVAL, ep->fifoctr);
+       }
+
+       /* update parameters */
+       req->req.actual += size;
+       /* check transfer finish */
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
+               disable_irq_ready(r8a66597, pipenum);
+               enable_irq_empty(r8a66597, pipenum);
+       } else {
+               disable_irq_empty(r8a66597, pipenum);
+               pipe_irq_enable(r8a66597, pipenum);
+       }
+}
+
+static void irq_packet_read(struct r8a66597_ep *ep,
+                               struct r8a66597_request *req)
+{
+       u16 tmp;
+       int rcv_len, bufsize, req_len;
+       int size;
+       void *buf;
+       u16 pipenum = ep->pipenum;
+       struct r8a66597 *r8a66597 = ep->r8a66597;
+       int finish = 0;
+
+       pipe_change(r8a66597, pipenum);
+       tmp = r8a66597_read(r8a66597, ep->fifoctr);
+       if (unlikely((tmp & FRDY) == 0)) {
+               req->req.status = -EPIPE;
+               pipe_stop(r8a66597, pipenum);
+               pipe_irq_disable(r8a66597, pipenum);
+               dev_err(r8a66597_to_dev(r8a66597), "read fifo not ready");
+               return;
+       }
+
+       /* prepare parameters */
+       rcv_len = tmp & DTLN;
+       bufsize = get_buffer_size(r8a66597, pipenum);
+
+       buf = req->req.buf + req->req.actual;
+       req_len = req->req.length - req->req.actual;
+       if (rcv_len < bufsize)
+               size = min(rcv_len, req_len);
+       else
+               size = min(bufsize, req_len);
+
+       /* update parameters */
+       req->req.actual += size;
+
+       /* check transfer finish */
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
+               pipe_stop(r8a66597, pipenum);
+               pipe_irq_disable(r8a66597, pipenum);
+               finish = 1;
+       }
+
+       /* read fifo */
+       if (req->req.buf) {
+               if (size == 0)
+                       r8a66597_write(r8a66597, BCLR, ep->fifoctr);
+               else
+                       r8a66597_read_fifo(r8a66597, ep->fifoaddr, buf, size);
+
+       }
+
+       if ((ep->pipenum != 0) && finish)
+               transfer_complete(ep, req, 0);
+}
+
+static void irq_pipe_ready(struct r8a66597 *r8a66597, u16 status, u16 enb)
+{
+       u16 check;
+       u16 pipenum;
+       struct r8a66597_ep *ep;
+       struct r8a66597_request *req;
+
+       if ((status & BRDY0) && (enb & BRDY0)) {
+               r8a66597_write(r8a66597, ~BRDY0, BRDYSTS);
+               r8a66597_mdfy(r8a66597, 0, CURPIPE, CFIFOSEL);
+
+               ep = &r8a66597->ep[0];
+               req = get_request_from_ep(ep);
+               irq_packet_read(ep, req);
+       } else {
+               for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+                       check = 1 << pipenum;
+                       if ((status & check) && (enb & check)) {
+                               r8a66597_write(r8a66597, ~check, BRDYSTS);
+                               ep = r8a66597->pipenum2ep[pipenum];
+                               req = get_request_from_ep(ep);
+                               if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
+                                       irq_packet_write(ep, req);
+                               else
+                                       irq_packet_read(ep, req);
+                       }
+               }
+       }
+}
+
+static void irq_pipe_empty(struct r8a66597 *r8a66597, u16 status, u16 enb)
+{
+       u16 tmp;
+       u16 check;
+       u16 pipenum;
+       struct r8a66597_ep *ep;
+       struct r8a66597_request *req;
+
+       if ((status & BEMP0) && (enb & BEMP0)) {
+               r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
+
+               ep = &r8a66597->ep[0];
+               req = get_request_from_ep(ep);
+               irq_ep0_write(ep, req);
+       } else {
+               for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+                       check = 1 << pipenum;
+                       if ((status & check) && (enb & check)) {
+                               r8a66597_write(r8a66597, ~check, BEMPSTS);
+                               tmp = control_reg_get(r8a66597, pipenum);
+                               if ((tmp & INBUFM) == 0) {
+                                       disable_irq_empty(r8a66597, pipenum);
+                                       pipe_irq_disable(r8a66597, pipenum);
+                                       pipe_stop(r8a66597, pipenum);
+                                       ep = r8a66597->pipenum2ep[pipenum];
+                                       req = get_request_from_ep(ep);
+                                       if (!list_empty(&ep->queue))
+                                               transfer_complete(ep, req, 0);
+                               }
+                       }
+               }
+       }
+}
+
+static void get_status(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl)
+__releases(r8a66597->lock)
+__acquires(r8a66597->lock)
+{
+       struct r8a66597_ep *ep;
+       u16 pid;
+       u16 status = 0;
+       u16 w_index = le16_to_cpu(ctrl->wIndex);
+
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               status = r8a66597->device_status;
+               break;
+       case USB_RECIP_INTERFACE:
+               status = 0;
+               break;
+       case USB_RECIP_ENDPOINT:
+               ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
+               pid = control_reg_get_pid(r8a66597, ep->pipenum);
+               if (pid == PID_STALL)
+                       status = 1 << USB_ENDPOINT_HALT;
+               else
+                       status = 0;
+               break;
+       default:
+               pipe_stall(r8a66597, 0);
+               return;         /* exit */
+       }
+
+       r8a66597->ep0_data = cpu_to_le16(status);
+       r8a66597->ep0_req->buf = &r8a66597->ep0_data;
+       r8a66597->ep0_req->length = 2;
+       /* AV: what happens if we get called again before that gets through? */
+       spin_unlock(&r8a66597->lock);
+       r8a66597_queue(r8a66597->gadget.ep0, r8a66597->ep0_req, GFP_KERNEL);
+       spin_lock(&r8a66597->lock);
+}
+
+static void clear_feature(struct r8a66597 *r8a66597,
+                               struct usb_ctrlrequest *ctrl)
+{
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               control_end(r8a66597, 1);
+               break;
+       case USB_RECIP_INTERFACE:
+               control_end(r8a66597, 1);
+               break;
+       case USB_RECIP_ENDPOINT: {
+               struct r8a66597_ep *ep;
+               struct r8a66597_request *req;
+               u16 w_index = le16_to_cpu(ctrl->wIndex);
+
+               ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
+               if (!ep->wedge) {
+                       pipe_stop(r8a66597, ep->pipenum);
+                       control_reg_sqclr(r8a66597, ep->pipenum);
+                       spin_unlock(&r8a66597->lock);
+                       usb_ep_clear_halt(&ep->ep);
+                       spin_lock(&r8a66597->lock);
+               }
+
+               control_end(r8a66597, 1);
+
+               req = get_request_from_ep(ep);
+               if (ep->busy) {
+                       ep->busy = 0;
+                       if (list_empty(&ep->queue))
+                               break;
+                       start_packet(ep, req);
+               } else if (!list_empty(&ep->queue))
+                       pipe_start(r8a66597, ep->pipenum);
+               }
+               break;
+       default:
+               pipe_stall(r8a66597, 0);
+               break;
+       }
+}
+
+static void set_feature(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl)
+{
+       u16 tmp;
+       int timeout = 3000;
+
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               switch (le16_to_cpu(ctrl->wValue)) {
+               case USB_DEVICE_TEST_MODE:
+                       control_end(r8a66597, 1);
+                       /* Wait for the completion of status stage */
+                       do {
+                               tmp = r8a66597_read(r8a66597, INTSTS0) & CTSQ;
+                               udelay(1);
+                       } while (tmp != CS_IDST || timeout-- > 0);
+
+                       if (tmp == CS_IDST)
+                               r8a66597_bset(r8a66597,
+                                             le16_to_cpu(ctrl->wIndex >> 8),
+                                             TESTMODE);
+                       break;
+               default:
+                       pipe_stall(r8a66597, 0);
+                       break;
+               }
+               break;
+       case USB_RECIP_INTERFACE:
+               control_end(r8a66597, 1);
+               break;
+       case USB_RECIP_ENDPOINT: {
+               struct r8a66597_ep *ep;
+               u16 w_index = le16_to_cpu(ctrl->wIndex);
+
+               ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
+               pipe_stall(r8a66597, ep->pipenum);
+
+               control_end(r8a66597, 1);
+               }
+               break;
+       default:
+               pipe_stall(r8a66597, 0);
+               break;
+       }
+}
+
+/* if return value is true, call class driver's setup() */
+static int setup_packet(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl)
+{
+       u16 *p = (u16 *)ctrl;
+       unsigned long offset = USBREQ;
+       int i, ret = 0;
+
+       /* read fifo */
+       r8a66597_write(r8a66597, ~VALID, INTSTS0);
+
+       for (i = 0; i < 4; i++)
+               p[i] = r8a66597_read(r8a66597, offset + i*2);
+
+       /* check request */
+       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+               switch (ctrl->bRequest) {
+               case USB_REQ_GET_STATUS:
+                       get_status(r8a66597, ctrl);
+                       break;
+               case USB_REQ_CLEAR_FEATURE:
+                       clear_feature(r8a66597, ctrl);
+                       break;
+               case USB_REQ_SET_FEATURE:
+                       set_feature(r8a66597, ctrl);
+                       break;
+               default:
+                       ret = 1;
+                       break;
+               }
+       } else
+               ret = 1;
+       return ret;
+}
+
+static void r8a66597_update_usb_speed(struct r8a66597 *r8a66597)
+{
+       u16 speed = get_usb_speed(r8a66597);
+
+       switch (speed) {
+       case HSMODE:
+               r8a66597->gadget.speed = USB_SPEED_HIGH;
+               break;
+       case FSMODE:
+               r8a66597->gadget.speed = USB_SPEED_FULL;
+               break;
+       default:
+               r8a66597->gadget.speed = USB_SPEED_UNKNOWN;
+               dev_err(r8a66597_to_dev(r8a66597), "USB speed unknown\n");
+       }
+}
+
+static void irq_device_state(struct r8a66597 *r8a66597)
+{
+       u16 dvsq;
+
+       dvsq = r8a66597_read(r8a66597, INTSTS0) & DVSQ;
+       r8a66597_write(r8a66597, ~DVST, INTSTS0);
+
+       if (dvsq == DS_DFLT) {
+               /* bus reset */
+               spin_unlock(&r8a66597->lock);
+               r8a66597->driver->disconnect(&r8a66597->gadget);
+               spin_lock(&r8a66597->lock);
+               r8a66597_update_usb_speed(r8a66597);
+       }
+       if (r8a66597->old_dvsq == DS_CNFG && dvsq != DS_CNFG)
+               r8a66597_update_usb_speed(r8a66597);
+       if ((dvsq == DS_CNFG || dvsq == DS_ADDS)
+                       && r8a66597->gadget.speed == USB_SPEED_UNKNOWN)
+               r8a66597_update_usb_speed(r8a66597);
+
+       r8a66597->old_dvsq = dvsq;
+}
+
+static void irq_control_stage(struct r8a66597 *r8a66597)
+__releases(r8a66597->lock)
+__acquires(r8a66597->lock)
+{
+       struct usb_ctrlrequest ctrl;
+       u16 ctsq;
+
+       ctsq = r8a66597_read(r8a66597, INTSTS0) & CTSQ;
+       r8a66597_write(r8a66597, ~CTRT, INTSTS0);
+
+       switch (ctsq) {
+       case CS_IDST: {
+               struct r8a66597_ep *ep;
+               struct r8a66597_request *req;
+               ep = &r8a66597->ep[0];
+               req = get_request_from_ep(ep);
+               transfer_complete(ep, req, 0);
+               }
+               break;
+
+       case CS_RDDS:
+       case CS_WRDS:
+       case CS_WRND:
+               if (setup_packet(r8a66597, &ctrl)) {
+                       spin_unlock(&r8a66597->lock);
+                       if (r8a66597->driver->setup(&r8a66597->gadget, &ctrl)
+                               < 0)
+                               pipe_stall(r8a66597, 0);
+                       spin_lock(&r8a66597->lock);
+               }
+               break;
+       case CS_RDSS:
+       case CS_WRSS:
+               control_end(r8a66597, 0);
+               break;
+       default:
+               dev_err(r8a66597_to_dev(r8a66597),
+                       "ctrl_stage: unexpect ctsq(%x)\n", ctsq);
+               break;
+       }
+}
+
+static void sudmac_finish(struct r8a66597 *r8a66597, struct r8a66597_ep *ep)
+{
+       u16 pipenum;
+       struct r8a66597_request *req;
+       u32 len;
+       int i = 0;
+
+       pipenum = ep->pipenum;
+       pipe_change(r8a66597, pipenum);
+
+       while (!(r8a66597_read(r8a66597, ep->fifoctr) & FRDY)) {
+               udelay(1);
+               if (unlikely(i++ >= 10000)) {   /* timeout = 10 msec */
+                       dev_err(r8a66597_to_dev(r8a66597),
+                               "%s: FRDY was not set (%d)\n",
+                               __func__, pipenum);
+                       return;
+               }
+       }
+
+       r8a66597_bset(r8a66597, BCLR, ep->fifoctr);
+       req = get_request_from_ep(ep);
+
+       /* prepare parameters */
+       len = r8a66597_sudmac_read(r8a66597, CH0CBC);
+       req->req.actual += len;
+
+       /* clear */
+       r8a66597_sudmac_write(r8a66597, CH0STCLR, DSTSCLR);
+
+       /* check transfer finish */
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (len % ep->ep.maxpacket)) {
+               if (ep->dma->dir) {
+                       disable_irq_ready(r8a66597, pipenum);
+                       enable_irq_empty(r8a66597, pipenum);
+               } else {
+                       /* Clear the interrupt flag for next transfer */
+                       r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS);
+                       transfer_complete(ep, req, 0);
+               }
+       }
+}
+
+static void r8a66597_sudmac_irq(struct r8a66597 *r8a66597)
+{
+       u32 irqsts;
+       struct r8a66597_ep *ep;
+       u16 pipenum;
+
+       irqsts = r8a66597_sudmac_read(r8a66597, DINTSTS);
+       if (irqsts & CH0ENDS) {
+               r8a66597_sudmac_write(r8a66597, CH0ENDC, DINTSTSCLR);
+               pipenum = (r8a66597_read(r8a66597, D0FIFOSEL) & CURPIPE);
+               ep = r8a66597->pipenum2ep[pipenum];
+               sudmac_finish(r8a66597, ep);
+       }
+}
+
+static irqreturn_t r8a66597_irq(int irq, void *_r8a66597)
+{
+       struct r8a66597 *r8a66597 = _r8a66597;
+       u16 intsts0;
+       u16 intenb0;
+       u16 brdysts, nrdysts, bempsts;
+       u16 brdyenb, nrdyenb, bempenb;
+       u16 savepipe;
+       u16 mask0;
+
+       spin_lock(&r8a66597->lock);
+
+       if (r8a66597_is_sudmac(r8a66597))
+               r8a66597_sudmac_irq(r8a66597);
+
+       intsts0 = r8a66597_read(r8a66597, INTSTS0);
+       intenb0 = r8a66597_read(r8a66597, INTENB0);
+
+       savepipe = r8a66597_read(r8a66597, CFIFOSEL);
+
+       mask0 = intsts0 & intenb0;
+       if (mask0) {
+               brdysts = r8a66597_read(r8a66597, BRDYSTS);
+               nrdysts = r8a66597_read(r8a66597, NRDYSTS);
+               bempsts = r8a66597_read(r8a66597, BEMPSTS);
+               brdyenb = r8a66597_read(r8a66597, BRDYENB);
+               nrdyenb = r8a66597_read(r8a66597, NRDYENB);
+               bempenb = r8a66597_read(r8a66597, BEMPENB);
+
+               if (mask0 & VBINT) {
+                       r8a66597_write(r8a66597,  0xffff & ~VBINT,
+                                       INTSTS0);
+                       r8a66597_start_xclock(r8a66597);
+
+                       /* start vbus sampling */
+                       r8a66597->old_vbus = r8a66597_read(r8a66597, INTSTS0)
+                                       & VBSTS;
+                       r8a66597->scount = R8A66597_MAX_SAMPLING;
+
+                       mod_timer(&r8a66597->timer,
+                                       jiffies + msecs_to_jiffies(50));
+               }
+               if (intsts0 & DVSQ)
+                       irq_device_state(r8a66597);
+
+               if ((intsts0 & BRDY) && (intenb0 & BRDYE)
+                               && (brdysts & brdyenb))
+                       irq_pipe_ready(r8a66597, brdysts, brdyenb);
+               if ((intsts0 & BEMP) && (intenb0 & BEMPE)
+                               && (bempsts & bempenb))
+                       irq_pipe_empty(r8a66597, bempsts, bempenb);
+
+               if (intsts0 & CTRT)
+                       irq_control_stage(r8a66597);
+       }
+
+       r8a66597_write(r8a66597, savepipe, CFIFOSEL);
+
+       spin_unlock(&r8a66597->lock);
+       return IRQ_HANDLED;
+}
+
+static void r8a66597_timer(unsigned long _r8a66597)
+{
+       struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
+       unsigned long flags;
+       u16 tmp;
+
+       spin_lock_irqsave(&r8a66597->lock, flags);
+       tmp = r8a66597_read(r8a66597, SYSCFG0);
+       if (r8a66597->scount > 0) {
+               tmp = r8a66597_read(r8a66597, INTSTS0) & VBSTS;
+               if (tmp == r8a66597->old_vbus) {
+                       r8a66597->scount--;
+                       if (r8a66597->scount == 0) {
+                               if (tmp == VBSTS)
+                                       r8a66597_usb_connect(r8a66597);
+                               else
+                                       r8a66597_usb_disconnect(r8a66597);
+                       } else {
+                               mod_timer(&r8a66597->timer,
+                                       jiffies + msecs_to_jiffies(50));
+                       }
+               } else {
+                       r8a66597->scount = R8A66597_MAX_SAMPLING;
+                       r8a66597->old_vbus = tmp;
+                       mod_timer(&r8a66597->timer,
+                                       jiffies + msecs_to_jiffies(50));
+               }
+       }
+       spin_unlock_irqrestore(&r8a66597->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+static int r8a66597_enable(struct usb_ep *_ep,
+                        const struct usb_endpoint_descriptor *desc)
+{
+       struct r8a66597_ep *ep;
+
+       ep = container_of(_ep, struct r8a66597_ep, ep);
+       return alloc_pipe_config(ep, desc);
+}
+
+static int r8a66597_disable(struct usb_ep *_ep)
+{
+       struct r8a66597_ep *ep;
+       struct r8a66597_request *req;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct r8a66597_ep, ep);
+       BUG_ON(!ep);
+
+       while (!list_empty(&ep->queue)) {
+               req = get_request_from_ep(ep);
+               spin_lock_irqsave(&ep->r8a66597->lock, flags);
+               transfer_complete(ep, req, -ECONNRESET);
+               spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
+       }
+
+       pipe_irq_disable(ep->r8a66597, ep->pipenum);
+       return free_pipe_config(ep);
+}
+
+static struct usb_request *r8a66597_alloc_request(struct usb_ep *_ep,
+                                               gfp_t gfp_flags)
+{
+       struct r8a66597_request *req;
+
+       req = kzalloc(sizeof(struct r8a66597_request), gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void r8a66597_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct r8a66597_request *req;
+
+       req = container_of(_req, struct r8a66597_request, req);
+       kfree(req);
+}
+
+static int r8a66597_queue(struct usb_ep *_ep, struct usb_request *_req,
+                       gfp_t gfp_flags)
+{
+       struct r8a66597_ep *ep;
+       struct r8a66597_request *req;
+       unsigned long flags;
+       int request = 0;
+
+       ep = container_of(_ep, struct r8a66597_ep, ep);
+       req = container_of(_req, struct r8a66597_request, req);
+
+       if (ep->r8a66597->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       spin_lock_irqsave(&ep->r8a66597->lock, flags);
+
+       if (list_empty(&ep->queue))
+               request = 1;
+
+       list_add_tail(&req->queue, &ep->queue);
+       req->req.actual = 0;
+       req->req.status = -EINPROGRESS;
+
+       if (ep->ep.desc == NULL)        /* control */
+               start_ep0(ep, req);
+       else {
+               if (request && !ep->busy)
+                       start_packet(ep, req);
+       }
+
+       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
+
+       return 0;
+}
+
+static int r8a66597_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct r8a66597_ep *ep;
+       struct r8a66597_request *req;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct r8a66597_ep, ep);
+       req = container_of(_req, struct r8a66597_request, req);
+
+       spin_lock_irqsave(&ep->r8a66597->lock, flags);
+       if (!list_empty(&ep->queue))
+               transfer_complete(ep, req, -ECONNRESET);
+       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
+
+       return 0;
+}
+
+static int r8a66597_set_halt(struct usb_ep *_ep, int value)
+{
+       struct r8a66597_ep *ep;
+       struct r8a66597_request *req;
+       unsigned long flags;
+       int ret = 0;
+
+       ep = container_of(_ep, struct r8a66597_ep, ep);
+       req = get_request_from_ep(ep);
+
+       spin_lock_irqsave(&ep->r8a66597->lock, flags);
+       if (!list_empty(&ep->queue)) {
+               ret = -EAGAIN;
+               goto out;
+       }
+       if (value) {
+               ep->busy = 1;
+               pipe_stall(ep->r8a66597, ep->pipenum);
+       } else {
+               ep->busy = 0;
+               ep->wedge = 0;
+               pipe_stop(ep->r8a66597, ep->pipenum);
+       }
+
+out:
+       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
+       return ret;
+}
+
+static int r8a66597_set_wedge(struct usb_ep *_ep)
+{
+       struct r8a66597_ep *ep;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct r8a66597_ep, ep);
+
+       if (!ep || !ep->ep.desc)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ep->r8a66597->lock, flags);
+       ep->wedge = 1;
+       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
+
+       return usb_ep_set_halt(_ep);
+}
+
+static void r8a66597_fifo_flush(struct usb_ep *_ep)
+{
+       struct r8a66597_ep *ep;
+       unsigned long flags;
+
+       ep = container_of(_ep, struct r8a66597_ep, ep);
+       spin_lock_irqsave(&ep->r8a66597->lock, flags);
+       if (list_empty(&ep->queue) && !ep->busy) {
+               pipe_stop(ep->r8a66597, ep->pipenum);
+               r8a66597_bclr(ep->r8a66597, BCLR, ep->fifoctr);
+               r8a66597_write(ep->r8a66597, ACLRM, ep->pipectr);
+               r8a66597_write(ep->r8a66597, 0, ep->pipectr);
+       }
+       spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
+}
+
+static struct usb_ep_ops r8a66597_ep_ops = {
+       .enable         = r8a66597_enable,
+       .disable        = r8a66597_disable,
+
+       .alloc_request  = r8a66597_alloc_request,
+       .free_request   = r8a66597_free_request,
+
+       .queue          = r8a66597_queue,
+       .dequeue        = r8a66597_dequeue,
+
+       .set_halt       = r8a66597_set_halt,
+       .set_wedge      = r8a66597_set_wedge,
+       .fifo_flush     = r8a66597_fifo_flush,
+};
+
+/*-------------------------------------------------------------------------*/
+static int r8a66597_start(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
+
+       if (!driver
+                       || driver->max_speed < USB_SPEED_HIGH
+                       || !driver->setup)
+               return -EINVAL;
+       if (!r8a66597)
+               return -ENODEV;
+
+       /* hook up the driver */
+       r8a66597->driver = driver;
+
+       init_controller(r8a66597);
+       r8a66597_bset(r8a66597, VBSE, INTENB0);
+       if (r8a66597_read(r8a66597, INTSTS0) & VBSTS) {
+               r8a66597_start_xclock(r8a66597);
+               /* start vbus sampling */
+               r8a66597->old_vbus = r8a66597_read(r8a66597,
+                                        INTSTS0) & VBSTS;
+               r8a66597->scount = R8A66597_MAX_SAMPLING;
+               mod_timer(&r8a66597->timer, jiffies + msecs_to_jiffies(50));
+       }
+
+       return 0;
+}
+
+static int r8a66597_stop(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
+       unsigned long flags;
+
+       spin_lock_irqsave(&r8a66597->lock, flags);
+       r8a66597_bclr(r8a66597, VBSE, INTENB0);
+       disable_controller(r8a66597);
+       spin_unlock_irqrestore(&r8a66597->lock, flags);
+
+       r8a66597->driver = NULL;
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static int r8a66597_get_frame(struct usb_gadget *_gadget)
+{
+       struct r8a66597 *r8a66597 = gadget_to_r8a66597(_gadget);
+       return r8a66597_read(r8a66597, FRMNUM) & 0x03FF;
+}
+
+static int r8a66597_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
+       unsigned long flags;
+
+       spin_lock_irqsave(&r8a66597->lock, flags);
+       if (is_on)
+               r8a66597_bset(r8a66597, DPRPU, SYSCFG0);
+       else
+               r8a66597_bclr(r8a66597, DPRPU, SYSCFG0);
+       spin_unlock_irqrestore(&r8a66597->lock, flags);
+
+       return 0;
+}
+
+static int r8a66597_set_selfpowered(struct usb_gadget *gadget, int is_self)
+{
+       struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
+
+       if (is_self)
+               r8a66597->device_status |= 1 << USB_DEVICE_SELF_POWERED;
+       else
+               r8a66597->device_status &= ~(1 << USB_DEVICE_SELF_POWERED);
+
+       return 0;
+}
+
+static const struct usb_gadget_ops r8a66597_gadget_ops = {
+       .get_frame              = r8a66597_get_frame,
+       .udc_start              = r8a66597_start,
+       .udc_stop               = r8a66597_stop,
+       .pullup                 = r8a66597_pullup,
+       .set_selfpowered        = r8a66597_set_selfpowered,
+};
+
+static int __exit r8a66597_remove(struct platform_device *pdev)
+{
+       struct r8a66597         *r8a66597 = platform_get_drvdata(pdev);
+
+       usb_del_gadget_udc(&r8a66597->gadget);
+       del_timer_sync(&r8a66597->timer);
+       r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
+
+       if (r8a66597->pdata->on_chip) {
+               clk_disable_unprepare(r8a66597->clk);
+       }
+
+       return 0;
+}
+
+static void nop_completion(struct usb_ep *ep, struct usb_request *r)
+{
+}
+
+static int r8a66597_sudmac_ioremap(struct r8a66597 *r8a66597,
+                                         struct platform_device *pdev)
+{
+       struct resource *res;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sudmac");
+       r8a66597->sudmac_reg = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(r8a66597->sudmac_reg)) {
+               dev_err(&pdev->dev, "ioremap error(sudmac).\n");
+               return PTR_ERR(r8a66597->sudmac_reg);
+       }
+
+       return 0;
+}
+
+static int r8a66597_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       char clk_name[8];
+       struct resource *res, *ires;
+       int irq;
+       void __iomem *reg = NULL;
+       struct r8a66597 *r8a66597 = NULL;
+       int ret = 0;
+       int i;
+       unsigned long irq_trigger;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       reg = devm_ioremap_resource(&pdev->dev, res);
+       if (!reg)
+               return -ENODEV;
+
+       ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       irq = ires->start;
+       irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
+
+       if (irq < 0) {
+               dev_err(dev, "platform_get_irq error.\n");
+               return -ENODEV;
+       }
+
+       /* initialize ucd */
+       r8a66597 = devm_kzalloc(dev, sizeof(struct r8a66597), GFP_KERNEL);
+       if (r8a66597 == NULL)
+               return -ENOMEM;
+
+       spin_lock_init(&r8a66597->lock);
+       platform_set_drvdata(pdev, r8a66597);
+       r8a66597->pdata = dev_get_platdata(dev);
+       r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
+
+       r8a66597->gadget.ops = &r8a66597_gadget_ops;
+       r8a66597->gadget.max_speed = USB_SPEED_HIGH;
+       r8a66597->gadget.name = udc_name;
+
+       init_timer(&r8a66597->timer);
+       r8a66597->timer.function = r8a66597_timer;
+       r8a66597->timer.data = (unsigned long)r8a66597;
+       r8a66597->reg = reg;
+
+       if (r8a66597->pdata->on_chip) {
+               snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id);
+               r8a66597->clk = devm_clk_get(dev, clk_name);
+               if (IS_ERR(r8a66597->clk)) {
+                       dev_err(dev, "cannot get clock \"%s\"\n", clk_name);
+                       return PTR_ERR(r8a66597->clk);
+               }
+               clk_prepare_enable(r8a66597->clk);
+       }
+
+       if (r8a66597->pdata->sudmac) {
+               ret = r8a66597_sudmac_ioremap(r8a66597, pdev);
+               if (ret < 0)
+                       goto clean_up2;
+       }
+
+       disable_controller(r8a66597); /* make sure controller is disabled */
+
+       ret = devm_request_irq(dev, irq, r8a66597_irq, IRQF_SHARED,
+                              udc_name, r8a66597);
+       if (ret < 0) {
+               dev_err(dev, "request_irq error (%d)\n", ret);
+               goto clean_up2;
+       }
+
+       INIT_LIST_HEAD(&r8a66597->gadget.ep_list);
+       r8a66597->gadget.ep0 = &r8a66597->ep[0].ep;
+       INIT_LIST_HEAD(&r8a66597->gadget.ep0->ep_list);
+       for (i = 0; i < R8A66597_MAX_NUM_PIPE; i++) {
+               struct r8a66597_ep *ep = &r8a66597->ep[i];
+
+               if (i != 0) {
+                       INIT_LIST_HEAD(&r8a66597->ep[i].ep.ep_list);
+                       list_add_tail(&r8a66597->ep[i].ep.ep_list,
+                                       &r8a66597->gadget.ep_list);
+               }
+               ep->r8a66597 = r8a66597;
+               INIT_LIST_HEAD(&ep->queue);
+               ep->ep.name = r8a66597_ep_name[i];
+               ep->ep.ops = &r8a66597_ep_ops;
+               usb_ep_set_maxpacket_limit(&ep->ep, 512);
+       }
+       usb_ep_set_maxpacket_limit(&r8a66597->ep[0].ep, 64);
+       r8a66597->ep[0].pipenum = 0;
+       r8a66597->ep[0].fifoaddr = CFIFO;
+       r8a66597->ep[0].fifosel = CFIFOSEL;
+       r8a66597->ep[0].fifoctr = CFIFOCTR;
+       r8a66597->ep[0].pipectr = get_pipectr_addr(0);
+       r8a66597->pipenum2ep[0] = &r8a66597->ep[0];
+       r8a66597->epaddr2ep[0] = &r8a66597->ep[0];
+
+       r8a66597->ep0_req = r8a66597_alloc_request(&r8a66597->ep[0].ep,
+                                                       GFP_KERNEL);
+       if (r8a66597->ep0_req == NULL) {
+               ret = -ENOMEM;
+               goto clean_up2;
+       }
+       r8a66597->ep0_req->complete = nop_completion;
+
+       ret = usb_add_gadget_udc(dev, &r8a66597->gadget);
+       if (ret)
+               goto err_add_udc;
+
+       dev_info(dev, "version %s\n", DRIVER_VERSION);
+       return 0;
+
+err_add_udc:
+       r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
+clean_up2:
+       if (r8a66597->pdata->on_chip)
+               clk_disable_unprepare(r8a66597->clk);
+
+       if (r8a66597->ep0_req)
+               r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
+
+       return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+static struct platform_driver r8a66597_driver = {
+       .remove =       __exit_p(r8a66597_remove),
+       .driver         = {
+               .name = (char *) udc_name,
+       },
+};
+
+module_platform_driver_probe(r8a66597_driver, r8a66597_probe);
+
+MODULE_DESCRIPTION("R8A66597 USB gadget driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yoshihiro Shimoda");
+MODULE_ALIAS("platform:r8a66597_udc");
diff --git a/drivers/usb/gadget/udc/r8a66597-udc.h b/drivers/usb/gadget/udc/r8a66597-udc.h
new file mode 100644 (file)
index 0000000..45c4b2d
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * R8A66597 UDC
+ *
+ * Copyright (C) 2007-2009 Renesas Solutions Corp.
+ *
+ * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#ifndef __R8A66597_H__
+#define __R8A66597_H__
+
+#include <linux/clk.h>
+#include <linux/usb/r8a66597.h>
+
+#define R8A66597_MAX_SAMPLING  10
+
+#define R8A66597_MAX_NUM_PIPE  8
+#define R8A66597_MAX_NUM_BULK  3
+#define R8A66597_MAX_NUM_ISOC  2
+#define R8A66597_MAX_NUM_INT   2
+
+#define R8A66597_BASE_PIPENUM_BULK     3
+#define R8A66597_BASE_PIPENUM_ISOC     1
+#define R8A66597_BASE_PIPENUM_INT      6
+
+#define R8A66597_BASE_BUFNUM   6
+#define R8A66597_MAX_BUFNUM    0x4F
+
+#define is_bulk_pipe(pipenum)  \
+       ((pipenum >= R8A66597_BASE_PIPENUM_BULK) && \
+        (pipenum < (R8A66597_BASE_PIPENUM_BULK + R8A66597_MAX_NUM_BULK)))
+#define is_interrupt_pipe(pipenum)     \
+       ((pipenum >= R8A66597_BASE_PIPENUM_INT) && \
+        (pipenum < (R8A66597_BASE_PIPENUM_INT + R8A66597_MAX_NUM_INT)))
+#define is_isoc_pipe(pipenum)  \
+       ((pipenum >= R8A66597_BASE_PIPENUM_ISOC) && \
+        (pipenum < (R8A66597_BASE_PIPENUM_ISOC + R8A66597_MAX_NUM_ISOC)))
+
+#define r8a66597_is_sudmac(r8a66597)   (r8a66597->pdata->sudmac)
+struct r8a66597_pipe_info {
+       u16     pipe;
+       u16     epnum;
+       u16     maxpacket;
+       u16     type;
+       u16     interval;
+       u16     dir_in;
+};
+
+struct r8a66597_request {
+       struct usb_request      req;
+       struct list_head        queue;
+};
+
+struct r8a66597_ep {
+       struct usb_ep           ep;
+       struct r8a66597         *r8a66597;
+       struct r8a66597_dma     *dma;
+
+       struct list_head        queue;
+       unsigned                busy:1;
+       unsigned                wedge:1;
+       unsigned                internal_ccpl:1;        /* use only control */
+
+       /* this member can able to after r8a66597_enable */
+       unsigned                use_dma:1;
+       u16                     pipenum;
+       u16                     type;
+
+       /* register address */
+       unsigned char           fifoaddr;
+       unsigned char           fifosel;
+       unsigned char           fifoctr;
+       unsigned char           pipectr;
+       unsigned char           pipetre;
+       unsigned char           pipetrn;
+};
+
+struct r8a66597_dma {
+       unsigned                used:1;
+       unsigned                dir:1;  /* 1 = IN(write), 0 = OUT(read) */
+};
+
+struct r8a66597 {
+       spinlock_t              lock;
+       void __iomem            *reg;
+       void __iomem            *sudmac_reg;
+
+       struct clk *clk;
+       struct r8a66597_platdata        *pdata;
+
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+
+       struct r8a66597_ep      ep[R8A66597_MAX_NUM_PIPE];
+       struct r8a66597_ep      *pipenum2ep[R8A66597_MAX_NUM_PIPE];
+       struct r8a66597_ep      *epaddr2ep[16];
+       struct r8a66597_dma     dma;
+
+       struct timer_list       timer;
+       struct usb_request      *ep0_req;       /* for internal request */
+       u16                     ep0_data;       /* for internal request */
+       u16                     old_vbus;
+       u16                     scount;
+       u16                     old_dvsq;
+       u16                     device_status;  /* for GET_STATUS */
+
+       /* pipe config */
+       unsigned char bulk;
+       unsigned char interrupt;
+       unsigned char isochronous;
+       unsigned char num_dma;
+
+       unsigned irq_sense_low:1;
+};
+
+#define gadget_to_r8a66597(_gadget)    \
+               container_of(_gadget, struct r8a66597, gadget)
+#define r8a66597_to_gadget(r8a66597) (&r8a66597->gadget)
+#define r8a66597_to_dev(r8a66597)      (r8a66597->gadget.dev.parent)
+
+static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
+{
+       return ioread16(r8a66597->reg + offset);
+}
+
+static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
+                                     unsigned long offset,
+                                     unsigned char *buf,
+                                     int len)
+{
+       void __iomem *fifoaddr = r8a66597->reg + offset;
+       unsigned int data = 0;
+       int i;
+
+       if (r8a66597->pdata->on_chip) {
+               /* 32-bit accesses for on_chip controllers */
+
+               /* aligned buf case */
+               if (len >= 4 && !((unsigned long)buf & 0x03)) {
+                       ioread32_rep(fifoaddr, buf, len / 4);
+                       buf += len & ~0x03;
+                       len &= 0x03;
+               }
+
+               /* unaligned buf case */
+               for (i = 0; i < len; i++) {
+                       if (!(i & 0x03))
+                               data = ioread32(fifoaddr);
+
+                       buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
+               }
+       } else {
+               /* 16-bit accesses for external controllers */
+
+               /* aligned buf case */
+               if (len >= 2 && !((unsigned long)buf & 0x01)) {
+                       ioread16_rep(fifoaddr, buf, len / 2);
+                       buf += len & ~0x01;
+                       len &= 0x01;
+               }
+
+               /* unaligned buf case */
+               for (i = 0; i < len; i++) {
+                       if (!(i & 0x01))
+                               data = ioread16(fifoaddr);
+
+                       buf[i] = (data >> ((i & 0x01) * 8)) & 0xff;
+               }
+       }
+}
+
+static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
+                                 unsigned long offset)
+{
+       iowrite16(val, r8a66597->reg + offset);
+}
+
+static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
+                                u16 val, u16 pat, unsigned long offset)
+{
+       u16 tmp;
+       tmp = r8a66597_read(r8a66597, offset);
+       tmp = tmp & (~pat);
+       tmp = tmp | val;
+       r8a66597_write(r8a66597, tmp, offset);
+}
+
+#define r8a66597_bclr(r8a66597, val, offset)   \
+                       r8a66597_mdfy(r8a66597, 0, val, offset)
+#define r8a66597_bset(r8a66597, val, offset)   \
+                       r8a66597_mdfy(r8a66597, val, 0, offset)
+
+static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
+                                      struct r8a66597_ep *ep,
+                                      unsigned char *buf,
+                                      int len)
+{
+       void __iomem *fifoaddr = r8a66597->reg + ep->fifoaddr;
+       int adj = 0;
+       int i;
+
+       if (r8a66597->pdata->on_chip) {
+               /* 32-bit access only if buf is 32-bit aligned */
+               if (len >= 4 && !((unsigned long)buf & 0x03)) {
+                       iowrite32_rep(fifoaddr, buf, len / 4);
+                       buf += len & ~0x03;
+                       len &= 0x03;
+               }
+       } else {
+               /* 16-bit access only if buf is 16-bit aligned */
+               if (len >= 2 && !((unsigned long)buf & 0x01)) {
+                       iowrite16_rep(fifoaddr, buf, len / 2);
+                       buf += len & ~0x01;
+                       len &= 0x01;
+               }
+       }
+
+       /* adjust fifo address in the little endian case */
+       if (!(r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)) {
+               if (r8a66597->pdata->on_chip)
+                       adj = 0x03; /* 32-bit wide */
+               else
+                       adj = 0x01; /* 16-bit wide */
+       }
+
+       if (r8a66597->pdata->wr0_shorted_to_wr1)
+               r8a66597_bclr(r8a66597, MBW_16, ep->fifosel);
+       for (i = 0; i < len; i++)
+               iowrite8(buf[i], fifoaddr + adj - (i & adj));
+       if (r8a66597->pdata->wr0_shorted_to_wr1)
+               r8a66597_bclr(r8a66597, MBW_16, ep->fifosel);
+}
+
+static inline u16 get_xtal_from_pdata(struct r8a66597_platdata *pdata)
+{
+       u16 clock = 0;
+
+       switch (pdata->xtal) {
+       case R8A66597_PLATDATA_XTAL_12MHZ:
+               clock = XTAL12;
+               break;
+       case R8A66597_PLATDATA_XTAL_24MHZ:
+               clock = XTAL24;
+               break;
+       case R8A66597_PLATDATA_XTAL_48MHZ:
+               clock = XTAL48;
+               break;
+       default:
+               printk(KERN_ERR "r8a66597: platdata clock is wrong.\n");
+               break;
+       }
+
+       return clock;
+}
+
+static inline u32 r8a66597_sudmac_read(struct r8a66597 *r8a66597,
+                                      unsigned long offset)
+{
+       return ioread32(r8a66597->sudmac_reg + offset);
+}
+
+static inline void r8a66597_sudmac_write(struct r8a66597 *r8a66597, u32 val,
+                                        unsigned long offset)
+{
+       iowrite32(val, r8a66597->sudmac_reg + offset);
+}
+
+#define get_pipectr_addr(pipenum)      (PIPE1CTR + (pipenum - 1) * 2)
+#define get_pipetre_addr(pipenum)      (PIPE1TRE + (pipenum - 1) * 4)
+#define get_pipetrn_addr(pipenum)      (PIPE1TRN + (pipenum - 1) * 4)
+
+#define enable_irq_ready(r8a66597, pipenum)    \
+       enable_pipe_irq(r8a66597, pipenum, BRDYENB)
+#define disable_irq_ready(r8a66597, pipenum)   \
+       disable_pipe_irq(r8a66597, pipenum, BRDYENB)
+#define enable_irq_empty(r8a66597, pipenum)    \
+       enable_pipe_irq(r8a66597, pipenum, BEMPENB)
+#define disable_irq_empty(r8a66597, pipenum)   \
+       disable_pipe_irq(r8a66597, pipenum, BEMPENB)
+#define enable_irq_nrdy(r8a66597, pipenum)     \
+       enable_pipe_irq(r8a66597, pipenum, NRDYENB)
+#define disable_irq_nrdy(r8a66597, pipenum)    \
+       disable_pipe_irq(r8a66597, pipenum, NRDYENB)
+
+#endif /* __R8A66597_H__ */
+
diff --git a/drivers/usb/gadget/udc/s3c-hsudc.c b/drivers/usb/gadget/udc/s3c-hsudc.c
new file mode 100644 (file)
index 0000000..10c6a12
--- /dev/null
@@ -0,0 +1,1369 @@
+/* linux/drivers/usb/gadget/s3c-hsudc.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * S3C24XX USB 2.0 High-speed USB controller gadget driver
+ *
+ * The S3C24XX USB 2.0 high-speed USB controller supports upto 9 endpoints.
+ * Each endpoint can be configured as either in or out endpoint. Endpoints
+ * can be configured for Bulk or Interrupt transfer mode.
+ *
+ * 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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+#include <linux/prefetch.h>
+#include <linux/platform_data/s3c-hsudc.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+
+#include <mach/regs-s3c2443-clock.h>
+
+#define S3C_HSUDC_REG(x)       (x)
+
+/* Non-Indexed Registers */
+#define S3C_IR                         S3C_HSUDC_REG(0x00) /* Index Register */
+#define S3C_EIR                                S3C_HSUDC_REG(0x04) /* EP Intr Status */
+#define S3C_EIR_EP0                    (1<<0)
+#define S3C_EIER                       S3C_HSUDC_REG(0x08) /* EP Intr Enable */
+#define S3C_FAR                                S3C_HSUDC_REG(0x0c) /* Gadget Address */
+#define S3C_FNR                                S3C_HSUDC_REG(0x10) /* Frame Number */
+#define S3C_EDR                                S3C_HSUDC_REG(0x14) /* EP Direction */
+#define S3C_TR                         S3C_HSUDC_REG(0x18) /* Test Register */
+#define S3C_SSR                                S3C_HSUDC_REG(0x1c) /* System Status */
+#define S3C_SSR_DTZIEN_EN              (0xff8f)
+#define S3C_SSR_ERR                    (0xff80)
+#define S3C_SSR_VBUSON                 (1 << 8)
+#define S3C_SSR_HSP                    (1 << 4)
+#define S3C_SSR_SDE                    (1 << 3)
+#define S3C_SSR_RESUME                 (1 << 2)
+#define S3C_SSR_SUSPEND                        (1 << 1)
+#define S3C_SSR_RESET                  (1 << 0)
+#define S3C_SCR                                S3C_HSUDC_REG(0x20) /* System Control */
+#define S3C_SCR_DTZIEN_EN              (1 << 14)
+#define S3C_SCR_RRD_EN                 (1 << 5)
+#define S3C_SCR_SUS_EN                 (1 << 1)
+#define S3C_SCR_RST_EN                 (1 << 0)
+#define S3C_EP0SR                      S3C_HSUDC_REG(0x24) /* EP0 Status */
+#define S3C_EP0SR_EP0_LWO              (1 << 6)
+#define S3C_EP0SR_STALL                        (1 << 4)
+#define S3C_EP0SR_TX_SUCCESS           (1 << 1)
+#define S3C_EP0SR_RX_SUCCESS           (1 << 0)
+#define S3C_EP0CR                      S3C_HSUDC_REG(0x28) /* EP0 Control */
+#define S3C_BR(_x)                     S3C_HSUDC_REG(0x60 + (_x * 4))
+
+/* Indexed Registers */
+#define S3C_ESR                                S3C_HSUDC_REG(0x2c) /* EPn Status */
+#define S3C_ESR_FLUSH                  (1 << 6)
+#define S3C_ESR_STALL                  (1 << 5)
+#define S3C_ESR_LWO                    (1 << 4)
+#define S3C_ESR_PSIF_ONE               (1 << 2)
+#define S3C_ESR_PSIF_TWO               (2 << 2)
+#define S3C_ESR_TX_SUCCESS             (1 << 1)
+#define S3C_ESR_RX_SUCCESS             (1 << 0)
+#define S3C_ECR                                S3C_HSUDC_REG(0x30) /* EPn Control */
+#define S3C_ECR_DUEN                   (1 << 7)
+#define S3C_ECR_FLUSH                  (1 << 6)
+#define S3C_ECR_STALL                  (1 << 1)
+#define S3C_ECR_IEMS                   (1 << 0)
+#define S3C_BRCR                       S3C_HSUDC_REG(0x34) /* Read Count */
+#define S3C_BWCR                       S3C_HSUDC_REG(0x38) /* Write Count */
+#define S3C_MPR                                S3C_HSUDC_REG(0x3c) /* Max Pkt Size */
+
+#define WAIT_FOR_SETUP                 (0)
+#define DATA_STATE_XMIT                        (1)
+#define DATA_STATE_RECV                        (2)
+
+static const char * const s3c_hsudc_supply_names[] = {
+       "vdda",         /* analog phy supply, 3.3V */
+       "vddi",         /* digital phy supply, 1.2V */
+       "vddosc",       /* oscillator supply, 1.8V - 3.3V */
+};
+
+/**
+ * struct s3c_hsudc_ep - Endpoint representation used by driver.
+ * @ep: USB gadget layer representation of device endpoint.
+ * @name: Endpoint name (as required by ep autoconfiguration).
+ * @dev: Reference to the device controller to which this EP belongs.
+ * @desc: Endpoint descriptor obtained from the gadget driver.
+ * @queue: Transfer request queue for the endpoint.
+ * @stopped: Maintains state of endpoint, set if EP is halted.
+ * @bEndpointAddress: EP address (including direction bit).
+ * @fifo: Base address of EP FIFO.
+ */
+struct s3c_hsudc_ep {
+       struct usb_ep ep;
+       char name[20];
+       struct s3c_hsudc *dev;
+       struct list_head queue;
+       u8 stopped;
+       u8 wedge;
+       u8 bEndpointAddress;
+       void __iomem *fifo;
+};
+
+/**
+ * struct s3c_hsudc_req - Driver encapsulation of USB gadget transfer request.
+ * @req: Reference to USB gadget transfer request.
+ * @queue: Used for inserting this request to the endpoint request queue.
+ */
+struct s3c_hsudc_req {
+       struct usb_request req;
+       struct list_head queue;
+};
+
+/**
+ * struct s3c_hsudc - Driver's abstraction of the device controller.
+ * @gadget: Instance of usb_gadget which is referenced by gadget driver.
+ * @driver: Reference to currenty active gadget driver.
+ * @dev: The device reference used by probe function.
+ * @lock: Lock to synchronize the usage of Endpoints (EP's are indexed).
+ * @regs: Remapped base address of controller's register space.
+ * irq: IRQ number used by the controller.
+ * uclk: Reference to the controller clock.
+ * ep0state: Current state of EP0.
+ * ep: List of endpoints supported by the controller.
+ */
+struct s3c_hsudc {
+       struct usb_gadget gadget;
+       struct usb_gadget_driver *driver;
+       struct device *dev;
+       struct s3c24xx_hsudc_platdata *pd;
+       struct usb_phy *transceiver;
+       struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsudc_supply_names)];
+       spinlock_t lock;
+       void __iomem *regs;
+       int irq;
+       struct clk *uclk;
+       int ep0state;
+       struct s3c_hsudc_ep ep[];
+};
+
+#define ep_maxpacket(_ep)      ((_ep)->ep.maxpacket)
+#define ep_is_in(_ep)          ((_ep)->bEndpointAddress & USB_DIR_IN)
+#define ep_index(_ep)          ((_ep)->bEndpointAddress & \
+                                       USB_ENDPOINT_NUMBER_MASK)
+
+static const char driver_name[] = "s3c-udc";
+static const char ep0name[] = "ep0-control";
+
+static inline struct s3c_hsudc_req *our_req(struct usb_request *req)
+{
+       return container_of(req, struct s3c_hsudc_req, req);
+}
+
+static inline struct s3c_hsudc_ep *our_ep(struct usb_ep *ep)
+{
+       return container_of(ep, struct s3c_hsudc_ep, ep);
+}
+
+static inline struct s3c_hsudc *to_hsudc(struct usb_gadget *gadget)
+{
+       return container_of(gadget, struct s3c_hsudc, gadget);
+}
+
+static inline void set_index(struct s3c_hsudc *hsudc, int ep_addr)
+{
+       ep_addr &= USB_ENDPOINT_NUMBER_MASK;
+       writel(ep_addr, hsudc->regs + S3C_IR);
+}
+
+static inline void __orr32(void __iomem *ptr, u32 val)
+{
+       writel(readl(ptr) | val, ptr);
+}
+
+static void s3c_hsudc_init_phy(void)
+{
+       u32 cfg;
+
+       cfg = readl(S3C2443_PWRCFG) | S3C2443_PWRCFG_USBPHY;
+       writel(cfg, S3C2443_PWRCFG);
+
+       cfg = readl(S3C2443_URSTCON);
+       cfg |= (S3C2443_URSTCON_FUNCRST | S3C2443_URSTCON_PHYRST);
+       writel(cfg, S3C2443_URSTCON);
+       mdelay(1);
+
+       cfg = readl(S3C2443_URSTCON);
+       cfg &= ~(S3C2443_URSTCON_FUNCRST | S3C2443_URSTCON_PHYRST);
+       writel(cfg, S3C2443_URSTCON);
+
+       cfg = readl(S3C2443_PHYCTRL);
+       cfg &= ~(S3C2443_PHYCTRL_CLKSEL | S3C2443_PHYCTRL_DSPORT);
+       cfg |= (S3C2443_PHYCTRL_EXTCLK | S3C2443_PHYCTRL_PLLSEL);
+       writel(cfg, S3C2443_PHYCTRL);
+
+       cfg = readl(S3C2443_PHYPWR);
+       cfg &= ~(S3C2443_PHYPWR_FSUSPEND | S3C2443_PHYPWR_PLL_PWRDN |
+               S3C2443_PHYPWR_XO_ON | S3C2443_PHYPWR_PLL_REFCLK |
+               S3C2443_PHYPWR_ANALOG_PD);
+       cfg |= S3C2443_PHYPWR_COMMON_ON;
+       writel(cfg, S3C2443_PHYPWR);
+
+       cfg = readl(S3C2443_UCLKCON);
+       cfg |= (S3C2443_UCLKCON_DETECT_VBUS | S3C2443_UCLKCON_FUNC_CLKEN |
+               S3C2443_UCLKCON_TCLKEN);
+       writel(cfg, S3C2443_UCLKCON);
+}
+
+static void s3c_hsudc_uninit_phy(void)
+{
+       u32 cfg;
+
+       cfg = readl(S3C2443_PWRCFG) & ~S3C2443_PWRCFG_USBPHY;
+       writel(cfg, S3C2443_PWRCFG);
+
+       writel(S3C2443_PHYPWR_FSUSPEND, S3C2443_PHYPWR);
+
+       cfg = readl(S3C2443_UCLKCON) & ~S3C2443_UCLKCON_FUNC_CLKEN;
+       writel(cfg, S3C2443_UCLKCON);
+}
+
+/**
+ * s3c_hsudc_complete_request - Complete a transfer request.
+ * @hsep: Endpoint to which the request belongs.
+ * @hsreq: Transfer request to be completed.
+ * @status: Transfer completion status for the transfer request.
+ */
+static void s3c_hsudc_complete_request(struct s3c_hsudc_ep *hsep,
+                               struct s3c_hsudc_req *hsreq, int status)
+{
+       unsigned int stopped = hsep->stopped;
+       struct s3c_hsudc *hsudc = hsep->dev;
+
+       list_del_init(&hsreq->queue);
+       hsreq->req.status = status;
+
+       if (!ep_index(hsep)) {
+               hsudc->ep0state = WAIT_FOR_SETUP;
+               hsep->bEndpointAddress &= ~USB_DIR_IN;
+       }
+
+       hsep->stopped = 1;
+       spin_unlock(&hsudc->lock);
+       if (hsreq->req.complete != NULL)
+               hsreq->req.complete(&hsep->ep, &hsreq->req);
+       spin_lock(&hsudc->lock);
+       hsep->stopped = stopped;
+}
+
+/**
+ * s3c_hsudc_nuke_ep - Terminate all requests queued for a endpoint.
+ * @hsep: Endpoint for which queued requests have to be terminated.
+ * @status: Transfer completion status for the transfer request.
+ */
+static void s3c_hsudc_nuke_ep(struct s3c_hsudc_ep *hsep, int status)
+{
+       struct s3c_hsudc_req *hsreq;
+
+       while (!list_empty(&hsep->queue)) {
+               hsreq = list_entry(hsep->queue.next,
+                               struct s3c_hsudc_req, queue);
+               s3c_hsudc_complete_request(hsep, hsreq, status);
+       }
+}
+
+/**
+ * s3c_hsudc_stop_activity - Stop activity on all endpoints.
+ * @hsudc: Device controller for which EP activity is to be stopped.
+ *
+ * All the endpoints are stopped and any pending transfer requests if any on
+ * the endpoint are terminated.
+ */
+static void s3c_hsudc_stop_activity(struct s3c_hsudc *hsudc)
+{
+       struct s3c_hsudc_ep *hsep;
+       int epnum;
+
+       hsudc->gadget.speed = USB_SPEED_UNKNOWN;
+
+       for (epnum = 0; epnum < hsudc->pd->epnum; epnum++) {
+               hsep = &hsudc->ep[epnum];
+               hsep->stopped = 1;
+               s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN);
+       }
+}
+
+/**
+ * s3c_hsudc_read_setup_pkt - Read the received setup packet from EP0 fifo.
+ * @hsudc: Device controller from which setup packet is to be read.
+ * @buf: The buffer into which the setup packet is read.
+ *
+ * The setup packet received in the EP0 fifo is read and stored into a
+ * given buffer address.
+ */
+
+static void s3c_hsudc_read_setup_pkt(struct s3c_hsudc *hsudc, u16 *buf)
+{
+       int count;
+
+       count = readl(hsudc->regs + S3C_BRCR);
+       while (count--)
+               *buf++ = (u16)readl(hsudc->regs + S3C_BR(0));
+
+       writel(S3C_EP0SR_RX_SUCCESS, hsudc->regs + S3C_EP0SR);
+}
+
+/**
+ * s3c_hsudc_write_fifo - Write next chunk of transfer data to EP fifo.
+ * @hsep: Endpoint to which the data is to be written.
+ * @hsreq: Transfer request from which the next chunk of data is written.
+ *
+ * Write the next chunk of data from a transfer request to the endpoint FIFO.
+ * If the transfer request completes, 1 is returned, otherwise 0 is returned.
+ */
+static int s3c_hsudc_write_fifo(struct s3c_hsudc_ep *hsep,
+                               struct s3c_hsudc_req *hsreq)
+{
+       u16 *buf;
+       u32 max = ep_maxpacket(hsep);
+       u32 count, length;
+       bool is_last;
+       void __iomem *fifo = hsep->fifo;
+
+       buf = hsreq->req.buf + hsreq->req.actual;
+       prefetch(buf);
+
+       length = hsreq->req.length - hsreq->req.actual;
+       length = min(length, max);
+       hsreq->req.actual += length;
+
+       writel(length, hsep->dev->regs + S3C_BWCR);
+       for (count = 0; count < length; count += 2)
+               writel(*buf++, fifo);
+
+       if (count != max) {
+               is_last = true;
+       } else {
+               if (hsreq->req.length != hsreq->req.actual || hsreq->req.zero)
+                       is_last = false;
+               else
+                       is_last = true;
+       }
+
+       if (is_last) {
+               s3c_hsudc_complete_request(hsep, hsreq, 0);
+               return 1;
+       }
+
+       return 0;
+}
+
+/**
+ * s3c_hsudc_read_fifo - Read the next chunk of data from EP fifo.
+ * @hsep: Endpoint from which the data is to be read.
+ * @hsreq: Transfer request to which the next chunk of data read is written.
+ *
+ * Read the next chunk of data from the endpoint FIFO and a write it to the
+ * transfer request buffer. If the transfer request completes, 1 is returned,
+ * otherwise 0 is returned.
+ */
+static int s3c_hsudc_read_fifo(struct s3c_hsudc_ep *hsep,
+                               struct s3c_hsudc_req *hsreq)
+{
+       struct s3c_hsudc *hsudc = hsep->dev;
+       u32 csr, offset;
+       u16 *buf, word;
+       u32 buflen, rcnt, rlen;
+       void __iomem *fifo = hsep->fifo;
+       u32 is_short = 0;
+
+       offset = (ep_index(hsep)) ? S3C_ESR : S3C_EP0SR;
+       csr = readl(hsudc->regs + offset);
+       if (!(csr & S3C_ESR_RX_SUCCESS))
+               return -EINVAL;
+
+       buf = hsreq->req.buf + hsreq->req.actual;
+       prefetchw(buf);
+       buflen = hsreq->req.length - hsreq->req.actual;
+
+       rcnt = readl(hsudc->regs + S3C_BRCR);
+       rlen = (csr & S3C_ESR_LWO) ? (rcnt * 2 - 1) : (rcnt * 2);
+
+       hsreq->req.actual += min(rlen, buflen);
+       is_short = (rlen < hsep->ep.maxpacket);
+
+       while (rcnt-- != 0) {
+               word = (u16)readl(fifo);
+               if (buflen) {
+                       *buf++ = word;
+                       buflen--;
+               } else {
+                       hsreq->req.status = -EOVERFLOW;
+               }
+       }
+
+       writel(S3C_ESR_RX_SUCCESS, hsudc->regs + offset);
+
+       if (is_short || hsreq->req.actual == hsreq->req.length) {
+               s3c_hsudc_complete_request(hsep, hsreq, 0);
+               return 1;
+       }
+
+       return 0;
+}
+
+/**
+ * s3c_hsudc_epin_intr - Handle in-endpoint interrupt.
+ * @hsudc - Device controller for which the interrupt is to be handled.
+ * @ep_idx - Endpoint number on which an interrupt is pending.
+ *
+ * Handles interrupt for a in-endpoint. The interrupts that are handled are
+ * stall and data transmit complete interrupt.
+ */
+static void s3c_hsudc_epin_intr(struct s3c_hsudc *hsudc, u32 ep_idx)
+{
+       struct s3c_hsudc_ep *hsep = &hsudc->ep[ep_idx];
+       struct s3c_hsudc_req *hsreq;
+       u32 csr;
+
+       csr = readl(hsudc->regs + S3C_ESR);
+       if (csr & S3C_ESR_STALL) {
+               writel(S3C_ESR_STALL, hsudc->regs + S3C_ESR);
+               return;
+       }
+
+       if (csr & S3C_ESR_TX_SUCCESS) {
+               writel(S3C_ESR_TX_SUCCESS, hsudc->regs + S3C_ESR);
+               if (list_empty(&hsep->queue))
+                       return;
+
+               hsreq = list_entry(hsep->queue.next,
+                               struct s3c_hsudc_req, queue);
+               if ((s3c_hsudc_write_fifo(hsep, hsreq) == 0) &&
+                               (csr & S3C_ESR_PSIF_TWO))
+                       s3c_hsudc_write_fifo(hsep, hsreq);
+       }
+}
+
+/**
+ * s3c_hsudc_epout_intr - Handle out-endpoint interrupt.
+ * @hsudc - Device controller for which the interrupt is to be handled.
+ * @ep_idx - Endpoint number on which an interrupt is pending.
+ *
+ * Handles interrupt for a out-endpoint. The interrupts that are handled are
+ * stall, flush and data ready interrupt.
+ */
+static void s3c_hsudc_epout_intr(struct s3c_hsudc *hsudc, u32 ep_idx)
+{
+       struct s3c_hsudc_ep *hsep = &hsudc->ep[ep_idx];
+       struct s3c_hsudc_req *hsreq;
+       u32 csr;
+
+       csr = readl(hsudc->regs + S3C_ESR);
+       if (csr & S3C_ESR_STALL) {
+               writel(S3C_ESR_STALL, hsudc->regs + S3C_ESR);
+               return;
+       }
+
+       if (csr & S3C_ESR_FLUSH) {
+               __orr32(hsudc->regs + S3C_ECR, S3C_ECR_FLUSH);
+               return;
+       }
+
+       if (csr & S3C_ESR_RX_SUCCESS) {
+               if (list_empty(&hsep->queue))
+                       return;
+
+               hsreq = list_entry(hsep->queue.next,
+                               struct s3c_hsudc_req, queue);
+               if (((s3c_hsudc_read_fifo(hsep, hsreq)) == 0) &&
+                               (csr & S3C_ESR_PSIF_TWO))
+                       s3c_hsudc_read_fifo(hsep, hsreq);
+       }
+}
+
+/** s3c_hsudc_set_halt - Set or clear a endpoint halt.
+ * @_ep: Endpoint on which halt has to be set or cleared.
+ * @value: 1 for setting halt on endpoint, 0 to clear halt.
+ *
+ * Set or clear endpoint halt. If halt is set, the endpoint is stopped.
+ * If halt is cleared, for in-endpoints, if there are any pending
+ * transfer requests, transfers are started.
+ */
+static int s3c_hsudc_set_halt(struct usb_ep *_ep, int value)
+{
+       struct s3c_hsudc_ep *hsep = our_ep(_ep);
+       struct s3c_hsudc *hsudc = hsep->dev;
+       struct s3c_hsudc_req *hsreq;
+       unsigned long irqflags;
+       u32 ecr;
+       u32 offset;
+
+       if (value && ep_is_in(hsep) && !list_empty(&hsep->queue))
+               return -EAGAIN;
+
+       spin_lock_irqsave(&hsudc->lock, irqflags);
+       set_index(hsudc, ep_index(hsep));
+       offset = (ep_index(hsep)) ? S3C_ECR : S3C_EP0CR;
+       ecr = readl(hsudc->regs + offset);
+
+       if (value) {
+               ecr |= S3C_ECR_STALL;
+               if (ep_index(hsep))
+                       ecr |= S3C_ECR_FLUSH;
+               hsep->stopped = 1;
+       } else {
+               ecr &= ~S3C_ECR_STALL;
+               hsep->stopped = hsep->wedge = 0;
+       }
+       writel(ecr, hsudc->regs + offset);
+
+       if (ep_is_in(hsep) && !list_empty(&hsep->queue) && !value) {
+               hsreq = list_entry(hsep->queue.next,
+                       struct s3c_hsudc_req, queue);
+               if (hsreq)
+                       s3c_hsudc_write_fifo(hsep, hsreq);
+       }
+
+       spin_unlock_irqrestore(&hsudc->lock, irqflags);
+       return 0;
+}
+
+/** s3c_hsudc_set_wedge - Sets the halt feature with the clear requests ignored
+ * @_ep: Endpoint on which wedge has to be set.
+ *
+ * Sets the halt feature with the clear requests ignored.
+ */
+static int s3c_hsudc_set_wedge(struct usb_ep *_ep)
+{
+       struct s3c_hsudc_ep *hsep = our_ep(_ep);
+
+       if (!hsep)
+               return -EINVAL;
+
+       hsep->wedge = 1;
+       return usb_ep_set_halt(_ep);
+}
+
+/** s3c_hsudc_handle_reqfeat - Handle set feature or clear feature requests.
+ * @_ep: Device controller on which the set/clear feature needs to be handled.
+ * @ctrl: Control request as received on the endpoint 0.
+ *
+ * Handle set feature or clear feature control requests on the control endpoint.
+ */
+static int s3c_hsudc_handle_reqfeat(struct s3c_hsudc *hsudc,
+                                       struct usb_ctrlrequest *ctrl)
+{
+       struct s3c_hsudc_ep *hsep;
+       bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE);
+       u8 ep_num = ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK;
+
+       if (ctrl->bRequestType == USB_RECIP_ENDPOINT) {
+               hsep = &hsudc->ep[ep_num];
+               switch (le16_to_cpu(ctrl->wValue)) {
+               case USB_ENDPOINT_HALT:
+                       if (set || (!set && !hsep->wedge))
+                               s3c_hsudc_set_halt(&hsep->ep, set);
+                       return 0;
+               }
+       }
+
+       return -ENOENT;
+}
+
+/**
+ * s3c_hsudc_process_req_status - Handle get status control request.
+ * @hsudc: Device controller on which get status request has be handled.
+ * @ctrl: Control request as received on the endpoint 0.
+ *
+ * Handle get status control request received on control endpoint.
+ */
+static void s3c_hsudc_process_req_status(struct s3c_hsudc *hsudc,
+                                       struct usb_ctrlrequest *ctrl)
+{
+       struct s3c_hsudc_ep *hsep0 = &hsudc->ep[0];
+       struct s3c_hsudc_req hsreq;
+       struct s3c_hsudc_ep *hsep;
+       __le16 reply;
+       u8 epnum;
+
+       switch (ctrl->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               reply = cpu_to_le16(0);
+               break;
+
+       case USB_RECIP_INTERFACE:
+               reply = cpu_to_le16(0);
+               break;
+
+       case USB_RECIP_ENDPOINT:
+               epnum = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
+               hsep = &hsudc->ep[epnum];
+               reply = cpu_to_le16(hsep->stopped ? 1 : 0);
+               break;
+       }
+
+       INIT_LIST_HEAD(&hsreq.queue);
+       hsreq.req.length = 2;
+       hsreq.req.buf = &reply;
+       hsreq.req.actual = 0;
+       hsreq.req.complete = NULL;
+       s3c_hsudc_write_fifo(hsep0, &hsreq);
+}
+
+/**
+ * s3c_hsudc_process_setup - Process control request received on endpoint 0.
+ * @hsudc: Device controller on which control request has been received.
+ *
+ * Read the control request received on endpoint 0, decode it and handle
+ * the request.
+ */
+static void s3c_hsudc_process_setup(struct s3c_hsudc *hsudc)
+{
+       struct s3c_hsudc_ep *hsep = &hsudc->ep[0];
+       struct usb_ctrlrequest ctrl = {0};
+       int ret;
+
+       s3c_hsudc_nuke_ep(hsep, -EPROTO);
+       s3c_hsudc_read_setup_pkt(hsudc, (u16 *)&ctrl);
+
+       if (ctrl.bRequestType & USB_DIR_IN) {
+               hsep->bEndpointAddress |= USB_DIR_IN;
+               hsudc->ep0state = DATA_STATE_XMIT;
+       } else {
+               hsep->bEndpointAddress &= ~USB_DIR_IN;
+               hsudc->ep0state = DATA_STATE_RECV;
+       }
+
+       switch (ctrl.bRequest) {
+       case USB_REQ_SET_ADDRESS:
+               if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE))
+                       break;
+               hsudc->ep0state = WAIT_FOR_SETUP;
+               return;
+
+       case USB_REQ_GET_STATUS:
+               if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD)
+                       break;
+               s3c_hsudc_process_req_status(hsudc, &ctrl);
+               return;
+
+       case USB_REQ_SET_FEATURE:
+       case USB_REQ_CLEAR_FEATURE:
+               if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD)
+                       break;
+               s3c_hsudc_handle_reqfeat(hsudc, &ctrl);
+               hsudc->ep0state = WAIT_FOR_SETUP;
+               return;
+       }
+
+       if (hsudc->driver) {
+               spin_unlock(&hsudc->lock);
+               ret = hsudc->driver->setup(&hsudc->gadget, &ctrl);
+               spin_lock(&hsudc->lock);
+
+               if (ctrl.bRequest == USB_REQ_SET_CONFIGURATION) {
+                       hsep->bEndpointAddress &= ~USB_DIR_IN;
+                       hsudc->ep0state = WAIT_FOR_SETUP;
+               }
+
+               if (ret < 0) {
+                       dev_err(hsudc->dev, "setup failed, returned %d\n",
+                                               ret);
+                       s3c_hsudc_set_halt(&hsep->ep, 1);
+                       hsudc->ep0state = WAIT_FOR_SETUP;
+                       hsep->bEndpointAddress &= ~USB_DIR_IN;
+               }
+       }
+}
+
+/** s3c_hsudc_handle_ep0_intr - Handle endpoint 0 interrupt.
+ * @hsudc: Device controller on which endpoint 0 interrupt has occured.
+ *
+ * Handle endpoint 0 interrupt when it occurs. EP0 interrupt could occur
+ * when a stall handshake is sent to host or data is sent/received on
+ * endpoint 0.
+ */
+static void s3c_hsudc_handle_ep0_intr(struct s3c_hsudc *hsudc)
+{
+       struct s3c_hsudc_ep *hsep = &hsudc->ep[0];
+       struct s3c_hsudc_req *hsreq;
+       u32 csr = readl(hsudc->regs + S3C_EP0SR);
+       u32 ecr;
+
+       if (csr & S3C_EP0SR_STALL) {
+               ecr = readl(hsudc->regs + S3C_EP0CR);
+               ecr &= ~(S3C_ECR_STALL | S3C_ECR_FLUSH);
+               writel(ecr, hsudc->regs + S3C_EP0CR);
+
+               writel(S3C_EP0SR_STALL, hsudc->regs + S3C_EP0SR);
+               hsep->stopped = 0;
+
+               s3c_hsudc_nuke_ep(hsep, -ECONNABORTED);
+               hsudc->ep0state = WAIT_FOR_SETUP;
+               hsep->bEndpointAddress &= ~USB_DIR_IN;
+               return;
+       }
+
+       if (csr & S3C_EP0SR_TX_SUCCESS) {
+               writel(S3C_EP0SR_TX_SUCCESS, hsudc->regs + S3C_EP0SR);
+               if (ep_is_in(hsep)) {
+                       if (list_empty(&hsep->queue))
+                               return;
+
+                       hsreq = list_entry(hsep->queue.next,
+                                       struct s3c_hsudc_req, queue);
+                       s3c_hsudc_write_fifo(hsep, hsreq);
+               }
+       }
+
+       if (csr & S3C_EP0SR_RX_SUCCESS) {
+               if (hsudc->ep0state == WAIT_FOR_SETUP)
+                       s3c_hsudc_process_setup(hsudc);
+               else {
+                       if (!ep_is_in(hsep)) {
+                               if (list_empty(&hsep->queue))
+                                       return;
+                               hsreq = list_entry(hsep->queue.next,
+                                       struct s3c_hsudc_req, queue);
+                               s3c_hsudc_read_fifo(hsep, hsreq);
+                       }
+               }
+       }
+}
+
+/**
+ * s3c_hsudc_ep_enable - Enable a endpoint.
+ * @_ep: The endpoint to be enabled.
+ * @desc: Endpoint descriptor.
+ *
+ * Enables a endpoint when called from the gadget driver. Endpoint stall if
+ * any is cleared, transfer type is configured and endpoint interrupt is
+ * enabled.
+ */
+static int s3c_hsudc_ep_enable(struct usb_ep *_ep,
+                               const struct usb_endpoint_descriptor *desc)
+{
+       struct s3c_hsudc_ep *hsep;
+       struct s3c_hsudc *hsudc;
+       unsigned long flags;
+       u32 ecr = 0;
+
+       hsep = our_ep(_ep);
+       if (!_ep || !desc || _ep->name == ep0name
+               || desc->bDescriptorType != USB_DT_ENDPOINT
+               || hsep->bEndpointAddress != desc->bEndpointAddress
+               || ep_maxpacket(hsep) < usb_endpoint_maxp(desc))
+               return -EINVAL;
+
+       if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+               && usb_endpoint_maxp(desc) != ep_maxpacket(hsep))
+               || !desc->wMaxPacketSize)
+               return -ERANGE;
+
+       hsudc = hsep->dev;
+       if (!hsudc->driver || hsudc->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       spin_lock_irqsave(&hsudc->lock, flags);
+
+       set_index(hsudc, hsep->bEndpointAddress);
+       ecr |= ((usb_endpoint_xfer_int(desc)) ? S3C_ECR_IEMS : S3C_ECR_DUEN);
+       writel(ecr, hsudc->regs + S3C_ECR);
+
+       hsep->stopped = hsep->wedge = 0;
+       hsep->ep.desc = desc;
+       hsep->ep.maxpacket = usb_endpoint_maxp(desc);
+
+       s3c_hsudc_set_halt(_ep, 0);
+       __set_bit(ep_index(hsep), hsudc->regs + S3C_EIER);
+
+       spin_unlock_irqrestore(&hsudc->lock, flags);
+       return 0;
+}
+
+/**
+ * s3c_hsudc_ep_disable - Disable a endpoint.
+ * @_ep: The endpoint to be disabled.
+ * @desc: Endpoint descriptor.
+ *
+ * Disables a endpoint when called from the gadget driver.
+ */
+static int s3c_hsudc_ep_disable(struct usb_ep *_ep)
+{
+       struct s3c_hsudc_ep *hsep = our_ep(_ep);
+       struct s3c_hsudc *hsudc = hsep->dev;
+       unsigned long flags;
+
+       if (!_ep || !hsep->ep.desc)
+               return -EINVAL;
+
+       spin_lock_irqsave(&hsudc->lock, flags);
+
+       set_index(hsudc, hsep->bEndpointAddress);
+       __clear_bit(ep_index(hsep), hsudc->regs + S3C_EIER);
+
+       s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN);
+
+       hsep->ep.desc = NULL;
+       hsep->stopped = 1;
+
+       spin_unlock_irqrestore(&hsudc->lock, flags);
+       return 0;
+}
+
+/**
+ * s3c_hsudc_alloc_request - Allocate a new request.
+ * @_ep: Endpoint for which request is allocated (not used).
+ * @gfp_flags: Flags used for the allocation.
+ *
+ * Allocates a single transfer request structure when called from gadget driver.
+ */
+static struct usb_request *s3c_hsudc_alloc_request(struct usb_ep *_ep,
+                                               gfp_t gfp_flags)
+{
+       struct s3c_hsudc_req *hsreq;
+
+       hsreq = kzalloc(sizeof(*hsreq), gfp_flags);
+       if (!hsreq)
+               return NULL;
+
+       INIT_LIST_HEAD(&hsreq->queue);
+       return &hsreq->req;
+}
+
+/**
+ * s3c_hsudc_free_request - Deallocate a request.
+ * @ep: Endpoint for which request is deallocated (not used).
+ * @_req: Request to be deallocated.
+ *
+ * Allocates a single transfer request structure when called from gadget driver.
+ */
+static void s3c_hsudc_free_request(struct usb_ep *ep, struct usb_request *_req)
+{
+       struct s3c_hsudc_req *hsreq;
+
+       hsreq = our_req(_req);
+       WARN_ON(!list_empty(&hsreq->queue));
+       kfree(hsreq);
+}
+
+/**
+ * s3c_hsudc_queue - Queue a transfer request for the endpoint.
+ * @_ep: Endpoint for which the request is queued.
+ * @_req: Request to be queued.
+ * @gfp_flags: Not used.
+ *
+ * Start or enqueue a request for a endpoint when called from gadget driver.
+ */
+static int s3c_hsudc_queue(struct usb_ep *_ep, struct usb_request *_req,
+                       gfp_t gfp_flags)
+{
+       struct s3c_hsudc_req *hsreq;
+       struct s3c_hsudc_ep *hsep;
+       struct s3c_hsudc *hsudc;
+       unsigned long flags;
+       u32 offset;
+       u32 csr;
+
+       hsreq = our_req(_req);
+       if ((!_req || !_req->complete || !_req->buf ||
+               !list_empty(&hsreq->queue)))
+               return -EINVAL;
+
+       hsep = our_ep(_ep);
+       hsudc = hsep->dev;
+       if (!hsudc->driver || hsudc->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       spin_lock_irqsave(&hsudc->lock, flags);
+       set_index(hsudc, hsep->bEndpointAddress);
+
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       if (!ep_index(hsep) && _req->length == 0) {
+               hsudc->ep0state = WAIT_FOR_SETUP;
+               s3c_hsudc_complete_request(hsep, hsreq, 0);
+               spin_unlock_irqrestore(&hsudc->lock, flags);
+               return 0;
+       }
+
+       if (list_empty(&hsep->queue) && !hsep->stopped) {
+               offset = (ep_index(hsep)) ? S3C_ESR : S3C_EP0SR;
+               if (ep_is_in(hsep)) {
+                       csr = readl(hsudc->regs + offset);
+                       if (!(csr & S3C_ESR_TX_SUCCESS) &&
+                               (s3c_hsudc_write_fifo(hsep, hsreq) == 1))
+                               hsreq = NULL;
+               } else {
+                       csr = readl(hsudc->regs + offset);
+                       if ((csr & S3C_ESR_RX_SUCCESS)
+                                  && (s3c_hsudc_read_fifo(hsep, hsreq) == 1))
+                               hsreq = NULL;
+               }
+       }
+
+       if (hsreq)
+               list_add_tail(&hsreq->queue, &hsep->queue);
+
+       spin_unlock_irqrestore(&hsudc->lock, flags);
+       return 0;
+}
+
+/**
+ * s3c_hsudc_dequeue - Dequeue a transfer request from an endpoint.
+ * @_ep: Endpoint from which the request is dequeued.
+ * @_req: Request to be dequeued.
+ *
+ * Dequeue a request from a endpoint when called from gadget driver.
+ */
+static int s3c_hsudc_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct s3c_hsudc_ep *hsep = our_ep(_ep);
+       struct s3c_hsudc *hsudc = hsep->dev;
+       struct s3c_hsudc_req *hsreq;
+       unsigned long flags;
+
+       hsep = our_ep(_ep);
+       if (!_ep || hsep->ep.name == ep0name)
+               return -EINVAL;
+
+       spin_lock_irqsave(&hsudc->lock, flags);
+
+       list_for_each_entry(hsreq, &hsep->queue, queue) {
+               if (&hsreq->req == _req)
+                       break;
+       }
+       if (&hsreq->req != _req) {
+               spin_unlock_irqrestore(&hsudc->lock, flags);
+               return -EINVAL;
+       }
+
+       set_index(hsudc, hsep->bEndpointAddress);
+       s3c_hsudc_complete_request(hsep, hsreq, -ECONNRESET);
+
+       spin_unlock_irqrestore(&hsudc->lock, flags);
+       return 0;
+}
+
+static struct usb_ep_ops s3c_hsudc_ep_ops = {
+       .enable = s3c_hsudc_ep_enable,
+       .disable = s3c_hsudc_ep_disable,
+       .alloc_request = s3c_hsudc_alloc_request,
+       .free_request = s3c_hsudc_free_request,
+       .queue = s3c_hsudc_queue,
+       .dequeue = s3c_hsudc_dequeue,
+       .set_halt = s3c_hsudc_set_halt,
+       .set_wedge = s3c_hsudc_set_wedge,
+};
+
+/**
+ * s3c_hsudc_initep - Initialize a endpoint to default state.
+ * @hsudc - Reference to the device controller.
+ * @hsep - Endpoint to be initialized.
+ * @epnum - Address to be assigned to the endpoint.
+ *
+ * Initialize a endpoint with default configuration.
+ */
+static void s3c_hsudc_initep(struct s3c_hsudc *hsudc,
+                               struct s3c_hsudc_ep *hsep, int epnum)
+{
+       char *dir;
+
+       if ((epnum % 2) == 0) {
+               dir = "out";
+       } else {
+               dir = "in";
+               hsep->bEndpointAddress = USB_DIR_IN;
+       }
+
+       hsep->bEndpointAddress |= epnum;
+       if (epnum)
+               snprintf(hsep->name, sizeof(hsep->name), "ep%d%s", epnum, dir);
+       else
+               snprintf(hsep->name, sizeof(hsep->name), "%s", ep0name);
+
+       INIT_LIST_HEAD(&hsep->queue);
+       INIT_LIST_HEAD(&hsep->ep.ep_list);
+       if (epnum)
+               list_add_tail(&hsep->ep.ep_list, &hsudc->gadget.ep_list);
+
+       hsep->dev = hsudc;
+       hsep->ep.name = hsep->name;
+       usb_ep_set_maxpacket_limit(&hsep->ep, epnum ? 512 : 64);
+       hsep->ep.ops = &s3c_hsudc_ep_ops;
+       hsep->fifo = hsudc->regs + S3C_BR(epnum);
+       hsep->ep.desc = NULL;
+       hsep->stopped = 0;
+       hsep->wedge = 0;
+
+       set_index(hsudc, epnum);
+       writel(hsep->ep.maxpacket, hsudc->regs + S3C_MPR);
+}
+
+/**
+ * s3c_hsudc_setup_ep - Configure all endpoints to default state.
+ * @hsudc: Reference to device controller.
+ *
+ * Configures all endpoints to default state.
+ */
+static void s3c_hsudc_setup_ep(struct s3c_hsudc *hsudc)
+{
+       int epnum;
+
+       hsudc->ep0state = WAIT_FOR_SETUP;
+       INIT_LIST_HEAD(&hsudc->gadget.ep_list);
+       for (epnum = 0; epnum < hsudc->pd->epnum; epnum++)
+               s3c_hsudc_initep(hsudc, &hsudc->ep[epnum], epnum);
+}
+
+/**
+ * s3c_hsudc_reconfig - Reconfigure the device controller to default state.
+ * @hsudc: Reference to device controller.
+ *
+ * Reconfigures the device controller registers to a default state.
+ */
+static void s3c_hsudc_reconfig(struct s3c_hsudc *hsudc)
+{
+       writel(0xAA, hsudc->regs + S3C_EDR);
+       writel(1, hsudc->regs + S3C_EIER);
+       writel(0, hsudc->regs + S3C_TR);
+       writel(S3C_SCR_DTZIEN_EN | S3C_SCR_RRD_EN | S3C_SCR_SUS_EN |
+                       S3C_SCR_RST_EN, hsudc->regs + S3C_SCR);
+       writel(0, hsudc->regs + S3C_EP0CR);
+
+       s3c_hsudc_setup_ep(hsudc);
+}
+
+/**
+ * s3c_hsudc_irq - Interrupt handler for device controller.
+ * @irq: Not used.
+ * @_dev: Reference to the device controller.
+ *
+ * Interrupt handler for the device controller. This handler handles controller
+ * interrupts and endpoint interrupts.
+ */
+static irqreturn_t s3c_hsudc_irq(int irq, void *_dev)
+{
+       struct s3c_hsudc *hsudc = _dev;
+       struct s3c_hsudc_ep *hsep;
+       u32 ep_intr;
+       u32 sys_status;
+       u32 ep_idx;
+
+       spin_lock(&hsudc->lock);
+
+       sys_status = readl(hsudc->regs + S3C_SSR);
+       ep_intr = readl(hsudc->regs + S3C_EIR) & 0x3FF;
+
+       if (!ep_intr && !(sys_status & S3C_SSR_DTZIEN_EN)) {
+               spin_unlock(&hsudc->lock);
+               return IRQ_HANDLED;
+       }
+
+       if (sys_status) {
+               if (sys_status & S3C_SSR_VBUSON)
+                       writel(S3C_SSR_VBUSON, hsudc->regs + S3C_SSR);
+
+               if (sys_status & S3C_SSR_ERR)
+                       writel(S3C_SSR_ERR, hsudc->regs + S3C_SSR);
+
+               if (sys_status & S3C_SSR_SDE) {
+                       writel(S3C_SSR_SDE, hsudc->regs + S3C_SSR);
+                       hsudc->gadget.speed = (sys_status & S3C_SSR_HSP) ?
+                               USB_SPEED_HIGH : USB_SPEED_FULL;
+               }
+
+               if (sys_status & S3C_SSR_SUSPEND) {
+                       writel(S3C_SSR_SUSPEND, hsudc->regs + S3C_SSR);
+                       if (hsudc->gadget.speed != USB_SPEED_UNKNOWN
+                               && hsudc->driver && hsudc->driver->suspend)
+                               hsudc->driver->suspend(&hsudc->gadget);
+               }
+
+               if (sys_status & S3C_SSR_RESUME) {
+                       writel(S3C_SSR_RESUME, hsudc->regs + S3C_SSR);
+                       if (hsudc->gadget.speed != USB_SPEED_UNKNOWN
+                               && hsudc->driver && hsudc->driver->resume)
+                               hsudc->driver->resume(&hsudc->gadget);
+               }
+
+               if (sys_status & S3C_SSR_RESET) {
+                       writel(S3C_SSR_RESET, hsudc->regs + S3C_SSR);
+                       for (ep_idx = 0; ep_idx < hsudc->pd->epnum; ep_idx++) {
+                               hsep = &hsudc->ep[ep_idx];
+                               hsep->stopped = 1;
+                               s3c_hsudc_nuke_ep(hsep, -ECONNRESET);
+                       }
+                       s3c_hsudc_reconfig(hsudc);
+                       hsudc->ep0state = WAIT_FOR_SETUP;
+               }
+       }
+
+       if (ep_intr & S3C_EIR_EP0) {
+               writel(S3C_EIR_EP0, hsudc->regs + S3C_EIR);
+               set_index(hsudc, 0);
+               s3c_hsudc_handle_ep0_intr(hsudc);
+       }
+
+       ep_intr >>= 1;
+       ep_idx = 1;
+       while (ep_intr) {
+               if (ep_intr & 1)  {
+                       hsep = &hsudc->ep[ep_idx];
+                       set_index(hsudc, ep_idx);
+                       writel(1 << ep_idx, hsudc->regs + S3C_EIR);
+                       if (ep_is_in(hsep))
+                               s3c_hsudc_epin_intr(hsudc, ep_idx);
+                       else
+                               s3c_hsudc_epout_intr(hsudc, ep_idx);
+               }
+               ep_intr >>= 1;
+               ep_idx++;
+       }
+
+       spin_unlock(&hsudc->lock);
+       return IRQ_HANDLED;
+}
+
+static int s3c_hsudc_start(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct s3c_hsudc *hsudc = to_hsudc(gadget);
+       int ret;
+
+       if (!driver
+               || driver->max_speed < USB_SPEED_FULL
+               || !driver->setup)
+               return -EINVAL;
+
+       if (!hsudc)
+               return -ENODEV;
+
+       if (hsudc->driver)
+               return -EBUSY;
+
+       hsudc->driver = driver;
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies),
+                                   hsudc->supplies);
+       if (ret != 0) {
+               dev_err(hsudc->dev, "failed to enable supplies: %d\n", ret);
+               goto err_supplies;
+       }
+
+       /* connect to bus through transceiver */
+       if (!IS_ERR_OR_NULL(hsudc->transceiver)) {
+               ret = otg_set_peripheral(hsudc->transceiver->otg,
+                                       &hsudc->gadget);
+               if (ret) {
+                       dev_err(hsudc->dev, "%s: can't bind to transceiver\n",
+                                       hsudc->gadget.name);
+                       goto err_otg;
+               }
+       }
+
+       enable_irq(hsudc->irq);
+       dev_info(hsudc->dev, "bound driver %s\n", driver->driver.name);
+
+       s3c_hsudc_reconfig(hsudc);
+
+       pm_runtime_get_sync(hsudc->dev);
+
+       s3c_hsudc_init_phy();
+       if (hsudc->pd->gpio_init)
+               hsudc->pd->gpio_init();
+
+       return 0;
+err_otg:
+       regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
+err_supplies:
+       hsudc->driver = NULL;
+       return ret;
+}
+
+static int s3c_hsudc_stop(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct s3c_hsudc *hsudc = to_hsudc(gadget);
+       unsigned long flags;
+
+       if (!hsudc)
+               return -ENODEV;
+
+       if (!driver || driver != hsudc->driver)
+               return -EINVAL;
+
+       spin_lock_irqsave(&hsudc->lock, flags);
+       hsudc->driver = NULL;
+       hsudc->gadget.speed = USB_SPEED_UNKNOWN;
+       s3c_hsudc_uninit_phy();
+
+       pm_runtime_put(hsudc->dev);
+
+       if (hsudc->pd->gpio_uninit)
+               hsudc->pd->gpio_uninit();
+       s3c_hsudc_stop_activity(hsudc);
+       spin_unlock_irqrestore(&hsudc->lock, flags);
+
+       if (!IS_ERR_OR_NULL(hsudc->transceiver))
+               (void) otg_set_peripheral(hsudc->transceiver->otg, NULL);
+
+       disable_irq(hsudc->irq);
+
+       regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
+
+       dev_info(hsudc->dev, "unregistered gadget driver '%s'\n",
+                       driver->driver.name);
+       return 0;
+}
+
+static inline u32 s3c_hsudc_read_frameno(struct s3c_hsudc *hsudc)
+{
+       return readl(hsudc->regs + S3C_FNR) & 0x3FF;
+}
+
+static int s3c_hsudc_gadget_getframe(struct usb_gadget *gadget)
+{
+       return s3c_hsudc_read_frameno(to_hsudc(gadget));
+}
+
+static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+       struct s3c_hsudc *hsudc = to_hsudc(gadget);
+
+       if (!hsudc)
+               return -ENODEV;
+
+       if (!IS_ERR_OR_NULL(hsudc->transceiver))
+               return usb_phy_set_power(hsudc->transceiver, mA);
+
+       return -EOPNOTSUPP;
+}
+
+static const struct usb_gadget_ops s3c_hsudc_gadget_ops = {
+       .get_frame      = s3c_hsudc_gadget_getframe,
+       .udc_start      = s3c_hsudc_start,
+       .udc_stop       = s3c_hsudc_stop,
+       .vbus_draw      = s3c_hsudc_vbus_draw,
+};
+
+static int s3c_hsudc_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       struct s3c_hsudc *hsudc;
+       struct s3c24xx_hsudc_platdata *pd = dev_get_platdata(&pdev->dev);
+       int ret, i;
+
+       hsudc = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsudc) +
+                       sizeof(struct s3c_hsudc_ep) * pd->epnum,
+                       GFP_KERNEL);
+       if (!hsudc) {
+               dev_err(dev, "cannot allocate memory\n");
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(pdev, dev);
+       hsudc->dev = dev;
+       hsudc->pd = dev_get_platdata(&pdev->dev);
+
+       hsudc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+
+       for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++)
+               hsudc->supplies[i].supply = s3c_hsudc_supply_names[i];
+
+       ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsudc->supplies),
+                                hsudc->supplies);
+       if (ret != 0) {
+               dev_err(dev, "failed to request supplies: %d\n", ret);
+               goto err_supplies;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       hsudc->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(hsudc->regs)) {
+               ret = PTR_ERR(hsudc->regs);
+               goto err_res;
+       }
+
+       spin_lock_init(&hsudc->lock);
+
+       hsudc->gadget.max_speed = USB_SPEED_HIGH;
+       hsudc->gadget.ops = &s3c_hsudc_gadget_ops;
+       hsudc->gadget.name = dev_name(dev);
+       hsudc->gadget.ep0 = &hsudc->ep[0].ep;
+       hsudc->gadget.is_otg = 0;
+       hsudc->gadget.is_a_peripheral = 0;
+       hsudc->gadget.speed = USB_SPEED_UNKNOWN;
+
+       s3c_hsudc_setup_ep(hsudc);
+
+       ret = platform_get_irq(pdev, 0);
+       if (ret < 0) {
+               dev_err(dev, "unable to obtain IRQ number\n");
+               goto err_res;
+       }
+       hsudc->irq = ret;
+
+       ret = devm_request_irq(&pdev->dev, hsudc->irq, s3c_hsudc_irq, 0,
+                               driver_name, hsudc);
+       if (ret < 0) {
+               dev_err(dev, "irq request failed\n");
+               goto err_res;
+       }
+
+       hsudc->uclk = devm_clk_get(&pdev->dev, "usb-device");
+       if (IS_ERR(hsudc->uclk)) {
+               dev_err(dev, "failed to find usb-device clock source\n");
+               ret = PTR_ERR(hsudc->uclk);
+               goto err_res;
+       }
+       clk_enable(hsudc->uclk);
+
+       local_irq_disable();
+
+       disable_irq(hsudc->irq);
+       local_irq_enable();
+
+       ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget);
+       if (ret)
+               goto err_add_udc;
+
+       pm_runtime_enable(dev);
+
+       return 0;
+err_add_udc:
+       clk_disable(hsudc->uclk);
+err_res:
+       if (!IS_ERR_OR_NULL(hsudc->transceiver))
+               usb_put_phy(hsudc->transceiver);
+
+err_supplies:
+       return ret;
+}
+
+static struct platform_driver s3c_hsudc_driver = {
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "s3c-hsudc",
+       },
+       .probe          = s3c_hsudc_probe,
+};
+
+module_platform_driver(s3c_hsudc_driver);
+
+MODULE_DESCRIPTION("Samsung S3C24XX USB high-speed controller driver");
+MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:s3c-hsudc");
diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c
new file mode 100644 (file)
index 0000000..357b58e
--- /dev/null
@@ -0,0 +1,2045 @@
+/*
+ * linux/drivers/usb/gadget/s3c2410_udc.c
+ *
+ * Samsung S3C24xx series on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2004-2007 Herbert Pötzl - Arnaud Patard
+ *     Additional cleanups by Ben Dooks <ben-linux@fluff.org>
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) "s3c2410_udc: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/prefetch.h>
+#include <linux/io.h>
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <linux/usb.h>
+#include <linux/usb/gadget.h>
+
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/unaligned.h>
+#include <mach/irqs.h>
+
+#include <mach/hardware.h>
+
+#include <plat/regs-udc.h>
+#include <linux/platform_data/usb-s3c2410_udc.h>
+
+
+#include "s3c2410_udc.h"
+
+#define DRIVER_DESC    "S3C2410 USB Device Controller Gadget"
+#define DRIVER_VERSION "29 Apr 2007"
+#define DRIVER_AUTHOR  "Herbert Pötzl <herbert@13thfloor.at>, " \
+                       "Arnaud Patard <arnaud.patard@rtp-net.org>"
+
+static const char              gadget_name[] = "s3c2410_udc";
+static const char              driver_desc[] = DRIVER_DESC;
+
+static struct s3c2410_udc      *the_controller;
+static struct clk              *udc_clock;
+static struct clk              *usb_bus_clock;
+static void __iomem            *base_addr;
+static u64                     rsrc_start;
+static u64                     rsrc_len;
+static struct dentry           *s3c2410_udc_debugfs_root;
+
+static inline u32 udc_read(u32 reg)
+{
+       return readb(base_addr + reg);
+}
+
+static inline void udc_write(u32 value, u32 reg)
+{
+       writeb(value, base_addr + reg);
+}
+
+static inline void udc_writeb(void __iomem *base, u32 value, u32 reg)
+{
+       writeb(value, base + reg);
+}
+
+static struct s3c2410_udc_mach_info *udc_info;
+
+/*************************** DEBUG FUNCTION ***************************/
+#define DEBUG_NORMAL   1
+#define DEBUG_VERBOSE  2
+
+#ifdef CONFIG_USB_S3C2410_DEBUG
+#define USB_S3C2410_DEBUG_LEVEL 0
+
+static uint32_t s3c2410_ticks = 0;
+
+static int dprintk(int level, const char *fmt, ...)
+{
+       static char printk_buf[1024];
+       static long prevticks;
+       static int invocation;
+       va_list args;
+       int len;
+
+       if (level > USB_S3C2410_DEBUG_LEVEL)
+               return 0;
+
+       if (s3c2410_ticks != prevticks) {
+               prevticks = s3c2410_ticks;
+               invocation = 0;
+       }
+
+       len = scnprintf(printk_buf,
+                       sizeof(printk_buf), "%1lu.%02d USB: ",
+                       prevticks, invocation++);
+
+       va_start(args, fmt);
+       len = vscnprintf(printk_buf+len,
+                       sizeof(printk_buf)-len, fmt, args);
+       va_end(args);
+
+       pr_debug("%s", printk_buf);
+       return len;
+}
+#else
+static int dprintk(int level, const char *fmt, ...)
+{
+       return 0;
+}
+#endif
+static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
+{
+       u32 addr_reg, pwr_reg, ep_int_reg, usb_int_reg;
+       u32 ep_int_en_reg, usb_int_en_reg, ep0_csr;
+       u32 ep1_i_csr1, ep1_i_csr2, ep1_o_csr1, ep1_o_csr2;
+       u32 ep2_i_csr1, ep2_i_csr2, ep2_o_csr1, ep2_o_csr2;
+
+       addr_reg       = udc_read(S3C2410_UDC_FUNC_ADDR_REG);
+       pwr_reg        = udc_read(S3C2410_UDC_PWR_REG);
+       ep_int_reg     = udc_read(S3C2410_UDC_EP_INT_REG);
+       usb_int_reg    = udc_read(S3C2410_UDC_USB_INT_REG);
+       ep_int_en_reg  = udc_read(S3C2410_UDC_EP_INT_EN_REG);
+       usb_int_en_reg = udc_read(S3C2410_UDC_USB_INT_EN_REG);
+       udc_write(0, S3C2410_UDC_INDEX_REG);
+       ep0_csr        = udc_read(S3C2410_UDC_IN_CSR1_REG);
+       udc_write(1, S3C2410_UDC_INDEX_REG);
+       ep1_i_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
+       ep1_i_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
+       ep1_o_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
+       ep1_o_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
+       udc_write(2, S3C2410_UDC_INDEX_REG);
+       ep2_i_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
+       ep2_i_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
+       ep2_o_csr1     = udc_read(S3C2410_UDC_IN_CSR1_REG);
+       ep2_o_csr2     = udc_read(S3C2410_UDC_IN_CSR2_REG);
+
+       seq_printf(m, "FUNC_ADDR_REG  : 0x%04X\n"
+                "PWR_REG        : 0x%04X\n"
+                "EP_INT_REG     : 0x%04X\n"
+                "USB_INT_REG    : 0x%04X\n"
+                "EP_INT_EN_REG  : 0x%04X\n"
+                "USB_INT_EN_REG : 0x%04X\n"
+                "EP0_CSR        : 0x%04X\n"
+                "EP1_I_CSR1     : 0x%04X\n"
+                "EP1_I_CSR2     : 0x%04X\n"
+                "EP1_O_CSR1     : 0x%04X\n"
+                "EP1_O_CSR2     : 0x%04X\n"
+                "EP2_I_CSR1     : 0x%04X\n"
+                "EP2_I_CSR2     : 0x%04X\n"
+                "EP2_O_CSR1     : 0x%04X\n"
+                "EP2_O_CSR2     : 0x%04X\n",
+                       addr_reg, pwr_reg, ep_int_reg, usb_int_reg,
+                       ep_int_en_reg, usb_int_en_reg, ep0_csr,
+                       ep1_i_csr1, ep1_i_csr2, ep1_o_csr1, ep1_o_csr2,
+                       ep2_i_csr1, ep2_i_csr2, ep2_o_csr1, ep2_o_csr2
+               );
+
+       return 0;
+}
+
+static int s3c2410_udc_debugfs_fops_open(struct inode *inode,
+                                        struct file *file)
+{
+       return single_open(file, s3c2410_udc_debugfs_seq_show, NULL);
+}
+
+static const struct file_operations s3c2410_udc_debugfs_fops = {
+       .open           = s3c2410_udc_debugfs_fops_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .owner          = THIS_MODULE,
+};
+
+/* io macros */
+
+static inline void s3c2410_udc_clear_ep0_opr(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       udc_writeb(base, S3C2410_UDC_EP0_CSR_SOPKTRDY,
+                       S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_clear_ep0_sst(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       writeb(0x00, base + S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_clear_ep0_se(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       udc_writeb(base, S3C2410_UDC_EP0_CSR_SSE, S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_ipr(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       udc_writeb(base, S3C2410_UDC_EP0_CSR_IPKRDY, S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_de(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       udc_writeb(base, S3C2410_UDC_EP0_CSR_DE, S3C2410_UDC_EP0_CSR_REG);
+}
+
+inline void s3c2410_udc_set_ep0_ss(void __iomem *b)
+{
+       udc_writeb(b, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       udc_writeb(b, S3C2410_UDC_EP0_CSR_SENDSTL, S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_de_out(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+
+       udc_writeb(base, (S3C2410_UDC_EP0_CSR_SOPKTRDY
+                               | S3C2410_UDC_EP0_CSR_DE),
+                       S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_sse_out(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       udc_writeb(base, (S3C2410_UDC_EP0_CSR_SOPKTRDY
+                               | S3C2410_UDC_EP0_CSR_SSE),
+                       S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_de_in(void __iomem *base)
+{
+       udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       udc_writeb(base, (S3C2410_UDC_EP0_CSR_IPKRDY
+                       | S3C2410_UDC_EP0_CSR_DE),
+               S3C2410_UDC_EP0_CSR_REG);
+}
+
+/*------------------------- I/O ----------------------------------*/
+
+/*
+ *     s3c2410_udc_done
+ */
+static void s3c2410_udc_done(struct s3c2410_ep *ep,
+               struct s3c2410_request *req, int status)
+{
+       unsigned halted = ep->halted;
+
+       list_del_init(&req->queue);
+
+       if (likely(req->req.status == -EINPROGRESS))
+               req->req.status = status;
+       else
+               status = req->req.status;
+
+       ep->halted = 1;
+       req->req.complete(&ep->ep, &req->req);
+       ep->halted = halted;
+}
+
+static void s3c2410_udc_nuke(struct s3c2410_udc *udc,
+               struct s3c2410_ep *ep, int status)
+{
+       /* Sanity check */
+       if (&ep->queue == NULL)
+               return;
+
+       while (!list_empty(&ep->queue)) {
+               struct s3c2410_request *req;
+               req = list_entry(ep->queue.next, struct s3c2410_request,
+                               queue);
+               s3c2410_udc_done(ep, req, status);
+       }
+}
+
+static inline void s3c2410_udc_clear_ep_state(struct s3c2410_udc *dev)
+{
+       unsigned i;
+
+       /* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
+        * fifos, and pending transactions mustn't be continued in any case.
+        */
+
+       for (i = 1; i < S3C2410_ENDPOINTS; i++)
+               s3c2410_udc_nuke(dev, &dev->ep[i], -ECONNABORTED);
+}
+
+static inline int s3c2410_udc_fifo_count_out(void)
+{
+       int tmp;
+
+       tmp = udc_read(S3C2410_UDC_OUT_FIFO_CNT2_REG) << 8;
+       tmp |= udc_read(S3C2410_UDC_OUT_FIFO_CNT1_REG);
+       return tmp;
+}
+
+/*
+ *     s3c2410_udc_write_packet
+ */
+static inline int s3c2410_udc_write_packet(int fifo,
+               struct s3c2410_request *req,
+               unsigned max)
+{
+       unsigned len = min(req->req.length - req->req.actual, max);
+       u8 *buf = req->req.buf + req->req.actual;
+
+       prefetch(buf);
+
+       dprintk(DEBUG_VERBOSE, "%s %d %d %d %d\n", __func__,
+               req->req.actual, req->req.length, len, req->req.actual + len);
+
+       req->req.actual += len;
+
+       udelay(5);
+       writesb(base_addr + fifo, buf, len);
+       return len;
+}
+
+/*
+ *     s3c2410_udc_write_fifo
+ *
+ * return:  0 = still running, 1 = completed, negative = errno
+ */
+static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep,
+               struct s3c2410_request *req)
+{
+       unsigned        count;
+       int             is_last;
+       u32             idx;
+       int             fifo_reg;
+       u32             ep_csr;
+
+       idx = ep->bEndpointAddress & 0x7F;
+       switch (idx) {
+       default:
+               idx = 0;
+       case 0:
+               fifo_reg = S3C2410_UDC_EP0_FIFO_REG;
+               break;
+       case 1:
+               fifo_reg = S3C2410_UDC_EP1_FIFO_REG;
+               break;
+       case 2:
+               fifo_reg = S3C2410_UDC_EP2_FIFO_REG;
+               break;
+       case 3:
+               fifo_reg = S3C2410_UDC_EP3_FIFO_REG;
+               break;
+       case 4:
+               fifo_reg = S3C2410_UDC_EP4_FIFO_REG;
+               break;
+       }
+
+       count = s3c2410_udc_write_packet(fifo_reg, req, ep->ep.maxpacket);
+
+       /* last packet is often short (sometimes a zlp) */
+       if (count != ep->ep.maxpacket)
+               is_last = 1;
+       else if (req->req.length != req->req.actual || req->req.zero)
+               is_last = 0;
+       else
+               is_last = 2;
+
+       /* Only ep0 debug messages are interesting */
+       if (idx == 0)
+               dprintk(DEBUG_NORMAL,
+                       "Written ep%d %d.%d of %d b [last %d,z %d]\n",
+                       idx, count, req->req.actual, req->req.length,
+                       is_last, req->req.zero);
+
+       if (is_last) {
+               /* The order is important. It prevents sending 2 packets
+                * at the same time */
+
+               if (idx == 0) {
+                       /* Reset signal => no need to say 'data sent' */
+                       if (!(udc_read(S3C2410_UDC_USB_INT_REG)
+                                       & S3C2410_UDC_USBINT_RESET))
+                               s3c2410_udc_set_ep0_de_in(base_addr);
+                       ep->dev->ep0state = EP0_IDLE;
+               } else {
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY,
+                                       S3C2410_UDC_IN_CSR1_REG);
+               }
+
+               s3c2410_udc_done(ep, req, 0);
+               is_last = 1;
+       } else {
+               if (idx == 0) {
+                       /* Reset signal => no need to say 'data sent' */
+                       if (!(udc_read(S3C2410_UDC_USB_INT_REG)
+                                       & S3C2410_UDC_USBINT_RESET))
+                               s3c2410_udc_set_ep0_ipr(base_addr);
+               } else {
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY,
+                                       S3C2410_UDC_IN_CSR1_REG);
+               }
+       }
+
+       return is_last;
+}
+
+static inline int s3c2410_udc_read_packet(int fifo, u8 *buf,
+               struct s3c2410_request *req, unsigned avail)
+{
+       unsigned len;
+
+       len = min(req->req.length - req->req.actual, avail);
+       req->req.actual += len;
+
+       readsb(fifo + base_addr, buf, len);
+       return len;
+}
+
+/*
+ * return:  0 = still running, 1 = queue empty, negative = errno
+ */
+static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep,
+                                struct s3c2410_request *req)
+{
+       u8              *buf;
+       u32             ep_csr;
+       unsigned        bufferspace;
+       int             is_last = 1;
+       unsigned        avail;
+       int             fifo_count = 0;
+       u32             idx;
+       int             fifo_reg;
+
+       idx = ep->bEndpointAddress & 0x7F;
+
+       switch (idx) {
+       default:
+               idx = 0;
+       case 0:
+               fifo_reg = S3C2410_UDC_EP0_FIFO_REG;
+               break;
+       case 1:
+               fifo_reg = S3C2410_UDC_EP1_FIFO_REG;
+               break;
+       case 2:
+               fifo_reg = S3C2410_UDC_EP2_FIFO_REG;
+               break;
+       case 3:
+               fifo_reg = S3C2410_UDC_EP3_FIFO_REG;
+               break;
+       case 4:
+               fifo_reg = S3C2410_UDC_EP4_FIFO_REG;
+               break;
+       }
+
+       if (!req->req.length)
+               return 1;
+
+       buf = req->req.buf + req->req.actual;
+       bufferspace = req->req.length - req->req.actual;
+       if (!bufferspace) {
+               dprintk(DEBUG_NORMAL, "%s: buffer full!\n", __func__);
+               return -1;
+       }
+
+       udc_write(idx, S3C2410_UDC_INDEX_REG);
+
+       fifo_count = s3c2410_udc_fifo_count_out();
+       dprintk(DEBUG_NORMAL, "%s fifo count : %d\n", __func__, fifo_count);
+
+       if (fifo_count > ep->ep.maxpacket)
+               avail = ep->ep.maxpacket;
+       else
+               avail = fifo_count;
+
+       fifo_count = s3c2410_udc_read_packet(fifo_reg, buf, req, avail);
+
+       /* checking this with ep0 is not accurate as we already
+        * read a control request
+        **/
+       if (idx != 0 && fifo_count < ep->ep.maxpacket) {
+               is_last = 1;
+               /* overflowed this request?  flush extra data */
+               if (fifo_count != avail)
+                       req->req.status = -EOVERFLOW;
+       } else {
+               is_last = (req->req.length <= req->req.actual) ? 1 : 0;
+       }
+
+       udc_write(idx, S3C2410_UDC_INDEX_REG);
+       fifo_count = s3c2410_udc_fifo_count_out();
+
+       /* Only ep0 debug messages are interesting */
+       if (idx == 0)
+               dprintk(DEBUG_VERBOSE, "%s fifo count : %d [last %d]\n",
+                       __func__, fifo_count, is_last);
+
+       if (is_last) {
+               if (idx == 0) {
+                       s3c2410_udc_set_ep0_de_out(base_addr);
+                       ep->dev->ep0state = EP0_IDLE;
+               } else {
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY,
+                                       S3C2410_UDC_OUT_CSR1_REG);
+               }
+
+               s3c2410_udc_done(ep, req, 0);
+       } else {
+               if (idx == 0) {
+                       s3c2410_udc_clear_ep0_opr(base_addr);
+               } else {
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY,
+                                       S3C2410_UDC_OUT_CSR1_REG);
+               }
+       }
+
+       return is_last;
+}
+
+static int s3c2410_udc_read_fifo_crq(struct usb_ctrlrequest *crq)
+{
+       unsigned char *outbuf = (unsigned char *)crq;
+       int bytes_read = 0;
+
+       udc_write(0, S3C2410_UDC_INDEX_REG);
+
+       bytes_read = s3c2410_udc_fifo_count_out();
+
+       dprintk(DEBUG_NORMAL, "%s: fifo_count=%d\n", __func__, bytes_read);
+
+       if (bytes_read > sizeof(struct usb_ctrlrequest))
+               bytes_read = sizeof(struct usb_ctrlrequest);
+
+       readsb(S3C2410_UDC_EP0_FIFO_REG + base_addr, outbuf, bytes_read);
+
+       dprintk(DEBUG_VERBOSE, "%s: len=%d %02x:%02x {%x,%x,%x}\n", __func__,
+               bytes_read, crq->bRequest, crq->bRequestType,
+               crq->wValue, crq->wIndex, crq->wLength);
+
+       return bytes_read;
+}
+
+static int s3c2410_udc_get_status(struct s3c2410_udc *dev,
+               struct usb_ctrlrequest *crq)
+{
+       u16 status = 0;
+       u8 ep_num = crq->wIndex & 0x7F;
+       u8 is_in = crq->wIndex & USB_DIR_IN;
+
+       switch (crq->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_INTERFACE:
+               break;
+
+       case USB_RECIP_DEVICE:
+               status = dev->devstatus;
+               break;
+
+       case USB_RECIP_ENDPOINT:
+               if (ep_num > 4 || crq->wLength > 2)
+                       return 1;
+
+               if (ep_num == 0) {
+                       udc_write(0, S3C2410_UDC_INDEX_REG);
+                       status = udc_read(S3C2410_UDC_IN_CSR1_REG);
+                       status = status & S3C2410_UDC_EP0_CSR_SENDSTL;
+               } else {
+                       udc_write(ep_num, S3C2410_UDC_INDEX_REG);
+                       if (is_in) {
+                               status = udc_read(S3C2410_UDC_IN_CSR1_REG);
+                               status = status & S3C2410_UDC_ICSR1_SENDSTL;
+                       } else {
+                               status = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+                               status = status & S3C2410_UDC_OCSR1_SENDSTL;
+                       }
+               }
+
+               status = status ? 1 : 0;
+               break;
+
+       default:
+               return 1;
+       }
+
+       /* Seems to be needed to get it working. ouch :( */
+       udelay(5);
+       udc_write(status & 0xFF, S3C2410_UDC_EP0_FIFO_REG);
+       udc_write(status >> 8, S3C2410_UDC_EP0_FIFO_REG);
+       s3c2410_udc_set_ep0_de_in(base_addr);
+
+       return 0;
+}
+/*------------------------- usb state machine -------------------------------*/
+static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value);
+
+static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev,
+                                       struct s3c2410_ep *ep,
+                                       struct usb_ctrlrequest *crq,
+                                       u32 ep0csr)
+{
+       int len, ret, tmp;
+
+       /* start control request? */
+       if (!(ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY))
+               return;
+
+       s3c2410_udc_nuke(dev, ep, -EPROTO);
+
+       len = s3c2410_udc_read_fifo_crq(crq);
+       if (len != sizeof(*crq)) {
+               dprintk(DEBUG_NORMAL, "setup begin: fifo READ ERROR"
+                       " wanted %d bytes got %d. Stalling out...\n",
+                       sizeof(*crq), len);
+               s3c2410_udc_set_ep0_ss(base_addr);
+               return;
+       }
+
+       dprintk(DEBUG_NORMAL, "bRequest = %d bRequestType %d wLength = %d\n",
+               crq->bRequest, crq->bRequestType, crq->wLength);
+
+       /* cope with automagic for some standard requests. */
+       dev->req_std = (crq->bRequestType & USB_TYPE_MASK)
+               == USB_TYPE_STANDARD;
+       dev->req_config = 0;
+       dev->req_pending = 1;
+
+       switch (crq->bRequest) {
+       case USB_REQ_SET_CONFIGURATION:
+               dprintk(DEBUG_NORMAL, "USB_REQ_SET_CONFIGURATION ...\n");
+
+               if (crq->bRequestType == USB_RECIP_DEVICE) {
+                       dev->req_config = 1;
+                       s3c2410_udc_set_ep0_de_out(base_addr);
+               }
+               break;
+
+       case USB_REQ_SET_INTERFACE:
+               dprintk(DEBUG_NORMAL, "USB_REQ_SET_INTERFACE ...\n");
+
+               if (crq->bRequestType == USB_RECIP_INTERFACE) {
+                       dev->req_config = 1;
+                       s3c2410_udc_set_ep0_de_out(base_addr);
+               }
+               break;
+
+       case USB_REQ_SET_ADDRESS:
+               dprintk(DEBUG_NORMAL, "USB_REQ_SET_ADDRESS ...\n");
+
+               if (crq->bRequestType == USB_RECIP_DEVICE) {
+                       tmp = crq->wValue & 0x7F;
+                       dev->address = tmp;
+                       udc_write((tmp | S3C2410_UDC_FUNCADDR_UPDATE),
+                                       S3C2410_UDC_FUNC_ADDR_REG);
+                       s3c2410_udc_set_ep0_de_out(base_addr);
+                       return;
+               }
+               break;
+
+       case USB_REQ_GET_STATUS:
+               dprintk(DEBUG_NORMAL, "USB_REQ_GET_STATUS ...\n");
+               s3c2410_udc_clear_ep0_opr(base_addr);
+
+               if (dev->req_std) {
+                       if (!s3c2410_udc_get_status(dev, crq))
+                               return;
+               }
+               break;
+
+       case USB_REQ_CLEAR_FEATURE:
+               s3c2410_udc_clear_ep0_opr(base_addr);
+
+               if (crq->bRequestType != USB_RECIP_ENDPOINT)
+                       break;
+
+               if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0)
+                       break;
+
+               s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 0);
+               s3c2410_udc_set_ep0_de_out(base_addr);
+               return;
+
+       case USB_REQ_SET_FEATURE:
+               s3c2410_udc_clear_ep0_opr(base_addr);
+
+               if (crq->bRequestType != USB_RECIP_ENDPOINT)
+                       break;
+
+               if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0)
+                       break;
+
+               s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 1);
+               s3c2410_udc_set_ep0_de_out(base_addr);
+               return;
+
+       default:
+               s3c2410_udc_clear_ep0_opr(base_addr);
+               break;
+       }
+
+       if (crq->bRequestType & USB_DIR_IN)
+               dev->ep0state = EP0_IN_DATA_PHASE;
+       else
+               dev->ep0state = EP0_OUT_DATA_PHASE;
+
+       if (!dev->driver)
+               return;
+
+       /* deliver the request to the gadget driver */
+       ret = dev->driver->setup(&dev->gadget, crq);
+       if (ret < 0) {
+               if (dev->req_config) {
+                       dprintk(DEBUG_NORMAL, "config change %02x fail %d?\n",
+                               crq->bRequest, ret);
+                       return;
+               }
+
+               if (ret == -EOPNOTSUPP)
+                       dprintk(DEBUG_NORMAL, "Operation not supported\n");
+               else
+                       dprintk(DEBUG_NORMAL,
+                               "dev->driver->setup failed. (%d)\n", ret);
+
+               udelay(5);
+               s3c2410_udc_set_ep0_ss(base_addr);
+               s3c2410_udc_set_ep0_de_out(base_addr);
+               dev->ep0state = EP0_IDLE;
+               /* deferred i/o == no response yet */
+       } else if (dev->req_pending) {
+               dprintk(DEBUG_VERBOSE, "dev->req_pending... what now?\n");
+               dev->req_pending = 0;
+       }
+
+       dprintk(DEBUG_VERBOSE, "ep0state %s\n", ep0states[dev->ep0state]);
+}
+
+static void s3c2410_udc_handle_ep0(struct s3c2410_udc *dev)
+{
+       u32                     ep0csr;
+       struct s3c2410_ep       *ep = &dev->ep[0];
+       struct s3c2410_request  *req;
+       struct usb_ctrlrequest  crq;
+
+       if (list_empty(&ep->queue))
+               req = NULL;
+       else
+               req = list_entry(ep->queue.next, struct s3c2410_request, queue);
+
+       /* We make the assumption that S3C2410_UDC_IN_CSR1_REG equal to
+        * S3C2410_UDC_EP0_CSR_REG when index is zero */
+
+       udc_write(0, S3C2410_UDC_INDEX_REG);
+       ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+
+       dprintk(DEBUG_NORMAL, "ep0csr %x ep0state %s\n",
+               ep0csr, ep0states[dev->ep0state]);
+
+       /* clear stall status */
+       if (ep0csr & S3C2410_UDC_EP0_CSR_SENTSTL) {
+               s3c2410_udc_nuke(dev, ep, -EPIPE);
+               dprintk(DEBUG_NORMAL, "... clear SENT_STALL ...\n");
+               s3c2410_udc_clear_ep0_sst(base_addr);
+               dev->ep0state = EP0_IDLE;
+               return;
+       }
+
+       /* clear setup end */
+       if (ep0csr & S3C2410_UDC_EP0_CSR_SE) {
+               dprintk(DEBUG_NORMAL, "... serviced SETUP_END ...\n");
+               s3c2410_udc_nuke(dev, ep, 0);
+               s3c2410_udc_clear_ep0_se(base_addr);
+               dev->ep0state = EP0_IDLE;
+       }
+
+       switch (dev->ep0state) {
+       case EP0_IDLE:
+               s3c2410_udc_handle_ep0_idle(dev, ep, &crq, ep0csr);
+               break;
+
+       case EP0_IN_DATA_PHASE:                 /* GET_DESCRIPTOR etc */
+               dprintk(DEBUG_NORMAL, "EP0_IN_DATA_PHASE ... what now?\n");
+               if (!(ep0csr & S3C2410_UDC_EP0_CSR_IPKRDY) && req)
+                       s3c2410_udc_write_fifo(ep, req);
+               break;
+
+       case EP0_OUT_DATA_PHASE:                /* SET_DESCRIPTOR etc */
+               dprintk(DEBUG_NORMAL, "EP0_OUT_DATA_PHASE ... what now?\n");
+               if ((ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY) && req)
+                       s3c2410_udc_read_fifo(ep, req);
+               break;
+
+       case EP0_END_XFER:
+               dprintk(DEBUG_NORMAL, "EP0_END_XFER ... what now?\n");
+               dev->ep0state = EP0_IDLE;
+               break;
+
+       case EP0_STALL:
+               dprintk(DEBUG_NORMAL, "EP0_STALL ... what now?\n");
+               dev->ep0state = EP0_IDLE;
+               break;
+       }
+}
+
+/*
+ *     handle_ep - Manage I/O endpoints
+ */
+
+static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
+{
+       struct s3c2410_request  *req;
+       int                     is_in = ep->bEndpointAddress & USB_DIR_IN;
+       u32                     ep_csr1;
+       u32                     idx;
+
+       if (likely(!list_empty(&ep->queue)))
+               req = list_entry(ep->queue.next,
+                               struct s3c2410_request, queue);
+       else
+               req = NULL;
+
+       idx = ep->bEndpointAddress & 0x7F;
+
+       if (is_in) {
+               udc_write(idx, S3C2410_UDC_INDEX_REG);
+               ep_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
+               dprintk(DEBUG_VERBOSE, "ep%01d write csr:%02x %d\n",
+                       idx, ep_csr1, req ? 1 : 0);
+
+               if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) {
+                       dprintk(DEBUG_VERBOSE, "st\n");
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       udc_write(ep_csr1 & ~S3C2410_UDC_ICSR1_SENTSTL,
+                                       S3C2410_UDC_IN_CSR1_REG);
+                       return;
+               }
+
+               if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req)
+                       s3c2410_udc_write_fifo(ep, req);
+       } else {
+               udc_write(idx, S3C2410_UDC_INDEX_REG);
+               ep_csr1 = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+               dprintk(DEBUG_VERBOSE, "ep%01d rd csr:%02x\n", idx, ep_csr1);
+
+               if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) {
+                       udc_write(idx, S3C2410_UDC_INDEX_REG);
+                       udc_write(ep_csr1 & ~S3C2410_UDC_OCSR1_SENTSTL,
+                                       S3C2410_UDC_OUT_CSR1_REG);
+                       return;
+               }
+
+               if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req)
+                       s3c2410_udc_read_fifo(ep, req);
+       }
+}
+
+#include <mach/regs-irq.h>
+
+/*
+ *     s3c2410_udc_irq - interrupt handler
+ */
+static irqreturn_t s3c2410_udc_irq(int dummy, void *_dev)
+{
+       struct s3c2410_udc *dev = _dev;
+       int usb_status;
+       int usbd_status;
+       int pwr_reg;
+       int ep0csr;
+       int i;
+       u32 idx, idx2;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       /* Driver connected ? */
+       if (!dev->driver) {
+               /* Clear interrupts */
+               udc_write(udc_read(S3C2410_UDC_USB_INT_REG),
+                               S3C2410_UDC_USB_INT_REG);
+               udc_write(udc_read(S3C2410_UDC_EP_INT_REG),
+                               S3C2410_UDC_EP_INT_REG);
+       }
+
+       /* Save index */
+       idx = udc_read(S3C2410_UDC_INDEX_REG);
+
+       /* Read status registers */
+       usb_status = udc_read(S3C2410_UDC_USB_INT_REG);
+       usbd_status = udc_read(S3C2410_UDC_EP_INT_REG);
+       pwr_reg = udc_read(S3C2410_UDC_PWR_REG);
+
+       udc_writeb(base_addr, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+       ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+
+       dprintk(DEBUG_NORMAL, "usbs=%02x, usbds=%02x, pwr=%02x ep0csr=%02x\n",
+               usb_status, usbd_status, pwr_reg, ep0csr);
+
+       /*
+        * Now, handle interrupts. There's two types :
+        * - Reset, Resume, Suspend coming -> usb_int_reg
+        * - EP -> ep_int_reg
+        */
+
+       /* RESET */
+       if (usb_status & S3C2410_UDC_USBINT_RESET) {
+               /* two kind of reset :
+                * - reset start -> pwr reg = 8
+                * - reset end   -> pwr reg = 0
+                **/
+               dprintk(DEBUG_NORMAL, "USB reset csr %x pwr %x\n",
+                       ep0csr, pwr_reg);
+
+               dev->gadget.speed = USB_SPEED_UNKNOWN;
+               udc_write(0x00, S3C2410_UDC_INDEX_REG);
+               udc_write((dev->ep[0].ep.maxpacket & 0x7ff) >> 3,
+                               S3C2410_UDC_MAXP_REG);
+               dev->address = 0;
+
+               dev->ep0state = EP0_IDLE;
+               dev->gadget.speed = USB_SPEED_FULL;
+
+               /* clear interrupt */
+               udc_write(S3C2410_UDC_USBINT_RESET,
+                               S3C2410_UDC_USB_INT_REG);
+
+               udc_write(idx, S3C2410_UDC_INDEX_REG);
+               spin_unlock_irqrestore(&dev->lock, flags);
+               return IRQ_HANDLED;
+       }
+
+       /* RESUME */
+       if (usb_status & S3C2410_UDC_USBINT_RESUME) {
+               dprintk(DEBUG_NORMAL, "USB resume\n");
+
+               /* clear interrupt */
+               udc_write(S3C2410_UDC_USBINT_RESUME,
+                               S3C2410_UDC_USB_INT_REG);
+
+               if (dev->gadget.speed != USB_SPEED_UNKNOWN
+                               && dev->driver
+                               && dev->driver->resume)
+                       dev->driver->resume(&dev->gadget);
+       }
+
+       /* SUSPEND */
+       if (usb_status & S3C2410_UDC_USBINT_SUSPEND) {
+               dprintk(DEBUG_NORMAL, "USB suspend\n");
+
+               /* clear interrupt */
+               udc_write(S3C2410_UDC_USBINT_SUSPEND,
+                               S3C2410_UDC_USB_INT_REG);
+
+               if (dev->gadget.speed != USB_SPEED_UNKNOWN
+                               && dev->driver
+                               && dev->driver->suspend)
+                       dev->driver->suspend(&dev->gadget);
+
+               dev->ep0state = EP0_IDLE;
+       }
+
+       /* EP */
+       /* control traffic */
+       /* check on ep0csr != 0 is not a good idea as clearing in_pkt_ready
+        * generate an interrupt
+        */
+       if (usbd_status & S3C2410_UDC_INT_EP0) {
+               dprintk(DEBUG_VERBOSE, "USB ep0 irq\n");
+               /* Clear the interrupt bit by setting it to 1 */
+               udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_REG);
+               s3c2410_udc_handle_ep0(dev);
+       }
+
+       /* endpoint data transfers */
+       for (i = 1; i < S3C2410_ENDPOINTS; i++) {
+               u32 tmp = 1 << i;
+               if (usbd_status & tmp) {
+                       dprintk(DEBUG_VERBOSE, "USB ep%d irq\n", i);
+
+                       /* Clear the interrupt bit by setting it to 1 */
+                       udc_write(tmp, S3C2410_UDC_EP_INT_REG);
+                       s3c2410_udc_handle_ep(&dev->ep[i]);
+               }
+       }
+
+       /* what else causes this interrupt? a receive! who is it? */
+       if (!usb_status && !usbd_status && !pwr_reg && !ep0csr) {
+               for (i = 1; i < S3C2410_ENDPOINTS; i++) {
+                       idx2 = udc_read(S3C2410_UDC_INDEX_REG);
+                       udc_write(i, S3C2410_UDC_INDEX_REG);
+
+                       if (udc_read(S3C2410_UDC_OUT_CSR1_REG) & 0x1)
+                               s3c2410_udc_handle_ep(&dev->ep[i]);
+
+                       /* restore index */
+                       udc_write(idx2, S3C2410_UDC_INDEX_REG);
+               }
+       }
+
+       dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", IRQ_USBD);
+
+       /* Restore old index */
+       udc_write(idx, S3C2410_UDC_INDEX_REG);
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return IRQ_HANDLED;
+}
+/*------------------------- s3c2410_ep_ops ----------------------------------*/
+
+static inline struct s3c2410_ep *to_s3c2410_ep(struct usb_ep *ep)
+{
+       return container_of(ep, struct s3c2410_ep, ep);
+}
+
+static inline struct s3c2410_udc *to_s3c2410_udc(struct usb_gadget *gadget)
+{
+       return container_of(gadget, struct s3c2410_udc, gadget);
+}
+
+static inline struct s3c2410_request *to_s3c2410_req(struct usb_request *req)
+{
+       return container_of(req, struct s3c2410_request, req);
+}
+
+/*
+ *     s3c2410_udc_ep_enable
+ */
+static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
+                                const struct usb_endpoint_descriptor *desc)
+{
+       struct s3c2410_udc      *dev;
+       struct s3c2410_ep       *ep;
+       u32                     max, tmp;
+       unsigned long           flags;
+       u32                     csr1, csr2;
+       u32                     int_en_reg;
+
+       ep = to_s3c2410_ep(_ep);
+
+       if (!_ep || !desc
+                       || _ep->name == ep0name
+                       || desc->bDescriptorType != USB_DT_ENDPOINT)
+               return -EINVAL;
+
+       dev = ep->dev;
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       max = usb_endpoint_maxp(desc) & 0x1fff;
+
+       local_irq_save(flags);
+       _ep->maxpacket = max & 0x7ff;
+       ep->ep.desc = desc;
+       ep->halted = 0;
+       ep->bEndpointAddress = desc->bEndpointAddress;
+
+       /* set max packet */
+       udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+       udc_write(max >> 3, S3C2410_UDC_MAXP_REG);
+
+       /* set type, direction, address; reset fifo counters */
+       if (desc->bEndpointAddress & USB_DIR_IN) {
+               csr1 = S3C2410_UDC_ICSR1_FFLUSH|S3C2410_UDC_ICSR1_CLRDT;
+               csr2 = S3C2410_UDC_ICSR2_MODEIN|S3C2410_UDC_ICSR2_DMAIEN;
+
+               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+               udc_write(csr1, S3C2410_UDC_IN_CSR1_REG);
+               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+               udc_write(csr2, S3C2410_UDC_IN_CSR2_REG);
+       } else {
+               /* don't flush in fifo or it will cause endpoint interrupt */
+               csr1 = S3C2410_UDC_ICSR1_CLRDT;
+               csr2 = S3C2410_UDC_ICSR2_DMAIEN;
+
+               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+               udc_write(csr1, S3C2410_UDC_IN_CSR1_REG);
+               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+               udc_write(csr2, S3C2410_UDC_IN_CSR2_REG);
+
+               csr1 = S3C2410_UDC_OCSR1_FFLUSH | S3C2410_UDC_OCSR1_CLRDT;
+               csr2 = S3C2410_UDC_OCSR2_DMAIEN;
+
+               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+               udc_write(csr1, S3C2410_UDC_OUT_CSR1_REG);
+               udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+               udc_write(csr2, S3C2410_UDC_OUT_CSR2_REG);
+       }
+
+       /* enable irqs */
+       int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
+       udc_write(int_en_reg | (1 << ep->num), S3C2410_UDC_EP_INT_EN_REG);
+
+       /* print some debug message */
+       tmp = desc->bEndpointAddress;
+       dprintk(DEBUG_NORMAL, "enable %s(%d) ep%x%s-blk max %02x\n",
+                _ep->name, ep->num, tmp,
+                desc->bEndpointAddress & USB_DIR_IN ? "in" : "out", max);
+
+       local_irq_restore(flags);
+       s3c2410_udc_set_halt(_ep, 0);
+
+       return 0;
+}
+
+/*
+ * s3c2410_udc_ep_disable
+ */
+static int s3c2410_udc_ep_disable(struct usb_ep *_ep)
+{
+       struct s3c2410_ep *ep = to_s3c2410_ep(_ep);
+       unsigned long flags;
+       u32 int_en_reg;
+
+       if (!_ep || !ep->ep.desc) {
+               dprintk(DEBUG_NORMAL, "%s not enabled\n",
+                       _ep ? ep->ep.name : NULL);
+               return -EINVAL;
+       }
+
+       local_irq_save(flags);
+
+       dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name);
+
+       ep->ep.desc = NULL;
+       ep->halted = 1;
+
+       s3c2410_udc_nuke(ep->dev, ep, -ESHUTDOWN);
+
+       /* disable irqs */
+       int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
+       udc_write(int_en_reg & ~(1<<ep->num), S3C2410_UDC_EP_INT_EN_REG);
+
+       local_irq_restore(flags);
+
+       dprintk(DEBUG_NORMAL, "%s disabled\n", _ep->name);
+
+       return 0;
+}
+
+/*
+ * s3c2410_udc_alloc_request
+ */
+static struct usb_request *
+s3c2410_udc_alloc_request(struct usb_ep *_ep, gfp_t mem_flags)
+{
+       struct s3c2410_request *req;
+
+       dprintk(DEBUG_VERBOSE, "%s(%p,%d)\n", __func__, _ep, mem_flags);
+
+       if (!_ep)
+               return NULL;
+
+       req = kzalloc(sizeof(struct s3c2410_request), mem_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+       return &req->req;
+}
+
+/*
+ * s3c2410_udc_free_request
+ */
+static void
+s3c2410_udc_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct s3c2410_ep       *ep = to_s3c2410_ep(_ep);
+       struct s3c2410_request  *req = to_s3c2410_req(_req);
+
+       dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req);
+
+       if (!ep || !_req || (!ep->ep.desc && _ep->name != ep0name))
+               return;
+
+       WARN_ON(!list_empty(&req->queue));
+       kfree(req);
+}
+
+/*
+ *     s3c2410_udc_queue
+ */
+static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req,
+               gfp_t gfp_flags)
+{
+       struct s3c2410_request  *req = to_s3c2410_req(_req);
+       struct s3c2410_ep       *ep = to_s3c2410_ep(_ep);
+       struct s3c2410_udc      *dev;
+       u32                     ep_csr = 0;
+       int                     fifo_count = 0;
+       unsigned long           flags;
+
+       if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) {
+               dprintk(DEBUG_NORMAL, "%s: invalid args\n", __func__);
+               return -EINVAL;
+       }
+
+       dev = ep->dev;
+       if (unlikely(!dev->driver
+                       || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+               return -ESHUTDOWN;
+       }
+
+       local_irq_save(flags);
+
+       if (unlikely(!_req || !_req->complete
+                       || !_req->buf || !list_empty(&req->queue))) {
+               if (!_req)
+                       dprintk(DEBUG_NORMAL, "%s: 1 X X X\n", __func__);
+               else {
+                       dprintk(DEBUG_NORMAL, "%s: 0 %01d %01d %01d\n",
+                               __func__, !_req->complete, !_req->buf,
+                               !list_empty(&req->queue));
+               }
+
+               local_irq_restore(flags);
+               return -EINVAL;
+       }
+
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       dprintk(DEBUG_VERBOSE, "%s: ep%x len %d\n",
+                __func__, ep->bEndpointAddress, _req->length);
+
+       if (ep->bEndpointAddress) {
+               udc_write(ep->bEndpointAddress & 0x7F, S3C2410_UDC_INDEX_REG);
+
+               ep_csr = udc_read((ep->bEndpointAddress & USB_DIR_IN)
+                               ? S3C2410_UDC_IN_CSR1_REG
+                               : S3C2410_UDC_OUT_CSR1_REG);
+               fifo_count = s3c2410_udc_fifo_count_out();
+       } else {
+               udc_write(0, S3C2410_UDC_INDEX_REG);
+               ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+               fifo_count = s3c2410_udc_fifo_count_out();
+       }
+
+       /* kickstart this i/o queue? */
+       if (list_empty(&ep->queue) && !ep->halted) {
+               if (ep->bEndpointAddress == 0 /* ep0 */) {
+                       switch (dev->ep0state) {
+                       case EP0_IN_DATA_PHASE:
+                               if (!(ep_csr&S3C2410_UDC_EP0_CSR_IPKRDY)
+                                               && s3c2410_udc_write_fifo(ep,
+                                                       req)) {
+                                       dev->ep0state = EP0_IDLE;
+                                       req = NULL;
+                               }
+                               break;
+
+                       case EP0_OUT_DATA_PHASE:
+                               if ((!_req->length)
+                                       || ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY)
+                                               && s3c2410_udc_read_fifo(ep,
+                                                       req))) {
+                                       dev->ep0state = EP0_IDLE;
+                                       req = NULL;
+                               }
+                               break;
+
+                       default:
+                               local_irq_restore(flags);
+                               return -EL2HLT;
+                       }
+               } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0
+                               && (!(ep_csr&S3C2410_UDC_OCSR1_PKTRDY))
+                               && s3c2410_udc_write_fifo(ep, req)) {
+                       req = NULL;
+               } else if ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY)
+                               && fifo_count
+                               && s3c2410_udc_read_fifo(ep, req)) {
+                       req = NULL;
+               }
+       }
+
+       /* pio or dma irq handler advances the queue. */
+       if (likely(req))
+               list_add_tail(&req->queue, &ep->queue);
+
+       local_irq_restore(flags);
+
+       dprintk(DEBUG_VERBOSE, "%s ok\n", __func__);
+       return 0;
+}
+
+/*
+ *     s3c2410_udc_dequeue
+ */
+static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct s3c2410_ep       *ep = to_s3c2410_ep(_ep);
+       struct s3c2410_udc      *udc;
+       int                     retval = -EINVAL;
+       unsigned long           flags;
+       struct s3c2410_request  *req = NULL;
+
+       dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req);
+
+       if (!the_controller->driver)
+               return -ESHUTDOWN;
+
+       if (!_ep || !_req)
+               return retval;
+
+       udc = to_s3c2410_udc(ep->gadget);
+
+       local_irq_save(flags);
+
+       list_for_each_entry(req, &ep->queue, queue) {
+               if (&req->req == _req) {
+                       list_del_init(&req->queue);
+                       _req->status = -ECONNRESET;
+                       retval = 0;
+                       break;
+               }
+       }
+
+       if (retval == 0) {
+               dprintk(DEBUG_VERBOSE,
+                       "dequeued req %p from %s, len %d buf %p\n",
+                       req, _ep->name, _req->length, _req->buf);
+
+               s3c2410_udc_done(ep, req, -ECONNRESET);
+       }
+
+       local_irq_restore(flags);
+       return retval;
+}
+
+/*
+ * s3c2410_udc_set_halt
+ */
+static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value)
+{
+       struct s3c2410_ep       *ep = to_s3c2410_ep(_ep);
+       u32                     ep_csr = 0;
+       unsigned long           flags;
+       u32                     idx;
+
+       if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) {
+               dprintk(DEBUG_NORMAL, "%s: inval 2\n", __func__);
+               return -EINVAL;
+       }
+
+       local_irq_save(flags);
+
+       idx = ep->bEndpointAddress & 0x7F;
+
+       if (idx == 0) {
+               s3c2410_udc_set_ep0_ss(base_addr);
+               s3c2410_udc_set_ep0_de_out(base_addr);
+       } else {
+               udc_write(idx, S3C2410_UDC_INDEX_REG);
+               ep_csr = udc_read((ep->bEndpointAddress & USB_DIR_IN)
+                               ? S3C2410_UDC_IN_CSR1_REG
+                               : S3C2410_UDC_OUT_CSR1_REG);
+
+               if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
+                       if (value)
+                               udc_write(ep_csr | S3C2410_UDC_ICSR1_SENDSTL,
+                                       S3C2410_UDC_IN_CSR1_REG);
+                       else {
+                               ep_csr &= ~S3C2410_UDC_ICSR1_SENDSTL;
+                               udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG);
+                               ep_csr |= S3C2410_UDC_ICSR1_CLRDT;
+                               udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG);
+                       }
+               } else {
+                       if (value)
+                               udc_write(ep_csr | S3C2410_UDC_OCSR1_SENDSTL,
+                                       S3C2410_UDC_OUT_CSR1_REG);
+                       else {
+                               ep_csr &= ~S3C2410_UDC_OCSR1_SENDSTL;
+                               udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG);
+                               ep_csr |= S3C2410_UDC_OCSR1_CLRDT;
+                               udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG);
+                       }
+               }
+       }
+
+       ep->halted = value ? 1 : 0;
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+static const struct usb_ep_ops s3c2410_ep_ops = {
+       .enable         = s3c2410_udc_ep_enable,
+       .disable        = s3c2410_udc_ep_disable,
+
+       .alloc_request  = s3c2410_udc_alloc_request,
+       .free_request   = s3c2410_udc_free_request,
+
+       .queue          = s3c2410_udc_queue,
+       .dequeue        = s3c2410_udc_dequeue,
+
+       .set_halt       = s3c2410_udc_set_halt,
+};
+
+/*------------------------- usb_gadget_ops ----------------------------------*/
+
+/*
+ *     s3c2410_udc_get_frame
+ */
+static int s3c2410_udc_get_frame(struct usb_gadget *_gadget)
+{
+       int tmp;
+
+       dprintk(DEBUG_VERBOSE, "%s()\n", __func__);
+
+       tmp = udc_read(S3C2410_UDC_FRAME_NUM2_REG) << 8;
+       tmp |= udc_read(S3C2410_UDC_FRAME_NUM1_REG);
+       return tmp;
+}
+
+/*
+ *     s3c2410_udc_wakeup
+ */
+static int s3c2410_udc_wakeup(struct usb_gadget *_gadget)
+{
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+       return 0;
+}
+
+/*
+ *     s3c2410_udc_set_selfpowered
+ */
+static int s3c2410_udc_set_selfpowered(struct usb_gadget *gadget, int value)
+{
+       struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
+
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+       if (value)
+               udc->devstatus |= (1 << USB_DEVICE_SELF_POWERED);
+       else
+               udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
+
+       return 0;
+}
+
+static void s3c2410_udc_disable(struct s3c2410_udc *dev);
+static void s3c2410_udc_enable(struct s3c2410_udc *dev);
+
+static int s3c2410_udc_set_pullup(struct s3c2410_udc *udc, int is_on)
+{
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+       if (udc_info && (udc_info->udc_command ||
+               gpio_is_valid(udc_info->pullup_pin))) {
+
+               if (is_on)
+                       s3c2410_udc_enable(udc);
+               else {
+                       if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+                               if (udc->driver && udc->driver->disconnect)
+                                       udc->driver->disconnect(&udc->gadget);
+
+                       }
+                       s3c2410_udc_disable(udc);
+               }
+       } else {
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+static int s3c2410_udc_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+       struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
+
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+       udc->vbus = (is_active != 0);
+       s3c2410_udc_set_pullup(udc, is_active);
+       return 0;
+}
+
+static int s3c2410_udc_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
+
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+       s3c2410_udc_set_pullup(udc, is_on ? 0 : 1);
+       return 0;
+}
+
+static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev)
+{
+       struct s3c2410_udc      *dev = _dev;
+       unsigned int            value;
+
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+       value = gpio_get_value(udc_info->vbus_pin) ? 1 : 0;
+       if (udc_info->vbus_pin_inverted)
+               value = !value;
+
+       if (value != dev->vbus)
+               s3c2410_udc_vbus_session(&dev->gadget, value);
+
+       return IRQ_HANDLED;
+}
+
+static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
+{
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+       if (udc_info && udc_info->vbus_draw) {
+               udc_info->vbus_draw(ma);
+               return 0;
+       }
+
+       return -ENOTSUPP;
+}
+
+static int s3c2410_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+static int s3c2410_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver);
+
+static const struct usb_gadget_ops s3c2410_ops = {
+       .get_frame              = s3c2410_udc_get_frame,
+       .wakeup                 = s3c2410_udc_wakeup,
+       .set_selfpowered        = s3c2410_udc_set_selfpowered,
+       .pullup                 = s3c2410_udc_pullup,
+       .vbus_session           = s3c2410_udc_vbus_session,
+       .vbus_draw              = s3c2410_vbus_draw,
+       .udc_start              = s3c2410_udc_start,
+       .udc_stop               = s3c2410_udc_stop,
+};
+
+static void s3c2410_udc_command(enum s3c2410_udc_cmd_e cmd)
+{
+       if (!udc_info)
+               return;
+
+       if (udc_info->udc_command) {
+               udc_info->udc_command(cmd);
+       } else if (gpio_is_valid(udc_info->pullup_pin)) {
+               int value;
+
+               switch (cmd) {
+               case S3C2410_UDC_P_ENABLE:
+                       value = 1;
+                       break;
+               case S3C2410_UDC_P_DISABLE:
+                       value = 0;
+                       break;
+               default:
+                       return;
+               }
+               value ^= udc_info->pullup_pin_inverted;
+
+               gpio_set_value(udc_info->pullup_pin, value);
+       }
+}
+
+/*------------------------- gadget driver handling---------------------------*/
+/*
+ * s3c2410_udc_disable
+ */
+static void s3c2410_udc_disable(struct s3c2410_udc *dev)
+{
+       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+       /* Disable all interrupts */
+       udc_write(0x00, S3C2410_UDC_USB_INT_EN_REG);
+       udc_write(0x00, S3C2410_UDC_EP_INT_EN_REG);
+
+       /* Clear the interrupt registers */
+       udc_write(S3C2410_UDC_USBINT_RESET
+                               | S3C2410_UDC_USBINT_RESUME
+                               | S3C2410_UDC_USBINT_SUSPEND,
+                       S3C2410_UDC_USB_INT_REG);
+
+       udc_write(0x1F, S3C2410_UDC_EP_INT_REG);
+
+       /* Good bye, cruel world */
+       s3c2410_udc_command(S3C2410_UDC_P_DISABLE);
+
+       /* Set speed to unknown */
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+}
+
+/*
+ * s3c2410_udc_reinit
+ */
+static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
+{
+       u32 i;
+
+       /* device/ep0 records init */
+       INIT_LIST_HEAD(&dev->gadget.ep_list);
+       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+       dev->ep0state = EP0_IDLE;
+
+       for (i = 0; i < S3C2410_ENDPOINTS; i++) {
+               struct s3c2410_ep *ep = &dev->ep[i];
+
+               if (i != 0)
+                       list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+
+               ep->dev = dev;
+               ep->ep.desc = NULL;
+               ep->halted = 0;
+               INIT_LIST_HEAD(&ep->queue);
+               usb_ep_set_maxpacket_limit(&ep->ep, ep->ep.maxpacket);
+       }
+}
+
+/*
+ * s3c2410_udc_enable
+ */
+static void s3c2410_udc_enable(struct s3c2410_udc *dev)
+{
+       int i;
+
+       dprintk(DEBUG_NORMAL, "s3c2410_udc_enable called\n");
+
+       /* dev->gadget.speed = USB_SPEED_UNKNOWN; */
+       dev->gadget.speed = USB_SPEED_FULL;
+
+       /* Set MAXP for all endpoints */
+       for (i = 0; i < S3C2410_ENDPOINTS; i++) {
+               udc_write(i, S3C2410_UDC_INDEX_REG);
+               udc_write((dev->ep[i].ep.maxpacket & 0x7ff) >> 3,
+                               S3C2410_UDC_MAXP_REG);
+       }
+
+       /* Set default power state */
+       udc_write(DEFAULT_POWER_STATE, S3C2410_UDC_PWR_REG);
+
+       /* Enable reset and suspend interrupt interrupts */
+       udc_write(S3C2410_UDC_USBINT_RESET | S3C2410_UDC_USBINT_SUSPEND,
+                       S3C2410_UDC_USB_INT_EN_REG);
+
+       /* Enable ep0 interrupt */
+       udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_EN_REG);
+
+       /* time to say "hello, world" */
+       s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
+}
+
+static int s3c2410_udc_start(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct s3c2410_udc *udc = to_s3c2410(g);
+
+       dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name);
+
+       /* Hook the driver */
+       udc->driver = driver;
+
+       /* Enable udc */
+       s3c2410_udc_enable(udc);
+
+       return 0;
+}
+
+static int s3c2410_udc_stop(struct usb_gadget *g,
+               struct usb_gadget_driver *driver)
+{
+       struct s3c2410_udc *udc = to_s3c2410(g);
+
+       udc->driver = NULL;
+
+       /* Disable udc */
+       s3c2410_udc_disable(udc);
+
+       return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+static struct s3c2410_udc memory = {
+       .gadget = {
+               .ops            = &s3c2410_ops,
+               .ep0            = &memory.ep[0].ep,
+               .name           = gadget_name,
+               .dev = {
+                       .init_name      = "gadget",
+               },
+       },
+
+       /* control endpoint */
+       .ep[0] = {
+               .num            = 0,
+               .ep = {
+                       .name           = ep0name,
+                       .ops            = &s3c2410_ep_ops,
+                       .maxpacket      = EP0_FIFO_SIZE,
+               },
+               .dev            = &memory,
+       },
+
+       /* first group of endpoints */
+       .ep[1] = {
+               .num            = 1,
+               .ep = {
+                       .name           = "ep1-bulk",
+                       .ops            = &s3c2410_ep_ops,
+                       .maxpacket      = EP_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = EP_FIFO_SIZE,
+               .bEndpointAddress = 1,
+               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
+       },
+       .ep[2] = {
+               .num            = 2,
+               .ep = {
+                       .name           = "ep2-bulk",
+                       .ops            = &s3c2410_ep_ops,
+                       .maxpacket      = EP_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = EP_FIFO_SIZE,
+               .bEndpointAddress = 2,
+               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
+       },
+       .ep[3] = {
+               .num            = 3,
+               .ep = {
+                       .name           = "ep3-bulk",
+                       .ops            = &s3c2410_ep_ops,
+                       .maxpacket      = EP_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = EP_FIFO_SIZE,
+               .bEndpointAddress = 3,
+               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
+       },
+       .ep[4] = {
+               .num            = 4,
+               .ep = {
+                       .name           = "ep4-bulk",
+                       .ops            = &s3c2410_ep_ops,
+                       .maxpacket      = EP_FIFO_SIZE,
+               },
+               .dev            = &memory,
+               .fifo_size      = EP_FIFO_SIZE,
+               .bEndpointAddress = 4,
+               .bmAttributes   = USB_ENDPOINT_XFER_BULK,
+       }
+
+};
+
+/*
+ *     probe - binds to the platform device
+ */
+static int s3c2410_udc_probe(struct platform_device *pdev)
+{
+       struct s3c2410_udc *udc = &memory;
+       struct device *dev = &pdev->dev;
+       int retval;
+       int irq;
+
+       dev_dbg(dev, "%s()\n", __func__);
+
+       usb_bus_clock = clk_get(NULL, "usb-bus-gadget");
+       if (IS_ERR(usb_bus_clock)) {
+               dev_err(dev, "failed to get usb bus clock source\n");
+               return PTR_ERR(usb_bus_clock);
+       }
+
+       clk_prepare_enable(usb_bus_clock);
+
+       udc_clock = clk_get(NULL, "usb-device");
+       if (IS_ERR(udc_clock)) {
+               dev_err(dev, "failed to get udc clock source\n");
+               return PTR_ERR(udc_clock);
+       }
+
+       clk_prepare_enable(udc_clock);
+
+       mdelay(10);
+
+       dev_dbg(dev, "got and enabled clocks\n");
+
+       if (strncmp(pdev->name, "s3c2440", 7) == 0) {
+               dev_info(dev, "S3C2440: increasing FIFO to 128 bytes\n");
+               memory.ep[1].fifo_size = S3C2440_EP_FIFO_SIZE;
+               memory.ep[2].fifo_size = S3C2440_EP_FIFO_SIZE;
+               memory.ep[3].fifo_size = S3C2440_EP_FIFO_SIZE;
+               memory.ep[4].fifo_size = S3C2440_EP_FIFO_SIZE;
+       }
+
+       spin_lock_init(&udc->lock);
+       udc_info = dev_get_platdata(&pdev->dev);
+
+       rsrc_start = S3C2410_PA_USBDEV;
+       rsrc_len   = S3C24XX_SZ_USBDEV;
+
+       if (!request_mem_region(rsrc_start, rsrc_len, gadget_name))
+               return -EBUSY;
+
+       base_addr = ioremap(rsrc_start, rsrc_len);
+       if (!base_addr) {
+               retval = -ENOMEM;
+               goto err_mem;
+       }
+
+       the_controller = udc;
+       platform_set_drvdata(pdev, udc);
+
+       s3c2410_udc_disable(udc);
+       s3c2410_udc_reinit(udc);
+
+       /* irq setup after old hardware state is cleaned up */
+       retval = request_irq(IRQ_USBD, s3c2410_udc_irq,
+                            0, gadget_name, udc);
+
+       if (retval != 0) {
+               dev_err(dev, "cannot get irq %i, err %d\n", IRQ_USBD, retval);
+               retval = -EBUSY;
+               goto err_map;
+       }
+
+       dev_dbg(dev, "got irq %i\n", IRQ_USBD);
+
+       if (udc_info && udc_info->vbus_pin > 0) {
+               retval = gpio_request(udc_info->vbus_pin, "udc vbus");
+               if (retval < 0) {
+                       dev_err(dev, "cannot claim vbus pin\n");
+                       goto err_int;
+               }
+
+               irq = gpio_to_irq(udc_info->vbus_pin);
+               if (irq < 0) {
+                       dev_err(dev, "no irq for gpio vbus pin\n");
+                       retval = irq;
+                       goto err_gpio_claim;
+               }
+
+               retval = request_irq(irq, s3c2410_udc_vbus_irq,
+                                    IRQF_TRIGGER_RISING
+                                    | IRQF_TRIGGER_FALLING | IRQF_SHARED,
+                                    gadget_name, udc);
+
+               if (retval != 0) {
+                       dev_err(dev, "can't get vbus irq %d, err %d\n",
+                               irq, retval);
+                       retval = -EBUSY;
+                       goto err_gpio_claim;
+               }
+
+               dev_dbg(dev, "got irq %i\n", irq);
+       } else {
+               udc->vbus = 1;
+       }
+
+       if (udc_info && !udc_info->udc_command &&
+               gpio_is_valid(udc_info->pullup_pin)) {
+
+               retval = gpio_request_one(udc_info->pullup_pin,
+                               udc_info->vbus_pin_inverted ?
+                               GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
+                               "udc pullup");
+               if (retval)
+                       goto err_vbus_irq;
+       }
+
+       retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
+       if (retval)
+               goto err_add_udc;
+
+       if (s3c2410_udc_debugfs_root) {
+               udc->regs_info = debugfs_create_file("registers", S_IRUGO,
+                               s3c2410_udc_debugfs_root,
+                               udc, &s3c2410_udc_debugfs_fops);
+               if (!udc->regs_info)
+                       dev_warn(dev, "debugfs file creation failed\n");
+       }
+
+       dev_dbg(dev, "probe ok\n");
+
+       return 0;
+
+err_add_udc:
+       if (udc_info && !udc_info->udc_command &&
+                       gpio_is_valid(udc_info->pullup_pin))
+               gpio_free(udc_info->pullup_pin);
+err_vbus_irq:
+       if (udc_info && udc_info->vbus_pin > 0)
+               free_irq(gpio_to_irq(udc_info->vbus_pin), udc);
+err_gpio_claim:
+       if (udc_info && udc_info->vbus_pin > 0)
+               gpio_free(udc_info->vbus_pin);
+err_int:
+       free_irq(IRQ_USBD, udc);
+err_map:
+       iounmap(base_addr);
+err_mem:
+       release_mem_region(rsrc_start, rsrc_len);
+
+       return retval;
+}
+
+/*
+ *     s3c2410_udc_remove
+ */
+static int s3c2410_udc_remove(struct platform_device *pdev)
+{
+       struct s3c2410_udc *udc = platform_get_drvdata(pdev);
+       unsigned int irq;
+
+       dev_dbg(&pdev->dev, "%s()\n", __func__);
+
+       if (udc->driver)
+               return -EBUSY;
+
+       usb_del_gadget_udc(&udc->gadget);
+       debugfs_remove(udc->regs_info);
+
+       if (udc_info && !udc_info->udc_command &&
+               gpio_is_valid(udc_info->pullup_pin))
+               gpio_free(udc_info->pullup_pin);
+
+       if (udc_info && udc_info->vbus_pin > 0) {
+               irq = gpio_to_irq(udc_info->vbus_pin);
+               free_irq(irq, udc);
+       }
+
+       free_irq(IRQ_USBD, udc);
+
+       iounmap(base_addr);
+       release_mem_region(rsrc_start, rsrc_len);
+
+       if (!IS_ERR(udc_clock) && udc_clock != NULL) {
+               clk_disable_unprepare(udc_clock);
+               clk_put(udc_clock);
+               udc_clock = NULL;
+       }
+
+       if (!IS_ERR(usb_bus_clock) && usb_bus_clock != NULL) {
+               clk_disable_unprepare(usb_bus_clock);
+               clk_put(usb_bus_clock);
+               usb_bus_clock = NULL;
+       }
+
+       dev_dbg(&pdev->dev, "%s: remove ok\n", __func__);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int
+s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message)
+{
+       s3c2410_udc_command(S3C2410_UDC_P_DISABLE);
+
+       return 0;
+}
+
+static int s3c2410_udc_resume(struct platform_device *pdev)
+{
+       s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
+
+       return 0;
+}
+#else
+#define s3c2410_udc_suspend    NULL
+#define s3c2410_udc_resume     NULL
+#endif
+
+static const struct platform_device_id s3c_udc_ids[] = {
+       { "s3c2410-usbgadget", },
+       { "s3c2440-usbgadget", },
+       { }
+};
+MODULE_DEVICE_TABLE(platform, s3c_udc_ids);
+
+static struct platform_driver udc_driver_24x0 = {
+       .driver         = {
+               .name   = "s3c24x0-usbgadget",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = s3c2410_udc_probe,
+       .remove         = s3c2410_udc_remove,
+       .suspend        = s3c2410_udc_suspend,
+       .resume         = s3c2410_udc_resume,
+       .id_table       = s3c_udc_ids,
+};
+
+static int __init udc_init(void)
+{
+       int retval;
+
+       dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);
+
+       s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
+       if (IS_ERR(s3c2410_udc_debugfs_root)) {
+               pr_err("%s: debugfs dir creation failed %ld\n",
+                       gadget_name, PTR_ERR(s3c2410_udc_debugfs_root));
+               s3c2410_udc_debugfs_root = NULL;
+       }
+
+       retval = platform_driver_register(&udc_driver_24x0);
+       if (retval)
+               goto err;
+
+       return 0;
+
+err:
+       debugfs_remove(s3c2410_udc_debugfs_root);
+       return retval;
+}
+
+static void __exit udc_exit(void)
+{
+       platform_driver_unregister(&udc_driver_24x0);
+       debugfs_remove(s3c2410_udc_debugfs_root);
+}
+
+module_init(udc_init);
+module_exit(udc_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/udc/s3c2410_udc.h b/drivers/usb/gadget/udc/s3c2410_udc.h
new file mode 100644 (file)
index 0000000..93bf225
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * linux/drivers/usb/gadget/s3c2410_udc.h
+ * Samsung on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2004-2007 Herbert Pötzl - Arnaud Patard
+ *     Additional cleanups by Ben Dooks <ben-linux@fluff.org>
+ *
+ * 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.
+ */
+
+#ifndef _S3C2410_UDC_H
+#define _S3C2410_UDC_H
+
+struct s3c2410_ep {
+       struct list_head                queue;
+       unsigned long                   last_io;        /* jiffies timestamp */
+       struct usb_gadget               *gadget;
+       struct s3c2410_udc              *dev;
+       struct usb_ep                   ep;
+       u8                              num;
+
+       unsigned short                  fifo_size;
+       u8                              bEndpointAddress;
+       u8                              bmAttributes;
+
+       unsigned                        halted : 1;
+       unsigned                        already_seen : 1;
+       unsigned                        setup_stage : 1;
+};
+
+
+/* Warning : ep0 has a fifo of 16 bytes */
+/* Don't try to set 32 or 64            */
+/* also testusb 14 fails  wit 16 but is */
+/* fine with 8                          */
+#define EP0_FIFO_SIZE           8
+#define EP_FIFO_SIZE           64
+#define DEFAULT_POWER_STATE    0x00
+
+#define S3C2440_EP_FIFO_SIZE   128
+
+static const char ep0name [] = "ep0";
+
+static const char *const ep_name[] = {
+       ep0name,                                /* everyone has ep0 */
+       /* s3c2410 four bidirectional bulk endpoints */
+       "ep1-bulk", "ep2-bulk", "ep3-bulk", "ep4-bulk",
+};
+
+#define S3C2410_ENDPOINTS       ARRAY_SIZE(ep_name)
+
+struct s3c2410_request {
+       struct list_head                queue;          /* ep's requests */
+       struct usb_request              req;
+};
+
+enum ep0_state {
+        EP0_IDLE,
+        EP0_IN_DATA_PHASE,
+        EP0_OUT_DATA_PHASE,
+        EP0_END_XFER,
+        EP0_STALL,
+};
+
+static const char *ep0states[]= {
+        "EP0_IDLE",
+        "EP0_IN_DATA_PHASE",
+        "EP0_OUT_DATA_PHASE",
+        "EP0_END_XFER",
+        "EP0_STALL",
+};
+
+struct s3c2410_udc {
+       spinlock_t                      lock;
+
+       struct s3c2410_ep               ep[S3C2410_ENDPOINTS];
+       int                             address;
+       struct usb_gadget               gadget;
+       struct usb_gadget_driver        *driver;
+       struct s3c2410_request          fifo_req;
+       u8                              fifo_buf[EP_FIFO_SIZE];
+       u16                             devstatus;
+
+       u32                             port_status;
+       int                             ep0state;
+
+       unsigned                        got_irq : 1;
+
+       unsigned                        req_std : 1;
+       unsigned                        req_config : 1;
+       unsigned                        req_pending : 1;
+       u8                              vbus;
+       struct dentry                   *regs_info;
+};
+#define to_s3c2410(g)  (container_of((g), struct s3c2410_udc, gadget))
+
+#endif
diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
new file mode 100644 (file)
index 0000000..b0d9817
--- /dev/null
@@ -0,0 +1,585 @@
+/**
+ * udc.c - Core UDC Framework
+ *
+ * Copyright (C) 2010 Texas Instruments
+ * Author: Felipe Balbi <balbi@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/workqueue.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+/**
+ * struct usb_udc - describes one usb device controller
+ * @driver - the gadget driver pointer. For use by the class code
+ * @dev - the child device to the actual controller
+ * @gadget - the gadget. For use by the class code
+ * @list - for use by the udc class driver
+ *
+ * This represents the internal data structure which is used by the UDC-class
+ * to hold information about udc driver and gadget together.
+ */
+struct usb_udc {
+       struct usb_gadget_driver        *driver;
+       struct usb_gadget               *gadget;
+       struct device                   dev;
+       struct list_head                list;
+};
+
+static struct class *udc_class;
+static LIST_HEAD(udc_list);
+static DEFINE_MUTEX(udc_lock);
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_HAS_DMA
+
+int usb_gadget_map_request(struct usb_gadget *gadget,
+               struct usb_request *req, int is_in)
+{
+       if (req->length == 0)
+               return 0;
+
+       if (req->num_sgs) {
+               int     mapped;
+
+               mapped = dma_map_sg(&gadget->dev, req->sg, req->num_sgs,
+                               is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+               if (mapped == 0) {
+                       dev_err(&gadget->dev, "failed to map SGs\n");
+                       return -EFAULT;
+               }
+
+               req->num_mapped_sgs = mapped;
+       } else {
+               req->dma = dma_map_single(&gadget->dev, req->buf, req->length,
+                               is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+
+               if (dma_mapping_error(&gadget->dev, req->dma)) {
+                       dev_err(&gadget->dev, "failed to map buffer\n");
+                       return -EFAULT;
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_map_request);
+
+void usb_gadget_unmap_request(struct usb_gadget *gadget,
+               struct usb_request *req, int is_in)
+{
+       if (req->length == 0)
+               return;
+
+       if (req->num_mapped_sgs) {
+               dma_unmap_sg(&gadget->dev, req->sg, req->num_mapped_sgs,
+                               is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+
+               req->num_mapped_sgs = 0;
+       } else {
+               dma_unmap_single(&gadget->dev, req->dma, req->length,
+                               is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+       }
+}
+EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
+
+#endif /* CONFIG_HAS_DMA */
+
+/* ------------------------------------------------------------------------- */
+
+static void usb_gadget_state_work(struct work_struct *work)
+{
+       struct usb_gadget       *gadget = work_to_gadget(work);
+
+       sysfs_notify(&gadget->dev.kobj, NULL, "state");
+}
+
+void usb_gadget_set_state(struct usb_gadget *gadget,
+               enum usb_device_state state)
+{
+       gadget->state = state;
+       schedule_work(&gadget->work);
+}
+EXPORT_SYMBOL_GPL(usb_gadget_set_state);
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * usb_gadget_udc_start - tells usb device controller to start up
+ * @gadget: The gadget we want to get started
+ * @driver: The driver we want to bind to @gadget
+ *
+ * This call is issued by the UDC Class driver when it's about
+ * to register a gadget driver to the device controller, before
+ * calling gadget driver's bind() method.
+ *
+ * It allows the controller to be powered off until strictly
+ * necessary to have it powered on.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int usb_gadget_udc_start(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       return gadget->ops->udc_start(gadget, driver);
+}
+
+/**
+ * usb_gadget_udc_stop - tells usb device controller we don't need it anymore
+ * @gadget: The device we want to stop activity
+ * @driver: The driver to unbind from @gadget
+ *
+ * This call is issued by the UDC Class driver after calling
+ * gadget driver's unbind() method.
+ *
+ * The details are implementation specific, but it can go as
+ * far as powering off UDC completely and disable its data
+ * line pullups.
+ */
+static inline void usb_gadget_udc_stop(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       gadget->ops->udc_stop(gadget, driver);
+}
+
+/**
+ * usb_udc_release - release the usb_udc struct
+ * @dev: the dev member within usb_udc
+ *
+ * This is called by driver's core in order to free memory once the last
+ * reference is released.
+ */
+static void usb_udc_release(struct device *dev)
+{
+       struct usb_udc *udc;
+
+       udc = container_of(dev, struct usb_udc, dev);
+       dev_dbg(dev, "releasing '%s'\n", dev_name(dev));
+       kfree(udc);
+}
+
+static const struct attribute_group *usb_udc_attr_groups[];
+
+static void usb_udc_nop_release(struct device *dev)
+{
+       dev_vdbg(dev, "%s\n", __func__);
+}
+
+/**
+ * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
+ * @parent: the parent device to this udc. Usually the controller driver's
+ * device.
+ * @gadget: the gadget to be added to the list.
+ * @release: a gadget release function.
+ *
+ * Returns zero on success, negative errno otherwise.
+ */
+int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+               void (*release)(struct device *dev))
+{
+       struct usb_udc          *udc;
+       int                     ret = -ENOMEM;
+
+       udc = kzalloc(sizeof(*udc), GFP_KERNEL);
+       if (!udc)
+               goto err1;
+
+       dev_set_name(&gadget->dev, "gadget");
+       INIT_WORK(&gadget->work, usb_gadget_state_work);
+       gadget->dev.parent = parent;
+
+#ifdef CONFIG_HAS_DMA
+       dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask);
+       gadget->dev.dma_parms = parent->dma_parms;
+       gadget->dev.dma_mask = parent->dma_mask;
+#endif
+
+       if (release)
+               gadget->dev.release = release;
+       else
+               gadget->dev.release = usb_udc_nop_release;
+
+       ret = device_register(&gadget->dev);
+       if (ret)
+               goto err2;
+
+       device_initialize(&udc->dev);
+       udc->dev.release = usb_udc_release;
+       udc->dev.class = udc_class;
+       udc->dev.groups = usb_udc_attr_groups;
+       udc->dev.parent = parent;
+       ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
+       if (ret)
+               goto err3;
+
+       udc->gadget = gadget;
+
+       mutex_lock(&udc_lock);
+       list_add_tail(&udc->list, &udc_list);
+
+       ret = device_add(&udc->dev);
+       if (ret)
+               goto err4;
+
+       usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
+
+       mutex_unlock(&udc_lock);
+
+       return 0;
+
+err4:
+       list_del(&udc->list);
+       mutex_unlock(&udc_lock);
+
+err3:
+       put_device(&udc->dev);
+
+err2:
+       put_device(&gadget->dev);
+       kfree(udc);
+
+err1:
+       return ret;
+}
+EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);
+
+/**
+ * usb_add_gadget_udc - adds a new gadget to the udc class driver list
+ * @parent: the parent device to this udc. Usually the controller
+ * driver's device.
+ * @gadget: the gadget to be added to the list
+ *
+ * Returns zero on success, negative errno otherwise.
+ */
+int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
+{
+       return usb_add_gadget_udc_release(parent, gadget, NULL);
+}
+EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
+
+static void usb_gadget_remove_driver(struct usb_udc *udc)
+{
+       dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
+                       udc->gadget->name);
+
+       kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
+
+       usb_gadget_disconnect(udc->gadget);
+       udc->driver->disconnect(udc->gadget);
+       udc->driver->unbind(udc->gadget);
+       usb_gadget_udc_stop(udc->gadget, NULL);
+
+       udc->driver = NULL;
+       udc->dev.driver = NULL;
+       udc->gadget->dev.driver = NULL;
+}
+
+/**
+ * usb_del_gadget_udc - deletes @udc from udc_list
+ * @gadget: the gadget to be removed.
+ *
+ * This, will call usb_gadget_unregister_driver() if
+ * the @udc is still busy.
+ */
+void usb_del_gadget_udc(struct usb_gadget *gadget)
+{
+       struct usb_udc          *udc = NULL;
+
+       mutex_lock(&udc_lock);
+       list_for_each_entry(udc, &udc_list, list)
+               if (udc->gadget == gadget)
+                       goto found;
+
+       dev_err(gadget->dev.parent, "gadget not registered.\n");
+       mutex_unlock(&udc_lock);
+
+       return;
+
+found:
+       dev_vdbg(gadget->dev.parent, "unregistering gadget\n");
+
+       list_del(&udc->list);
+       mutex_unlock(&udc_lock);
+
+       if (udc->driver)
+               usb_gadget_remove_driver(udc);
+
+       kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
+       flush_work(&gadget->work);
+       device_unregister(&udc->dev);
+       device_unregister(&gadget->dev);
+}
+EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
+
+/* ------------------------------------------------------------------------- */
+
+static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
+{
+       int ret;
+
+       dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
+                       driver->function);
+
+       udc->driver = driver;
+       udc->dev.driver = &driver->driver;
+       udc->gadget->dev.driver = &driver->driver;
+
+       ret = driver->bind(udc->gadget, driver);
+       if (ret)
+               goto err1;
+       ret = usb_gadget_udc_start(udc->gadget, driver);
+       if (ret) {
+               driver->unbind(udc->gadget);
+               goto err1;
+       }
+       usb_gadget_connect(udc->gadget);
+
+       kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
+       return 0;
+err1:
+       if (ret != -EISNAM)
+               dev_err(&udc->dev, "failed to start %s: %d\n",
+                       udc->driver->function, ret);
+       udc->driver = NULL;
+       udc->dev.driver = NULL;
+       udc->gadget->dev.driver = NULL;
+       return ret;
+}
+
+int udc_attach_driver(const char *name, struct usb_gadget_driver *driver)
+{
+       struct usb_udc *udc = NULL;
+       int ret = -ENODEV;
+
+       mutex_lock(&udc_lock);
+       list_for_each_entry(udc, &udc_list, list) {
+               ret = strcmp(name, dev_name(&udc->dev));
+               if (!ret)
+                       break;
+       }
+       if (ret) {
+               ret = -ENODEV;
+               goto out;
+       }
+       if (udc->driver) {
+               ret = -EBUSY;
+               goto out;
+       }
+       ret = udc_bind_to_driver(udc, driver);
+out:
+       mutex_unlock(&udc_lock);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(udc_attach_driver);
+
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
+{
+       struct usb_udc          *udc = NULL;
+       int                     ret;
+
+       if (!driver || !driver->bind || !driver->setup)
+               return -EINVAL;
+
+       mutex_lock(&udc_lock);
+       list_for_each_entry(udc, &udc_list, list) {
+               /* For now we take the first one */
+               if (!udc->driver)
+                       goto found;
+       }
+
+       pr_debug("couldn't find an available UDC\n");
+       mutex_unlock(&udc_lock);
+       return -ENODEV;
+found:
+       ret = udc_bind_to_driver(udc, driver);
+       mutex_unlock(&udc_lock);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_probe_driver);
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+       struct usb_udc          *udc = NULL;
+       int                     ret = -ENODEV;
+
+       if (!driver || !driver->unbind)
+               return -EINVAL;
+
+       mutex_lock(&udc_lock);
+       list_for_each_entry(udc, &udc_list, list)
+               if (udc->driver == driver) {
+                       usb_gadget_remove_driver(udc);
+                       usb_gadget_set_state(udc->gadget,
+                                       USB_STATE_NOTATTACHED);
+                       ret = 0;
+                       break;
+               }
+
+       mutex_unlock(&udc_lock);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver);
+
+/* ------------------------------------------------------------------------- */
+
+static ssize_t usb_udc_srp_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t n)
+{
+       struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
+
+       if (sysfs_streq(buf, "1"))
+               usb_gadget_wakeup(udc->gadget);
+
+       return n;
+}
+static DEVICE_ATTR(srp, S_IWUSR, NULL, usb_udc_srp_store);
+
+static ssize_t usb_udc_softconn_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t n)
+{
+       struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
+
+       if (sysfs_streq(buf, "connect")) {
+               usb_gadget_udc_start(udc->gadget, udc->driver);
+               usb_gadget_connect(udc->gadget);
+       } else if (sysfs_streq(buf, "disconnect")) {
+               usb_gadget_disconnect(udc->gadget);
+               usb_gadget_udc_stop(udc->gadget, udc->driver);
+       } else {
+               dev_err(dev, "unsupported command '%s'\n", buf);
+               return -EINVAL;
+       }
+
+       return n;
+}
+static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
+
+static ssize_t state_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
+       struct usb_gadget       *gadget = udc->gadget;
+
+       return sprintf(buf, "%s\n", usb_state_string(gadget->state));
+}
+static DEVICE_ATTR_RO(state);
+
+#define USB_UDC_SPEED_ATTR(name, param)                                        \
+ssize_t name##_show(struct device *dev,                                        \
+               struct device_attribute *attr, char *buf)               \
+{                                                                      \
+       struct usb_udc *udc = container_of(dev, struct usb_udc, dev);   \
+       return snprintf(buf, PAGE_SIZE, "%s\n",                         \
+                       usb_speed_string(udc->gadget->param));          \
+}                                                                      \
+static DEVICE_ATTR_RO(name)
+
+static USB_UDC_SPEED_ATTR(current_speed, speed);
+static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
+
+#define USB_UDC_ATTR(name)                                     \
+ssize_t name##_show(struct device *dev,                                \
+               struct device_attribute *attr, char *buf)       \
+{                                                              \
+       struct usb_udc          *udc = container_of(dev, struct usb_udc, dev); \
+       struct usb_gadget       *gadget = udc->gadget;          \
+                                                               \
+       return snprintf(buf, PAGE_SIZE, "%d\n", gadget->name);  \
+}                                                              \
+static DEVICE_ATTR_RO(name)
+
+static USB_UDC_ATTR(is_otg);
+static USB_UDC_ATTR(is_a_peripheral);
+static USB_UDC_ATTR(b_hnp_enable);
+static USB_UDC_ATTR(a_hnp_support);
+static USB_UDC_ATTR(a_alt_hnp_support);
+
+static struct attribute *usb_udc_attrs[] = {
+       &dev_attr_srp.attr,
+       &dev_attr_soft_connect.attr,
+       &dev_attr_state.attr,
+       &dev_attr_current_speed.attr,
+       &dev_attr_maximum_speed.attr,
+
+       &dev_attr_is_otg.attr,
+       &dev_attr_is_a_peripheral.attr,
+       &dev_attr_b_hnp_enable.attr,
+       &dev_attr_a_hnp_support.attr,
+       &dev_attr_a_alt_hnp_support.attr,
+       NULL,
+};
+
+static const struct attribute_group usb_udc_attr_group = {
+       .attrs = usb_udc_attrs,
+};
+
+static const struct attribute_group *usb_udc_attr_groups[] = {
+       &usb_udc_attr_group,
+       NULL,
+};
+
+static int usb_udc_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
+       int                     ret;
+
+       ret = add_uevent_var(env, "USB_UDC_NAME=%s", udc->gadget->name);
+       if (ret) {
+               dev_err(dev, "failed to add uevent USB_UDC_NAME\n");
+               return ret;
+       }
+
+       if (udc->driver) {
+               ret = add_uevent_var(env, "USB_UDC_DRIVER=%s",
+                               udc->driver->function);
+               if (ret) {
+                       dev_err(dev, "failed to add uevent USB_UDC_DRIVER\n");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int __init usb_udc_init(void)
+{
+       udc_class = class_create(THIS_MODULE, "udc");
+       if (IS_ERR(udc_class)) {
+               pr_err("failed to create udc class --> %ld\n",
+                               PTR_ERR(udc_class));
+               return PTR_ERR(udc_class);
+       }
+
+       udc_class->dev_uevent = usb_udc_uevent;
+       return 0;
+}
+subsys_initcall(usb_udc_init);
+
+static void __exit usb_udc_exit(void)
+{
+       class_destroy(udc_class);
+}
+module_exit(usb_udc_exit);
+
+MODULE_DESCRIPTION("UDC Framework");
+MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
+MODULE_LICENSE("GPL v2");