summary refs log tree commit diff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-04 20:11:28 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-04 20:11:28 -0700
commitae9b475ebed96afe51d6bcf10dc7aee9c8d89ed7 (patch)
tree374bf5821a03d717b35f0b91dcbdeaa2428e649d /drivers
parent79eb238c76782a59d51adf8a3dd7f6444245b475 (diff)
parentd310d05f1225d1f6f2bf505255fdf593bfbb3051 (diff)
downloadlinux-ae9b475ebed96afe51d6bcf10dc7aee9c8d89ed7.tar.gz
Merge tag 'usb-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB updates from Greg KH:
 "Here is the big USB driver update for 3.17-rc1.

  Loads of gadget driver changes in here, including some big file
  movements to make things easier to manage over time.  There's also the
  usual xhci and uas driver updates, and a handful of other changes in
  here.  The changelog has the full details.

  All of these have been in linux-next for a while"

* tag 'usb-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (211 commits)
  USB: devio: fix issue with log flooding
  uas: Log a warning when we cannot use uas because the hcd lacks streams
  uas: Only complain about missing sg if all other checks succeed
  xhci: Add missing checks for xhci_alloc_command failure
  xhci: Rename Asrock P67 pci product-id to EJ168
  xhci: Blacklist using streams on the Etron EJ168 controller
  uas: Limit qdepth to 32 when connected over usb-2
  uwb/whci: use correct structure type name in sizeof
  usb-core bInterval quirk
  USB: serial: ftdi_sio: Add support for new Xsens devices
  USB: serial: ftdi_sio: Annotate the current Xsens PID assignments
  usb: chipidea: debug: fix sparse non static symbol warnings
  usb: ci_hdrc_imx doc: fsl,usbphy is required
  usb: ci_hdrc_imx: Return -EINVAL for missing USB PHY
  usb: core: allow zero packet flag for interrupt urbs
  usb: lvstest: Fix sparse warnings generated by kbuild test bot
  USB: core: hcd-pci: free IRQ before disabling PCI device when shutting down
  phy: miphy365x: Represent each PHY channel as a DT subnode
  phy: miphy365x: Provide support for the MiPHY356x Generic PHY
  phy: miphy365x: Add Device Tree bindings for the MiPHY365x
  ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/phy/Kconfig78
-rw-r--r--drivers/phy/Makefile5
-rw-r--r--drivers/phy/phy-bcm-kona-usb2.c2
-rw-r--r--drivers/phy/phy-berlin-sata.c284
-rw-r--r--drivers/phy/phy-core.c56
-rw-r--r--drivers/phy/phy-exynos-dp-video.c7
-rw-r--r--drivers/phy/phy-exynos-mipi-video.c7
-rw-r--r--drivers/phy/phy-exynos4x12-usb2.c125
-rw-r--r--drivers/phy/phy-exynos5-usbdrd.c9
-rw-r--r--drivers/phy/phy-exynos5250-sata.c2
-rw-r--r--drivers/phy/phy-exynos5250-usb2.c2
-rw-r--r--drivers/phy/phy-hix5hd2-sata.c192
-rw-r--r--drivers/phy/phy-miphy365x.c636
-rw-r--r--drivers/phy/phy-mvebu-sata.c2
-rw-r--r--drivers/phy/phy-omap-control.c52
-rw-r--r--drivers/phy/phy-omap-usb2.c2
-rw-r--r--drivers/phy/phy-qcom-apq8064-sata.c289
-rw-r--r--drivers/phy/phy-qcom-ipq806x-sata.c211
-rw-r--r--drivers/phy/phy-samsung-usb2.c9
-rw-r--r--drivers/phy/phy-samsung-usb2.h5
-rw-r--r--drivers/phy/phy-sun4i-usb.c7
-rw-r--r--drivers/phy/phy-ti-pipe3.c107
-rw-r--r--drivers/phy/phy-twl4030-usb.c2
-rw-r--r--drivers/phy/phy-xgene.c2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c3
-rw-r--r--drivers/usb/chipidea/debug.c4
-rw-r--r--drivers/usb/class/usbtmc.c2
-rw-r--r--drivers/usb/core/config.c11
-rw-r--r--drivers/usb/core/devio.c2
-rw-r--r--drivers/usb/core/driver.c7
-rw-r--r--drivers/usb/core/hcd-pci.c2
-rw-r--r--drivers/usb/core/hcd.c4
-rw-r--r--drivers/usb/core/hub.c94
-rw-r--r--drivers/usb/core/hub.h2
-rw-r--r--drivers/usb/core/port.c21
-rw-r--r--drivers/usb/core/quirks.c7
-rw-r--r--drivers/usb/core/urb.c1
-rw-r--r--drivers/usb/core/usb.c1
-rw-r--r--drivers/usb/dwc2/gadget.c12
-rw-r--r--drivers/usb/dwc3/Kconfig7
-rw-r--r--drivers/usb/dwc3/core.c51
-rw-r--r--drivers/usb/dwc3/core.h13
-rw-r--r--drivers/usb/dwc3/dwc3-omap.c172
-rw-r--r--drivers/usb/dwc3/gadget.c7
-rw-r--r--drivers/usb/dwc3/host.c14
-rw-r--r--drivers/usb/gadget/Kconfig824
-rw-r--r--drivers/usb/gadget/Makefile101
-rw-r--r--drivers/usb/gadget/composite.c1
-rw-r--r--drivers/usb/gadget/configfs.c4
-rw-r--r--drivers/usb/gadget/function/Makefile34
-rw-r--r--drivers/usb/gadget/function/f_acm.c (renamed from drivers/usb/gadget/f_acm.c)0
-rw-r--r--drivers/usb/gadget/function/f_ecm.c (renamed from drivers/usb/gadget/f_ecm.c)0
-rw-r--r--drivers/usb/gadget/function/f_eem.c (renamed from drivers/usb/gadget/f_eem.c)22
-rw-r--r--drivers/usb/gadget/function/f_fs.c (renamed from drivers/usb/gadget/f_fs.c)352
-rw-r--r--drivers/usb/gadget/function/f_hid.c (renamed from drivers/usb/gadget/f_hid.c)0
-rw-r--r--drivers/usb/gadget/function/f_loopback.c (renamed from drivers/usb/gadget/f_loopback.c)0
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c (renamed from drivers/usb/gadget/f_mass_storage.c)0
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.h (renamed from drivers/usb/gadget/f_mass_storage.h)0
-rw-r--r--drivers/usb/gadget/function/f_midi.c (renamed from drivers/usb/gadget/f_midi.c)0
-rw-r--r--drivers/usb/gadget/function/f_ncm.c (renamed from drivers/usb/gadget/f_ncm.c)480
-rw-r--r--drivers/usb/gadget/function/f_obex.c (renamed from drivers/usb/gadget/f_obex.c)0
-rw-r--r--drivers/usb/gadget/function/f_phonet.c (renamed from drivers/usb/gadget/f_phonet.c)0
-rw-r--r--drivers/usb/gadget/function/f_rndis.c (renamed from drivers/usb/gadget/f_rndis.c)4
-rw-r--r--drivers/usb/gadget/function/f_serial.c (renamed from drivers/usb/gadget/f_serial.c)0
-rw-r--r--drivers/usb/gadget/function/f_sourcesink.c (renamed from drivers/usb/gadget/f_sourcesink.c)0
-rw-r--r--drivers/usb/gadget/function/f_subset.c (renamed from drivers/usb/gadget/f_subset.c)0
-rw-r--r--drivers/usb/gadget/function/f_uac1.c (renamed from drivers/usb/gadget/f_uac1.c)0
-rw-r--r--drivers/usb/gadget/function/f_uac2.c (renamed from drivers/usb/gadget/f_uac2.c)24
-rw-r--r--drivers/usb/gadget/function/f_uvc.c (renamed from drivers/usb/gadget/f_uvc.c)0
-rw-r--r--drivers/usb/gadget/function/f_uvc.h (renamed from drivers/usb/gadget/f_uvc.h)0
-rw-r--r--drivers/usb/gadget/function/g_zero.h (renamed from drivers/usb/gadget/g_zero.h)0
-rw-r--r--drivers/usb/gadget/function/ndis.h (renamed from drivers/usb/gadget/ndis.h)0
-rw-r--r--drivers/usb/gadget/function/rndis.c (renamed from drivers/usb/gadget/rndis.c)0
-rw-r--r--drivers/usb/gadget/function/rndis.h (renamed from drivers/usb/gadget/rndis.h)0
-rw-r--r--drivers/usb/gadget/function/storage_common.c (renamed from drivers/usb/gadget/storage_common.c)0
-rw-r--r--drivers/usb/gadget/function/storage_common.h (renamed from drivers/usb/gadget/storage_common.h)0
-rw-r--r--drivers/usb/gadget/function/u_ecm.h (renamed from drivers/usb/gadget/u_ecm.h)0
-rw-r--r--drivers/usb/gadget/function/u_eem.h (renamed from drivers/usb/gadget/u_eem.h)0
-rw-r--r--drivers/usb/gadget/function/u_ether.c (renamed from drivers/usb/gadget/u_ether.c)19
-rw-r--r--drivers/usb/gadget/function/u_ether.h (renamed from drivers/usb/gadget/u_ether.h)2
-rw-r--r--drivers/usb/gadget/function/u_ether_configfs.h (renamed from drivers/usb/gadget/u_ether_configfs.h)0
-rw-r--r--drivers/usb/gadget/function/u_fs.h (renamed from drivers/usb/gadget/u_fs.h)7
-rw-r--r--drivers/usb/gadget/function/u_gether.h (renamed from drivers/usb/gadget/u_gether.h)0
-rw-r--r--drivers/usb/gadget/function/u_ncm.h (renamed from drivers/usb/gadget/u_ncm.h)0
-rw-r--r--drivers/usb/gadget/function/u_phonet.h (renamed from drivers/usb/gadget/u_phonet.h)0
-rw-r--r--drivers/usb/gadget/function/u_rndis.h (renamed from drivers/usb/gadget/u_rndis.h)0
-rw-r--r--drivers/usb/gadget/function/u_serial.c (renamed from drivers/usb/gadget/u_serial.c)0
-rw-r--r--drivers/usb/gadget/function/u_serial.h (renamed from drivers/usb/gadget/u_serial.h)0
-rw-r--r--drivers/usb/gadget/function/u_uac1.c (renamed from drivers/usb/gadget/u_uac1.c)0
-rw-r--r--drivers/usb/gadget/function/u_uac1.h (renamed from drivers/usb/gadget/u_uac1.h)0
-rw-r--r--drivers/usb/gadget/function/uvc.h (renamed from drivers/usb/gadget/uvc.h)0
-rw-r--r--drivers/usb/gadget/function/uvc_queue.c (renamed from drivers/usb/gadget/uvc_queue.c)0
-rw-r--r--drivers/usb/gadget/function/uvc_queue.h (renamed from drivers/usb/gadget/uvc_queue.h)0
-rw-r--r--drivers/usb/gadget/function/uvc_v4l2.c (renamed from drivers/usb/gadget/uvc_v4l2.c)0
-rw-r--r--drivers/usb/gadget/function/uvc_video.c (renamed from drivers/usb/gadget/uvc_video.c)0
-rw-r--r--drivers/usb/gadget/legacy/Kconfig475
-rw-r--r--drivers/usb/gadget/legacy/Makefile44
-rw-r--r--drivers/usb/gadget/legacy/acm_ms.c (renamed from drivers/usb/gadget/acm_ms.c)14
-rw-r--r--drivers/usb/gadget/legacy/audio.c (renamed from drivers/usb/gadget/audio.c)12
-rw-r--r--drivers/usb/gadget/legacy/cdc2.c (renamed from drivers/usb/gadget/cdc2.c)14
-rw-r--r--drivers/usb/gadget/legacy/dbgp.c (renamed from drivers/usb/gadget/dbgp.c)0
-rw-r--r--drivers/usb/gadget/legacy/ether.c (renamed from drivers/usb/gadget/ether.c)14
-rw-r--r--drivers/usb/gadget/legacy/g_ffs.c (renamed from drivers/usb/gadget/g_ffs.c)2
-rw-r--r--drivers/usb/gadget/legacy/gmidi.c (renamed from drivers/usb/gadget/gmidi.c)13
-rw-r--r--drivers/usb/gadget/legacy/hid.c (renamed from drivers/usb/gadget/hid.c)0
-rw-r--r--drivers/usb/gadget/legacy/inode.c (renamed from drivers/usb/gadget/inode.c)0
-rw-r--r--drivers/usb/gadget/legacy/mass_storage.c (renamed from drivers/usb/gadget/mass_storage.c)0
-rw-r--r--drivers/usb/gadget/legacy/multi.c (renamed from drivers/usb/gadget/multi.c)13
-rw-r--r--drivers/usb/gadget/legacy/ncm.c (renamed from drivers/usb/gadget/ncm.c)14
-rw-r--r--drivers/usb/gadget/legacy/nokia.c (renamed from drivers/usb/gadget/nokia.c)12
-rw-r--r--drivers/usb/gadget/legacy/printer.c (renamed from drivers/usb/gadget/printer.c)0
-rw-r--r--drivers/usb/gadget/legacy/serial.c (renamed from drivers/usb/gadget/serial.c)0
-rw-r--r--drivers/usb/gadget/legacy/tcm_usb_gadget.c (renamed from drivers/usb/gadget/tcm_usb_gadget.c)0
-rw-r--r--drivers/usb/gadget/legacy/tcm_usb_gadget.h (renamed from drivers/usb/gadget/tcm_usb_gadget.h)0
-rw-r--r--drivers/usb/gadget/legacy/webcam.c (renamed from drivers/usb/gadget/webcam.c)15
-rw-r--r--drivers/usb/gadget/legacy/zero.c (renamed from drivers/usb/gadget/zero.c)14
-rw-r--r--drivers/usb/gadget/net2280.c2905
-rw-r--r--drivers/usb/gadget/net2280.h308
-rw-r--r--drivers/usb/gadget/u_os_desc.h59
-rw-r--r--drivers/usb/gadget/udc/Kconfig385
-rw-r--r--drivers/usb/gadget/udc/Makefile31
-rw-r--r--drivers/usb/gadget/udc/amd5536udc.c (renamed from drivers/usb/gadget/amd5536udc.c)0
-rw-r--r--drivers/usb/gadget/udc/amd5536udc.h (renamed from drivers/usb/gadget/amd5536udc.h)0
-rw-r--r--drivers/usb/gadget/udc/at91_udc.c (renamed from drivers/usb/gadget/at91_udc.c)0
-rw-r--r--drivers/usb/gadget/udc/at91_udc.h (renamed from drivers/usb/gadget/at91_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/atmel_usba_udc.c (renamed from drivers/usb/gadget/atmel_usba_udc.c)2
-rw-r--r--drivers/usb/gadget/udc/atmel_usba_udc.h (renamed from drivers/usb/gadget/atmel_usba_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/bcm63xx_udc.c (renamed from drivers/usb/gadget/bcm63xx_udc.c)0
-rw-r--r--drivers/usb/gadget/udc/dummy_hcd.c (renamed from drivers/usb/gadget/dummy_hcd.c)0
-rw-r--r--drivers/usb/gadget/udc/fotg210-udc.c (renamed from drivers/usb/gadget/fotg210-udc.c)0
-rw-r--r--drivers/usb/gadget/udc/fotg210.h (renamed from drivers/usb/gadget/fotg210.h)0
-rw-r--r--drivers/usb/gadget/udc/fsl_mxc_udc.c (renamed from drivers/usb/gadget/fsl_mxc_udc.c)2
-rw-r--r--drivers/usb/gadget/udc/fsl_qe_udc.c (renamed from drivers/usb/gadget/fsl_qe_udc.c)19
-rw-r--r--drivers/usb/gadget/udc/fsl_qe_udc.h (renamed from drivers/usb/gadget/fsl_qe_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/fsl_udc_core.c (renamed from drivers/usb/gadget/fsl_udc_core.c)19
-rw-r--r--drivers/usb/gadget/udc/fsl_usb2_udc.h (renamed from drivers/usb/gadget/fsl_usb2_udc.h)3
-rw-r--r--drivers/usb/gadget/udc/fusb300_udc.c (renamed from drivers/usb/gadget/fusb300_udc.c)4
-rw-r--r--drivers/usb/gadget/udc/fusb300_udc.h (renamed from drivers/usb/gadget/fusb300_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/gadget_chips.h (renamed from drivers/usb/gadget/gadget_chips.h)0
-rw-r--r--drivers/usb/gadget/udc/goku_udc.c (renamed from drivers/usb/gadget/goku_udc.c)0
-rw-r--r--drivers/usb/gadget/udc/goku_udc.h (renamed from drivers/usb/gadget/goku_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/gr_udc.c (renamed from drivers/usb/gadget/gr_udc.c)2
-rw-r--r--drivers/usb/gadget/udc/gr_udc.h (renamed from drivers/usb/gadget/gr_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/lpc32xx_udc.c (renamed from drivers/usb/gadget/lpc32xx_udc.c)7
-rw-r--r--drivers/usb/gadget/udc/m66592-udc.c (renamed from drivers/usb/gadget/m66592-udc.c)4
-rw-r--r--drivers/usb/gadget/udc/m66592-udc.h (renamed from drivers/usb/gadget/m66592-udc.h)0
-rw-r--r--drivers/usb/gadget/udc/mv_u3d.h (renamed from drivers/usb/gadget/mv_u3d.h)0
-rw-r--r--drivers/usb/gadget/udc/mv_u3d_core.c (renamed from drivers/usb/gadget/mv_u3d_core.c)0
-rw-r--r--drivers/usb/gadget/udc/mv_udc.h (renamed from drivers/usb/gadget/mv_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/mv_udc_core.c (renamed from drivers/usb/gadget/mv_udc_core.c)4
-rw-r--r--drivers/usb/gadget/udc/net2272.c (renamed from drivers/usb/gadget/net2272.c)2
-rw-r--r--drivers/usb/gadget/udc/net2272.h (renamed from drivers/usb/gadget/net2272.h)0
-rw-r--r--drivers/usb/gadget/udc/net2280.c3827
-rw-r--r--drivers/usb/gadget/udc/net2280.h403
-rw-r--r--drivers/usb/gadget/udc/omap_udc.c (renamed from drivers/usb/gadget/omap_udc.c)5
-rw-r--r--drivers/usb/gadget/udc/omap_udc.h (renamed from drivers/usb/gadget/omap_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/pch_udc.c (renamed from drivers/usb/gadget/pch_udc.c)0
-rw-r--r--drivers/usb/gadget/udc/pxa25x_udc.c (renamed from drivers/usb/gadget/pxa25x_udc.c)75
-rw-r--r--drivers/usb/gadget/udc/pxa25x_udc.h (renamed from drivers/usb/gadget/pxa25x_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/pxa27x_udc.c (renamed from drivers/usb/gadget/pxa27x_udc.c)6
-rw-r--r--drivers/usb/gadget/udc/pxa27x_udc.h (renamed from drivers/usb/gadget/pxa27x_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/r8a66597-udc.c (renamed from drivers/usb/gadget/r8a66597-udc.c)92
-rw-r--r--drivers/usb/gadget/udc/r8a66597-udc.h (renamed from drivers/usb/gadget/r8a66597-udc.h)0
-rw-r--r--drivers/usb/gadget/udc/s3c-hsudc.c (renamed from drivers/usb/gadget/s3c-hsudc.c)0
-rw-r--r--drivers/usb/gadget/udc/s3c2410_udc.c (renamed from drivers/usb/gadget/s3c2410_udc.c)8
-rw-r--r--drivers/usb/gadget/udc/s3c2410_udc.h (renamed from drivers/usb/gadget/s3c2410_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/udc-core.c (renamed from drivers/usb/gadget/udc-core.c)0
-rw-r--r--drivers/usb/host/Kconfig8
-rw-r--r--drivers/usb/host/Makefile3
-rw-r--r--drivers/usb/host/ehci-exynos.c2
-rw-r--r--drivers/usb/host/ehci-mem.c2
-rw-r--r--drivers/usb/host/ehci-msm.c2
-rw-r--r--drivers/usb/host/ehci-pci.c25
-rw-r--r--drivers/usb/host/ehci-spear.c2
-rw-r--r--drivers/usb/host/ehci-tegra.c67
-rw-r--r--drivers/usb/host/fhci-dbg.c8
-rw-r--r--drivers/usb/host/fotg210-hcd.c48
-rw-r--r--drivers/usb/host/max3421-hcd.c48
-rw-r--r--drivers/usb/host/ohci-dbg.c9
-rw-r--r--drivers/usb/host/ohci-exynos.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c381
-rw-r--r--drivers/usb/host/ohci-hub.c11
-rw-r--r--drivers/usb/host/ohci-mem.c1
-rw-r--r--drivers/usb/host/ohci-q.c262
-rw-r--r--drivers/usb/host/ohci-spear.c2
-rw-r--r--drivers/usb/host/ohci.h23
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c48
-rw-r--r--drivers/usb/host/uhci-grlib.c31
-rw-r--r--drivers/usb/host/uhci-hcd.c2
-rw-r--r--drivers/usb/host/uhci-platform.c22
-rw-r--r--drivers/usb/host/xhci-pci.c8
-rw-r--r--drivers/usb/host/xhci-plat.c52
-rw-r--r--drivers/usb/host/xhci-rcar.c148
-rw-r--r--drivers/usb/host/xhci-rcar.h27
-rw-r--r--drivers/usb/host/xhci-ring.c4
-rw-r--r--drivers/usb/host/xhci.c160
-rw-r--r--drivers/usb/host/xhci.h2
-rw-r--r--drivers/usb/misc/Kconfig7
-rw-r--r--drivers/usb/misc/Makefile1
-rw-r--r--drivers/usb/misc/lvstest.c460
-rw-r--r--drivers/usb/misc/usb3503.c37
-rw-r--r--drivers/usb/musb/blackfin.c20
-rw-r--r--drivers/usb/musb/davinci.c20
-rw-r--r--drivers/usb/musb/jz4740.c3
-rw-r--r--drivers/usb/musb/musb_core.c41
-rw-r--r--drivers/usb/musb/musb_core.h12
-rw-r--r--drivers/usb/musb/musb_cppi41.c70
-rw-r--r--drivers/usb/musb/musb_dma.h1
-rw-r--r--drivers/usb/musb/musb_dsps.c104
-rw-r--r--drivers/usb/musb/musb_host.c19
-rw-r--r--drivers/usb/musb/musb_regs.h7
-rw-r--r--drivers/usb/musb/tusb6010.c16
-rw-r--r--drivers/usb/musb/ux500.c28
-rw-r--r--drivers/usb/phy/phy-am335x.c12
-rw-r--r--drivers/usb/phy/phy-gpio-vbus-usb.c45
-rw-r--r--drivers/usb/phy/phy-msm-usb.c12
-rw-r--r--drivers/usb/phy/phy-tegra-usb.c11
-rw-r--r--drivers/usb/renesas_usbhs/Makefile2
-rw-r--r--drivers/usb/renesas_usbhs/common.c66
-rw-r--r--drivers/usb/renesas_usbhs/common.h2
-rw-r--r--drivers/usb/renesas_usbhs/mod_gadget.c2
-rw-r--r--drivers/usb/renesas_usbhs/pipe.c11
-rw-r--r--drivers/usb/renesas_usbhs/pipe.h1
-rw-r--r--drivers/usb/renesas_usbhs/rcar2.c77
-rw-r--r--drivers/usb/renesas_usbhs/rcar2.h4
-rw-r--r--drivers/usb/serial/cp210x.c3
-rw-r--r--drivers/usb/serial/ftdi_sio.c84
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h13
-rw-r--r--drivers/usb/serial/kl5kusb105.c30
-rw-r--r--drivers/usb/serial/mos7840.c5
-rw-r--r--drivers/usb/storage/uas-detect.h40
-rw-r--r--drivers/usb/storage/uas.c2
-rw-r--r--drivers/uwb/whci.c2
233 files changed, 10155 insertions, 5757 deletions
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 64b98d242ea6..cc97c897945a 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -15,6 +15,13 @@ config GENERIC_PHY
 	  phy users can obtain reference to the PHY. All the users of this
 	  framework should select this config.
 
+config PHY_BERLIN_SATA
+	tristate "Marvell Berlin SATA PHY driver"
+	depends on ARCH_BERLIN && HAS_IOMEM && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support the SATA PHY on Marvell Berlin SoCs.
+
 config PHY_EXYNOS_MIPI_VIDEO
 	tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
 	depends on HAS_IOMEM
@@ -27,10 +34,20 @@ config PHY_EXYNOS_MIPI_VIDEO
 
 config PHY_MVEBU_SATA
 	def_bool y
-	depends on ARCH_KIRKWOOD || ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
+	depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
 	depends on OF
 	select GENERIC_PHY
 
+config PHY_MIPHY365X
+	tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series"
+	depends on ARCH_STI
+	depends on GENERIC_PHY
+	depends on HAS_IOMEM
+	depends on OF
+	help
+	  Enable this to support the miphy transceiver (for SATA/PCIE)
+	  that is part of STMicroelectronics STiH41x SoC series.
+
 config OMAP_CONTROL_PHY
 	tristate "OMAP CONTROL PHY Driver"
 	depends on ARCH_OMAP2PLUS || COMPILE_TEST
@@ -109,6 +126,14 @@ config PHY_EXYNOS5250_SATA
 	  SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host
 	  port to accept one SATA device.
 
+config PHY_HIX5HD2_SATA
+	tristate "HIX5HD2 SATA PHY Driver"
+	depends on ARCH_HIX5HD2 && OF && HAS_IOMEM
+	select GENERIC_PHY
+	select MFD_SYSCON
+	help
+	  Support for SATA PHY on Hisilicon hix5hd2 Soc.
+
 config PHY_SUN4I_USB
 	tristate "Allwinner sunxi SoC USB PHY driver"
 	depends on ARCH_SUNXI && HAS_IOMEM && OF
@@ -124,50 +149,39 @@ config PHY_SUN4I_USB
 config PHY_SAMSUNG_USB2
 	tristate "Samsung USB 2.0 PHY driver"
 	depends on HAS_IOMEM
+	depends on USB_EHCI_EXYNOS || USB_OHCI_EXYNOS || USB_DWC2
 	select GENERIC_PHY
 	select MFD_SYSCON
+	default ARCH_EXYNOS
 	help
 	  Enable this to support the Samsung USB 2.0 PHY driver for Samsung
-	  SoCs. This driver provides the interface for USB 2.0 PHY. Support for
-	  particular SoCs has to be enabled in addition to this driver. Number
-	  and type of supported phys depends on the SoC.
+	  SoCs. This driver provides the interface for USB 2.0 PHY. Support
+	  for particular PHYs will be enabled based on the SoC type in addition
+	  to this driver.
 
 config PHY_EXYNOS4210_USB2
-	bool "Support for Exynos 4210"
+	bool
 	depends on PHY_SAMSUNG_USB2
-	depends on CPU_EXYNOS4210
-	help
-	  Enable USB PHY support for Exynos 4210. This option requires that
-	  Samsung USB 2.0 PHY driver is enabled and means that support for this
-	  particular SoC is compiled in the driver. In case of Exynos 4210 four
-	  phys are available - device, host, HSIC0 and HSIC1.
+	default CPU_EXYNOS4210
 
 config PHY_EXYNOS4X12_USB2
-	bool "Support for Exynos 4x12"
+	bool
 	depends on PHY_SAMSUNG_USB2
-	depends on (SOC_EXYNOS4212 || SOC_EXYNOS4412)
-	help
-	  Enable USB PHY support for Exynos 4x12. This option requires that
-	  Samsung USB 2.0 PHY driver is enabled and means that support for this
-	  particular SoC is compiled in the driver. In case of Exynos 4x12 four
-	  phys are available - device, host, HSIC0 and HSIC1.
+	default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412
 
 config PHY_EXYNOS5250_USB2
-	bool "Support for Exynos 5250"
+	bool
 	depends on PHY_SAMSUNG_USB2
-	depends on SOC_EXYNOS5250
-	help
-	  Enable USB PHY support for Exynos 5250. This option requires that
-	  Samsung USB 2.0 PHY driver is enabled and means that support for this
-	  particular SoC is compiled in the driver. In case of Exynos 5250 four
-	  phys are available - device, host, HSIC0 and HSIC.
+	default SOC_EXYNOS5250 || SOC_EXYNOS5420
 
 config PHY_EXYNOS5_USBDRD
 	tristate "Exynos5 SoC series USB DRD PHY driver"
 	depends on ARCH_EXYNOS5 && OF
 	depends on HAS_IOMEM
+	depends on USB_DWC3_EXYNOS
 	select GENERIC_PHY
 	select MFD_SYSCON
+	default y
 	help
 	  Enable USB DRD PHY support for Exynos 5 SoC series.
 	  This driver provides PHY interface for USB 3.0 DRD controller
@@ -180,4 +194,18 @@ config PHY_XGENE
 	help
 	  This option enables support for APM X-Gene SoC multi-purpose PHY.
 
+config PHY_QCOM_APQ8064_SATA
+	tristate "Qualcomm APQ8064 SATA SerDes/PHY driver"
+	depends on ARCH_QCOM
+	depends on HAS_IOMEM
+	depends on OF
+	select GENERIC_PHY
+
+config PHY_QCOM_IPQ806X_SATA
+	tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
+	depends on ARCH_QCOM
+	depends on HAS_IOMEM
+	depends on OF
+	select GENERIC_PHY
+
 endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index b4f1d5770601..971ad0aac388 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -3,15 +3,18 @@
 #
 
 obj-$(CONFIG_GENERIC_PHY)		+= phy-core.o
+obj-$(CONFIG_PHY_BERLIN_SATA)		+= phy-berlin-sata.o
 obj-$(CONFIG_BCM_KONA_USB2_PHY)		+= phy-bcm-kona-usb2.o
 obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)	+= phy-exynos-dp-video.o
 obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)	+= phy-exynos-mipi-video.o
 obj-$(CONFIG_PHY_MVEBU_SATA)		+= phy-mvebu-sata.o
+obj-$(CONFIG_PHY_MIPHY365X)		+= phy-miphy365x.o
 obj-$(CONFIG_OMAP_CONTROL_PHY)		+= phy-omap-control.o
 obj-$(CONFIG_OMAP_USB2)			+= phy-omap-usb2.o
 obj-$(CONFIG_TI_PIPE3)			+= phy-ti-pipe3.o
 obj-$(CONFIG_TWL4030_USB)		+= phy-twl4030-usb.o
 obj-$(CONFIG_PHY_EXYNOS5250_SATA)	+= phy-exynos5250-sata.o
+obj-$(CONFIG_PHY_HIX5HD2_SATA)		+= phy-hix5hd2-sata.o
 obj-$(CONFIG_PHY_SUN4I_USB)		+= phy-sun4i-usb.o
 obj-$(CONFIG_PHY_SAMSUNG_USB2)		+= phy-exynos-usb2.o
 phy-exynos-usb2-y			+= phy-samsung-usb2.o
@@ -20,3 +23,5 @@ phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2)	+= phy-exynos4x12-usb2.o
 phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2)	+= phy-exynos5250-usb2.o
 obj-$(CONFIG_PHY_EXYNOS5_USBDRD)	+= phy-exynos5-usbdrd.o
 obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
+obj-$(CONFIG_PHY_QCOM_APQ8064_SATA)	+= phy-qcom-apq8064-sata.o
+obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)	+= phy-qcom-ipq806x-sata.o
diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/phy-bcm-kona-usb2.c
index e94f5a6a5645..894fe74c1e44 100644
--- a/drivers/phy/phy-bcm-kona-usb2.c
+++ b/drivers/phy/phy-bcm-kona-usb2.c
@@ -117,7 +117,7 @@ static int bcm_kona_usb2_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, phy);
 
-	gphy = devm_phy_create(dev, &ops, NULL);
+	gphy = devm_phy_create(dev, NULL, &ops, NULL);
 	if (IS_ERR(gphy))
 		return PTR_ERR(gphy);
 
diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c
new file mode 100644
index 000000000000..5c3a0424aeb4
--- /dev/null
+++ b/drivers/phy/phy-berlin-sata.c
@@ -0,0 +1,284 @@
+/*
+ * Marvell Berlin SATA PHY driver
+ *
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine Ténart <antoine.tenart@free-electrons.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.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#define HOST_VSA_ADDR		0x0
+#define HOST_VSA_DATA		0x4
+#define PORT_SCR_CTL		0x2c
+#define PORT_VSR_ADDR		0x78
+#define PORT_VSR_DATA		0x7c
+
+#define CONTROL_REGISTER	0x0
+#define MBUS_SIZE_CONTROL	0x4
+
+#define POWER_DOWN_PHY0			BIT(6)
+#define POWER_DOWN_PHY1			BIT(14)
+#define MBUS_WRITE_REQUEST_SIZE_128	(BIT(2) << 16)
+#define MBUS_READ_REQUEST_SIZE_128	(BIT(2) << 19)
+
+#define PHY_BASE		0x200
+
+/* register 0x01 */
+#define REF_FREF_SEL_25		BIT(0)
+#define PHY_MODE_SATA		(0x0 << 5)
+
+/* register 0x02 */
+#define USE_MAX_PLL_RATE	BIT(12)
+
+/* register 0x23 */
+#define DATA_BIT_WIDTH_10	(0x0 << 10)
+#define DATA_BIT_WIDTH_20	(0x1 << 10)
+#define DATA_BIT_WIDTH_40	(0x2 << 10)
+
+/* register 0x25 */
+#define PHY_GEN_MAX_1_5		(0x0 << 10)
+#define PHY_GEN_MAX_3_0		(0x1 << 10)
+#define PHY_GEN_MAX_6_0		(0x2 << 10)
+
+struct phy_berlin_desc {
+	struct phy	*phy;
+	u32		power_bit;
+	unsigned	index;
+};
+
+struct phy_berlin_priv {
+	void __iomem		*base;
+	spinlock_t		lock;
+	struct clk		*clk;
+	struct phy_berlin_desc	**phys;
+	unsigned		nphys;
+};
+
+static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg, u32 reg,
+					       u32 mask, u32 val)
+{
+	u32 regval;
+
+	/* select register */
+	writel(PHY_BASE + reg, ctrl_reg + PORT_VSR_ADDR);
+
+	/* set bits */
+	regval = readl(ctrl_reg + PORT_VSR_DATA);
+	regval &= ~mask;
+	regval |= val;
+	writel(regval, ctrl_reg + PORT_VSR_DATA);
+}
+
+static int phy_berlin_sata_power_on(struct phy *phy)
+{
+	struct phy_berlin_desc *desc = phy_get_drvdata(phy);
+	struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
+	void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80);
+	int ret = 0;
+	u32 regval;
+
+	clk_prepare_enable(priv->clk);
+
+	spin_lock(&priv->lock);
+
+	/* Power on PHY */
+	writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
+	regval = readl(priv->base + HOST_VSA_DATA);
+	regval &= ~desc->power_bit;
+	writel(regval, priv->base + HOST_VSA_DATA);
+
+	/* Configure MBus */
+	writel(MBUS_SIZE_CONTROL, priv->base + HOST_VSA_ADDR);
+	regval = readl(priv->base + HOST_VSA_DATA);
+	regval |= MBUS_WRITE_REQUEST_SIZE_128 | MBUS_READ_REQUEST_SIZE_128;
+	writel(regval, priv->base + HOST_VSA_DATA);
+
+	/* set PHY mode and ref freq to 25 MHz */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x1, 0xff,
+				    REF_FREF_SEL_25 | PHY_MODE_SATA);
+
+	/* set PHY up to 6 Gbps */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x25, 0xc00, PHY_GEN_MAX_6_0);
+
+	/* set 40 bits width */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x23,  0xc00, DATA_BIT_WIDTH_40);
+
+	/* use max pll rate */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x2, 0x0, USE_MAX_PLL_RATE);
+
+	/* set Gen3 controller speed */
+	regval = readl(ctrl_reg + PORT_SCR_CTL);
+	regval &= ~GENMASK(7, 4);
+	regval |= 0x30;
+	writel(regval, ctrl_reg + PORT_SCR_CTL);
+
+	spin_unlock(&priv->lock);
+
+	clk_disable_unprepare(priv->clk);
+
+	return ret;
+}
+
+static int phy_berlin_sata_power_off(struct phy *phy)
+{
+	struct phy_berlin_desc *desc = phy_get_drvdata(phy);
+	struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
+	u32 regval;
+
+	clk_prepare_enable(priv->clk);
+
+	spin_lock(&priv->lock);
+
+	/* Power down PHY */
+	writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
+	regval = readl(priv->base + HOST_VSA_DATA);
+	regval |= desc->power_bit;
+	writel(regval, priv->base + HOST_VSA_DATA);
+
+	spin_unlock(&priv->lock);
+
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+static struct phy *phy_berlin_sata_phy_xlate(struct device *dev,
+					     struct of_phandle_args *args)
+{
+	struct phy_berlin_priv *priv = dev_get_drvdata(dev);
+	int i;
+
+	if (WARN_ON(args->args[0] >= priv->nphys))
+		return ERR_PTR(-ENODEV);
+
+	for (i = 0; i < priv->nphys; i++) {
+		if (priv->phys[i]->index == args->args[0])
+			break;
+	}
+
+	if (i == priv->nphys)
+		return ERR_PTR(-ENODEV);
+
+	return priv->phys[i]->phy;
+}
+
+static struct phy_ops phy_berlin_sata_ops = {
+	.power_on	= phy_berlin_sata_power_on,
+	.power_off	= phy_berlin_sata_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static u32 phy_berlin_power_down_bits[] = {
+	POWER_DOWN_PHY0,
+	POWER_DOWN_PHY1,
+};
+
+static int phy_berlin_sata_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *child;
+	struct phy *phy;
+	struct phy_provider *phy_provider;
+	struct phy_berlin_priv *priv;
+	struct resource *res;
+	int i = 0;
+	u32 phy_id;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	priv->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!priv->base)
+		return -ENOMEM;
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk))
+		return PTR_ERR(priv->clk);
+
+	priv->nphys = of_get_child_count(dev->of_node);
+	if (priv->nphys == 0)
+		return -ENODEV;
+
+	priv->phys = devm_kzalloc(dev, priv->nphys * sizeof(*priv->phys),
+				  GFP_KERNEL);
+	if (!priv->phys)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, priv);
+	spin_lock_init(&priv->lock);
+
+	for_each_available_child_of_node(dev->of_node, child) {
+		struct phy_berlin_desc *phy_desc;
+
+		if (of_property_read_u32(child, "reg", &phy_id)) {
+			dev_err(dev, "missing reg property in node %s\n",
+				child->name);
+			return -EINVAL;
+		}
+
+		if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) {
+			dev_err(dev, "invalid reg in node %s\n", child->name);
+			return -EINVAL;
+		}
+
+		phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL);
+		if (!phy_desc)
+			return -ENOMEM;
+
+		phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops, NULL);
+		if (IS_ERR(phy)) {
+			dev_err(dev, "failed to create PHY %d\n", phy_id);
+			return PTR_ERR(phy);
+		}
+
+		phy_desc->phy = phy;
+		phy_desc->power_bit = phy_berlin_power_down_bits[phy_id];
+		phy_desc->index = phy_id;
+		phy_set_drvdata(phy, phy_desc);
+
+		priv->phys[i++] = phy_desc;
+
+		/* Make sure the PHY is off */
+		phy_berlin_sata_power_off(phy);
+	}
+
+	phy_provider =
+		devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
+	return 0;
+}
+
+static const struct of_device_id phy_berlin_sata_of_match[] = {
+	{ .compatible = "marvell,berlin2q-sata-phy" },
+	{ },
+};
+
+static struct platform_driver phy_berlin_sata_driver = {
+	.probe	= phy_berlin_sata_probe,
+	.driver	= {
+		.name		= "phy-berlin-sata",
+		.owner		= THIS_MODULE,
+		.of_match_table	= phy_berlin_sata_of_match,
+	},
+};
+module_platform_driver(phy_berlin_sata_driver);
+
+MODULE_DESCRIPTION("Marvell Berlin SATA PHY driver");
+MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 49c446530101..ff5eec5af817 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -21,6 +21,7 @@
 #include <linux/phy/phy.h>
 #include <linux/idr.h>
 #include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
 
 static struct class *phy_class;
 static DEFINE_MUTEX(phy_provider_mutex);
@@ -86,10 +87,15 @@ static struct phy *phy_lookup(struct device *device, const char *port)
 static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
 {
 	struct phy_provider *phy_provider;
+	struct device_node *child;
 
 	list_for_each_entry(phy_provider, &phy_provider_list, list) {
 		if (phy_provider->dev->of_node == node)
 			return phy_provider;
+
+		for_each_child_of_node(phy_provider->dev->of_node, child)
+			if (child == node)
+				return phy_provider;
 	}
 
 	return ERR_PTR(-EPROBE_DEFER);
@@ -226,6 +232,12 @@ int phy_power_on(struct phy *phy)
 	if (!phy)
 		return 0;
 
+	if (phy->pwr) {
+		ret = regulator_enable(phy->pwr);
+		if (ret)
+			return ret;
+	}
+
 	ret = phy_pm_runtime_get_sync(phy);
 	if (ret < 0 && ret != -ENOTSUPP)
 		return ret;
@@ -247,6 +259,8 @@ int phy_power_on(struct phy *phy)
 out:
 	mutex_unlock(&phy->mutex);
 	phy_pm_runtime_put_sync(phy);
+	if (phy->pwr)
+		regulator_disable(phy->pwr);
 
 	return ret;
 }
@@ -272,6 +286,9 @@ int phy_power_off(struct phy *phy)
 	mutex_unlock(&phy->mutex);
 	phy_pm_runtime_put(phy);
 
+	if (phy->pwr)
+		regulator_disable(phy->pwr);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(phy_power_off);
@@ -398,13 +415,20 @@ struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args
 	struct phy *phy;
 	struct class_dev_iter iter;
 	struct device_node *node = dev->of_node;
+	struct device_node *child;
 
 	class_dev_iter_init(&iter, phy_class, NULL, NULL);
 	while ((dev = class_dev_iter_next(&iter))) {
 		phy = to_phy(dev);
-		if (node != phy->dev.of_node)
+		if (node != phy->dev.of_node) {
+			for_each_child_of_node(node, child) {
+				if (child == phy->dev.of_node)
+					goto phy_found;
+			}
 			continue;
+		}
 
+phy_found:
 		class_dev_iter_exit(&iter);
 		return phy;
 	}
@@ -562,13 +586,15 @@ EXPORT_SYMBOL_GPL(devm_of_phy_get);
 /**
  * phy_create() - create a new phy
  * @dev: device that is creating the new phy
+ * @node: device node of the phy
  * @ops: function pointers for performing phy operations
  * @init_data: contains the list of PHY consumers or NULL
  *
  * Called to create a phy using phy framework.
  */
-struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
-	struct phy_init_data *init_data)
+struct phy *phy_create(struct device *dev, struct device_node *node,
+		       const struct phy_ops *ops,
+		       struct phy_init_data *init_data)
 {
 	int ret;
 	int id;
@@ -588,12 +614,22 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
 		goto free_phy;
 	}
 
+	/* phy-supply */
+	phy->pwr = regulator_get_optional(dev, "phy");
+	if (IS_ERR(phy->pwr)) {
+		if (PTR_ERR(phy->pwr) == -EPROBE_DEFER) {
+			ret = -EPROBE_DEFER;
+			goto free_ida;
+		}
+		phy->pwr = NULL;
+	}
+
 	device_initialize(&phy->dev);
 	mutex_init(&phy->mutex);
 
 	phy->dev.class = phy_class;
 	phy->dev.parent = dev;
-	phy->dev.of_node = dev->of_node;
+	phy->dev.of_node = node ?: dev->of_node;
 	phy->id = id;
 	phy->ops = ops;
 	phy->init_data = init_data;
@@ -617,6 +653,9 @@ put_dev:
 	put_device(&phy->dev);  /* calls phy_release() which frees resources */
 	return ERR_PTR(ret);
 
+free_ida:
+	ida_simple_remove(&phy_ida, phy->id);
+
 free_phy:
 	kfree(phy);
 	return ERR_PTR(ret);
@@ -626,6 +665,7 @@ EXPORT_SYMBOL_GPL(phy_create);
 /**
  * devm_phy_create() - create a new phy
  * @dev: device that is creating the new phy
+ * @node: device node of the phy
  * @ops: function pointers for performing phy operations
  * @init_data: contains the list of PHY consumers or NULL
  *
@@ -634,8 +674,9 @@ EXPORT_SYMBOL_GPL(phy_create);
  * On driver detach, release function is invoked on the devres data,
  * then, devres data is freed.
  */
-struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops,
-	struct phy_init_data *init_data)
+struct phy *devm_phy_create(struct device *dev, struct device_node *node,
+			    const struct phy_ops *ops,
+			    struct phy_init_data *init_data)
 {
 	struct phy **ptr, *phy;
 
@@ -643,7 +684,7 @@ struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops,
 	if (!ptr)
 		return ERR_PTR(-ENOMEM);
 
-	phy = phy_create(dev, ops, init_data);
+	phy = phy_create(dev, node, ops, init_data);
 	if (!IS_ERR(phy)) {
 		*ptr = phy;
 		devres_add(dev, ptr);
@@ -800,6 +841,7 @@ static void phy_release(struct device *dev)
 
 	phy = to_phy(dev);
 	dev_vdbg(dev, "releasing '%s'\n", dev_name(dev));
+	regulator_put(phy->pwr);
 	ida_simple_remove(&phy_ida, phy->id);
 	kfree(phy);
 }
diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c
index 0786fef842e7..8b3026e2af7f 100644
--- a/drivers/phy/phy-exynos-dp-video.c
+++ b/drivers/phy/phy-exynos-dp-video.c
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -76,7 +77,7 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
 	if (IS_ERR(state->regs))
 		return PTR_ERR(state->regs);
 
-	phy = devm_phy_create(dev, &exynos_dp_video_phy_ops, NULL);
+	phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops, NULL);
 	if (IS_ERR(phy)) {
 		dev_err(dev, "failed to create Display Port PHY\n");
 		return PTR_ERR(phy);
@@ -84,10 +85,8 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
 	phy_set_drvdata(phy, state);
 
 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(phy_provider);
 }
 
 static const struct of_device_id exynos_dp_video_phy_of_match[] = {
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
index ff026689358c..b55a92e12496 100644
--- a/drivers/phy/phy-exynos-mipi-video.c
+++ b/drivers/phy/phy-exynos-mipi-video.c
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -135,7 +136,7 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
 	spin_lock_init(&state->slock);
 
 	for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
-		struct phy *phy = devm_phy_create(dev,
+		struct phy *phy = devm_phy_create(dev, NULL,
 					&exynos_mipi_video_phy_ops, NULL);
 		if (IS_ERR(phy)) {
 			dev_err(dev, "failed to create PHY %d\n", i);
@@ -149,10 +150,8 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
 
 	phy_provider = devm_of_phy_provider_register(dev,
 					exynos_mipi_video_phy_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(phy_provider);
 }
 
 static const struct of_device_id exynos_mipi_video_phy_of_match[] = {
diff --git a/drivers/phy/phy-exynos4x12-usb2.c b/drivers/phy/phy-exynos4x12-usb2.c
index d92a7cc5698a..0b9de88579b1 100644
--- a/drivers/phy/phy-exynos4x12-usb2.c
+++ b/drivers/phy/phy-exynos4x12-usb2.c
@@ -67,6 +67,8 @@
 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ	(0x5 << 0)
 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ	(0x7 << 0)
 
+#define EXYNOS_3250_UPHYCLK_REFCLKSEL		(0x2 << 8)
+
 #define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP	BIT(3)
 #define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON	BIT(4)
 #define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON	BIT(7)
@@ -86,13 +88,23 @@
 #define EXYNOS_4x12_URSTCON_OTG_HLINK		BIT(1)
 #define EXYNOS_4x12_URSTCON_OTG_PHYLINK		BIT(2)
 #define EXYNOS_4x12_URSTCON_HOST_PHY		BIT(3)
+/* The following bit defines are presented in the
+ * order taken from the Exynos4412 reference manual.
+ *
+ * During experiments with the hardware and debugging
+ * it was determined that the hardware behaves contrary
+ * to the manual.
+ *
+ * The following bit values were chaned accordingly to the
+ * results of real hardware experiments.
+ */
 #define EXYNOS_4x12_URSTCON_PHY1		BIT(4)
-#define EXYNOS_4x12_URSTCON_HSIC0		BIT(5)
-#define EXYNOS_4x12_URSTCON_HSIC1		BIT(6)
+#define EXYNOS_4x12_URSTCON_HSIC0		BIT(6)
+#define EXYNOS_4x12_URSTCON_HSIC1		BIT(5)
 #define EXYNOS_4x12_URSTCON_HOST_LINK_ALL	BIT(7)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P0	BIT(8)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P0	BIT(10)
 #define EXYNOS_4x12_URSTCON_HOST_LINK_P1	BIT(9)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P2	BIT(10)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P2	BIT(8)
 
 /* Isolation, configured in the power management unit */
 #define EXYNOS_4x12_USB_ISOL_OFFSET		0x704
@@ -187,7 +199,12 @@ static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst)
 
 	clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK);
 	clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK;
+
+	if (drv->cfg->has_refclk_sel)
+		clk = EXYNOS_3250_UPHYCLK_REFCLKSEL;
+
 	clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET;
+	clk |= EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON;
 	writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK);
 }
 
@@ -198,27 +215,22 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
 	u32 phypwr = 0;
 	u32 rst;
 	u32 pwr;
-	u32 mode = 0;
-	u32 switch_mode = 0;
 
 	switch (inst->cfg->id) {
 	case EXYNOS4x12_DEVICE:
 		phypwr =	EXYNOS_4x12_UPHYPWR_PHY0;
 		rstbits =	EXYNOS_4x12_URSTCON_PHY0;
-		mode =		EXYNOS_4x12_MODE_SWITCH_DEVICE;
-		switch_mode =	1;
 		break;
 	case EXYNOS4x12_HOST:
 		phypwr =	EXYNOS_4x12_UPHYPWR_PHY1;
-		rstbits =	EXYNOS_4x12_URSTCON_HOST_PHY;
-		mode =		EXYNOS_4x12_MODE_SWITCH_HOST;
-		switch_mode =	1;
+		rstbits =	EXYNOS_4x12_URSTCON_HOST_PHY |
+				EXYNOS_4x12_URSTCON_PHY1 |
+				EXYNOS_4x12_URSTCON_HOST_LINK_P0;
 		break;
 	case EXYNOS4x12_HSIC0:
 		phypwr =	EXYNOS_4x12_UPHYPWR_HSIC0;
-		rstbits =	EXYNOS_4x12_URSTCON_HSIC1 |
-				EXYNOS_4x12_URSTCON_HOST_LINK_P0 |
-				EXYNOS_4x12_URSTCON_HOST_PHY;
+		rstbits =	EXYNOS_4x12_URSTCON_HSIC0 |
+				EXYNOS_4x12_URSTCON_HOST_LINK_P1;
 		break;
 	case EXYNOS4x12_HSIC1:
 		phypwr =	EXYNOS_4x12_UPHYPWR_HSIC1;
@@ -228,11 +240,6 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
 	};
 
 	if (on) {
-		if (switch_mode)
-			regmap_update_bits(drv->reg_sys,
-					   EXYNOS_4x12_MODE_SWITCH_OFFSET,
-					   EXYNOS_4x12_MODE_SWITCH_MASK, mode);
-
 		pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
 		pwr &= ~phypwr;
 		writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
@@ -253,41 +260,78 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
 	}
 }
 
-static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
+static void exynos4x12_power_on_int(struct samsung_usb2_phy_instance *inst)
 {
-	struct samsung_usb2_phy_driver *drv = inst->drv;
+	if (inst->int_cnt++ > 0)
+		return;
 
-	inst->enabled = 1;
 	exynos4x12_setup_clk(inst);
-	exynos4x12_phy_pwr(inst, 1);
 	exynos4x12_isol(inst, 0);
+	exynos4x12_phy_pwr(inst, 1);
+}
+
+static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
+{
+	struct samsung_usb2_phy_driver *drv = inst->drv;
+
+	if (inst->ext_cnt++ > 0)
+		return 0;
 
-	/* Power on the device, as it is necessary for HSIC to work */
-	if (inst->cfg->id == EXYNOS4x12_HSIC0) {
-		struct samsung_usb2_phy_instance *device =
-					&drv->instances[EXYNOS4x12_DEVICE];
-		exynos4x12_phy_pwr(device, 1);
-		exynos4x12_isol(device, 0);
+	if (inst->cfg->id == EXYNOS4x12_HOST) {
+		regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+						EXYNOS_4x12_MODE_SWITCH_MASK,
+						EXYNOS_4x12_MODE_SWITCH_HOST);
+		exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
 	}
 
+	if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
+		regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+						EXYNOS_4x12_MODE_SWITCH_MASK,
+						EXYNOS_4x12_MODE_SWITCH_DEVICE);
+
+	if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
+		inst->cfg->id == EXYNOS4x12_HSIC1) {
+		exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
+		exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_HOST]);
+	}
+
+	exynos4x12_power_on_int(inst);
+
 	return 0;
 }
 
-static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
+static void exynos4x12_power_off_int(struct samsung_usb2_phy_instance *inst)
 {
-	struct samsung_usb2_phy_driver *drv = inst->drv;
-	struct samsung_usb2_phy_instance *device =
-					&drv->instances[EXYNOS4x12_DEVICE];
+	if (inst->int_cnt-- > 1)
+		return;
 
-	inst->enabled = 0;
 	exynos4x12_isol(inst, 1);
 	exynos4x12_phy_pwr(inst, 0);
+}
+
+static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
+{
+	struct samsung_usb2_phy_driver *drv = inst->drv;
+
+	if (inst->ext_cnt-- > 1)
+		return 0;
+
+	if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
+		regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+						EXYNOS_4x12_MODE_SWITCH_MASK,
+						EXYNOS_4x12_MODE_SWITCH_HOST);
+
+	if (inst->cfg->id == EXYNOS4x12_HOST)
+		exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
 
-	if (inst->cfg->id == EXYNOS4x12_HSIC0 && !device->enabled) {
-		exynos4x12_isol(device, 1);
-		exynos4x12_phy_pwr(device, 0);
+	if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
+		inst->cfg->id == EXYNOS4x12_HSIC1) {
+		exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
+		exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_HOST]);
 	}
 
+	exynos4x12_power_off_int(inst);
+
 	return 0;
 }
 
@@ -320,6 +364,13 @@ static const struct samsung_usb2_common_phy exynos4x12_phys[] = {
 	{},
 };
 
+const struct samsung_usb2_phy_config exynos3250_usb2_phy_config = {
+	.has_refclk_sel		= 1,
+	.num_phys		= 1,
+	.phys			= exynos4x12_phys,
+	.rate_to_clk		= exynos4x12_rate_to_clk,
+};
+
 const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = {
 	.has_mode_switch	= 1,
 	.num_phys		= EXYNOS4x12_NUM_PHYS,
diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
index 76d862b2202f..b05302b09c9f 100644
--- a/drivers/phy/phy-exynos5-usbdrd.c
+++ b/drivers/phy/phy-exynos5-usbdrd.c
@@ -506,7 +506,7 @@ static struct phy_ops exynos5_usbdrd_phy_ops = {
 	.owner		= THIS_MODULE,
 };
 
-const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
+static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
 	{
 		.id		= EXYNOS5_DRDPHY_UTMI,
 		.phy_isol	= exynos5_usbdrd_phy_isol,
@@ -521,13 +521,13 @@ const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
 	},
 };
 
-const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
+static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
 	.phy_cfg		= phy_cfg_exynos5,
 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
 	.pmu_offset_usbdrd1_phy	= EXYNOS5420_USBDRD1_PHY_CONTROL,
 };
 
-const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
+static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
 	.phy_cfg		= phy_cfg_exynos5,
 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
 };
@@ -635,7 +635,8 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
 	dev_vdbg(dev, "Creating usbdrd_phy phy\n");
 
 	for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
-		struct phy *phy = devm_phy_create(dev, &exynos5_usbdrd_phy_ops,
+		struct phy *phy = devm_phy_create(dev, NULL,
+						  &exynos5_usbdrd_phy_ops,
 						  NULL);
 		if (IS_ERR(phy)) {
 			dev_err(dev, "Failed to create usbdrd_phy phy\n");
diff --git a/drivers/phy/phy-exynos5250-sata.c b/drivers/phy/phy-exynos5250-sata.c
index 05689450f93b..19a679aca4ac 100644
--- a/drivers/phy/phy-exynos5250-sata.c
+++ b/drivers/phy/phy-exynos5250-sata.c
@@ -210,7 +210,7 @@ static int exynos_sata_phy_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	sata_phy->phy = devm_phy_create(dev, &exynos_sata_phy_ops, NULL);
+	sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops, NULL);
 	if (IS_ERR(sata_phy->phy)) {
 		clk_disable_unprepare(sata_phy->phyclk);
 		dev_err(dev, "failed to create PHY\n");
diff --git a/drivers/phy/phy-exynos5250-usb2.c b/drivers/phy/phy-exynos5250-usb2.c
index 94179afda951..1c139aa0d074 100644
--- a/drivers/phy/phy-exynos5250-usb2.c
+++ b/drivers/phy/phy-exynos5250-usb2.c
@@ -318,7 +318,6 @@ static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst)
 
 		break;
 	}
-	inst->enabled = 1;
 	exynos5250_isol(inst, 0);
 
 	return 0;
@@ -331,7 +330,6 @@ static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst)
 	u32 otg;
 	u32 hsic;
 
-	inst->enabled = 0;
 	exynos5250_isol(inst, 1);
 
 	switch (inst->cfg->id) {
diff --git a/drivers/phy/phy-hix5hd2-sata.c b/drivers/phy/phy-hix5hd2-sata.c
new file mode 100644
index 000000000000..6a08fa5f81eb
--- /dev/null
+++ b/drivers/phy/phy-hix5hd2-sata.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2014 Linaro Ltd.
+ * Copyright (c) 2014 Hisilicon Limited.
+ *
+ * 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/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define SATA_PHY0_CTLL		0xa0
+#define MPLL_MULTIPLIER_SHIFT	1
+#define MPLL_MULTIPLIER_MASK	0xfe
+#define MPLL_MULTIPLIER_50M	0x3c
+#define MPLL_MULTIPLIER_100M	0x1e
+#define PHY_RESET		BIT(0)
+#define REF_SSP_EN		BIT(9)
+#define SSC_EN			BIT(10)
+#define REF_USE_PAD		BIT(23)
+
+#define SATA_PORT_PHYCTL	0x174
+#define SPEED_MODE_MASK		0x6f0000
+#define HALF_RATE_SHIFT		16
+#define PHY_CONFIG_SHIFT	18
+#define GEN2_EN_SHIFT		21
+#define SPEED_CTRL		BIT(20)
+
+#define SATA_PORT_PHYCTL1	0x148
+#define AMPLITUDE_MASK		0x3ffffe
+#define AMPLITUDE_GEN3		0x68
+#define AMPLITUDE_GEN3_SHIFT	15
+#define AMPLITUDE_GEN2		0x56
+#define AMPLITUDE_GEN2_SHIFT	8
+#define AMPLITUDE_GEN1		0x56
+#define AMPLITUDE_GEN1_SHIFT	1
+
+#define SATA_PORT_PHYCTL2	0x14c
+#define PREEMPH_MASK		0x3ffff
+#define PREEMPH_GEN3		0x20
+#define PREEMPH_GEN3_SHIFT	12
+#define PREEMPH_GEN2		0x15
+#define PREEMPH_GEN2_SHIFT	6
+#define PREEMPH_GEN1		0x5
+#define PREEMPH_GEN1_SHIFT	0
+
+struct hix5hd2_priv {
+	void __iomem	*base;
+	struct regmap	*peri_ctrl;
+};
+
+enum phy_speed_mode {
+	SPEED_MODE_GEN1 = 0,
+	SPEED_MODE_GEN2 = 1,
+	SPEED_MODE_GEN3 = 2,
+};
+
+static int hix5hd2_sata_phy_init(struct phy *phy)
+{
+	struct hix5hd2_priv *priv = phy_get_drvdata(phy);
+	u32 val, data[2];
+	int ret;
+
+	if (priv->peri_ctrl) {
+		ret = of_property_read_u32_array(phy->dev.of_node,
+						 "hisilicon,power-reg",
+						 &data[0], 2);
+		if (ret) {
+			dev_err(&phy->dev, "Fail read hisilicon,power-reg\n");
+			return ret;
+		}
+
+		regmap_update_bits(priv->peri_ctrl, data[0],
+				   BIT(data[1]), BIT(data[1]));
+	}
+
+	/* reset phy */
+	val = readl_relaxed(priv->base + SATA_PHY0_CTLL);
+	val &= ~(MPLL_MULTIPLIER_MASK | REF_USE_PAD);
+	val |= MPLL_MULTIPLIER_50M << MPLL_MULTIPLIER_SHIFT |
+	       REF_SSP_EN | PHY_RESET;
+	writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
+	msleep(20);
+	val &= ~PHY_RESET;
+	writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
+
+	val = readl_relaxed(priv->base + SATA_PORT_PHYCTL1);
+	val &= ~AMPLITUDE_MASK;
+	val |= AMPLITUDE_GEN3 << AMPLITUDE_GEN3_SHIFT |
+	       AMPLITUDE_GEN2 << AMPLITUDE_GEN2_SHIFT |
+	       AMPLITUDE_GEN1 << AMPLITUDE_GEN1_SHIFT;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL1);
+
+	val = readl_relaxed(priv->base + SATA_PORT_PHYCTL2);
+	val &= ~PREEMPH_MASK;
+	val |= PREEMPH_GEN3 << PREEMPH_GEN3_SHIFT |
+	       PREEMPH_GEN2 << PREEMPH_GEN2_SHIFT |
+	       PREEMPH_GEN1 << PREEMPH_GEN1_SHIFT;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL2);
+
+	/* ensure PHYCTRL setting takes effect */
+	val = readl_relaxed(priv->base + SATA_PORT_PHYCTL);
+	val &= ~SPEED_MODE_MASK;
+	val |= SPEED_MODE_GEN1 << HALF_RATE_SHIFT |
+	       SPEED_MODE_GEN1 << PHY_CONFIG_SHIFT |
+	       SPEED_MODE_GEN1 << GEN2_EN_SHIFT | SPEED_CTRL;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+	msleep(20);
+	val &= ~SPEED_MODE_MASK;
+	val |= SPEED_MODE_GEN3 << HALF_RATE_SHIFT |
+	       SPEED_MODE_GEN3 << PHY_CONFIG_SHIFT |
+	       SPEED_MODE_GEN3 << GEN2_EN_SHIFT | SPEED_CTRL;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+	val &= ~(SPEED_MODE_MASK | SPEED_CTRL);
+	val |= SPEED_MODE_GEN2 << HALF_RATE_SHIFT |
+	       SPEED_MODE_GEN2 << PHY_CONFIG_SHIFT |
+	       SPEED_MODE_GEN2 << GEN2_EN_SHIFT;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+	return 0;
+}
+
+static struct phy_ops hix5hd2_sata_phy_ops = {
+	.init		= hix5hd2_sata_phy_init,
+	.owner		= THIS_MODULE,
+};
+
+static int hix5hd2_sata_phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct phy *phy;
+	struct hix5hd2_priv *priv;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!priv->base)
+		return -ENOMEM;
+
+	priv->peri_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
+					"hisilicon,peripheral-syscon");
+	if (IS_ERR(priv->peri_ctrl))
+		priv->peri_ctrl = NULL;
+
+	phy = devm_phy_create(dev, NULL, &hix5hd2_sata_phy_ops, NULL);
+	if (IS_ERR(phy)) {
+		dev_err(dev, "failed to create PHY\n");
+		return PTR_ERR(phy);
+	}
+
+	phy_set_drvdata(phy, priv);
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
+	return 0;
+}
+
+static const struct of_device_id hix5hd2_sata_phy_of_match[] = {
+	{.compatible = "hisilicon,hix5hd2-sata-phy",},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, hix5hd2_sata_phy_of_match);
+
+static struct platform_driver hix5hd2_sata_phy_driver = {
+	.probe	= hix5hd2_sata_phy_probe,
+	.driver = {
+		.name	= "hix5hd2-sata-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table	= hix5hd2_sata_phy_of_match,
+	}
+};
+module_platform_driver(hix5hd2_sata_phy_driver);
+
+MODULE_AUTHOR("Jiancheng Xue <xuejiancheng@huawei.com>");
+MODULE_DESCRIPTION("HISILICON HIX5HD2 SATA PHY driver");
+MODULE_ALIAS("platform:hix5hd2-sata-phy");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c
new file mode 100644
index 000000000000..e111baf187ce
--- /dev/null
+++ b/drivers/phy/phy-miphy365x.c
@@ -0,0 +1,636 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics – All Rights Reserved
+ *
+ * STMicroelectronics PHY driver MiPHY365 (for SoC STiH416).
+ *
+ * Authors: Alexandre Torgue <alexandre.torgue@st.com>
+ *          Lee Jones <lee.jones@linaro.org>
+ *
+ * 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/platform_device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/clk.h>
+#include <linux/phy/phy.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/phy/phy-miphy365x.h>
+
+#define HFC_TIMEOUT		100
+
+#define SYSCFG_SELECT_SATA_MASK	BIT(1)
+#define SYSCFG_SELECT_SATA_POS	1
+
+/* MiPHY365x register definitions */
+#define RESET_REG		0x00
+#define RST_PLL			BIT(1)
+#define RST_PLL_CAL		BIT(2)
+#define RST_RX			BIT(4)
+#define RST_MACRO		BIT(7)
+
+#define STATUS_REG		0x01
+#define IDLL_RDY		BIT(0)
+#define PLL_RDY			BIT(1)
+#define DES_BIT_LOCK		BIT(2)
+#define DES_SYMBOL_LOCK		BIT(3)
+
+#define CTRL_REG		0x02
+#define TERM_EN			BIT(0)
+#define PCI_EN			BIT(2)
+#define DES_BIT_LOCK_EN		BIT(3)
+#define TX_POL			BIT(5)
+
+#define INT_CTRL_REG		0x03
+
+#define BOUNDARY1_REG		0x10
+#define SPDSEL_SEL		BIT(0)
+
+#define BOUNDARY3_REG		0x12
+#define TX_SPDSEL_GEN1_VAL	0
+#define TX_SPDSEL_GEN2_VAL	0x01
+#define TX_SPDSEL_GEN3_VAL	0x02
+#define RX_SPDSEL_GEN1_VAL	0
+#define RX_SPDSEL_GEN2_VAL	(0x01 << 3)
+#define RX_SPDSEL_GEN3_VAL	(0x02 << 3)
+
+#define PCIE_REG		0x16
+
+#define BUF_SEL_REG		0x20
+#define CONF_GEN_SEL_GEN3	0x02
+#define CONF_GEN_SEL_GEN2	0x01
+#define PD_VDDTFILTER		BIT(4)
+
+#define TXBUF1_REG		0x21
+#define SWING_VAL		0x04
+#define SWING_VAL_GEN1		0x03
+#define PREEMPH_VAL		(0x3 << 5)
+
+#define TXBUF2_REG		0x22
+#define TXSLEW_VAL		0x2
+#define TXSLEW_VAL_GEN1		0x4
+
+#define RXBUF_OFFSET_CTRL_REG	0x23
+
+#define RXBUF_REG		0x25
+#define SDTHRES_VAL		0x01
+#define EQ_ON3			(0x03 << 4)
+#define EQ_ON1			(0x01 << 4)
+
+#define COMP_CTRL1_REG		0x40
+#define START_COMSR		BIT(0)
+#define START_COMZC		BIT(1)
+#define COMSR_DONE		BIT(2)
+#define COMZC_DONE		BIT(3)
+#define COMP_AUTO_LOAD		BIT(4)
+
+#define COMP_CTRL2_REG		0x41
+#define COMP_2MHZ_RAT_GEN1	0x1e
+#define COMP_2MHZ_RAT		0xf
+
+#define COMP_CTRL3_REG		0x42
+#define COMSR_COMP_REF		0x33
+
+#define COMP_IDLL_REG		0x47
+#define COMZC_IDLL		0x2a
+
+#define PLL_CTRL1_REG		0x50
+#define PLL_START_CAL		BIT(0)
+#define BUF_EN			BIT(2)
+#define SYNCHRO_TX		BIT(3)
+#define SSC_EN			BIT(6)
+#define CONFIG_PLL		BIT(7)
+
+#define PLL_CTRL2_REG		0x51
+#define BYPASS_PLL_CAL		BIT(1)
+
+#define PLL_RAT_REG		0x52
+
+#define PLL_SSC_STEP_MSB_REG	0x56
+#define PLL_SSC_STEP_MSB_VAL	0x03
+
+#define PLL_SSC_STEP_LSB_REG	0x57
+#define PLL_SSC_STEP_LSB_VAL	0x63
+
+#define PLL_SSC_PER_MSB_REG	0x58
+#define PLL_SSC_PER_MSB_VAL	0
+
+#define PLL_SSC_PER_LSB_REG	0x59
+#define PLL_SSC_PER_LSB_VAL	0xf1
+
+#define IDLL_TEST_REG		0x72
+#define START_CLK_HF		BIT(6)
+
+#define DES_BITLOCK_REG		0x86
+#define BIT_LOCK_LEVEL		0x01
+#define BIT_LOCK_CNT_512	(0x03 << 5)
+
+struct miphy365x_phy {
+	struct phy *phy;
+	void __iomem *base;
+	bool pcie_tx_pol_inv;
+	bool sata_tx_pol_inv;
+	u32 sata_gen;
+	u64 ctrlreg;
+	u8 type;
+};
+
+struct miphy365x_dev {
+	struct device *dev;
+	struct regmap *regmap;
+	struct mutex miphy_mutex;
+	struct miphy365x_phy **phys;
+};
+
+/*
+ * These values are represented in Device tree. They are considered to be ABI
+ * and although they can be extended any existing values must not change.
+ */
+enum miphy_sata_gen {
+	SATA_GEN1 = 1,
+	SATA_GEN2,
+	SATA_GEN3
+};
+
+static u8 rx_tx_spd[] = {
+	TX_SPDSEL_GEN1_VAL | RX_SPDSEL_GEN1_VAL,
+	TX_SPDSEL_GEN2_VAL | RX_SPDSEL_GEN2_VAL,
+	TX_SPDSEL_GEN3_VAL | RX_SPDSEL_GEN3_VAL
+};
+
+/*
+ * This function selects the system configuration,
+ * either two SATA, one SATA and one PCIe, or two PCIe lanes.
+ */
+static int miphy365x_set_path(struct miphy365x_phy *miphy_phy,
+			      struct miphy365x_dev *miphy_dev)
+{
+	bool sata = (miphy_phy->type == MIPHY_TYPE_SATA);
+
+	return regmap_update_bits(miphy_dev->regmap,
+				  (unsigned int)miphy_phy->ctrlreg,
+				  SYSCFG_SELECT_SATA_MASK,
+				  sata << SYSCFG_SELECT_SATA_POS);
+}
+
+static int miphy365x_init_pcie_port(struct miphy365x_phy *miphy_phy,
+				    struct miphy365x_dev *miphy_dev)
+{
+	u8 val;
+
+	if (miphy_phy->pcie_tx_pol_inv) {
+		/* Invert Tx polarity and clear pci_txdetect_pol bit */
+		val = TERM_EN | PCI_EN | DES_BIT_LOCK_EN | TX_POL;
+		writeb_relaxed(val, miphy_phy->base + CTRL_REG);
+		writeb_relaxed(0x00, miphy_phy->base + PCIE_REG);
+	}
+
+	return 0;
+}
+
+static inline int miphy365x_hfc_not_rdy(struct miphy365x_phy *miphy_phy,
+					struct miphy365x_dev *miphy_dev)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT);
+	u8 mask = IDLL_RDY | PLL_RDY;
+	u8 regval;
+
+	do {
+		regval = readb_relaxed(miphy_phy->base + STATUS_REG);
+		if (!(regval & mask))
+			return 0;
+
+		usleep_range(2000, 2500);
+	} while (time_before(jiffies, timeout));
+
+	dev_err(miphy_dev->dev, "HFC ready timeout!\n");
+	return -EBUSY;
+}
+
+static inline int miphy365x_rdy(struct miphy365x_phy *miphy_phy,
+				struct miphy365x_dev *miphy_dev)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT);
+	u8 mask = IDLL_RDY | PLL_RDY;
+	u8 regval;
+
+	do {
+		regval = readb_relaxed(miphy_phy->base + STATUS_REG);
+		if ((regval & mask) == mask)
+			return 0;
+
+		usleep_range(2000, 2500);
+	} while (time_before(jiffies, timeout));
+
+	dev_err(miphy_dev->dev, "PHY not ready timeout!\n");
+	return -EBUSY;
+}
+
+static inline void miphy365x_set_comp(struct miphy365x_phy *miphy_phy,
+				      struct miphy365x_dev *miphy_dev)
+{
+	u8 val, mask;
+
+	if (miphy_phy->sata_gen == SATA_GEN1)
+		writeb_relaxed(COMP_2MHZ_RAT_GEN1,
+			       miphy_phy->base + COMP_CTRL2_REG);
+	else
+		writeb_relaxed(COMP_2MHZ_RAT,
+			       miphy_phy->base + COMP_CTRL2_REG);
+
+	if (miphy_phy->sata_gen != SATA_GEN3) {
+		writeb_relaxed(COMSR_COMP_REF,
+			       miphy_phy->base + COMP_CTRL3_REG);
+		/*
+		 * Force VCO current to value defined by address 0x5A
+		 * and disable PCIe100Mref bit
+		 * Enable auto load compensation for pll_i_bias
+		 */
+		writeb_relaxed(BYPASS_PLL_CAL, miphy_phy->base + PLL_CTRL2_REG);
+		writeb_relaxed(COMZC_IDLL, miphy_phy->base + COMP_IDLL_REG);
+	}
+
+	/*
+	 * Force restart compensation and enable auto load
+	 * for Comzc_Tx, Comzc_Rx and Comsr on macro
+	 */
+	val = START_COMSR | START_COMZC | COMP_AUTO_LOAD;
+	writeb_relaxed(val, miphy_phy->base + COMP_CTRL1_REG);
+
+	mask = COMSR_DONE | COMZC_DONE;
+	while ((readb_relaxed(miphy_phy->base + COMP_CTRL1_REG) & mask)	!= mask)
+		cpu_relax();
+}
+
+static inline void miphy365x_set_ssc(struct miphy365x_phy *miphy_phy,
+				     struct miphy365x_dev *miphy_dev)
+{
+	u8 val;
+
+	/*
+	 * SSC Settings. SSC will be enabled through Link
+	 * SSC Ampl. = 0.4%
+	 * SSC Freq = 31KHz
+	 */
+	writeb_relaxed(PLL_SSC_STEP_MSB_VAL,
+		       miphy_phy->base + PLL_SSC_STEP_MSB_REG);
+	writeb_relaxed(PLL_SSC_STEP_LSB_VAL,
+		       miphy_phy->base + PLL_SSC_STEP_LSB_REG);
+	writeb_relaxed(PLL_SSC_PER_MSB_VAL,
+		       miphy_phy->base + PLL_SSC_PER_MSB_REG);
+	writeb_relaxed(PLL_SSC_PER_LSB_VAL,
+		       miphy_phy->base + PLL_SSC_PER_LSB_REG);
+
+	/* SSC Settings complete */
+	if (miphy_phy->sata_gen == SATA_GEN1) {
+		val = PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL;
+		writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG);
+	} else {
+		val = SSC_EN | PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL;
+		writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG);
+	}
+}
+
+static int miphy365x_init_sata_port(struct miphy365x_phy *miphy_phy,
+				    struct miphy365x_dev *miphy_dev)
+{
+	int ret;
+	u8 val;
+
+	/*
+	 * Force PHY macro reset, PLL calibration reset, PLL reset
+	 * and assert Deserializer Reset
+	 */
+	val = RST_PLL | RST_PLL_CAL | RST_RX | RST_MACRO;
+	writeb_relaxed(val, miphy_phy->base + RESET_REG);
+
+	if (miphy_phy->sata_tx_pol_inv)
+		writeb_relaxed(TX_POL, miphy_phy->base + CTRL_REG);
+
+	/*
+	 * Force macro1 to use rx_lspd, tx_lspd
+	 * Force Rx_Clock on first I-DLL phase
+	 * Force Des in HP mode on macro, rx_lspd, tx_lspd for Gen2/3
+	 */
+	writeb_relaxed(SPDSEL_SEL, miphy_phy->base + BOUNDARY1_REG);
+	writeb_relaxed(START_CLK_HF, miphy_phy->base + IDLL_TEST_REG);
+	val = rx_tx_spd[miphy_phy->sata_gen];
+	writeb_relaxed(val, miphy_phy->base + BOUNDARY3_REG);
+
+	/* Wait for HFC_READY = 0 */
+	ret = miphy365x_hfc_not_rdy(miphy_phy, miphy_dev);
+	if (ret)
+		return ret;
+
+	/* Compensation Recalibration */
+	miphy365x_set_comp(miphy_phy, miphy_dev);
+
+	switch (miphy_phy->sata_gen) {
+	case SATA_GEN3:
+		/*
+		 * TX Swing target 550-600mv peak to peak diff
+		 * Tx Slew target 90-110ps rising/falling time
+		 * Rx Eq ON3, Sigdet threshold SDTH1
+		 */
+		val = PD_VDDTFILTER | CONF_GEN_SEL_GEN3;
+		writeb_relaxed(val, miphy_phy->base + BUF_SEL_REG);
+		val = SWING_VAL | PREEMPH_VAL;
+		writeb_relaxed(val, miphy_phy->base + TXBUF1_REG);
+		writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG);
+		writeb_relaxed(0x00, miphy_phy->base + RXBUF_OFFSET_CTRL_REG);
+		val = SDTHRES_VAL | EQ_ON3;
+		writeb_relaxed(val, miphy_phy->base + RXBUF_REG);
+		break;
+	case SATA_GEN2:
+		/*
+		 * conf gen sel=0x1 to program Gen2 banked registers
+		 * VDDT filter ON
+		 * Tx Swing target 550-600mV peak-to-peak diff
+		 * Tx Slew target 90-110 ps rising/falling time
+		 * RX Equalization ON1, Sigdet threshold SDTH1
+		 */
+		writeb_relaxed(CONF_GEN_SEL_GEN2,
+			       miphy_phy->base + BUF_SEL_REG);
+		writeb_relaxed(SWING_VAL, miphy_phy->base + TXBUF1_REG);
+		writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG);
+		val = SDTHRES_VAL | EQ_ON1;
+		writeb_relaxed(val, miphy_phy->base + RXBUF_REG);
+		break;
+	case SATA_GEN1:
+		/*
+		 * conf gen sel = 00b to program Gen1 banked registers
+		 * VDDT filter ON
+		 * Tx Swing target 500-550mV peak-to-peak diff
+		 * Tx Slew target120-140 ps rising/falling time
+		 */
+		writeb_relaxed(PD_VDDTFILTER, miphy_phy->base + BUF_SEL_REG);
+		writeb_relaxed(SWING_VAL_GEN1, miphy_phy->base + TXBUF1_REG);
+		writeb_relaxed(TXSLEW_VAL_GEN1,	miphy_phy->base + TXBUF2_REG);
+		break;
+	default:
+		break;
+	}
+
+	/* Force Macro1 in partial mode & release pll cal reset */
+	writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG);
+	usleep_range(100, 150);
+
+	miphy365x_set_ssc(miphy_phy, miphy_dev);
+
+	/* Wait for phy_ready */
+	ret = miphy365x_rdy(miphy_phy, miphy_dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * Enable macro1 to use rx_lspd & tx_lspd
+	 * Release Rx_Clock on first I-DLL phase on macro1
+	 * Assert deserializer reset
+	 * des_bit_lock_en is set
+	 * bit lock detection strength
+	 * Deassert deserializer reset
+	 */
+	writeb_relaxed(0x00, miphy_phy->base + BOUNDARY1_REG);
+	writeb_relaxed(0x00, miphy_phy->base + IDLL_TEST_REG);
+	writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG);
+	val = miphy_phy->sata_tx_pol_inv ?
+		(TX_POL | DES_BIT_LOCK_EN) : DES_BIT_LOCK_EN;
+	writeb_relaxed(val, miphy_phy->base + CTRL_REG);
+
+	val = BIT_LOCK_CNT_512 | BIT_LOCK_LEVEL;
+	writeb_relaxed(val, miphy_phy->base + DES_BITLOCK_REG);
+	writeb_relaxed(0x00, miphy_phy->base + RESET_REG);
+
+	return 0;
+}
+
+static int miphy365x_init(struct phy *phy)
+{
+	struct miphy365x_phy *miphy_phy = phy_get_drvdata(phy);
+	struct miphy365x_dev *miphy_dev = dev_get_drvdata(phy->dev.parent);
+	int ret = 0;
+
+	mutex_lock(&miphy_dev->miphy_mutex);
+
+	ret = miphy365x_set_path(miphy_phy, miphy_dev);
+	if (ret) {
+		mutex_unlock(&miphy_dev->miphy_mutex);
+		return ret;
+	}
+
+	/* Initialise Miphy for PCIe or SATA */
+	if (miphy_phy->type == MIPHY_TYPE_PCIE)
+		ret = miphy365x_init_pcie_port(miphy_phy, miphy_dev);
+	else
+		ret = miphy365x_init_sata_port(miphy_phy, miphy_dev);
+
+	mutex_unlock(&miphy_dev->miphy_mutex);
+
+	return ret;
+}
+
+int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy,
+		       int index)
+{
+	struct device_node *phynode = miphy_phy->phy->dev.of_node;
+	const char *name;
+	const __be32 *taddr;
+	int type = miphy_phy->type;
+	int ret;
+
+	ret = of_property_read_string_index(phynode, "reg-names", index, &name);
+	if (ret) {
+		dev_err(dev, "no reg-names property not found\n");
+		return ret;
+	}
+
+	if (!strncmp(name, "syscfg", 6)) {
+		taddr = of_get_address(phynode, index, NULL, NULL);
+		if (!taddr) {
+			dev_err(dev, "failed to fetch syscfg address\n");
+			return -EINVAL;
+		}
+
+		miphy_phy->ctrlreg = of_translate_address(phynode, taddr);
+		if (miphy_phy->ctrlreg == OF_BAD_ADDR) {
+			dev_err(dev, "failed to translate syscfg address\n");
+			return -EINVAL;
+		}
+
+		return 0;
+	}
+
+	if (!((!strncmp(name, "sata", 4) && type == MIPHY_TYPE_SATA) ||
+	      (!strncmp(name, "pcie", 4) && type == MIPHY_TYPE_PCIE)))
+		return 0;
+
+	miphy_phy->base = of_iomap(phynode, index);
+	if (!miphy_phy->base) {
+		dev_err(dev, "Failed to map %s\n", phynode->full_name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct phy *miphy365x_xlate(struct device *dev,
+				   struct of_phandle_args *args)
+{
+	struct miphy365x_dev *miphy_dev = dev_get_drvdata(dev);
+	struct miphy365x_phy *miphy_phy = NULL;
+	struct device_node *phynode = args->np;
+	int ret, index;
+
+	if (!of_device_is_available(phynode)) {
+		dev_warn(dev, "Requested PHY is disabled\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	if (args->args_count != 1) {
+		dev_err(dev, "Invalid number of cells in 'phy' property\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	for (index = 0; index < of_get_child_count(dev->of_node); index++)
+		if (phynode == miphy_dev->phys[index]->phy->dev.of_node) {
+			miphy_phy = miphy_dev->phys[index];
+			break;
+		}
+
+	if (!miphy_phy) {
+		dev_err(dev, "Failed to find appropriate phy\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	miphy_phy->type = args->args[0];
+
+	if (!(miphy_phy->type == MIPHY_TYPE_SATA ||
+	      miphy_phy->type == MIPHY_TYPE_PCIE)) {
+		dev_err(dev, "Unsupported device type: %d\n", miphy_phy->type);
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* Each port handles SATA and PCIE - third entry is always sysconf. */
+	for (index = 0; index < 3; index++) {
+		ret = miphy365x_get_addr(dev, miphy_phy, index);
+		if (ret < 0)
+			return ERR_PTR(ret);
+	}
+
+	return miphy_phy->phy;
+}
+
+static struct phy_ops miphy365x_ops = {
+	.init		= miphy365x_init,
+	.owner		= THIS_MODULE,
+};
+
+static int miphy365x_of_probe(struct device_node *phynode,
+			      struct miphy365x_phy *miphy_phy)
+{
+	of_property_read_u32(phynode, "st,sata-gen", &miphy_phy->sata_gen);
+	if (!miphy_phy->sata_gen)
+		miphy_phy->sata_gen = SATA_GEN1;
+
+	miphy_phy->pcie_tx_pol_inv =
+		of_property_read_bool(phynode, "st,pcie-tx-pol-inv");
+
+	miphy_phy->sata_tx_pol_inv =
+		of_property_read_bool(phynode, "st,sata-tx-pol-inv");
+
+	return 0;
+}
+
+static int miphy365x_probe(struct platform_device *pdev)
+{
+	struct device_node *child, *np = pdev->dev.of_node;
+	struct miphy365x_dev *miphy_dev;
+	struct phy_provider *provider;
+	struct phy *phy;
+	int chancount, port = 0;
+	int ret;
+
+	miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL);
+	if (!miphy_dev)
+		return -ENOMEM;
+
+	chancount = of_get_child_count(np);
+	miphy_dev->phys = devm_kzalloc(&pdev->dev, sizeof(phy) * chancount,
+				       GFP_KERNEL);
+	if (!miphy_dev->phys)
+		return -ENOMEM;
+
+	miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+	if (IS_ERR(miphy_dev->regmap)) {
+		dev_err(miphy_dev->dev, "No syscfg phandle specified\n");
+		return PTR_ERR(miphy_dev->regmap);
+	}
+
+	miphy_dev->dev = &pdev->dev;
+
+	dev_set_drvdata(&pdev->dev, miphy_dev);
+
+	mutex_init(&miphy_dev->miphy_mutex);
+
+	for_each_child_of_node(np, child) {
+		struct miphy365x_phy *miphy_phy;
+
+		miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),
+					 GFP_KERNEL);
+		if (!miphy_phy)
+			return -ENOMEM;
+
+		miphy_dev->phys[port] = miphy_phy;
+
+		phy = devm_phy_create(&pdev->dev, child, &miphy365x_ops, NULL);
+		if (IS_ERR(phy)) {
+			dev_err(&pdev->dev, "failed to create PHY\n");
+			return PTR_ERR(phy);
+		}
+
+		miphy_dev->phys[port]->phy = phy;
+
+		ret = miphy365x_of_probe(child, miphy_phy);
+		if (ret)
+			return ret;
+
+		phy_set_drvdata(phy, miphy_dev->phys[port]);
+		port++;
+	}
+
+	provider = devm_of_phy_provider_register(&pdev->dev, miphy365x_xlate);
+	if (IS_ERR(provider))
+		return PTR_ERR(provider);
+
+	return 0;
+}
+
+static const struct of_device_id miphy365x_of_match[] = {
+	{ .compatible = "st,miphy365x-phy", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, miphy365x_of_match);
+
+static struct platform_driver miphy365x_driver = {
+	.probe	= miphy365x_probe,
+	.driver = {
+		.name	= "miphy365x-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table	= miphy365x_of_match,
+	}
+};
+module_platform_driver(miphy365x_driver);
+
+MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics miphy365x driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/phy-mvebu-sata.c
index d70ecd6a1b3f..cc3c0e166daf 100644
--- a/drivers/phy/phy-mvebu-sata.c
+++ b/drivers/phy/phy-mvebu-sata.c
@@ -99,7 +99,7 @@ static int phy_mvebu_sata_probe(struct platform_device *pdev)
 	if (IS_ERR(priv->clk))
 		return PTR_ERR(priv->clk);
 
-	phy = devm_phy_create(&pdev->dev, &phy_mvebu_sata_ops, NULL);
+	phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops, NULL);
 	if (IS_ERR(phy))
 		return PTR_ERR(phy);
 
diff --git a/drivers/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c
index 311b4f9a5132..9487bf112267 100644
--- a/drivers/phy/phy-omap-control.c
+++ b/drivers/phy/phy-omap-control.c
@@ -27,6 +27,41 @@
 #include <linux/phy/omap_control_phy.h>
 
 /**
+ * omap_control_pcie_pcs - set the PCS delay count
+ * @dev: the control module device
+ * @id: index of the pcie PHY (should be 1 or 2)
+ * @delay: 8 bit delay value
+ */
+void omap_control_pcie_pcs(struct device *dev, u8 id, u8 delay)
+{
+	u32 val;
+	struct omap_control_phy	*control_phy;
+
+	if (IS_ERR(dev) || !dev) {
+		pr_err("%s: invalid device\n", __func__);
+		return;
+	}
+
+	control_phy = dev_get_drvdata(dev);
+	if (!control_phy) {
+		dev_err(dev, "%s: invalid control phy device\n", __func__);
+		return;
+	}
+
+	if (control_phy->type != OMAP_CTRL_TYPE_PCIE) {
+		dev_err(dev, "%s: unsupported operation\n", __func__);
+		return;
+	}
+
+	val = readl(control_phy->pcie_pcs);
+	val &= ~(OMAP_CTRL_PCIE_PCS_MASK <<
+		(id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT));
+	val |= delay << (id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT);
+	writel(val, control_phy->pcie_pcs);
+}
+EXPORT_SYMBOL_GPL(omap_control_pcie_pcs);
+
+/**
  * omap_control_phy_power - power on/off the phy using control module reg
  * @dev: the control module device
  * @on: 0 or 1, based on powering on or off the PHY
@@ -61,6 +96,7 @@ void omap_control_phy_power(struct device *dev, int on)
 			val |= OMAP_CTRL_DEV_PHY_PD;
 		break;
 
+	case OMAP_CTRL_TYPE_PCIE:
 	case OMAP_CTRL_TYPE_PIPE3:
 		rate = clk_get_rate(control_phy->sys_clk);
 		rate = rate/1000000;
@@ -211,6 +247,7 @@ EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
 static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS;
 static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2;
 static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3;
+static const enum omap_control_phy_type pcie_data = OMAP_CTRL_TYPE_PCIE;
 static const enum omap_control_phy_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2;
 static const enum omap_control_phy_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2;
 
@@ -228,6 +265,10 @@ static const struct of_device_id omap_control_phy_id_table[] = {
 		.data = &pipe3_data,
 	},
 	{
+		.compatible = "ti,control-phy-pcie",
+		.data = &pcie_data,
+	},
+	{
 		.compatible = "ti,control-phy-usb2-dra7",
 		.data = &dra7usb2_data,
 	},
@@ -279,7 +320,8 @@ static int omap_control_phy_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (control_phy->type == OMAP_CTRL_TYPE_PIPE3) {
+	if (control_phy->type == OMAP_CTRL_TYPE_PIPE3 ||
+	    control_phy->type == OMAP_CTRL_TYPE_PCIE) {
 		control_phy->sys_clk = devm_clk_get(control_phy->dev,
 			"sys_clkin");
 		if (IS_ERR(control_phy->sys_clk)) {
@@ -288,6 +330,14 @@ static int omap_control_phy_probe(struct platform_device *pdev)
 		}
 	}
 
+	if (control_phy->type == OMAP_CTRL_TYPE_PCIE) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						   "pcie_pcs");
+		control_phy->pcie_pcs = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(control_phy->pcie_pcs))
+			return PTR_ERR(control_phy->pcie_pcs);
+	}
+
 	dev_set_drvdata(control_phy->dev, control_phy);
 
 	return 0;
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
index 34b396146c8a..93d78359246c 100644
--- a/drivers/phy/phy-omap-usb2.c
+++ b/drivers/phy/phy-omap-usb2.c
@@ -263,7 +263,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, phy);
 
-	generic_phy = devm_phy_create(phy->dev, &ops, NULL);
+	generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL);
 	if (IS_ERR(generic_phy))
 		return PTR_ERR(generic_phy);
 
diff --git a/drivers/phy/phy-qcom-apq8064-sata.c b/drivers/phy/phy-qcom-apq8064-sata.c
new file mode 100644
index 000000000000..b3ef7d805765
--- /dev/null
+++ b/drivers/phy/phy-qcom-apq8064-sata.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+/* PHY registers */
+#define UNIPHY_PLL_REFCLK_CFG		0x000
+#define UNIPHY_PLL_PWRGEN_CFG		0x014
+#define UNIPHY_PLL_GLB_CFG		0x020
+#define UNIPHY_PLL_SDM_CFG0		0x038
+#define UNIPHY_PLL_SDM_CFG1		0x03C
+#define UNIPHY_PLL_SDM_CFG2		0x040
+#define UNIPHY_PLL_SDM_CFG3		0x044
+#define UNIPHY_PLL_SDM_CFG4		0x048
+#define UNIPHY_PLL_SSC_CFG0		0x04C
+#define UNIPHY_PLL_SSC_CFG1		0x050
+#define UNIPHY_PLL_SSC_CFG2		0x054
+#define UNIPHY_PLL_SSC_CFG3		0x058
+#define UNIPHY_PLL_LKDET_CFG0		0x05C
+#define UNIPHY_PLL_LKDET_CFG1		0x060
+#define UNIPHY_PLL_LKDET_CFG2		0x064
+#define UNIPHY_PLL_CAL_CFG0		0x06C
+#define UNIPHY_PLL_CAL_CFG8		0x08C
+#define UNIPHY_PLL_CAL_CFG9		0x090
+#define UNIPHY_PLL_CAL_CFG10		0x094
+#define UNIPHY_PLL_CAL_CFG11		0x098
+#define UNIPHY_PLL_STATUS		0x0C0
+
+#define SATA_PHY_SER_CTRL		0x100
+#define SATA_PHY_TX_DRIV_CTRL0		0x104
+#define SATA_PHY_TX_DRIV_CTRL1		0x108
+#define SATA_PHY_TX_IMCAL0		0x11C
+#define SATA_PHY_TX_IMCAL2		0x124
+#define SATA_PHY_RX_IMCAL0		0x128
+#define SATA_PHY_EQUAL			0x13C
+#define SATA_PHY_OOB_TERM		0x144
+#define SATA_PHY_CDR_CTRL0		0x148
+#define SATA_PHY_CDR_CTRL1		0x14C
+#define SATA_PHY_CDR_CTRL2		0x150
+#define SATA_PHY_CDR_CTRL3		0x154
+#define SATA_PHY_PI_CTRL0		0x168
+#define SATA_PHY_POW_DWN_CTRL0		0x180
+#define SATA_PHY_POW_DWN_CTRL1		0x184
+#define SATA_PHY_TX_DATA_CTRL		0x188
+#define SATA_PHY_ALIGNP			0x1A4
+#define SATA_PHY_TX_IMCAL_STAT		0x1E4
+#define SATA_PHY_RX_IMCAL_STAT		0x1E8
+
+#define UNIPHY_PLL_LOCK		BIT(0)
+#define SATA_PHY_TX_CAL		BIT(0)
+#define SATA_PHY_RX_CAL		BIT(0)
+
+/* default timeout set to 1 sec */
+#define TIMEOUT_MS		10000
+#define DELAY_INTERVAL_US	100
+
+struct qcom_apq8064_sata_phy {
+	void __iomem *mmio;
+	struct clk *cfg_clk;
+	struct device *dev;
+};
+
+/* Helper function to do poll and timeout */
+static int read_poll_timeout(void __iomem *addr, u32 mask)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS);
+
+	do {
+		if (readl_relaxed(addr) & mask)
+			return 0;
+
+		 usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50);
+	} while (!time_after(jiffies, timeout));
+
+	return (readl_relaxed(addr) & mask) ? 0 : -ETIMEDOUT;
+}
+
+static int qcom_apq8064_sata_phy_init(struct phy *generic_phy)
+{
+	struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
+	void __iomem *base = phy->mmio;
+	int ret = 0;
+
+	/* SATA phy initialization */
+	writel_relaxed(0x01, base + SATA_PHY_SER_CTRL);
+	writel_relaxed(0xB1, base + SATA_PHY_POW_DWN_CTRL0);
+	/* Make sure the power down happens before power up */
+	mb();
+	usleep_range(10, 60);
+
+	writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
+	writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
+	writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
+	writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
+	writel_relaxed(0x02, base + SATA_PHY_TX_IMCAL2);
+
+	/* Write UNIPHYPLL registers to configure PLL */
+	writel_relaxed(0x04, base + UNIPHY_PLL_REFCLK_CFG);
+	writel_relaxed(0x00, base + UNIPHY_PLL_PWRGEN_CFG);
+
+	writel_relaxed(0x0A, base + UNIPHY_PLL_CAL_CFG0);
+	writel_relaxed(0xF3, base + UNIPHY_PLL_CAL_CFG8);
+	writel_relaxed(0x01, base + UNIPHY_PLL_CAL_CFG9);
+	writel_relaxed(0xED, base + UNIPHY_PLL_CAL_CFG10);
+	writel_relaxed(0x02, base + UNIPHY_PLL_CAL_CFG11);
+
+	writel_relaxed(0x36, base + UNIPHY_PLL_SDM_CFG0);
+	writel_relaxed(0x0D, base + UNIPHY_PLL_SDM_CFG1);
+	writel_relaxed(0xA3, base + UNIPHY_PLL_SDM_CFG2);
+	writel_relaxed(0xF0, base + UNIPHY_PLL_SDM_CFG3);
+	writel_relaxed(0x00, base + UNIPHY_PLL_SDM_CFG4);
+
+	writel_relaxed(0x19, base + UNIPHY_PLL_SSC_CFG0);
+	writel_relaxed(0xE1, base + UNIPHY_PLL_SSC_CFG1);
+	writel_relaxed(0x00, base + UNIPHY_PLL_SSC_CFG2);
+	writel_relaxed(0x11, base + UNIPHY_PLL_SSC_CFG3);
+
+	writel_relaxed(0x04, base + UNIPHY_PLL_LKDET_CFG0);
+	writel_relaxed(0xFF, base + UNIPHY_PLL_LKDET_CFG1);
+
+	writel_relaxed(0x02, base + UNIPHY_PLL_GLB_CFG);
+	/* make sure global config LDO power down happens before power up */
+	mb();
+
+	writel_relaxed(0x03, base + UNIPHY_PLL_GLB_CFG);
+	writel_relaxed(0x05, base + UNIPHY_PLL_LKDET_CFG2);
+
+	/* PLL Lock wait */
+	ret = read_poll_timeout(base + UNIPHY_PLL_STATUS, UNIPHY_PLL_LOCK);
+	if (ret) {
+		dev_err(phy->dev, "poll timeout UNIPHY_PLL_STATUS\n");
+		return ret;
+	}
+
+	/* TX Calibration */
+	ret = read_poll_timeout(base + SATA_PHY_TX_IMCAL_STAT, SATA_PHY_TX_CAL);
+	if (ret) {
+		dev_err(phy->dev, "poll timeout SATA_PHY_TX_IMCAL_STAT\n");
+		return ret;
+	}
+
+	/* RX Calibration */
+	ret = read_poll_timeout(base + SATA_PHY_RX_IMCAL_STAT, SATA_PHY_RX_CAL);
+	if (ret) {
+		dev_err(phy->dev, "poll timeout SATA_PHY_RX_IMCAL_STAT\n");
+		return ret;
+	}
+
+	/* SATA phy calibrated succesfully, power up to functional mode */
+	writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
+	writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
+	writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
+
+	writel_relaxed(0x00, base + SATA_PHY_POW_DWN_CTRL1);
+	writel_relaxed(0x59, base + SATA_PHY_CDR_CTRL0);
+	writel_relaxed(0x04, base + SATA_PHY_CDR_CTRL1);
+	writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL2);
+	writel_relaxed(0x00, base + SATA_PHY_PI_CTRL0);
+	writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL3);
+	writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
+
+	writel_relaxed(0x11, base + SATA_PHY_TX_DATA_CTRL);
+	writel_relaxed(0x43, base + SATA_PHY_ALIGNP);
+	writel_relaxed(0x04, base + SATA_PHY_OOB_TERM);
+
+	writel_relaxed(0x01, base + SATA_PHY_EQUAL);
+	writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL0);
+	writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL1);
+
+	return 0;
+}
+
+static int qcom_apq8064_sata_phy_exit(struct phy *generic_phy)
+{
+	struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
+	void __iomem *base = phy->mmio;
+
+	/* Power down PHY */
+	writel_relaxed(0xF8, base + SATA_PHY_POW_DWN_CTRL0);
+	writel_relaxed(0xFE, base + SATA_PHY_POW_DWN_CTRL1);
+
+	/* Power down PLL block */
+	writel_relaxed(0x00, base + UNIPHY_PLL_GLB_CFG);
+
+	return 0;
+}
+
+static struct phy_ops qcom_apq8064_sata_phy_ops = {
+	.init		= qcom_apq8064_sata_phy_init,
+	.exit		= qcom_apq8064_sata_phy_exit,
+	.owner		= THIS_MODULE,
+};
+
+static int qcom_apq8064_sata_phy_probe(struct platform_device *pdev)
+{
+	struct qcom_apq8064_sata_phy *phy;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct phy_provider *phy_provider;
+	struct phy *generic_phy;
+	int ret;
+
+	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	phy->mmio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(phy->mmio))
+		return PTR_ERR(phy->mmio);
+
+	generic_phy = devm_phy_create(dev, NULL, &qcom_apq8064_sata_phy_ops,
+				      NULL);
+	if (IS_ERR(generic_phy)) {
+		dev_err(dev, "%s: failed to create phy\n", __func__);
+		return PTR_ERR(generic_phy);
+	}
+
+	phy->dev = dev;
+	phy_set_drvdata(generic_phy, phy);
+	platform_set_drvdata(pdev, phy);
+
+	phy->cfg_clk = devm_clk_get(dev, "cfg");
+	if (IS_ERR(phy->cfg_clk)) {
+		dev_err(dev, "Failed to get sata cfg clock\n");
+		return PTR_ERR(phy->cfg_clk);
+	}
+
+	ret = clk_prepare_enable(phy->cfg_clk);
+	if (ret)
+		return ret;
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider)) {
+		clk_disable_unprepare(phy->cfg_clk);
+		dev_err(dev, "%s: failed to register phy\n", __func__);
+		return PTR_ERR(phy_provider);
+	}
+
+	return 0;
+}
+
+static int qcom_apq8064_sata_phy_remove(struct platform_device *pdev)
+{
+	struct qcom_apq8064_sata_phy *phy = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(phy->cfg_clk);
+
+	return 0;
+}
+
+static const struct of_device_id qcom_apq8064_sata_phy_of_match[] = {
+	{ .compatible = "qcom,apq8064-sata-phy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, qcom_apq8064_sata_phy_of_match);
+
+static struct platform_driver qcom_apq8064_sata_phy_driver = {
+	.probe	= qcom_apq8064_sata_phy_probe,
+	.remove	= qcom_apq8064_sata_phy_remove,
+	.driver = {
+		.name	= "qcom-apq8064-sata-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table	= qcom_apq8064_sata_phy_of_match,
+	}
+};
+module_platform_driver(qcom_apq8064_sata_phy_driver);
+
+MODULE_DESCRIPTION("QCOM apq8064 SATA PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-qcom-ipq806x-sata.c b/drivers/phy/phy-qcom-ipq806x-sata.c
new file mode 100644
index 000000000000..909b5a87fc6a
--- /dev/null
+++ b/drivers/phy/phy-qcom-ipq806x-sata.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+struct qcom_ipq806x_sata_phy {
+	void __iomem *mmio;
+	struct clk *cfg_clk;
+	struct device *dev;
+};
+
+#define __set(v, a, b)	(((v) << (b)) & GENMASK(a, b))
+
+#define SATA_PHY_P0_PARAM0		0x200
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(x)	__set(x, 17, 12)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK	GENMASK(17, 12)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2(x)	__set(x, 11, 6)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK	GENMASK(11, 6)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1(x)	__set(x, 5, 0)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK	GENMASK(5, 0)
+
+#define SATA_PHY_P0_PARAM1		0x204
+#define SATA_PHY_P0_PARAM1_RESERVED_BITS31_21(x)	__set(x, 31, 21)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(x)	__set(x, 20, 14)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK	GENMASK(20, 14)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(x)	__set(x, 13, 7)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK	GENMASK(13, 7)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(x)	__set(x, 6, 0)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK	GENMASK(6, 0)
+
+#define SATA_PHY_P0_PARAM2		0x208
+#define SATA_PHY_P0_PARAM2_RX_EQ(x)	__set(x, 20, 18)
+#define SATA_PHY_P0_PARAM2_RX_EQ_MASK	GENMASK(20, 18)
+
+#define SATA_PHY_P0_PARAM3		0x20C
+#define SATA_PHY_SSC_EN			0x8
+#define SATA_PHY_P0_PARAM4		0x210
+#define SATA_PHY_REF_SSP_EN		0x2
+#define SATA_PHY_RESET			0x1
+
+static int qcom_ipq806x_sata_phy_init(struct phy *generic_phy)
+{
+	struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy);
+	u32 reg;
+
+	/* Setting SSC_EN to 1 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM3);
+	reg = reg | SATA_PHY_SSC_EN;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM3);
+
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM0) &
+			~(SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK |
+			  SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK |
+			  SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK);
+	reg |= SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(0xf);
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM0);
+
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM1) &
+			~(SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK |
+			  SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK |
+			  SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK);
+	reg |= SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(0x55) |
+		SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(0x55) |
+		SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(0x55);
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM1);
+
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM2) &
+		~SATA_PHY_P0_PARAM2_RX_EQ_MASK;
+	reg |= SATA_PHY_P0_PARAM2_RX_EQ(0x3);
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM2);
+
+	/* Setting PHY_RESET to 1 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+	reg = reg | SATA_PHY_RESET;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+	/* Setting REF_SSP_EN to 1 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+	reg = reg | SATA_PHY_REF_SSP_EN | SATA_PHY_RESET;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+	/* make sure all changes complete before we let the PHY out of reset */
+	mb();
+
+	/* sleep for max. 50us more to combine processor wakeups */
+	usleep_range(20, 20 + 50);
+
+	/* Clearing PHY_RESET to 0 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+	reg = reg & ~SATA_PHY_RESET;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+	return 0;
+}
+
+static int qcom_ipq806x_sata_phy_exit(struct phy *generic_phy)
+{
+	struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy);
+	u32 reg;
+
+	/* Setting PHY_RESET to 1 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+	reg = reg | SATA_PHY_RESET;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+	return 0;
+}
+
+static struct phy_ops qcom_ipq806x_sata_phy_ops = {
+	.init		= qcom_ipq806x_sata_phy_init,
+	.exit		= qcom_ipq806x_sata_phy_exit,
+	.owner		= THIS_MODULE,
+};
+
+static int qcom_ipq806x_sata_phy_probe(struct platform_device *pdev)
+{
+	struct qcom_ipq806x_sata_phy *phy;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct phy_provider *phy_provider;
+	struct phy *generic_phy;
+	int ret;
+
+	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	phy->mmio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(phy->mmio))
+		return PTR_ERR(phy->mmio);
+
+	generic_phy = devm_phy_create(dev, NULL, &qcom_ipq806x_sata_phy_ops,
+				      NULL);
+	if (IS_ERR(generic_phy)) {
+		dev_err(dev, "%s: failed to create phy\n", __func__);
+		return PTR_ERR(generic_phy);
+	}
+
+	phy->dev = dev;
+	phy_set_drvdata(generic_phy, phy);
+	platform_set_drvdata(pdev, phy);
+
+	phy->cfg_clk = devm_clk_get(dev, "cfg");
+	if (IS_ERR(phy->cfg_clk)) {
+		dev_err(dev, "Failed to get sata cfg clock\n");
+		return PTR_ERR(phy->cfg_clk);
+	}
+
+	ret = clk_prepare_enable(phy->cfg_clk);
+	if (ret)
+		return ret;
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider)) {
+		clk_disable_unprepare(phy->cfg_clk);
+		dev_err(dev, "%s: failed to register phy\n", __func__);
+		return PTR_ERR(phy_provider);
+	}
+
+	return 0;
+}
+
+static int qcom_ipq806x_sata_phy_remove(struct platform_device *pdev)
+{
+	struct qcom_ipq806x_sata_phy *phy = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(phy->cfg_clk);
+
+	return 0;
+}
+
+static const struct of_device_id qcom_ipq806x_sata_phy_of_match[] = {
+	{ .compatible = "qcom,ipq806x-sata-phy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, qcom_ipq806x_sata_phy_of_match);
+
+static struct platform_driver qcom_ipq806x_sata_phy_driver = {
+	.probe	= qcom_ipq806x_sata_phy_probe,
+	.remove	= qcom_ipq806x_sata_phy_remove,
+	.driver = {
+		.name	= "qcom-ipq806x-sata-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table	= qcom_ipq806x_sata_phy_of_match,
+	}
+};
+module_platform_driver(qcom_ipq806x_sata_phy_driver);
+
+MODULE_DESCRIPTION("QCOM IPQ806x SATA PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c
index 1e69a32c221d..ae30640a411d 100644
--- a/drivers/phy/phy-samsung-usb2.c
+++ b/drivers/phy/phy-samsung-usb2.c
@@ -87,6 +87,12 @@ static struct phy *samsung_usb2_phy_xlate(struct device *dev,
 }
 
 static const struct of_device_id samsung_usb2_phy_of_match[] = {
+#ifdef CONFIG_PHY_EXYNOS4X12_USB2
+	{
+		.compatible = "samsung,exynos3250-usb2-phy",
+		.data = &exynos3250_usb2_phy_config,
+	},
+#endif
 #ifdef CONFIG_PHY_EXYNOS4210_USB2
 	{
 		.compatible = "samsung,exynos4210-usb2-phy",
@@ -190,7 +196,8 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev)
 		struct samsung_usb2_phy_instance *p = &drv->instances[i];
 
 		dev_dbg(dev, "Creating phy \"%s\"\n", label);
-		p->phy = devm_phy_create(dev, &samsung_usb2_phy_ops, NULL);
+		p->phy = devm_phy_create(dev, NULL, &samsung_usb2_phy_ops,
+					 NULL);
 		if (IS_ERR(p->phy)) {
 			dev_err(drv->dev, "Failed to create usb2_phy \"%s\"\n",
 				label);
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h
index 45b3170652bd..b03da0ef39ac 100644
--- a/drivers/phy/phy-samsung-usb2.h
+++ b/drivers/phy/phy-samsung-usb2.h
@@ -29,7 +29,8 @@ struct samsung_usb2_phy_instance {
 	const struct samsung_usb2_common_phy *cfg;
 	struct phy *phy;
 	struct samsung_usb2_phy_driver *drv;
-	bool enabled;
+	int int_cnt;
+	int ext_cnt;
 };
 
 struct samsung_usb2_phy_driver {
@@ -59,8 +60,10 @@ struct samsung_usb2_phy_config {
 	int (*rate_to_clk)(unsigned long, u32 *);
 	unsigned int num_phys;
 	bool has_mode_switch;
+	bool has_refclk_sel;
 };
 
+extern const struct samsung_usb2_phy_config exynos3250_usb2_phy_config;
 extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config;
 extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config;
 extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config;
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index 115d8d5190d5..61ebea49709b 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -22,6 +22,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -294,7 +295,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 				return PTR_ERR(phy->pmu);
 		}
 
-		phy->phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL);
+		phy->phy = devm_phy_create(dev, NULL, &sun4i_usb_phy_ops, NULL);
 		if (IS_ERR(phy->phy)) {
 			dev_err(dev, "failed to create PHY %d\n", i);
 			return PTR_ERR(phy->phy);
@@ -306,10 +307,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 
 	dev_set_drvdata(dev, data);
 	phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(phy_provider);
 }
 
 static const struct of_device_id sun4i_usb_phy_of_match[] = {
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
index 591367654613..b964aa967b46 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -80,7 +80,9 @@ struct ti_pipe3 {
 	struct clk		*wkupclk;
 	struct clk		*sys_clk;
 	struct clk		*refclk;
+	struct clk		*div_clk;
 	struct pipe3_dpll_map	*dpll_map;
+	u8			id;
 };
 
 static struct pipe3_dpll_map dpll_map_usb[] = {
@@ -215,6 +217,11 @@ static int ti_pipe3_init(struct phy *x)
 	u32 val;
 	int ret = 0;
 
+	if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) {
+		omap_control_pcie_pcs(phy->control_dev, phy->id, 0xF1);
+		return 0;
+	}
+
 	/* Bring it out of IDLE if it is IDLE */
 	val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
 	if (val & PLL_IDLE) {
@@ -238,8 +245,11 @@ static int ti_pipe3_exit(struct phy *x)
 	u32 val;
 	unsigned long timeout;
 
-	/* SATA DPLL can't be powered down due to Errata i783 */
-	if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata"))
+	/* SATA DPLL can't be powered down due to Errata i783 and PCIe
+	 * does not have internal DPLL
+	 */
+	if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") ||
+	    of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie"))
 		return 0;
 
 	/* Put DPLL in IDLE mode */
@@ -286,32 +296,41 @@ static int ti_pipe3_probe(struct platform_device *pdev)
 	struct device_node *control_node;
 	struct platform_device *control_pdev;
 	const struct of_device_id *match;
-
-	match = of_match_device(of_match_ptr(ti_pipe3_id_table), &pdev->dev);
-	if (!match)
-		return -EINVAL;
+	struct clk *clk;
 
 	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
 	if (!phy) {
 		dev_err(&pdev->dev, "unable to alloc mem for TI PIPE3 PHY\n");
 		return -ENOMEM;
 	}
+	phy->dev		= &pdev->dev;
 
-	phy->dpll_map = (struct pipe3_dpll_map *)match->data;
-	if (!phy->dpll_map) {
-		dev_err(&pdev->dev, "no DPLL data\n");
-		return -EINVAL;
-	}
+	if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
+		match = of_match_device(of_match_ptr(ti_pipe3_id_table),
+					&pdev->dev);
+		if (!match)
+			return -EINVAL;
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl");
-	phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(phy->pll_ctrl_base))
-		return PTR_ERR(phy->pll_ctrl_base);
+		phy->dpll_map = (struct pipe3_dpll_map *)match->data;
+		if (!phy->dpll_map) {
+			dev_err(&pdev->dev, "no DPLL data\n");
+			return -EINVAL;
+		}
 
-	phy->dev		= &pdev->dev;
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						   "pll_ctrl");
+		phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(phy->pll_ctrl_base))
+			return PTR_ERR(phy->pll_ctrl_base);
 
-	if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
+		phy->sys_clk = devm_clk_get(phy->dev, "sysclk");
+		if (IS_ERR(phy->sys_clk)) {
+			dev_err(&pdev->dev, "unable to get sysclk\n");
+			return -EINVAL;
+		}
+	}
 
+	if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
 		phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
 		if (IS_ERR(phy->wkupclk)) {
 			dev_err(&pdev->dev, "unable to get wkupclk\n");
@@ -328,10 +347,38 @@ static int ti_pipe3_probe(struct platform_device *pdev)
 		phy->refclk = ERR_PTR(-ENODEV);
 	}
 
-	phy->sys_clk = devm_clk_get(phy->dev, "sysclk");
-	if (IS_ERR(phy->sys_clk)) {
-		dev_err(&pdev->dev, "unable to get sysclk\n");
-		return -EINVAL;
+	if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
+		if (of_property_read_u8(node, "id", &phy->id) < 0)
+			phy->id = 1;
+
+		clk = devm_clk_get(phy->dev, "dpll_ref");
+		if (IS_ERR(clk)) {
+			dev_err(&pdev->dev, "unable to get dpll ref clk\n");
+			return PTR_ERR(clk);
+		}
+		clk_set_rate(clk, 1500000000);
+
+		clk = devm_clk_get(phy->dev, "dpll_ref_m2");
+		if (IS_ERR(clk)) {
+			dev_err(&pdev->dev, "unable to get dpll ref m2 clk\n");
+			return PTR_ERR(clk);
+		}
+		clk_set_rate(clk, 100000000);
+
+		clk = devm_clk_get(phy->dev, "phy-div");
+		if (IS_ERR(clk)) {
+			dev_err(&pdev->dev, "unable to get phy-div clk\n");
+			return PTR_ERR(clk);
+		}
+		clk_set_rate(clk, 100000000);
+
+		phy->div_clk = devm_clk_get(phy->dev, "div-clk");
+		if (IS_ERR(phy->div_clk)) {
+			dev_err(&pdev->dev, "unable to get div-clk\n");
+			return PTR_ERR(phy->div_clk);
+		}
+	} else {
+		phy->div_clk = ERR_PTR(-ENODEV);
 	}
 
 	control_node = of_parse_phandle(node, "ctrl-module", 0);
@@ -353,7 +400,7 @@ static int ti_pipe3_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, phy);
 	pm_runtime_enable(phy->dev);
 
-	generic_phy = devm_phy_create(phy->dev, &ops, NULL);
+	generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL);
 	if (IS_ERR(generic_phy))
 		return PTR_ERR(generic_phy);
 
@@ -387,6 +434,8 @@ static int ti_pipe3_runtime_suspend(struct device *dev)
 		clk_disable_unprepare(phy->wkupclk);
 	if (!IS_ERR(phy->refclk))
 		clk_disable_unprepare(phy->refclk);
+	if (!IS_ERR(phy->div_clk))
+		clk_disable_unprepare(phy->div_clk);
 
 	return 0;
 }
@@ -412,8 +461,19 @@ static int ti_pipe3_runtime_resume(struct device *dev)
 		}
 	}
 
+	if (!IS_ERR(phy->div_clk)) {
+		ret = clk_prepare_enable(phy->div_clk);
+		if (ret) {
+			dev_err(phy->dev, "Failed to enable div_clk %d\n", ret);
+			goto err3;
+		}
+	}
 	return 0;
 
+err3:
+	if (!IS_ERR(phy->wkupclk))
+		clk_disable_unprepare(phy->wkupclk);
+
 err2:
 	if (!IS_ERR(phy->refclk))
 		clk_disable_unprepare(phy->refclk);
@@ -446,6 +506,9 @@ static const struct of_device_id ti_pipe3_id_table[] = {
 		.compatible = "ti,phy-pipe3-sata",
 		.data = dpll_map_sata,
 	},
+	{
+		.compatible = "ti,phy-pipe3-pcie",
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);
diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c
index 2e0e9b3774c8..e1a6623d4696 100644
--- a/drivers/phy/phy-twl4030-usb.c
+++ b/drivers/phy/phy-twl4030-usb.c
@@ -695,7 +695,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
 	otg->set_host		= twl4030_set_host;
 	otg->set_peripheral	= twl4030_set_peripheral;
 
-	phy = devm_phy_create(twl->dev, &ops, init_data);
+	phy = devm_phy_create(twl->dev, NULL, &ops, init_data);
 	if (IS_ERR(phy)) {
 		dev_dbg(&pdev->dev, "Failed to create PHY\n");
 		return PTR_ERR(phy);
diff --git a/drivers/phy/phy-xgene.c b/drivers/phy/phy-xgene.c
index 4aa1ccd1511f..db809b97219e 100644
--- a/drivers/phy/phy-xgene.c
+++ b/drivers/phy/phy-xgene.c
@@ -1707,7 +1707,7 @@ static int xgene_phy_probe(struct platform_device *pdev)
 	ctx->dev = &pdev->dev;
 	platform_set_drvdata(pdev, ctx);
 
-	ctx->phy = devm_phy_create(ctx->dev, &xgene_phy_ops, NULL);
+	ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops, NULL);
 	if (IS_ERR(ctx->phy)) {
 		dev_dbg(&pdev->dev, "Failed to create PHY\n");
 		rc = PTR_ERR(ctx->phy);
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 2e58f8dfd311..65444b02bd68 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -133,6 +133,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 	data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0);
 	if (IS_ERR(data->phy)) {
 		ret = PTR_ERR(data->phy);
+		/* Return -EINVAL if no usbphy is available */
+		if (ret == -ENODEV)
+			ret = -EINVAL;
 		goto err_clk;
 	}
 
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index 7cccab6ff308..795d6538d630 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -208,7 +208,7 @@ static const struct file_operations ci_requests_fops = {
 	.release	= single_release,
 };
 
-int ci_otg_show(struct seq_file *s, void *unused)
+static int ci_otg_show(struct seq_file *s, void *unused)
 {
 	struct ci_hdrc *ci = s->private;
 	struct otg_fsm *fsm;
@@ -331,7 +331,7 @@ static const struct file_operations ci_role_fops = {
 	.release	= single_release,
 };
 
-int ci_registers_show(struct seq_file *s, void *unused)
+static int ci_registers_show(struct seq_file *s, void *unused)
 {
 	struct ci_hdrc *ci = s->private;
 	u32 tmp_reg;
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 103a6e9ee49d..ec978408a2ee 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -715,7 +715,7 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data)
 	u8 *buffer;
 	int rv;
 	int n;
-	int actual;
+	int actual = 0;
 	int max_size;
 
 	dev = &data->intf->dev;
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 1ab4df1de2da..b2a540b43f97 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -199,6 +199,17 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
 			if (n == 0)
 				n = 9;	/* 32 ms = 2^(9-1) uframes */
 			j = 16;
+
+			/*
+			 * Adjust bInterval for quirked devices.
+			 * This quirk fixes bIntervals reported in
+			 * linear microframes.
+			 */
+			if (to_usb_device(ddev)->quirks &
+				USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL) {
+				n = clamp(fls(d->bInterval), i, j);
+				i = j = n;
+			}
 			break;
 		default:		/* USB_SPEED_FULL or _LOW */
 			/* For low-speed, 10 ms is the official minimum.
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 257876ea03a1..0b59731c3021 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1509,7 +1509,7 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
 	u = (is_in ? URB_DIR_IN : URB_DIR_OUT);
 	if (uurb->flags & USBDEVFS_URB_ISO_ASAP)
 		u |= URB_ISO_ASAP;
-	if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK)
+	if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK && is_in)
 		u |= URB_SHORT_NOT_OK;
 	if (uurb->flags & USBDEVFS_URB_NO_FSBR)
 		u |= URB_NO_FSBR;
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 4aeb10034de7..9bffd26cea05 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -417,10 +417,11 @@ static int usb_unbind_interface(struct device *dev)
 	 */
 	lpm_disable_error = usb_unlocked_disable_lpm(udev);
 
-	/* Terminate all URBs for this interface unless the driver
-	 * supports "soft" unbinding.
+	/*
+	 * Terminate all URBs for this interface unless the driver
+	 * supports "soft" unbinding and the device is still present.
 	 */
-	if (!driver->soft_unbind)
+	if (!driver->soft_unbind || udev->state == USB_STATE_NOTATTACHED)
 		usb_disable_interface(udev, intf, false);
 
 	driver->disconnect(intf);
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 82044b5d6113..efc953119ce2 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -380,6 +380,8 @@ void usb_hcd_pci_shutdown(struct pci_dev *dev)
 	if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) &&
 			hcd->driver->shutdown) {
 		hcd->driver->shutdown(hcd);
+		if (usb_hcd_is_primary_hcd(hcd) && hcd->irq > 0)
+			free_irq(hcd->irq, hcd);
 		pci_disable_device(dev);
 	}
 }
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index bec31e2efb88..487abcfcccd8 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -855,8 +855,6 @@ static ssize_t authorized_default_show(struct device *dev,
 	struct usb_bus *usb_bus = rh_usb_dev->bus;
 	struct usb_hcd *usb_hcd;
 
-	if (usb_bus == NULL)	/* FIXME: not sure if this case is possible */
-		return -ENODEV;
 	usb_hcd = bus_to_hcd(usb_bus);
 	return snprintf(buf, PAGE_SIZE, "%u\n", usb_hcd->authorized_default);
 }
@@ -871,8 +869,6 @@ static ssize_t authorized_default_store(struct device *dev,
 	struct usb_bus *usb_bus = rh_usb_dev->bus;
 	struct usb_hcd *usb_hcd;
 
-	if (usb_bus == NULL)	/* FIXME: not sure if this case is possible */
-		return -ENODEV;
 	usb_hcd = bus_to_hcd(usb_bus);
 	result = sscanf(buf, "%u\n", &val);
 	if (result == 1) {
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 0e950ad8cb25..8a4dcbc7a75f 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2606,13 +2606,20 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
 /* Is a USB 3.0 port in the Inactive or Compliance Mode state?
  * Port worm reset is required to recover
  */
-static bool hub_port_warm_reset_required(struct usb_hub *hub, u16 portstatus)
+static bool hub_port_warm_reset_required(struct usb_hub *hub, int port1,
+		u16 portstatus)
 {
-	return hub_is_superspeed(hub->hdev) &&
-		(((portstatus & USB_PORT_STAT_LINK_STATE) ==
-		  USB_SS_PORT_LS_SS_INACTIVE) ||
-		 ((portstatus & USB_PORT_STAT_LINK_STATE) ==
-		  USB_SS_PORT_LS_COMP_MOD)) ;
+	u16 link_state;
+
+	if (!hub_is_superspeed(hub->hdev))
+		return false;
+
+	if (test_bit(port1, hub->warm_reset_bits))
+		return true;
+
+	link_state = portstatus & USB_PORT_STAT_LINK_STATE;
+	return link_state == USB_SS_PORT_LS_SS_INACTIVE
+		|| link_state == USB_SS_PORT_LS_COMP_MOD;
 }
 
 static int hub_port_wait_reset(struct usb_hub *hub, int port1,
@@ -2649,7 +2656,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
 	if ((portstatus & USB_PORT_STAT_RESET))
 		return -EBUSY;
 
-	if (hub_port_warm_reset_required(hub, portstatus))
+	if (hub_port_warm_reset_required(hub, port1, portstatus))
 		return -ENOTCONN;
 
 	/* Device went away? */
@@ -2749,9 +2756,10 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
 		if (status < 0)
 			goto done;
 
-		if (hub_port_warm_reset_required(hub, portstatus))
+		if (hub_port_warm_reset_required(hub, port1, portstatus))
 			warm = true;
 	}
+	clear_bit(port1, hub->warm_reset_bits);
 
 	/* Reset the port */
 	for (i = 0; i < PORT_RESET_TRIES; i++) {
@@ -2788,7 +2796,8 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
 					&portstatus, &portchange) < 0)
 				goto done;
 
-			if (!hub_port_warm_reset_required(hub, portstatus))
+			if (!hub_port_warm_reset_required(hub, port1,
+					portstatus))
 				goto done;
 
 			/*
@@ -2875,8 +2884,13 @@ static int check_port_resume_type(struct usb_device *udev,
 {
 	struct usb_port *port_dev = hub->ports[port1 - 1];
 
+	/* Is a warm reset needed to recover the connection? */
+	if (status == 0 && udev->reset_resume
+		&& hub_port_warm_reset_required(hub, port1, portstatus)) {
+		/* pass */;
+	}
 	/* Is the device still present? */
-	if (status || port_is_suspended(hub, portstatus) ||
+	else if (status || port_is_suspended(hub, portstatus) ||
 			!port_is_power_on(hub, portstatus) ||
 			!(portstatus & USB_PORT_STAT_CONNECTION)) {
 		if (status >= 0)
@@ -3264,6 +3278,43 @@ static int finish_port_resume(struct usb_device *udev)
 }
 
 /*
+ * There are some SS USB devices which take longer time for link training.
+ * XHCI specs 4.19.4 says that when Link training is successful, port
+ * sets CSC bit to 1. So if SW reads port status before successful link
+ * training, then it will not find device to be present.
+ * USB Analyzer log with such buggy devices show that in some cases
+ * device switch on the RX termination after long delay of host enabling
+ * the VBUS. In few other cases it has been seen that device fails to
+ * negotiate link training in first attempt. It has been
+ * reported till now that few devices take as long as 2000 ms to train
+ * the link after host enabling its VBUS and termination. Following
+ * routine implements a 2000 ms timeout for link training. If in a case
+ * link trains before timeout, loop will exit earlier.
+ *
+ * FIXME: If a device was connected before suspend, but was removed
+ * while system was asleep, then the loop in the following routine will
+ * only exit at timeout.
+ *
+ * This routine should only be called when persist is enabled for a SS
+ * device.
+ */
+static int wait_for_ss_port_enable(struct usb_device *udev,
+		struct usb_hub *hub, int *port1,
+		u16 *portchange, u16 *portstatus)
+{
+	int status = 0, delay_ms = 0;
+
+	while (delay_ms < 2000) {
+		if (status || *portstatus & USB_PORT_STAT_CONNECTION)
+			break;
+		msleep(20);
+		delay_ms += 20;
+		status = hub_port_status(hub, *port1, portstatus, portchange);
+	}
+	return status;
+}
+
+/*
  * usb_port_resume - re-activate a suspended usb device's upstream port
  * @udev: device to re-activate, not a root hub
  * Context: must be able to sleep; device not locked; pm locks held
@@ -3359,6 +3410,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
 		}
 	}
 
+	if (udev->persist_enabled && hub_is_superspeed(hub->hdev))
+		status = wait_for_ss_port_enable(udev, hub, &port1, &portchange,
+				&portstatus);
+
 	status = check_port_resume_type(udev,
 			hub, port1, status, portchange, portstatus);
 	if (status == 0)
@@ -3879,7 +3934,8 @@ int usb_disable_lpm(struct usb_device *udev)
 
 	if (!udev || !udev->parent ||
 			udev->speed != USB_SPEED_SUPER ||
-			!udev->lpm_capable)
+			!udev->lpm_capable ||
+			udev->state < USB_STATE_DEFAULT)
 		return 0;
 
 	hcd = bus_to_hcd(udev->bus);
@@ -3935,7 +3991,8 @@ void usb_enable_lpm(struct usb_device *udev)
 
 	if (!udev || !udev->parent ||
 			udev->speed != USB_SPEED_SUPER ||
-			!udev->lpm_capable)
+			!udev->lpm_capable ||
+			udev->state < USB_STATE_DEFAULT)
 		return;
 
 	udev->lpm_disable_count--;
@@ -4550,6 +4607,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
 	struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
 	struct usb_port *port_dev = hub->ports[port1 - 1];
 	struct usb_device *udev = port_dev->child;
+	static int unreliable_port = -1;
 
 	/* Disconnect any existing devices under this port */
 	if (udev) {
@@ -4570,10 +4628,14 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
 				USB_PORT_STAT_C_ENABLE)) {
 		status = hub_port_debounce_be_stable(hub, port1);
 		if (status < 0) {
-			if (status != -ENODEV && printk_ratelimit())
-				dev_err(&port_dev->dev,
-						"connect-debounce failed\n");
+			if (status != -ENODEV &&
+				port1 != unreliable_port &&
+				printk_ratelimit())
+				dev_err(&udev->dev, "connect-debounce failed, port %d disabled\n",
+					port1);
+
 			portstatus &= ~USB_PORT_STAT_CONNECTION;
+			unreliable_port = port1;
 		} else {
 			portstatus = status;
 		}
@@ -4889,7 +4951,7 @@ static void port_event(struct usb_hub *hub, int port1)
 	 * Warm reset a USB3 protocol port if it's in
 	 * SS.Inactive state.
 	 */
-	if (hub_port_warm_reset_required(hub, portstatus)) {
+	if (hub_port_warm_reset_required(hub, port1, portstatus)) {
 		dev_dbg(&port_dev->dev, "do warm reset\n");
 		if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION)
 				|| udev->state == USB_STATE_NOTATTACHED) {
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 326308e53961..c77d8778af4b 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -52,6 +52,8 @@ struct usb_hub {
 	unsigned long		power_bits[1]; /* ports that are powered */
 	unsigned long		child_usage_bits[1]; /* ports powered on for
 							children */
+	unsigned long		warm_reset_bits[1]; /* ports requesting warm
+							reset recovery */
 #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
 #error event_bits[] is too short!
 #endif
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index fe1b6d0967e3..cd3f9dc24a06 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -103,16 +103,19 @@ static int usb_port_runtime_resume(struct device *dev)
 	msleep(hub_power_on_good_delay(hub));
 	if (udev && !retval) {
 		/*
-		 * Attempt to wait for usb hub port to be reconnected in order
-		 * to make the resume procedure successful.  The device may have
-		 * disconnected while the port was powered off, so ignore the
-		 * return status.
+		 * Our preference is to simply wait for the port to reconnect,
+		 * as that is the lowest latency method to restart the port.
+		 * However, there are cases where toggling port power results in
+		 * the host port and the device port getting out of sync causing
+		 * a link training live lock.  Upon timeout, flag the port as
+		 * needing warm reset recovery (to be performed later by
+		 * usb_port_resume() as requested via usb_wakeup_notification())
 		 */
-		retval = hub_port_debounce_be_connected(hub, port1);
-		if (retval < 0)
-			dev_dbg(&port_dev->dev, "can't get reconnection after setting port  power on, status %d\n",
-					retval);
-		retval = 0;
+		if (hub_port_debounce_be_connected(hub, port1) < 0) {
+			dev_dbg(&port_dev->dev, "reconnect timeout\n");
+			if (hub_is_superspeed(hdev))
+				set_bit(port1, hub->warm_reset_bits);
+		}
 
 		/* Force the child awake to revalidate after the power loss. */
 		if (!test_and_set_bit(port1, hub->child_usage_bits)) {
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 739ee8e8bdfd..bae636e2a1a3 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -145,6 +145,10 @@ static const struct usb_device_id usb_quirk_list[] = {
 	/* SKYMEDI USB_DRIVE */
 	{ USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* Razer - Razer Blade Keyboard */
+	{ USB_DEVICE(0x1532, 0x0116), .driver_info =
+			USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
+
 	/* BUILDWIN Photo Frame */
 	{ USB_DEVICE(0x1908, 0x1315), .driver_info =
 			USB_QUIRK_HONOR_BNUMINTERFACES },
@@ -152,6 +156,9 @@ static const struct usb_device_id usb_quirk_list[] = {
 	/* INTEL VALUE SSD */
 	{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* USB3503 */
+	{ USB_DEVICE(0x0424, 0x3503), .driver_info = USB_QUIRK_RESET_RESUME },
+
 	{ }  /* terminating entry must be last */
 };
 
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 991386ceb4ec..c9e8ee81b6b7 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -454,6 +454,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 			URB_FREE_BUFFER);
 	switch (xfertype) {
 	case USB_ENDPOINT_XFER_BULK:
+	case USB_ENDPOINT_XFER_INT:
 		if (is_out)
 			allowed |= URB_ZERO_PACKET;
 		/* FALLTHROUGH */
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 4d1144990d4c..2dd2362198d2 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -501,6 +501,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
 	}
 	return dev;
 }
+EXPORT_SYMBOL_GPL(usb_alloc_dev);
 
 /**
  * usb_get_dev - increments the reference count of the usb device structure
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index f3c56a2fed5b..0ba9c335b584 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -1,6 +1,4 @@
 /**
- * linux/drivers/usb/gadget/s3c-hsotg.c
- *
  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  *
@@ -1022,7 +1020,8 @@ static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg);
  *
  * Set stall for ep0 as response for setup request.
  */
-static void s3c_hsotg_stall_ep0(struct s3c_hsotg *hsotg) {
+static void s3c_hsotg_stall_ep0(struct s3c_hsotg *hsotg)
+{
 	struct s3c_hsotg_ep *ep0 = &hsotg->eps[0];
 	u32 reg;
 	u32 ctrl;
@@ -1994,7 +1993,7 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
 		s3c_hsotg_complete_request(hsotg, ep, req,
 					   result);
 	}
-	if(hsotg->dedicated_fifos)
+	if (hsotg->dedicated_fifos)
 		if ((readl(hsotg->regs + DTXFSTS(ep->index)) & 0xffff) * 4 < 3072)
 			s3c_hsotg_txfifo_flush(hsotg, ep->index);
 }
@@ -3390,10 +3389,8 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 	int i;
 
 	hsotg = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsotg), GFP_KERNEL);
-	if (!hsotg) {
-		dev_err(dev, "cannot get memory\n");
+	if (!hsotg)
 		return -ENOMEM;
-	}
 
 	/*
 	 * Attempt to find a generic PHY, then look for an old style
@@ -3512,7 +3509,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 	eps = kcalloc(hsotg->num_of_eps + 1, sizeof(struct s3c_hsotg_ep),
 		      GFP_KERNEL);
 	if (!eps) {
-		dev_err(dev, "cannot get memory\n");
 		ret = -ENOMEM;
 		goto err_supplies;
 	}
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 261c3b428220..785510a0a0c3 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -93,4 +93,11 @@ config USB_DWC3_VERBOSE
 	help
 	  Say Y here to enable verbose debugging messages on DWC3 Driver.
 
+config DWC3_HOST_USB3_LPM_ENABLE
+	bool "Enable USB3 LPM Capability"
+	depends on USB_DWC3_HOST=y || USB_DWC3_DUAL_ROLE=y
+	default n
+	help
+	  Select this when you want to enable USB3 LPM with dwc3 xhci host.
+
 endif
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index eb69eb9f06c8..b769c1faaf03 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -386,6 +386,13 @@ static int dwc3_core_init(struct dwc3 *dwc)
 	}
 	dwc->revision = reg;
 
+	/* Handle USB2.0-only core configuration */
+	if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
+			DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
+		if (dwc->maximum_speed == USB_SPEED_SUPER)
+			dwc->maximum_speed = USB_SPEED_HIGH;
+	}
+
 	/* issue device SoftReset too */
 	timeout = jiffies + msecs_to_jiffies(500);
 	dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
@@ -656,6 +663,31 @@ static int dwc3_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
+	dwc->xhci_resources[0].start = res->start;
+	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
+					DWC3_XHCI_REGS_END;
+	dwc->xhci_resources[0].flags = res->flags;
+	dwc->xhci_resources[0].name = res->name;
+
+	res->start += DWC3_GLOBALS_REGS_START;
+
+	/*
+	 * Request memory region but exclude xHCI regs,
+	 * since it will be requested by the xhci-plat driver.
+	 */
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	dwc->regs	= regs;
+	dwc->regs_size	= resource_size(res);
+	/*
+	 * restore res->start back to its original value so that,
+	 * in case the probe is deferred, we don't end up getting error in
+	 * request the memory region the next time probe is called.
+	 */
+	res->start -= DWC3_GLOBALS_REGS_START;
+
 	if (node) {
 		dwc->maximum_speed = of_usb_get_maximum_speed(node);
 
@@ -676,28 +708,9 @@ static int dwc3_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	dwc->xhci_resources[0].start = res->start;
-	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
-					DWC3_XHCI_REGS_END;
-	dwc->xhci_resources[0].flags = res->flags;
-	dwc->xhci_resources[0].name = res->name;
-
-	res->start += DWC3_GLOBALS_REGS_START;
-
-	/*
-	 * Request memory region but exclude xHCI regs,
-	 * since it will be requested by the xhci-plat driver.
-	 */
-	regs = devm_ioremap_resource(dev, res);
-	if (IS_ERR(regs))
-		return PTR_ERR(regs);
-
 	spin_lock_init(&dwc->lock);
 	platform_set_drvdata(pdev, dwc);
 
-	dwc->regs	= regs;
-	dwc->regs_size	= resource_size(res);
-
 	dev->dma_mask	= dev->parent->dma_mask;
 	dev->dma_parms	= dev->parent->dma_parms;
 	dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 57332e3768e4..48fb264065db 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -191,6 +191,19 @@
 #define DWC3_GHWPARAMS1_PWROPT(n)	((n) << 24)
 #define DWC3_GHWPARAMS1_PWROPT_MASK	DWC3_GHWPARAMS1_PWROPT(3)
 
+/* Global HWPARAMS3 Register */
+#define DWC3_GHWPARAMS3_SSPHY_IFC(n)		((n) & 3)
+#define DWC3_GHWPARAMS3_SSPHY_IFC_DIS		0
+#define DWC3_GHWPARAMS3_SSPHY_IFC_ENA		1
+#define DWC3_GHWPARAMS3_HSPHY_IFC(n)		(((n) & (3 << 2)) >> 2)
+#define DWC3_GHWPARAMS3_HSPHY_IFC_DIS		0
+#define DWC3_GHWPARAMS3_HSPHY_IFC_UTMI		1
+#define DWC3_GHWPARAMS3_HSPHY_IFC_ULPI		2
+#define DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI	3
+#define DWC3_GHWPARAMS3_FSPHY_IFC(n)		(((n) & (3 << 4)) >> 4)
+#define DWC3_GHWPARAMS3_FSPHY_IFC_DIS		0
+#define DWC3_GHWPARAMS3_FSPHY_IFC_ENA		1
+
 /* Global HWPARAMS4 Register */
 #define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n)	(((n) & (0x0f << 13)) >> 13)
 #define DWC3_MAX_HIBER_SCRATCHBUFS		15
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index 07a736acd0f2..ef4936ff626c 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -77,10 +77,6 @@
 #define USBOTGSS_DEV_EBC_EN			0x0110
 #define USBOTGSS_DEBUG_OFFSET			0x0600
 
-/* REVISION REGISTER */
-#define USBOTGSS_REVISION_XMAJOR(reg)		((reg >> 8) & 0x7)
-#define USBOTGSS_REVISION_XMAJOR1		1
-#define USBOTGSS_REVISION_XMAJOR2		2
 /* SYSCONFIG REGISTER */
 #define USBOTGSS_SYSCONFIG_DMADISABLE		(1 << 16)
 
@@ -129,7 +125,6 @@ struct dwc3_omap {
 	u32			irq_eoi_offset;
 	u32			debug_offset;
 	u32			irq0_offset;
-	u32			revision;
 
 	u32			dma_status:1;
 
@@ -383,6 +378,87 @@ static int dwc3_omap_vbus_notifier(struct notifier_block *nb,
 	return NOTIFY_DONE;
 }
 
+static void dwc3_omap_map_offset(struct dwc3_omap *omap)
+{
+	struct device_node	*node = omap->dev->of_node;
+
+	/*
+	 * Differentiate between OMAP5 and AM437x.
+	 *
+	 * For OMAP5(ES2.0) and AM437x wrapper revision is same, even
+	 * though there are changes in wrapper register offsets.
+	 *
+	 * Using dt compatible to differentiate AM437x.
+	 */
+	if (of_device_is_compatible(node, "ti,am437x-dwc3")) {
+		omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
+		omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
+		omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
+		omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
+		omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
+	}
+}
+
+static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap)
+{
+	u32			reg;
+	struct device_node	*node = omap->dev->of_node;
+	int			utmi_mode = 0;
+
+	reg = dwc3_omap_read_utmi_status(omap);
+
+	of_property_read_u32(node, "utmi-mode", &utmi_mode);
+
+	switch (utmi_mode) {
+	case DWC3_OMAP_UTMI_MODE_SW:
+		reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+		break;
+	case DWC3_OMAP_UTMI_MODE_HW:
+		reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+		break;
+	default:
+		dev_dbg(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode);
+	}
+
+	dwc3_omap_write_utmi_status(omap, reg);
+}
+
+static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
+{
+	u32			ret;
+	struct device_node	*node = omap->dev->of_node;
+	struct extcon_dev	*edev;
+
+	if (of_property_read_bool(node, "extcon")) {
+		edev = extcon_get_edev_by_phandle(omap->dev, 0);
+		if (IS_ERR(edev)) {
+			dev_vdbg(omap->dev, "couldn't get extcon device\n");
+			return -EPROBE_DEFER;
+		}
+
+		omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
+		ret = extcon_register_interest(&omap->extcon_vbus_dev,
+					       edev->name, "USB",
+					       &omap->vbus_nb);
+		if (ret < 0)
+			dev_vdbg(omap->dev, "failed to register notifier for USB\n");
+
+		omap->id_nb.notifier_call = dwc3_omap_id_notifier;
+		ret = extcon_register_interest(&omap->extcon_id_dev,
+					       edev->name, "USB-HOST",
+					       &omap->id_nb);
+		if (ret < 0)
+			dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n");
+
+		if (extcon_get_cable_state(edev, "USB") == true)
+			dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
+		if (extcon_get_cable_state(edev, "USB-HOST") == true)
+			dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
+	}
+
+	return 0;
+}
+
 static int dwc3_omap_probe(struct platform_device *pdev)
 {
 	struct device_node	*node = pdev->dev.of_node;
@@ -390,15 +466,11 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 	struct dwc3_omap	*omap;
 	struct resource		*res;
 	struct device		*dev = &pdev->dev;
-	struct extcon_dev	*edev;
 	struct regulator	*vbus_reg = NULL;
 
 	int			ret;
 	int			irq;
 
-	int			utmi_mode = 0;
-	int			x_major;
-
 	u32			reg;
 
 	void __iomem		*base;
@@ -448,58 +520,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
-	reg = dwc3_omap_readl(omap->base, USBOTGSS_REVISION);
-	omap->revision = reg;
-	x_major = USBOTGSS_REVISION_XMAJOR(reg);
-
-	/* Differentiate between OMAP5 and AM437x */
-	switch (x_major) {
-	case USBOTGSS_REVISION_XMAJOR1:
-	case USBOTGSS_REVISION_XMAJOR2:
-		omap->irq_eoi_offset = 0;
-		omap->irq0_offset = 0;
-		omap->irqmisc_offset = 0;
-		omap->utmi_otg_offset = 0;
-		omap->debug_offset = 0;
-		break;
-	default:
-		/* Default to the latest revision */
-		omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
-		omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
-		omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
-		omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
-		omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
-		break;
-	}
-
-	/* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are
-	 * changes in wrapper registers, Using dt compatible for aegis
-	 */
-
-	if (of_device_is_compatible(node, "ti,am437x-dwc3")) {
-		omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
-		omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
-		omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
-		omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
-		omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
-	}
-
-	reg = dwc3_omap_read_utmi_status(omap);
-
-	of_property_read_u32(node, "utmi-mode", &utmi_mode);
-
-	switch (utmi_mode) {
-	case DWC3_OMAP_UTMI_MODE_SW:
-		reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
-		break;
-	case DWC3_OMAP_UTMI_MODE_HW:
-		reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
-		break;
-	default:
-		dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode);
-	}
-
-	dwc3_omap_write_utmi_status(omap, reg);
+	dwc3_omap_map_offset(omap);
+	dwc3_omap_set_utmi_mode(omap);
 
 	/* check the DMA Status */
 	reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
@@ -515,31 +537,9 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 
 	dwc3_omap_enable_irqs(omap);
 
-	if (of_property_read_bool(node, "extcon")) {
-		edev = extcon_get_edev_by_phandle(dev, 0);
-		if (IS_ERR(edev)) {
-			dev_vdbg(dev, "couldn't get extcon device\n");
-			ret = -EPROBE_DEFER;
-			goto err2;
-		}
-
-		omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
-		ret = extcon_register_interest(&omap->extcon_vbus_dev,
-			edev->name, "USB", &omap->vbus_nb);
-		if (ret < 0)
-			dev_vdbg(dev, "failed to register notifier for USB\n");
-		omap->id_nb.notifier_call = dwc3_omap_id_notifier;
-		ret = extcon_register_interest(&omap->extcon_id_dev, edev->name,
-					 "USB-HOST", &omap->id_nb);
-		if (ret < 0)
-			dev_vdbg(dev,
-				"failed to register notifier for USB-HOST\n");
-
-		if (extcon_get_cable_state(edev, "USB") == true)
-			dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
-		if (extcon_get_cable_state(edev, "USB-HOST") == true)
-			dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
-	}
+	ret = dwc3_omap_extcon_register(omap);
+	if (ret < 0)
+		goto err2;
 
 	ret = of_platform_populate(node, NULL, NULL, dev);
 	if (ret) {
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index dab7927d1009..349cacc577d8 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1971,8 +1971,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
 }
 
 static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
-		struct dwc3_ep *dep, const struct dwc3_event_depevt *event,
-		int start_new)
+		struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
 {
 	unsigned		status = 0;
 	int			clean_busy;
@@ -2039,7 +2038,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 			return;
 		}
 
-		dwc3_endpoint_transfer_complete(dwc, dep, event, 1);
+		dwc3_endpoint_transfer_complete(dwc, dep, event);
 		break;
 	case DWC3_DEPEVT_XFERINPROGRESS:
 		if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
@@ -2048,7 +2047,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 			return;
 		}
 
-		dwc3_endpoint_transfer_complete(dwc, dep, event, 0);
+		dwc3_endpoint_transfer_complete(dwc, dep, event);
 		break;
 	case DWC3_DEPEVT_XFERNOTREADY:
 		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index 32db328cc769..dcb8ca084598 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -16,12 +16,14 @@
  */
 
 #include <linux/platform_device.h>
+#include <linux/usb/xhci_pdriver.h>
 
 #include "core.h"
 
 int dwc3_host_init(struct dwc3 *dwc)
 {
 	struct platform_device	*xhci;
+	struct usb_xhci_pdata	pdata;
 	int			ret;
 
 	xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
@@ -46,6 +48,18 @@ int dwc3_host_init(struct dwc3 *dwc)
 		goto err1;
 	}
 
+	memset(&pdata, 0, sizeof(pdata));
+
+#ifdef CONFIG_DWC3_HOST_USB3_LPM_ENABLE
+	pdata.usb3_lpm_capable = 1;
+#endif
+
+	ret = platform_device_add_data(xhci, &pdata, sizeof(pdata));
+	if (ret) {
+		dev_err(dwc->dev, "couldn't add platform data to xHCI device\n");
+		goto err1;
+	}
+
 	ret = platform_device_add(xhci);
 	if (ret) {
 		dev_err(dwc->dev, "failed to register xHCI device\n");
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index ba18e9c110cc..5c822afb6d70 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -127,368 +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"
-	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.
-
-	   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
@@ -714,466 +353,7 @@ config USB_CONFIGFS_F_FS
 	  implemented in kernel space (for instance Ethernet, serial or
 	  mass storage) and other are implemented in user space.
 
-config USB_ZERO
-	tristate "Gadget Zero (DEVELOPMENT)"
-	select USB_LIBCOMPOSITE
-	select USB_F_SS_LB
-	help
-	  Gadget Zero is a two-configuration device.  It either sinks and
-	  sources bulk data; or it loops back a configurable number of
-	  transfers.  It also implements control requests, for "chapter 9"
-	  conformance.  The driver needs only two bulk-capable endpoints, so
-	  it can work on top of most device-side usb controllers.  It's
-	  useful for testing, and is also a working example showing how
-	  USB "gadget drivers" can be written.
-
-	  Make this be the first driver you try using on top of any new
-	  USB peripheral controller driver.  Then you can use host-side
-	  test software, like the "usbtest" driver, to put your hardware
-	  and its driver through a basic set of functional tests.
-
-	  Gadget Zero also works with the host-side "usb-skeleton" driver,
-	  and with many kinds of host-side test software.  You may need
-	  to tweak product and vendor IDs before host software knows about
-	  this device, and arrange to select an appropriate configuration.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_zero".
-
-config USB_ZERO_HNPTEST
-	boolean "HNP Test Device"
-	depends on USB_ZERO && USB_OTG
-	help
-	  You can configure this device to enumerate using the device
-	  identifiers of the USB-OTG test device.  That means that when
-	  this gadget connects to another OTG device, with this one using
-	  the "B-Peripheral" role, that device will use HNP to let this
-	  one serve as the USB host instead (in the "B-Host" role).
-
-config USB_AUDIO
-	tristate "Audio Gadget"
-	depends on SND
-	select USB_LIBCOMPOSITE
-	select SND_PCM
-	help
-	  This Gadget Audio driver is compatible with USB Audio Class
-	  specification 2.0. It implements 1 AudioControl interface,
-	  1 AudioStreaming Interface each for USB-OUT and USB-IN.
-	  Number of channels, sample rate and sample size can be
-	  specified as module parameters.
-	  This driver doesn't expect any real Audio codec to be present
-	  on the device - the audio streams are simply sinked to and
-	  sourced from a virtual ALSA sound card created. The user-space
-	  application may choose to do whatever it wants with the data
-	  received from the USB Host and choose to provide whatever it
-	  wants as audio data to the USB Host.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_audio".
-
-config GADGET_UAC1
-	bool "UAC 1.0 (Legacy)"
-	depends on USB_AUDIO
-	help
-	  If you instead want older UAC Spec-1.0 driver that also has audio
-	  paths hardwired to the Audio codec chip on-board and doesn't work
-	  without one.
-
-config USB_ETH
-	tristate "Ethernet Gadget (with CDC Ethernet support)"
-	depends on NET
-	select USB_LIBCOMPOSITE
-	select USB_U_ETHER
-	select USB_F_ECM
-	select USB_F_SUBSET
-	select CRC32
-	help
-	  This driver implements Ethernet style communication, in one of
-	  several ways:
-	  
-	   - The "Communication Device Class" (CDC) Ethernet Control Model.
-	     That protocol is often avoided with pure Ethernet adapters, in
-	     favor of simpler vendor-specific hardware, but is widely
-	     supported by firmware for smart network devices.
-
-	   - On hardware can't implement that protocol, a simple CDC subset
-	     is used, placing fewer demands on USB.
-
-	   - CDC Ethernet Emulation Model (EEM) is a newer standard that has
-	     a simpler interface that can be used by more USB hardware.
-
-	  RNDIS support is an additional option, more demanding than than
-	  subset.
-
-	  Within the USB device, this gadget driver exposes a network device
-	  "usbX", where X depends on what other networking devices you have.
-	  Treat it like a two-node Ethernet link:  host, and gadget.
-
-	  The Linux-USB host-side "usbnet" driver interoperates with this
-	  driver, so that deep I/O queues can be supported.  On 2.4 kernels,
-	  use "CDCEther" instead, if you're using the CDC option. That CDC
-	  mode should also interoperate with standard CDC Ethernet class
-	  drivers on other host operating systems.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_ether".
-
-config USB_ETH_RNDIS
-	bool "RNDIS support"
-	depends on USB_ETH
-	select USB_LIBCOMPOSITE
-	select USB_F_RNDIS
-	default y
-	help
-	   Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
-	   and Microsoft provides redistributable binary RNDIS drivers for
-	   older versions of Windows.
-
-	   If you say "y" here, the Ethernet gadget driver will try to provide
-	   a second device configuration, supporting RNDIS to talk to such
-	   Microsoft USB hosts.
-	   
-	   To make MS-Windows work with this, use Documentation/usb/linux.inf
-	   as the "driver info file".  For versions of MS-Windows older than
-	   XP, you'll need to download drivers from Microsoft's website; a URL
-	   is given in comments found in that info file.
-
-config USB_ETH_EEM
-       bool "Ethernet Emulation Model (EEM) support"
-       depends on USB_ETH
-	select USB_LIBCOMPOSITE
-	select USB_F_EEM
-       default n
-       help
-         CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
-         and therefore can be supported by more hardware.  Technically ECM and
-         EEM are designed for different applications.  The ECM model extends
-         the network interface to the target (e.g. a USB cable modem), and the
-         EEM model is for mobile devices to communicate with hosts using
-         ethernet over USB.  For Linux gadgets, however, the interface with
-         the host is the same (a usbX device), so the differences are minimal.
-
-         If you say "y" here, the Ethernet gadget driver will use the EEM
-         protocol rather than ECM.  If unsure, say "n".
-
-config USB_G_NCM
-	tristate "Network Control Model (NCM) support"
-	depends on NET
-	select USB_LIBCOMPOSITE
-	select USB_U_ETHER
-	select USB_F_NCM
-	select CRC32
-	help
-	  This driver implements USB CDC NCM subclass standard. NCM is
-	  an advanced protocol for Ethernet encapsulation, allows grouping
-	  of several ethernet frames into one USB transfer and different
-	  alignment possibilities.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_ncm".
-
-config USB_GADGETFS
-	tristate "Gadget Filesystem"
-	help
-	  This driver provides a filesystem based API that lets user mode
-	  programs implement a single-configuration USB device, including
-	  endpoint I/O and control requests that don't relate to enumeration.
-	  All endpoints, transfer speeds, and transfer types supported by
-	  the hardware are available, through read() and write() calls.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "gadgetfs".
-
-config USB_FUNCTIONFS
-	tristate "Function Filesystem"
-	select USB_LIBCOMPOSITE
-	select USB_F_FS
-	select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
-	help
-	  The Function Filesystem (FunctionFS) lets one create USB
-	  composite functions in user space in the same way GadgetFS
-	  lets one create USB gadgets in user space.  This allows creation
-	  of composite gadgets such that some of the functions are
-	  implemented in kernel space (for instance Ethernet, serial or
-	  mass storage) and other are implemented in user space.
-
-	  If you say "y" or "m" here you will be able what kind of
-	  configurations the gadget will provide.
-
-	  Say "y" to link the driver statically, or "m" to build
-	  a dynamically linked module called "g_ffs".
-
-config USB_FUNCTIONFS_ETH
-	bool "Include configuration with CDC ECM (Ethernet)"
-	depends on USB_FUNCTIONFS && NET
-	select USB_U_ETHER
-	select USB_F_ECM
-	select USB_F_SUBSET
-	help
-	  Include a configuration with CDC ECM function (Ethernet) and the
-	  Function Filesystem.
-
-config USB_FUNCTIONFS_RNDIS
-	bool "Include configuration with RNDIS (Ethernet)"
-	depends on USB_FUNCTIONFS && NET
-	select USB_U_ETHER
-	select USB_F_RNDIS
-	help
-	  Include a configuration with RNDIS function (Ethernet) and the Filesystem.
-
-config USB_FUNCTIONFS_GENERIC
-	bool "Include 'pure' configuration"
-	depends on USB_FUNCTIONFS
-	help
-	  Include a configuration with the Function Filesystem alone with
-	  no Ethernet interface.
-
-config USB_MASS_STORAGE
-	tristate "Mass Storage Gadget"
-	depends on BLOCK
-	select USB_LIBCOMPOSITE
-	select USB_F_MASS_STORAGE
-	help
-	  The Mass Storage Gadget acts as a USB Mass Storage disk drive.
-	  As its storage repository it can use a regular file or a block
-	  device (in much the same way as the "loop" device driver),
-	  specified as a module parameter or sysfs option.
-
-	  This driver is a replacement for now removed File-backed
-	  Storage Gadget (g_file_storage).
-
-	  Say "y" to link the driver statically, or "m" to build
-	  a dynamically linked module called "g_mass_storage".
-
-config USB_GADGET_TARGET
-	tristate "USB Gadget Target Fabric Module"
-	depends on TARGET_CORE
-	select USB_LIBCOMPOSITE
-	help
-	  This fabric is an USB gadget. Two USB protocols are supported that is
-	  BBB or BOT (Bulk Only Transport) and UAS (USB Attached SCSI). BOT is
-	  advertised on alternative interface 0 (primary) and UAS is on
-	  alternative interface 1. Both protocols can work on USB2.0 and USB3.0.
-	  UAS utilizes the USB 3.0 feature called streams support.
-
-config USB_G_SERIAL
-	tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
-	depends on TTY
-	select USB_U_SERIAL
-	select USB_F_ACM
-	select USB_F_SERIAL
-	select USB_F_OBEX
-	select USB_LIBCOMPOSITE
-	help
-	  The Serial Gadget talks to the Linux-USB generic serial driver.
-	  This driver supports a CDC-ACM module option, which can be used
-	  to interoperate with MS-Windows hosts or with the Linux-USB
-	  "cdc-acm" driver.
-
-	  This driver also supports a CDC-OBEX option.  You will need a
-	  user space OBEX server talking to /dev/ttyGS*, since the kernel
-	  itself doesn't implement the OBEX protocol.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_serial".
-
-	  For more information, see Documentation/usb/gadget_serial.txt
-	  which includes instructions and a "driver info file" needed to
-	  make MS-Windows work with CDC ACM.
-
-config USB_MIDI_GADGET
-	tristate "MIDI Gadget"
-	depends on SND
-	select USB_LIBCOMPOSITE
-	select SND_RAWMIDI
-	help
-	  The MIDI Gadget acts as a USB Audio device, with one MIDI
-	  input and one MIDI output. These MIDI jacks appear as
-	  a sound "card" in the ALSA sound system. Other MIDI
-	  connections can then be made on the gadget system, using
-	  ALSA's aconnect utility etc.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_midi".
-
-config USB_G_PRINTER
-	tristate "Printer Gadget"
-	select USB_LIBCOMPOSITE
-	help
-	  The Printer Gadget channels data between the USB host and a
-	  userspace program driving the print engine. The user space
-	  program reads and writes the device file /dev/g_printer to
-	  receive or send printer data. It can use ioctl calls to
-	  the device file to get or set printer status.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_printer".
-
-	  For more information, see Documentation/usb/gadget_printer.txt
-	  which includes sample code for accessing the device file.
-
-if TTY
-
-config USB_CDC_COMPOSITE
-	tristate "CDC Composite Device (Ethernet and ACM)"
-	depends on NET
-	select USB_LIBCOMPOSITE
-	select USB_U_SERIAL
-	select USB_U_ETHER
-	select USB_F_ACM
-	select USB_F_ECM
-	help
-	  This driver provides two functions in one configuration:
-	  a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
-
-	  This driver requires four bulk and two interrupt endpoints,
-	  plus the ability to handle altsettings.  Not all peripheral
-	  controllers are that capable.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module.
-
-config USB_G_NOKIA
-	tristate "Nokia composite gadget"
-	depends on PHONET
-	select USB_LIBCOMPOSITE
-	select USB_U_SERIAL
-	select USB_U_ETHER
-	select USB_F_ACM
-	select USB_F_OBEX
-	select USB_F_PHONET
-	select USB_F_ECM
-	help
-	  The Nokia composite gadget provides support for acm, obex
-	  and phonet in only one composite gadget driver.
-
-	  It's only really useful for N900 hardware. If you're building
-	  a kernel for N900, say Y or M here. If unsure, say N.
-
-config USB_G_ACM_MS
-	tristate "CDC Composite Device (ACM and mass storage)"
-	depends on BLOCK
-	select USB_LIBCOMPOSITE
-	select USB_U_SERIAL
-	select USB_F_ACM
-	select USB_F_MASS_STORAGE
-	help
-	  This driver provides two functions in one configuration:
-	  a mass storage, and a CDC ACM (serial port) link.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_acm_ms".
-
-config USB_G_MULTI
-	tristate "Multifunction Composite Gadget"
-	depends on BLOCK && NET
-	select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
-	select USB_LIBCOMPOSITE
-	select USB_U_SERIAL
-	select USB_U_ETHER
-	select USB_F_ACM
-	select USB_F_MASS_STORAGE
-	help
-	  The Multifunction Composite Gadget provides Ethernet (RNDIS
-	  and/or CDC Ethernet), mass storage and ACM serial link
-	  interfaces.
-
-	  You will be asked to choose which of the two configurations is
-	  to be available in the gadget.  At least one configuration must
-	  be chosen to make the gadget usable.  Selecting more than one
-	  configuration will prevent Windows from automatically detecting
-	  the gadget as a composite gadget, so an INF file will be needed to
-	  use the gadget.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_multi".
-
-config USB_G_MULTI_RNDIS
-	bool "RNDIS + CDC Serial + Storage configuration"
-	depends on USB_G_MULTI
-	select USB_F_RNDIS
-	default y
-	help
-	  This option enables a configuration with RNDIS, CDC Serial and
-	  Mass Storage functions available in the Multifunction Composite
-	  Gadget.  This is the configuration dedicated for Windows since RNDIS
-	  is Microsoft's protocol.
-
-	  If unsure, say "y".
-
-config USB_G_MULTI_CDC
-	bool "CDC Ethernet + CDC Serial + Storage configuration"
-	depends on USB_G_MULTI
-	default n
-	select USB_F_ECM
-	help
-	  This option enables a configuration with CDC Ethernet (ECM), CDC
-	  Serial and Mass Storage functions available in the Multifunction
-	  Composite Gadget.
-
-	  If unsure, say "y".
-
-endif # TTY
-
-config USB_G_HID
-	tristate "HID Gadget"
-	select USB_LIBCOMPOSITE
-	help
-	  The HID gadget driver provides generic emulation of USB
-	  Human Interface Devices (HID).
-
-	  For more information, see Documentation/usb/gadget_hid.txt which
-	  includes sample code for accessing the device files.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_hid".
-
-# Standalone / single function gadgets
-config USB_G_DBGP
-	tristate "EHCI Debug Device Gadget"
-	depends on TTY
-	select USB_LIBCOMPOSITE
-	help
-	  This gadget emulates an EHCI Debug device. This is useful when you want
-	  to interact with an EHCI Debug Port.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_dbgp".
-
-if USB_G_DBGP
-choice
-	prompt "EHCI Debug Device mode"
-	default USB_G_DBGP_SERIAL
-
-config USB_G_DBGP_PRINTK
-	depends on USB_G_DBGP
-	bool "printk"
-	help
-	  Directly printk() received data. No interaction.
-
-config USB_G_DBGP_SERIAL
-	depends on USB_G_DBGP
-	select USB_U_SERIAL
-	bool "serial"
-	help
-	  Userland can interact using /dev/ttyGSxxx.
-endchoice
-endif
-
-# put drivers that need isochronous transfer support (for audio
-# or video class gadget drivers), or specific hardware, here.
-config USB_G_WEBCAM
-	tristate "USB Webcam Gadget"
-	depends on VIDEO_DEV
-	select USB_LIBCOMPOSITE
-	select VIDEOBUF2_VMALLOC
-	help
-	  The Webcam Gadget acts as a composite USB Audio and Video Class
-	  device. It provides a userspace API to process UVC control requests
-	  and stream video data to the host.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_webcam".
+source "drivers/usb/gadget/legacy/Kconfig"
 
 endchoice
 
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 49514ea60a98..a186afeaa700 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -1,105 +1,12 @@
 #
 # USB peripheral controller drivers
 #
-ccflags-$(CONFIG_USB_GADGET_DEBUG)	:= -DDEBUG
-ccflags-$(CONFIG_USB_GADGET_VERBOSE)	+= -DVERBOSE_DEBUG
+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
-obj-$(CONFIG_USB_F_ACM)		+= usb_f_acm.o
-usb_f_ss_lb-y			:= f_loopback.o f_sourcesink.o
-obj-$(CONFIG_USB_F_SS_LB)	+= usb_f_ss_lb.o
-obj-$(CONFIG_USB_U_SERIAL)	+= u_serial.o
-usb_f_serial-y			:= f_serial.o
-obj-$(CONFIG_USB_F_SERIAL)	+= usb_f_serial.o
-usb_f_obex-y			:= f_obex.o
-obj-$(CONFIG_USB_F_OBEX)	+= usb_f_obex.o
-obj-$(CONFIG_USB_U_ETHER)	+= u_ether.o
-usb_f_ncm-y			:= f_ncm.o
-obj-$(CONFIG_USB_F_NCM)		+= usb_f_ncm.o
-usb_f_ecm-y			:= f_ecm.o
-obj-$(CONFIG_USB_F_ECM)		+= usb_f_ecm.o
-usb_f_phonet-y			:= f_phonet.o
-obj-$(CONFIG_USB_F_PHONET)	+= usb_f_phonet.o
-usb_f_eem-y			:= f_eem.o
-obj-$(CONFIG_USB_F_EEM)		+= usb_f_eem.o
-usb_f_ecm_subset-y		:= f_subset.o
-obj-$(CONFIG_USB_F_SUBSET)	+= usb_f_ecm_subset.o
-usb_f_rndis-y			:= f_rndis.o rndis.o
-obj-$(CONFIG_USB_F_RNDIS)	+= usb_f_rndis.o
-usb_f_mass_storage-y		:= f_mass_storage.o storage_common.o
-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
-
-#
-# USB gadget drivers
-#
-g_zero-y			:= zero.o
-g_audio-y			:= audio.o
-g_ether-y			:= ether.o
-g_serial-y			:= serial.o
-g_midi-y			:= gmidi.o
-gadgetfs-y			:= inode.o
-g_mass_storage-y		:= mass_storage.o
-g_printer-y			:= printer.o
-g_cdc-y				:= cdc2.o
-g_multi-y			:= multi.o
-g_hid-y				:= hid.o
-g_dbgp-y			:= dbgp.o
-g_nokia-y			:= nokia.o
-g_webcam-y			:= webcam.o
-g_ncm-y				:= ncm.o
-g_acm_ms-y			:= acm_ms.o
-g_tcm_usb_gadget-y		:= tcm_usb_gadget.o
-
-obj-$(CONFIG_USB_ZERO)		+= g_zero.o
-obj-$(CONFIG_USB_AUDIO)		+= g_audio.o
-obj-$(CONFIG_USB_ETH)		+= g_ether.o
-obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o
-obj-$(CONFIG_USB_FUNCTIONFS)	+= g_ffs.o
-obj-$(CONFIG_USB_MASS_STORAGE)	+= g_mass_storage.o
-obj-$(CONFIG_USB_G_SERIAL)	+= g_serial.o
-obj-$(CONFIG_USB_G_PRINTER)	+= g_printer.o
-obj-$(CONFIG_USB_MIDI_GADGET)	+= g_midi.o
-obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
-obj-$(CONFIG_USB_G_HID)		+= g_hid.o
-obj-$(CONFIG_USB_G_DBGP)	+= g_dbgp.o
-obj-$(CONFIG_USB_G_MULTI)	+= g_multi.o
-obj-$(CONFIG_USB_G_NOKIA)	+= g_nokia.o
-obj-$(CONFIG_USB_G_WEBCAM)	+= g_webcam.o
-obj-$(CONFIG_USB_G_NCM)		+= g_ncm.o
-obj-$(CONFIG_USB_G_ACM_MS)	+= g_acm_ms.o
-obj-$(CONFIG_USB_GADGET_TARGET)	+= tcm_usb_gadget.o
+obj-$(CONFIG_USB_GADGET)	+= udc/ function/ legacy/
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index f80151932053..6935a822ce2b 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1956,6 +1956,7 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
 	}
 	if (cdev->req) {
 		kfree(cdev->req->buf);
+		usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
 		usb_ep_free_request(cdev->gadget->ep0, cdev->req);
 	}
 	cdev->next_string_id = 0;
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 97142146eead..811c2c7cc269 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1021,12 +1021,10 @@ static ssize_t ext_prop_data_store(struct usb_os_desc_ext_prop *ext_prop,
 
 	if (page[len - 1] == '\n' || page[len - 1] == '\0')
 		--len;
-	new_data = kzalloc(len, GFP_KERNEL);
+	new_data = kmemdup(page, len, GFP_KERNEL);
 	if (!new_data)
 		return -ENOMEM;
 
-	memcpy(new_data, page, len);
-
 	if (desc->opts_mutex)
 		mutex_lock(desc->opts_mutex);
 	kfree(ext_prop->data);
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile
new file mode 100644
index 000000000000..6d91f21b52a6
--- /dev/null
+++ b/drivers/usb/gadget/function/Makefile
@@ -0,0 +1,34 @@
+#
+# USB peripheral controller drivers
+#
+
+ccflags-y			:= -I$(PWD)/drivers/usb/gadget/
+ccflags-y			+= -I$(PWD)/drivers/usb/gadget/udc/
+
+# USB Functions
+usb_f_acm-y			:= f_acm.o
+obj-$(CONFIG_USB_F_ACM)		+= usb_f_acm.o
+usb_f_ss_lb-y			:= f_loopback.o f_sourcesink.o
+obj-$(CONFIG_USB_F_SS_LB)	+= usb_f_ss_lb.o
+obj-$(CONFIG_USB_U_SERIAL)	+= u_serial.o
+usb_f_serial-y			:= f_serial.o
+obj-$(CONFIG_USB_F_SERIAL)	+= usb_f_serial.o
+usb_f_obex-y			:= f_obex.o
+obj-$(CONFIG_USB_F_OBEX)	+= usb_f_obex.o
+obj-$(CONFIG_USB_U_ETHER)	+= u_ether.o
+usb_f_ncm-y			:= f_ncm.o
+obj-$(CONFIG_USB_F_NCM)		+= usb_f_ncm.o
+usb_f_ecm-y			:= f_ecm.o
+obj-$(CONFIG_USB_F_ECM)		+= usb_f_ecm.o
+usb_f_phonet-y			:= f_phonet.o
+obj-$(CONFIG_USB_F_PHONET)	+= usb_f_phonet.o
+usb_f_eem-y			:= f_eem.o
+obj-$(CONFIG_USB_F_EEM)		+= usb_f_eem.o
+usb_f_ecm_subset-y		:= f_subset.o
+obj-$(CONFIG_USB_F_SUBSET)	+= usb_f_ecm_subset.o
+usb_f_rndis-y			:= f_rndis.o rndis.o
+obj-$(CONFIG_USB_F_RNDIS)	+= usb_f_rndis.o
+usb_f_mass_storage-y		:= f_mass_storage.o storage_common.o
+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
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/function/f_acm.c
index ab1065afbbd0..ab1065afbbd0 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/function/f_acm.c
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/function/f_ecm.c
index 798760fa7e70..798760fa7e70 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/function/f_ecm.c
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/function/f_eem.c
index d61c11d765d0..4d8b236ea608 100644
--- a/drivers/usb/gadget/f_eem.c
+++ b/drivers/usb/gadget/function/f_eem.c
@@ -355,20 +355,18 @@ static struct sk_buff *eem_wrap(struct gether *port, struct sk_buff *skb)
 	int		padlen = 0;
 	u16		len = skb->len;
 
-	if (!skb_cloned(skb)) {
-		int headroom = skb_headroom(skb);
-		int tailroom = skb_tailroom(skb);
+	int headroom = skb_headroom(skb);
+	int tailroom = skb_tailroom(skb);
 
-		/* When (len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) is 0,
-		 * stick two bytes of zero-length EEM packet on the end.
-		 */
-		if (((len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) == 0)
-			padlen += 2;
+	/* When (len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) is 0,
+	 * stick two bytes of zero-length EEM packet on the end.
+	 */
+	if (((len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) == 0)
+		padlen += 2;
 
-		if ((tailroom >= (ETH_FCS_LEN + padlen)) &&
-				(headroom >= EEM_HLEN))
-			goto done;
-	}
+	if ((tailroom >= (ETH_FCS_LEN + padlen)) &&
+			(headroom >= EEM_HLEN) && !skb_cloned(skb))
+		goto done;
 
 	skb2 = skb_copy_expand(skb, EEM_HLEN, ETH_FCS_LEN + padlen, GFP_ATOMIC);
 	dev_kfree_skb_any(skb);
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 8598c27c7d43..dc30adf15a01 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -34,6 +34,7 @@
 
 #include "u_fs.h"
 #include "u_f.h"
+#include "u_os_desc.h"
 #include "configfs.h"
 
 #define FUNCTIONFS_MAGIC	0xa647361 /* Chosen by a honest dice roll ;) */
@@ -1646,13 +1647,22 @@ enum ffs_entity_type {
 	FFS_DESCRIPTOR, FFS_INTERFACE, FFS_STRING, FFS_ENDPOINT
 };
 
+enum ffs_os_desc_type {
+	FFS_OS_DESC, FFS_OS_DESC_EXT_COMPAT, FFS_OS_DESC_EXT_PROP
+};
+
 typedef int (*ffs_entity_callback)(enum ffs_entity_type entity,
 				   u8 *valuep,
 				   struct usb_descriptor_header *desc,
 				   void *priv);
 
-static int __must_check ffs_do_desc(char *data, unsigned len,
-				    ffs_entity_callback entity, void *priv)
+typedef int (*ffs_os_desc_callback)(enum ffs_os_desc_type entity,
+				    struct usb_os_desc_header *h, void *data,
+				    unsigned len, void *priv);
+
+static int __must_check ffs_do_single_desc(char *data, unsigned len,
+					   ffs_entity_callback entity,
+					   void *priv)
 {
 	struct usb_descriptor_header *_ds = (void *)data;
 	u8 length;
@@ -1804,7 +1814,7 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len,
 		if (!data)
 			return _len - len;
 
-		ret = ffs_do_desc(data, len, entity, priv);
+		ret = ffs_do_single_desc(data, len, entity, priv);
 		if (unlikely(ret < 0)) {
 			pr_debug("%s returns %d\n", __func__, ret);
 			return ret;
@@ -1857,11 +1867,191 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
 	return 0;
 }
 
+static int __ffs_do_os_desc_header(enum ffs_os_desc_type *next_type,
+				   struct usb_os_desc_header *desc)
+{
+	u16 bcd_version = le16_to_cpu(desc->bcdVersion);
+	u16 w_index = le16_to_cpu(desc->wIndex);
+
+	if (bcd_version != 1) {
+		pr_vdebug("unsupported os descriptors version: %d",
+			  bcd_version);
+		return -EINVAL;
+	}
+	switch (w_index) {
+	case 0x4:
+		*next_type = FFS_OS_DESC_EXT_COMPAT;
+		break;
+	case 0x5:
+		*next_type = FFS_OS_DESC_EXT_PROP;
+		break;
+	default:
+		pr_vdebug("unsupported os descriptor type: %d", w_index);
+		return -EINVAL;
+	}
+
+	return sizeof(*desc);
+}
+
+/*
+ * Process all extended compatibility/extended property descriptors
+ * of a feature descriptor
+ */
+static int __must_check ffs_do_single_os_desc(char *data, unsigned len,
+					      enum ffs_os_desc_type type,
+					      u16 feature_count,
+					      ffs_os_desc_callback entity,
+					      void *priv,
+					      struct usb_os_desc_header *h)
+{
+	int ret;
+	const unsigned _len = len;
+
+	ENTER();
+
+	/* loop over all ext compat/ext prop descriptors */
+	while (feature_count--) {
+		ret = entity(type, h, data, len, priv);
+		if (unlikely(ret < 0)) {
+			pr_debug("bad OS descriptor, type: %d\n", type);
+			return ret;
+		}
+		data += ret;
+		len -= ret;
+	}
+	return _len - len;
+}
+
+/* Process a number of complete Feature Descriptors (Ext Compat or Ext Prop) */
+static int __must_check ffs_do_os_descs(unsigned count,
+					char *data, unsigned len,
+					ffs_os_desc_callback entity, void *priv)
+{
+	const unsigned _len = len;
+	unsigned long num = 0;
+
+	ENTER();
+
+	for (num = 0; num < count; ++num) {
+		int ret;
+		enum ffs_os_desc_type type;
+		u16 feature_count;
+		struct usb_os_desc_header *desc = (void *)data;
+
+		if (len < sizeof(*desc))
+			return -EINVAL;
+
+		/*
+		 * Record "descriptor" entity.
+		 * Process dwLength, bcdVersion, wIndex, get b/wCount.
+		 * Move the data pointer to the beginning of extended
+		 * compatibilities proper or extended properties proper
+		 * portions of the data
+		 */
+		if (le32_to_cpu(desc->dwLength) > len)
+			return -EINVAL;
+
+		ret = __ffs_do_os_desc_header(&type, desc);
+		if (unlikely(ret < 0)) {
+			pr_debug("entity OS_DESCRIPTOR(%02lx); ret = %d\n",
+				 num, ret);
+			return ret;
+		}
+		/*
+		 * 16-bit hex "?? 00" Little Endian looks like 8-bit hex "??"
+		 */
+		feature_count = le16_to_cpu(desc->wCount);
+		if (type == FFS_OS_DESC_EXT_COMPAT &&
+		    (feature_count > 255 || desc->Reserved))
+				return -EINVAL;
+		len -= ret;
+		data += ret;
+
+		/*
+		 * Process all function/property descriptors
+		 * of this Feature Descriptor
+		 */
+		ret = ffs_do_single_os_desc(data, len, type,
+					    feature_count, entity, priv, desc);
+		if (unlikely(ret < 0)) {
+			pr_debug("%s returns %d\n", __func__, ret);
+			return ret;
+		}
+
+		len -= ret;
+		data += ret;
+	}
+	return _len - len;
+}
+
+/**
+ * Validate contents of the buffer from userspace related to OS descriptors.
+ */
+static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
+				 struct usb_os_desc_header *h, void *data,
+				 unsigned len, void *priv)
+{
+	struct ffs_data *ffs = priv;
+	u8 length;
+
+	ENTER();
+
+	switch (type) {
+	case FFS_OS_DESC_EXT_COMPAT: {
+		struct usb_ext_compat_desc *d = data;
+		int i;
+
+		if (len < sizeof(*d) ||
+		    d->bFirstInterfaceNumber >= ffs->interfaces_count ||
+		    d->Reserved1)
+			return -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i)
+			if (d->Reserved2[i])
+				return -EINVAL;
+
+		length = sizeof(struct usb_ext_compat_desc);
+	}
+		break;
+	case FFS_OS_DESC_EXT_PROP: {
+		struct usb_ext_prop_desc *d = data;
+		u32 type, pdl;
+		u16 pnl;
+
+		if (len < sizeof(*d) || h->interface >= ffs->interfaces_count)
+			return -EINVAL;
+		length = le32_to_cpu(d->dwSize);
+		type = le32_to_cpu(d->dwPropertyDataType);
+		if (type < USB_EXT_PROP_UNICODE ||
+		    type > USB_EXT_PROP_UNICODE_MULTI) {
+			pr_vdebug("unsupported os descriptor property type: %d",
+				  type);
+			return -EINVAL;
+		}
+		pnl = le16_to_cpu(d->wPropertyNameLength);
+		pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl));
+		if (length != 14 + pnl + pdl) {
+			pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n",
+				  length, pnl, pdl, type);
+			return -EINVAL;
+		}
+		++ffs->ms_os_descs_ext_prop_count;
+		/* property name reported to the host as "WCHAR"s */
+		ffs->ms_os_descs_ext_prop_name_len += pnl * 2;
+		ffs->ms_os_descs_ext_prop_data_len += pdl;
+	}
+		break;
+	default:
+		pr_vdebug("unknown descriptor: %d\n", type);
+		return -EINVAL;
+	}
+	return length;
+}
+
 static int __ffs_data_got_descs(struct ffs_data *ffs,
 				char *const _data, size_t len)
 {
 	char *data = _data, *raw_descs;
-	unsigned counts[3], flags;
+	unsigned os_descs_count = 0, counts[3], flags;
 	int ret = -EINVAL, i;
 
 	ENTER();
@@ -1879,7 +2069,8 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
 		flags = get_unaligned_le32(data + 8);
 		if (flags & ~(FUNCTIONFS_HAS_FS_DESC |
 			      FUNCTIONFS_HAS_HS_DESC |
-			      FUNCTIONFS_HAS_SS_DESC)) {
+			      FUNCTIONFS_HAS_SS_DESC |
+			      FUNCTIONFS_HAS_MS_OS_DESC)) {
 			ret = -ENOSYS;
 			goto error;
 		}
@@ -1902,6 +2093,11 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
 			len  -= 4;
 		}
 	}
+	if (flags & (1 << i)) {
+		os_descs_count = get_unaligned_le32(data);
+		data += 4;
+		len -= 4;
+	};
 
 	/* Read descriptors */
 	raw_descs = data;
@@ -1915,6 +2111,14 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
 		data += ret;
 		len  -= ret;
 	}
+	if (os_descs_count) {
+		ret = ffs_do_os_descs(os_descs_count, data, len,
+				      __ffs_data_do_os_desc, ffs);
+		if (ret < 0)
+			goto error;
+		data += ret;
+		len -= ret;
+	}
 
 	if (raw_descs == data || len) {
 		ret = -EINVAL;
@@ -1927,6 +2131,7 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
 	ffs->fs_descs_count	= counts[0];
 	ffs->hs_descs_count	= counts[1];
 	ffs->ss_descs_count	= counts[2];
+	ffs->ms_os_descs_count	= os_descs_count;
 
 	return 0;
 
@@ -2268,6 +2473,85 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
 	return 0;
 }
 
+static int __ffs_func_bind_do_os_desc(enum ffs_os_desc_type type,
+				      struct usb_os_desc_header *h, void *data,
+				      unsigned len, void *priv)
+{
+	struct ffs_function *func = priv;
+	u8 length = 0;
+
+	switch (type) {
+	case FFS_OS_DESC_EXT_COMPAT: {
+		struct usb_ext_compat_desc *desc = data;
+		struct usb_os_desc_table *t;
+
+		t = &func->function.os_desc_table[desc->bFirstInterfaceNumber];
+		t->if_id = func->interfaces_nums[desc->bFirstInterfaceNumber];
+		memcpy(t->os_desc->ext_compat_id, &desc->CompatibleID,
+		       ARRAY_SIZE(desc->CompatibleID) +
+		       ARRAY_SIZE(desc->SubCompatibleID));
+		length = sizeof(*desc);
+	}
+		break;
+	case FFS_OS_DESC_EXT_PROP: {
+		struct usb_ext_prop_desc *desc = data;
+		struct usb_os_desc_table *t;
+		struct usb_os_desc_ext_prop *ext_prop;
+		char *ext_prop_name;
+		char *ext_prop_data;
+
+		t = &func->function.os_desc_table[h->interface];
+		t->if_id = func->interfaces_nums[h->interface];
+
+		ext_prop = func->ffs->ms_os_descs_ext_prop_avail;
+		func->ffs->ms_os_descs_ext_prop_avail += sizeof(*ext_prop);
+
+		ext_prop->type = le32_to_cpu(desc->dwPropertyDataType);
+		ext_prop->name_len = le16_to_cpu(desc->wPropertyNameLength);
+		ext_prop->data_len = le32_to_cpu(*(u32 *)
+			usb_ext_prop_data_len_ptr(data, ext_prop->name_len));
+		length = ext_prop->name_len + ext_prop->data_len + 14;
+
+		ext_prop_name = func->ffs->ms_os_descs_ext_prop_name_avail;
+		func->ffs->ms_os_descs_ext_prop_name_avail +=
+			ext_prop->name_len;
+
+		ext_prop_data = func->ffs->ms_os_descs_ext_prop_data_avail;
+		func->ffs->ms_os_descs_ext_prop_data_avail +=
+			ext_prop->data_len;
+		memcpy(ext_prop_data,
+		       usb_ext_prop_data_ptr(data, ext_prop->name_len),
+		       ext_prop->data_len);
+		/* unicode data reported to the host as "WCHAR"s */
+		switch (ext_prop->type) {
+		case USB_EXT_PROP_UNICODE:
+		case USB_EXT_PROP_UNICODE_ENV:
+		case USB_EXT_PROP_UNICODE_LINK:
+		case USB_EXT_PROP_UNICODE_MULTI:
+			ext_prop->data_len *= 2;
+			break;
+		}
+		ext_prop->data = ext_prop_data;
+
+		memcpy(ext_prop_name, usb_ext_prop_name_ptr(data),
+		       ext_prop->name_len);
+		/* property name reported to the host as "WCHAR"s */
+		ext_prop->name_len *= 2;
+		ext_prop->name = ext_prop_name;
+
+		t->os_desc->ext_prop_len +=
+			ext_prop->name_len + ext_prop->data_len + 14;
+		++t->os_desc->ext_prop_count;
+		list_add_tail(&ext_prop->entry, &t->os_desc->ext_prop);
+	}
+		break;
+	default:
+		pr_vdebug("unknown descriptor: %d\n", type);
+	}
+
+	return length;
+}
+
 static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
 						struct usb_configuration *c)
 {
@@ -2329,7 +2613,7 @@ static int _ffs_func_bind(struct usb_configuration *c,
 	const int super = gadget_is_superspeed(func->gadget) &&
 		func->ffs->ss_descs_count;
 
-	int fs_len, hs_len, ret;
+	int fs_len, hs_len, ss_len, ret, i;
 
 	/* Make it a single chunk, less management later on */
 	vla_group(d);
@@ -2341,6 +2625,18 @@ static int _ffs_func_bind(struct usb_configuration *c,
 	vla_item_with_sz(d, struct usb_descriptor_header *, ss_descs,
 		super ? ffs->ss_descs_count + 1 : 0);
 	vla_item_with_sz(d, short, inums, ffs->interfaces_count);
+	vla_item_with_sz(d, struct usb_os_desc_table, os_desc_table,
+			 c->cdev->use_os_string ? ffs->interfaces_count : 0);
+	vla_item_with_sz(d, char[16], ext_compat,
+			 c->cdev->use_os_string ? ffs->interfaces_count : 0);
+	vla_item_with_sz(d, struct usb_os_desc, os_desc,
+			 c->cdev->use_os_string ? ffs->interfaces_count : 0);
+	vla_item_with_sz(d, struct usb_os_desc_ext_prop, ext_prop,
+			 ffs->ms_os_descs_ext_prop_count);
+	vla_item_with_sz(d, char, ext_prop_name,
+			 ffs->ms_os_descs_ext_prop_name_len);
+	vla_item_with_sz(d, char, ext_prop_data,
+			 ffs->ms_os_descs_ext_prop_data_len);
 	vla_item_with_sz(d, char, raw_descs, ffs->raw_descs_length);
 	char *vlabuf;
 
@@ -2351,12 +2647,16 @@ static int _ffs_func_bind(struct usb_configuration *c,
 		return -ENOTSUPP;
 
 	/* Allocate a single chunk, less management later on */
-	vlabuf = kmalloc(vla_group_size(d), GFP_KERNEL);
+	vlabuf = kzalloc(vla_group_size(d), GFP_KERNEL);
 	if (unlikely(!vlabuf))
 		return -ENOMEM;
 
-	/* Zero */
-	memset(vla_ptr(vlabuf, d, eps), 0, d_eps__sz);
+	ffs->ms_os_descs_ext_prop_avail = vla_ptr(vlabuf, d, ext_prop);
+	ffs->ms_os_descs_ext_prop_name_avail =
+		vla_ptr(vlabuf, d, ext_prop_name);
+	ffs->ms_os_descs_ext_prop_data_avail =
+		vla_ptr(vlabuf, d, ext_prop_data);
+
 	/* Copy descriptors  */
 	memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs,
 	       ffs->raw_descs_length);
@@ -2410,12 +2710,16 @@ static int _ffs_func_bind(struct usb_configuration *c,
 
 	if (likely(super)) {
 		func->function.ss_descriptors = vla_ptr(vlabuf, d, ss_descs);
-		ret = ffs_do_descs(ffs->ss_descs_count,
+		ss_len = ffs_do_descs(ffs->ss_descs_count,
 				vla_ptr(vlabuf, d, raw_descs) + fs_len + hs_len,
 				d_raw_descs__sz - fs_len - hs_len,
 				__ffs_func_bind_do_descs, func);
-		if (unlikely(ret < 0))
+		if (unlikely(ss_len < 0)) {
+			ret = ss_len;
 			goto error;
+		}
+	} else {
+		ss_len = 0;
 	}
 
 	/*
@@ -2431,6 +2735,28 @@ static int _ffs_func_bind(struct usb_configuration *c,
 	if (unlikely(ret < 0))
 		goto error;
 
+	func->function.os_desc_table = vla_ptr(vlabuf, d, os_desc_table);
+	if (c->cdev->use_os_string)
+		for (i = 0; i < ffs->interfaces_count; ++i) {
+			struct usb_os_desc *desc;
+
+			desc = func->function.os_desc_table[i].os_desc =
+				vla_ptr(vlabuf, d, os_desc) +
+				i * sizeof(struct usb_os_desc);
+			desc->ext_compat_id =
+				vla_ptr(vlabuf, d, ext_compat) + i * 16;
+			INIT_LIST_HEAD(&desc->ext_prop);
+		}
+	ret = ffs_do_os_descs(ffs->ms_os_descs_count,
+			      vla_ptr(vlabuf, d, raw_descs) +
+			      fs_len + hs_len + ss_len,
+			      d_raw_descs__sz - fs_len - hs_len - ss_len,
+			      __ffs_func_bind_do_os_desc, func);
+	if (unlikely(ret < 0))
+		goto error;
+	func->function.os_desc_n =
+		c->cdev->use_os_string ? ffs->interfaces_count : 0;
+
 	/* And we're done */
 	ffs_event_add(ffs, FUNCTIONFS_BIND);
 	return 0;
@@ -2901,12 +3227,12 @@ static void *ffs_acquire_dev(const char *dev_name)
 
 	ffs_dev = _ffs_find_dev(dev_name);
 	if (!ffs_dev)
-		ffs_dev = ERR_PTR(-ENODEV);
+		ffs_dev = ERR_PTR(-ENOENT);
 	else if (ffs_dev->mounted)
 		ffs_dev = ERR_PTR(-EBUSY);
 	else if (ffs_dev->ffs_acquire_dev_callback &&
 	    ffs_dev->ffs_acquire_dev_callback(ffs_dev))
-		ffs_dev = ERR_PTR(-ENODEV);
+		ffs_dev = ERR_PTR(-ENOENT);
 	else
 		ffs_dev->mounted = true;
 
diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/function/f_hid.c
index a95290a1289f..a95290a1289f 100644
--- a/drivers/usb/gadget/f_hid.c
+++ b/drivers/usb/gadget/function/f_hid.c
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c
index 4557cd03f0b1..4557cd03f0b1 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/function/f_loopback.c
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index b96393908860..b96393908860 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
diff --git a/drivers/usb/gadget/f_mass_storage.h b/drivers/usb/gadget/function/f_mass_storage.h
index b4866fcef30b..b4866fcef30b 100644
--- a/drivers/usb/gadget/f_mass_storage.h
+++ b/drivers/usb/gadget/function/f_mass_storage.h
diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index 807b31c0edc3..807b31c0edc3 100644
--- a/drivers/usb/gadget/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
index a9499fd30792..bcdc882cd415 100644
--- a/drivers/usb/gadget/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -68,6 +68,18 @@ struct f_ncm {
 	 * callback and ethernet open/close
 	 */
 	spinlock_t			lock;
+
+	struct net_device		*netdev;
+
+	/* For multi-frame NDP TX */
+	struct sk_buff			*skb_tx_data;
+	struct sk_buff			*skb_tx_ndp;
+	u16				ndp_dgram_count;
+	bool				timer_force_tx;
+	struct tasklet_struct		tx_tasklet;
+	struct hrtimer			task_timer;
+
+	bool				timer_stopping;
 };
 
 static inline struct f_ncm *func_to_ncm(struct usb_function *f)
@@ -92,15 +104,20 @@ static inline unsigned ncm_bitrate(struct usb_gadget *g)
  * If the host can group frames, allow it to do that, 16K is selected,
  * because it's used by default by the current linux host driver
  */
-#define NTB_DEFAULT_IN_SIZE	USB_CDC_NCM_NTB_MIN_IN_SIZE
+#define NTB_DEFAULT_IN_SIZE	16384
 #define NTB_OUT_SIZE		16384
 
-/*
- * skbs of size less than that will not be aligned
- * to NCM's dwNtbInMaxSize to save bus bandwidth
+/* Allocation for storing the NDP, 32 should suffice for a
+ * 16k packet. This allows a maximum of 32 * 507 Byte packets to
+ * be transmitted in a single 16kB skb, though when sending full size
+ * packets this limit will be plenty.
+ * Smaller packets are not likely to be trying to maximize the
+ * throughput and will be mstly sending smaller infrequent frames.
  */
+#define TX_MAX_NUM_DPE		32
 
-#define	MAX_TX_NONFIXED		(512 * 3)
+/* Delay for the transmit to wait before sending an unfilled NTB frame. */
+#define TX_TIMEOUT_NSECS	300000
 
 #define FORMATS_SUPPORTED	(USB_CDC_NCM_NTB16_SUPPORTED |	\
 				 USB_CDC_NCM_NTB32_SUPPORTED)
@@ -355,14 +372,15 @@ struct ndp_parser_opts {
 	u32		ndp_sign;
 	unsigned	nth_size;
 	unsigned	ndp_size;
+	unsigned	dpe_size;
 	unsigned	ndplen_align;
 	/* sizes in u16 units */
 	unsigned	dgram_item_len; /* index or length */
 	unsigned	block_length;
-	unsigned	fp_index;
+	unsigned	ndp_index;
 	unsigned	reserved1;
 	unsigned	reserved2;
-	unsigned	next_fp_index;
+	unsigned	next_ndp_index;
 };
 
 #define INIT_NDP16_OPTS {					\
@@ -370,13 +388,14 @@ struct ndp_parser_opts {
 		.ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN,	\
 		.nth_size = sizeof(struct usb_cdc_ncm_nth16),	\
 		.ndp_size = sizeof(struct usb_cdc_ncm_ndp16),	\
+		.dpe_size = sizeof(struct usb_cdc_ncm_dpe16),	\
 		.ndplen_align = 4,				\
 		.dgram_item_len = 1,				\
 		.block_length = 1,				\
-		.fp_index = 1,					\
+		.ndp_index = 1,					\
 		.reserved1 = 0,					\
 		.reserved2 = 0,					\
-		.next_fp_index = 1,				\
+		.next_ndp_index = 1,				\
 	}
 
 
@@ -385,13 +404,14 @@ struct ndp_parser_opts {
 		.ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN,	\
 		.nth_size = sizeof(struct usb_cdc_ncm_nth32),	\
 		.ndp_size = sizeof(struct usb_cdc_ncm_ndp32),	\
+		.dpe_size = sizeof(struct usb_cdc_ncm_dpe32),	\
 		.ndplen_align = 8,				\
 		.dgram_item_len = 2,				\
 		.block_length = 2,				\
-		.fp_index = 2,					\
+		.ndp_index = 2,					\
 		.reserved1 = 1,					\
 		.reserved2 = 2,					\
-		.next_fp_index = 2,				\
+		.next_ndp_index = 2,				\
 	}
 
 static const struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
@@ -803,6 +823,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 
 		if (ncm->port.in_ep->driver_data) {
 			DBG(cdev, "reset ncm\n");
+			ncm->timer_stopping = true;
+			ncm->netdev = NULL;
 			gether_disconnect(&ncm->port);
 			ncm_reset_values(ncm);
 		}
@@ -839,6 +861,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 			net = gether_connect(&ncm->port);
 			if (IS_ERR(net))
 				return PTR_ERR(net);
+			ncm->netdev = net;
+			ncm->timer_stopping = false;
 		}
 
 		spin_lock(&ncm->lock);
@@ -865,95 +889,232 @@ static int ncm_get_alt(struct usb_function *f, unsigned intf)
 	return ncm->port.in_ep->driver_data ? 1 : 0;
 }
 
+static struct sk_buff *package_for_tx(struct f_ncm *ncm)
+{
+	__le16		*ntb_iter;
+	struct sk_buff	*skb2 = NULL;
+	unsigned	ndp_pad;
+	unsigned	ndp_index;
+	unsigned	new_len;
+
+	const struct ndp_parser_opts *opts = ncm->parser_opts;
+	const int ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
+	const int dgram_idx_len = 2 * 2 * opts->dgram_item_len;
+
+	/* Stop the timer */
+	hrtimer_try_to_cancel(&ncm->task_timer);
+
+	ndp_pad = ALIGN(ncm->skb_tx_data->len, ndp_align) -
+			ncm->skb_tx_data->len;
+	ndp_index = ncm->skb_tx_data->len + ndp_pad;
+	new_len = ndp_index + dgram_idx_len + ncm->skb_tx_ndp->len;
+
+	/* Set the final BlockLength and wNdpIndex */
+	ntb_iter = (void *) ncm->skb_tx_data->data;
+	/* Increment pointer to BlockLength */
+	ntb_iter += 2 + 1 + 1;
+	put_ncm(&ntb_iter, opts->block_length, new_len);
+	put_ncm(&ntb_iter, opts->ndp_index, ndp_index);
+
+	/* Set the final NDP wLength */
+	new_len = opts->ndp_size +
+			(ncm->ndp_dgram_count * dgram_idx_len);
+	ncm->ndp_dgram_count = 0;
+	/* Increment from start to wLength */
+	ntb_iter = (void *) ncm->skb_tx_ndp->data;
+	ntb_iter += 2;
+	put_unaligned_le16(new_len, ntb_iter);
+
+	/* Merge the skbs */
+	swap(skb2, ncm->skb_tx_data);
+	if (ncm->skb_tx_data) {
+		dev_kfree_skb_any(ncm->skb_tx_data);
+		ncm->skb_tx_data = NULL;
+	}
+
+	/* Insert NDP alignment. */
+	ntb_iter = (void *) skb_put(skb2, ndp_pad);
+	memset(ntb_iter, 0, ndp_pad);
+
+	/* Copy NTB across. */
+	ntb_iter = (void *) skb_put(skb2, ncm->skb_tx_ndp->len);
+	memcpy(ntb_iter, ncm->skb_tx_ndp->data, ncm->skb_tx_ndp->len);
+	dev_kfree_skb_any(ncm->skb_tx_ndp);
+	ncm->skb_tx_ndp = NULL;
+
+	/* Insert zero'd datagram. */
+	ntb_iter = (void *) skb_put(skb2, dgram_idx_len);
+	memset(ntb_iter, 0, dgram_idx_len);
+
+	return skb2;
+}
+
 static struct sk_buff *ncm_wrap_ntb(struct gether *port,
 				    struct sk_buff *skb)
 {
 	struct f_ncm	*ncm = func_to_ncm(&port->func);
-	struct sk_buff	*skb2;
+	struct sk_buff	*skb2 = NULL;
 	int		ncb_len = 0;
-	__le16		*tmp;
-	int		div;
-	int		rem;
-	int		pad;
-	int		ndp_align;
-	int		ndp_pad;
+	__le16		*ntb_data;
+	__le16		*ntb_ndp;
+	int		dgram_pad;
+
 	unsigned	max_size = ncm->port.fixed_in_len;
 	const struct ndp_parser_opts *opts = ncm->parser_opts;
-	unsigned	crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
-
-	div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
-	rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
-	ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
+	const int ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
+	const int div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
+	const int rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
+	const int dgram_idx_len = 2 * 2 * opts->dgram_item_len;
 
-	ncb_len += opts->nth_size;
-	ndp_pad = ALIGN(ncb_len, ndp_align) - ncb_len;
-	ncb_len += ndp_pad;
-	ncb_len += opts->ndp_size;
-	ncb_len += 2 * 2 * opts->dgram_item_len; /* Datagram entry */
-	ncb_len += 2 * 2 * opts->dgram_item_len; /* Zero datagram entry */
-	pad = ALIGN(ncb_len, div) + rem - ncb_len;
-	ncb_len += pad;
-
-	if (ncb_len + skb->len + crc_len > max_size) {
-		dev_kfree_skb_any(skb);
+	if (!skb && !ncm->skb_tx_data)
 		return NULL;
-	}
 
-	skb2 = skb_copy_expand(skb, ncb_len,
-			       max_size - skb->len - ncb_len - crc_len,
-			       GFP_ATOMIC);
-	dev_kfree_skb_any(skb);
-	if (!skb2)
-		return NULL;
+	if (skb) {
+		/* Add the CRC if required up front */
+		if (ncm->is_crc) {
+			uint32_t	crc;
+			__le16		*crc_pos;
+
+			crc = ~crc32_le(~0,
+					skb->data,
+					skb->len);
+			crc_pos = (void *) skb_put(skb, sizeof(uint32_t));
+			put_unaligned_le32(crc, crc_pos);
+		}
 
-	skb = skb2;
+		/* If the new skb is too big for the current NCM NTB then
+		 * set the current stored skb to be sent now and clear it
+		 * ready for new data.
+		 * NOTE: Assume maximum align for speed of calculation.
+		 */
+		if (ncm->skb_tx_data
+		    && (ncm->ndp_dgram_count >= TX_MAX_NUM_DPE
+		    || (ncm->skb_tx_data->len +
+		    div + rem + skb->len +
+		    ncm->skb_tx_ndp->len + ndp_align + (2 * dgram_idx_len))
+		    > max_size)) {
+			skb2 = package_for_tx(ncm);
+			if (!skb2)
+				goto err;
+		}
 
-	tmp = (void *) skb_push(skb, ncb_len);
-	memset(tmp, 0, ncb_len);
+		if (!ncm->skb_tx_data) {
+			ncb_len = opts->nth_size;
+			dgram_pad = ALIGN(ncb_len, div) + rem - ncb_len;
+			ncb_len += dgram_pad;
 
-	put_unaligned_le32(opts->nth_sign, tmp); /* dwSignature */
-	tmp += 2;
-	/* wHeaderLength */
-	put_unaligned_le16(opts->nth_size, tmp++);
-	tmp++; /* skip wSequence */
-	put_ncm(&tmp, opts->block_length, skb->len); /* (d)wBlockLength */
-	/* (d)wFpIndex */
-	/* the first pointer is right after the NTH + align */
-	put_ncm(&tmp, opts->fp_index, opts->nth_size + ndp_pad);
+			/* Create a new skb for the NTH and datagrams. */
+			ncm->skb_tx_data = alloc_skb(max_size, GFP_ATOMIC);
+			if (!ncm->skb_tx_data)
+				goto err;
 
-	tmp = (void *)tmp + ndp_pad;
+			ntb_data = (void *) skb_put(ncm->skb_tx_data, ncb_len);
+			memset(ntb_data, 0, ncb_len);
+			/* dwSignature */
+			put_unaligned_le32(opts->nth_sign, ntb_data);
+			ntb_data += 2;
+			/* wHeaderLength */
+			put_unaligned_le16(opts->nth_size, ntb_data++);
+
+			/* Allocate an skb for storing the NDP,
+			 * TX_MAX_NUM_DPE should easily suffice for a
+			 * 16k packet.
+			 */
+			ncm->skb_tx_ndp = alloc_skb((int)(opts->ndp_size
+						    + opts->dpe_size
+						    * TX_MAX_NUM_DPE),
+						    GFP_ATOMIC);
+			if (!ncm->skb_tx_ndp)
+				goto err;
+			ntb_ndp = (void *) skb_put(ncm->skb_tx_ndp,
+						    opts->ndp_size);
+			memset(ntb_ndp, 0, ncb_len);
+			/* dwSignature */
+			put_unaligned_le32(ncm->ndp_sign, ntb_ndp);
+			ntb_ndp += 2;
 
-	/* NDP */
-	put_unaligned_le32(ncm->ndp_sign, tmp); /* dwSignature */
-	tmp += 2;
-	/* wLength */
-	put_unaligned_le16(ncb_len - opts->nth_size - pad, tmp++);
+			/* There is always a zeroed entry */
+			ncm->ndp_dgram_count = 1;
 
-	tmp += opts->reserved1;
-	tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */
-	tmp += opts->reserved2;
+			/* Note: we skip opts->next_ndp_index */
+		}
 
-	if (ncm->is_crc) {
-		uint32_t crc;
+		/* Delay the timer. */
+		hrtimer_start(&ncm->task_timer,
+			      ktime_set(0, TX_TIMEOUT_NSECS),
+			      HRTIMER_MODE_REL);
+
+		/* Add the datagram position entries */
+		ntb_ndp = (void *) skb_put(ncm->skb_tx_ndp, dgram_idx_len);
+		memset(ntb_ndp, 0, dgram_idx_len);
+
+		ncb_len = ncm->skb_tx_data->len;
+		dgram_pad = ALIGN(ncb_len, div) + rem - ncb_len;
+		ncb_len += dgram_pad;
+
+		/* (d)wDatagramIndex */
+		put_ncm(&ntb_ndp, opts->dgram_item_len, ncb_len);
+		/* (d)wDatagramLength */
+		put_ncm(&ntb_ndp, opts->dgram_item_len, skb->len);
+		ncm->ndp_dgram_count++;
+
+		/* Add the new data to the skb */
+		ntb_data = (void *) skb_put(ncm->skb_tx_data, dgram_pad);
+		memset(ntb_data, 0, dgram_pad);
+		ntb_data = (void *) skb_put(ncm->skb_tx_data, skb->len);
+		memcpy(ntb_data, skb->data, skb->len);
+		dev_kfree_skb_any(skb);
+		skb = NULL;
 
-		crc = ~crc32_le(~0,
-				skb->data + ncb_len,
-				skb->len - ncb_len);
-		put_unaligned_le32(crc, skb->data + skb->len);
-		skb_put(skb, crc_len);
+	} else if (ncm->skb_tx_data && ncm->timer_force_tx) {
+		/* If the tx was requested because of a timeout then send */
+		skb2 = package_for_tx(ncm);
+		if (!skb2)
+			goto err;
 	}
 
-	/* (d)wDatagramIndex[0] */
-	put_ncm(&tmp, opts->dgram_item_len, ncb_len);
-	/* (d)wDatagramLength[0] */
-	put_ncm(&tmp, opts->dgram_item_len, skb->len - ncb_len);
-	/* (d)wDatagramIndex[1] and  (d)wDatagramLength[1] already zeroed */
+	return skb2;
 
-	if (skb->len > MAX_TX_NONFIXED)
-		memset(skb_put(skb, max_size - skb->len),
-		       0, max_size - skb->len);
+err:
+	ncm->netdev->stats.tx_dropped++;
+
+	if (skb)
+		dev_kfree_skb_any(skb);
+	if (ncm->skb_tx_data)
+		dev_kfree_skb_any(ncm->skb_tx_data);
+	if (ncm->skb_tx_ndp)
+		dev_kfree_skb_any(ncm->skb_tx_ndp);
 
-	return skb;
+	return NULL;
+}
+
+/*
+ * This transmits the NTB if there are frames waiting.
+ */
+static void ncm_tx_tasklet(unsigned long data)
+{
+	struct f_ncm	*ncm = (void *)data;
+
+	if (ncm->timer_stopping)
+		return;
+
+	/* Only send if data is available. */
+	if (ncm->skb_tx_data) {
+		ncm->timer_force_tx = true;
+		ncm->netdev->netdev_ops->ndo_start_xmit(NULL, ncm->netdev);
+		ncm->timer_force_tx = false;
+	}
+}
+
+/*
+ * The transmit should only be run if no skb data has been sent
+ * for a certain duration.
+ */
+static enum hrtimer_restart ncm_tx_timeout(struct hrtimer *data)
+{
+	struct f_ncm *ncm = container_of(data, struct f_ncm, task_timer);
+	tasklet_schedule(&ncm->tx_tasklet);
+	return HRTIMER_NORESTART;
 }
 
 static int ncm_unwrap_ntb(struct gether *port,
@@ -963,6 +1124,7 @@ static int ncm_unwrap_ntb(struct gether *port,
 	struct f_ncm	*ncm = func_to_ncm(&port->func);
 	__le16		*tmp = (void *) skb->data;
 	unsigned	index, index2;
+	int		ndp_index;
 	unsigned	dg_len, dg_len2;
 	unsigned	ndp_len;
 	struct sk_buff	*skb2;
@@ -995,91 +1157,101 @@ static int ncm_unwrap_ntb(struct gether *port,
 		goto err;
 	}
 
-	index = get_ncm(&tmp, opts->fp_index);
-	/* NCM 3.2 */
-	if (((index % 4) != 0) && (index < opts->nth_size)) {
-		INFO(port->func.config->cdev, "Bad index: %x\n",
-			index);
-		goto err;
-	}
-
-	/* walk through NDP */
-	tmp = ((void *)skb->data) + index;
-	if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
-		INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
-		goto err;
-	}
-	tmp += 2;
-
-	ndp_len = get_unaligned_le16(tmp++);
-	/*
-	 * NCM 3.3.1
-	 * entry is 2 items
-	 * item size is 16/32 bits, opts->dgram_item_len * 2 bytes
-	 * minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry
-	 */
-	if ((ndp_len < opts->ndp_size + 2 * 2 * (opts->dgram_item_len * 2))
-	    || (ndp_len % opts->ndplen_align != 0)) {
-		INFO(port->func.config->cdev, "Bad NDP length: %x\n", ndp_len);
-		goto err;
-	}
-	tmp += opts->reserved1;
-	tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */
-	tmp += opts->reserved2;
-
-	ndp_len -= opts->ndp_size;
-	index2 = get_ncm(&tmp, opts->dgram_item_len);
-	dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
-	dgram_counter = 0;
+	ndp_index = get_ncm(&tmp, opts->ndp_index);
 
+	/* Run through all the NDP's in the NTB */
 	do {
-		index = index2;
-		dg_len = dg_len2;
-		if (dg_len < 14 + crc_len) { /* ethernet header + crc */
-			INFO(port->func.config->cdev, "Bad dgram length: %x\n",
-			     dg_len);
+		/* NCM 3.2 */
+		if (((ndp_index % 4) != 0) &&
+				(ndp_index < opts->nth_size)) {
+			INFO(port->func.config->cdev, "Bad index: %#X\n",
+			     ndp_index);
 			goto err;
 		}
-		if (ncm->is_crc) {
-			uint32_t crc, crc2;
-
-			crc = get_unaligned_le32(skb->data +
-						 index + dg_len - crc_len);
-			crc2 = ~crc32_le(~0,
-					 skb->data + index,
-					 dg_len - crc_len);
-			if (crc != crc2) {
-				INFO(port->func.config->cdev, "Bad CRC\n");
-				goto err;
-			}
+
+		/* walk through NDP */
+		tmp = (void *)(skb->data + ndp_index);
+		if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
+			INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
+			goto err;
 		}
+		tmp += 2;
 
+		ndp_len = get_unaligned_le16(tmp++);
+		/*
+		 * NCM 3.3.1
+		 * entry is 2 items
+		 * item size is 16/32 bits, opts->dgram_item_len * 2 bytes
+		 * minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry
+		 * Each entry is a dgram index and a dgram length.
+		 */
+		if ((ndp_len < opts->ndp_size
+				+ 2 * 2 * (opts->dgram_item_len * 2))
+				|| (ndp_len % opts->ndplen_align != 0)) {
+			INFO(port->func.config->cdev, "Bad NDP length: %#X\n",
+			     ndp_len);
+			goto err;
+		}
+		tmp += opts->reserved1;
+		/* Check for another NDP (d)wNextNdpIndex */
+		ndp_index = get_ncm(&tmp, opts->next_ndp_index);
+		tmp += opts->reserved2;
+
+		ndp_len -= opts->ndp_size;
 		index2 = get_ncm(&tmp, opts->dgram_item_len);
 		dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
+		dgram_counter = 0;
+
+		do {
+			index = index2;
+			dg_len = dg_len2;
+			if (dg_len < 14 + crc_len) { /* ethernet hdr + crc */
+				INFO(port->func.config->cdev,
+				     "Bad dgram length: %#X\n", dg_len);
+				goto err;
+			}
+			if (ncm->is_crc) {
+				uint32_t crc, crc2;
+
+				crc = get_unaligned_le32(skb->data +
+							 index + dg_len -
+							 crc_len);
+				crc2 = ~crc32_le(~0,
+						 skb->data + index,
+						 dg_len - crc_len);
+				if (crc != crc2) {
+					INFO(port->func.config->cdev,
+					     "Bad CRC\n");
+					goto err;
+				}
+			}
+
+			index2 = get_ncm(&tmp, opts->dgram_item_len);
+			dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
 
-		if (index2 == 0 || dg_len2 == 0) {
-			skb2 = skb;
-		} else {
-			skb2 = skb_clone(skb, GFP_ATOMIC);
+			/*
+			 * Copy the data into a new skb.
+			 * This ensures the truesize is correct
+			 */
+			skb2 = netdev_alloc_skb_ip_align(ncm->netdev,
+							 dg_len - crc_len);
 			if (skb2 == NULL)
 				goto err;
-		}
+			memcpy(skb_put(skb2, dg_len - crc_len),
+			       skb->data + index, dg_len - crc_len);
 
-		if (!skb_pull(skb2, index)) {
-			ret = -EOVERFLOW;
-			goto err;
-		}
+			skb_queue_tail(list, skb2);
 
-		skb_trim(skb2, dg_len - crc_len);
-		skb_queue_tail(list, skb2);
+			ndp_len -= 2 * (opts->dgram_item_len * 2);
 
-		ndp_len -= 2 * (opts->dgram_item_len * 2);
+			dgram_counter++;
 
-		dgram_counter++;
+			if (index2 == 0 || dg_len2 == 0)
+				break;
+		} while (ndp_len > 2 * (opts->dgram_item_len * 2));
+	} while (ndp_index);
 
-		if (index2 == 0 || dg_len2 == 0)
-			break;
-	} while (ndp_len > 2 * (opts->dgram_item_len * 2)); /* zero entry */
+	dev_kfree_skb_any(skb);
 
 	VDBG(port->func.config->cdev,
 	     "Parsed NTB with %d frames\n", dgram_counter);
@@ -1097,8 +1269,11 @@ static void ncm_disable(struct usb_function *f)
 
 	DBG(cdev, "ncm deactivated\n");
 
-	if (ncm->port.in_ep->driver_data)
+	if (ncm->port.in_ep->driver_data) {
+		ncm->timer_stopping = true;
+		ncm->netdev = NULL;
 		gether_disconnect(&ncm->port);
+	}
 
 	if (ncm->notify->driver_data) {
 		usb_ep_disable(ncm->notify);
@@ -1267,6 +1442,10 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
 	ncm->port.open = ncm_open;
 	ncm->port.close = ncm_close;
 
+	tasklet_init(&ncm->tx_tasklet, ncm_tx_tasklet, (unsigned long) ncm);
+	hrtimer_init(&ncm->task_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	ncm->task_timer.function = ncm_tx_timeout;
+
 	DBG(cdev, "CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n",
 			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
 			ncm->port.in_ep->name, ncm->port.out_ep->name,
@@ -1380,6 +1559,10 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f)
 
 	DBG(c->cdev, "ncm unbind\n");
 
+	hrtimer_cancel(&ncm->task_timer);
+	tasklet_kill(&ncm->tx_tasklet);
+
+	ncm_string_defs[0].id = 0;
 	usb_free_all_descriptors(f);
 
 	kfree(ncm->notify_req->buf);
@@ -1416,6 +1599,7 @@ static struct usb_function *ncm_alloc(struct usb_function_instance *fi)
 	ncm->port.ioport = netdev_priv(opts->net);
 	mutex_unlock(&opts->lock);
 	ncm->port.is_fixed = true;
+	ncm->port.supports_multi_frame = true;
 
 	ncm->port.func.name = "cdc_network";
 	/* descriptors are per-instance copies */
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/function/f_obex.c
index aebae1853bce..aebae1853bce 100644
--- a/drivers/usb/gadget/f_obex.c
+++ b/drivers/usb/gadget/function/f_obex.c
diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/function/f_phonet.c
index f2b781773eed..f2b781773eed 100644
--- a/drivers/usb/gadget/f_phonet.c
+++ b/drivers/usb/gadget/function/f_phonet.c
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c
index 9c41e9515b8e..ddb09dc6d1f2 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/function/f_rndis.c
@@ -727,6 +727,10 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
 	rndis_control_intf.bInterfaceNumber = status;
 	rndis_union_desc.bMasterInterface0 = status;
 
+	if (cdev->use_os_string)
+		f->os_desc_table[0].if_id =
+			rndis_iad_descriptor.bFirstInterface;
+
 	status = usb_interface_id(c, f);
 	if (status < 0)
 		goto fail;
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/function/f_serial.c
index 9ecbcbf36a45..9ecbcbf36a45 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/function/f_serial.c
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c
index d3cd52db78fe..d3cd52db78fe 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/function/f_sourcesink.c
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/function/f_subset.c
index 1ea8baf33333..1ea8baf33333 100644
--- a/drivers/usb/gadget/f_subset.c
+++ b/drivers/usb/gadget/function/f_subset.c
diff --git a/drivers/usb/gadget/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c
index 2b4c82d84bfc..2b4c82d84bfc 100644
--- a/drivers/usb/gadget/f_uac1.c
+++ b/drivers/usb/gadget/function/f_uac1.c
diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index 6261db4a9910..3ed89ecc8d6d 100644
--- a/drivers/usb/gadget/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -348,14 +348,34 @@ static int uac2_pcm_open(struct snd_pcm_substream *substream)
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		spin_lock_init(&uac2->p_prm.lock);
 		runtime->hw.rate_min = p_srate;
-		runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! p_ssize ! */
+		switch (p_ssize) {
+		case 3:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
+			break;
+		case 4:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
+			break;
+		default:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+			break;
+		}
 		runtime->hw.channels_min = num_channels(p_chmask);
 		runtime->hw.period_bytes_min = 2 * uac2->p_prm.max_psize
 						/ runtime->hw.periods_min;
 	} else {
 		spin_lock_init(&uac2->c_prm.lock);
 		runtime->hw.rate_min = c_srate;
-		runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! c_ssize ! */
+		switch (c_ssize) {
+		case 3:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
+			break;
+		case 4:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
+			break;
+		default:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+			break;
+		}
 		runtime->hw.channels_min = num_channels(c_chmask);
 		runtime->hw.period_bytes_min = 2 * uac2->c_prm.max_psize
 						/ runtime->hw.periods_min;
diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
index e2a1f50bd93c..e2a1f50bd93c 100644
--- a/drivers/usb/gadget/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
diff --git a/drivers/usb/gadget/f_uvc.h b/drivers/usb/gadget/function/f_uvc.h
index ec52752f7326..ec52752f7326 100644
--- a/drivers/usb/gadget/f_uvc.h
+++ b/drivers/usb/gadget/function/f_uvc.h
diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/function/g_zero.h
index 15f180904f8a..15f180904f8a 100644
--- a/drivers/usb/gadget/g_zero.h
+++ b/drivers/usb/gadget/function/g_zero.h
diff --git a/drivers/usb/gadget/ndis.h b/drivers/usb/gadget/function/ndis.h
index a19f72dec0cd..a19f72dec0cd 100644
--- a/drivers/usb/gadget/ndis.h
+++ b/drivers/usb/gadget/function/ndis.h
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/function/rndis.c
index 95d2324f6977..95d2324f6977 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/function/rndis.c
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/function/rndis.h
index 0f4abb4c3775..0f4abb4c3775 100644
--- a/drivers/usb/gadget/rndis.h
+++ b/drivers/usb/gadget/function/rndis.h
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/function/storage_common.c
index 648f9e489b39..648f9e489b39 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/function/storage_common.c
diff --git a/drivers/usb/gadget/storage_common.h b/drivers/usb/gadget/function/storage_common.h
index 70c891469f57..70c891469f57 100644
--- a/drivers/usb/gadget/storage_common.h
+++ b/drivers/usb/gadget/function/storage_common.h
diff --git a/drivers/usb/gadget/u_ecm.h b/drivers/usb/gadget/function/u_ecm.h
index 262cc03cc2c0..262cc03cc2c0 100644
--- a/drivers/usb/gadget/u_ecm.h
+++ b/drivers/usb/gadget/function/u_ecm.h
diff --git a/drivers/usb/gadget/u_eem.h b/drivers/usb/gadget/function/u_eem.h
index e3ae97874c4f..e3ae97874c4f 100644
--- a/drivers/usb/gadget/u_eem.h
+++ b/drivers/usb/gadget/function/u_eem.h
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index 97b027724ee7..d50adda913cf 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -483,7 +483,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
 					struct net_device *net)
 {
 	struct eth_dev		*dev = netdev_priv(net);
-	int			length = skb->len;
+	int			length = 0;
 	int			retval;
 	struct usb_request	*req = NULL;
 	unsigned long		flags;
@@ -500,13 +500,13 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
 	}
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	if (!in) {
+	if (skb && !in) {
 		dev_kfree_skb_any(skb);
 		return NETDEV_TX_OK;
 	}
 
 	/* apply outgoing CDC or RNDIS filters */
-	if (!is_promisc(cdc_filter)) {
+	if (skb && !is_promisc(cdc_filter)) {
 		u8		*dest = skb->data;
 
 		if (is_multicast_ether_addr(dest)) {
@@ -557,11 +557,17 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
 		if (dev->port_usb)
 			skb = dev->wrap(dev->port_usb, skb);
 		spin_unlock_irqrestore(&dev->lock, flags);
-		if (!skb)
+		if (!skb) {
+			/* Multi frame CDC protocols may store the frame for
+			 * later which is not a dropped frame.
+			 */
+			if (dev->port_usb->supports_multi_frame)
+				goto multiframe;
 			goto drop;
-
-		length = skb->len;
+		}
 	}
+
+	length = skb->len;
 	req->buf = skb->data;
 	req->context = skb;
 	req->complete = tx_complete;
@@ -604,6 +610,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
 		dev_kfree_skb_any(skb);
 drop:
 		dev->net->stats.tx_dropped++;
+multiframe:
 		spin_lock_irqsave(&dev->req_lock, flags);
 		if (list_empty(&dev->tx_reqs))
 			netif_start_queue(net);
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/function/u_ether.h
index 0f0290acea7e..334b38947916 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/function/u_ether.h
@@ -18,6 +18,7 @@
 #include <linux/if_ether.h>
 #include <linux/usb/composite.h>
 #include <linux/usb/cdc.h>
+#include <linux/netdevice.h>
 
 #include "gadget_chips.h"
 
@@ -74,6 +75,7 @@ struct gether {
 	bool				is_fixed;
 	u32				fixed_out_len;
 	u32				fixed_in_len;
+	bool				supports_multi_frame;
 	struct sk_buff			*(*wrap)(struct gether *port,
 						struct sk_buff *skb);
 	int				(*unwrap)(struct gether *port,
diff --git a/drivers/usb/gadget/u_ether_configfs.h b/drivers/usb/gadget/function/u_ether_configfs.h
index bcbd30146cfd..bcbd30146cfd 100644
--- a/drivers/usb/gadget/u_ether_configfs.h
+++ b/drivers/usb/gadget/function/u_ether_configfs.h
diff --git a/drivers/usb/gadget/u_fs.h b/drivers/usb/gadget/function/u_fs.h
index bf0ba375d459..63d6e71569c1 100644
--- a/drivers/usb/gadget/u_fs.h
+++ b/drivers/usb/gadget/function/u_fs.h
@@ -216,6 +216,13 @@ struct ffs_data {
 	unsigned			fs_descs_count;
 	unsigned			hs_descs_count;
 	unsigned			ss_descs_count;
+	unsigned			ms_os_descs_count;
+	unsigned			ms_os_descs_ext_prop_count;
+	unsigned			ms_os_descs_ext_prop_name_len;
+	unsigned			ms_os_descs_ext_prop_data_len;
+	void				*ms_os_descs_ext_prop_avail;
+	void				*ms_os_descs_ext_prop_name_avail;
+	void				*ms_os_descs_ext_prop_data_avail;
 
 	unsigned short			strings_count;
 	unsigned short			interfaces_count;
diff --git a/drivers/usb/gadget/u_gether.h b/drivers/usb/gadget/function/u_gether.h
index d4078426ba5d..d4078426ba5d 100644
--- a/drivers/usb/gadget/u_gether.h
+++ b/drivers/usb/gadget/function/u_gether.h
diff --git a/drivers/usb/gadget/u_ncm.h b/drivers/usb/gadget/function/u_ncm.h
index ce0f3a78ca13..ce0f3a78ca13 100644
--- a/drivers/usb/gadget/u_ncm.h
+++ b/drivers/usb/gadget/function/u_ncm.h
diff --git a/drivers/usb/gadget/u_phonet.h b/drivers/usb/gadget/function/u_phonet.h
index 98ced18779ea..98ced18779ea 100644
--- a/drivers/usb/gadget/u_phonet.h
+++ b/drivers/usb/gadget/function/u_phonet.h
diff --git a/drivers/usb/gadget/u_rndis.h b/drivers/usb/gadget/function/u_rndis.h
index e902aa42a297..e902aa42a297 100644
--- a/drivers/usb/gadget/u_rndis.h
+++ b/drivers/usb/gadget/function/u_rndis.h
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/function/u_serial.c
index ad0aca812002..ad0aca812002 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/function/u_serial.h
index c20210c0babd..c20210c0babd 100644
--- a/drivers/usb/gadget/u_serial.h
+++ b/drivers/usb/gadget/function/u_serial.h
diff --git a/drivers/usb/gadget/u_uac1.c b/drivers/usb/gadget/function/u_uac1.c
index 7a55fea43430..7a55fea43430 100644
--- a/drivers/usb/gadget/u_uac1.c
+++ b/drivers/usb/gadget/function/u_uac1.c
diff --git a/drivers/usb/gadget/u_uac1.h b/drivers/usb/gadget/function/u_uac1.h
index 18c2e729faf6..18c2e729faf6 100644
--- a/drivers/usb/gadget/u_uac1.h
+++ b/drivers/usb/gadget/function/u_uac1.h
diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/function/uvc.h
index 7a9111de8054..7a9111de8054 100644
--- a/drivers/usb/gadget/uvc.h
+++ b/drivers/usb/gadget/function/uvc.h
diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c
index 1c29bc954db9..1c29bc954db9 100644
--- a/drivers/usb/gadget/uvc_queue.c
+++ b/drivers/usb/gadget/function/uvc_queue.c
diff --git a/drivers/usb/gadget/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h
index 8e76ce982f1e..8e76ce982f1e 100644
--- a/drivers/usb/gadget/uvc_queue.h
+++ b/drivers/usb/gadget/function/uvc_queue.h
diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c
index ad48e81155e2..ad48e81155e2 100644
--- a/drivers/usb/gadget/uvc_v4l2.c
+++ b/drivers/usb/gadget/function/uvc_v4l2.c
diff --git a/drivers/usb/gadget/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c
index 71e896d4c5ae..71e896d4c5ae 100644
--- a/drivers/usb/gadget/uvc_video.c
+++ b/drivers/usb/gadget/function/uvc_video.c
diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig
new file mode 100644
index 000000000000..aa376f006333
--- /dev/null
+++ b/drivers/usb/gadget/legacy/Kconfig
@@ -0,0 +1,475 @@
+#
+# 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).
+#
+
+config USB_ZERO
+	tristate "Gadget Zero (DEVELOPMENT)"
+	select USB_LIBCOMPOSITE
+	select USB_F_SS_LB
+	help
+	  Gadget Zero is a two-configuration device.  It either sinks and
+	  sources bulk data; or it loops back a configurable number of
+	  transfers.  It also implements control requests, for "chapter 9"
+	  conformance.  The driver needs only two bulk-capable endpoints, so
+	  it can work on top of most device-side usb controllers.  It's
+	  useful for testing, and is also a working example showing how
+	  USB "gadget drivers" can be written.
+
+	  Make this be the first driver you try using on top of any new
+	  USB peripheral controller driver.  Then you can use host-side
+	  test software, like the "usbtest" driver, to put your hardware
+	  and its driver through a basic set of functional tests.
+
+	  Gadget Zero also works with the host-side "usb-skeleton" driver,
+	  and with many kinds of host-side test software.  You may need
+	  to tweak product and vendor IDs before host software knows about
+	  this device, and arrange to select an appropriate configuration.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_zero".
+
+config USB_ZERO_HNPTEST
+	boolean "HNP Test Device"
+	depends on USB_ZERO && USB_OTG
+	help
+	  You can configure this device to enumerate using the device
+	  identifiers of the USB-OTG test device.  That means that when
+	  this gadget connects to another OTG device, with this one using
+	  the "B-Peripheral" role, that device will use HNP to let this
+	  one serve as the USB host instead (in the "B-Host" role).
+
+config USB_AUDIO
+	tristate "Audio Gadget"
+	depends on SND
+	select USB_LIBCOMPOSITE
+	select SND_PCM
+	help
+	  This Gadget Audio driver is compatible with USB Audio Class
+	  specification 2.0. It implements 1 AudioControl interface,
+	  1 AudioStreaming Interface each for USB-OUT and USB-IN.
+	  Number of channels, sample rate and sample size can be
+	  specified as module parameters.
+	  This driver doesn't expect any real Audio codec to be present
+	  on the device - the audio streams are simply sinked to and
+	  sourced from a virtual ALSA sound card created. The user-space
+	  application may choose to do whatever it wants with the data
+	  received from the USB Host and choose to provide whatever it
+	  wants as audio data to the USB Host.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_audio".
+
+config GADGET_UAC1
+	bool "UAC 1.0 (Legacy)"
+	depends on USB_AUDIO
+	help
+	  If you instead want older UAC Spec-1.0 driver that also has audio
+	  paths hardwired to the Audio codec chip on-board and doesn't work
+	  without one.
+
+config USB_ETH
+	tristate "Ethernet Gadget (with CDC Ethernet support)"
+	depends on NET
+	select USB_LIBCOMPOSITE
+	select USB_U_ETHER
+	select USB_F_ECM
+	select USB_F_SUBSET
+	select CRC32
+	help
+	  This driver implements Ethernet style communication, in one of
+	  several ways:
+
+	   - The "Communication Device Class" (CDC) Ethernet Control Model.
+	     That protocol is often avoided with pure Ethernet adapters, in
+	     favor of simpler vendor-specific hardware, but is widely
+	     supported by firmware for smart network devices.
+
+	   - On hardware can't implement that protocol, a simple CDC subset
+	     is used, placing fewer demands on USB.
+
+	   - CDC Ethernet Emulation Model (EEM) is a newer standard that has
+	     a simpler interface that can be used by more USB hardware.
+
+	  RNDIS support is an additional option, more demanding than than
+	  subset.
+
+	  Within the USB device, this gadget driver exposes a network device
+	  "usbX", where X depends on what other networking devices you have.
+	  Treat it like a two-node Ethernet link:  host, and gadget.
+
+	  The Linux-USB host-side "usbnet" driver interoperates with this
+	  driver, so that deep I/O queues can be supported.  On 2.4 kernels,
+	  use "CDCEther" instead, if you're using the CDC option. That CDC
+	  mode should also interoperate with standard CDC Ethernet class
+	  drivers on other host operating systems.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_ether".
+
+config USB_ETH_RNDIS
+	bool "RNDIS support"
+	depends on USB_ETH
+	select USB_LIBCOMPOSITE
+	select USB_F_RNDIS
+	default y
+	help
+	   Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
+	   and Microsoft provides redistributable binary RNDIS drivers for
+	   older versions of Windows.
+
+	   If you say "y" here, the Ethernet gadget driver will try to provide
+	   a second device configuration, supporting RNDIS to talk to such
+	   Microsoft USB hosts.
+
+	   To make MS-Windows work with this, use Documentation/usb/linux.inf
+	   as the "driver info file".  For versions of MS-Windows older than
+	   XP, you'll need to download drivers from Microsoft's website; a URL
+	   is given in comments found in that info file.
+
+config USB_ETH_EEM
+       bool "Ethernet Emulation Model (EEM) support"
+       depends on USB_ETH
+	select USB_LIBCOMPOSITE
+	select USB_F_EEM
+       default n
+       help
+         CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
+         and therefore can be supported by more hardware.  Technically ECM and
+         EEM are designed for different applications.  The ECM model extends
+         the network interface to the target (e.g. a USB cable modem), and the
+         EEM model is for mobile devices to communicate with hosts using
+         ethernet over USB.  For Linux gadgets, however, the interface with
+         the host is the same (a usbX device), so the differences are minimal.
+
+         If you say "y" here, the Ethernet gadget driver will use the EEM
+         protocol rather than ECM.  If unsure, say "n".
+
+config USB_G_NCM
+	tristate "Network Control Model (NCM) support"
+	depends on NET
+	select USB_LIBCOMPOSITE
+	select USB_U_ETHER
+	select USB_F_NCM
+	select CRC32
+	help
+	  This driver implements USB CDC NCM subclass standard. NCM is
+	  an advanced protocol for Ethernet encapsulation, allows grouping
+	  of several ethernet frames into one USB transfer and different
+	  alignment possibilities.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_ncm".
+
+config USB_GADGETFS
+	tristate "Gadget Filesystem"
+	help
+	  This driver provides a filesystem based API that lets user mode
+	  programs implement a single-configuration USB device, including
+	  endpoint I/O and control requests that don't relate to enumeration.
+	  All endpoints, transfer speeds, and transfer types supported by
+	  the hardware are available, through read() and write() calls.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "gadgetfs".
+
+config USB_FUNCTIONFS
+	tristate "Function Filesystem"
+	select USB_LIBCOMPOSITE
+	select USB_F_FS
+	select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
+	help
+	  The Function Filesystem (FunctionFS) lets one create USB
+	  composite functions in user space in the same way GadgetFS
+	  lets one create USB gadgets in user space.  This allows creation
+	  of composite gadgets such that some of the functions are
+	  implemented in kernel space (for instance Ethernet, serial or
+	  mass storage) and other are implemented in user space.
+
+	  If you say "y" or "m" here you will be able what kind of
+	  configurations the gadget will provide.
+
+	  Say "y" to link the driver statically, or "m" to build
+	  a dynamically linked module called "g_ffs".
+
+config USB_FUNCTIONFS_ETH
+	bool "Include configuration with CDC ECM (Ethernet)"
+	depends on USB_FUNCTIONFS && NET
+	select USB_U_ETHER
+	select USB_F_ECM
+	select USB_F_SUBSET
+	help
+	  Include a configuration with CDC ECM function (Ethernet) and the
+	  Function Filesystem.
+
+config USB_FUNCTIONFS_RNDIS
+	bool "Include configuration with RNDIS (Ethernet)"
+	depends on USB_FUNCTIONFS && NET
+	select USB_U_ETHER
+	select USB_F_RNDIS
+	help
+	  Include a configuration with RNDIS function (Ethernet) and the Filesystem.
+
+config USB_FUNCTIONFS_GENERIC
+	bool "Include 'pure' configuration"
+	depends on USB_FUNCTIONFS
+	help
+	  Include a configuration with the Function Filesystem alone with
+	  no Ethernet interface.
+
+config USB_MASS_STORAGE
+	tristate "Mass Storage Gadget"
+	depends on BLOCK
+	select USB_LIBCOMPOSITE
+	select USB_F_MASS_STORAGE
+	help
+	  The Mass Storage Gadget acts as a USB Mass Storage disk drive.
+	  As its storage repository it can use a regular file or a block
+	  device (in much the same way as the "loop" device driver),
+	  specified as a module parameter or sysfs option.
+
+	  This driver is a replacement for now removed File-backed
+	  Storage Gadget (g_file_storage).
+
+	  Say "y" to link the driver statically, or "m" to build
+	  a dynamically linked module called "g_mass_storage".
+
+config USB_GADGET_TARGET
+	tristate "USB Gadget Target Fabric Module"
+	depends on TARGET_CORE
+	select USB_LIBCOMPOSITE
+	help
+	  This fabric is an USB gadget. Two USB protocols are supported that is
+	  BBB or BOT (Bulk Only Transport) and UAS (USB Attached SCSI). BOT is
+	  advertised on alternative interface 0 (primary) and UAS is on
+	  alternative interface 1. Both protocols can work on USB2.0 and USB3.0.
+	  UAS utilizes the USB 3.0 feature called streams support.
+
+config USB_G_SERIAL
+	tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
+	depends on TTY
+	select USB_U_SERIAL
+	select USB_F_ACM
+	select USB_F_SERIAL
+	select USB_F_OBEX
+	select USB_LIBCOMPOSITE
+	help
+	  The Serial Gadget talks to the Linux-USB generic serial driver.
+	  This driver supports a CDC-ACM module option, which can be used
+	  to interoperate with MS-Windows hosts or with the Linux-USB
+	  "cdc-acm" driver.
+
+	  This driver also supports a CDC-OBEX option.  You will need a
+	  user space OBEX server talking to /dev/ttyGS*, since the kernel
+	  itself doesn't implement the OBEX protocol.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_serial".
+
+	  For more information, see Documentation/usb/gadget_serial.txt
+	  which includes instructions and a "driver info file" needed to
+	  make MS-Windows work with CDC ACM.
+
+config USB_MIDI_GADGET
+	tristate "MIDI Gadget"
+	depends on SND
+	select USB_LIBCOMPOSITE
+	select SND_RAWMIDI
+	help
+	  The MIDI Gadget acts as a USB Audio device, with one MIDI
+	  input and one MIDI output. These MIDI jacks appear as
+	  a sound "card" in the ALSA sound system. Other MIDI
+	  connections can then be made on the gadget system, using
+	  ALSA's aconnect utility etc.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_midi".
+
+config USB_G_PRINTER
+	tristate "Printer Gadget"
+	select USB_LIBCOMPOSITE
+	help
+	  The Printer Gadget channels data between the USB host and a
+	  userspace program driving the print engine. The user space
+	  program reads and writes the device file /dev/g_printer to
+	  receive or send printer data. It can use ioctl calls to
+	  the device file to get or set printer status.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_printer".
+
+	  For more information, see Documentation/usb/gadget_printer.txt
+	  which includes sample code for accessing the device file.
+
+if TTY
+
+config USB_CDC_COMPOSITE
+	tristate "CDC Composite Device (Ethernet and ACM)"
+	depends on NET
+	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_U_ETHER
+	select USB_F_ACM
+	select USB_F_ECM
+	help
+	  This driver provides two functions in one configuration:
+	  a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
+
+	  This driver requires four bulk and two interrupt endpoints,
+	  plus the ability to handle altsettings.  Not all peripheral
+	  controllers are that capable.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module.
+
+config USB_G_NOKIA
+	tristate "Nokia composite gadget"
+	depends on PHONET
+	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_U_ETHER
+	select USB_F_ACM
+	select USB_F_OBEX
+	select USB_F_PHONET
+	select USB_F_ECM
+	help
+	  The Nokia composite gadget provides support for acm, obex
+	  and phonet in only one composite gadget driver.
+
+	  It's only really useful for N900 hardware. If you're building
+	  a kernel for N900, say Y or M here. If unsure, say N.
+
+config USB_G_ACM_MS
+	tristate "CDC Composite Device (ACM and mass storage)"
+	depends on BLOCK
+	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_F_ACM
+	select USB_F_MASS_STORAGE
+	help
+	  This driver provides two functions in one configuration:
+	  a mass storage, and a CDC ACM (serial port) link.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_acm_ms".
+
+config USB_G_MULTI
+	tristate "Multifunction Composite Gadget"
+	depends on BLOCK && NET
+	select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
+	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_U_ETHER
+	select USB_F_ACM
+	select USB_F_MASS_STORAGE
+	help
+	  The Multifunction Composite Gadget provides Ethernet (RNDIS
+	  and/or CDC Ethernet), mass storage and ACM serial link
+	  interfaces.
+
+	  You will be asked to choose which of the two configurations is
+	  to be available in the gadget.  At least one configuration must
+	  be chosen to make the gadget usable.  Selecting more than one
+	  configuration will prevent Windows from automatically detecting
+	  the gadget as a composite gadget, so an INF file will be needed to
+	  use the gadget.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_multi".
+
+config USB_G_MULTI_RNDIS
+	bool "RNDIS + CDC Serial + Storage configuration"
+	depends on USB_G_MULTI
+	select USB_F_RNDIS
+	default y
+	help
+	  This option enables a configuration with RNDIS, CDC Serial and
+	  Mass Storage functions available in the Multifunction Composite
+	  Gadget.  This is the configuration dedicated for Windows since RNDIS
+	  is Microsoft's protocol.
+
+	  If unsure, say "y".
+
+config USB_G_MULTI_CDC
+	bool "CDC Ethernet + CDC Serial + Storage configuration"
+	depends on USB_G_MULTI
+	default n
+	select USB_F_ECM
+	help
+	  This option enables a configuration with CDC Ethernet (ECM), CDC
+	  Serial and Mass Storage functions available in the Multifunction
+	  Composite Gadget.
+
+	  If unsure, say "y".
+
+endif # TTY
+
+config USB_G_HID
+	tristate "HID Gadget"
+	select USB_LIBCOMPOSITE
+	help
+	  The HID gadget driver provides generic emulation of USB
+	  Human Interface Devices (HID).
+
+	  For more information, see Documentation/usb/gadget_hid.txt which
+	  includes sample code for accessing the device files.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_hid".
+
+# Standalone / single function gadgets
+config USB_G_DBGP
+	tristate "EHCI Debug Device Gadget"
+	depends on TTY
+	select USB_LIBCOMPOSITE
+	help
+	  This gadget emulates an EHCI Debug device. This is useful when you want
+	  to interact with an EHCI Debug Port.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_dbgp".
+
+if USB_G_DBGP
+choice
+	prompt "EHCI Debug Device mode"
+	default USB_G_DBGP_SERIAL
+
+config USB_G_DBGP_PRINTK
+	depends on USB_G_DBGP
+	bool "printk"
+	help
+	  Directly printk() received data. No interaction.
+
+config USB_G_DBGP_SERIAL
+	depends on USB_G_DBGP
+	select USB_U_SERIAL
+	bool "serial"
+	help
+	  Userland can interact using /dev/ttyGSxxx.
+endchoice
+endif
+
+# put drivers that need isochronous transfer support (for audio
+# or video class gadget drivers), or specific hardware, here.
+config USB_G_WEBCAM
+	tristate "USB Webcam Gadget"
+	depends on VIDEO_DEV
+	select USB_LIBCOMPOSITE
+	select VIDEOBUF2_VMALLOC
+	help
+	  The Webcam Gadget acts as a composite USB Audio and Video Class
+	  device. It provides a userspace API to process UVC control requests
+	  and stream video data to the host.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_webcam".
diff --git a/drivers/usb/gadget/legacy/Makefile b/drivers/usb/gadget/legacy/Makefile
new file mode 100644
index 000000000000..a11aad5635df
--- /dev/null
+++ b/drivers/usb/gadget/legacy/Makefile
@@ -0,0 +1,44 @@
+#
+# USB gadget drivers
+#
+
+ccflags-y			:= -I$(PWD)/drivers/usb/gadget/
+ccflags-y			+= -I$(PWD)/drivers/usb/gadget/udc/
+ccflags-y			+= -I$(PWD)/drivers/usb/gadget/function/
+
+g_zero-y			:= zero.o
+g_audio-y			:= audio.o
+g_ether-y			:= ether.o
+g_serial-y			:= serial.o
+g_midi-y			:= gmidi.o
+gadgetfs-y			:= inode.o
+g_mass_storage-y		:= mass_storage.o
+g_printer-y			:= printer.o
+g_cdc-y				:= cdc2.o
+g_multi-y			:= multi.o
+g_hid-y				:= hid.o
+g_dbgp-y			:= dbgp.o
+g_nokia-y			:= nokia.o
+g_webcam-y			:= webcam.o
+g_ncm-y				:= ncm.o
+g_acm_ms-y			:= acm_ms.o
+g_tcm_usb_gadget-y		:= tcm_usb_gadget.o
+
+obj-$(CONFIG_USB_ZERO)		+= g_zero.o
+obj-$(CONFIG_USB_AUDIO)		+= g_audio.o
+obj-$(CONFIG_USB_ETH)		+= g_ether.o
+obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o
+obj-$(CONFIG_USB_FUNCTIONFS)	+= g_ffs.o
+obj-$(CONFIG_USB_MASS_STORAGE)	+= g_mass_storage.o
+obj-$(CONFIG_USB_G_SERIAL)	+= g_serial.o
+obj-$(CONFIG_USB_G_PRINTER)	+= g_printer.o
+obj-$(CONFIG_USB_MIDI_GADGET)	+= g_midi.o
+obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
+obj-$(CONFIG_USB_G_HID)		+= g_hid.o
+obj-$(CONFIG_USB_G_DBGP)	+= g_dbgp.o
+obj-$(CONFIG_USB_G_MULTI)	+= g_multi.o
+obj-$(CONFIG_USB_G_NOKIA)	+= g_nokia.o
+obj-$(CONFIG_USB_G_WEBCAM)	+= g_webcam.o
+obj-$(CONFIG_USB_G_NCM)		+= g_ncm.o
+obj-$(CONFIG_USB_G_ACM_MS)	+= g_acm_ms.o
+obj-$(CONFIG_USB_GADGET_TARGET)	+= tcm_usb_gadget.o
diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/legacy/acm_ms.c
index a252444cc0a7..c30b7b572465 100644
--- a/drivers/usb/gadget/acm_ms.c
+++ b/drivers/usb/gadget/legacy/acm_ms.c
@@ -267,18 +267,8 @@ static __refdata struct usb_composite_driver acm_ms_driver = {
 	.unbind		= __exit_p(acm_ms_unbind),
 };
 
+module_usb_composite_driver(acm_ms_driver);
+
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Klaus Schwarzkopf <schwarzkopf@sensortherm.de>");
 MODULE_LICENSE("GPL v2");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&acm_ms_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&acm_ms_driver);
-}
-module_exit(cleanup);
diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/legacy/audio.c
index 231b0efe8fdc..6eb695e5e43a 100644
--- a/drivers/usb/gadget/audio.c
+++ b/drivers/usb/gadget/legacy/audio.c
@@ -172,17 +172,7 @@ static __refdata struct usb_composite_driver audio_driver = {
 	.unbind		= __exit_p(audio_unbind),
 };
 
-static int __init init(void)
-{
-	return usb_composite_probe(&audio_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&audio_driver);
-}
-module_exit(cleanup);
+module_usb_composite_driver(audio_driver);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Bryan Wu <cooloney@kernel.org>");
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/legacy/cdc2.c
index e126b6b248e6..2e85d9473478 100644
--- a/drivers/usb/gadget/cdc2.c
+++ b/drivers/usb/gadget/legacy/cdc2.c
@@ -231,18 +231,8 @@ static __refdata struct usb_composite_driver cdc_driver = {
 	.unbind		= __exit_p(cdc_unbind),
 };
 
+module_usb_composite_driver(cdc_driver);
+
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("David Brownell");
 MODULE_LICENSE("GPL");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&cdc_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&cdc_driver);
-}
-module_exit(cleanup);
diff --git a/drivers/usb/gadget/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c
index 986fc511a2ed..986fc511a2ed 100644
--- a/drivers/usb/gadget/dbgp.c
+++ b/drivers/usb/gadget/legacy/dbgp.c
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/legacy/ether.c
index c1c113ef950c..c5fdc61cdc4a 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/legacy/ether.c
@@ -475,18 +475,8 @@ static __refdata struct usb_composite_driver eth_driver = {
 	.unbind		= __exit_p(eth_unbind),
 };
 
+module_usb_composite_driver(eth_driver);
+
 MODULE_DESCRIPTION(PREFIX DRIVER_DESC);
 MODULE_AUTHOR("David Brownell, Benedikt Spanger");
 MODULE_LICENSE("GPL");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&eth_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&eth_driver);
-}
-module_exit(cleanup);
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/legacy/g_ffs.c
index fe12e6a27448..06acfa55864a 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/legacy/g_ffs.c
@@ -276,7 +276,7 @@ module_exit(gfs_exit);
 static void *functionfs_acquire_dev(struct ffs_dev *dev)
 {
 	if (!try_module_get(THIS_MODULE))
-		return ERR_PTR(-ENODEV);
+		return ERR_PTR(-ENOENT);
 	
 	return 0;
 }
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/legacy/gmidi.c
index e879e2c9f461..3d696b86ff76 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/legacy/gmidi.c
@@ -163,15 +163,4 @@ static __refdata struct usb_composite_driver midi_driver = {
 	.unbind		= __exit_p(midi_unbind),
 };
 
-static int __init midi_init(void)
-{
-	return usb_composite_probe(&midi_driver);
-}
-module_init(midi_init);
-
-static void __exit midi_cleanup(void)
-{
-	usb_composite_unregister(&midi_driver);
-}
-module_exit(midi_cleanup);
-
+module_usb_composite_driver(midi_driver);
diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/legacy/hid.c
index 778613eb37af..778613eb37af 100644
--- a/drivers/usb/gadget/hid.c
+++ b/drivers/usb/gadget/legacy/hid.c
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/legacy/inode.c
index 2e4ce7704908..2e4ce7704908 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/legacy/mass_storage.c
index 8e27a8c96444..8e27a8c96444 100644
--- a/drivers/usb/gadget/mass_storage.c
+++ b/drivers/usb/gadget/legacy/mass_storage.c
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/legacy/multi.c
index 940f6cde8e89..39d27bb343b4 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/legacy/multi.c
@@ -507,15 +507,4 @@ static __refdata struct usb_composite_driver multi_driver = {
 	.needs_serial	= 1,
 };
 
-
-static int __init multi_init(void)
-{
-	return usb_composite_probe(&multi_driver);
-}
-module_init(multi_init);
-
-static void __exit multi_exit(void)
-{
-	usb_composite_unregister(&multi_driver);
-}
-module_exit(multi_exit);
+module_usb_composite_driver(multi_driver);
diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/legacy/ncm.c
index 81956feca1bd..e90e23db2acb 100644
--- a/drivers/usb/gadget/ncm.c
+++ b/drivers/usb/gadget/legacy/ncm.c
@@ -204,18 +204,8 @@ static __refdata struct usb_composite_driver ncm_driver = {
 	.unbind		= __exit_p(gncm_unbind),
 };
 
+module_usb_composite_driver(ncm_driver);
+
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Yauheni Kaliuta");
 MODULE_LICENSE("GPL");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&ncm_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&ncm_driver);
-}
-module_exit(cleanup);
diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/legacy/nokia.c
index 3ab386167519..9b8fd701648c 100644
--- a/drivers/usb/gadget/nokia.c
+++ b/drivers/usb/gadget/legacy/nokia.c
@@ -347,14 +347,4 @@ static __refdata struct usb_composite_driver nokia_driver = {
 	.unbind		= __exit_p(nokia_unbind),
 };
 
-static int __init nokia_init(void)
-{
-	return usb_composite_probe(&nokia_driver);
-}
-module_init(nokia_init);
-
-static void __exit nokia_cleanup(void)
-{
-	usb_composite_unregister(&nokia_driver);
-}
-module_exit(nokia_cleanup);
+module_usb_composite_driver(nokia_driver);
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/legacy/printer.c
index 6474081dcbaf..6474081dcbaf 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/legacy/printer.c
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/legacy/serial.c
index 1f5f978d35d5..1f5f978d35d5 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/legacy/serial.c
diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/legacy/tcm_usb_gadget.c
index 6cdb7a534f23..6cdb7a534f23 100644
--- a/drivers/usb/gadget/tcm_usb_gadget.c
+++ b/drivers/usb/gadget/legacy/tcm_usb_gadget.c
diff --git a/drivers/usb/gadget/tcm_usb_gadget.h b/drivers/usb/gadget/legacy/tcm_usb_gadget.h
index 8289219925b8..8289219925b8 100644
--- a/drivers/usb/gadget/tcm_usb_gadget.h
+++ b/drivers/usb/gadget/legacy/tcm_usb_gadget.h
diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/legacy/webcam.c
index 8cef1e658c29..a11d8e420bfe 100644
--- a/drivers/usb/gadget/webcam.c
+++ b/drivers/usb/gadget/legacy/webcam.c
@@ -390,20 +390,7 @@ static __refdata struct usb_composite_driver webcam_driver = {
 	.unbind		= webcam_unbind,
 };
 
-static int __init
-webcam_init(void)
-{
-	return usb_composite_probe(&webcam_driver);
-}
-
-static void __exit
-webcam_cleanup(void)
-{
-	usb_composite_unregister(&webcam_driver);
-}
-
-module_init(webcam_init);
-module_exit(webcam_cleanup);
+module_usb_composite_driver(webcam_driver);
 
 MODULE_AUTHOR("Laurent Pinchart");
 MODULE_DESCRIPTION("Webcam Video Gadget");
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/legacy/zero.c
index 134f354ede62..c3d496828b74 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/legacy/zero.c
@@ -411,17 +411,7 @@ static __refdata struct usb_composite_driver zero_driver = {
 	.resume		= zero_resume,
 };
 
+module_usb_composite_driver(zero_driver);
+
 MODULE_AUTHOR("David Brownell");
 MODULE_LICENSE("GPL");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&zero_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&zero_driver);
-}
-module_exit(cleanup);
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
deleted file mode 100644
index 300b3a71383b..000000000000
--- a/drivers/usb/gadget/net2280.c
+++ /dev/null
@@ -1,2905 +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.
- *
- * 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.
- *
- * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility
- *	with 2282 chip
- *
- * 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		/* messages on error and most fault paths */
-#undef	VERBOSE		/* extra debug messages (success too) */
-
-#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 <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/unaligned.h>
-
-
-#define	DRIVER_DESC		"PLX NET228x USB Peripheral Controller"
-#define	DRIVER_VERSION		"2005 Sept 27"
-
-#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 char ep0name [] = "ep0";
-static const char *const ep_name [] = {
-	ep0name,
-	"ep-a", "ep-b", "ep-c", "ep-d",
-	"ep-e", "ep-f",
-};
-
-/* 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 = 1;
-static bool use_dma_chaining = 0;
-
-/* "modprobe net2280 use_dma=n" etc */
-module_param (use_dma, bool, S_IRUGO);
-module_param (use_dma_chaining, bool, S_IRUGO);
-
-
-/* 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 = 0;
-
-/* "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 = 0;
-
-/* "modprobe net2280 enable_suspend=1" etc */
-module_param (enable_suspend, bool, S_IRUGO);
-
-/* 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")
-
-#if defined(CONFIG_USB_GADGET_DEBUG_FILES) || defined (DEBUG)
-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";
-}
-#endif
-
-#include "net2280.h"
-
-#define valid_bit	cpu_to_le32 (1 << VALID_BIT)
-#define dma_done_ie	cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE)
-
-/*-------------------------------------------------------------------------*/
-
-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;
-
-	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;
-
-	/* sanity check ep-e/ep-f since their fifos are small */
-	max = usb_endpoint_maxp (desc) & 0x1fff;
-	if (ep->num > 4 && max > 64)
-		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_idx_reg (dev->regs, REG_EP_MAXPKT (dev, ep->num), 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) {
-		DEBUG (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 ((1 << 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 ((1 << 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_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) ? 1 : 0;
-	tmp <<= ENDPOINT_TYPE;
-	tmp |= desc->bEndpointAddress;
-	tmp |= (4 << ENDPOINT_BYTE_COUNT);	/* default full fifo lines */
-	tmp |= 1 << ENDPOINT_ENABLE;
-	wmb ();
-
-	/* for OUT transfers, block the rx fifo until a read is posted */
-	ep->is_in = (tmp & USB_DIR_IN) != 0;
-	if (!ep->is_in)
-		writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-	else if (dev->pdev->device != 0x2280) {
-		/* Added for 2282, Don't use nak packets on an in endpoint,
-		 * this was ignored on 2280
-		 */
-		writel ((1 << CLEAR_NAK_OUT_PACKETS)
-			| (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
-	}
-
-	writel (tmp, &ep->regs->ep_cfg);
-
-	/* enable irqs */
-	if (!ep->dma) {				/* pio, per-packet */
-		tmp = (1 << ep->num) | readl (&dev->regs->pciirqenb0);
-		writel (tmp, &dev->regs->pciirqenb0);
-
-		tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
-			| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE);
-		if (dev->pdev->device == 0x2280)
-			tmp |= readl (&ep->regs->ep_irqenb);
-		writel (tmp, &ep->regs->ep_irqenb);
-	} else {				/* dma, per-request */
-		tmp = (1 << (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 = (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE);
-			writel (tmp, &ep->regs->ep_irqenb);
-
-			tmp = (1 << ep->num) | readl (&dev->regs->pciirqenb0);
-			writel (tmp, &dev->regs->pciirqenb0);
-		}
-	}
-
-	tmp = desc->bEndpointAddress;
-	DEBUG (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 (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 (  (1 << DMA_SCATTER_GATHER_DONE_INTERRUPT)
-			| (1 << DMA_TRANSACTION_DONE_INTERRUPT)
-			| (1 << DMA_ABORT)
-			, &ep->dma->dmastat);
-
-		tmp = readl (&regs->pciirqenb0);
-		tmp &= ~(1 << ep->num);
-		writel (tmp, &regs->pciirqenb0);
-	} else {
-		tmp = readl (&regs->pciirqenb1);
-		tmp &= ~(1 << (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->pdev->device == 0x2280) {
-		tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
-		| (1 << SET_NAK_OUT_PACKETS)
-		| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
-		| (1 << CLEAR_INTERRUPT_MODE);
-	} else {
-		/* added for 2282 */
-		tmp = (1 << CLEAR_NAK_OUT_PACKETS_MODE)
-		| (1 << CLEAR_NAK_OUT_PACKETS)
-		| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
-		| (1 << CLEAR_INTERRUPT_MODE);
-	}
-
-	if (ep->num != 0) {
-		tmp |= (1 << CLEAR_ENDPOINT_TOGGLE)
-			| (1 << CLEAR_ENDPOINT_HALT);
-	}
-	writel (tmp, &ep->regs->ep_rsp);
-
-	/* scrub most status bits, and flush any fifo state */
-	if (ep->dev->pdev->device == 0x2280)
-		tmp = (1 << FIFO_OVERFLOW)
-			| (1 << FIFO_UNDERFLOW);
-	else
-		tmp = 0;
-
-	writel (tmp | (1 << TIMEOUT)
-		| (1 << USB_STALL_SENT)
-		| (1 << USB_IN_NAK_SENT)
-		| (1 << USB_IN_ACK_RCVD)
-		| (1 << USB_OUT_PING_NAK_SENT)
-		| (1 << USB_OUT_ACK_SENT)
-		| (1 << FIFO_FLUSH)
-		| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
-		| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
-		| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-		| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
-		| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-		| (1 << DATA_IN_TOKEN_INTERRUPT)
-		, &ep->regs->ep_stat);
-
-	/* fifo size is handled separately */
-}
-
-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);
-	ep_reset (ep->dev->regs, ep);
-
-	VDEBUG (ep->dev, "disabled %s %s\n",
-			ep->dma ? "dma" : "pio", _ep->name);
-
-	/* synch memory views with the device */
-	(void) readl (&ep->regs->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;
-
-	VDEBUG (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 (  (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-		| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-		, statp);
-	writel ((1 << FIFO_FLUSH), statp);
-	mb ();
-	tmp = readl (statp);
-	if (tmp & (1 << 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, (1 << USB_OUT_PING_NAK_SENT),
-				(1 << 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 & (1 << NAK_OUT_PACKETS)))
-			cleanup = 1;
-		else if ((tmp & (1 << 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 & (1 << 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) {
-			ERROR (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);
-
-	VDEBUG (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 ((1 << 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 |= (1 << DMA_DIRECTION);
-	if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0)
-			|| ep->dev->pdev->device != 0x2280)
-		dmacount |= (1 << END_OF_CHAIN);
-
-	req->valid = valid;
-	if (valid)
-		dmacount |= (1 << VALID_BIT);
-	if (likely(!req->req.no_interrupt || !use_dma_chaining))
-		dmacount |= (1 << 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 =
-		  (1 << DMA_SCATTER_GATHER_DONE_INTERRUPT)
-		| (1 << DMA_CLEAR_COUNT_ENABLE)
-		/* erratum 0116 workaround part 1 (use POLLING) */
-		| (POLL_100_USEC << DESCRIPTOR_POLLING_RATE)
-		| (1 << DMA_VALID_BIT_POLLING_ENABLE)
-		| (1 << DMA_VALID_BIT_ENABLE)
-		| (1 << DMA_SCATTER_GATHER_ENABLE)
-		/* erratum 0116 workaround part 2 (no AUTOSTART) */
-		| (1 << DMA_ENABLE);
-
-static inline void spin_stop_dma (struct net2280_dma_regs __iomem *dma)
-{
-	handshake (&dma->dmactl, (1 << DMA_ENABLE), 0, 50);
-}
-
-static inline void stop_dma (struct net2280_dma_regs __iomem *dma)
-{
-	writel (readl (&dma->dmactl) & ~(1 << 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 = (1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION);
-
-	if (ep->dev->pdev->device != 0x2280)
-		tmp |= (1 << END_OF_CHAIN);
-
-	writel (tmp, &dma->dmacount);
-	writel (readl (&dma->dmastat), &dma->dmastat);
-
-	writel (td_dma, &dma->dmadesc);
-	writel (dmactl, &dma->dmactl);
-
-	/* erratum 0116 workaround part 3:  pci arbiter away from net2280 */
-	(void) readl (&ep->dev->pci->pcimstctl);
-
-	writel ((1 << 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) & (1 << DMA_ENABLE));
-	writel (0, &ep->dma->dmactl);
-
-	/* previous OUT packet might have been short */
-	if (!ep->is_in && ((tmp = readl (&ep->regs->ep_stat))
-				& (1 << NAK_OUT_PACKETS)) != 0) {
-		writel ((1 << 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 ((1 << DMA_DONE_INTERRUPT_ENABLE)
-				| tmp, &dma->dmacount);
-			req->td->dmadesc = 0;
-			req->valid = 1;
-
-			writel ((1 << DMA_ENABLE), &dma->dmactl);
-			writel ((1 << 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) != 0
-				|| req->req.zero)) {
-			tmp |= (1 << 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 (1 << END_OF_CHAIN);
-
-	start_queue (ep, tmp, req->td_dma);
-}
-
-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)
-		VDEBUG (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
-	VDEBUG (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) {
-		/* use DMA if the endpoint supports it, else pio */
-		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);
-				VDEBUG (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 & (1 << 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)) {
-						done (ep, req, 0);
-						if (ep->num == 0)
-							allow_status (ep);
-						/* don't queue it */
-						req = NULL;
-					} else
-						s = readl (&ep->regs->ep_stat);
-				}
-
-				/* don't NAK, let the fifo fill */
-				if (req && (s & (1 << NAK_OUT_PACKETS)))
-					writel ((1 << 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) != 0);
-			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 & (1 << 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);
-
-			/* 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 & (1 << NAK_OUT_PACKETS)) == 0) {
-				WARNING (ep->dev, "%s lost packet sync!\n",
-						ep->ep.name);
-				req->req.status = -EOVERFLOW;
-			} else if ((tmp = readl (&ep->regs->ep_avail)) != 0) {
-				/* fifo gets flushed later */
-				ep->out_overflow = 1;
-				DEBUG (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;
-
-		DEBUG (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 |= (1 << 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) != 0);
-				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 (struct net2280_ep *ep)
-{
-	/* abort the current transfer */
-	if (likely (!list_empty (&ep->queue))) {
-		/* FIXME work around errata 0121, 0122, 0124 */
-		writel ((1 << DMA_ABORT), &ep->dma->dmastat);
-		spin_stop_dma (ep->dma);
-	} else
-		stop_dma (ep->dma);
-	scan_dma_completions (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) {
-			DEBUG (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 {
-			DEBUG (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 {
-		VDEBUG (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);
-			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) & ((1 << 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 ((1 << 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 & (1 << DEVICE_REMOTE_WAKEUP_ENABLE))
-		writel (1 << 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 |= (1 << SELF_POWERED_STATUS);
-	else
-		tmp &= ~(1 << SELF_POWERED_STATUS);
-	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 |= (1 << USB_DETECT_ENABLE);
-	else
-		tmp &= ~(1 << 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 & (1 << VBUS_PIN)) {
-		if (t2 & (1 << 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 < 7; i++) {
-		struct net2280_ep	*ep;
-
-		ep = &dev->ep [i];
-		if (i && !ep->desc)
-			continue;
-
-		t1 = readl (&ep->regs->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 & (1 << CLEAR_NAK_OUT_PACKETS))
-					? "NAK " : "",
-				(t2 & (1 << CLEAR_EP_HIDE_STATUS_PHASE))
-					? "hide " : "",
-				(t2 & (1 << CLEAR_EP_FORCE_CRC_ERROR))
-					? "CRC " : "",
-				(t2 & (1 << CLEAR_INTERRUPT_MODE))
-					? "interrupt " : "",
-				(t2 & (1<<CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE))
-					? "status " : "",
-				(t2 & (1 << CLEAR_NAK_OUT_PACKETS_MODE))
-					? "NAKmode " : "",
-				(t2 & (1 << CLEAR_ENDPOINT_TOGGLE))
-					? "DATA1 " : "DATA0 ",
-				(t2 & (1 << 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 < 7; 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 < 7; 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",
-				({ char *val;
-				 switch (d->bmAttributes & 0x03) {
-				 case USB_ENDPOINT_XFER_BULK:
-					val = "bulk"; break;
-				 case USB_ENDPOINT_XFER_INT:
-					val = "intr"; break;
-				 default:
-					val = "iso"; break;
-				 } val; }),
-				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);
-}
-
-/* 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 (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 (~(1 << SUSPEND_REQUEST_INTERRUPT), &dev->regs->irqstat1),
-
-	/* reset, and enable pci */
-	tmp = readl (&dev->regs->devinit)
-		| (1 << PCI_ENABLE)
-		| (1 << FIFO_SOFT_RESET)
-		| (1 << USB_SOFT_RESET)
-		| (1 << 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_reinit (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_reset (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 ep0_start (struct net2280 *dev)
-{
-	writel (  (1 << CLEAR_EP_HIDE_STATUS_PHASE)
-		| (1 << CLEAR_NAK_OUT_PACKETS)
-		| (1 << 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 (  (1 << SET_TEST_MODE)
-		| (1 << SET_ADDRESS)
-		| (1 << DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP)
-		| (1 << GET_DEVICE_STATUS)
-		| (1 << GET_INTERFACE_STATUS)
-		, &dev->usb->stdrsp);
-	writel (  (1 << USB_ROOT_PORT_WAKEUP_ENABLE)
-		| (1 << SELF_POWERED_USB_DEVICE)
-		| (1 << REMOTE_WAKEUP_SUPPORT)
-		| (dev->softconnect << USB_DETECT_ENABLE)
-		| (1 << SELF_POWERED_STATUS)
-		, &dev->usb->usbctl);
-
-	/* enable irqs so we can see ep0 and general operation  */
-	writel (  (1 << SETUP_PACKET_INTERRUPT_ENABLE)
-		| (1 << ENDPOINT_0_INTERRUPT_ENABLE)
-		, &dev->regs->pciirqenb0);
-	writel (  (1 << PCI_INTERRUPT_ENABLE)
-		| (1 << PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE)
-		| (1 << PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE)
-		| (1 << PCI_RETRY_ABORT_INTERRUPT_ENABLE)
-		| (1 << VBUS_INTERRUPT_ENABLE)
-		| (1 << ROOT_PORT_RESET_INTERRUPT_ENABLE)
-		| (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE)
-		, &dev->regs->pciirqenb1);
-
-	/* don't leave any writes posted */
-	(void) readl (&dev->usb->usbctl);
-}
-
-/* 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 < 7; 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)
-		writel(1 << 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);
-	ep0_start (dev);
-
-	DEBUG (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 < 7; 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 */
-	writel(0, &dev->usb->xcvrdiag);
-
-	device_remove_file (&dev->pdev->dev, &dev_attr_function);
-	device_remove_file (&dev->pdev->dev, &dev_attr_queues);
-
-	DEBUG(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
-	VDEBUG (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->pdev->device == 0x2280)
-		writel (t & ~(1 << 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 & (1 << 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 & (1 << 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 & (1 << 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 & (1 << 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 & (1 << 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 & (1 << 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 ((1 << 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
-			DEBUG (ep->dev, "%s dma ep_stat %08x ??\n",
-					ep->ep.name, t);
-		return;
-
-	/* data packet(s) received (in the fifo, OUT) */
-	} else if (t & (1 << DATA_PACKET_RECEIVED_INTERRUPT)) {
-		if (read_fifo (ep, req) && ep->num != 0)
-			mode = 2;
-
-	/* data packet(s) transmitted (IN) */
-	} else if (t & (1 << 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 */
-		if (req->req.actual == req->req.length) {
-			if (ep->num == 0) {
-				/* send zlps until the status stage */
-			} else if (!req->req.zero || len != ep->ep.maxpacket)
-				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 & (1 << 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 handle_stat0_irqs (struct net2280 *dev, u32 stat)
-{
-	struct net2280_ep	*ep;
-	u32			num, scratch;
-
-	/* most of these don't need individual acks */
-	stat &= ~(1 << INTA_ASSERTED);
-	if (!stat)
-		return;
-	// DEBUG (dev, "irqstat0 %04x\n", stat);
-
-	/* starting a control request? */
-	if (unlikely (stat & (1 << 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) {
-			if (readl (&dev->usb->usbstat) & (1 << HIGH_SPEED))
-				dev->gadget.speed = USB_SPEED_HIGH;
-			else
-				dev->gadget.speed = USB_SPEED_FULL;
-			net2280_led_speed (dev, dev->gadget.speed);
-			DEBUG(dev, "%s\n", usb_speed_string(dev->gadget.speed));
-		}
-
-		ep = &dev->ep [0];
-		ep->irqs++;
-
-		/* make sure any leftover request state is cleared */
-		stat &= ~(1 << 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 (ep->dev->pdev->device == 0x2280)
-			tmp = (1 << FIFO_OVERFLOW)
-				| (1 << FIFO_UNDERFLOW);
-		else
-			tmp = 0;
-
-		writel (tmp | (1 << TIMEOUT)
-			| (1 << USB_STALL_SENT)
-			| (1 << USB_IN_NAK_SENT)
-			| (1 << USB_IN_ACK_RCVD)
-			| (1 << USB_OUT_PING_NAK_SENT)
-			| (1 << USB_OUT_ACK_SENT)
-			| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
-			| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
-			| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-			| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
-			| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-			| (1 << 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]);
-
-		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 (1 << SETUP_PACKET_INTERRUPT, &dev->regs->irqstat0);
-		stat ^= (1 << 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 = (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
-				| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-				| (1 << DATA_IN_TOKEN_INTERRUPT);
-			stop_out_naking (ep);
-		} else
-			scratch = (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-				| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-				| (1 << 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;
-		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;
-			if ((e = get_ep_by_addr (dev, w_index)) == NULL
-					|| w_length > 2)
-				goto do_stall;
-
-			if (readl (&e->regs->ep_rsp)
-					& (1 << 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);
-			VDEBUG (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;
-			if ((e = get_ep_by_addr (dev, w_index)) == NULL)
-				goto do_stall;
-			if (e->wedged) {
-				VDEBUG(dev, "%s wedged, halt not cleared\n",
-						ep->ep.name);
-			} else {
-				VDEBUG(dev, "%s clear halt\n", ep->ep.name);
-				clear_halt(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;
-			if ((e = get_ep_by_addr (dev, w_index)) == NULL)
-				goto do_stall;
-			if (e->ep.name == ep0name)
-				goto do_stall;
-			set_halt (e);
-			allow_status (ep);
-			VDEBUG (dev, "%s set halt\n", ep->ep.name);
-			goto next_endpoints;
-			}
-			break;
-		default:
-delegate:
-			VDEBUG (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->regs->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:
-			VDEBUG (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 = 1 << num;
-		if ((scratch & t) == 0)
-			continue;
-		scratch ^= t;
-
-		ep = &dev->ep [num];
-		handle_ep_small (ep);
-	}
-
-	if (stat)
-		DEBUG (dev, "unhandled irqstat0 %08x\n", stat);
-}
-
-#define DMA_INTERRUPTS ( \
-		  (1 << DMA_D_INTERRUPT) \
-		| (1 << DMA_C_INTERRUPT) \
-		| (1 << DMA_B_INTERRUPT) \
-		| (1 << DMA_A_INTERRUPT))
-#define	PCI_ERROR_INTERRUPTS ( \
-		  (1 << PCI_MASTER_ABORT_RECEIVED_INTERRUPT) \
-		| (1 << PCI_TARGET_ABORT_RECEIVED_INTERRUPT) \
-		| (1 << 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 = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT);
-	mask = (1 << HIGH_SPEED) | (1 << 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 & (1 << ROOT_PORT_RESET_INTERRUPT))
-					&& ((readl (&dev->usb->usbstat) & mask)
-							== 0))
-				|| ((readl (&dev->usb->usbctl)
-					& (1 << VBUS_PIN)) == 0)
-			    ) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) {
-			DEBUG (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 = (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT);
-	if (stat & tmp) {
-		writel (tmp, &dev->regs->irqstat1);
-		if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
-			if (dev->driver->suspend)
-				dev->driver->suspend (&dev->gadget);
-			if (!enable_suspend)
-				stat &= ~(1 << 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->pdev->device == 0x2280)
-		stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
-			  | (1 << SUSPEND_REQUEST_INTERRUPT)
-			  | (1 << RESUME_INTERRUPT)
-			  | (1 << SOF_INTERRUPT));
-	else
-		stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
-			  | (1 << RESUME_INTERRUPT)
-			  | (1 << SOF_DOWN_INTERRUPT)
-			  | (1 << SOF_INTERRUPT));
-
-	if (!stat)
-		return;
-	// DEBUG (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 = 1 << 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);
-
-		/* chaining should stop on abort, short OUT from fifo,
-		 * or (stat0 codepath) short OUT transfer.
-		 */
-		if (!use_dma_chaining) {
-			if ((tmp & (1 << DMA_TRANSACTION_DONE_INTERRUPT))
-					== 0) {
-				DEBUG (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 & (1 << 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 (
-						(1 << 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) {
-		ERROR (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)
-		DEBUG (dev, "unhandled irqstat1 %08x\n", stat);
-}
-
-static irqreturn_t net2280_irq (int irq, void *_dev)
-{
-	struct net2280		*dev = _dev;
-
-	/* shared interrupt, not ours */
-	if (!(readl(&dev->regs->irqstat0) & (1 << 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));
-
-	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 (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);
-
-	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;
-
-	/* 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->pdev = pdev;
-	dev->gadget.ops = &net2280_ops;
-	dev->gadget.max_speed = 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)) {
-		DEBUG (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) {
-		DEBUG (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);
-
-	/* 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) {
-		ERROR (dev, "No IRQ.  Check PCI setup!\n");
-		retval = -ENODEV;
-		goto done;
-	}
-
-	if (request_irq (pdev->irq, net2280_irq, IRQF_SHARED, driver_name, dev)
-			!= 0) {
-		ERROR (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) {
-		DEBUG (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) {
-			DEBUG (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 */
-	writel ( (1 << DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE)
-			// 256 write retries may not be enough...
-			// | (1 << PCI_RETRY_ABORT_ENABLE)
-			| (1 << DMA_READ_MULTIPLE_ENABLE)
-			| (1 << 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 */
-	INFO (dev, "%s\n", driver_desc);
-	INFO (dev, "irq %d, pci mem %p, chip rev %04x\n",
-			pdev->irq, base, dev->chiprev);
-	INFO (dev, "version: " DRIVER_VERSION "; dma %s\n",
-			use_dma
-				? (use_dma_chaining ? "chaining" : "enabled")
-				: "disabled");
-	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 */
-	writel(0, &dev->usb->xcvrdiag);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static const struct pci_device_id pci_ids [] = { {
-	.class =	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-	.class_mask =	~0,
-	.vendor =	0x17cc,
-	.device =	0x2280,
-	.subvendor =	PCI_ANY_ID,
-	.subdevice =	PCI_ANY_ID,
-}, {
-	.class =	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-	.class_mask =	~0,
-	.vendor =	0x17cc,
-	.device =	0x2282,
-	.subvendor =	PCI_ANY_ID,
-	.subdevice =	PCI_ANY_ID,
-
-}, { /* 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_DESCRIPTION (DRIVER_DESC);
-MODULE_AUTHOR ("David Brownell");
-MODULE_LICENSE ("GPL");
-
-static int __init init (void)
-{
-	if (!use_dma)
-		use_dma_chaining = 0;
-	return pci_register_driver (&net2280_pci_driver);
-}
-module_init (init);
-
-static void __exit cleanup (void)
-{
-	pci_unregister_driver (&net2280_pci_driver);
-}
-module_exit (cleanup);
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
deleted file mode 100644
index a844be0d683a..000000000000
--- a/drivers/usb/gadget/net2280.h
+++ /dev/null
@@ -1,308 +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
- *
- * 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>
-
-/*-------------------------------------------------------------------------*/
-
-#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 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
-
-#ifdef	__KERNEL__
-
-/* ep a-f highspeed and fullspeed maxpacket, addresses
- * computed from ep->num
- */
-#define REG_EP_MAXPKT(dev,num) (((num) + 1) * 0x10 + \
-		(((dev)->gadget.speed == USB_SPEED_HIGH) ? 0 : 1))
-
-/*-------------------------------------------------------------------------*/
-
-/* [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;
-} __attribute__ ((aligned (16)));
-
-/*-------------------------------------------------------------------------*/
-
-/* DRIVER DATA STRUCTURES and UTILITIES */
-
-struct net2280_ep {
-	struct usb_ep				ep;
-	struct net2280_ep_regs			__iomem *regs;
-	struct net2280_dma_regs			__iomem *dma;
-	struct net2280_dma			*dummy;
-	dma_addr_t				td_dma;	/* of dummy */
-	struct net2280				*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,
-						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 (  (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
-		| (1 << CLEAR_NAK_OUT_PACKETS)
-		| (1 << CLEAR_NAK_OUT_PACKETS_MODE)
-		, &ep->regs->ep_rsp);
-	ep->stopped = 1;
-}
-
-/* count (<= 4) bytes in the next fifo write will be valid */
-static inline void set_fifo_bytecount (struct net2280_ep *ep, unsigned count)
-{
-	writeb (count, 2 + (u8 __iomem *) &ep->regs->ep_cfg);
-}
-
-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 [7];
-	struct usb_gadget_driver 	*driver;
-	unsigned			enabled : 1,
-					protocol_stall : 1,
-					softconnect : 1,
-					got_irq : 1,
-					region : 1;
-	u16				chiprev;
-
-	/* pci state used to access those endpoints */
-	struct pci_dev			*pdev;
-	struct net2280_regs		__iomem *regs;
-	struct net2280_usb_regs		__iomem *usb;
-	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 pci_pool			*requests;
-	// statistics...
-};
-
-static inline void set_halt (struct net2280_ep *ep)
-{
-	/* ep0 and bulk/intr endpoints */
-	writel (  (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
-		    /* set NAK_OUT for erratum 0114 */
-		| ((ep->dev->chiprev == CHIPREV_1) << SET_NAK_OUT_PACKETS)
-		| (1 << SET_ENDPOINT_HALT)
-		, &ep->regs->ep_rsp);
-}
-
-static inline void clear_halt (struct net2280_ep *ep)
-{
-	/* ep0 and bulk/intr endpoints */
-	writel (  (1 << CLEAR_ENDPOINT_HALT)
-		| (1 << 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);
-}
-
-#ifdef USE_RDK_LEDS
-
-static inline void net2280_led_init (struct net2280 *dev)
-{
-	/* LED3 (green) is on during USB activity. note erratum 0113. */
-	writel ((1 << GPIO3_LED_SELECT)
-		| (1 << GPIO3_OUTPUT_ENABLE)
-		| (1 << GPIO2_OUTPUT_ENABLE)
-		| (1 << GPIO1_OUTPUT_ENABLE)
-		| (1 << 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_HIGH:		/* green */
-		val &= ~(1 << GPIO0_DATA);
-		val |= (1 << GPIO1_DATA);
-		break;
-	case USB_SPEED_FULL:		/* red */
-		val &= ~(1 << GPIO1_DATA);
-		val |= (1 << GPIO0_DATA);
-		break;
-	default:			/* (off/black) */
-		val &= ~((1 << GPIO1_DATA) | (1 << 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 xprintk(dev,level,fmt,args...) \
-	printk(level "%s %s: " fmt , driver_name , \
-			pci_name(dev->pdev) , ## args)
-
-#ifdef DEBUG
-#undef DEBUG
-#define DEBUG(dev,fmt,args...) \
-	xprintk(dev , KERN_DEBUG , fmt , ## args)
-#else
-#define DEBUG(dev,fmt,args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#ifdef VERBOSE
-#define VDEBUG DEBUG
-#else
-#define VDEBUG(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)
-
-/*-------------------------------------------------------------------------*/
-
-static inline void start_out_naking (struct net2280_ep *ep)
-{
-	/* NOTE:  hardware races lurk here, and PING protocol issues */
-	writel ((1 << 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 & (1 << NAK_OUT_PACKETS)) == 0) {
-		DEBUG (ep->dev, "%s %s %08x !NAK\n",
-				ep->ep.name, where, tmp);
-		writel ((1 << 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 & (1 << NAK_OUT_PACKETS)) != 0)
-		writel ((1 << CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-}
-
-#endif	/* __KERNEL__ */
diff --git a/drivers/usb/gadget/u_os_desc.h b/drivers/usb/gadget/u_os_desc.h
index ea5cf8c2da28..947b7ddff691 100644
--- a/drivers/usb/gadget/u_os_desc.h
+++ b/drivers/usb/gadget/u_os_desc.h
@@ -35,27 +35,63 @@
 #define USB_EXT_PROP_UNICODE_LINK		6
 #define USB_EXT_PROP_UNICODE_MULTI		7
 
+static inline u8 *__usb_ext_prop_ptr(u8 *buf, size_t offset)
+{
+	return buf + offset;
+}
+
+static inline u8 *usb_ext_prop_size_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_DW_SIZE);
+}
+
+static inline u8 *usb_ext_prop_type_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_DW_PROPERTY_DATA_TYPE);
+}
+
+static inline u8 *usb_ext_prop_name_len_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_W_PROPERTY_NAME_LENGTH);
+}
+
+static inline u8 *usb_ext_prop_name_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_B_PROPERTY_NAME);
+}
+
+static inline u8 *usb_ext_prop_data_len_ptr(u8 *buf, size_t off)
+{
+	return __usb_ext_prop_ptr(buf,
+				  USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + off);
+}
+
+static inline u8 *usb_ext_prop_data_ptr(u8 *buf, size_t off)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_B_PROPERTY_DATA + off);
+}
+
 static inline void usb_ext_prop_put_size(u8 *buf, int dw_size)
 {
-	put_unaligned_le32(dw_size, &buf[USB_EXT_PROP_DW_SIZE]);
+	put_unaligned_le32(dw_size, usb_ext_prop_size_ptr(buf));
 }
 
 static inline void usb_ext_prop_put_type(u8 *buf, int type)
 {
-	put_unaligned_le32(type, &buf[USB_EXT_PROP_DW_PROPERTY_DATA_TYPE]);
+	put_unaligned_le32(type, usb_ext_prop_type_ptr(buf));
 }
 
 static inline int usb_ext_prop_put_name(u8 *buf, const char *name, int pnl)
 {
 	int result;
 
-	put_unaligned_le16(pnl, &buf[USB_EXT_PROP_W_PROPERTY_NAME_LENGTH]);
+	put_unaligned_le16(pnl, usb_ext_prop_name_len_ptr(buf));
 	result = utf8s_to_utf16s(name, strlen(name), UTF16_LITTLE_ENDIAN,
-		(wchar_t *) &buf[USB_EXT_PROP_B_PROPERTY_NAME], pnl - 2);
+		(wchar_t *) usb_ext_prop_name_ptr(buf), pnl - 2);
 	if (result < 0)
 		return result;
 
-	put_unaligned_le16(0, &buf[USB_EXT_PROP_B_PROPERTY_NAME + pnl]);
+	put_unaligned_le16(0, &buf[USB_EXT_PROP_B_PROPERTY_NAME + pnl - 2]);
 
 	return pnl;
 }
@@ -63,26 +99,23 @@ static inline int usb_ext_prop_put_name(u8 *buf, const char *name, int pnl)
 static inline void usb_ext_prop_put_binary(u8 *buf, int pnl, const u8 *data,
 					   int data_len)
 {
-	put_unaligned_le32(data_len,
-			   &buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
-	memcpy(&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl], data, data_len);
+	put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl));
+	memcpy(usb_ext_prop_data_ptr(buf, pnl), data, data_len);
 }
 
 static inline int usb_ext_prop_put_unicode(u8 *buf, int pnl, const char *string,
 					   int data_len)
 {
 	int result;
-	put_unaligned_le32(data_len,
-			&buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
-
+	put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl));
 	result = utf8s_to_utf16s(string, data_len >> 1, UTF16_LITTLE_ENDIAN,
-			(wchar_t *) &buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl],
+			(wchar_t *) usb_ext_prop_data_ptr(buf, pnl),
 			data_len - 2);
 	if (result < 0)
 		return result;
 
 	put_unaligned_le16(0,
-			&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl + data_len]);
+		&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl + data_len - 2]);
 
 	return data_len;
 }
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
new file mode 100644
index 000000000000..5151f947a4f5
--- /dev/null
+++ b/drivers/usb/gadget/udc/Kconfig
@@ -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
index 000000000000..4096122bb283
--- /dev/null
+++ b/drivers/usb/gadget/udc/Makefile
@@ -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/amd5536udc.c b/drivers/usb/gadget/udc/amd5536udc.c
index 41b062eb4de0..41b062eb4de0 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/udc/amd5536udc.c
diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/udc/amd5536udc.h
index 6744d3b83109..6744d3b83109 100644
--- a/drivers/usb/gadget/amd5536udc.h
+++ b/drivers/usb/gadget/udc/amd5536udc.h
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c
index cfd18bcca723..cfd18bcca723 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/udc/at91_udc.c
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/udc/at91_udc.h
index 017524663381..017524663381 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/drivers/usb/gadget/udc/at91_udc.h
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index 76023ce449a3..906e65f0e4fa 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -1979,7 +1979,7 @@ static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
 	return eps;
 }
 
-static int __init usba_udc_probe(struct platform_device *pdev)
+static int usba_udc_probe(struct platform_device *pdev)
 {
 	struct resource *regs, *fifo;
 	struct clk *pclk, *hclk;
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/udc/atmel_usba_udc.h
index a70706e8cb02..a70706e8cb02 100644
--- a/drivers/usb/gadget/atmel_usba_udc.h
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.h
diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/udc/bcm63xx_udc.c
index e969eb809a85..e969eb809a85 100644
--- a/drivers/usb/gadget/bcm63xx_udc.c
+++ b/drivers/usb/gadget/udc/bcm63xx_udc.c
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index 2b54955d3166..2b54955d3166 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
diff --git a/drivers/usb/gadget/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c
index e143d69f6017..e143d69f6017 100644
--- a/drivers/usb/gadget/fotg210-udc.c
+++ b/drivers/usb/gadget/udc/fotg210-udc.c
diff --git a/drivers/usb/gadget/fotg210.h b/drivers/usb/gadget/udc/fotg210.h
index bbf991bcbe7c..bbf991bcbe7c 100644
--- a/drivers/usb/gadget/fotg210.h
+++ b/drivers/usb/gadget/udc/fotg210.h
diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/udc/fsl_mxc_udc.c
index 9b140fc4d3bc..f16e149c5b3e 100644
--- a/drivers/usb/gadget/fsl_mxc_udc.c
+++ b/drivers/usb/gadget/udc/fsl_mxc_udc.c
@@ -18,6 +18,8 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
+#include "fsl_usb2_udc.h"
+
 static struct clk *mxc_ahb_clk;
 static struct clk *mxc_per_clk;
 static struct clk *mxc_ipg_clk;
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c
index ad5483335167..732430804841 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/udc/fsl_qe_udc.c
@@ -2539,7 +2539,7 @@ static int qe_udc_probe(struct platform_device *ofdev)
 		goto err2;
 
 	/* create a buf for ZLP send, need to remain zeroed */
-	udc->nullbuf = kzalloc(256, GFP_KERNEL);
+	udc->nullbuf = devm_kzalloc(&ofdev->dev, 256, GFP_KERNEL);
 	if (udc->nullbuf == NULL) {
 		dev_err(udc->dev, "cannot alloc nullbuf\n");
 		ret = -ENOMEM;
@@ -2547,10 +2547,10 @@ static int qe_udc_probe(struct platform_device *ofdev)
 	}
 
 	/* buffer for data of get_status request */
-	udc->statusbuf = kzalloc(2, GFP_KERNEL);
+	udc->statusbuf = devm_kzalloc(&ofdev->dev, 2, GFP_KERNEL);
 	if (udc->statusbuf == NULL) {
 		ret = -ENOMEM;
-		goto err4;
+		goto err3;
 	}
 
 	udc->nullp = virt_to_phys((void *)udc->nullbuf);
@@ -2581,13 +2581,13 @@ static int qe_udc_probe(struct platform_device *ofdev)
 	if (ret) {
 		dev_err(udc->dev, "cannot request irq %d err %d\n",
 				udc->usb_irq, ret);
-		goto err5;
+		goto err4;
 	}
 
 	ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
 			qe_udc_release);
 	if (ret)
-		goto err6;
+		goto err5;
 
 	platform_set_drvdata(ofdev, udc);
 	dev_info(udc->dev,
@@ -2595,9 +2595,9 @@ static int qe_udc_probe(struct platform_device *ofdev)
 			(udc->soc_type == PORT_QE) ? "QE" : "CPM");
 	return 0;
 
-err6:
-	free_irq(udc->usb_irq, udc);
 err5:
+	free_irq(udc->usb_irq, udc);
+err4:
 	irq_dispose_mapping(udc->usb_irq);
 err_noirq:
 	if (udc->nullmap) {
@@ -2610,9 +2610,6 @@ err_noirq:
 			udc->nullp, 256,
 				DMA_TO_DEVICE);
 	}
-	kfree(udc->statusbuf);
-err4:
-	kfree(udc->nullbuf);
 err3:
 	ep = &udc->eps[0];
 	cpm_muram_free(cpm_muram_offset(ep->rxbase));
@@ -2660,8 +2657,6 @@ static int qe_udc_remove(struct platform_device *ofdev)
 			udc->nullp, 256,
 				DMA_TO_DEVICE);
 	}
-	kfree(udc->statusbuf);
-	kfree(udc->nullbuf);
 
 	ep = &udc->eps[0];
 	cpm_muram_free(cpm_muram_offset(ep->rxbase));
diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/udc/fsl_qe_udc.h
index 7026919fc901..7026919fc901 100644
--- a/drivers/usb/gadget/fsl_qe_udc.h
+++ b/drivers/usb/gadget/udc/fsl_qe_udc.h
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c
index 28e4fc957026..75b23ea077a7 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -59,9 +59,9 @@
 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_dr_device __iomem *dr_regs;
 
-static struct usb_sys_interface *usb_sys_regs;
+static struct usb_sys_interface __iomem *usb_sys_regs;
 
 /* it is initialized in probe()  */
 static struct fsl_udc *udc_controller = NULL;
@@ -159,6 +159,8 @@ static inline void fsl_set_accessors(struct fsl_usb2_platform_data *pdata) {}
  *	request is still in progress.
  *--------------------------------------------------------------*/
 static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
+__releases(ep->udc->lock)
+__acquires(ep->udc->lock)
 {
 	struct fsl_udc *udc = NULL;
 	unsigned char stopped = ep->stopped;
@@ -1392,6 +1394,8 @@ stall:
 
 static void setup_received_irq(struct fsl_udc *udc,
 		struct usb_ctrlrequest *setup)
+__releases(udc->lock)
+__acquires(udc->lock)
 {
 	u16 wValue = le16_to_cpu(setup->wValue);
 	u16 wIndex = le16_to_cpu(setup->wIndex);
@@ -1957,8 +1961,7 @@ static int fsl_udc_start(struct usb_gadget *g,
 						    &udc_controller->gadget);
 			if (retval < 0) {
 				ERR("can't bind to transceiver\n");
-				driver->unbind(&udc_controller->gadget);
-				udc_controller->driver = 0;
+				udc_controller->driver = NULL;
 				return retval;
 			}
 		}
@@ -2246,7 +2249,7 @@ static void fsl_udc_release(struct device *dev)
  * init resource for globle controller
  * Return the udc handle on success or NULL on failure
  ------------------------------------------------------------------*/
-static int __init struct_udc_setup(struct fsl_udc *udc,
+static int struct_udc_setup(struct fsl_udc *udc,
 		struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata;
@@ -2298,7 +2301,7 @@ static int __init struct_udc_setup(struct fsl_udc *udc,
  * ep0out is not used so do nothing here
  * ep0in should be taken care
  *--------------------------------------------------------------*/
-static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
+static int struct_ep_setup(struct fsl_udc *udc, unsigned char index,
 		char *name, int link)
 {
 	struct fsl_ep *ep = &udc->eps[index];
@@ -2331,7 +2334,7 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
  * all intialization operations implemented here except enabling usb_intr reg
  * board setup should have been done in the platform code
  */
-static int __init fsl_udc_probe(struct platform_device *pdev)
+static int fsl_udc_probe(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata;
 	struct resource *res;
@@ -2380,7 +2383,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 		goto err_release_mem_region;
 	}
 
-	pdata->regs = (void *)dr_regs;
+	pdata->regs = (void __iomem *)dr_regs;
 
 	/*
 	 * do platform specific init: check the clock, grab/config pins, etc.
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/udc/fsl_usb2_udc.h
index c6703bb07b23..84715625b2b3 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/udc/fsl_usb2_udc.h
@@ -12,6 +12,9 @@
 #ifndef __FSL_USB2_UDC_H
 #define __FSL_USB2_UDC_H
 
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
 /* ### define USB registers here
  */
 #define USB_MAX_CTRL_PAYLOAD		64
diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c
index 3deb4e938071..d40255f784df 100644
--- a/drivers/usb/gadget/fusb300_udc.c
+++ b/drivers/usb/gadget/udc/fusb300_udc.c
@@ -1325,8 +1325,6 @@ static int fusb300_udc_stop(struct usb_gadget *g,
 {
 	struct fusb300 *fusb300 = to_fusb300(g);
 
-	driver->unbind(&fusb300->gadget);
-
 	init_controller(fusb300);
 	fusb300->driver = NULL;
 
@@ -1359,7 +1357,7 @@ static int __exit fusb300_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static int __init fusb300_probe(struct platform_device *pdev)
+static int fusb300_probe(struct platform_device *pdev)
 {
 	struct resource *res, *ires, *ires1;
 	void __iomem *reg = NULL;
diff --git a/drivers/usb/gadget/fusb300_udc.h b/drivers/usb/gadget/udc/fusb300_udc.h
index ae811d8d38b4..ae811d8d38b4 100644
--- a/drivers/usb/gadget/fusb300_udc.h
+++ b/drivers/usb/gadget/udc/fusb300_udc.h
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/udc/gadget_chips.h
index bcd04bc66b98..bcd04bc66b98 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/udc/gadget_chips.h
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/udc/goku_udc.c
index 6c85839e15ad..6c85839e15ad 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/udc/goku_udc.c
diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/udc/goku_udc.h
index 86d2adafe149..86d2adafe149 100644
--- a/drivers/usb/gadget/goku_udc.h
+++ b/drivers/usb/gadget/udc/goku_udc.h
diff --git a/drivers/usb/gadget/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c
index c7004ee89c90..08df5c4f46ce 100644
--- a/drivers/usb/gadget/gr_udc.c
+++ b/drivers/usb/gadget/udc/gr_udc.c
@@ -2213,7 +2213,7 @@ out:
 	return retval;
 }
 
-static struct of_device_id gr_match[] = {
+static const struct of_device_id gr_match[] = {
 	{.name = "GAISLER_USBDC"},
 	{.name = "01_021"},
 	{},
diff --git a/drivers/usb/gadget/gr_udc.h b/drivers/usb/gadget/udc/gr_udc.h
index 8388897d9ec3..8388897d9ec3 100644
--- a/drivers/usb/gadget/gr_udc.h
+++ b/drivers/usb/gadget/udc/gr_udc.h
diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index e471580a2a3b..1629ad7dcb80 100644
--- a/drivers/usb/gadget/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -3036,7 +3036,7 @@ struct lpc32xx_usbd_cfg lpc32xx_usbddata = {
 
 static u64 lpc32xx_usbd_dmamask = ~(u32) 0x7F;
 
-static int __init lpc32xx_udc_probe(struct platform_device *pdev)
+static int lpc32xx_udc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct lpc32xx_udc *udc;
@@ -3045,11 +3045,10 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
 	dma_addr_t dma_handle;
 	struct device_node *isp1301_node;
 
-	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
+	udc = kmemdup(&controller_template, sizeof(*udc), GFP_KERNEL);
 	if (!udc)
 		return -ENOMEM;
 
-	memcpy(udc, &controller_template, sizeof(*udc));
 	for (i = 0; i <= 15; i++)
 		udc->ep[i].udc = udc;
 	udc->gadget.ep0 = &udc->ep[0].ep;
@@ -3397,7 +3396,7 @@ static int lpc32xx_udc_resume(struct platform_device *pdev)
 #endif
 
 #ifdef CONFIG_OF
-static struct of_device_id lpc32xx_udc_of_match[] = {
+static const struct of_device_id lpc32xx_udc_of_match[] = {
 	{ .compatible = "nxp,lpc3220-udc", },
 	{ },
 };
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c
index 0d17174b86f8..de88d33b44b2 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/udc/m66592-udc.c
@@ -1492,8 +1492,6 @@ static int m66592_udc_stop(struct usb_gadget *g,
 
 	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 
-	driver->unbind(&m66592->gadget);
-
 	init_controller(m66592);
 	disable_controller(m66592);
 
@@ -1553,7 +1551,7 @@ static void nop_completion(struct usb_ep *ep, struct usb_request *r)
 {
 }
 
-static int __init m66592_probe(struct platform_device *pdev)
+static int m66592_probe(struct platform_device *pdev)
 {
 	struct resource *res, *ires;
 	void __iomem *reg = NULL;
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/udc/m66592-udc.h
index 96d49d7bfb6b..96d49d7bfb6b 100644
--- a/drivers/usb/gadget/m66592-udc.h
+++ b/drivers/usb/gadget/udc/m66592-udc.h
diff --git a/drivers/usb/gadget/mv_u3d.h b/drivers/usb/gadget/udc/mv_u3d.h
index e32a787ac373..e32a787ac373 100644
--- a/drivers/usb/gadget/mv_u3d.h
+++ b/drivers/usb/gadget/udc/mv_u3d.h
diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c
index 16248711c152..16248711c152 100644
--- a/drivers/usb/gadget/mv_u3d_core.c
+++ b/drivers/usb/gadget/udc/mv_u3d_core.c
diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/udc/mv_udc.h
index be77f207dbaf..be77f207dbaf 100644
--- a/drivers/usb/gadget/mv_udc.h
+++ b/drivers/usb/gadget/udc/mv_udc.h
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c
index fcff3a571b45..040fb169b162 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/udc/mv_udc_core.c
@@ -332,7 +332,7 @@ static int queue_dtd(struct mv_ep *ep, struct mv_req *req)
 	/* 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. */
+	/* Ensure that updates to the QH will occur before priming. */
 	wmb();
 
 	/* Prime the Endpoint */
@@ -1656,7 +1656,7 @@ static void handle_setup_packet(struct mv_udc *udc, u8 ep_num,
 	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 */
+	/* We process some standard setup requests here */
 	if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
 		switch (setup->bRequest) {
 		case USB_REQ_GET_STATUS:
diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/udc/net2272.c
index ca15405583e2..059cfe527982 100644
--- a/drivers/usb/gadget/net2272.c
+++ b/drivers/usb/gadget/udc/net2272.c
@@ -1453,7 +1453,7 @@ static int net2272_start(struct usb_gadget *_gadget,
 	struct net2272 *dev;
 	unsigned i;
 
-	if (!driver || !driver->unbind || !driver->setup ||
+	if (!driver || !driver->setup ||
 	    driver->max_speed != USB_SPEED_HIGH)
 		return -EINVAL;
 
diff --git a/drivers/usb/gadget/net2272.h b/drivers/usb/gadget/udc/net2272.h
index e59505789359..e59505789359 100644
--- a/drivers/usb/gadget/net2272.h
+++ b/drivers/usb/gadget/udc/net2272.h
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
new file mode 100644
index 000000000000..f4eac113690e
--- /dev/null
+++ b/drivers/usb/gadget/udc/net2280.c
@@ -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 __iomem *)&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
index 000000000000..03f15242d794
--- /dev/null
+++ b/drivers/usb/gadget/udc/net2280.h
@@ -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/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c
index 2ae4f6d69f74..e731373fd4d7 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/udc/omap_udc.c
@@ -2079,10 +2079,7 @@ static int omap_udc_start(struct usb_gadget *g,
 						&udc->gadget);
 		if (status < 0) {
 			ERR("can't bind to transceiver\n");
-			if (driver->unbind) {
-				driver->unbind(&udc->gadget);
-				udc->driver = NULL;
-			}
+			udc->driver = NULL;
 			goto done;
 		}
 	} else {
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/udc/omap_udc.h
index cfadeb5fc5de..cfadeb5fc5de 100644
--- a/drivers/usb/gadget/omap_udc.h
+++ b/drivers/usb/gadget/udc/omap_udc.h
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c
index eb8c3bedb57a..eb8c3bedb57a 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/udc/pch_udc.c
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c
index 9984437d2952..251e4d5ee152 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/udc/pxa25x_udc.c
@@ -16,6 +16,7 @@
 /* #define VERBOSE_DEBUG */
 
 #include <linux/device.h>
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
@@ -40,7 +41,6 @@
 
 #include <asm/byteorder.h>
 #include <asm/dma.h>
-#include <asm/gpio.h>
 #include <asm/mach-types.h>
 #include <asm/unaligned.h>
 
@@ -2105,11 +2105,9 @@ static int pxa25x_udc_probe(struct platform_device *pdev)
 	if (irq < 0)
 		return -ENODEV;
 
-	dev->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(dev->clk)) {
-		retval = PTR_ERR(dev->clk);
-		goto err_clk;
-	}
+	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)",
@@ -2120,15 +2118,16 @@ static int pxa25x_udc_probe(struct platform_device *pdev)
 	dev->dev = &pdev->dev;
 	dev->mach = dev_get_platdata(&pdev->dev);
 
-	dev->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+	dev->transceiver = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 
 	if (gpio_is_valid(dev->mach->gpio_pullup)) {
-		if ((retval = gpio_request(dev->mach->gpio_pullup,
-				"pca25x_udc 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_pullup;
+			goto err;
 		}
 		gpio_direction_output(dev->mach->gpio_pullup, 0);
 	}
@@ -2146,30 +2145,32 @@ static int pxa25x_udc_probe(struct platform_device *pdev)
 	dev->vbus = 0;
 
 	/* irq setup after old hardware state is cleaned up */
-	retval = request_irq(irq, pxa25x_udc_irq,
-			0, driver_name, dev);
+	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_irq1;
+		goto err;
 	}
 	dev->got_irq = 1;
 
 #ifdef CONFIG_ARCH_LUBBOCK
 	if (machine_is_lubbock()) {
-		retval = request_irq(LUBBOCK_USB_DISC_IRQ, lubbock_vbus_irq,
-				     0, driver_name, dev);
+		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_irq_lub;
+			goto err;
 		}
-		retval = request_irq(LUBBOCK_USB_IRQ, lubbock_vbus_irq,
-				     0, driver_name, dev);
+		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 lubbock_fail0;
+			goto err;
 		}
 	} else
 #endif
@@ -2180,22 +2181,9 @@ static int pxa25x_udc_probe(struct platform_device *pdev)
 		return retval;
 
 	remove_debug_files(dev);
-#ifdef	CONFIG_ARCH_LUBBOCK
-lubbock_fail0:
-	free_irq(LUBBOCK_USB_DISC_IRQ, dev);
- err_irq_lub:
-	free_irq(irq, dev);
-#endif
- err_irq1:
-	if (gpio_is_valid(dev->mach->gpio_pullup))
-		gpio_free(dev->mach->gpio_pullup);
- err_gpio_pullup:
-	if (!IS_ERR_OR_NULL(dev->transceiver)) {
-		usb_put_phy(dev->transceiver);
+ err:
+	if (!IS_ERR_OR_NULL(dev->transceiver))
 		dev->transceiver = NULL;
-	}
-	clk_put(dev->clk);
- err_clk:
 	return retval;
 }
 
@@ -2217,25 +2205,8 @@ static int pxa25x_udc_remove(struct platform_device *pdev)
 
 	remove_debug_files(dev);
 
-	if (dev->got_irq) {
-		free_irq(platform_get_irq(pdev, 0), dev);
-		dev->got_irq = 0;
-	}
-#ifdef CONFIG_ARCH_LUBBOCK
-	if (machine_is_lubbock()) {
-		free_irq(LUBBOCK_USB_DISC_IRQ, dev);
-		free_irq(LUBBOCK_USB_IRQ, dev);
-	}
-#endif
-	if (gpio_is_valid(dev->mach->gpio_pullup))
-		gpio_free(dev->mach->gpio_pullup);
-
-	clk_put(dev->clk);
-
-	if (!IS_ERR_OR_NULL(dev->transceiver)) {
-		usb_put_phy(dev->transceiver);
+	if (!IS_ERR_OR_NULL(dev->transceiver))
 		dev->transceiver = NULL;
-	}
 
 	the_controller = NULL;
 	return 0;
diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/udc/pxa25x_udc.h
index 3fe5931dc21a..3fe5931dc21a 100644
--- a/drivers/usb/gadget/pxa25x_udc.h
+++ b/drivers/usb/gadget/udc/pxa25x_udc.h
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c
index cdf4d678be96..597d39f89420 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/udc/pxa27x_udc.c
@@ -2446,6 +2446,9 @@ static int pxa_udc_probe(struct platform_device *pdev)
 		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));
@@ -2483,6 +2486,8 @@ err_add_udc:
 err_irq:
 	iounmap(udc->regs);
 err_map:
+	clk_unprepare(udc->clk);
+err_clk_prepare:
 	clk_put(udc->clk);
 	udc->clk = NULL;
 err_clk:
@@ -2509,6 +2514,7 @@ static int pxa_udc_remove(struct platform_device *_dev)
 
 	udc->transceiver = NULL;
 	the_controller = NULL;
+	clk_unprepare(udc->clk);
 	clk_put(udc->clk);
 	iounmap(udc->regs);
 
diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/udc/pxa27x_udc.h
index 28f2b53530f5..28f2b53530f5 100644
--- a/drivers/usb/gadget/pxa27x_udc.h
+++ b/drivers/usb/gadget/udc/pxa27x_udc.h
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c
index b698a490cc7d..46008421c1ec 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/udc/r8a66597-udc.c
@@ -1826,18 +1826,12 @@ static int __exit r8a66597_remove(struct platform_device *pdev)
 
 	usb_del_gadget_udc(&r8a66597->gadget);
 	del_timer_sync(&r8a66597->timer);
-	iounmap(r8a66597->reg);
-	if (r8a66597->pdata->sudmac)
-		iounmap(r8a66597->sudmac_reg);
-	free_irq(platform_get_irq(pdev, 0), r8a66597);
 	r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
 
 	if (r8a66597->pdata->on_chip) {
 		clk_disable_unprepare(r8a66597->clk);
-		clk_put(r8a66597->clk);
 	}
 
-	kfree(r8a66597);
 	return 0;
 }
 
@@ -1845,28 +1839,24 @@ static void nop_completion(struct usb_ep *ep, struct usb_request *r)
 {
 }
 
-static int __init r8a66597_sudmac_ioremap(struct r8a66597 *r8a66597,
+static int r8a66597_sudmac_ioremap(struct r8a66597 *r8a66597,
 					  struct platform_device *pdev)
 {
 	struct resource *res;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sudmac");
-	if (!res) {
-		dev_err(&pdev->dev, "platform_get_resource error(sudmac).\n");
-		return -ENODEV;
-	}
-
-	r8a66597->sudmac_reg = ioremap(res->start, resource_size(res));
-	if (r8a66597->sudmac_reg == NULL) {
+	r8a66597->sudmac_reg = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(r8a66597->sudmac_reg)) {
 		dev_err(&pdev->dev, "ioremap error(sudmac).\n");
-		return -ENOMEM;
+		return PTR_ERR(r8a66597->sudmac_reg);
 	}
 
 	return 0;
 }
 
-static int __init r8a66597_probe(struct platform_device *pdev)
+static int r8a66597_probe(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
 	char clk_name[8];
 	struct resource *res, *ires;
 	int irq;
@@ -1877,39 +1867,27 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 	unsigned long irq_trigger;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -ENODEV;
-		dev_err(&pdev->dev, "platform_get_resource error.\n");
-		goto clean_up;
-	}
+	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) {
-		ret = -ENODEV;
-		dev_err(&pdev->dev, "platform_get_irq error.\n");
-		goto clean_up;
-	}
-
-	reg = ioremap(res->start, resource_size(res));
-	if (reg == NULL) {
-		ret = -ENOMEM;
-		dev_err(&pdev->dev, "ioremap error.\n");
-		goto clean_up;
+		dev_err(dev, "platform_get_irq error.\n");
+		return -ENODEV;
 	}
 
 	/* initialize ucd */
-	r8a66597 = kzalloc(sizeof(struct r8a66597), GFP_KERNEL);
-	if (r8a66597 == NULL) {
-		ret = -ENOMEM;
-		goto clean_up;
-	}
+	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(&pdev->dev);
+	r8a66597->pdata = dev_get_platdata(dev);
 	r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 
 	r8a66597->gadget.ops = &r8a66597_gadget_ops;
@@ -1923,12 +1901,10 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 
 	if (r8a66597->pdata->on_chip) {
 		snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id);
-		r8a66597->clk = clk_get(&pdev->dev, clk_name);
+		r8a66597->clk = devm_clk_get(dev, clk_name);
 		if (IS_ERR(r8a66597->clk)) {
-			dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
-				clk_name);
-			ret = PTR_ERR(r8a66597->clk);
-			goto clean_up;
+			dev_err(dev, "cannot get clock \"%s\"\n", clk_name);
+			return PTR_ERR(r8a66597->clk);
 		}
 		clk_prepare_enable(r8a66597->clk);
 	}
@@ -1941,10 +1917,10 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 
 	disable_controller(r8a66597); /* make sure controller is disabled */
 
-	ret = request_irq(irq, r8a66597_irq, IRQF_SHARED,
-			udc_name, r8a66597);
+	ret = devm_request_irq(dev, irq, r8a66597_irq, IRQF_SHARED,
+			       udc_name, r8a66597);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "request_irq error (%d)\n", ret);
+		dev_err(dev, "request_irq error (%d)\n", ret);
 		goto clean_up2;
 	}
 
@@ -1978,37 +1954,25 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 							GFP_KERNEL);
 	if (r8a66597->ep0_req == NULL) {
 		ret = -ENOMEM;
-		goto clean_up3;
+		goto clean_up2;
 	}
 	r8a66597->ep0_req->complete = nop_completion;
 
-	ret = usb_add_gadget_udc(&pdev->dev, &r8a66597->gadget);
+	ret = usb_add_gadget_udc(dev, &r8a66597->gadget);
 	if (ret)
 		goto err_add_udc;
 
-	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
+	dev_info(dev, "version %s\n", DRIVER_VERSION);
 	return 0;
 
 err_add_udc:
 	r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
-clean_up3:
-	free_irq(irq, r8a66597);
 clean_up2:
-	if (r8a66597->pdata->on_chip) {
+	if (r8a66597->pdata->on_chip)
 		clk_disable_unprepare(r8a66597->clk);
-		clk_put(r8a66597->clk);
-	}
-clean_up:
-	if (r8a66597) {
-		if (r8a66597->sudmac_reg)
-			iounmap(r8a66597->sudmac_reg);
-		if (r8a66597->ep0_req)
-			r8a66597_free_request(&r8a66597->ep[0].ep,
-						r8a66597->ep0_req);
-		kfree(r8a66597);
-	}
-	if (reg)
-		iounmap(reg);
+
+	if (r8a66597->ep0_req)
+		r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
 
 	return ret;
 }
diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/udc/r8a66597-udc.h
index 45c4b2df1785..45c4b2df1785 100644
--- a/drivers/usb/gadget/r8a66597-udc.h
+++ b/drivers/usb/gadget/udc/r8a66597-udc.h
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/udc/s3c-hsudc.c
index 10c6a128250c..10c6a128250c 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/udc/s3c-hsudc.c
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c
index 7987aa049fab..357b58e0087b 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/udc/s3c2410_udc.c
@@ -1788,7 +1788,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
 		return PTR_ERR(usb_bus_clock);
 	}
 
-	clk_enable(usb_bus_clock);
+	clk_prepare_enable(usb_bus_clock);
 
 	udc_clock = clk_get(NULL, "usb-device");
 	if (IS_ERR(udc_clock)) {
@@ -1796,7 +1796,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
 		return PTR_ERR(udc_clock);
 	}
 
-	clk_enable(udc_clock);
+	clk_prepare_enable(udc_clock);
 
 	mdelay(10);
 
@@ -1952,13 +1952,13 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
 	release_mem_region(rsrc_start, rsrc_len);
 
 	if (!IS_ERR(udc_clock) && udc_clock != NULL) {
-		clk_disable(udc_clock);
+		clk_disable_unprepare(udc_clock);
 		clk_put(udc_clock);
 		udc_clock = NULL;
 	}
 
 	if (!IS_ERR(usb_bus_clock) && usb_bus_clock != NULL) {
-		clk_disable(usb_bus_clock);
+		clk_disable_unprepare(usb_bus_clock);
 		clk_put(usb_bus_clock);
 		usb_bus_clock = NULL;
 	}
diff --git a/drivers/usb/gadget/s3c2410_udc.h b/drivers/usb/gadget/udc/s3c2410_udc.h
index 93bf225f1969..93bf225f1969 100644
--- a/drivers/usb/gadget/s3c2410_udc.h
+++ b/drivers/usb/gadget/udc/s3c2410_udc.h
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
index b0d98172bc07..b0d98172bc07 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 03314f861bee..82800a775501 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -37,6 +37,14 @@ config USB_XHCI_MVEBU
 	  Say 'Y' to enable the support for the xHCI host controller
 	  found in Marvell Armada 375/38x ARM SOCs.
 
+config USB_XHCI_RCAR
+	tristate "xHCI support for Renesas R-Car SoCs"
+	select USB_XHCI_PLATFORM
+	depends on ARCH_SHMOBILE || COMPILE_TEST
+	---help---
+	  Say 'Y' to enable the support for the xHCI host controller
+	  found in Renesas R-Car ARM SoCs.
+
 endif # USB_XHCI_HCD
 
 config USB_EHCI_HCD
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index af89a903d97e..144c038ef70f 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -22,6 +22,9 @@ ifneq ($(CONFIG_USB_XHCI_PLATFORM), )
 ifneq ($(CONFIG_USB_XHCI_MVEBU), )
 	xhci-hcd-y		+= xhci-mvebu.o
 endif
+ifneq ($(CONFIG_USB_XHCI_RCAR), )
+	xhci-hcd-y		+= xhci-rcar.o
+endif
 endif
 
 obj-$(CONFIG_USB_WHCI_HCD)	+= whci/
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index d1c76216350f..cda0a2f5c467 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -88,7 +88,7 @@ static int exynos_ehci_get_phy(struct device *dev,
 			return -EINVAL;
 		}
 
-		phy = devm_of_phy_get(dev, child, 0);
+		phy = devm_of_phy_get(dev, child, NULL);
 		of_node_put(child);
 		if (IS_ERR(phy)) {
 			ret = PTR_ERR(phy);
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index c0fb6a8ae6a3..b6205fac3567 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -209,7 +209,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
 	ehci->periodic = (__le32 *)
 		dma_alloc_coherent (ehci_to_hcd(ehci)->self.controller,
 			ehci->periodic_size * sizeof(__le32),
-			&ehci->periodic_dma, 0);
+			&ehci->periodic_dma, flags);
 	if (ehci->periodic == NULL) {
 		goto fail;
 	}
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 982c09bebe0f..934b39d5e44a 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -190,7 +190,7 @@ static const struct dev_pm_ops ehci_msm_dev_pm_ops = {
 	.resume          = ehci_msm_pm_resume,
 };
 
-static struct of_device_id msm_ehci_dt_match[] = {
+static const struct of_device_id msm_ehci_dt_match[] = {
 	{ .compatible = "qcom,ehci-host", },
 	{}
 };
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 3e86bf4371b3..ca7b964124af 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -35,6 +35,21 @@ static const char hcd_name[] = "ehci-pci";
 #define PCI_DEVICE_ID_INTEL_CE4100_USB	0x2e70
 
 /*-------------------------------------------------------------------------*/
+#define PCI_DEVICE_ID_INTEL_QUARK_X1000_SOC		0x0939
+static inline bool is_intel_quark_x1000(struct pci_dev *pdev)
+{
+	return pdev->vendor == PCI_VENDOR_ID_INTEL &&
+		pdev->device == PCI_DEVICE_ID_INTEL_QUARK_X1000_SOC;
+}
+
+/*
+ * 0x84 is the offset of in/out threshold register,
+ * and it is the same offset as the register of 'hostpc'.
+ */
+#define	intel_quark_x1000_insnreg01	hostpc
+
+/* Maximum usable threshold value is 0x7f dwords for both IN and OUT */
+#define INTEL_QUARK_X1000_EHCI_MAX_THRESHOLD	0x007f007f
 
 /* called after powerup, by probe or system-pm "wakeup" */
 static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
@@ -50,6 +65,16 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
 	if (!retval)
 		ehci_dbg(ehci, "MWI active\n");
 
+	/* Reset the threshold limit */
+	if (is_intel_quark_x1000(pdev)) {
+		/*
+		 * For the Intel QUARK X1000, raise the I/O threshold to the
+		 * maximum usable value in order to improve performance.
+		 */
+		ehci_writel(ehci, INTEL_QUARK_X1000_EHCI_MAX_THRESHOLD,
+			ehci->regs->intel_quark_x1000_insnreg01);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index 1d59958ad0ce..1355ff0946b9 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -150,7 +150,7 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static struct of_device_id spear_ehci_id_table[] = {
+static const struct of_device_id spear_ehci_id_table[] = {
 	{ .compatible = "st,spear600-ehci", },
 	{ },
 };
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 6fdcb8ad2296..7aafb05e7a40 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -46,6 +46,7 @@
 #define DRV_NAME "tegra-ehci"
 
 static struct hc_driver __read_mostly tegra_ehci_hc_driver;
+static bool usb1_reset_attempted;
 
 struct tegra_ehci_soc_config {
 	bool has_hostpc;
@@ -60,6 +61,61 @@ struct tegra_ehci_hcd {
 	enum tegra_usb_phy_port_speed port_speed;
 };
 
+/*
+ * The 1st USB controller contains some UTMI pad registers that are global for
+ * all the controllers on the chip. Those registers are also cleared when
+ * reset is asserted to the 1st controller. This means that the 1st controller
+ * can only be reset when no other controlled has finished probing. So we'll
+ * reset the 1st controller before doing any other setup on any of the
+ * controllers, and then never again.
+ *
+ * Since this is a PHY issue, the Tegra PHY driver should probably be doing
+ * the resetting of the USB controllers. But to keep compatibility with old
+ * device trees that don't have reset phandles in the PHYs, do it here.
+ * Those old DTs will be vulnerable to total USB breakage if the 1st EHCI
+ * device isn't the first one to finish probing, so warn them.
+ */
+static int tegra_reset_usb_controller(struct platform_device *pdev)
+{
+	struct device_node *phy_np;
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct tegra_ehci_hcd *tegra =
+		(struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv;
+
+	phy_np = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0);
+	if (!phy_np)
+		return -ENOENT;
+
+	if (!usb1_reset_attempted) {
+		struct reset_control *usb1_reset;
+
+		usb1_reset = of_reset_control_get(phy_np, "usb");
+		if (IS_ERR(usb1_reset)) {
+			dev_warn(&pdev->dev,
+				 "can't get utmi-pads reset from the PHY\n");
+			dev_warn(&pdev->dev,
+				 "continuing, but please update your DT\n");
+		} else {
+			reset_control_assert(usb1_reset);
+			udelay(1);
+			reset_control_deassert(usb1_reset);
+		}
+
+		reset_control_put(usb1_reset);
+		usb1_reset_attempted = true;
+	}
+
+	if (!of_property_read_bool(phy_np, "nvidia,has-utmi-pad-registers")) {
+		reset_control_assert(tegra->rst);
+		udelay(1);
+		reset_control_deassert(tegra->rst);
+	}
+
+	of_node_put(phy_np);
+
+	return 0;
+}
+
 static int tegra_ehci_internal_port_reset(
 	struct ehci_hcd	*ehci,
 	u32 __iomem	*portsc_reg
@@ -326,7 +382,7 @@ static const struct tegra_ehci_soc_config tegra20_soc_config = {
 	.has_hostpc = false,
 };
 
-static struct of_device_id tegra_ehci_of_match[] = {
+static const struct of_device_id tegra_ehci_of_match[] = {
 	{ .compatible = "nvidia,tegra30-ehci", .data = &tegra30_soc_config },
 	{ .compatible = "nvidia,tegra20-ehci", .data = &tegra20_soc_config },
 	{ },
@@ -389,9 +445,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 	if (err)
 		goto cleanup_hcd_create;
 
-	reset_control_assert(tegra->rst);
-	udelay(1);
-	reset_control_deassert(tegra->rst);
+	err = tegra_reset_usb_controller(pdev);
+	if (err)
+		goto cleanup_clk_en;
 
 	u_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0);
 	if (IS_ERR(u_phy)) {
@@ -479,10 +535,11 @@ static int tegra_ehci_remove(struct platform_device *pdev)
 
 	usb_phy_shutdown(hcd->phy);
 	usb_remove_hcd(hcd);
-	usb_put_hcd(hcd);
 
 	clk_disable_unprepare(tegra->clk);
 
+	usb_put_hcd(hcd);
+
 	return 0;
 }
 
diff --git a/drivers/usb/host/fhci-dbg.c b/drivers/usb/host/fhci-dbg.c
index f238cb37305c..b58e7a60913a 100644
--- a/drivers/usb/host/fhci-dbg.c
+++ b/drivers/usb/host/fhci-dbg.c
@@ -129,11 +129,7 @@ void fhci_dfs_destroy(struct fhci_hcd *fhci)
 	if (!fhci->dfs_root)
 		return;
 
-	if (fhci->dfs_irq_stat)
-		debugfs_remove(fhci->dfs_irq_stat);
-
-	if (fhci->dfs_regs)
-		debugfs_remove(fhci->dfs_regs);
-
+	debugfs_remove(fhci->dfs_irq_stat);
+	debugfs_remove(fhci->dfs_regs);
 	debugfs_remove(fhci->dfs_root);
 }
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c
index 98a89d16cc3e..adcd2050dced 100644
--- a/drivers/usb/host/fotg210-hcd.c
+++ b/drivers/usb/host/fotg210-hcd.c
@@ -5838,41 +5838,17 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
 		goto fail_create_hcd;
 	}
 
+	hcd->has_tt = 1;
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev,
-			"Found HC with no register addr. Check %s setup!\n",
-			dev_name(dev));
-		retval = -ENODEV;
-		goto fail_request_resource;
+	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(hcd->regs)) {
+		retval = PTR_ERR(hcd->regs);
+		goto failed;
 	}
 
 	hcd->rsrc_start = res->start;
 	hcd->rsrc_len = resource_size(res);
-	hcd->has_tt = 1;
-
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-				fotg210_fotg210_hc_driver.description)) {
-		dev_dbg(dev, "controller already in use\n");
-		retval = -EBUSY;
-		goto fail_request_resource;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!res) {
-		dev_err(dev,
-			"Found HC with no register addr. Check %s setup!\n",
-			dev_name(dev));
-		retval = -ENODEV;
-		goto fail_request_resource;
-	}
-
-	hcd->regs = ioremap_nocache(res->start, resource_size(res));
-	if (hcd->regs == NULL) {
-		dev_dbg(dev, "error mapping memory\n");
-		retval = -EFAULT;
-		goto fail_ioremap;
-	}
 
 	fotg210 = hcd_to_fotg210(hcd);
 
@@ -5880,24 +5856,20 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
 
 	retval = fotg210_setup(hcd);
 	if (retval)
-		goto fail_add_hcd;
+		goto failed;
 
 	fotg210_init(fotg210);
 
 	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (retval) {
 		dev_err(dev, "failed to add hcd with err %d\n", retval);
-		goto fail_add_hcd;
+		goto failed;
 	}
 	device_wakeup_enable(hcd->self.controller);
 
 	return retval;
 
-fail_add_hcd:
-	iounmap(hcd->regs);
-fail_ioremap:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-fail_request_resource:
+failed:
 	usb_put_hcd(hcd);
 fail_create_hcd:
 	dev_err(dev, "init %s fail, %d\n", dev_name(dev), retval);
@@ -5918,8 +5890,6 @@ static int fotg210_hcd_remove(struct platform_device *pdev)
 		return 0;
 
 	usb_remove_hcd(hcd);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 
 	return 0;
diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c
index 858efcfda50b..6234c75da33f 100644
--- a/drivers/usb/host/max3421-hcd.c
+++ b/drivers/usb/host/max3421-hcd.c
@@ -102,6 +102,15 @@ enum scheduling_pass {
 	SCHED_PASS_DONE
 };
 
+/* Bit numbers for max3421_hcd->todo: */
+enum {
+	ENABLE_IRQ = 0,
+	RESET_HCD,
+	RESET_PORT,
+	CHECK_UNLINK,
+	IOPIN_UPDATE
+};
+
 struct max3421_dma_buf {
 	u8 data[2];
 };
@@ -146,11 +155,7 @@ struct max3421_hcd {
 	u8 hien;
 	u8 mode;
 	u8 iopins[2];
-	unsigned int do_enable_irq:1;
-	unsigned int do_reset_hcd:1;
-	unsigned int do_reset_port:1;
-	unsigned int do_check_unlink:1;
-	unsigned int do_iopin_update:1;
+	unsigned long todo;
 #ifdef DEBUG
 	unsigned long err_stat[16];
 #endif
@@ -1165,10 +1170,8 @@ max3421_irq_handler(int irq, void *dev_id)
 	if (max3421_hcd->spi_thread &&
 	    max3421_hcd->spi_thread->state != TASK_RUNNING)
 		wake_up_process(max3421_hcd->spi_thread);
-	if (!max3421_hcd->do_enable_irq) {
-		max3421_hcd->do_enable_irq = 1;
+	if (!test_and_set_bit(ENABLE_IRQ, &max3421_hcd->todo))
 		disable_irq_nosync(spi->irq);
-	}
 	return IRQ_HANDLED;
 }
 
@@ -1423,10 +1426,8 @@ max3421_spi_thread(void *dev_id)
 			spi_wr8(hcd, MAX3421_REG_HIEN, max3421_hcd->hien);
 
 			set_current_state(TASK_INTERRUPTIBLE);
-			if (max3421_hcd->do_enable_irq) {
-				max3421_hcd->do_enable_irq = 0;
+			if (test_and_clear_bit(ENABLE_IRQ, &max3421_hcd->todo))
 				enable_irq(spi->irq);
-			}
 			schedule();
 			__set_current_state(TASK_RUNNING);
 		}
@@ -1440,23 +1441,18 @@ max3421_spi_thread(void *dev_id)
 		else if (!max3421_hcd->curr_urb)
 			i_worked |= max3421_select_and_start_urb(hcd);
 
-		if (max3421_hcd->do_reset_hcd) {
+		if (test_and_clear_bit(RESET_HCD, &max3421_hcd->todo))
 			/* reset the HCD: */
-			max3421_hcd->do_reset_hcd = 0;
 			i_worked |= max3421_reset_hcd(hcd);
-		}
-		if (max3421_hcd->do_reset_port) {
+		if (test_and_clear_bit(RESET_PORT, &max3421_hcd->todo)) {
 			/* perform a USB bus reset: */
-			max3421_hcd->do_reset_port = 0;
 			spi_wr8(hcd, MAX3421_REG_HCTL,
 				BIT(MAX3421_HCTL_BUSRST_BIT));
 			i_worked = 1;
 		}
-		if (max3421_hcd->do_check_unlink) {
-			max3421_hcd->do_check_unlink = 0;
+		if (test_and_clear_bit(CHECK_UNLINK, &max3421_hcd->todo))
 			i_worked |= max3421_check_unlink(hcd);
-		}
-		if (max3421_hcd->do_iopin_update) {
+		if (test_and_clear_bit(IOPIN_UPDATE, &max3421_hcd->todo)) {
 			/*
 			 * IOPINS1/IOPINS2 do not auto-increment, so we can't
 			 * use spi_wr_buf().
@@ -1469,7 +1465,6 @@ max3421_spi_thread(void *dev_id)
 				spi_wr8(hcd, MAX3421_REG_IOPINS1 + i, val);
 				max3421_hcd->iopins[i] = val;
 			}
-			max3421_hcd->do_iopin_update = 0;
 			i_worked = 1;
 		}
 	}
@@ -1485,7 +1480,8 @@ max3421_reset_port(struct usb_hcd *hcd)
 
 	max3421_hcd->port_status &= ~(USB_PORT_STAT_ENABLE |
 				      USB_PORT_STAT_LOW_SPEED);
-	max3421_hcd->do_reset_port = 1;
+	max3421_hcd->port_status |= USB_PORT_STAT_RESET;
+	set_bit(RESET_PORT, &max3421_hcd->todo);
 	wake_up_process(max3421_hcd->spi_thread);
 	return 0;
 }
@@ -1498,7 +1494,7 @@ max3421_reset(struct usb_hcd *hcd)
 	hcd->self.sg_tablesize = 0;
 	hcd->speed = HCD_USB2;
 	hcd->self.root_hub->speed = USB_SPEED_FULL;
-	max3421_hcd->do_reset_hcd = 1;
+	set_bit(RESET_HCD, &max3421_hcd->todo);
 	wake_up_process(max3421_hcd->spi_thread);
 	return 0;
 }
@@ -1551,7 +1547,7 @@ max3421_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
 	max3421_ep = urb->ep->hcpriv;
 	if (!max3421_ep) {
 		/* gets freed in max3421_endpoint_disable: */
-		max3421_ep = kzalloc(sizeof(struct max3421_ep), mem_flags);
+		max3421_ep = kzalloc(sizeof(struct max3421_ep), GFP_ATOMIC);
 		if (!max3421_ep) {
 			retval = -ENOMEM;
 			goto out;
@@ -1590,7 +1586,7 @@ max3421_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 	 */
 	retval = usb_hcd_check_unlink_urb(hcd, urb, status);
 	if (retval == 0) {
-		max3421_hcd->do_check_unlink = 1;
+		set_bit(CHECK_UNLINK, &max3421_hcd->todo);
 		wake_up_process(max3421_hcd->spi_thread);
 	}
 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
@@ -1690,7 +1686,7 @@ max3421_gpout_set_value(struct usb_hcd *hcd, u8 pin_number, u8 value)
 		max3421_hcd->iopins[idx] |=  mask;
 	else
 		max3421_hcd->iopins[idx] &= ~mask;
-	max3421_hcd->do_iopin_update = 1;
+	set_bit(IOPIN_UPDATE, &max3421_hcd->todo);
 	wake_up_process(max3421_hcd->spi_thread);
 }
 
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 45032e933e18..04f2186939d2 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -236,7 +236,7 @@ ohci_dump_roothub (
 	}
 }
 
-static void ohci_dump (struct ohci_hcd *controller, int verbose)
+static void ohci_dump(struct ohci_hcd *controller)
 {
 	ohci_dbg (controller, "OHCI controller state\n");
 
@@ -464,15 +464,16 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
 static ssize_t fill_async_buffer(struct debug_buffer *buf)
 {
 	struct ohci_hcd		*ohci;
-	size_t			temp;
+	size_t			temp, size;
 	unsigned long		flags;
 
 	ohci = buf->ohci;
+	size = PAGE_SIZE;
 
 	/* display control and bulk lists together, for simplicity */
 	spin_lock_irqsave (&ohci->lock, flags);
-	temp = show_list(ohci, buf->page, buf->count, ohci->ed_controltail);
-	temp += show_list(ohci, buf->page + temp, buf->count - temp,
+	temp = show_list(ohci, buf->page, size, ohci->ed_controltail);
+	temp += show_list(ohci, buf->page + temp, size - temp,
 			  ohci->ed_bulktail);
 	spin_unlock_irqrestore (&ohci->lock, flags);
 
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index 060a6a414750..a72ab8fe8cd3 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -87,7 +87,7 @@ static int exynos_ohci_get_phy(struct device *dev,
 			return -EINVAL;
 		}
 
-		phy = devm_of_phy_get(dev, child, 0);
+		phy = devm_of_phy_get(dev, child, NULL);
 		of_node_put(child);
 		if (IS_ERR(phy)) {
 			ret = PTR_ERR(phy);
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index f98d03f3144c..46987735a2e3 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -72,12 +72,14 @@
 static const char	hcd_name [] = "ohci_hcd";
 
 #define	STATECHANGE_DELAY	msecs_to_jiffies(300)
+#define	IO_WATCHDOG_DELAY	msecs_to_jiffies(250)
 
 #include "ohci.h"
 #include "pci-quirks.h"
 
-static void ohci_dump (struct ohci_hcd *ohci, int verbose);
-static void ohci_stop (struct usb_hcd *hcd);
+static void ohci_dump(struct ohci_hcd *ohci);
+static void ohci_stop(struct usb_hcd *hcd);
+static void io_watchdog_func(unsigned long _ohci);
 
 #include "ohci-hub.c"
 #include "ohci-dbg.c"
@@ -109,6 +111,33 @@ MODULE_PARM_DESC (no_handshake, "true (not default) disables BIOS handshake");
 
 /*-------------------------------------------------------------------------*/
 
+static int number_of_tds(struct urb *urb)
+{
+	int			len, i, num, this_sg_len;
+	struct scatterlist	*sg;
+
+	len = urb->transfer_buffer_length;
+	i = urb->num_mapped_sgs;
+
+	if (len > 0 && i > 0) {		/* Scatter-gather transfer */
+		num = 0;
+		sg = urb->sg;
+		for (;;) {
+			this_sg_len = min_t(int, sg_dma_len(sg), len);
+			num += DIV_ROUND_UP(this_sg_len, 4096);
+			len -= this_sg_len;
+			if (--i <= 0 || len <= 0)
+				break;
+			sg = sg_next(sg);
+		}
+
+	} else {			/* Non-SG transfer */
+		/* one TD for every 4096 Bytes (could be up to 8K) */
+		num = DIV_ROUND_UP(len, 4096);
+	}
+	return num;
+}
+
 /*
  * queue up an urb for anything except the root hub
  */
@@ -142,12 +171,8 @@ static int ohci_urb_enqueue (
 		// case PIPE_INTERRUPT:
 		// case PIPE_BULK:
 		default:
-			/* one TD for every 4096 Bytes (can be up to 8K) */
-			size += urb->transfer_buffer_length / 4096;
-			/* ... and for any remaining bytes ... */
-			if ((urb->transfer_buffer_length % 4096) != 0)
-				size++;
-			/* ... and maybe a zero length packet to wrap it up */
+			size += number_of_tds(urb);
+			/* maybe a zero-length packet to wrap it up */
 			if (size == 0)
 				size++;
 			else if ((urb->transfer_flags & URB_ZERO_PACKET) != 0
@@ -202,6 +227,16 @@ static int ohci_urb_enqueue (
 			usb_hcd_unlink_urb_from_ep(hcd, urb);
 			goto fail;
 		}
+
+		/* Start up the I/O watchdog timer, if it's not running */
+		if (!timer_pending(&ohci->io_watchdog) &&
+				list_empty(&ohci->eds_in_use)) {
+			ohci->prev_frame_no = ohci_frame_no(ohci);
+			mod_timer(&ohci->io_watchdog,
+					jiffies + IO_WATCHDOG_DELAY);
+		}
+		list_add(&ed->in_use_list, &ohci->eds_in_use);
+
 		if (ed->type == PIPE_ISOCHRONOUS) {
 			u16	frame = ohci_frame_no(ohci);
 
@@ -277,30 +312,24 @@ static int ohci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 	unsigned long		flags;
 	int			rc;
+	urb_priv_t		*urb_priv;
 
 	spin_lock_irqsave (&ohci->lock, flags);
 	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
-	if (rc) {
-		;	/* Do nothing */
-	} else if (ohci->rh_state == OHCI_RH_RUNNING) {
-		urb_priv_t  *urb_priv;
+	if (rc == 0) {
 
 		/* Unless an IRQ completed the unlink while it was being
 		 * handed to us, flag it for unlink and giveback, and force
 		 * some upcoming INTR_SF to call finish_unlinks()
 		 */
 		urb_priv = urb->hcpriv;
-		if (urb_priv) {
-			if (urb_priv->ed->state == ED_OPER)
-				start_ed_unlink (ohci, urb_priv->ed);
+		if (urb_priv->ed->state == ED_OPER)
+			start_ed_unlink(ohci, urb_priv->ed);
+
+		if (ohci->rh_state != OHCI_RH_RUNNING) {
+			/* With HC dead, we can clean up right away */
+			ohci_work(ohci);
 		}
-	} else {
-		/*
-		 * with HC dead, we won't respect hc queue pointers
-		 * any more ... just clean up every urb's memory.
-		 */
-		if (urb->hcpriv)
-			finish_urb(ohci, urb, status);
 	}
 	spin_unlock_irqrestore (&ohci->lock, flags);
 	return rc;
@@ -332,9 +361,7 @@ rescan:
 	if (ohci->rh_state != OHCI_RH_RUNNING) {
 sanitize:
 		ed->state = ED_IDLE;
-		if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT)
-			ohci->eds_scheduled--;
-		finish_unlinks (ohci, 0);
+		ohci_work(ohci);
 	}
 
 	switch (ed->state) {
@@ -342,11 +369,6 @@ sanitize:
 		/* major IRQ delivery trouble loses INTR_SF too... */
 		if (limit-- == 0) {
 			ohci_warn(ohci, "ED unlink timeout\n");
-			if (quirk_zfmicro(ohci)) {
-				ohci_warn(ohci, "Attempting ZF TD recovery\n");
-				ohci->ed_to_check = ed;
-				ohci->zf_delay = 2;
-			}
 			goto sanitize;
 		}
 		spin_unlock_irqrestore (&ohci->lock, flags);
@@ -406,93 +428,7 @@ ohci_shutdown (struct usb_hcd *hcd)
 	udelay(10);
 
 	ohci_writel(ohci, ohci->fminterval, &ohci->regs->fminterval);
-}
-
-static int check_ed(struct ohci_hcd *ohci, struct ed *ed)
-{
-	return (hc32_to_cpu(ohci, ed->hwINFO) & ED_IN) != 0
-		&& (hc32_to_cpu(ohci, ed->hwHeadP) & TD_MASK)
-			== (hc32_to_cpu(ohci, ed->hwTailP) & TD_MASK)
-		&& !list_empty(&ed->td_list);
-}
-
-/* ZF Micro watchdog timer callback. The ZF Micro chipset sometimes completes
- * an interrupt TD but neglects to add it to the donelist.  On systems with
- * this chipset, we need to periodically check the state of the queues to look
- * for such "lost" TDs.
- */
-static void unlink_watchdog_func(unsigned long _ohci)
-{
-	unsigned long	flags;
-	unsigned	max;
-	unsigned	seen_count = 0;
-	unsigned	i;
-	struct ed	**seen = NULL;
-	struct ohci_hcd	*ohci = (struct ohci_hcd *) _ohci;
-
-	spin_lock_irqsave(&ohci->lock, flags);
-	max = ohci->eds_scheduled;
-	if (!max)
-		goto done;
-
-	if (ohci->ed_to_check)
-		goto out;
-
-	seen = kcalloc(max, sizeof *seen, GFP_ATOMIC);
-	if (!seen)
-		goto out;
-
-	for (i = 0; i < NUM_INTS; i++) {
-		struct ed	*ed = ohci->periodic[i];
-
-		while (ed) {
-			unsigned	temp;
-
-			/* scan this branch of the periodic schedule tree */
-			for (temp = 0; temp < seen_count; temp++) {
-				if (seen[temp] == ed) {
-					/* we've checked it and what's after */
-					ed = NULL;
-					break;
-				}
-			}
-			if (!ed)
-				break;
-			seen[seen_count++] = ed;
-			if (!check_ed(ohci, ed)) {
-				ed = ed->ed_next;
-				continue;
-			}
-
-			/* HC's TD list is empty, but HCD sees at least one
-			 * TD that's not been sent through the donelist.
-			 */
-			ohci->ed_to_check = ed;
-			ohci->zf_delay = 2;
-
-			/* The HC may wait until the next frame to report the
-			 * TD as done through the donelist and INTR_WDH.  (We
-			 * just *assume* it's not a multi-TD interrupt URB;
-			 * those could defer the IRQ more than one frame, using
-			 * DI...)  Check again after the next INTR_SF.
-			 */
-			ohci_writel(ohci, OHCI_INTR_SF,
-					&ohci->regs->intrstatus);
-			ohci_writel(ohci, OHCI_INTR_SF,
-					&ohci->regs->intrenable);
-
-			/* flush those writes */
-			(void) ohci_readl(ohci, &ohci->regs->control);
-
-			goto out;
-		}
-	}
-out:
-	kfree(seen);
-	if (ohci->eds_scheduled)
-		mod_timer(&ohci->unlink_watchdog, round_jiffies(jiffies + HZ));
-done:
-	spin_unlock_irqrestore(&ohci->lock, flags);
+	ohci->rh_state = OHCI_RH_HALTED;
 }
 
 /*-------------------------------------------------------------------------*
@@ -506,6 +442,9 @@ static int ohci_init (struct ohci_hcd *ohci)
 	int ret;
 	struct usb_hcd *hcd = ohci_to_hcd(ohci);
 
+	/* Accept arbitrarily long scatter-gather lists */
+	hcd->self.sg_tablesize = ~0;
+
 	if (distrust_firmware)
 		ohci->flags |= OHCI_QUIRK_HUB_POWER;
 
@@ -558,8 +497,12 @@ static int ohci_init (struct ohci_hcd *ohci)
 	if (ohci->hcca)
 		return 0;
 
+	setup_timer(&ohci->io_watchdog, io_watchdog_func,
+			(unsigned long) ohci);
+	set_timer_slack(&ohci->io_watchdog, msecs_to_jiffies(20));
+
 	ohci->hcca = dma_alloc_coherent (hcd->self.controller,
-			sizeof *ohci->hcca, &ohci->hcca_dma, 0);
+			sizeof(*ohci->hcca), &ohci->hcca_dma, GFP_KERNEL);
 	if (!ohci->hcca)
 		return -ENOMEM;
 
@@ -735,16 +678,7 @@ retry:
 	// POTPGT delay is bits 24-31, in 2 ms units.
 	mdelay ((val >> 23) & 0x1fe);
 
-	if (quirk_zfmicro(ohci)) {
-		/* Create timer to watch for bad queue state on ZF Micro */
-		setup_timer(&ohci->unlink_watchdog, unlink_watchdog_func,
-				(unsigned long) ohci);
-
-		ohci->eds_scheduled = 0;
-		ohci->ed_to_check = NULL;
-	}
-
-	ohci_dump (ohci, 1);
+	ohci_dump(ohci);
 
 	return 0;
 }
@@ -777,6 +711,142 @@ static int ohci_start(struct usb_hcd *hcd)
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Some OHCI controllers are known to lose track of completed TDs.  They
+ * don't add the TDs to the hardware done queue, which means we never see
+ * them as being completed.
+ *
+ * This watchdog routine checks for such problems.  Without some way to
+ * tell when those TDs have completed, we would never take their EDs off
+ * the unlink list.  As a result, URBs could never be dequeued and
+ * endpoints could never be released.
+ */
+static void io_watchdog_func(unsigned long _ohci)
+{
+	struct ohci_hcd	*ohci = (struct ohci_hcd *) _ohci;
+	bool		takeback_all_pending = false;
+	u32		status;
+	u32		head;
+	struct ed	*ed;
+	struct td	*td, *td_start, *td_next;
+	unsigned	frame_no;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&ohci->lock, flags);
+
+	/*
+	 * One way to lose track of completed TDs is if the controller
+	 * never writes back the done queue head.  If it hasn't been
+	 * written back since the last time this function ran and if it
+	 * was non-empty at that time, something is badly wrong with the
+	 * hardware.
+	 */
+	status = ohci_readl(ohci, &ohci->regs->intrstatus);
+	if (!(status & OHCI_INTR_WDH) && ohci->wdh_cnt == ohci->prev_wdh_cnt) {
+		if (ohci->prev_donehead) {
+			ohci_err(ohci, "HcDoneHead not written back; disabled\n");
+ died:
+			usb_hc_died(ohci_to_hcd(ohci));
+			ohci_dump(ohci);
+			ohci_shutdown(ohci_to_hcd(ohci));
+			goto done;
+		} else {
+			/* No write back because the done queue was empty */
+			takeback_all_pending = true;
+		}
+	}
+
+	/* Check every ED which might have pending TDs */
+	list_for_each_entry(ed, &ohci->eds_in_use, in_use_list) {
+		if (ed->pending_td) {
+			if (takeback_all_pending ||
+					OKAY_TO_TAKEBACK(ohci, ed)) {
+				unsigned tmp = hc32_to_cpu(ohci, ed->hwINFO);
+
+				ohci_dbg(ohci, "takeback pending TD for dev %d ep 0x%x\n",
+						0x007f & tmp,
+						(0x000f & (tmp >> 7)) +
+							((tmp & ED_IN) >> 5));
+				add_to_done_list(ohci, ed->pending_td);
+			}
+		}
+
+		/* Starting from the latest pending TD, */
+		td = ed->pending_td;
+
+		/* or the last TD on the done list, */
+		if (!td) {
+			list_for_each_entry(td_next, &ed->td_list, td_list) {
+				if (!td_next->next_dl_td)
+					break;
+				td = td_next;
+			}
+		}
+
+		/* find the last TD processed by the controller. */
+		head = hc32_to_cpu(ohci, ACCESS_ONCE(ed->hwHeadP)) & TD_MASK;
+		td_start = td;
+		td_next = list_prepare_entry(td, &ed->td_list, td_list);
+		list_for_each_entry_continue(td_next, &ed->td_list, td_list) {
+			if (head == (u32) td_next->td_dma)
+				break;
+			td = td_next;	/* head pointer has passed this TD */
+		}
+		if (td != td_start) {
+			/*
+			 * In case a WDH cycle is in progress, we will wait
+			 * for the next two cycles to complete before assuming
+			 * this TD will never get on the done queue.
+			 */
+			ed->takeback_wdh_cnt = ohci->wdh_cnt + 2;
+			ed->pending_td = td;
+		}
+	}
+
+	ohci_work(ohci);
+
+	if (ohci->rh_state == OHCI_RH_RUNNING) {
+
+		/*
+		 * Sometimes a controller just stops working.  We can tell
+		 * by checking that the frame counter has advanced since
+		 * the last time we ran.
+		 *
+		 * But be careful: Some controllers violate the spec by
+		 * stopping their frame counter when no ports are active.
+		 */
+		frame_no = ohci_frame_no(ohci);
+		if (frame_no == ohci->prev_frame_no) {
+			int		active_cnt = 0;
+			int		i;
+			unsigned	tmp;
+
+			for (i = 0; i < ohci->num_ports; ++i) {
+				tmp = roothub_portstatus(ohci, i);
+				/* Enabled and not suspended? */
+				if ((tmp & RH_PS_PES) && !(tmp & RH_PS_PSS))
+					++active_cnt;
+			}
+
+			if (active_cnt > 0) {
+				ohci_err(ohci, "frame counter not updating; disabled\n");
+				goto died;
+			}
+		}
+		if (!list_empty(&ohci->eds_in_use)) {
+			ohci->prev_frame_no = frame_no;
+			ohci->prev_wdh_cnt = ohci->wdh_cnt;
+			ohci->prev_donehead = ohci_readl(ohci,
+					&ohci->regs->donehead);
+			mod_timer(&ohci->io_watchdog,
+					jiffies + IO_WATCHDOG_DELAY);
+		}
+	}
+
+ done:
+	spin_unlock_irqrestore(&ohci->lock, flags);
+}
+
 /* an interrupt happens */
 
 static irqreturn_t ohci_irq (struct usb_hcd *hcd)
@@ -825,7 +895,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
 			usb_hc_died(hcd);
 		}
 
-		ohci_dump (ohci, 1);
+		ohci_dump(ohci);
 		ohci_usb_reset (ohci);
 	}
 
@@ -863,58 +933,30 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
 			usb_hcd_resume_root_hub(hcd);
 	}
 
-	if (ints & OHCI_INTR_WDH) {
-		spin_lock (&ohci->lock);
-		dl_done_list (ohci);
-		spin_unlock (&ohci->lock);
-	}
-
-	if (quirk_zfmicro(ohci) && (ints & OHCI_INTR_SF)) {
-		spin_lock(&ohci->lock);
-		if (ohci->ed_to_check) {
-			struct ed *ed = ohci->ed_to_check;
-
-			if (check_ed(ohci, ed)) {
-				/* HC thinks the TD list is empty; HCD knows
-				 * at least one TD is outstanding
-				 */
-				if (--ohci->zf_delay == 0) {
-					struct td *td = list_entry(
-						ed->td_list.next,
-						struct td, td_list);
-					ohci_warn(ohci,
-						  "Reclaiming orphan TD %p\n",
-						  td);
-					takeback_td(ohci, td);
-					ohci->ed_to_check = NULL;
-				}
-			} else
-				ohci->ed_to_check = NULL;
-		}
-		spin_unlock(&ohci->lock);
-	}
+	spin_lock(&ohci->lock);
+	if (ints & OHCI_INTR_WDH)
+		update_done_list(ohci);
 
 	/* could track INTR_SO to reduce available PCI/... bandwidth */
 
 	/* handle any pending URB/ED unlinks, leaving INTR_SF enabled
 	 * when there's still unlinking to be done (next frame).
 	 */
-	spin_lock (&ohci->lock);
-	if (ohci->ed_rm_list)
-		finish_unlinks (ohci, ohci_frame_no(ohci));
-	if ((ints & OHCI_INTR_SF) != 0
-			&& !ohci->ed_rm_list
-			&& !ohci->ed_to_check
+	ohci_work(ohci);
+	if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
 			&& ohci->rh_state == OHCI_RH_RUNNING)
 		ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);
-	spin_unlock (&ohci->lock);
 
 	if (ohci->rh_state == OHCI_RH_RUNNING) {
 		ohci_writel (ohci, ints, &regs->intrstatus);
+		if (ints & OHCI_INTR_WDH)
+			++ohci->wdh_cnt;
+
 		ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);
 		// flush those writes
 		(void) ohci_readl (ohci, &ohci->regs->control);
 	}
+	spin_unlock(&ohci->lock);
 
 	return IRQ_HANDLED;
 }
@@ -925,18 +967,17 @@ static void ohci_stop (struct usb_hcd *hcd)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 
-	ohci_dump (ohci, 1);
+	ohci_dump(ohci);
 
 	if (quirk_nec(ohci))
 		flush_work(&ohci->nec_work);
+	del_timer_sync(&ohci->io_watchdog);
 
 	ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
 	ohci_usb_reset(ohci);
 	free_irq(hcd->irq, hcd);
 	hcd->irq = 0;
 
-	if (quirk_zfmicro(ohci))
-		del_timer(&ohci->unlink_watchdog);
 	if (quirk_amdiso(ohci))
 		usb_amd_dev_put();
 
@@ -993,7 +1034,7 @@ int ohci_restart(struct ohci_hcd *ohci)
 		if (!urb->unlinked)
 			urb->unlinked = -ESHUTDOWN;
 	}
-	finish_unlinks (ohci, 0);
+	ohci_work(ohci);
 	spin_unlock_irq(&ohci->lock);
 
 	/* paranoia, in case that didn't work: */
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index b4940de1eba3..17d32b0ea565 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -39,8 +39,8 @@
 #define OHCI_SCHED_ENABLES \
 	(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
 
-static void dl_done_list (struct ohci_hcd *);
-static void finish_unlinks (struct ohci_hcd *, u16);
+static void update_done_list(struct ohci_hcd *);
+static void ohci_work(struct ohci_hcd *);
 
 #ifdef	CONFIG_PM
 static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
@@ -87,8 +87,8 @@ __acquires(ohci->lock)
 		msleep (8);
 		spin_lock_irq (&ohci->lock);
 	}
-	dl_done_list (ohci);
-	finish_unlinks (ohci, ohci_frame_no(ohci));
+	update_done_list(ohci);
+	ohci_work(ohci);
 
 	/*
 	 * Some controllers don't handle "global" suspend properly if
@@ -309,6 +309,9 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
 	else
 		rc = ohci_rh_suspend (ohci, 0);
 	spin_unlock_irq (&ohci->lock);
+
+	if (rc == 0)
+		del_timer_sync(&ohci->io_watchdog);
 	return rc;
 }
 
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index 2f20d3dc895b..c9e315c6808a 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -28,6 +28,7 @@ static void ohci_hcd_init (struct ohci_hcd *ohci)
 	ohci->next_statechange = jiffies;
 	spin_lock_init (&ohci->lock);
 	INIT_LIST_HEAD (&ohci->pending);
+	INIT_LIST_HEAD(&ohci->eds_in_use);
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index d4253e319428..1463c398d322 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -187,10 +187,6 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
 	ed->ed_prev = NULL;
 	ed->ed_next = NULL;
 	ed->hwNextED = 0;
-	if (quirk_zfmicro(ohci)
-			&& (ed->type == PIPE_INTERRUPT)
-			&& !(ohci->eds_scheduled++))
-		mod_timer(&ohci->unlink_watchdog, round_jiffies(jiffies + HZ));
 	wmb ();
 
 	/* we care about rm_list when setting CLE/BLE in case the HC was at
@@ -311,8 +307,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
  *  - ED_OPER: when there's any request queued, the ED gets rescheduled
  *    immediately.  HC should be working on them.
  *
- *  - ED_IDLE:  when there's no TD queue. there's no reason for the HC
- *    to care about this ED; safe to disable the endpoint.
+ *  - ED_IDLE: when there's no TD queue or the HC isn't running.
  *
  * When finish_unlinks() runs later, after SOF interrupt, it will often
  * complete one or more URB unlinks before making that state change.
@@ -602,6 +597,8 @@ static void td_submit_urb (
 	u32		info = 0;
 	int		is_out = usb_pipeout (urb->pipe);
 	int		periodic = 0;
+	int		i, this_sg_len, n;
+	struct scatterlist	*sg;
 
 	/* OHCI handles the bulk/interrupt data toggles itself.  We just
 	 * use the device toggle bits for resetting, and rely on the fact
@@ -615,10 +612,24 @@ static void td_submit_urb (
 
 	list_add (&urb_priv->pending, &ohci->pending);
 
-	if (data_len)
-		data = urb->transfer_dma;
-	else
-		data = 0;
+	i = urb->num_mapped_sgs;
+	if (data_len > 0 && i > 0) {
+		sg = urb->sg;
+		data = sg_dma_address(sg);
+
+		/*
+		 * urb->transfer_buffer_length may be smaller than the
+		 * size of the scatterlist (or vice versa)
+		 */
+		this_sg_len = min_t(int, sg_dma_len(sg), data_len);
+	} else {
+		sg = NULL;
+		if (data_len)
+			data = urb->transfer_dma;
+		else
+			data = 0;
+		this_sg_len = data_len;
+	}
 
 	/* NOTE:  TD_CC is set so we can tell which TDs the HC processed by
 	 * using TD_CC_GET, as well as by seeing them on the done list.
@@ -639,17 +650,29 @@ static void td_submit_urb (
 			? TD_T_TOGGLE | TD_CC | TD_DP_OUT
 			: TD_T_TOGGLE | TD_CC | TD_DP_IN;
 		/* TDs _could_ transfer up to 8K each */
-		while (data_len > 4096) {
-			td_fill (ohci, info, data, 4096, urb, cnt);
-			data += 4096;
-			data_len -= 4096;
+		for (;;) {
+			n = min(this_sg_len, 4096);
+
+			/* maybe avoid ED halt on final TD short read */
+			if (n >= data_len || (i == 1 && n >= this_sg_len)) {
+				if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
+					info |= TD_R;
+			}
+			td_fill(ohci, info, data, n, urb, cnt);
+			this_sg_len -= n;
+			data_len -= n;
+			data += n;
 			cnt++;
+
+			if (this_sg_len <= 0) {
+				if (--i <= 0 || data_len <= 0)
+					break;
+				sg = sg_next(sg);
+				data = sg_dma_address(sg);
+				this_sg_len = min_t(int, sg_dma_len(sg),
+						data_len);
+			}
 		}
-		/* maybe avoid ED halt on final TD short read */
-		if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
-			info |= TD_R;
-		td_fill (ohci, info, data, data_len, urb, cnt);
-		cnt++;
 		if ((urb->transfer_flags & URB_ZERO_PACKET)
 				&& cnt < urb_priv->length) {
 			td_fill (ohci, info, 0, 0, urb, cnt);
@@ -869,13 +892,46 @@ static void ed_halted(struct ohci_hcd *ohci, struct td *td, int cc)
 	}
 }
 
-/* replies to the request have to be on a FIFO basis so
- * we unreverse the hc-reversed done-list
- */
-static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
+/* Add a TD to the done list */
+static void add_to_done_list(struct ohci_hcd *ohci, struct td *td)
+{
+	struct td	*td2, *td_prev;
+	struct ed	*ed;
+
+	if (td->next_dl_td)
+		return;		/* Already on the list */
+
+	/* Add all the TDs going back until we reach one that's on the list */
+	ed = td->ed;
+	td2 = td_prev = td;
+	list_for_each_entry_continue_reverse(td2, &ed->td_list, td_list) {
+		if (td2->next_dl_td)
+			break;
+		td2->next_dl_td = td_prev;
+		td_prev = td2;
+	}
+
+	if (ohci->dl_end)
+		ohci->dl_end->next_dl_td = td_prev;
+	else
+		ohci->dl_start = td_prev;
+
+	/*
+	 * Make td->next_dl_td point to td itself, to mark the fact
+	 * that td is on the done list.
+	 */
+	ohci->dl_end = td->next_dl_td = td;
+
+	/* Did we just add the latest pending TD? */
+	td2 = ed->pending_td;
+	if (td2 && td2->next_dl_td)
+		ed->pending_td = NULL;
+}
+
+/* Get the entries on the hardware done queue and put them on our list */
+static void update_done_list(struct ohci_hcd *ohci)
 {
 	u32		td_dma;
-	struct td	*td_rev = NULL;
 	struct td	*td = NULL;
 
 	td_dma = hc32_to_cpup (ohci, &ohci->hcca->done_head);
@@ -883,7 +939,7 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
 	wmb();
 
 	/* get TD from hc's singly linked list, and
-	 * prepend to ours.  ed->td_list changes later.
+	 * add to ours.  ed->td_list changes later.
 	 */
 	while (td_dma) {
 		int		cc;
@@ -905,19 +961,17 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
 				&& (td->ed->hwHeadP & cpu_to_hc32 (ohci, ED_H)))
 			ed_halted(ohci, td, cc);
 
-		td->next_dl_td = td_rev;
-		td_rev = td;
 		td_dma = hc32_to_cpup (ohci, &td->hwNextTD);
+		add_to_done_list(ohci, td);
 	}
-	return td_rev;
 }
 
 /*-------------------------------------------------------------------------*/
 
 /* there are some urbs/eds to unlink; called in_irq(), with HCD locked */
-static void
-finish_unlinks (struct ohci_hcd *ohci, u16 tick)
+static void finish_unlinks(struct ohci_hcd *ohci)
 {
+	unsigned	tick = ohci_frame_no(ohci);
 	struct ed	*ed, **last;
 
 rescan_all:
@@ -926,41 +980,48 @@ rescan_all:
 		int			completed, modified;
 		__hc32			*prev;
 
+		/* Is this ED already invisible to the hardware? */
+		if (ed->state == ED_IDLE)
+			goto ed_idle;
+
 		/* only take off EDs that the HC isn't using, accounting for
 		 * frame counter wraps and EDs with partially retired TDs
 		 */
-		if (likely(ohci->rh_state == OHCI_RH_RUNNING)) {
-			if (tick_before (tick, ed->tick)) {
+		if (likely(ohci->rh_state == OHCI_RH_RUNNING) &&
+				tick_before(tick, ed->tick)) {
 skip_ed:
-				last = &ed->ed_next;
-				continue;
-			}
+			last = &ed->ed_next;
+			continue;
+		}
+		if (!list_empty(&ed->td_list)) {
+			struct td	*td;
+			u32		head;
 
-			if (!list_empty (&ed->td_list)) {
-				struct td	*td;
-				u32		head;
-
-				td = list_entry (ed->td_list.next, struct td,
-							td_list);
-				head = hc32_to_cpu (ohci, ed->hwHeadP) &
-								TD_MASK;
-
-				/* INTR_WDH may need to clean up first */
-				if (td->td_dma != head) {
-					if (ed == ohci->ed_to_check)
-						ohci->ed_to_check = NULL;
-					else
-						goto skip_ed;
-				}
-			}
+			td = list_first_entry(&ed->td_list, struct td, td_list);
+
+			/* INTR_WDH may need to clean up first */
+			head = hc32_to_cpu(ohci, ed->hwHeadP) & TD_MASK;
+			if (td->td_dma != head &&
+					ohci->rh_state == OHCI_RH_RUNNING)
+				goto skip_ed;
+
+			/* Don't mess up anything already on the done list */
+			if (td->next_dl_td)
+				goto skip_ed;
 		}
 
+		/* ED's now officially unlinked, hc doesn't see */
+		ed->state = ED_IDLE;
+		ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H);
+		ed->hwNextED = 0;
+		wmb();
+		ed->hwINFO &= ~cpu_to_hc32(ohci, ED_SKIP | ED_DEQUEUE);
+ed_idle:
+
 		/* reentrancy:  if we drop the schedule lock, someone might
 		 * have modified this list.  normally it's just prepending
 		 * entries (which we'd ignore), but paranoia won't hurt.
 		 */
-		*last = ed->ed_next;
-		ed->ed_next = NULL;
 		modified = 0;
 
 		/* unlink urbs as requested, but rescan the list after
@@ -1018,19 +1079,21 @@ rescan_this:
 		if (completed && !list_empty (&ed->td_list))
 			goto rescan_this;
 
-		/* ED's now officially unlinked, hc doesn't see */
-		ed->state = ED_IDLE;
-		if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT)
-			ohci->eds_scheduled--;
-		ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H);
-		ed->hwNextED = 0;
-		wmb ();
-		ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE);
-
-		/* but if there's work queued, reschedule */
-		if (!list_empty (&ed->td_list)) {
-			if (ohci->rh_state == OHCI_RH_RUNNING)
-				ed_schedule (ohci, ed);
+		/*
+		 * If no TDs are queued, take ED off the ed_rm_list.
+		 * Otherwise, if the HC is running, reschedule.
+		 * If not, leave it on the list for further dequeues.
+		 */
+		if (list_empty(&ed->td_list)) {
+			*last = ed->ed_next;
+			ed->ed_next = NULL;
+			list_del(&ed->in_use_list);
+		} else if (ohci->rh_state == OHCI_RH_RUNNING) {
+			*last = ed->ed_next;
+			ed->ed_next = NULL;
+			ed_schedule(ohci, ed);
+		} else {
+			last = &ed->ed_next;
 		}
 
 		if (modified)
@@ -1082,12 +1145,7 @@ rescan_this:
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * Used to take back a TD from the host controller. This would normally be
- * called from within dl_done_list, however it may be called directly if the
- * HC no longer sees the TD and it has not appeared on the donelist (after
- * two frames).  This bug has been observed on ZF Micro systems.
- */
+/* Take back a TD from the host controller */
 static void takeback_td(struct ohci_hcd *ohci, struct td *td)
 {
 	struct urb	*urb = td->urb;
@@ -1134,37 +1192,43 @@ static void takeback_td(struct ohci_hcd *ohci, struct td *td)
  *
  * This is the main path for handing urbs back to drivers.  The only other
  * normal path is finish_unlinks(), which unlinks URBs using ed_rm_list,
- * instead of scanning the (re-reversed) donelist as this does.  There's
- * an abnormal path too, handling a quirk in some Compaq silicon:  URBs
- * with TDs that appear to be orphaned are directly reclaimed.
+ * instead of scanning the (re-reversed) donelist as this does.
  */
-static void
-dl_done_list (struct ohci_hcd *ohci)
+static void process_done_list(struct ohci_hcd *ohci)
 {
-	struct td	*td = dl_reverse_done_list (ohci);
+	struct td	*td;
 
-	while (td) {
-		struct td	*td_next = td->next_dl_td;
-		struct ed	*ed = td->ed;
+	while (ohci->dl_start) {
+		td = ohci->dl_start;
+		if (td == ohci->dl_end)
+			ohci->dl_start = ohci->dl_end = NULL;
+		else
+			ohci->dl_start = td->next_dl_td;
 
-		/*
-		 * Some OHCI controllers (NVIDIA for sure, maybe others)
-		 * occasionally forget to add TDs to the done queue.  Since
-		 * TDs for a given endpoint are always processed in order,
-		 * if we find a TD on the donelist then all of its
-		 * predecessors must be finished as well.
-		 */
-		for (;;) {
-			struct td	*td2;
+		takeback_td(ohci, td);
+	}
+}
 
-			td2 = list_first_entry(&ed->td_list, struct td,
-					td_list);
-			if (td2 == td)
-				break;
-			takeback_td(ohci, td2);
-		}
+/*
+ * TD takeback and URB giveback must be single-threaded.
+ * This routine takes care of it all.
+ */
+static void ohci_work(struct ohci_hcd *ohci)
+{
+	if (ohci->working) {
+		ohci->restart_work = 1;
+		return;
+	}
+	ohci->working = 1;
 
-		takeback_td(ohci, td);
-		td = td_next;
+ restart:
+	process_done_list(ohci);
+	if (ohci->ed_rm_list)
+		finish_unlinks(ohci);
+
+	if (ohci->restart_work) {
+		ohci->restart_work = 0;
+		goto restart;
 	}
+	ohci->working = 0;
 }
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
index 8b29a0c04c23..8d5876692e7c 100644
--- a/drivers/usb/host/ohci-spear.c
+++ b/drivers/usb/host/ohci-spear.c
@@ -162,7 +162,7 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev)
 }
 #endif
 
-static struct of_device_id spear_ohci_id_table[] = {
+static const struct of_device_id spear_ohci_id_table[] = {
 	{ .compatible = "st,spear600-ohci", },
 	{ },
 };
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 05e02a709d4f..59f424567a8d 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -47,6 +47,7 @@ struct ed {
 	struct ed		*ed_next;	/* on schedule or rm_list */
 	struct ed		*ed_prev;	/* for non-interrupt EDs */
 	struct list_head	td_list;	/* "shadow list" of our TDs */
+	struct list_head	in_use_list;
 
 	/* create --> IDLE --> OPER --> ... --> IDLE --> destroy
 	 * usually:  OPER --> UNLINK --> (IDLE | OPER) --> ...
@@ -66,6 +67,13 @@ struct ed {
 
 	/* HC may see EDs on rm_list until next frame (frame_no == tick) */
 	u16			tick;
+
+	/* Detect TDs not added to the done queue */
+	unsigned		takeback_wdh_cnt;
+	struct td		*pending_td;
+#define	OKAY_TO_TAKEBACK(ohci, ed)			\
+		((int) (ohci->wdh_cnt - ed->takeback_wdh_cnt) >= 0)
+
 } __attribute__ ((aligned(16)));
 
 #define ED_MASK	((u32)~0x0f)		/* strip hw status in low addr bits */
@@ -380,7 +388,9 @@ struct ohci_hcd {
 	struct dma_pool		*td_cache;
 	struct dma_pool		*ed_cache;
 	struct td		*td_hash [TD_HASH_SIZE];
+	struct td		*dl_start, *dl_end;	/* the done list */
 	struct list_head	pending;
+	struct list_head	eds_in_use;	/* all EDs with at least 1 TD */
 
 	/*
 	 * driver state
@@ -392,6 +402,8 @@ struct ohci_hcd {
 	unsigned long		next_statechange;	/* suspend/resume */
 	u32			fminterval;		/* saved register */
 	unsigned		autostop:1;	/* rh auto stopping/stopped */
+	unsigned		working:1;
+	unsigned		restart_work:1;
 
 	unsigned long		flags;		/* for HC bugs */
 #define	OHCI_QUIRK_AMD756	0x01			/* erratum #4 */
@@ -409,13 +421,12 @@ struct ohci_hcd {
 
 	// there are also chip quirks/bugs in init logic
 
-	struct work_struct	nec_work;	/* Worker for NEC quirk */
+	unsigned		prev_frame_no;
+	unsigned		wdh_cnt, prev_wdh_cnt;
+	u32			prev_donehead;
+	struct timer_list	io_watchdog;
 
-	/* Needed for ZF Micro quirk */
-	struct timer_list	unlink_watchdog;
-	unsigned		eds_scheduled;
-	struct ed		*ed_to_check;
-	unsigned		zf_delay;
+	struct work_struct	nec_work;	/* Worker for NEC quirk */
 
 	struct dentry		*debug_dir;
 	struct dentry		*debug_async;
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index e07248b6ab67..da5fb0e3c363 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -3826,49 +3826,36 @@ static int oxu_drv_probe(struct platform_device *pdev)
 	dev_dbg(&pdev->dev, "IRQ resource %d\n", irq);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "no registers address! Check %s setup!\n",
-			dev_name(&pdev->dev));
-		return -ENODEV;
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base)) {
+		ret = PTR_ERR(base);
+		goto error;
 	}
 	memstart = res->start;
 	memlen = resource_size(res);
-	dev_dbg(&pdev->dev, "MEM resource %lx-%lx\n", memstart, memlen);
-	if (!request_mem_region(memstart, memlen,
-				oxu_hc_driver.description)) {
-		dev_dbg(&pdev->dev, "memory area already in use\n");
-		return -EBUSY;
-	}
 
 	ret = irq_set_irq_type(irq, IRQF_TRIGGER_FALLING);
 	if (ret) {
 		dev_err(&pdev->dev, "error setting irq type\n");
 		ret = -EFAULT;
-		goto error_set_irq_type;
-	}
-
-	base = ioremap(memstart, memlen);
-	if (!base) {
-		dev_dbg(&pdev->dev, "error mapping memory\n");
-		ret = -EFAULT;
-		goto error_ioremap;
+		goto error;
 	}
 
 	/* Allocate a driver data struct to hold useful info for both
 	 * SPH & OTG devices
 	 */
-	info = kzalloc(sizeof(struct oxu_info), GFP_KERNEL);
+	info = devm_kzalloc(&pdev->dev, sizeof(struct oxu_info), GFP_KERNEL);
 	if (!info) {
 		dev_dbg(&pdev->dev, "error allocating memory\n");
 		ret = -EFAULT;
-		goto error_alloc;
+		goto error;
 	}
 	platform_set_drvdata(pdev, info);
 
 	ret = oxu_init(pdev, memstart, memlen, base, irq);
 	if (ret < 0) {
 		dev_dbg(&pdev->dev, "cannot init USB devices\n");
-		goto error_init;
+		goto error;
 	}
 
 	dev_info(&pdev->dev, "devices enabled and running\n");
@@ -3876,16 +3863,7 @@ static int oxu_drv_probe(struct platform_device *pdev)
 
 	return 0;
 
-error_init:
-	kfree(info);
-
-error_alloc:
-	iounmap(base);
-
-error_set_irq_type:
-error_ioremap:
-	release_mem_region(memstart, memlen);
-
+error:
 	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), ret);
 	return ret;
 }
@@ -3899,18 +3877,10 @@ static void oxu_remove(struct platform_device *pdev, struct usb_hcd *hcd)
 static int oxu_drv_remove(struct platform_device *pdev)
 {
 	struct oxu_info *info = platform_get_drvdata(pdev);
-	unsigned long memstart = info->hcd[0]->rsrc_start,
-			memlen = info->hcd[0]->rsrc_len;
-	void *base = info->hcd[0]->regs;
 
 	oxu_remove(pdev, info->hcd[0]);
 	oxu_remove(pdev, info->hcd[1]);
 
-	iounmap(base);
-	release_mem_region(memstart, memlen);
-
-	kfree(info);
-
 	return 0;
 }
 
diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c
index ab25dc397e8b..05f57ffdf9ab 100644
--- a/drivers/usb/host/uhci-grlib.c
+++ b/drivers/usb/host/uhci-grlib.c
@@ -17,6 +17,7 @@
  * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
  */
 
+#include <linux/device.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
@@ -113,24 +114,17 @@ static int uhci_hcd_grlib_probe(struct platform_device *op)
 	hcd->rsrc_start = res.start;
 	hcd->rsrc_len = resource_size(&res);
 
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__);
-		rv = -EBUSY;
-		goto err_rmr;
-	}
-
 	irq = irq_of_parse_and_map(dn, 0);
 	if (irq == NO_IRQ) {
 		printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
 		rv = -EBUSY;
-		goto err_irq;
+		goto err_usb;
 	}
 
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		printk(KERN_ERR "%s: ioremap failed\n", __FILE__);
-		rv = -ENOMEM;
-		goto err_ioremap;
+	hcd->regs = devm_ioremap_resource(&op->dev, &res);
+	if (IS_ERR(hcd->regs)) {
+		rv = PTR_ERR(hcd->regs);
+		goto err_irq;
 	}
 
 	uhci = hcd_to_uhci(hcd);
@@ -139,18 +133,14 @@ static int uhci_hcd_grlib_probe(struct platform_device *op)
 
 	rv = usb_add_hcd(hcd, irq, 0);
 	if (rv)
-		goto err_uhci;
+		goto err_irq;
 
 	device_wakeup_enable(hcd->self.controller);
 	return 0;
 
-err_uhci:
-	iounmap(hcd->regs);
-err_ioremap:
-	irq_dispose_mapping(irq);
 err_irq:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err_rmr:
+	irq_dispose_mapping(irq);
+err_usb:
 	usb_put_hcd(hcd);
 
 	return rv;
@@ -164,10 +154,7 @@ static int uhci_hcd_grlib_remove(struct platform_device *op)
 
 	usb_remove_hcd(hcd);
 
-	iounmap(hcd->regs);
 	irq_dispose_mapping(hcd->irq);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-
 	usb_put_hcd(hcd);
 
 	return 0;
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 27f35e8f161b..a7de8e8bb458 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -591,7 +591,7 @@ static int uhci_start(struct usb_hcd *hcd)
 
 	uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
 			UHCI_NUMFRAMES * sizeof(*uhci->frame),
-			&uhci->frame_dma_handle, 0);
+			&uhci->frame_dma_handle, GFP_KERNEL);
 	if (!uhci->frame) {
 		dev_err(uhci_dev(uhci),
 			"unable to allocate consistent memory for frame list\n");
diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
index 01833ab2b5c3..b987f1d10058 100644
--- a/drivers/usb/host/uhci-platform.c
+++ b/drivers/usb/host/uhci-platform.c
@@ -8,6 +8,7 @@
  */
 
 #include <linux/of.h>
+#include <linux/device.h>
 #include <linux/platform_device.h>
 
 static int uhci_platform_init(struct usb_hcd *hcd)
@@ -88,33 +89,22 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev)
 	hcd->rsrc_start = res->start;
 	hcd->rsrc_len = resource_size(res);
 
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		pr_err("%s: request_mem_region failed\n", __func__);
-		ret = -EBUSY;
+	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(hcd->regs)) {
+		ret = PTR_ERR(hcd->regs);
 		goto err_rmr;
 	}
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		pr_err("%s: ioremap failed\n", __func__);
-		ret = -ENOMEM;
-		goto err_irq;
-	}
 	uhci = hcd_to_uhci(hcd);
 
 	uhci->regs = hcd->regs;
 
 	ret = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED);
 	if (ret)
-		goto err_uhci;
+		goto err_rmr;
 
 	device_wakeup_enable(hcd->self.controller);
 	return 0;
 
-err_uhci:
-	iounmap(hcd->regs);
-err_irq:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 err_rmr:
 	usb_put_hcd(hcd);
 
@@ -126,8 +116,6 @@ static int uhci_hcd_platform_remove(struct platform_device *pdev)
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
 	usb_remove_hcd(hcd);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 
 	return 0;
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index e20520f42753..687d36608155 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -33,7 +33,7 @@
 #define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400	0x1400
 
 #define PCI_VENDOR_ID_ETRON		0x1b6f
-#define PCI_DEVICE_ID_ASROCK_P67	0x7023
+#define PCI_DEVICE_ID_EJ168		0x7023
 
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI	0x8c31
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI	0x9c31
@@ -140,9 +140,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
 		xhci->quirks |= XHCI_SPURIOUS_REBOOT;
 	}
 	if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
-			pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
+			pdev->device == PCI_DEVICE_ID_EJ168) {
 		xhci->quirks |= XHCI_RESET_ON_RESUME;
 		xhci->quirks |= XHCI_TRUST_TX_LENGTH;
+		xhci->quirks |= XHCI_BROKEN_STREAMS;
 	}
 	if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
 			pdev->device == 0x0015)
@@ -230,7 +231,8 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		goto put_usb3_hcd;
 	/* Roothub already marked as USB 3.0 speed */
 
-	if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
+	if (!(xhci->quirks & XHCI_BROKEN_STREAMS) &&
+			HCC_MAX_PSA(xhci->hcc_params) >= 4)
 		xhci->shared_hcd->can_do_streams = 1;
 
 	/* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 29d8adb5c8d1..1a0cf9f31e43 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -17,9 +17,11 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/usb/xhci_pdriver.h>
 
 #include "xhci.h"
 #include "xhci-mvebu.h"
+#include "xhci-rcar.h"
 
 static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
 {
@@ -34,11 +36,27 @@ static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
 /* called during probe() after chip reset completes */
 static int xhci_plat_setup(struct usb_hcd *hcd)
 {
+	struct device_node *of_node = hcd->self.controller->of_node;
+	int ret;
+
+	if (of_device_is_compatible(of_node, "renesas,xhci-r8a7790") ||
+	    of_device_is_compatible(of_node, "renesas,xhci-r8a7791")) {
+		ret = xhci_rcar_init_quirk(hcd);
+		if (ret)
+			return ret;
+	}
+
 	return xhci_gen_setup(hcd, xhci_plat_quirks);
 }
 
 static int xhci_plat_start(struct usb_hcd *hcd)
 {
+	struct device_node *of_node = hcd->self.controller->of_node;
+
+	if (of_device_is_compatible(of_node, "renesas,xhci-r8a7790") ||
+	    of_device_is_compatible(of_node, "renesas,xhci-r8a7791"))
+		xhci_rcar_start(hcd);
+
 	return xhci_run(hcd);
 }
 
@@ -90,10 +108,15 @@ static const struct hc_driver xhci_plat_xhci_driver = {
 	.hub_status_data =	xhci_hub_status_data,
 	.bus_suspend =		xhci_bus_suspend,
 	.bus_resume =		xhci_bus_resume,
+
+	.enable_usb3_lpm_timeout =	xhci_enable_usb3_lpm_timeout,
+	.disable_usb3_lpm_timeout =	xhci_disable_usb3_lpm_timeout,
 };
 
 static int xhci_plat_probe(struct platform_device *pdev)
 {
+	struct device_node	*node = pdev->dev.of_node;
+	struct usb_xhci_pdata	*pdata = dev_get_platdata(&pdev->dev);
 	const struct hc_driver	*driver;
 	struct xhci_hcd		*xhci;
 	struct resource         *res;
@@ -140,20 +163,12 @@ static int xhci_plat_probe(struct platform_device *pdev)
 	hcd->rsrc_start = res->start;
 	hcd->rsrc_len = resource_size(res);
 
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-				driver->description)) {
-		dev_dbg(&pdev->dev, "controller already in use\n");
-		ret = -EBUSY;
+	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(hcd->regs)) {
+		ret = PTR_ERR(hcd->regs);
 		goto put_hcd;
 	}
 
-	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		dev_dbg(&pdev->dev, "error mapping memory\n");
-		ret = -EFAULT;
-		goto release_mem_region;
-	}
-
 	/*
 	 * Not all platforms have a clk so it is not an error if the
 	 * clock does not exists.
@@ -162,7 +177,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
 	if (!IS_ERR(clk)) {
 		ret = clk_prepare_enable(clk);
 		if (ret)
-			goto unmap_registers;
+			goto put_hcd;
 	}
 
 	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
@@ -182,6 +197,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
 		goto dealloc_usb2_hcd;
 	}
 
+	if ((node && of_property_read_bool(node, "usb3-lpm-capable")) ||
+			(pdata && pdata->usb3_lpm_capable))
+		xhci->quirks |= XHCI_LPM_SUPPORT;
 	/*
 	 * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset)
 	 * is called by usb_add_hcd().
@@ -207,12 +225,6 @@ disable_clk:
 	if (!IS_ERR(clk))
 		clk_disable_unprepare(clk);
 
-unmap_registers:
-	iounmap(hcd->regs);
-
-release_mem_region:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-
 put_hcd:
 	usb_put_hcd(hcd);
 
@@ -231,8 +243,6 @@ static int xhci_plat_remove(struct platform_device *dev)
 	usb_remove_hcd(hcd);
 	if (!IS_ERR(clk))
 		clk_disable_unprepare(clk);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 	kfree(xhci);
 
@@ -270,6 +280,8 @@ static const struct of_device_id usb_xhci_of_match[] = {
 	{ .compatible = "xhci-platform" },
 	{ .compatible = "marvell,armada-375-xhci"},
 	{ .compatible = "marvell,armada-380-xhci"},
+	{ .compatible = "renesas,xhci-r8a7790"},
+	{ .compatible = "renesas,xhci-r8a7791"},
 	{ },
 };
 MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
new file mode 100644
index 000000000000..ff0d1b44ea58
--- /dev/null
+++ b/drivers/usb/host/xhci-rcar.c
@@ -0,0 +1,148 @@
+/*
+ * xHCI host controller driver for R-Car SoCs
+ *
+ * Copyright (C) 2014 Renesas Electronics 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/firmware.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/usb/phy.h>
+
+#include "xhci.h"
+#include "xhci-rcar.h"
+
+#define FIRMWARE_NAME		"r8a779x_usb3_v1.dlmem"
+MODULE_FIRMWARE(FIRMWARE_NAME);
+
+/*** Register Offset ***/
+#define RCAR_USB3_INT_ENA	0x224	/* Interrupt Enable */
+#define RCAR_USB3_DL_CTRL	0x250	/* FW Download Control & Status */
+#define RCAR_USB3_FW_DATA0	0x258	/* FW Data0 */
+
+#define RCAR_USB3_LCLK		0xa44	/* LCLK Select */
+#define RCAR_USB3_CONF1		0xa48	/* USB3.0 Configuration1 */
+#define RCAR_USB3_CONF2		0xa5c	/* USB3.0 Configuration2 */
+#define RCAR_USB3_CONF3		0xaa8	/* USB3.0 Configuration3 */
+#define RCAR_USB3_RX_POL	0xab0	/* USB3.0 RX Polarity */
+#define RCAR_USB3_TX_POL	0xab8	/* USB3.0 TX Polarity */
+
+/*** Register Settings ***/
+/* Interrupt Enable */
+#define RCAR_USB3_INT_XHC_ENA	0x00000001
+#define RCAR_USB3_INT_PME_ENA	0x00000002
+#define RCAR_USB3_INT_HSE_ENA	0x00000004
+#define RCAR_USB3_INT_ENA_VAL	(RCAR_USB3_INT_XHC_ENA | \
+				RCAR_USB3_INT_PME_ENA | RCAR_USB3_INT_HSE_ENA)
+
+/* FW Download Control & Status */
+#define RCAR_USB3_DL_CTRL_ENABLE	0x00000001
+#define RCAR_USB3_DL_CTRL_FW_SUCCESS	0x00000010
+#define RCAR_USB3_DL_CTRL_FW_SET_DATA0	0x00000100
+
+/* LCLK Select */
+#define RCAR_USB3_LCLK_ENA_VAL	0x01030001
+
+/* USB3.0 Configuration */
+#define RCAR_USB3_CONF1_VAL	0x00030204
+#define RCAR_USB3_CONF2_VAL	0x00030300
+#define RCAR_USB3_CONF3_VAL	0x13802007
+
+/* USB3.0 Polarity */
+#define RCAR_USB3_RX_POL_VAL	BIT(21)
+#define RCAR_USB3_TX_POL_VAL	BIT(4)
+
+void xhci_rcar_start(struct usb_hcd *hcd)
+{
+	u32 temp;
+
+	if (hcd->regs != NULL) {
+		/* Interrupt Enable */
+		temp = readl(hcd->regs + RCAR_USB3_INT_ENA);
+		temp |= RCAR_USB3_INT_ENA_VAL;
+		writel(temp, hcd->regs + RCAR_USB3_INT_ENA);
+		/* LCLK Select */
+		writel(RCAR_USB3_LCLK_ENA_VAL, hcd->regs + RCAR_USB3_LCLK);
+		/* USB3.0 Configuration */
+		writel(RCAR_USB3_CONF1_VAL, hcd->regs + RCAR_USB3_CONF1);
+		writel(RCAR_USB3_CONF2_VAL, hcd->regs + RCAR_USB3_CONF2);
+		writel(RCAR_USB3_CONF3_VAL, hcd->regs + RCAR_USB3_CONF3);
+		/* USB3.0 Polarity */
+		writel(RCAR_USB3_RX_POL_VAL, hcd->regs + RCAR_USB3_RX_POL);
+		writel(RCAR_USB3_TX_POL_VAL, hcd->regs + RCAR_USB3_TX_POL);
+	}
+}
+
+static int xhci_rcar_download_firmware(struct device *dev, void __iomem *regs)
+{
+	const struct firmware *fw;
+	int retval, index, j, time;
+	int timeout = 10000;
+	u32 data, val, temp;
+
+	/* request R-Car USB3.0 firmware */
+	retval = request_firmware(&fw, FIRMWARE_NAME, dev);
+	if (retval)
+		return retval;
+
+	/* download R-Car USB3.0 firmware */
+	temp = readl(regs + RCAR_USB3_DL_CTRL);
+	temp |= RCAR_USB3_DL_CTRL_ENABLE;
+	writel(temp, regs + RCAR_USB3_DL_CTRL);
+
+	for (index = 0; index < fw->size; index += 4) {
+		/* to avoid reading beyond the end of the buffer */
+		for (data = 0, j = 3; j >= 0; j--) {
+			if ((j + index) < fw->size)
+				data |= fw->data[index + j] << (8 * j);
+		}
+		writel(data, regs + RCAR_USB3_FW_DATA0);
+		temp = readl(regs + RCAR_USB3_DL_CTRL);
+		temp |= RCAR_USB3_DL_CTRL_FW_SET_DATA0;
+		writel(temp, regs + RCAR_USB3_DL_CTRL);
+
+		for (time = 0; time < timeout; time++) {
+			val = readl(regs + RCAR_USB3_DL_CTRL);
+			if ((val & RCAR_USB3_DL_CTRL_FW_SET_DATA0) == 0)
+				break;
+			udelay(1);
+		}
+		if (time == timeout) {
+			retval = -ETIMEDOUT;
+			break;
+		}
+	}
+
+	temp = readl(regs + RCAR_USB3_DL_CTRL);
+	temp &= ~RCAR_USB3_DL_CTRL_ENABLE;
+	writel(temp, regs + RCAR_USB3_DL_CTRL);
+
+	for (time = 0; time < timeout; time++) {
+		val = readl(regs + RCAR_USB3_DL_CTRL);
+		if (val & RCAR_USB3_DL_CTRL_FW_SUCCESS) {
+			retval = 0;
+			break;
+		}
+		udelay(1);
+	}
+	if (time == timeout)
+		retval = -ETIMEDOUT;
+
+	release_firmware(fw);
+
+	return retval;
+}
+
+/* This function needs to initialize a "phy" of usb before */
+int xhci_rcar_init_quirk(struct usb_hcd *hcd)
+{
+	/* If hcd->regs is NULL, we don't just call the following function */
+	if (!hcd->regs)
+		return 0;
+
+	return xhci_rcar_download_firmware(hcd->self.controller, hcd->regs);
+}
diff --git a/drivers/usb/host/xhci-rcar.h b/drivers/usb/host/xhci-rcar.h
new file mode 100644
index 000000000000..58501256715d
--- /dev/null
+++ b/drivers/usb/host/xhci-rcar.h
@@ -0,0 +1,27 @@
+/*
+ * drivers/usb/host/xhci-rcar.h
+ *
+ * Copyright (C) 2014 Renesas Electronics 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 _XHCI_RCAR_H
+#define _XHCI_RCAR_H
+
+#if IS_ENABLED(CONFIG_USB_XHCI_RCAR)
+void xhci_rcar_start(struct usb_hcd *hcd);
+int xhci_rcar_init_quirk(struct usb_hcd *hcd);
+#else
+static inline void xhci_rcar_start(struct usb_hcd *hcd)
+{
+}
+
+static inline int xhci_rcar_init_quirk(struct usb_hcd *hcd)
+{
+	return 0;
+}
+#endif
+#endif /* _XHCI_RCAR_H */
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 749fc68eb5c1..60fb52ae864b 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1118,6 +1118,10 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
 	if (xhci->quirks & XHCI_RESET_EP_QUIRK) {
 		struct xhci_command *command;
 		command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
+		if (!command) {
+			xhci_warn(xhci, "WARN Cannot submit cfg ep: ENOMEM\n");
+			return;
+		}
 		xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
 				"Queueing configure endpoint command");
 		xhci_queue_configure_endpoint(xhci, command,
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 7436d5f5e67a..b6f21175b872 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1553,6 +1553,10 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 	 */
 	if (!(ep->ep_state & EP_HALT_PENDING)) {
 		command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
+		if (!command) {
+			ret = -ENOMEM;
+			goto done;
+		}
 		ep->ep_state |= EP_HALT_PENDING;
 		ep->stop_cmds_pending++;
 		ep->stop_cmd_timer.expires = jiffies +
@@ -1586,12 +1590,10 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
 	struct xhci_hcd *xhci;
 	struct xhci_container_ctx *in_ctx, *out_ctx;
 	struct xhci_input_control_ctx *ctrl_ctx;
-	struct xhci_slot_ctx *slot_ctx;
-	unsigned int last_ctx;
 	unsigned int ep_index;
 	struct xhci_ep_ctx *ep_ctx;
 	u32 drop_flag;
-	u32 new_add_flags, new_drop_flags, new_slot_info;
+	u32 new_add_flags, new_drop_flags;
 	int ret;
 
 	ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
@@ -1638,24 +1640,13 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
 	ctrl_ctx->add_flags &= cpu_to_le32(~drop_flag);
 	new_add_flags = le32_to_cpu(ctrl_ctx->add_flags);
 
-	last_ctx = xhci_last_valid_endpoint(le32_to_cpu(ctrl_ctx->add_flags));
-	slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
-	/* Update the last valid endpoint context, if we deleted the last one */
-	if ((le32_to_cpu(slot_ctx->dev_info) & LAST_CTX_MASK) >
-	    LAST_CTX(last_ctx)) {
-		slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK);
-		slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(last_ctx));
-	}
-	new_slot_info = le32_to_cpu(slot_ctx->dev_info);
-
 	xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
 
-	xhci_dbg(xhci, "drop ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x, new slot info = %#x\n",
+	xhci_dbg(xhci, "drop ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n",
 			(unsigned int) ep->desc.bEndpointAddress,
 			udev->slot_id,
 			(unsigned int) new_drop_flags,
-			(unsigned int) new_add_flags,
-			(unsigned int) new_slot_info);
+			(unsigned int) new_add_flags);
 	return 0;
 }
 
@@ -1678,11 +1669,9 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
 	struct xhci_hcd *xhci;
 	struct xhci_container_ctx *in_ctx, *out_ctx;
 	unsigned int ep_index;
-	struct xhci_slot_ctx *slot_ctx;
 	struct xhci_input_control_ctx *ctrl_ctx;
 	u32 added_ctxs;
-	unsigned int last_ctx;
-	u32 new_add_flags, new_drop_flags, new_slot_info;
+	u32 new_add_flags, new_drop_flags;
 	struct xhci_virt_device *virt_dev;
 	int ret = 0;
 
@@ -1697,7 +1686,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
 		return -ENODEV;
 
 	added_ctxs = xhci_get_endpoint_flag(&ep->desc);
-	last_ctx = xhci_last_valid_endpoint(added_ctxs);
 	if (added_ctxs == SLOT_FLAG || added_ctxs == EP0_FLAG) {
 		/* FIXME when we have to issue an evaluate endpoint command to
 		 * deal with ep0 max packet size changing once we get the
@@ -1763,24 +1751,14 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
 	 */
 	new_drop_flags = le32_to_cpu(ctrl_ctx->drop_flags);
 
-	slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
-	/* Update the last valid endpoint context, if we just added one past */
-	if ((le32_to_cpu(slot_ctx->dev_info) & LAST_CTX_MASK) <
-	    LAST_CTX(last_ctx)) {
-		slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK);
-		slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(last_ctx));
-	}
-	new_slot_info = le32_to_cpu(slot_ctx->dev_info);
-
 	/* Store the usb_device pointer for later use */
 	ep->hcpriv = udev;
 
-	xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x, new slot info = %#x\n",
+	xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n",
 			(unsigned int) ep->desc.bEndpointAddress,
 			udev->slot_id,
 			(unsigned int) new_drop_flags,
-			(unsigned int) new_add_flags,
-			(unsigned int) new_slot_info);
+			(unsigned int) new_add_flags);
 	return 0;
 }
 
@@ -1830,15 +1808,15 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
 		ret = -ETIME;
 		break;
 	case COMP_ENOMEM:
-		dev_warn(&udev->dev, "Not enough host controller resources "
-				"for new device state.\n");
+		dev_warn(&udev->dev,
+			 "Not enough host controller resources for new device state.\n");
 		ret = -ENOMEM;
 		/* FIXME: can we allocate more resources for the HC? */
 		break;
 	case COMP_BW_ERR:
 	case COMP_2ND_BW_ERR:
-		dev_warn(&udev->dev, "Not enough bandwidth "
-				"for new device state.\n");
+		dev_warn(&udev->dev,
+			 "Not enough bandwidth for new device state.\n");
 		ret = -ENOSPC;
 		/* FIXME: can we go back to the old state? */
 		break;
@@ -1850,8 +1828,8 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
 		ret = -EINVAL;
 		break;
 	case COMP_DEV_ERR:
-		dev_warn(&udev->dev, "ERROR: Incompatible device for endpoint "
-				"configure command.\n");
+		dev_warn(&udev->dev,
+			 "ERROR: Incompatible device for endpoint configure command.\n");
 		ret = -ENODEV;
 		break;
 	case COMP_SUCCESS:
@@ -1860,8 +1838,8 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
 		ret = 0;
 		break;
 	default:
-		xhci_err(xhci, "ERROR: unexpected command completion "
-				"code 0x%x.\n", *cmd_status);
+		xhci_err(xhci, "ERROR: unexpected command completion code 0x%x.\n",
+				*cmd_status);
 		ret = -EINVAL;
 		break;
 	}
@@ -1881,24 +1859,24 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
 		ret = -ETIME;
 		break;
 	case COMP_EINVAL:
-		dev_warn(&udev->dev, "WARN: xHCI driver setup invalid evaluate "
-				"context command.\n");
+		dev_warn(&udev->dev,
+			 "WARN: xHCI driver setup invalid evaluate context command.\n");
 		ret = -EINVAL;
 		break;
 	case COMP_EBADSLT:
-		dev_warn(&udev->dev, "WARN: slot not enabled for"
-				"evaluate context command.\n");
+		dev_warn(&udev->dev,
+			"WARN: slot not enabled for evaluate context command.\n");
 		ret = -EINVAL;
 		break;
 	case COMP_CTX_STATE:
-		dev_warn(&udev->dev, "WARN: invalid context state for "
-				"evaluate context command.\n");
+		dev_warn(&udev->dev,
+			"WARN: invalid context state for evaluate context command.\n");
 		xhci_dbg_ctx(xhci, virt_dev->out_ctx, 1);
 		ret = -EINVAL;
 		break;
 	case COMP_DEV_ERR:
-		dev_warn(&udev->dev, "ERROR: Incompatible device for evaluate "
-				"context command.\n");
+		dev_warn(&udev->dev,
+			"ERROR: Incompatible device for evaluate context command.\n");
 		ret = -ENODEV;
 		break;
 	case COMP_MEL_ERR:
@@ -1912,8 +1890,8 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
 		ret = 0;
 		break;
 	default:
-		xhci_err(xhci, "ERROR: unexpected command completion "
-				"code 0x%x.\n", *cmd_status);
+		xhci_err(xhci, "ERROR: unexpected command completion code 0x%x.\n",
+			*cmd_status);
 		ret = -EINVAL;
 		break;
 	}
@@ -2750,8 +2728,19 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
 		ret = 0;
 		goto command_cleanup;
 	}
-	xhci_dbg(xhci, "New Input Control Context:\n");
+	/* Fix up Context Entries field. Minimum value is EP0 == BIT(1). */
 	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
+	for (i = 31; i >= 1; i--) {
+		__le32 le32 = cpu_to_le32(BIT(i));
+
+		if ((virt_dev->eps[i-1].ring && !(ctrl_ctx->drop_flags & le32))
+		    || (ctrl_ctx->add_flags & le32) || i == 1) {
+			slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK);
+			slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(i));
+			break;
+		}
+	}
+	xhci_dbg(xhci, "New Input Control Context:\n");
 	xhci_dbg_ctx(xhci, virt_dev->in_ctx,
 		     LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)));
 
@@ -3163,7 +3152,8 @@ int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
 			num_streams);
 
 	/* MaxPSASize value 0 (2 streams) means streams are not supported */
-	if (HCC_MAX_PSA(xhci->hcc_params) < 4) {
+	if ((xhci->quirks & XHCI_BROKEN_STREAMS) ||
+			HCC_MAX_PSA(xhci->hcc_params) < 4) {
 		xhci_dbg(xhci, "xHCI controller does not support streams.\n");
 		return -ENOSYS;
 	}
@@ -4303,8 +4293,7 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
 	return USB3_LPM_DISABLED;
 }
 
-/* Returns the hub-encoded U1 timeout value.
- * The U1 timeout should be the maximum of the following values:
+/* The U1 timeout should be the maximum of the following values:
  *  - For control endpoints, U1 system exit latency (SEL) * 3
  *  - For bulk endpoints, U1 SEL * 5
  *  - For interrupt endpoints:
@@ -4312,7 +4301,8 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
  *    - Periodic EPs, max(105% of bInterval, U1 SEL * 2)
  *  - For isochronous endpoints, max(105% of bInterval, U1 SEL * 2)
  */
-static u16 xhci_calculate_intel_u1_timeout(struct usb_device *udev,
+static unsigned long long xhci_calculate_intel_u1_timeout(
+		struct usb_device *udev,
 		struct usb_endpoint_descriptor *desc)
 {
 	unsigned long long timeout_ns;
@@ -4344,11 +4334,28 @@ static u16 xhci_calculate_intel_u1_timeout(struct usb_device *udev,
 		return 0;
 	}
 
-	/* The U1 timeout is encoded in 1us intervals. */
-	timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 1000);
-	/* Don't return a timeout of zero, because that's USB3_LPM_DISABLED. */
+	return timeout_ns;
+}
+
+/* Returns the hub-encoded U1 timeout value. */
+static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci,
+		struct usb_device *udev,
+		struct usb_endpoint_descriptor *desc)
+{
+	unsigned long long timeout_ns;
+
+	if (xhci->quirks & XHCI_INTEL_HOST)
+		timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc);
+	else
+		timeout_ns = udev->u1_params.sel;
+
+	/* The U1 timeout is encoded in 1us intervals.
+	 * Don't return a timeout of zero, because that's USB3_LPM_DISABLED.
+	 */
 	if (timeout_ns == USB3_LPM_DISABLED)
-		timeout_ns++;
+		timeout_ns = 1;
+	else
+		timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 1000);
 
 	/* If the necessary timeout value is bigger than what we can set in the
 	 * USB 3.0 hub, we have to disable hub-initiated U1.
@@ -4360,14 +4367,14 @@ static u16 xhci_calculate_intel_u1_timeout(struct usb_device *udev,
 	return xhci_get_timeout_no_hub_lpm(udev, USB3_LPM_U1);
 }
 
-/* Returns the hub-encoded U2 timeout value.
- * The U2 timeout should be the maximum of:
+/* The U2 timeout should be the maximum of:
  *  - 10 ms (to avoid the bandwidth impact on the scheduler)
  *  - largest bInterval of any active periodic endpoint (to avoid going
  *    into lower power link states between intervals).
  *  - the U2 Exit Latency of the device
  */
-static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,
+static unsigned long long xhci_calculate_intel_u2_timeout(
+		struct usb_device *udev,
 		struct usb_endpoint_descriptor *desc)
 {
 	unsigned long long timeout_ns;
@@ -4383,6 +4390,21 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,
 	if (u2_del_ns > timeout_ns)
 		timeout_ns = u2_del_ns;
 
+	return timeout_ns;
+}
+
+/* Returns the hub-encoded U2 timeout value. */
+static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci,
+		struct usb_device *udev,
+		struct usb_endpoint_descriptor *desc)
+{
+	unsigned long long timeout_ns;
+
+	if (xhci->quirks & XHCI_INTEL_HOST)
+		timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc);
+	else
+		timeout_ns = udev->u2_params.sel;
+
 	/* The U2 timeout is encoded in 256us intervals */
 	timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 256 * 1000);
 	/* If the necessary timeout value is bigger than what we can set in the
@@ -4401,13 +4423,10 @@ static u16 xhci_call_host_update_timeout_for_endpoint(struct xhci_hcd *xhci,
 		enum usb3_link_state state,
 		u16 *timeout)
 {
-	if (state == USB3_LPM_U1) {
-		if (xhci->quirks & XHCI_INTEL_HOST)
-			return xhci_calculate_intel_u1_timeout(udev, desc);
-	} else {
-		if (xhci->quirks & XHCI_INTEL_HOST)
-			return xhci_calculate_intel_u2_timeout(udev, desc);
-	}
+	if (state == USB3_LPM_U1)
+		return xhci_calculate_u1_timeout(xhci, udev, desc);
+	else if (state == USB3_LPM_U2)
+		return xhci_calculate_u2_timeout(xhci, udev, desc);
 
 	return USB3_LPM_DISABLED;
 }
@@ -4484,7 +4503,8 @@ static int xhci_check_tier_policy(struct xhci_hcd *xhci,
 {
 	if (xhci->quirks & XHCI_INTEL_HOST)
 		return xhci_check_intel_tier_policy(udev, state);
-	return -EINVAL;
+	else
+		return 0;
 }
 
 /* Returns the U1 or U2 timeout that should be enabled.
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 9ffecd56600d..dace5152e179 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1558,6 +1558,8 @@ struct xhci_hcd {
 #define XHCI_PLAT		(1 << 16)
 #define XHCI_SLOW_SUSPEND	(1 << 17)
 #define XHCI_SPURIOUS_WAKEUP	(1 << 18)
+/* For controllers with a broken beyond repair streams implementation */
+#define XHCI_BROKEN_STREAMS	(1 << 19)
 	unsigned int		num_active_eps;
 	unsigned int		limit_active_eps;
 	/* There are two roothubs to keep track of bus suspend info for */
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 1bca274dc3b5..76d77206e011 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -248,3 +248,10 @@ config USB_HSIC_USB3503
        select REGMAP_I2C
        help
          This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver.
+
+config USB_LINK_LAYER_TEST
+	tristate "USB Link Layer Test driver"
+	help
+	  This driver is for generating specific traffic for Super Speed Link
+	  Layer Test Device. Say Y only when you want to conduct USB Super Speed
+	  Link Layer Test for host controllers.
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index e748fd5dbe94..65b0402c1ca1 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -27,3 +27,4 @@ obj-$(CONFIG_USB_YUREX)			+= yurex.o
 obj-$(CONFIG_USB_HSIC_USB3503)		+= usb3503.o
 
 obj-$(CONFIG_USB_SISUSBVGA)		+= sisusbvga/
+obj-$(CONFIG_USB_LINK_LAYER_TEST)	+= lvstest.o
diff --git a/drivers/usb/misc/lvstest.c b/drivers/usb/misc/lvstest.c
new file mode 100644
index 000000000000..7d589c156fb1
--- /dev/null
+++ b/drivers/usb/misc/lvstest.c
@@ -0,0 +1,460 @@
+/*
+ * drivers/usb/misc/lvstest.c
+ *
+ * Test pattern generation for Link Layer Validation System Tests
+ *
+ * Copyright (C) 2014 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@st.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.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/ch11.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/phy.h>
+
+struct lvs_rh {
+	/* root hub interface */
+	struct usb_interface *intf;
+	/* if lvs device connected */
+	bool present;
+	/* port no at which lvs device is present */
+	int portnum;
+	/* urb buffer */
+	u8 buffer[8];
+	/* class descriptor */
+	struct usb_hub_descriptor descriptor;
+	/* urb for polling interrupt pipe */
+	struct urb *urb;
+	/* LVS RH work queue */
+	struct workqueue_struct *rh_queue;
+	/* LVH RH work */
+	struct work_struct	rh_work;
+	/* RH port status */
+	struct usb_port_status port_status;
+};
+
+static struct usb_device *create_lvs_device(struct usb_interface *intf)
+{
+	struct usb_device *udev, *hdev;
+	struct usb_hcd *hcd;
+	struct lvs_rh *lvs = usb_get_intfdata(intf);
+
+	if (!lvs->present) {
+		dev_err(&intf->dev, "No LVS device is present\n");
+		return NULL;
+	}
+
+	hdev = interface_to_usbdev(intf);
+	hcd = bus_to_hcd(hdev->bus);
+
+	udev = usb_alloc_dev(hdev, hdev->bus, lvs->portnum);
+	if (!udev) {
+		dev_err(&intf->dev, "Could not allocate lvs udev\n");
+		return NULL;
+	}
+	udev->speed = USB_SPEED_SUPER;
+	udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
+	usb_set_device_state(udev, USB_STATE_DEFAULT);
+
+	if (hcd->driver->enable_device) {
+		if (hcd->driver->enable_device(hcd, udev) < 0) {
+			dev_err(&intf->dev, "Failed to enable\n");
+			usb_put_dev(udev);
+			return NULL;
+		}
+	}
+
+	return udev;
+}
+
+static void destroy_lvs_device(struct usb_device *udev)
+{
+	struct usb_device *hdev = udev->parent;
+	struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
+
+	if (hcd->driver->free_dev)
+		hcd->driver->free_dev(hcd, udev);
+
+	usb_put_dev(udev);
+}
+
+static int lvs_rh_clear_port_feature(struct usb_device *hdev,
+		int port1, int feature)
+{
+	return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
+		USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port1,
+		NULL, 0, 1000);
+}
+
+static int lvs_rh_set_port_feature(struct usb_device *hdev,
+		int port1, int feature)
+{
+	return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
+		USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port1,
+		NULL, 0, 1000);
+}
+
+static ssize_t u3_entry_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usb_device *hdev = interface_to_usbdev(intf);
+	struct lvs_rh *lvs = usb_get_intfdata(intf);
+	struct usb_device *udev;
+	int ret;
+
+	udev = create_lvs_device(intf);
+	if (!udev) {
+		dev_err(dev, "failed to create lvs device\n");
+		return -ENOMEM;
+	}
+
+	ret = lvs_rh_set_port_feature(hdev, lvs->portnum,
+			USB_PORT_FEAT_SUSPEND);
+	if (ret < 0)
+		dev_err(dev, "can't issue U3 entry %d\n", ret);
+
+	destroy_lvs_device(udev);
+
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+static DEVICE_ATTR_WO(u3_entry);
+
+static ssize_t u3_exit_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usb_device *hdev = interface_to_usbdev(intf);
+	struct lvs_rh *lvs = usb_get_intfdata(intf);
+	struct usb_device *udev;
+	int ret;
+
+	udev = create_lvs_device(intf);
+	if (!udev) {
+		dev_err(dev, "failed to create lvs device\n");
+		return -ENOMEM;
+	}
+
+	ret = lvs_rh_clear_port_feature(hdev, lvs->portnum,
+			USB_PORT_FEAT_SUSPEND);
+	if (ret < 0)
+		dev_err(dev, "can't issue U3 exit %d\n", ret);
+
+	destroy_lvs_device(udev);
+
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+static DEVICE_ATTR_WO(u3_exit);
+
+static ssize_t hot_reset_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usb_device *hdev = interface_to_usbdev(intf);
+	struct lvs_rh *lvs = usb_get_intfdata(intf);
+	int ret;
+
+	ret = lvs_rh_set_port_feature(hdev, lvs->portnum,
+			USB_PORT_FEAT_RESET);
+	if (ret < 0) {
+		dev_err(dev, "can't issue hot reset %d\n", ret);
+		return ret;
+	}
+
+	return count;
+}
+static DEVICE_ATTR_WO(hot_reset);
+
+static ssize_t u2_timeout_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usb_device *hdev = interface_to_usbdev(intf);
+	struct lvs_rh *lvs = usb_get_intfdata(intf);
+	unsigned long val;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret < 0) {
+		dev_err(dev, "couldn't parse string %d\n", ret);
+		return ret;
+	}
+
+	if (val < 0 || val > 127)
+		return -EINVAL;
+
+	ret = lvs_rh_set_port_feature(hdev, lvs->portnum | (val << 8),
+			USB_PORT_FEAT_U2_TIMEOUT);
+	if (ret < 0) {
+		dev_err(dev, "Error %d while setting U2 timeout %ld\n", ret, val);
+		return ret;
+	}
+
+	return count;
+}
+static DEVICE_ATTR_WO(u2_timeout);
+
+static ssize_t u1_timeout_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usb_device *hdev = interface_to_usbdev(intf);
+	struct lvs_rh *lvs = usb_get_intfdata(intf);
+	unsigned long val;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret < 0) {
+		dev_err(dev, "couldn't parse string %d\n", ret);
+		return ret;
+	}
+
+	if (val < 0 || val > 127)
+		return -EINVAL;
+
+	ret = lvs_rh_set_port_feature(hdev, lvs->portnum | (val << 8),
+			USB_PORT_FEAT_U1_TIMEOUT);
+	if (ret < 0) {
+		dev_err(dev, "Error %d while setting U1 timeout %ld\n", ret, val);
+		return ret;
+	}
+
+	return count;
+}
+static DEVICE_ATTR_WO(u1_timeout);
+
+static ssize_t get_dev_desc_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usb_device *udev;
+	struct usb_device_descriptor *descriptor;
+	int ret;
+
+	descriptor = kmalloc(sizeof(*descriptor), GFP_KERNEL);
+	if (!descriptor) {
+		dev_err(dev, "failed to allocate descriptor memory\n");
+		return -ENOMEM;
+	}
+
+	udev = create_lvs_device(intf);
+	if (!udev) {
+		dev_err(dev, "failed to create lvs device\n");
+		ret = -ENOMEM;
+		goto free_desc;
+	}
+
+	ret = usb_control_msg(udev, (PIPE_CONTROL << 30) | USB_DIR_IN,
+			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, USB_DT_DEVICE << 8,
+			0, descriptor, sizeof(*descriptor),
+			USB_CTRL_GET_TIMEOUT);
+	if (ret < 0)
+		dev_err(dev, "can't read device descriptor %d\n", ret);
+
+	destroy_lvs_device(udev);
+
+free_desc:
+	kfree(descriptor);
+
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+static DEVICE_ATTR_WO(get_dev_desc);
+
+static struct attribute *lvs_attributes[] = {
+	&dev_attr_get_dev_desc.attr,
+	&dev_attr_u1_timeout.attr,
+	&dev_attr_u2_timeout.attr,
+	&dev_attr_hot_reset.attr,
+	&dev_attr_u3_entry.attr,
+	&dev_attr_u3_exit.attr,
+	NULL
+};
+
+static const struct attribute_group lvs_attr_group = {
+	.attrs = lvs_attributes,
+};
+
+static void lvs_rh_work(struct work_struct *work)
+{
+	struct lvs_rh *lvs = container_of(work, struct lvs_rh, rh_work);
+	struct usb_interface *intf = lvs->intf;
+	struct usb_device *hdev = interface_to_usbdev(intf);
+	struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
+	struct usb_hub_descriptor *descriptor = &lvs->descriptor;
+	struct usb_port_status *port_status = &lvs->port_status;
+	int i, ret = 0;
+	u16 portchange;
+
+	/* Examine each root port */
+	for (i = 1; i <= descriptor->bNbrPorts; i++) {
+		ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
+			USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, i,
+			port_status, sizeof(*port_status), 1000);
+		if (ret < 4)
+			continue;
+
+		portchange = le16_to_cpu(port_status->wPortChange);
+
+		if (portchange & USB_PORT_STAT_C_LINK_STATE)
+			lvs_rh_clear_port_feature(hdev, i,
+					USB_PORT_FEAT_C_PORT_LINK_STATE);
+		if (portchange & USB_PORT_STAT_C_ENABLE)
+			lvs_rh_clear_port_feature(hdev, i,
+					USB_PORT_FEAT_C_ENABLE);
+		if (portchange & USB_PORT_STAT_C_RESET)
+			lvs_rh_clear_port_feature(hdev, i,
+					USB_PORT_FEAT_C_RESET);
+		if (portchange & USB_PORT_STAT_C_BH_RESET)
+			lvs_rh_clear_port_feature(hdev, i,
+					USB_PORT_FEAT_C_BH_PORT_RESET);
+		if (portchange & USB_PORT_STAT_C_CONNECTION) {
+			lvs_rh_clear_port_feature(hdev, i,
+					USB_PORT_FEAT_C_CONNECTION);
+
+			if (le16_to_cpu(port_status->wPortStatus) &
+					USB_PORT_STAT_CONNECTION) {
+				lvs->present = true;
+				lvs->portnum = i;
+				if (hcd->phy)
+					usb_phy_notify_connect(hcd->phy,
+							USB_SPEED_SUPER);
+			} else {
+				lvs->present = false;
+				if (hcd->phy)
+					usb_phy_notify_disconnect(hcd->phy,
+							USB_SPEED_SUPER);
+			}
+			break;
+		}
+	}
+
+	ret = usb_submit_urb(lvs->urb, GFP_KERNEL);
+	if (ret != 0 && ret != -ENODEV && ret != -EPERM)
+		dev_err(&intf->dev, "urb resubmit error %d\n", ret);
+}
+
+static void lvs_rh_irq(struct urb *urb)
+{
+	struct lvs_rh *lvs = urb->context;
+
+	queue_work(lvs->rh_queue, &lvs->rh_work);
+}
+
+static int lvs_rh_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	struct usb_device *hdev;
+	struct usb_host_interface *desc;
+	struct usb_endpoint_descriptor *endpoint;
+	struct lvs_rh *lvs;
+	unsigned int pipe;
+	int ret, maxp;
+
+	hdev = interface_to_usbdev(intf);
+	desc = intf->cur_altsetting;
+	endpoint = &desc->endpoint[0].desc;
+
+	/* valid only for SS root hub */
+	if (hdev->descriptor.bDeviceProtocol != USB_HUB_PR_SS || hdev->parent) {
+		dev_err(&intf->dev, "Bind LVS driver with SS root Hub only\n");
+		return -EINVAL;
+	}
+
+	lvs = devm_kzalloc(&intf->dev, sizeof(*lvs), GFP_KERNEL);
+	if (!lvs)
+		return -ENOMEM;
+
+	lvs->intf = intf;
+	usb_set_intfdata(intf, lvs);
+
+	/* how many number of ports this root hub has */
+	ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
+			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
+			USB_DT_SS_HUB << 8, 0, &lvs->descriptor,
+			USB_DT_SS_HUB_SIZE, USB_CTRL_GET_TIMEOUT);
+	if (ret < (USB_DT_HUB_NONVAR_SIZE + 2)) {
+		dev_err(&hdev->dev, "wrong root hub descriptor read %d\n", ret);
+		return ret;
+	}
+
+	/* submit urb to poll interrupt endpoint */
+	lvs->urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!lvs->urb) {
+		dev_err(&intf->dev, "couldn't allocate lvs urb\n");
+		return -ENOMEM;
+	}
+
+	lvs->rh_queue = create_singlethread_workqueue("lvs_rh_queue");
+	if (!lvs->rh_queue) {
+		dev_err(&intf->dev, "couldn't create workqueue\n");
+		ret = -ENOMEM;
+		goto free_urb;
+	}
+
+	INIT_WORK(&lvs->rh_work, lvs_rh_work);
+
+	ret = sysfs_create_group(&intf->dev.kobj, &lvs_attr_group);
+	if (ret < 0) {
+		dev_err(&intf->dev, "Failed to create sysfs node %d\n", ret);
+		goto destroy_queue;
+	}
+
+	pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress);
+	maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe));
+	usb_fill_int_urb(lvs->urb, hdev, pipe, &lvs->buffer[0], maxp,
+			lvs_rh_irq, lvs, endpoint->bInterval);
+
+	ret = usb_submit_urb(lvs->urb, GFP_KERNEL);
+	if (ret < 0) {
+		dev_err(&intf->dev, "couldn't submit lvs urb %d\n", ret);
+		goto sysfs_remove;
+	}
+
+	return ret;
+
+sysfs_remove:
+	sysfs_remove_group(&intf->dev.kobj, &lvs_attr_group);
+destroy_queue:
+	destroy_workqueue(lvs->rh_queue);
+free_urb:
+	usb_free_urb(lvs->urb);
+	return ret;
+}
+
+static void lvs_rh_disconnect(struct usb_interface *intf)
+{
+	struct lvs_rh *lvs = usb_get_intfdata(intf);
+
+	sysfs_remove_group(&intf->dev.kobj, &lvs_attr_group);
+	destroy_workqueue(lvs->rh_queue);
+	usb_free_urb(lvs->urb);
+}
+
+static struct usb_driver lvs_driver = {
+	.name =		"lvs",
+	.probe =	lvs_rh_probe,
+	.disconnect =	lvs_rh_disconnect,
+};
+
+module_usb_driver(lvs_driver);
+
+MODULE_DESCRIPTION("Link Layer Validation System Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index f43c61989cef..47cb143716a1 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -149,8 +149,6 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode)
 
 	case USB3503_MODE_STANDBY:
 		usb3503_reset(hub, 0);
-
-		hub->mode = mode;
 		dev_info(dev, "switched to STANDBY mode\n");
 		break;
 
@@ -192,7 +190,8 @@ static int usb3503_probe(struct usb3503 *hub)
 
 		clk = devm_clk_get(dev, "refclk");
 		if (IS_ERR(clk) && PTR_ERR(clk) != -ENOENT) {
-			dev_err(dev, "unable to request refclk (%d)\n", err);
+			dev_err(dev, "unable to request refclk (%ld)\n",
+					PTR_ERR(clk));
 			return PTR_ERR(clk);
 		}
 
@@ -346,6 +345,37 @@ static int usb3503_platform_probe(struct platform_device *pdev)
 	return usb3503_probe(hub);
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int usb3503_i2c_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct usb3503 *hub = i2c_get_clientdata(client);
+
+	usb3503_switch_mode(hub, USB3503_MODE_STANDBY);
+
+	if (hub->clk)
+		clk_disable_unprepare(hub->clk);
+
+	return 0;
+}
+
+static int usb3503_i2c_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct usb3503 *hub = i2c_get_clientdata(client);
+
+	if (hub->clk)
+		clk_prepare_enable(hub->clk);
+
+	usb3503_switch_mode(hub, hub->mode);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(usb3503_i2c_pm_ops, usb3503_i2c_suspend,
+		usb3503_i2c_resume);
+
 static const struct i2c_device_id usb3503_id[] = {
 	{ USB3503_I2C_NAME, 0 },
 	{ }
@@ -364,6 +394,7 @@ MODULE_DEVICE_TABLE(of, usb3503_of_match);
 static struct i2c_driver usb3503_i2c_driver = {
 	.driver = {
 		.name = USB3503_I2C_NAME,
+		.pm = &usb3503_i2c_pm_ops,
 		.of_match_table = of_match_ptr(usb3503_of_match),
 	},
 	.probe		= usb3503_i2c_probe,
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index d40d5f0b5528..ac4422b33dcd 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -455,7 +455,7 @@ static int bfin_probe(struct platform_device *pdev)
 
 	int				ret = -ENOMEM;
 
-	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
 		dev_err(&pdev->dev, "failed to allocate glue context\n");
 		goto err0;
@@ -464,7 +464,7 @@ static int bfin_probe(struct platform_device *pdev)
 	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 	if (!musb) {
 		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err1;
+		goto err0;
 	}
 
 	musb->dev.parent		= &pdev->dev;
@@ -478,7 +478,7 @@ static int bfin_probe(struct platform_device *pdev)
 
 	glue->phy = usb_phy_generic_register();
 	if (IS_ERR(glue->phy))
-		goto err2;
+		goto err1;
 	platform_set_drvdata(pdev, glue);
 
 	memset(musb_resources, 0x00, sizeof(*musb_resources) *
@@ -498,31 +498,28 @@ static int bfin_probe(struct platform_device *pdev)
 			ARRAY_SIZE(musb_resources));
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add resources\n");
-		goto err3;
+		goto err2;
 	}
 
 	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add platform_data\n");
-		goto err3;
+		goto err2;
 	}
 
 	ret = platform_device_add(musb);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register musb device\n");
-		goto err3;
+		goto err2;
 	}
 
 	return 0;
 
-err3:
-	usb_phy_generic_unregister(glue->phy);
-
 err2:
-	platform_device_put(musb);
+	usb_phy_generic_unregister(glue->phy);
 
 err1:
-	kfree(glue);
+	platform_device_put(musb);
 
 err0:
 	return ret;
@@ -534,7 +531,6 @@ static int bfin_remove(struct platform_device *pdev)
 
 	platform_device_unregister(glue->musb);
 	usb_phy_generic_unregister(glue->phy);
-	kfree(glue);
 
 	return 0;
 }
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index de8492b06e46..110b78415bf0 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -519,23 +519,23 @@ static int davinci_probe(struct platform_device *pdev)
 
 	int				ret = -ENOMEM;
 
-	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
 		dev_err(&pdev->dev, "failed to allocate glue context\n");
 		goto err0;
 	}
 
-	clk = clk_get(&pdev->dev, "usb");
+	clk = devm_clk_get(&pdev->dev, "usb");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clock\n");
 		ret = PTR_ERR(clk);
-		goto err3;
+		goto err0;
 	}
 
 	ret = clk_enable(clk);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to enable clock\n");
-		goto err4;
+		goto err0;
 	}
 
 	glue->dev			= &pdev->dev;
@@ -579,20 +579,14 @@ static int davinci_probe(struct platform_device *pdev)
 	if (IS_ERR(musb)) {
 		ret = PTR_ERR(musb);
 		dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
-		goto err5;
+		goto err1;
 	}
 
 	return 0;
 
-err5:
+err1:
 	clk_disable(clk);
 
-err4:
-	clk_put(clk);
-
-err3:
-	kfree(glue);
-
 err0:
 	return ret;
 }
@@ -604,8 +598,6 @@ static int davinci_remove(struct platform_device *pdev)
 	platform_device_unregister(glue->musb);
 	usb_phy_generic_unregister();
 	clk_disable(glue->clk);
-	clk_put(glue->clk);
-	kfree(glue);
 
 	return 0;
 }
diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c
index 5f30537f1927..d1187290d4e3 100644
--- a/drivers/usb/musb/jz4740.c
+++ b/drivers/usb/musb/jz4740.c
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/usb/usb_phy_generic.h>
 
 #include "musb_core.h"
 
@@ -80,6 +81,7 @@ static struct musb_hdrc_platform_data jz4740_musb_platform_data = {
 
 static int jz4740_musb_init(struct musb *musb)
 {
+	usb_phy_generic_register();
 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (!musb->xceiv) {
 		pr_err("HS UDC: no transceiver configured\n");
@@ -182,6 +184,7 @@ static int jz4740_remove(struct platform_device *pdev)
 	struct jz4740_glue	*glue = platform_get_drvdata(pdev);
 
 	platform_device_unregister(glue->musb);
+	usb_phy_generic_unregister(pdev);
 	clk_disable_unprepare(glue->clk);
 
 	return 0;
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index eff3c5cf84f4..b841ee0bff06 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -850,7 +850,8 @@ b_host:
 
 	/* handle babble condition */
 	if (int_usb & MUSB_INTR_BABBLE && is_host_active(musb))
-		schedule_work(&musb->recover_work);
+		schedule_delayed_work(&musb->recover_work,
+				      msecs_to_jiffies(100));
 
 #if 0
 /* REVISIT ... this would be for multiplexing periodic endpoints, or
@@ -1517,7 +1518,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
 	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 
 	dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n",
-		(devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
+		is_host_active(musb) ? "host" : "peripheral",
 		musb->int_usb, musb->int_tx, musb->int_rx);
 
 	/* the core can interrupt us for multiple reasons; docs have
@@ -1531,7 +1532,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
 
 	/* handle endpoint 0 first */
 	if (musb->int_tx & 1) {
-		if (devctl & MUSB_DEVCTL_HM)
+		if (is_host_active(musb))
 			retval |= musb_h_ep0_irq(musb);
 		else
 			retval |= musb_g_ep0_irq(musb);
@@ -1545,7 +1546,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
 			/* musb_ep_select(musb->mregs, ep_num); */
 			/* REVISIT just retval = ep->rx_irq(...) */
 			retval = IRQ_HANDLED;
-			if (devctl & MUSB_DEVCTL_HM)
+			if (is_host_active(musb))
 				musb_host_rx(musb, ep_num);
 			else
 				musb_g_rx(musb, ep_num);
@@ -1563,7 +1564,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
 			/* musb_ep_select(musb->mregs, ep_num); */
 			/* REVISIT just retval |= ep->tx_irq(...) */
 			retval = IRQ_HANDLED;
-			if (devctl & MUSB_DEVCTL_HM)
+			if (is_host_active(musb))
 				musb_host_tx(musb, ep_num);
 			else
 				musb_g_tx(musb, ep_num);
@@ -1585,15 +1586,13 @@ MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
 
 void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit)
 {
-	u8	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
-
 	/* called with controller lock already held */
 
 	if (!epnum) {
 #ifndef CONFIG_USB_TUSB_OMAP_DMA
 		if (!is_cppi_enabled()) {
 			/* endpoint 0 */
-			if (devctl & MUSB_DEVCTL_HM)
+			if (is_host_active(musb))
 				musb_h_ep0_irq(musb);
 			else
 				musb_g_ep0_irq(musb);
@@ -1602,13 +1601,13 @@ void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit)
 	} else {
 		/* endpoints 1..15 */
 		if (transmit) {
-			if (devctl & MUSB_DEVCTL_HM)
+			if (is_host_active(musb))
 				musb_host_tx(musb, epnum);
 			else
 				musb_g_tx(musb, epnum);
 		} else {
 			/* receive */
-			if (devctl & MUSB_DEVCTL_HM)
+			if (is_host_active(musb))
 				musb_host_rx(musb, epnum);
 			else
 				musb_g_rx(musb, epnum);
@@ -1753,20 +1752,22 @@ static void musb_irq_work(struct work_struct *data)
 /* Recover from babble interrupt conditions */
 static void musb_recover_work(struct work_struct *data)
 {
-	struct musb *musb = container_of(data, struct musb, recover_work);
-	int status;
+	struct musb *musb = container_of(data, struct musb, recover_work.work);
+	int status, ret;
 
-	musb_platform_reset(musb);
+	ret  = musb_platform_reset(musb);
+	if (ret)
+		return;
 
 	usb_phy_vbus_off(musb->xceiv);
-	udelay(100);
+	usleep_range(100, 200);
 
 	usb_phy_vbus_on(musb->xceiv);
-	udelay(100);
+	usleep_range(100, 200);
 
 	/*
-	 * When a babble condition occurs, the musb controller removes the
-	 * session bit and the endpoint config is lost.
+	 * When a babble condition occurs, the musb controller
+	 * removes the session bit and the endpoint config is lost.
 	 */
 	if (musb->dyn_fifo)
 		status = ep_config_from_table(musb);
@@ -1945,7 +1946,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 
 	/* Init IRQ workqueue before request_irq */
 	INIT_WORK(&musb->irq_work, musb_irq_work);
-	INIT_WORK(&musb->recover_work, musb_recover_work);
+	INIT_DELAYED_WORK(&musb->recover_work, musb_recover_work);
 	INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset);
 	INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume);
 
@@ -2041,7 +2042,7 @@ fail4:
 
 fail3:
 	cancel_work_sync(&musb->irq_work);
-	cancel_work_sync(&musb->recover_work);
+	cancel_delayed_work_sync(&musb->recover_work);
 	cancel_delayed_work_sync(&musb->finish_resume_work);
 	cancel_delayed_work_sync(&musb->deassert_reset_work);
 	if (musb->dma_controller)
@@ -2107,7 +2108,7 @@ static int musb_remove(struct platform_device *pdev)
 		dma_controller_destroy(musb->dma_controller);
 
 	cancel_work_sync(&musb->irq_work);
-	cancel_work_sync(&musb->recover_work);
+	cancel_delayed_work_sync(&musb->recover_work);
 	cancel_delayed_work_sync(&musb->finish_resume_work);
 	cancel_delayed_work_sync(&musb->deassert_reset_work);
 	musb_free(musb);
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index d155a156f240..414e57a984bb 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -192,7 +192,7 @@ struct musb_platform_ops {
 
 	int	(*set_mode)(struct musb *musb, u8 mode);
 	void	(*try_idle)(struct musb *musb, unsigned long timeout);
-	void	(*reset)(struct musb *musb);
+	int	(*reset)(struct musb *musb);
 
 	int	(*vbus_status)(struct musb *musb);
 	void	(*set_vbus)(struct musb *musb, int on);
@@ -297,7 +297,7 @@ struct musb {
 
 	irqreturn_t		(*isr)(int, void *);
 	struct work_struct	irq_work;
-	struct work_struct	recover_work;
+	struct delayed_work	recover_work;
 	struct delayed_work	deassert_reset_work;
 	struct delayed_work	finish_resume_work;
 	u16			hwvers;
@@ -555,10 +555,12 @@ static inline void musb_platform_try_idle(struct musb *musb,
 		musb->ops->try_idle(musb, timeout);
 }
 
-static inline void musb_platform_reset(struct musb *musb)
+static inline int  musb_platform_reset(struct musb *musb)
 {
-	if (musb->ops->reset)
-		musb->ops->reset(musb);
+	if (!musb->ops->reset)
+		return -EINVAL;
+
+	return musb->ops->reset(musb);
 }
 
 static inline int musb_platform_get_vbus_status(struct musb *musb)
diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c
index 5341bb223b7c..47ae6455d073 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -39,7 +39,6 @@ struct cppi41_dma_channel {
 	u32 transferred;
 	u32 packet_sz;
 	struct list_head tx_check;
-	struct work_struct dma_completion;
 };
 
 #define MUSB_DMA_NUM_CHANNELS 15
@@ -74,15 +73,18 @@ static void save_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
 
 static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
 {
+	struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+	struct musb *musb = hw_ep->musb;
 	u16 csr;
 	u8 toggle;
 
 	if (cppi41_channel->is_tx)
 		return;
-	if (!is_host_active(cppi41_channel->controller->musb))
+	if (!is_host_active(musb))
 		return;
 
-	csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR);
+	musb_ep_select(musb->mregs, hw_ep->epnum);
+	csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
 	toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;
 
 	/*
@@ -107,24 +109,13 @@ static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep)
 	void __iomem	*epio = musb->endpoints[epnum].regs;
 	u16		csr;
 
+	musb_ep_select(musb->mregs, hw_ep->epnum);
 	csr = musb_readw(epio, MUSB_TXCSR);
 	if (csr & MUSB_TXCSR_TXPKTRDY)
 		return false;
 	return true;
 }
 
-static bool is_isoc(struct musb_hw_ep *hw_ep, bool in)
-{
-	if (in && hw_ep->in_qh) {
-		if (hw_ep->in_qh->type == USB_ENDPOINT_XFER_ISOC)
-			return true;
-	} else if (hw_ep->out_qh) {
-		if (hw_ep->out_qh->type == USB_ENDPOINT_XFER_ISOC)
-			return true;
-	}
-	return false;
-}
-
 static void cppi41_dma_callback(void *private_data);
 
 static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
@@ -139,6 +130,7 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
 		cppi41_channel->channel.actual_len =
 			cppi41_channel->transferred;
 		cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE;
+		cppi41_channel->channel.rx_packet_done = true;
 		musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx);
 	} else {
 		/* next iteration, reload */
@@ -172,6 +164,7 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
 		dma_async_issue_pending(dc);
 
 		if (!cppi41_channel->is_tx) {
+			musb_ep_select(musb->mregs, hw_ep->epnum);
 			csr = musb_readw(epio, MUSB_RXCSR);
 			csr |= MUSB_RXCSR_H_REQPKT;
 			musb_writew(epio, MUSB_RXCSR, csr);
@@ -179,32 +172,6 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
 	}
 }
 
-static void cppi_trans_done_work(struct work_struct *work)
-{
-	unsigned long flags;
-	struct cppi41_dma_channel *cppi41_channel =
-		container_of(work, struct cppi41_dma_channel, dma_completion);
-	struct cppi41_dma_controller *controller = cppi41_channel->controller;
-	struct musb *musb = controller->musb;
-	struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
-	bool empty;
-
-	if (!cppi41_channel->is_tx && is_isoc(hw_ep, 1)) {
-		spin_lock_irqsave(&musb->lock, flags);
-		cppi41_trans_done(cppi41_channel);
-		spin_unlock_irqrestore(&musb->lock, flags);
-	} else {
-		empty = musb_is_tx_fifo_empty(hw_ep);
-		if (empty) {
-			spin_lock_irqsave(&musb->lock, flags);
-			cppi41_trans_done(cppi41_channel);
-			spin_unlock_irqrestore(&musb->lock, flags);
-		} else {
-			schedule_work(&cppi41_channel->dma_completion);
-		}
-	}
-}
-
 static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
 {
 	struct cppi41_dma_controller *controller;
@@ -233,7 +200,7 @@ static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
 	if (!list_empty(&controller->early_tx_list)) {
 		ret = HRTIMER_RESTART;
 		hrtimer_forward_now(&controller->early_tx,
-				ktime_set(0, 150 * NSEC_PER_USEC));
+				ktime_set(0, 50 * NSEC_PER_USEC));
 	}
 
 	spin_unlock_irqrestore(&musb->lock, flags);
@@ -268,14 +235,6 @@ static void cppi41_dma_callback(void *private_data)
 			transferred < cppi41_channel->packet_sz)
 		cppi41_channel->prog_len = 0;
 
-	if (!cppi41_channel->is_tx) {
-		if (is_isoc(hw_ep, 1))
-			schedule_work(&cppi41_channel->dma_completion);
-		else
-			cppi41_trans_done(cppi41_channel);
-		goto out;
-	}
-
 	empty = musb_is_tx_fifo_empty(hw_ep);
 	if (empty) {
 		cppi41_trans_done(cppi41_channel);
@@ -312,15 +271,13 @@ static void cppi41_dma_callback(void *private_data)
 				goto out;
 			}
 		}
-		if (is_isoc(hw_ep, 0)) {
-			schedule_work(&cppi41_channel->dma_completion);
-			goto out;
-		}
 		list_add_tail(&cppi41_channel->tx_check,
 				&controller->early_tx_list);
 		if (!hrtimer_is_queued(&controller->early_tx)) {
+			unsigned long usecs = cppi41_channel->total_len / 10;
+
 			hrtimer_start_range_ns(&controller->early_tx,
-				ktime_set(0, 140 * NSEC_PER_USEC),
+				ktime_set(0, usecs * NSEC_PER_USEC),
 				40 * NSEC_PER_USEC,
 				HRTIMER_MODE_REL);
 		}
@@ -450,6 +407,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel,
 	dma_desc->callback = cppi41_dma_callback;
 	dma_desc->callback_param = channel;
 	cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
+	cppi41_channel->channel.rx_packet_done = false;
 
 	save_rx_toggle(cppi41_channel);
 	dma_async_issue_pending(dc);
@@ -672,8 +630,6 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
 		cppi41_channel->port_num = port;
 		cppi41_channel->is_tx = is_tx;
 		INIT_LIST_HEAD(&cppi41_channel->tx_check);
-		INIT_WORK(&cppi41_channel->dma_completion,
-			  cppi_trans_done_work);
 
 		musb_dma = &cppi41_channel->channel;
 		musb_dma->private_data = cppi41_channel;
diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 1345a4ff041a..1d44faa86252 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -129,6 +129,7 @@ struct dma_channel {
 	size_t			actual_len;
 	enum dma_channel_status	status;
 	bool			desired_mode;
+	bool			rx_packet_done;
 };
 
 /*
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 09529f94e72d..c791ba5da91a 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -56,16 +56,24 @@ static const struct of_device_id musb_dsps_of_match[];
  * dependent on musb core layer symbols.
  */
 static inline u8 dsps_readb(const void __iomem *addr, unsigned offset)
-	{ return __raw_readb(addr + offset); }
+{
+	return __raw_readb(addr + offset);
+}
 
 static inline u32 dsps_readl(const void __iomem *addr, unsigned offset)
-	{ return __raw_readl(addr + offset); }
+{
+	return __raw_readl(addr + offset);
+}
 
 static inline void dsps_writeb(void __iomem *addr, unsigned offset, u8 data)
-	{ __raw_writeb(data, addr + offset); }
+{
+	__raw_writeb(data, addr + offset);
+}
 
 static inline void dsps_writel(void __iomem *addr, unsigned offset, u32 data)
-	{ __raw_writel(data, addr + offset); }
+{
+	__raw_writel(data, addr + offset);
+}
 
 /**
  * DSPS musb wrapper register offset.
@@ -136,6 +144,7 @@ struct dsps_glue {
 	const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
 	struct timer_list timer;	/* otg_workaround timer */
 	unsigned long last_timer;    /* last timer data for each instance */
+	bool sw_babble_enabled;
 
 	struct dsps_context context;
 	struct debugfs_regset32 regset;
@@ -469,6 +478,19 @@ static int dsps_musb_init(struct musb *musb)
 	val &= ~(1 << wrp->otg_disable);
 	dsps_writel(musb->ctrl_base, wrp->phy_utmi, val);
 
+	/*
+	 *  Check whether the dsps version has babble control enabled.
+	 * In latest silicon revision the babble control logic is enabled.
+	 * If MUSB_BABBLE_CTL returns 0x4 then we have the babble control
+	 * logic enabled.
+	 */
+	val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL);
+	if (val == MUSB_BABBLE_RCV_DISABLE) {
+		glue->sw_babble_enabled = true;
+		val |= MUSB_BABBLE_SW_SESSION_CTRL;
+		dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val);
+	}
+
 	ret = dsps_musb_dbg_init(musb, glue);
 	if (ret)
 		return ret;
@@ -535,14 +557,82 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode)
 	return 0;
 }
 
-static void dsps_musb_reset(struct musb *musb)
+static bool  sw_babble_control(struct musb *musb)
+{
+	u8 babble_ctl;
+	bool session_restart =  false;
+
+	babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL);
+	dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n",
+		babble_ctl);
+	/*
+	 * check line monitor flag to check whether babble is
+	 * due to noise
+	 */
+	dev_dbg(musb->controller, "STUCK_J is %s\n",
+		babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset");
+
+	if (babble_ctl & MUSB_BABBLE_STUCK_J) {
+		int timeout = 10;
+
+		/*
+		 * babble is due to noise, then set transmit idle (d7 bit)
+		 * to resume normal operation
+		 */
+		babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL);
+		babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE;
+		dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl);
+
+		/* wait till line monitor flag cleared */
+		dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n");
+		do {
+			babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL);
+			udelay(1);
+		} while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--);
+
+		/* check whether stuck_at_j bit cleared */
+		if (babble_ctl & MUSB_BABBLE_STUCK_J) {
+			/*
+			 * real babble condition has occurred
+			 * restart the controller to start the
+			 * session again
+			 */
+			dev_dbg(musb->controller, "J not cleared, misc (%x)\n",
+				babble_ctl);
+			session_restart = true;
+		}
+	} else {
+		session_restart = true;
+	}
+
+	return session_restart;
+}
+
+static int dsps_musb_reset(struct musb *musb)
 {
 	struct device *dev = musb->controller;
 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
 	const struct dsps_musb_wrapper *wrp = glue->wrp;
+	int session_restart = 0;
+
+	if (glue->sw_babble_enabled)
+		session_restart = sw_babble_control(musb);
+	/*
+	 * In case of new silicon version babble condition can be recovered
+	 * without resetting the MUSB. But for older silicon versions, MUSB
+	 * reset is needed
+	 */
+	if (session_restart || !glue->sw_babble_enabled) {
+		dev_info(musb->controller, "Restarting MUSB to recover from Babble\n");
+		dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset));
+		usleep_range(100, 200);
+		usb_phy_shutdown(musb->xceiv);
+		usleep_range(100, 200);
+		usb_phy_init(musb->xceiv);
+		session_restart = 1;
+	}
 
-	dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset));
-	udelay(100);
+	return !session_restart;
 }
 
 static struct musb_platform_ops dsps_ops = {
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index eb06291a40c8..855793d701bb 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -120,7 +120,7 @@ static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
 		if (csr != lastcsr)
 			dev_dbg(musb->controller, "Host TX FIFONOTEMPTY csr: %02x\n", csr);
 		lastcsr = csr;
-		csr |= MUSB_TXCSR_FLUSHFIFO;
+		csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_TXPKTRDY;
 		musb_writew(epio, MUSB_TXCSR, csr);
 		csr = musb_readw(epio, MUSB_TXCSR);
 		if (WARN(retries-- < 1,
@@ -1295,7 +1295,7 @@ done:
 	if (status) {
 		if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
 			dma->status = MUSB_DMA_STATUS_CORE_ABORT;
-			(void) musb->dma_controller->channel_abort(dma);
+			musb->dma_controller->channel_abort(dma);
 		}
 
 		/* do the proper sequence to abort the transfer in the
@@ -1640,7 +1640,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)
 		/* clean up dma and collect transfer count */
 		if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
 			dma->status = MUSB_DMA_STATUS_CORE_ABORT;
-			(void) musb->dma_controller->channel_abort(dma);
+			musb->dma_controller->channel_abort(dma);
 			xfer_len = dma->actual_len;
 		}
 		musb_h_flush_rxfifo(hw_ep, MUSB_RXCSR_CLRDATATOG);
@@ -1671,7 +1671,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)
 		 */
 		if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
 			dma->status = MUSB_DMA_STATUS_CORE_ABORT;
-			(void) musb->dma_controller->channel_abort(dma);
+			musb->dma_controller->channel_abort(dma);
 			xfer_len = dma->actual_len;
 			done = true;
 		}
@@ -1734,10 +1734,11 @@ void musb_host_rx(struct musb *musb, u8 epnum)
 			}
 
 		} else  {
-		/* done if urb buffer is full or short packet is recd */
-		done = (urb->actual_length + xfer_len >=
-				urb->transfer_buffer_length
-			|| dma->actual_len < qh->maxpacket);
+			/* done if urb buffer is full or short packet is recd */
+			done = (urb->actual_length + xfer_len >=
+					urb->transfer_buffer_length
+				|| dma->actual_len < qh->maxpacket
+				|| dma->rx_packet_done);
 		}
 
 		/* send IN token for next packet, without AUTOREQ */
@@ -1957,7 +1958,7 @@ static int musb_schedule(
 	struct musb_qh		*qh,
 	int			is_in)
 {
-	int			idle;
+	int			idle = 0;
 	int			best_diff;
 	int			best_end, epnum;
 	struct musb_hw_ep	*hw_ep = NULL;
diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h
index 03f2655af290..b9bcda5e3945 100644
--- a/drivers/usb/musb/musb_regs.h
+++ b/drivers/usb/musb/musb_regs.h
@@ -72,6 +72,12 @@
 #define MUSB_DEVCTL_HR		0x02
 #define MUSB_DEVCTL_SESSION	0x01
 
+/* BABBLE_CTL */
+#define MUSB_BABBLE_FORCE_TXIDLE	0x80
+#define MUSB_BABBLE_SW_SESSION_CTRL	0x40
+#define MUSB_BABBLE_STUCK_J		0x20
+#define MUSB_BABBLE_RCV_DISABLE		0x04
+
 /* MUSB ULPI VBUSCONTROL */
 #define MUSB_ULPI_USE_EXTVBUS	0x01
 #define MUSB_ULPI_USE_EXTVBUSIND 0x02
@@ -246,6 +252,7 @@
  */
 
 #define MUSB_DEVCTL		0x60	/* 8 bit */
+#define MUSB_BABBLE_CTL		0x61	/* 8 bit */
 
 /* These are always controlled through the INDEX register */
 #define MUSB_TXFIFOSZ		0x62	/* 8-bit (see masks) */
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 159ef4be1ef2..7dfc6cb732c9 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -22,6 +22,7 @@
 #include <linux/usb.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/usb/usb_phy_generic.h>
@@ -1160,12 +1161,12 @@ static int tusb_probe(struct platform_device *pdev)
 	struct platform_device		*musb;
 	struct tusb6010_glue		*glue;
 	struct platform_device_info	pinfo;
-	int				ret = -ENOMEM;
+	int				ret;
 
-	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
 		dev_err(&pdev->dev, "failed to allocate glue context\n");
-		goto err0;
+		return -ENOMEM;
 	}
 
 	glue->dev			= &pdev->dev;
@@ -1204,16 +1205,10 @@ static int tusb_probe(struct platform_device *pdev)
 	if (IS_ERR(musb)) {
 		ret = PTR_ERR(musb);
 		dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
-		goto err3;
+		return ret;
 	}
 
 	return 0;
-
-err3:
-	kfree(glue);
-
-err0:
-	return ret;
 }
 
 static int tusb_remove(struct platform_device *pdev)
@@ -1222,7 +1217,6 @@ static int tusb_remove(struct platform_device *pdev)
 
 	platform_device_unregister(glue->musb);
 	usb_phy_generic_unregister(glue->phy);
-	kfree(glue);
 
 	return 0;
 }
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index f202e5088461..dc666e96f45f 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -246,7 +246,7 @@ static int ux500_probe(struct platform_device *pdev)
 		}
 	}
 
-	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
 		dev_err(&pdev->dev, "failed to allocate glue context\n");
 		goto err0;
@@ -255,20 +255,20 @@ static int ux500_probe(struct platform_device *pdev)
 	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 	if (!musb) {
 		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err1;
+		goto err0;
 	}
 
-	clk = clk_get(&pdev->dev, NULL);
+	clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clock\n");
 		ret = PTR_ERR(clk);
-		goto err3;
+		goto err1;
 	}
 
 	ret = clk_prepare_enable(clk);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to enable clock\n");
-		goto err4;
+		goto err1;
 	}
 
 	musb->dev.parent		= &pdev->dev;
@@ -301,34 +301,28 @@ static int ux500_probe(struct platform_device *pdev)
 			ARRAY_SIZE(musb_resources));
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add resources\n");
-		goto err5;
+		goto err2;
 	}
 
 	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add platform_data\n");
-		goto err5;
+		goto err2;
 	}
 
 	ret = platform_device_add(musb);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register musb device\n");
-		goto err5;
+		goto err2;
 	}
 
 	return 0;
 
-err5:
+err2:
 	clk_disable_unprepare(clk);
 
-err4:
-	clk_put(clk);
-
-err3:
-	platform_device_put(musb);
-
 err1:
-	kfree(glue);
+	platform_device_put(musb);
 
 err0:
 	return ret;
@@ -340,8 +334,6 @@ static int ux500_remove(struct platform_device *pdev)
 
 	platform_device_unregister(glue->musb);
 	clk_disable_unprepare(glue->clk);
-	clk_put(glue->clk);
-	kfree(glue);
 
 	return 0;
 }
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c
index 585e50cb1980..b70e05537180 100644
--- a/drivers/usb/phy/phy-am335x.c
+++ b/drivers/usb/phy/phy-am335x.c
@@ -122,16 +122,10 @@ static int am335x_phy_resume(struct device *dev)
 
 	return 0;
 }
-
-static const struct dev_pm_ops am335x_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(am335x_phy_suspend, am335x_phy_resume)
-};
-
-#define DEV_PM_OPS     (&am335x_pm_ops)
-#else
-#define DEV_PM_OPS     NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(am335x_pm_ops, am335x_phy_suspend, am335x_phy_resume);
+
 static const struct of_device_id am335x_phy_ids[] = {
 	{ .compatible = "ti,am335x-usb-phy" },
 	{ }
@@ -144,7 +138,7 @@ static struct platform_driver am335x_phy_driver = {
 	.driver         = {
 		.name   = "am335x-phy-driver",
 		.owner  = THIS_MODULE,
-		.pm = DEV_PM_OPS,
+		.pm = &am335x_pm_ops,
 		.of_match_table = am335x_phy_ids,
 	},
 };
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index 69462e09d014..ea9e705555df 100644
--- a/drivers/usb/phy/phy-gpio-vbus-usb.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -253,11 +253,13 @@ static int gpio_vbus_probe(struct platform_device *pdev)
 		return -EINVAL;
 	gpio = pdata->gpio_vbus;
 
-	gpio_vbus = kzalloc(sizeof(struct gpio_vbus_data), GFP_KERNEL);
+	gpio_vbus = devm_kzalloc(&pdev->dev, sizeof(struct gpio_vbus_data),
+				 GFP_KERNEL);
 	if (!gpio_vbus)
 		return -ENOMEM;
 
-	gpio_vbus->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
+	gpio_vbus->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
+					  GFP_KERNEL);
 	if (!gpio_vbus->phy.otg) {
 		kfree(gpio_vbus);
 		return -ENOMEM;
@@ -274,11 +276,11 @@ static int gpio_vbus_probe(struct platform_device *pdev)
 	gpio_vbus->phy.otg->phy = &gpio_vbus->phy;
 	gpio_vbus->phy.otg->set_peripheral = gpio_vbus_set_peripheral;
 
-	err = gpio_request(gpio, "vbus_detect");
+	err = devm_gpio_request(&pdev->dev, gpio, "vbus_detect");
 	if (err) {
 		dev_err(&pdev->dev, "can't request vbus gpio %d, err: %d\n",
 			gpio, err);
-		goto err_gpio;
+		return err;
 	}
 	gpio_direction_input(gpio);
 
@@ -296,27 +298,27 @@ static int gpio_vbus_probe(struct platform_device *pdev)
 	/* if data line pullup is in use, initialize it to "not pulling up" */
 	gpio = pdata->gpio_pullup;
 	if (gpio_is_valid(gpio)) {
-		err = gpio_request(gpio, "udc_pullup");
+		err = devm_gpio_request(&pdev->dev, gpio, "udc_pullup");
 		if (err) {
 			dev_err(&pdev->dev,
 				"can't request pullup gpio %d, err: %d\n",
 				gpio, err);
-			gpio_free(pdata->gpio_vbus);
-			goto err_gpio;
+			return err;
 		}
 		gpio_direction_output(gpio, pdata->gpio_pullup_inverted);
 	}
 
-	err = request_irq(irq, gpio_vbus_irq, irqflags, "vbus_detect", pdev);
+	err = devm_request_irq(&pdev->dev, irq, gpio_vbus_irq, irqflags,
+			       "vbus_detect", pdev);
 	if (err) {
 		dev_err(&pdev->dev, "can't request irq %i, err: %d\n",
 			irq, err);
-		goto err_irq;
+		return err;
 	}
 
 	INIT_DELAYED_WORK(&gpio_vbus->work, gpio_vbus_work);
 
-	gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw");
+	gpio_vbus->vbus_draw = devm_regulator_get(&pdev->dev, "vbus_draw");
 	if (IS_ERR(gpio_vbus->vbus_draw)) {
 		dev_dbg(&pdev->dev, "can't get vbus_draw regulator, err: %ld\n",
 			PTR_ERR(gpio_vbus->vbus_draw));
@@ -328,44 +330,23 @@ static int gpio_vbus_probe(struct platform_device *pdev)
 	if (err) {
 		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
 			err);
-		goto err_otg;
+		return err;
 	}
 
 	device_init_wakeup(&pdev->dev, pdata->wakeup);
 
 	return 0;
-err_otg:
-	regulator_put(gpio_vbus->vbus_draw);
-	free_irq(irq, pdev);
-err_irq:
-	if (gpio_is_valid(pdata->gpio_pullup))
-		gpio_free(pdata->gpio_pullup);
-	gpio_free(pdata->gpio_vbus);
-err_gpio:
-	kfree(gpio_vbus->phy.otg);
-	kfree(gpio_vbus);
-	return err;
 }
 
 static int gpio_vbus_remove(struct platform_device *pdev)
 {
 	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
-	struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev);
-	int gpio = pdata->gpio_vbus;
 
 	device_init_wakeup(&pdev->dev, 0);
 	cancel_delayed_work_sync(&gpio_vbus->work);
-	regulator_put(gpio_vbus->vbus_draw);
 
 	usb_remove_phy(&gpio_vbus->phy);
 
-	free_irq(gpio_vbus->irq, pdev);
-	if (gpio_is_valid(pdata->gpio_pullup))
-		gpio_free(pdata->gpio_pullup);
-	gpio_free(gpio);
-	kfree(gpio_vbus->phy.otg);
-	kfree(gpio_vbus);
-
 	return 0;
 }
 
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index c929370cdaa6..e4108eec5ef4 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -279,11 +279,11 @@ static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
 
 static int msm_otg_phy_clk_reset(struct msm_otg *motg)
 {
-	int ret;
+	int ret = 0;
 
-	if (motg->pdata->phy_clk_reset)
+	if (motg->pdata->phy_clk_reset && motg->phy_reset_clk)
 		ret = motg->pdata->phy_clk_reset(motg->phy_reset_clk);
-	else
+	else if (motg->phy_rst)
 		ret = reset_control_reset(motg->phy_rst);
 
 	if (ret)
@@ -1429,7 +1429,7 @@ static void msm_otg_debugfs_cleanup(void)
 	debugfs_remove(msm_otg_dbg_root);
 }
 
-static struct of_device_id msm_otg_dt_match[] = {
+static const struct of_device_id msm_otg_dt_match[] = {
 	{
 		.compatible = "qcom,usb-otg-ci",
 		.data = (void *) CI_45NM_INTEGRATED_PHY
@@ -1466,7 +1466,7 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
 
 	motg->phy_rst = devm_reset_control_get(&pdev->dev, "phy");
 	if (IS_ERR(motg->phy_rst))
-		return PTR_ERR(motg->phy_rst);
+		motg->phy_rst = NULL;
 
 	pdata->mode = of_usb_get_dr_mode(node);
 	if (pdata->mode == USB_DR_MODE_UNKNOWN)
@@ -1558,7 +1558,7 @@ static int msm_otg_probe(struct platform_device *pdev)
 					   np ? "phy" : "usb_phy_clk");
 	if (IS_ERR(motg->phy_reset_clk)) {
 		dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
-		return PTR_ERR(motg->phy_reset_clk);
+		motg->phy_reset_clk = NULL;
 	}
 
 	motg->clk = devm_clk_get(&pdev->dev, np ? "core" : "usb_hs_clk");
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index bbe4f8e6e8d7..13b4fa287da8 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -33,7 +33,6 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <linux/usb/of.h>
-#include <asm/mach-types.h>
 #include <linux/usb/ehci_def.h>
 #include <linux/usb/tegra_usb_phy.h>
 #include <linux/regulator/consumer.h>
@@ -686,10 +685,8 @@ static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
 	return gpio_direction_output(phy->reset_gpio, 0);
 }
 
-static void tegra_usb_phy_close(struct usb_phy *x)
+static void tegra_usb_phy_close(struct tegra_usb_phy *phy)
 {
-	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
-
 	if (!IS_ERR(phy->vbus))
 		regulator_disable(phy->vbus);
 
@@ -965,7 +962,7 @@ static const struct tegra_phy_soc_config tegra30_soc_config = {
 	.requires_extra_tuning_parameters = true,
 };
 
-static struct of_device_id tegra_usb_phy_id_table[] = {
+static const struct of_device_id tegra_usb_phy_id_table[] = {
 	{ .compatible = "nvidia,tegra30-usb-phy", .data = &tegra30_soc_config },
 	{ .compatible = "nvidia,tegra20-usb-phy", .data = &tegra20_soc_config },
 	{ },
@@ -1061,14 +1058,13 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
 	if (err < 0)
 		return err;
 
-	tegra_phy->u_phy.shutdown = tegra_usb_phy_close;
 	tegra_phy->u_phy.set_suspend = tegra_usb_phy_suspend;
 
 	platform_set_drvdata(pdev, tegra_phy);
 
 	err = usb_add_phy_dev(&tegra_phy->u_phy);
 	if (err < 0) {
-		tegra_usb_phy_close(&tegra_phy->u_phy);
+		tegra_usb_phy_close(tegra_phy);
 		return err;
 	}
 
@@ -1080,6 +1076,7 @@ static int tegra_usb_phy_remove(struct platform_device *pdev)
 	struct tegra_usb_phy *tegra_phy = platform_get_drvdata(pdev);
 
 	usb_remove_phy(&tegra_phy->u_phy);
+	tegra_usb_phy_close(tegra_phy);
 
 	return 0;
 }
diff --git a/drivers/usb/renesas_usbhs/Makefile b/drivers/usb/renesas_usbhs/Makefile
index bc8aef4311a1..9e47f477b6d2 100644
--- a/drivers/usb/renesas_usbhs/Makefile
+++ b/drivers/usb/renesas_usbhs/Makefile
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_USB_RENESAS_USBHS)	+= renesas_usbhs.o
 
-renesas_usbhs-y			:= common.o mod.o pipe.o fifo.o
+renesas_usbhs-y			:= common.o mod.o pipe.o fifo.o rcar2.o
 
 ifneq ($(CONFIG_USB_RENESAS_USBHS_HCD),)
 	renesas_usbhs-y		+= mod_host.o
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index 17267b0a2e95..1b9bf8d83235 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -15,12 +15,14 @@
  *
  */
 #include <linux/err.h>
+#include <linux/gpio.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/sysfs.h>
 #include "common.h"
+#include "rcar2.h"
 
 /*
  *		image of renesas_usbhs
@@ -284,6 +286,8 @@ static void usbhsc_set_buswait(struct usbhs_priv *priv)
 /*
  *		platform default param
  */
+
+/* commonly used on old SH-Mobile SoCs */
 static u32 usbhsc_default_pipe_type[] = {
 		USB_ENDPOINT_XFER_CONTROL,
 		USB_ENDPOINT_XFER_ISOC,
@@ -297,6 +301,26 @@ static u32 usbhsc_default_pipe_type[] = {
 		USB_ENDPOINT_XFER_INT,
 };
 
+/* commonly used on newer SH-Mobile and R-Car SoCs */
+static u32 usbhsc_new_pipe_type[] = {
+		USB_ENDPOINT_XFER_CONTROL,
+		USB_ENDPOINT_XFER_ISOC,
+		USB_ENDPOINT_XFER_ISOC,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_INT,
+		USB_ENDPOINT_XFER_INT,
+		USB_ENDPOINT_XFER_INT,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+};
+
 /*
  *		power control
  */
@@ -423,8 +447,7 @@ static int usbhs_probe(struct platform_device *pdev)
 	int ret;
 
 	/* check platform information */
-	if (!info ||
-	    !info->platform_callback.get_id) {
+	if (!info) {
 		dev_err(&pdev->dev, "no platform information\n");
 		return -EINVAL;
 	}
@@ -451,13 +474,32 @@ static int usbhs_probe(struct platform_device *pdev)
 	/*
 	 * care platform info
 	 */
-	memcpy(&priv->pfunc,
-	       &info->platform_callback,
-	       sizeof(struct renesas_usbhs_platform_callback));
+
 	memcpy(&priv->dparam,
 	       &info->driver_param,
 	       sizeof(struct renesas_usbhs_driver_param));
 
+	switch (priv->dparam.type) {
+	case USBHS_TYPE_R8A7790:
+	case USBHS_TYPE_R8A7791:
+		priv->pfunc = usbhs_rcar2_ops;
+		if (!priv->dparam.pipe_type) {
+			priv->dparam.pipe_type = usbhsc_new_pipe_type;
+			priv->dparam.pipe_size =
+				ARRAY_SIZE(usbhsc_new_pipe_type);
+		}
+		break;
+	default:
+		if (!info->platform_callback.get_id) {
+			dev_err(&pdev->dev, "no platform callbacks");
+			return -EINVAL;
+		}
+		memcpy(&priv->pfunc,
+		       &info->platform_callback,
+		       sizeof(struct renesas_usbhs_platform_callback));
+		break;
+	}
+
 	/* set driver callback functions for platform */
 	dfunc			= &info->driver_callback;
 	dfunc->notify_hotplug	= usbhsc_drvcllbck_notify_hotplug;
@@ -507,6 +549,20 @@ static int usbhs_probe(struct platform_device *pdev)
 	 */
 	usbhs_sys_clock_ctrl(priv, 0);
 
+	/* check GPIO determining if USB function should be enabled */
+	if (priv->dparam.enable_gpio) {
+		gpio_request_one(priv->dparam.enable_gpio, GPIOF_IN, NULL);
+		ret = !gpio_get_value(priv->dparam.enable_gpio);
+		gpio_free(priv->dparam.enable_gpio);
+		if (ret) {
+			dev_warn(&pdev->dev,
+				 "USB function not selected (GPIO %d)\n",
+				 priv->dparam.enable_gpio);
+			ret = -ENOTSUPP;
+			goto probe_end_mod_exit;
+		}
+	}
+
 	/*
 	 * platform call
 	 *
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h
index c69dd2fba360..a7996da6a1bd 100644
--- a/drivers/usb/renesas_usbhs/common.h
+++ b/drivers/usb/renesas_usbhs/common.h
@@ -268,6 +268,8 @@ struct usbhs_priv {
 	 * fifo control
 	 */
 	struct usbhs_fifo_info fifo_info;
+
+	struct usb_phy *phy;
 };
 
 /*
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 458f3766bef1..04e6505777d0 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -600,8 +600,10 @@ static int usbhsg_ep_enable(struct usb_ep *ep,
 static int usbhsg_ep_disable(struct usb_ep *ep)
 {
 	struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
+	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
 
 	usbhsg_pipe_disable(uep);
+	usbhs_pipe_free(pipe);
 
 	uep->pipe->mod_private	= NULL;
 	uep->pipe		= NULL;
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c
index 7926e1c700f1..75fbcf6b102e 100644
--- a/drivers/usb/renesas_usbhs/pipe.c
+++ b/drivers/usb/renesas_usbhs/pipe.c
@@ -640,6 +640,11 @@ static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type)
 	return pipe;
 }
 
+static void usbhsp_put_pipe(struct usbhs_pipe *pipe)
+{
+	usbhsp_flags_init(pipe);
+}
+
 void usbhs_pipe_init(struct usbhs_priv *priv,
 		     int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map))
 {
@@ -710,6 +715,7 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
 	usbhsp_pipe_select(pipe);
 	usbhsp_pipe_cfg_set(pipe, 0xFFFF, pipecfg);
 	usbhsp_pipe_buf_set(pipe, 0xFFFF, pipebuf);
+	usbhs_pipe_clear(pipe);
 
 	usbhs_pipe_sequence_data0(pipe);
 
@@ -726,6 +732,11 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
 	return pipe;
 }
 
+void usbhs_pipe_free(struct usbhs_pipe *pipe)
+{
+	usbhsp_put_pipe(pipe);
+}
+
 void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo)
 {
 	if (pipe->fifo)
diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h
index 3e5349879838..406f36d050e4 100644
--- a/drivers/usb/renesas_usbhs/pipe.h
+++ b/drivers/usb/renesas_usbhs/pipe.h
@@ -75,6 +75,7 @@ struct usbhs_pipe_info {
 char *usbhs_pipe_name(struct usbhs_pipe *pipe);
 struct usbhs_pipe
 *usbhs_pipe_malloc(struct usbhs_priv *priv, int endpoint_type, int dir_in);
+void usbhs_pipe_free(struct usbhs_pipe *pipe);
 int usbhs_pipe_probe(struct usbhs_priv *priv);
 void usbhs_pipe_remove(struct usbhs_priv *priv);
 int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe);
diff --git a/drivers/usb/renesas_usbhs/rcar2.c b/drivers/usb/renesas_usbhs/rcar2.c
new file mode 100644
index 000000000000..e6b9dcc1c289
--- /dev/null
+++ b/drivers/usb/renesas_usbhs/rcar2.c
@@ -0,0 +1,77 @@
+/*
+ * Renesas USB driver R-Car Gen. 2 initialization and power control
+ *
+ * Copyright (C) 2014 Ulrich Hecht
+ *
+ * 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.
+ *
+ */
+
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_data/gpio-rcar.h>
+#include <linux/usb/phy.h>
+#include "common.h"
+#include "rcar2.h"
+
+static int usbhs_rcar2_hardware_init(struct platform_device *pdev)
+{
+	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
+	struct usb_phy *phy;
+
+	phy = usb_get_phy_dev(&pdev->dev, 0);
+	if (IS_ERR(phy))
+		return PTR_ERR(phy);
+
+	priv->phy = phy;
+	return 0;
+}
+
+static int usbhs_rcar2_hardware_exit(struct platform_device *pdev)
+{
+	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
+
+	if (!priv->phy)
+		return 0;
+
+	usb_put_phy(priv->phy);
+	priv->phy = NULL;
+
+	return 0;
+}
+
+static int usbhs_rcar2_power_ctrl(struct platform_device *pdev,
+				void __iomem *base, int enable)
+{
+	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
+
+	if (!priv->phy)
+		return -ENODEV;
+
+	if (enable) {
+		int retval = usb_phy_init(priv->phy);
+
+		if (!retval)
+			retval = usb_phy_set_suspend(priv->phy, 0);
+		return retval;
+	}
+
+	usb_phy_set_suspend(priv->phy, 1);
+	usb_phy_shutdown(priv->phy);
+	return 0;
+}
+
+static int usbhs_rcar2_get_id(struct platform_device *pdev)
+{
+	return USBHS_GADGET;
+}
+
+const struct renesas_usbhs_platform_callback usbhs_rcar2_ops = {
+	.hardware_init = usbhs_rcar2_hardware_init,
+	.hardware_exit = usbhs_rcar2_hardware_exit,
+	.power_ctrl = usbhs_rcar2_power_ctrl,
+	.get_id = usbhs_rcar2_get_id,
+};
diff --git a/drivers/usb/renesas_usbhs/rcar2.h b/drivers/usb/renesas_usbhs/rcar2.h
new file mode 100644
index 000000000000..f07f10d9b3b2
--- /dev/null
+++ b/drivers/usb/renesas_usbhs/rcar2.h
@@ -0,0 +1,4 @@
+#include "common.h"
+
+extern const struct renesas_usbhs_platform_callback
+	usbhs_rcar2_ops;
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 330df5ce435b..e4bb62225cb9 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -856,9 +856,6 @@ static int cp210x_startup(struct usb_serial *serial)
 	struct usb_host_interface *cur_altsetting;
 	struct cp210x_serial_private *spriv;
 
-	/* cp210x buffers behave strangely unless device is reset */
-	usb_reset_device(serial->dev);
-
 	spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
 	if (!spriv)
 		return -ENOMEM;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 8a3813be1b28..216ce3078270 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -87,7 +87,6 @@ struct ftdi_sio_quirk {
 };
 
 static int   ftdi_jtag_probe(struct usb_serial *serial);
-static int   ftdi_mtxorb_hack_setup(struct usb_serial *serial);
 static int   ftdi_NDI_device_setup(struct usb_serial *serial);
 static int   ftdi_stmclite_probe(struct usb_serial *serial);
 static int   ftdi_8u2232c_probe(struct usb_serial *serial);
@@ -98,10 +97,6 @@ static struct ftdi_sio_quirk ftdi_jtag_quirk = {
 	.probe	= ftdi_jtag_probe,
 };
 
-static struct ftdi_sio_quirk ftdi_mtxorb_hack_quirk = {
-	.probe  = ftdi_mtxorb_hack_setup,
-};
-
 static struct ftdi_sio_quirk ftdi_NDI_device_quirk = {
 	.probe	= ftdi_NDI_device_setup,
 };
@@ -256,14 +251,12 @@ static const struct usb_device_id id_table_combined[] = {
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0124_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0125_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0126_PID) },
-	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0127_PID),
-		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0127_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0128_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0129_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012A_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012B_PID) },
-	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012C_PID),
-		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012C_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012D_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012E_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012F_PID) },
@@ -302,18 +295,12 @@ static const struct usb_device_id id_table_combined[] = {
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0150_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0151_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0152_PID) },
-	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0153_PID),
-		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
-	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0154_PID),
-		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
-	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0155_PID),
-		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
-	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0156_PID),
-		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
-	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0157_PID),
-		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
-	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0158_PID),
-		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0153_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0154_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0155_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0156_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0157_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0158_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0159_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015A_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015B_PID) },
@@ -673,6 +660,8 @@ static const struct usb_device_id id_table_combined[] = {
 	{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },
 	{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },
 	{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
+	{ USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) },
+	{ USB_DEVICE(XSENS_VID, XSENS_MTW_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
 	{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
@@ -1559,45 +1548,40 @@ static void ftdi_determine_type(struct usb_serial_port *port)
 }
 
 
-/* Determine the maximum packet size for the device.  This depends on the chip
- * type and the USB host capabilities.  The value should be obtained from the
- * device descriptor as the chip will use the appropriate values for the host.*/
+/*
+ * Determine the maximum packet size for the device. This depends on the chip
+ * type and the USB host capabilities. The value should be obtained from the
+ * device descriptor as the chip will use the appropriate values for the host.
+ */
 static void ftdi_set_max_packet_size(struct usb_serial_port *port)
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	struct usb_serial *serial = port->serial;
-	struct usb_device *udev = serial->dev;
-
-	struct usb_interface *interface = serial->interface;
+	struct usb_interface *interface = port->serial->interface;
 	struct usb_endpoint_descriptor *ep_desc;
-
 	unsigned num_endpoints;
 	unsigned i;
 
 	num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
-	dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
-
 	if (!num_endpoints)
 		return;
 
-	/* NOTE: some customers have programmed FT232R/FT245R devices
-	 * with an endpoint size of 0 - not good.  In this case, we
+	/*
+	 * NOTE: Some customers have programmed FT232R/FT245R devices
+	 * with an endpoint size of 0 - not good. In this case, we
 	 * want to override the endpoint descriptor setting and use a
-	 * value of 64 for wMaxPacketSize */
+	 * value of 64 for wMaxPacketSize.
+	 */
 	for (i = 0; i < num_endpoints; i++) {
-		dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1,
-			interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
 		ep_desc = &interface->cur_altsetting->endpoint[i].desc;
-		if (ep_desc->wMaxPacketSize == 0) {
+		if (!ep_desc->wMaxPacketSize) {
 			ep_desc->wMaxPacketSize = cpu_to_le16(0x40);
-			dev_info(&udev->dev, "Overriding wMaxPacketSize on endpoint %d\n", i);
+			dev_warn(&port->dev, "Overriding wMaxPacketSize on endpoint %d\n",
+					usb_endpoint_num(ep_desc));
 		}
 	}
 
-	/* set max packet size based on descriptor */
+	/* Set max packet size based on last descriptor. */
 	priv->max_packet_size = usb_endpoint_maxp(ep_desc);
-
-	dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
 }
 
 
@@ -1866,24 +1850,6 @@ static int ftdi_stmclite_probe(struct usb_serial *serial)
 	return 0;
 }
 
-/*
- * The Matrix Orbital VK204-25-USB has an invalid IN endpoint.
- * We have to correct it if we want to read from it.
- */
-static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
-{
-	struct usb_host_endpoint *ep = serial->dev->ep_in[1];
-	struct usb_endpoint_descriptor *ep_desc = &ep->desc;
-
-	if (ep->enabled && ep_desc->wMaxPacketSize == 0) {
-		ep_desc->wMaxPacketSize = cpu_to_le16(0x40);
-		dev_info(&serial->dev->dev,
-			 "Fixing invalid wMaxPacketSize on read pipe\n");
-	}
-
-	return 0;
-}
-
 static int ftdi_sio_port_remove(struct usb_serial_port *port)
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index c4777bc6aee0..1e58d90a0b6c 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -140,12 +140,15 @@
 /*
  * Xsens Technologies BV products (http://www.xsens.com).
  */
-#define XSENS_CONVERTER_0_PID	0xD388
-#define XSENS_CONVERTER_1_PID	0xD389
+#define XSENS_VID		0x2639
+#define XSENS_CONVERTER_PID	0xD00D	/* Xsens USB-serial converter */
+#define XSENS_MTW_PID		0x0200	/* Xsens MTw */
+#define XSENS_CONVERTER_0_PID	0xD388	/* Xsens USB converter */
+#define XSENS_CONVERTER_1_PID	0xD389	/* Xsens Wireless Receiver */
 #define XSENS_CONVERTER_2_PID	0xD38A
-#define XSENS_CONVERTER_3_PID	0xD38B
-#define XSENS_CONVERTER_4_PID	0xD38C
-#define XSENS_CONVERTER_5_PID	0xD38D
+#define XSENS_CONVERTER_3_PID	0xD38B	/* Xsens USB-serial converter */
+#define XSENS_CONVERTER_4_PID	0xD38C	/* Xsens Wireless Receiver */
+#define XSENS_CONVERTER_5_PID	0xD38D	/* Xsens Awinda Station */
 #define XSENS_CONVERTER_6_PID	0xD38E
 #define XSENS_CONVERTER_7_PID	0xD38F
 
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index d7440b7557af..e020ad28a00c 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -62,8 +62,6 @@ static void klsi_105_close(struct usb_serial_port *port);
 static void klsi_105_set_termios(struct tty_struct *tty,
 			struct usb_serial_port *port, struct ktermios *old);
 static int  klsi_105_tiocmget(struct tty_struct *tty);
-static int  klsi_105_tiocmset(struct tty_struct *tty,
-			unsigned int set, unsigned int clear);
 static void klsi_105_process_read_urb(struct urb *urb);
 static int klsi_105_prepare_write_buffer(struct usb_serial_port *port,
 						void *dest, size_t size);
@@ -93,7 +91,6 @@ static struct usb_serial_driver kl5kusb105d_device = {
 	.set_termios =		klsi_105_set_termios,
 	/*.break_ctl =		klsi_105_break_ctl,*/
 	.tiocmget =		klsi_105_tiocmget,
-	.tiocmset =		klsi_105_tiocmset,
 	.port_probe =		klsi_105_port_probe,
 	.port_remove =		klsi_105_port_remove,
 	.throttle =		usb_serial_generic_throttle,
@@ -602,33 +599,6 @@ static int klsi_105_tiocmget(struct tty_struct *tty)
 	return (int)line_state;
 }
 
-static int klsi_105_tiocmset(struct tty_struct *tty,
-			     unsigned int set, unsigned int clear)
-{
-	int retval = -EINVAL;
-
-/* if this ever gets implemented, it should be done something like this:
-	struct usb_serial *serial = port->serial;
-	struct klsi_105_private *priv = usb_get_serial_port_data(port);
-	unsigned long flags;
-	int control;
-
-	spin_lock_irqsave (&priv->lock, flags);
-	if (set & TIOCM_RTS)
-		priv->control_state |= TIOCM_RTS;
-	if (set & TIOCM_DTR)
-		priv->control_state |= TIOCM_DTR;
-	if (clear & TIOCM_RTS)
-		priv->control_state &= ~TIOCM_RTS;
-	if (clear & TIOCM_DTR)
-		priv->control_state &= ~TIOCM_DTR;
-	control = priv->control_state;
-	spin_unlock_irqrestore (&priv->lock, flags);
-	retval = mct_u232_set_modem_ctrl(serial, control);
-*/
-	return retval;
-}
-
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 393be562d875..3d88eefdf1d1 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1181,10 +1181,7 @@ static void mos7840_close(struct usb_serial_port *port)
 	/* Freeing Write URBs */
 	for (j = 0; j < NUM_URBS; ++j) {
 		if (mos7840_port->write_urb_pool[j]) {
-			if (mos7840_port->write_urb_pool[j]->transfer_buffer)
-				kfree(mos7840_port->write_urb_pool[j]->
-				      transfer_buffer);
-
+			kfree(mos7840_port->write_urb_pool[j]->transfer_buffer);
 			usb_free_urb(mos7840_port->write_urb_pool[j]);
 		}
 	}
diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h
index bb05b984d5f6..503ac5c8d80f 100644
--- a/drivers/usb/storage/uas-detect.h
+++ b/drivers/usb/storage/uas-detect.h
@@ -9,32 +9,15 @@ static int uas_is_interface(struct usb_host_interface *intf)
 		intf->desc.bInterfaceProtocol == USB_PR_UAS);
 }
 
-static int uas_isnt_supported(struct usb_device *udev)
-{
-	struct usb_hcd *hcd = bus_to_hcd(udev->bus);
-
-	dev_warn(&udev->dev, "The driver for the USB controller %s does not "
-			"support scatter-gather which is\n",
-			hcd->driver->description);
-	dev_warn(&udev->dev, "required by the UAS driver. Please try an"
-			"alternative USB controller if you wish to use UAS.\n");
-	return -ENODEV;
-}
-
 static int uas_find_uas_alt_setting(struct usb_interface *intf)
 {
 	int i;
-	struct usb_device *udev = interface_to_usbdev(intf);
-	int sg_supported = udev->bus->sg_tablesize != 0;
 
 	for (i = 0; i < intf->num_altsetting; i++) {
 		struct usb_host_interface *alt = &intf->altsetting[i];
 
-		if (uas_is_interface(alt)) {
-			if (!sg_supported)
-				return uas_isnt_supported(udev);
+		if (uas_is_interface(alt))
 			return alt->desc.bAlternateSetting;
-		}
 	}
 
 	return -ENODEV;
@@ -81,9 +64,6 @@ static int uas_use_uas_driver(struct usb_interface *intf,
 	if (flags & US_FL_IGNORE_UAS)
 		return 0;
 
-	if (udev->speed >= USB_SPEED_SUPER && !hcd->can_do_streams)
-		return 0;
-
 	alt = uas_find_uas_alt_setting(intf);
 	if (alt < 0)
 		return 0;
@@ -92,5 +72,23 @@ static int uas_use_uas_driver(struct usb_interface *intf,
 	if (r < 0)
 		return 0;
 
+	if (udev->bus->sg_tablesize == 0) {
+		dev_warn(&udev->dev,
+			"The driver for the USB controller %s does not support scatter-gather which is\n",
+			hcd->driver->description);
+		dev_warn(&udev->dev,
+			"required by the UAS driver. Please try an other USB controller if you wish to use UAS.\n");
+		return 0;
+	}
+
+	if (udev->speed >= USB_SPEED_SUPER && !hcd->can_do_streams) {
+		dev_warn(&udev->dev,
+			"USB controller %s does not support streams, which are required by the UAS driver.\n",
+			hcd_to_bus(hcd)->bus_name);
+		dev_warn(&udev->dev,
+			"Please try an other USB controller if you wish to use UAS.\n");
+		return 0;
+	}
+
 	return 1;
 }
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 511b22953167..3f42785f653c 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -1026,7 +1026,7 @@ static int uas_configure_endpoints(struct uas_dev_info *devinfo)
 					    usb_endpoint_num(&eps[3]->desc));
 
 	if (udev->speed != USB_SPEED_SUPER) {
-		devinfo->qdepth = 256;
+		devinfo->qdepth = 32;
 		devinfo->use_streams = 0;
 	} else {
 		devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1,
diff --git a/drivers/uwb/whci.c b/drivers/uwb/whci.c
index c9df8ba97dae..46b7cfcdfbca 100644
--- a/drivers/uwb/whci.c
+++ b/drivers/uwb/whci.c
@@ -175,7 +175,7 @@ static int whci_probe(struct pci_dev *pci, const struct pci_device_id *id)
 
 	err = -ENOMEM;
 	card = kzalloc(sizeof(struct whci_card)
-		       + sizeof(struct whci_dev *) * (n_caps + 1),
+		       + sizeof(struct umc_dev *) * (n_caps + 1),
 		       GFP_KERNEL);
 	if (card == NULL)
 		goto error_kzalloc;