Browse Source

Merge 3.5-rc7 into usb-next

This resolves the merge issue with the drivers/usb/host/ehci-omap.c
file.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Greg Kroah-Hartman 13 years ago
parent
commit
b903bd69e3
100 changed files with 5345 additions and 2517 deletions
  1. 18 0
      Documentation/devicetree/bindings/usb/ci13xxx-imx.txt
  2. 13 0
      Documentation/devicetree/bindings/usb/mxs-phy.txt
  3. 226 0
      Documentation/usb/mass-storage.txt
  4. 7 7
      arch/arm/mach-omap2/clock3xxx_data.c
  5. 4 4
      drivers/power/ab8500_charger.c
  6. 4 4
      drivers/power/isp1704_charger.c
  7. 11 11
      drivers/power/pda_power.c
  8. 7 6
      drivers/power/twl4030_charger.c
  9. 1 0
      drivers/usb/chipidea/Kconfig
  10. 7 2
      drivers/usb/chipidea/Makefile
  11. 17 15
      drivers/usb/chipidea/ci.h
  12. 198 0
      drivers/usb/chipidea/ci13xxx_imx.c
  13. 26 37
      drivers/usb/chipidea/ci13xxx_msm.c
  14. 15 37
      drivers/usb/chipidea/ci13xxx_pci.c
  15. 64 6
      drivers/usb/chipidea/core.c
  16. 73 73
      drivers/usb/chipidea/debug.c
  17. 2 1
      drivers/usb/chipidea/host.c
  18. 318 317
      drivers/usb/chipidea/udc.c
  19. 1 1
      drivers/usb/class/cdc-acm.c
  20. 0 25
      drivers/usb/class/cdc-wdm.c
  21. 140 29
      drivers/usb/core/devio.c
  22. 8 2
      drivers/usb/core/driver.c
  23. 1 1
      drivers/usb/core/file.c
  24. 9 1
      drivers/usb/core/hcd.c
  25. 12 9
      drivers/usb/core/hub.c
  26. 3 2
      drivers/usb/core/message.c
  27. 3 2
      drivers/usb/core/sysfs.c
  28. 6 3
      drivers/usb/core/usb.h
  29. 10 3
      drivers/usb/dwc3/core.c
  30. 83 24
      drivers/usb/dwc3/core.h
  31. 0 1
      drivers/usb/dwc3/dwc3-exynos.c
  32. 92 54
      drivers/usb/dwc3/ep0.c
  33. 217 148
      drivers/usb/dwc3/gadget.c
  34. 6 0
      drivers/usb/dwc3/gadget.h
  35. 1 1
      drivers/usb/early/ehci-dbgp.c
  36. 9 0
      drivers/usb/gadget/Kconfig
  37. 1 0
      drivers/usb/gadget/Makefile
  38. 1 0
      drivers/usb/gadget/acm_ms.c
  39. 1 0
      drivers/usb/gadget/at91_udc.c
  40. 5 2
      drivers/usb/gadget/composite.c
  41. 7 0
      drivers/usb/gadget/f_fs.c
  42. 165 43
      drivers/usb/gadget/f_hid.c
  43. 31 102
      drivers/usb/gadget/f_mass_storage.c
  44. 241 46
      drivers/usb/gadget/f_uvc.c
  45. 5 3
      drivers/usb/gadget/f_uvc.h
  46. 31 43
      drivers/usb/gadget/fsl_mxc_udc.c
  47. 10 8
      drivers/usb/gadget/fsl_udc_core.c
  48. 3 3
      drivers/usb/gadget/imx_udc.c
  49. 25 60
      drivers/usb/gadget/lpc32xx_udc.c
  50. 320 0
      drivers/usb/gadget/mv_u3d.h
  51. 2098 0
      drivers/usb/gadget/mv_u3d_core.c
  52. 8 7
      drivers/usb/gadget/mv_udc_core.c
  53. 181 253
      drivers/usb/gadget/omap_udc.c
  54. 1 1
      drivers/usb/gadget/pch_udc.c
  55. 9 8
      drivers/usb/gadget/pxa25x_udc.c
  56. 8 7
      drivers/usb/gadget/pxa27x_udc.c
  57. 110 105
      drivers/usb/gadget/s3c-hsotg.c
  58. 7 6
      drivers/usb/gadget/s3c-hsudc.c
  59. 29 34
      drivers/usb/gadget/storage_common.c
  60. 6 6
      drivers/usb/gadget/u_ether.c
  61. 3 1
      drivers/usb/gadget/uvc.h
  62. 25 4
      drivers/usb/gadget/webcam.c
  63. 2 2
      drivers/usb/host/Kconfig
  64. 2 17
      drivers/usb/host/ehci-atmel.c
  65. 8 79
      drivers/usb/host/ehci-au1xxx.c
  66. 1 5
      drivers/usb/host/ehci-cns3xxx.c
  67. 12 28
      drivers/usb/host/ehci-fsl.c
  68. 2 13
      drivers/usb/host/ehci-grlib.c
  69. 98 11
      drivers/usb/host/ehci-hcd.c
  70. 11 21
      drivers/usb/host/ehci-hub.c
  71. 1 5
      drivers/usb/host/ehci-ixp4xx.c
  72. 7 20
      drivers/usb/host/ehci-msm.c
  73. 11 25
      drivers/usb/host/ehci-mv.c
  74. 1 16
      drivers/usb/host/ehci-mxc.c
  75. 1 7
      drivers/usb/host/ehci-octeon.c
  76. 56 52
      drivers/usb/host/ehci-omap.c
  77. 1 16
      drivers/usb/host/ehci-orion.c
  78. 82 152
      drivers/usb/host/ehci-pci.c
  79. 3 4
      drivers/usb/host/ehci-platform.c
  80. 2 15
      drivers/usb/host/ehci-pmcmsp.c
  81. 1 24
      drivers/usb/host/ehci-ppc-of.c
  82. 1 17
      drivers/usb/host/ehci-ps3.c
  83. 11 81
      drivers/usb/host/ehci-s5p.c
  84. 3 71
      drivers/usb/host/ehci-sead3.c
  85. 1 15
      drivers/usb/host/ehci-sh.c
  86. 4 67
      drivers/usb/host/ehci-spear.c
  87. 8 23
      drivers/usb/host/ehci-tegra.c
  88. 1 13
      drivers/usb/host/ehci-vt8500.c
  89. 1 8
      drivers/usb/host/ehci-w90x900.c
  90. 1 30
      drivers/usb/host/ehci-xilinx-of.c
  91. 1 20
      drivers/usb/host/ehci-xls.c
  92. 0 4
      drivers/usb/host/ehci.h
  93. 6 6
      drivers/usb/host/fhci-dbg.c
  94. 16 16
      drivers/usb/host/fhci-hcd.c
  95. 8 8
      drivers/usb/host/fhci-hub.c
  96. 15 15
      drivers/usb/host/fhci-sched.c
  97. 7 7
      drivers/usb/host/fhci-tds.c
  98. 2 20
      drivers/usb/host/fhci.h
  99. 3 3
      drivers/usb/host/imx21-hcd.c
  100. 11 13
      drivers/usb/host/ohci-exynos.c

+ 18 - 0
Documentation/devicetree/bindings/usb/ci13xxx-imx.txt

@@ -0,0 +1,18 @@
+* Freescale i.MX ci13xxx usb controllers
+
+Required properties:
+- compatible: Should be "fsl,imx27-usb"
+- reg: Should contain registers location and length
+- interrupts: Should contain controller interrupt
+
+Optional properties:
+- fsl,usbphy: phandler of usb phy that connects to the only one port
+- vbus-supply: regulator for vbus
+
+Examples:
+usb@02184000 { /* USB OTG */
+	compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+	reg = <0x02184000 0x200>;
+	interrupts = <0 43 0x04>;
+	fsl,usbphy = <&usbphy1>;
+};

+ 13 - 0
Documentation/devicetree/bindings/usb/mxs-phy.txt

@@ -0,0 +1,13 @@
+* Freescale MXS USB Phy Device
+
+Required properties:
+- compatible: Should be "fsl,imx23-usbphy"
+- reg: Should contain registers location and length
+- interrupts: Should contain phy interrupt
+
+Example:
+usbphy1: usbphy@020c9000 {
+	compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
+	reg = <0x020c9000 0x1000>;
+	interrupts = <0 44 0x04>;
+};

+ 226 - 0
Documentation/usb/mass-storage.txt

@@ -0,0 +1,226 @@
+* Overview
+
+  Mass Storage Gadget (or MSG) acts as a USB Mass Storage device,
+  appearing to the host as a disk or a CD-ROM drive.  It supports
+  multiple logical units (LUNs).  Backing storage for each LUN is
+  provided by a regular file or a block device, access can be limited
+  to read-only, and gadget can indicate that it is removable and/or
+  CD-ROM (the latter implies read-only access).
+
+  Its requirements are modest; only a bulk-in and a bulk-out endpoint
+  are needed.  The memory requirement amounts to two 16K buffers.
+  Support is included for full-speed, high-speed and SuperSpeed
+  operation.
+
+  Note that the driver is slightly non-portable in that it assumes
+  a single memory/DMA buffer will be useable for bulk-in and bulk-out
+  endpoints.  With most device controllers this is not an issue, but
+  there may be some with hardware restrictions that prevent a buffer
+  from being used by more than one endpoint.
+
+  This document describes how to use the gadget from user space, its
+  relation to mass storage function (or MSF) and different gadgets
+  using it, and how it differs from File Storage Gadget (or FSG).  It
+  will talk only briefly about how to use MSF within composite
+  gadgets.
+
+* Module parameters
+
+  The mass storage gadget accepts the following mass storage specific
+  module parameters:
+
+  - file=filename[,filename...]
+
+    This parameter lists paths to files or block devices used for
+    backing storage for each logical unit.  There may be at most
+    FSG_MAX_LUNS (8) LUNs set.  If more files are specified, they will
+    be silently ignored.  See also “luns” parameter.
+
+    *BEWARE* that if a file is used as a backing storage, it may not
+    be modified by any other process.  This is because the host
+    assumes the data does not change without its knowledge.  It may be
+    read, but (if the logical unit is writable) due to buffering on
+    the host side, the contents are not well defined.
+
+    The size of the logical unit will be rounded down to a full
+    logical block.  The logical block size is 2048 bytes for LUNs
+    simulating CD-ROM, block size of the device if the backing file is
+    a block device, or 512 bytes otherwise.
+
+  - removable=b[,b...]
+
+    This parameter specifies whether each logical unit should be
+    removable.  “b” here is either “y”, “Y” or “1” for true or “n”,
+    “N” or “0” for false.
+
+    If this option is set for a logical unit, gadget will accept an
+    “eject” SCSI request (Start/Stop Unit).  When it is sent, the
+    backing file will be closed to simulate ejection and the logical
+    unit will not be mountable by the host until a new backing file is
+    specified by userspace on the device (see “sysfs entries”
+    section).
+
+    If a logical unit is not removable (the default), a backing file
+    must be specified for it with the “file” parameter as the module
+    is loaded.  The same applies if the module is built in, no
+    exceptions.
+
+    The default value of the flag is false, *HOWEVER* it used to be
+    true.  This has been changed to better match File Storage Gadget
+    and because it seems like a saner default after all.  Thus to
+    maintain compatibility with older kernels, it's best to specify
+    the default values.  Also, if one relied on old default, explicit
+    “n” needs to be specified now.
+
+    Note that “removable” means the logical unit's media can be
+    ejected or removed (as is true for a CD-ROM drive or a card
+    reader).  It does *not* mean that the entire gadget can be
+    unplugged from the host; the proper term for that is
+    “hot-unpluggable”.
+
+  - cdrom=b[,b...]
+
+    This parameter specifies whether each logical unit should simulate
+    CD-ROM.  The default is false.
+
+  - ro=b[,b...]
+
+    This parameter specifies whether each logical unit should be
+    reported as read only.  This will prevent host from modifying the
+    backing files.
+
+    Note that if this flag for given logical unit is false but the
+    backing file could not be opened in read/write mode, the gadget
+    will fall back to read only mode anyway.
+
+    The default value for non-CD-ROM logical units is false; for
+    logical units simulating CD-ROM it is forced to true.
+
+  - nofua=b[,b...]
+
+    This parameter specifies whether FUA flag should be ignored in SCSI
+    Write10 and Write12 commands sent to given logical units.
+
+    MS Windows mounts removable storage in “Removal optimised mode” by
+    default.  All the writes to the media are synchronous, which is
+    achieved by setting the FUA (Force Unit Access) bit in SCSI
+    Write(10,12) commands.  This forces each write to wait until the
+    data has actually been written out and prevents I/O requests
+    aggregation in block layer dramatically decreasing performance.
+
+    Note that this may mean that if the device is powered from USB and
+    the user unplugs the device without unmounting it first (which at
+    least some Windows users do), the data may be lost.
+
+    The default value is false.
+
+  - luns=N
+
+    This parameter specifies number of logical units the gadget will
+    have.  It is limited by FSG_MAX_LUNS (8) and higher value will be
+    capped.
+
+    If this parameter is provided, and the number of files specified
+    in “file” argument is greater then the value of “luns”, all excess
+    files will be ignored.
+
+    If this parameter is not present, the number of logical units will
+    be deduced from the number of files specified in the “file”
+    parameter.  If the file parameter is missing as well, one is
+    assumed.
+
+  - stall=b
+
+    Specifies whether the gadget is allowed to halt bulk endpoints.
+    The default is determined according to the type of USB device
+    controller, but usually true.
+
+  In addition to the above, the gadget also accepts the following
+  parameters defined by the composite framework (they are common to
+  all composite gadgets so just a quick listing):
+
+  - idVendor      -- USB Vendor ID (16 bit integer)
+  - idProduct     -- USB Product ID (16 bit integer)
+  - bcdDevice     -- USB Device version (BCD) (16 bit integer)
+  - iManufacturer -- USB Manufacturer string (string)
+  - iProduct      -- USB Product string (string)
+  - iSerialNumber -- SerialNumber string (sting)
+
+* sysfs entries
+
+  For each logical unit, the gadget creates a directory in the sysfs
+  hierarchy.  Inside of it the following three files are created:
+
+  - file
+
+    When read it returns the path to the backing file for the given
+    logical unit.  If there is no backing file (possible only if the
+    logical unit is removable), the content is empty.
+
+    When written into, it changes the backing file for given logical
+    unit.  This change can be performed even if given logical unit is
+    not specified as removable (but that may look strange to the
+    host).  It may fail, however, if host disallowed medium removal
+    with the Prevent-Allow Medium Removal SCSI command.
+
+  - ro
+
+    Reflects the state of ro flag for the given logical unit.  It can
+    be read any time, and written to when there is no backing file
+    open for given logical unit.
+
+  - nofua
+
+    Reflects the state of nofua flag for given logical unit.  It can
+    be read and written.
+
+  Other then those, as usual, the values of module parameters can be
+  read from /sys/module/g_mass_storage/parameters/* files.
+
+* Other gadgets using mass storage function
+
+  The Mass Storage Gadget uses the Mass Storage Function to handle
+  mass storage protocol.  As a composite function, MSF may be used by
+  other gadgets as well (eg. g_multi and acm_ms).
+
+  All of the information in previous sections are valid for other
+  gadgets using MSF, except that support for mass storage related
+  module parameters may be missing, or the parameters may have
+  a prefix.  To figure out whether any of this is true one needs to
+  consult the gadget's documentation or its source code.
+
+  For examples of how to include mass storage function in gadgets, one
+  may take a look at mass_storage.c, acm_ms.c and multi.c (sorted by
+  complexity).
+
+* Relation to file storage gadget
+
+  The Mass Storage Function and thus the Mass Storage Gadget has been
+  based on the File Storage Gadget.  The difference between the two is
+  that MSG is a composite gadget (ie. uses the composite framework)
+  while file storage gadget is a traditional gadget.  From userspace
+  point of view this distinction does not really matter, but from
+  kernel hacker's point of view, this means that (i) MSG does not
+  duplicate code needed for handling basic USB protocol commands and
+  (ii) MSF can be used in any other composite gadget.
+
+  Because of that, File Storage Gadget has been deprecated and
+  scheduled to be removed in Linux 3.8.  All users need to transition
+  to the Mass Storage Gadget by that time.  The two gadgets behave
+  mostly the same from the outside except:
+
+  1. In FSG the “removable” and “cdrom” module parameters set the flag
+     for all logical units whereas in MSG they accept a list of y/n
+     values for each logical unit.  If one uses only a single logical
+     unit this does not matter, but if there are more, the y/n value
+     needs to be repeated for each logical unit.
+
+  2. FSG's “serial”, “vendor”, “product” and “release” module
+     parameters are handled in MSG by the composite layer's parameters
+     named respectively: “iSerialnumber”, “idVendor”, “idProduct” and
+     “bcdDevice”.
+
+  3. MSG does not support FSG's test mode, thus “transport”,
+     “protocol” and “buflen” FSG's module parameters are not
+     supported.  MSG always uses SCSI protocol with bulk only
+     transport mode and 16 KiB buffers.

+ 7 - 7
arch/arm/mach-omap2/clock3xxx_data.c

@@ -3391,15 +3391,15 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK(NULL,	"usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK("usbhs_omap",	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK("usbhs_omap",	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("usbhs_omap",	"utmi_p1_gfclk",	&dummy_ck,	CK_3XXX),
-	CLK("usbhs_omap",	"utmi_p2_gfclk",	&dummy_ck,	CK_3XXX),
-	CLK("usbhs_omap",	"xclk60mhsp1_ck",	&dummy_ck,	CK_3XXX),
-	CLK("usbhs_omap",	"xclk60mhsp2_ck",	&dummy_ck,	CK_3XXX),
-	CLK("usbhs_omap",	"usb_host_hs_utmi_p1_clk",	&dummy_ck,	CK_3XXX),
-	CLK("usbhs_omap",	"usb_host_hs_utmi_p2_clk",	&dummy_ck,	CK_3XXX),
+	CLK(NULL,	"utmi_p1_gfclk",	&dummy_ck,	CK_3XXX),
+	CLK(NULL,	"utmi_p2_gfclk",	&dummy_ck,	CK_3XXX),
+	CLK(NULL,	"xclk60mhsp1_ck",	&dummy_ck,	CK_3XXX),
+	CLK(NULL,	"xclk60mhsp2_ck",	&dummy_ck,	CK_3XXX),
+	CLK(NULL,	"usb_host_hs_utmi_p1_clk",	&dummy_ck,	CK_3XXX),
+	CLK(NULL,	"usb_host_hs_utmi_p2_clk",	&dummy_ck,	CK_3XXX),
 	CLK("usbhs_omap",	"usb_tll_hs_usb_ch0_clk",	&dummy_ck,	CK_3XXX),
 	CLK("usbhs_omap",	"usb_tll_hs_usb_ch0_clk",	&dummy_ck,	CK_3XXX),
 	CLK("usbhs_omap",	"usb_tll_hs_usb_ch1_clk",	&dummy_ck,	CK_3XXX),
 	CLK("usbhs_omap",	"usb_tll_hs_usb_ch1_clk",	&dummy_ck,	CK_3XXX),
-	CLK("usbhs_omap",	"init_60m_fclk",	&dummy_ck,	CK_3XXX),
+	CLK(NULL,	"init_60m_fclk",	&dummy_ck,	CK_3XXX),
 	CLK(NULL,	"usim_fck",	&usim_fck,	CK_3430ES2PLUS | CK_36XX),
 	CLK(NULL,	"usim_fck",	&usim_fck,	CK_3430ES2PLUS | CK_36XX),
 	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_3XXX),
 	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_3XXX),
 	CLK(NULL,	"wkup_32k_fck",	&wkup_32k_fck,	CK_3XXX),
 	CLK(NULL,	"wkup_32k_fck",	&wkup_32k_fck,	CK_3XXX),

+ 4 - 4
drivers/power/ab8500_charger.c

@@ -2517,7 +2517,7 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev)
 		dev_err(di->dev, "%s mask and set failed\n", __func__);
 		dev_err(di->dev, "%s mask and set failed\n", __func__);
 
 
 	usb_unregister_notifier(di->usb_phy, &di->nb);
 	usb_unregister_notifier(di->usb_phy, &di->nb);
-	usb_put_transceiver(di->usb_phy);
+	usb_put_phy(di->usb_phy);
 
 
 	/* Delete the work queue */
 	/* Delete the work queue */
 	destroy_workqueue(di->charger_wq);
 	destroy_workqueue(di->charger_wq);
@@ -2688,8 +2688,8 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
 		goto free_ac;
 		goto free_ac;
 	}
 	}
 
 
-	di->usb_phy = usb_get_transceiver();
-	if (!di->usb_phy) {
+	di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
+	if (IS_ERR_OR_NULL(di->usb_phy)) {
 		dev_err(di->dev, "failed to get usb transceiver\n");
 		dev_err(di->dev, "failed to get usb transceiver\n");
 		ret = -EINVAL;
 		ret = -EINVAL;
 		goto free_usb;
 		goto free_usb;
@@ -2747,7 +2747,7 @@ free_irq:
 		free_irq(irq, di);
 		free_irq(irq, di);
 	}
 	}
 put_usb_phy:
 put_usb_phy:
-	usb_put_transceiver(di->usb_phy);
+	usb_put_phy(di->usb_phy);
 free_usb:
 free_usb:
 	power_supply_unregister(&di->usb_chg.psy);
 	power_supply_unregister(&di->usb_chg.psy);
 free_ac:
 free_ac:

+ 4 - 4
drivers/power/isp1704_charger.c

@@ -415,8 +415,8 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev)
 	if (!isp)
 	if (!isp)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	isp->phy = usb_get_transceiver();
-	if (!isp->phy)
+	isp->phy = usb_get_phy(USB_PHY_TYPE_USB2);
+	if (IS_ERR_OR_NULL(isp->phy))
 		goto fail0;
 		goto fail0;
 
 
 	isp->dev = &pdev->dev;
 	isp->dev = &pdev->dev;
@@ -475,7 +475,7 @@ fail2:
 	power_supply_unregister(&isp->psy);
 	power_supply_unregister(&isp->psy);
 fail1:
 fail1:
 	isp1704_charger_set_power(isp, 0);
 	isp1704_charger_set_power(isp, 0);
-	usb_put_transceiver(isp->phy);
+	usb_put_phy(isp->phy);
 fail0:
 fail0:
 	kfree(isp);
 	kfree(isp);
 
 
@@ -490,7 +490,7 @@ static int __devexit isp1704_charger_remove(struct platform_device *pdev)
 
 
 	usb_unregister_notifier(isp->phy, &isp->nb);
 	usb_unregister_notifier(isp->phy, &isp->nb);
 	power_supply_unregister(&isp->psy);
 	power_supply_unregister(&isp->psy);
-	usb_put_transceiver(isp->phy);
+	usb_put_phy(isp->phy);
 	isp1704_charger_set_power(isp, 0);
 	isp1704_charger_set_power(isp, 0);
 	kfree(isp);
 	kfree(isp);
 
 

+ 11 - 11
drivers/power/pda_power.c

@@ -321,12 +321,12 @@ static int pda_power_probe(struct platform_device *pdev)
 	}
 	}
 
 
 #ifdef CONFIG_USB_OTG_UTILS
 #ifdef CONFIG_USB_OTG_UTILS
-	transceiver = usb_get_transceiver();
-	if (transceiver && !pdata->is_usb_online) {
-		pdata->is_usb_online = otg_is_usb_online;
-	}
-	if (transceiver && !pdata->is_ac_online) {
-		pdata->is_ac_online = otg_is_ac_online;
+	transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+	if (!IS_ERR_OR_NULL(transceiver)) {
+		if (!pdata->is_usb_online)
+			pdata->is_usb_online = otg_is_usb_online;
+		if (!pdata->is_ac_online)
+			pdata->is_ac_online = otg_is_ac_online;
 	}
 	}
 #endif
 #endif
 
 
@@ -373,7 +373,7 @@ static int pda_power_probe(struct platform_device *pdev)
 	}
 	}
 
 
 #ifdef CONFIG_USB_OTG_UTILS
 #ifdef CONFIG_USB_OTG_UTILS
-	if (transceiver && pdata->use_otg_notifier) {
+	if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
 		otg_nb.notifier_call = otg_handle_notification;
 		otg_nb.notifier_call = otg_handle_notification;
 		ret = usb_register_notifier(transceiver, &otg_nb);
 		ret = usb_register_notifier(transceiver, &otg_nb);
 		if (ret) {
 		if (ret) {
@@ -408,8 +408,8 @@ usb_supply_failed:
 	if (pdata->is_ac_online && ac_irq)
 	if (pdata->is_ac_online && ac_irq)
 		free_irq(ac_irq->start, &pda_psy_ac);
 		free_irq(ac_irq->start, &pda_psy_ac);
 #ifdef CONFIG_USB_OTG_UTILS
 #ifdef CONFIG_USB_OTG_UTILS
-	if (transceiver)
-		usb_put_transceiver(transceiver);
+	if (!IS_ERR_OR_NULL(transceiver))
+		usb_put_phy(transceiver);
 #endif
 #endif
 ac_irq_failed:
 ac_irq_failed:
 	if (pdata->is_ac_online)
 	if (pdata->is_ac_online)
@@ -443,8 +443,8 @@ static int pda_power_remove(struct platform_device *pdev)
 	if (pdata->is_ac_online)
 	if (pdata->is_ac_online)
 		power_supply_unregister(&pda_psy_ac);
 		power_supply_unregister(&pda_psy_ac);
 #ifdef CONFIG_USB_OTG_UTILS
 #ifdef CONFIG_USB_OTG_UTILS
-	if (transceiver)
-		usb_put_transceiver(transceiver);
+	if (!IS_ERR_OR_NULL(transceiver))
+		usb_put_phy(transceiver);
 #endif
 #endif
 	if (ac_draw) {
 	if (ac_draw) {
 		regulator_put(ac_draw);
 		regulator_put(ac_draw);

+ 7 - 6
drivers/power/twl4030_charger.c

@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
+#include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/i2c/twl.h>
 #include <linux/i2c/twl.h>
@@ -479,8 +480,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 
 
 	INIT_WORK(&bci->work, twl4030_bci_usb_work);
 	INIT_WORK(&bci->work, twl4030_bci_usb_work);
 
 
-	bci->transceiver = usb_get_transceiver();
-	if (bci->transceiver != NULL) {
+	bci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+	if (!IS_ERR_OR_NULL(bci->transceiver)) {
 		bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
 		bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
 		usb_register_notifier(bci->transceiver, &bci->usb_nb);
 		usb_register_notifier(bci->transceiver, &bci->usb_nb);
 	}
 	}
@@ -507,9 +508,9 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 
 
 fail_unmask_interrupts:
 fail_unmask_interrupts:
-	if (bci->transceiver != NULL) {
+	if (!IS_ERR_OR_NULL(bci->transceiver)) {
 		usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
 		usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
-		usb_put_transceiver(bci->transceiver);
+		usb_put_phy(bci->transceiver);
 	}
 	}
 	free_irq(bci->irq_bci, bci);
 	free_irq(bci->irq_bci, bci);
 fail_bci_irq:
 fail_bci_irq:
@@ -538,9 +539,9 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
 	twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
 	twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
 			 TWL4030_INTERRUPTS_BCIIMR2A);
 			 TWL4030_INTERRUPTS_BCIIMR2A);
 
 
-	if (bci->transceiver != NULL) {
+	if (!IS_ERR_OR_NULL(bci->transceiver)) {
 		usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
 		usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
-		usb_put_transceiver(bci->transceiver);
+		usb_put_phy(bci->transceiver);
 	}
 	}
 	free_irq(bci->irq_bci, bci);
 	free_irq(bci->irq_bci, bci);
 	free_irq(bci->irq_chg, bci);
 	free_irq(bci->irq_chg, bci);

+ 1 - 0
drivers/usb/chipidea/Kconfig

@@ -20,6 +20,7 @@ config USB_CHIPIDEA_UDC
 
 
 config USB_CHIPIDEA_HOST
 config USB_CHIPIDEA_HOST
 	bool "ChipIdea host controller"
 	bool "ChipIdea host controller"
+	select USB_EHCI_ROOT_HUB_TT
 	help
 	help
 	  Say Y here to enable host controller functionality of the
 	  Say Y here to enable host controller functionality of the
 	  ChipIdea driver.
 	  ChipIdea driver.

+ 7 - 2
drivers/usb/chipidea/Makefile

@@ -5,10 +5,15 @@ ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC)	+= udc.o
 ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST)	+= host.o
 ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST)	+= host.o
 ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG)	+= debug.o
 ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG)	+= debug.o
 
 
+# Glue/Bridge layers go here
+
+obj-$(CONFIG_USB_CHIPIDEA)	+= ci13xxx_msm.o
+
+# PCI doesn't provide stubs, need to check
 ifneq ($(CONFIG_PCI),)
 ifneq ($(CONFIG_PCI),)
 	obj-$(CONFIG_USB_CHIPIDEA)	+= ci13xxx_pci.o
 	obj-$(CONFIG_USB_CHIPIDEA)	+= ci13xxx_pci.o
 endif
 endif
 
 
-ifneq ($(CONFIG_ARCH_MSM),)
-	obj-$(CONFIG_USB_CHIPIDEA)	+= ci13xxx_msm.o
+ifneq ($(CONFIG_OF_DEVICE),)
+	obj-$(CONFIG_USB_CHIPIDEA)	+= ci13xxx_imx.o
 endif
 endif

+ 17 - 15
drivers/usb/chipidea/ci.h

@@ -36,7 +36,7 @@
  * @name: string description of the endpoint
  * @name: string description of the endpoint
  * @qh: queue head for this endpoint
  * @qh: queue head for this endpoint
  * @wedge: is the endpoint wedged
  * @wedge: is the endpoint wedged
- * @udc: pointer to the controller
+ * @ci: pointer to the controller
  * @lock: pointer to controller's spinlock
  * @lock: pointer to controller's spinlock
  * @td_pool: pointer to controller's TD pool
  * @td_pool: pointer to controller's TD pool
  */
  */
@@ -54,7 +54,7 @@ struct ci13xxx_ep {
 	int					wedge;
 	int					wedge;
 
 
 	/* global resources */
 	/* global resources */
-	struct ci13xxx				*udc;
+	struct ci13xxx				*ci;
 	spinlock_t				*lock;
 	spinlock_t				*lock;
 	struct dma_pool				*td_pool;
 	struct dma_pool				*td_pool;
 };
 };
@@ -125,7 +125,7 @@ struct hw_bank {
  * @remote_wakeup: host-enabled remote wakeup
  * @remote_wakeup: host-enabled remote wakeup
  * @suspended: suspended by host
  * @suspended: suspended by host
  * @test_mode: the selected test mode
  * @test_mode: the selected test mode
- * @udc_driver: platform specific information supplied by parent device
+ * @platdata: platform specific information supplied by parent device
  * @vbus_active: is VBUS active
  * @vbus_active: is VBUS active
  * @transceiver: pointer to USB PHY, if any
  * @transceiver: pointer to USB PHY, if any
  * @hcd: pointer to usb_hcd for ehci host driver
  * @hcd: pointer to usb_hcd for ehci host driver
@@ -158,8 +158,10 @@ struct ci13xxx {
 	u8				suspended;
 	u8				suspended;
 	u8				test_mode;
 	u8				test_mode;
 
 
-	struct ci13xxx_udc_driver	*udc_driver;
+	struct ci13xxx_platform_data	*platdata;
 	int				vbus_active;
 	int				vbus_active;
+	/* FIXME: some day, we'll not use global phy */
+	bool				global_phy;
 	struct usb_phy			*transceiver;
 	struct usb_phy			*transceiver;
 	struct usb_hcd			*hcd;
 	struct usb_hcd			*hcd;
 };
 };
@@ -250,9 +252,9 @@ static inline int ffs_nr(u32 x)
  *
  *
  * This function returns register contents
  * This function returns register contents
  */
  */
-static inline u32 hw_read(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask)
+static inline u32 hw_read(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask)
 {
 {
-	return ioread32(udc->hw_bank.regmap[reg]) & mask;
+	return ioread32(ci->hw_bank.regmap[reg]) & mask;
 }
 }
 
 
 /**
 /**
@@ -261,14 +263,14 @@ static inline u32 hw_read(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask)
  * @mask: bitfield mask
  * @mask: bitfield mask
  * @data: new value
  * @data: new value
  */
  */
-static inline void hw_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
+static inline void hw_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
 			    u32 mask, u32 data)
 			    u32 mask, u32 data)
 {
 {
 	if (~mask)
 	if (~mask)
-		data = (ioread32(udc->hw_bank.regmap[reg]) & ~mask)
+		data = (ioread32(ci->hw_bank.regmap[reg]) & ~mask)
 			| (data & mask);
 			| (data & mask);
 
 
-	iowrite32(data, udc->hw_bank.regmap[reg]);
+	iowrite32(data, ci->hw_bank.regmap[reg]);
 }
 }
 
 
 /**
 /**
@@ -278,12 +280,12 @@ static inline void hw_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
  *
  *
  * This function returns register contents
  * This function returns register contents
  */
  */
-static inline u32 hw_test_and_clear(struct ci13xxx *udc, enum ci13xxx_regs reg,
+static inline u32 hw_test_and_clear(struct ci13xxx *ci, enum ci13xxx_regs reg,
 				    u32 mask)
 				    u32 mask)
 {
 {
-	u32 val = ioread32(udc->hw_bank.regmap[reg]) & mask;
+	u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask;
 
 
-	iowrite32(val, udc->hw_bank.regmap[reg]);
+	iowrite32(val, ci->hw_bank.regmap[reg]);
 	return val;
 	return val;
 }
 }
 
 
@@ -295,12 +297,12 @@ static inline u32 hw_test_and_clear(struct ci13xxx *udc, enum ci13xxx_regs reg,
  *
  *
  * This function returns register contents
  * This function returns register contents
  */
  */
-static inline u32 hw_test_and_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
+static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
 				    u32 mask, u32 data)
 				    u32 mask, u32 data)
 {
 {
-	u32 val = hw_read(udc, reg, ~0);
+	u32 val = hw_read(ci, reg, ~0);
 
 
-	hw_write(udc, reg, mask, data);
+	hw_write(ci, reg, mask, data);
 	return (val & mask) >> ffs_nr(mask);
 	return (val & mask) >> ffs_nr(mask);
 }
 }
 
 

+ 198 - 0
drivers/usb/chipidea/ci13xxx_imx.c

@@ -0,0 +1,198 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Marek Vasut <marex@denx.de>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/dma-mapping.h>
+#include <linux/usb/chipidea.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+
+#include "ci.h"
+
+#define pdev_to_phy(pdev) \
+	((struct usb_phy *)platform_get_drvdata(pdev))
+
+struct ci13xxx_imx_data {
+	struct device_node *phy_np;
+	struct usb_phy *phy;
+	struct platform_device *ci_pdev;
+	struct clk *clk;
+	struct regulator *reg_vbus;
+};
+
+static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata  = {
+	.name			= "ci13xxx_imx",
+	.flags			= CI13XXX_REQUIRE_TRANSCEIVER |
+				  CI13XXX_PULLUP_ON_VBUS |
+				  CI13XXX_DISABLE_STREAMING,
+	.capoffset		= DEF_CAPOFFSET,
+};
+
+static int __devinit ci13xxx_imx_probe(struct platform_device *pdev)
+{
+	struct ci13xxx_imx_data *data;
+	struct platform_device *plat_ci, *phy_pdev;
+	struct device_node *phy_np;
+	struct resource *res;
+	struct regulator *reg_vbus;
+	int ret;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		dev_err(&pdev->dev, "Failed to allocate CI13xxx-IMX data!\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Can't get device resources!\n");
+		return -ENOENT;
+	}
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk)) {
+		dev_err(&pdev->dev,
+			"Failed to get clock, err=%ld\n", PTR_ERR(data->clk));
+		return PTR_ERR(data->clk);
+	}
+
+	ret = clk_prepare_enable(data->clk);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Failed to prepare or enable clock, err=%d\n", ret);
+		return ret;
+	}
+
+	phy_np = of_parse_phandle(pdev->dev.of_node, "fsl,usbphy", 0);
+	if (phy_np) {
+		data->phy_np = phy_np;
+		phy_pdev = of_find_device_by_node(phy_np);
+		if (phy_pdev) {
+			struct usb_phy *phy;
+			phy = pdev_to_phy(phy_pdev);
+			if (phy &&
+			    try_module_get(phy_pdev->dev.driver->owner)) {
+				usb_phy_init(phy);
+				data->phy = phy;
+			}
+		}
+	}
+
+	/* we only support host now, so enable vbus here */
+	reg_vbus = devm_regulator_get(&pdev->dev, "vbus");
+	if (!IS_ERR(reg_vbus)) {
+		ret = regulator_enable(reg_vbus);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed to enable vbus regulator, err=%d\n",
+				ret);
+			goto put_np;
+		}
+		data->reg_vbus = reg_vbus;
+	} else {
+		reg_vbus = NULL;
+	}
+
+	ci13xxx_imx_platdata.phy = data->phy;
+
+	if (!pdev->dev.dma_mask) {
+		pdev->dev.dma_mask = devm_kzalloc(&pdev->dev,
+				      sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
+		if (!pdev->dev.dma_mask) {
+			ret = -ENOMEM;
+			dev_err(&pdev->dev, "Failed to alloc dma_mask!\n");
+			goto err;
+		}
+		*pdev->dev.dma_mask = DMA_BIT_MASK(32);
+		dma_set_coherent_mask(&pdev->dev, *pdev->dev.dma_mask);
+	}
+	plat_ci = ci13xxx_add_device(&pdev->dev,
+				pdev->resource, pdev->num_resources,
+				&ci13xxx_imx_platdata);
+	if (IS_ERR(plat_ci)) {
+		ret = PTR_ERR(plat_ci);
+		dev_err(&pdev->dev,
+			"Can't register ci_hdrc platform device, err=%d\n",
+			ret);
+		goto err;
+	}
+
+	data->ci_pdev = plat_ci;
+	platform_set_drvdata(pdev, data);
+
+	pm_runtime_no_callbacks(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+
+err:
+	if (reg_vbus)
+		regulator_disable(reg_vbus);
+put_np:
+	if (phy_np)
+		of_node_put(phy_np);
+	clk_disable_unprepare(data->clk);
+	return ret;
+}
+
+static int __devexit ci13xxx_imx_remove(struct platform_device *pdev)
+{
+	struct ci13xxx_imx_data *data = platform_get_drvdata(pdev);
+
+	pm_runtime_disable(&pdev->dev);
+	ci13xxx_remove_device(data->ci_pdev);
+
+	if (data->reg_vbus)
+		regulator_disable(data->reg_vbus);
+
+	if (data->phy) {
+		usb_phy_shutdown(data->phy);
+		module_put(data->phy->dev->driver->owner);
+	}
+
+	of_node_put(data->phy_np);
+
+	clk_disable_unprepare(data->clk);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static const struct of_device_id ci13xxx_imx_dt_ids[] = {
+	{ .compatible = "fsl,imx27-usb", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ci13xxx_imx_dt_ids);
+
+static struct platform_driver ci13xxx_imx_driver = {
+	.probe = ci13xxx_imx_probe,
+	.remove = __devexit_p(ci13xxx_imx_remove),
+	.driver = {
+		.name = "imx_usb",
+		.owner = THIS_MODULE,
+		.of_match_table = ci13xxx_imx_dt_ids,
+	 },
+};
+
+module_platform_driver(ci13xxx_imx_driver);
+
+MODULE_ALIAS("platform:imx-usb");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CI13xxx i.MX USB binding");
+MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
+MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");

+ 26 - 37
drivers/usb/chipidea/ci13xxx_msm.c

@@ -15,11 +15,11 @@
 
 
 #include "ci.h"
 #include "ci.h"
 
 
-#define MSM_USB_BASE	(udc->hw_bank.abs)
+#define MSM_USB_BASE	(ci->hw_bank.abs)
 
 
-static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event)
+static void ci13xxx_msm_notify_event(struct ci13xxx *ci, unsigned event)
 {
 {
-	struct device *dev = udc->gadget.dev.parent;
+	struct device *dev = ci->gadget.dev.parent;
 	int val;
 	int val;
 
 
 	switch (event) {
 	switch (event) {
@@ -34,18 +34,18 @@ static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event)
 		 * Put the transceiver in non-driving mode. Otherwise host
 		 * Put the transceiver in non-driving mode. Otherwise host
 		 * may not detect soft-disconnection.
 		 * may not detect soft-disconnection.
 		 */
 		 */
-		val = usb_phy_io_read(udc->transceiver, ULPI_FUNC_CTRL);
+		val = usb_phy_io_read(ci->transceiver, ULPI_FUNC_CTRL);
 		val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
 		val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
 		val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
 		val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
-		usb_phy_io_write(udc->transceiver, val, ULPI_FUNC_CTRL);
+		usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL);
 		break;
 		break;
 	default:
 	default:
-		dev_dbg(dev, "unknown ci13xxx_udc event\n");
+		dev_dbg(dev, "unknown ci13xxx event\n");
 		break;
 		break;
 	}
 	}
 }
 }
 
 
-static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
+static struct ci13xxx_platform_data ci13xxx_msm_platdata = {
 	.name			= "ci13xxx_msm",
 	.name			= "ci13xxx_msm",
 	.flags			= CI13XXX_REGS_SHARED |
 	.flags			= CI13XXX_REGS_SHARED |
 				  CI13XXX_REQUIRE_TRANSCEIVER |
 				  CI13XXX_REQUIRE_TRANSCEIVER |
@@ -55,56 +55,45 @@ static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
 	.notify_event		= ci13xxx_msm_notify_event,
 	.notify_event		= ci13xxx_msm_notify_event,
 };
 };
 
 
-static int ci13xxx_msm_probe(struct platform_device *pdev)
+static int __devinit ci13xxx_msm_probe(struct platform_device *pdev)
 {
 {
 	struct platform_device *plat_ci;
 	struct platform_device *plat_ci;
-	int ret;
 
 
 	dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
 	dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
 
 
-	plat_ci = platform_device_alloc("ci_hdrc", -1);
-	if (!plat_ci) {
-		dev_err(&pdev->dev, "can't allocate ci_hdrc platform device\n");
-		return -ENOMEM;
+	plat_ci = ci13xxx_add_device(&pdev->dev,
+				pdev->resource, pdev->num_resources,
+				&ci13xxx_msm_platdata);
+	if (IS_ERR(plat_ci)) {
+		dev_err(&pdev->dev, "ci13xxx_add_device failed!\n");
+		return PTR_ERR(plat_ci);
 	}
 	}
 
 
-	ret = platform_device_add_resources(plat_ci, pdev->resource,
-					    pdev->num_resources);
-	if (ret) {
-		dev_err(&pdev->dev, "can't add resources to platform device\n");
-		goto put_platform;
-	}
-
-	ret = platform_device_add_data(plat_ci, &ci13xxx_msm_udc_driver,
-				       sizeof(ci13xxx_msm_udc_driver));
-	if (ret)
-		goto put_platform;
-
-	ret = platform_device_add(plat_ci);
-	if (ret)
-		goto put_platform;
+	platform_set_drvdata(pdev, plat_ci);
 
 
 	pm_runtime_no_callbacks(&pdev->dev);
 	pm_runtime_no_callbacks(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
 
 	return 0;
 	return 0;
+}
+
+static int __devexit ci13xxx_msm_remove(struct platform_device *pdev)
+{
+	struct platform_device *plat_ci = platform_get_drvdata(pdev);
 
 
-put_platform:
-	platform_device_put(plat_ci);
+	pm_runtime_disable(&pdev->dev);
+	ci13xxx_remove_device(plat_ci);
 
 
-	return ret;
+	return 0;
 }
 }
 
 
 static struct platform_driver ci13xxx_msm_driver = {
 static struct platform_driver ci13xxx_msm_driver = {
 	.probe = ci13xxx_msm_probe,
 	.probe = ci13xxx_msm_probe,
+	.remove = __devexit_p(ci13xxx_msm_remove),
 	.driver = { .name = "msm_hsusb", },
 	.driver = { .name = "msm_hsusb", },
 };
 };
-MODULE_ALIAS("platform:msm_hsusb");
 
 
-static int __init ci13xxx_msm_init(void)
-{
-	return platform_driver_register(&ci13xxx_msm_driver);
-}
-module_init(ci13xxx_msm_init);
+module_platform_driver(ci13xxx_msm_driver);
 
 
+MODULE_ALIAS("platform:msm_hsusb");
 MODULE_LICENSE("GPL v2");
 MODULE_LICENSE("GPL v2");

+ 15 - 37
drivers/usb/chipidea/ci13xxx_pci.c

@@ -23,17 +23,17 @@
 /******************************************************************************
 /******************************************************************************
  * PCI block
  * PCI block
  *****************************************************************************/
  *****************************************************************************/
-struct ci13xxx_udc_driver pci_driver = {
+struct ci13xxx_platform_data pci_platdata = {
 	.name		= UDC_DRIVER_NAME,
 	.name		= UDC_DRIVER_NAME,
 	.capoffset	= DEF_CAPOFFSET,
 	.capoffset	= DEF_CAPOFFSET,
 };
 };
 
 
-struct ci13xxx_udc_driver langwell_pci_driver = {
+struct ci13xxx_platform_data langwell_pci_platdata = {
 	.name		= UDC_DRIVER_NAME,
 	.name		= UDC_DRIVER_NAME,
 	.capoffset	= 0,
 	.capoffset	= 0,
 };
 };
 
 
-struct ci13xxx_udc_driver penwell_pci_driver = {
+struct ci13xxx_platform_data penwell_pci_platdata = {
 	.name		= UDC_DRIVER_NAME,
 	.name		= UDC_DRIVER_NAME,
 	.capoffset	= 0,
 	.capoffset	= 0,
 	.power_budget	= 200,
 	.power_budget	= 200,
@@ -51,12 +51,12 @@ struct ci13xxx_udc_driver penwell_pci_driver = {
 static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
 static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
 				       const struct pci_device_id *id)
 				       const struct pci_device_id *id)
 {
 {
-	struct ci13xxx_udc_driver *driver = (void *)id->driver_data;
+	struct ci13xxx_platform_data *platdata = (void *)id->driver_data;
 	struct platform_device *plat_ci;
 	struct platform_device *plat_ci;
 	struct resource res[3];
 	struct resource res[3];
 	int retval = 0, nres = 2;
 	int retval = 0, nres = 2;
 
 
-	if (!driver) {
+	if (!platdata) {
 		dev_err(&pdev->dev, "device doesn't provide driver data\n");
 		dev_err(&pdev->dev, "device doesn't provide driver data\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
@@ -75,13 +75,6 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
 	pci_set_master(pdev);
 	pci_set_master(pdev);
 	pci_try_set_mwi(pdev);
 	pci_try_set_mwi(pdev);
 
 
-	plat_ci = platform_device_alloc("ci_hdrc", -1);
-	if (!plat_ci) {
-		dev_err(&pdev->dev, "can't allocate ci_hdrc platform device\n");
-		retval = -ENOMEM;
-		goto disable_device;
-	}
-
 	memset(res, 0, sizeof(res));
 	memset(res, 0, sizeof(res));
 	res[0].start	= pci_resource_start(pdev, 0);
 	res[0].start	= pci_resource_start(pdev, 0);
 	res[0].end	= pci_resource_end(pdev, 0);
 	res[0].end	= pci_resource_end(pdev, 0);
@@ -89,32 +82,17 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
 	res[1].start	= pdev->irq;
 	res[1].start	= pdev->irq;
 	res[1].flags	= IORESOURCE_IRQ;
 	res[1].flags	= IORESOURCE_IRQ;
 
 
-	retval = platform_device_add_resources(plat_ci, res, nres);
-	if (retval) {
-		dev_err(&pdev->dev, "can't add resources to platform device\n");
-		goto put_platform;
+	plat_ci = ci13xxx_add_device(&pdev->dev, res, nres, platdata);
+	if (IS_ERR(plat_ci)) {
+		dev_err(&pdev->dev, "ci13xxx_add_device failed!\n");
+		retval = PTR_ERR(plat_ci);
+		goto disable_device;
 	}
 	}
 
 
-	retval = platform_device_add_data(plat_ci, driver, sizeof(*driver));
-	if (retval)
-		goto put_platform;
-
-	dma_set_coherent_mask(&plat_ci->dev, pdev->dev.coherent_dma_mask);
-	plat_ci->dev.dma_mask = pdev->dev.dma_mask;
-	plat_ci->dev.dma_parms = pdev->dev.dma_parms;
-	plat_ci->dev.parent = &pdev->dev;
-
 	pci_set_drvdata(pdev, plat_ci);
 	pci_set_drvdata(pdev, plat_ci);
 
 
-	retval = platform_device_add(plat_ci);
-	if (retval)
-		goto put_platform;
-
 	return 0;
 	return 0;
 
 
- put_platform:
-	pci_set_drvdata(pdev, NULL);
-	platform_device_put(plat_ci);
  disable_device:
  disable_device:
 	pci_disable_device(pdev);
 	pci_disable_device(pdev);
  done:
  done:
@@ -133,7 +111,7 @@ static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
 {
 {
 	struct platform_device *plat_ci = pci_get_drvdata(pdev);
 	struct platform_device *plat_ci = pci_get_drvdata(pdev);
 
 
-	platform_device_unregister(plat_ci);
+	ci13xxx_remove_device(plat_ci);
 	pci_set_drvdata(pdev, NULL);
 	pci_set_drvdata(pdev, NULL);
 	pci_disable_device(pdev);
 	pci_disable_device(pdev);
 }
 }
@@ -147,19 +125,19 @@ static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
 static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = {
 static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = {
 	{
 	{
 		PCI_DEVICE(0x153F, 0x1004),
 		PCI_DEVICE(0x153F, 0x1004),
-		.driver_data = (kernel_ulong_t)&pci_driver,
+		.driver_data = (kernel_ulong_t)&pci_platdata,
 	},
 	},
 	{
 	{
 		PCI_DEVICE(0x153F, 0x1006),
 		PCI_DEVICE(0x153F, 0x1006),
-		.driver_data = (kernel_ulong_t)&pci_driver,
+		.driver_data = (kernel_ulong_t)&pci_platdata,
 	},
 	},
 	{
 	{
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811),
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811),
-		.driver_data = (kernel_ulong_t)&langwell_pci_driver,
+		.driver_data = (kernel_ulong_t)&langwell_pci_platdata,
 	},
 	},
 	{
 	{
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829),
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829),
-		.driver_data = (kernel_ulong_t)&penwell_pci_driver,
+		.driver_data = (kernel_ulong_t)&penwell_pci_platdata,
 	},
 	},
 	{ 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ }
 	{ 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ }
 };
 };

+ 64 - 6
drivers/usb/chipidea/core.c

@@ -56,6 +56,7 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/module.h>
+#include <linux/idr.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irq.h>
@@ -179,7 +180,7 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
 	ci->hw_bank.abs = base;
 	ci->hw_bank.abs = base;
 
 
 	ci->hw_bank.cap = ci->hw_bank.abs;
 	ci->hw_bank.cap = ci->hw_bank.abs;
-	ci->hw_bank.cap += ci->udc_driver->capoffset;
+	ci->hw_bank.cap += ci->platdata->capoffset;
 	ci->hw_bank.op = ci->hw_bank.cap + ioread8(ci->hw_bank.cap);
 	ci->hw_bank.op = ci->hw_bank.cap + ioread8(ci->hw_bank.cap);
 
 
 	hw_alloc_regmap(ci, false);
 	hw_alloc_regmap(ci, false);
@@ -227,11 +228,11 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode)
 		udelay(10);		/* not RTOS friendly */
 		udelay(10);		/* not RTOS friendly */
 
 
 
 
-	if (ci->udc_driver->notify_event)
-		ci->udc_driver->notify_event(ci,
+	if (ci->platdata->notify_event)
+		ci->platdata->notify_event(ci,
 			CI13XXX_CONTROLLER_RESET_EVENT);
 			CI13XXX_CONTROLLER_RESET_EVENT);
 
 
-	if (ci->udc_driver->flags & CI13XXX_DISABLE_STREAMING)
+	if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING)
 		hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
 		hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
 
 
 	/* USBMODE should be configured step by step */
 	/* USBMODE should be configured step by step */
@@ -332,6 +333,59 @@ static irqreturn_t ci_irq(int irq, void *data)
 	return ci->role == CI_ROLE_END ? ret : ci_role(ci)->irq(ci);
 	return ci->role == CI_ROLE_END ? ret : ci_role(ci)->irq(ci);
 }
 }
 
 
+static DEFINE_IDA(ci_ida);
+
+struct platform_device *ci13xxx_add_device(struct device *dev,
+			struct resource *res, int nres,
+			struct ci13xxx_platform_data *platdata)
+{
+	struct platform_device *pdev;
+	int id, ret;
+
+	id = ida_simple_get(&ci_ida, 0, 0, GFP_KERNEL);
+	if (id < 0)
+		return ERR_PTR(id);
+
+	pdev = platform_device_alloc("ci_hdrc", id);
+	if (!pdev) {
+		ret = -ENOMEM;
+		goto put_id;
+	}
+
+	pdev->dev.parent = dev;
+	pdev->dev.dma_mask = dev->dma_mask;
+	pdev->dev.dma_parms = dev->dma_parms;
+	dma_set_coherent_mask(&pdev->dev, dev->coherent_dma_mask);
+
+	ret = platform_device_add_resources(pdev, res, nres);
+	if (ret)
+		goto err;
+
+	ret = platform_device_add_data(pdev, platdata, sizeof(*platdata));
+	if (ret)
+		goto err;
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto err;
+
+	return pdev;
+
+err:
+	platform_device_put(pdev);
+put_id:
+	ida_simple_remove(&ci_ida, id);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(ci13xxx_add_device);
+
+void ci13xxx_remove_device(struct platform_device *pdev)
+{
+	platform_device_unregister(pdev);
+	ida_simple_remove(&ci_ida, pdev->id);
+}
+EXPORT_SYMBOL_GPL(ci13xxx_remove_device);
+
 static int __devinit ci_hdrc_probe(struct platform_device *pdev)
 static int __devinit ci_hdrc_probe(struct platform_device *pdev)
 {
 {
 	struct device	*dev = &pdev->dev;
 	struct device	*dev = &pdev->dev;
@@ -364,7 +418,11 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	ci->dev = dev;
 	ci->dev = dev;
-	ci->udc_driver = dev->platform_data;
+	ci->platdata = dev->platform_data;
+	if (ci->platdata->phy)
+		ci->transceiver = ci->platdata->phy;
+	else
+		ci->global_phy = true;
 
 
 	ret = hw_device_init(ci, base);
 	ret = hw_device_init(ci, base);
 	if (ret < 0) {
 	if (ret < 0) {
@@ -419,7 +477,7 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	platform_set_drvdata(pdev, ci);
 	platform_set_drvdata(pdev, ci);
-	ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->udc_driver->name,
+	ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->platdata->name,
 			  ci);
 			  ci);
 	if (ret)
 	if (ret)
 		goto stop;
 		goto stop;

+ 73 - 73
drivers/usb/chipidea/debug.c

@@ -68,15 +68,15 @@ void dbg_interrupt(u32 intmask)
  *
  *
  * This function returns number of registers read
  * This function returns number of registers read
  */
  */
-static size_t hw_register_read(struct ci13xxx *udc, u32 *buf, size_t size)
+static size_t hw_register_read(struct ci13xxx *ci, u32 *buf, size_t size)
 {
 {
 	unsigned i;
 	unsigned i;
 
 
-	if (size > udc->hw_bank.size)
-		size = udc->hw_bank.size;
+	if (size > ci->hw_bank.size)
+		size = ci->hw_bank.size;
 
 
 	for (i = 0; i < size; i++)
 	for (i = 0; i < size; i++)
-		buf[i] = hw_read(udc, i * sizeof(u32), ~0);
+		buf[i] = hw_read(ci, i * sizeof(u32), ~0);
 
 
 	return size;
 	return size;
 }
 }
@@ -88,18 +88,18 @@ static size_t hw_register_read(struct ci13xxx *udc, u32 *buf, size_t size)
  *
  *
  * This function returns an error code
  * This function returns an error code
  */
  */
-static int hw_register_write(struct ci13xxx *udc, u16 addr, u32 data)
+static int hw_register_write(struct ci13xxx *ci, u16 addr, u32 data)
 {
 {
 	/* align */
 	/* align */
 	addr /= sizeof(u32);
 	addr /= sizeof(u32);
 
 
-	if (addr >= udc->hw_bank.size)
+	if (addr >= ci->hw_bank.size)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	/* align */
 	/* align */
 	addr *= sizeof(u32);
 	addr *= sizeof(u32);
 
 
-	hw_write(udc, addr, ~0, data);
+	hw_write(ci, addr, ~0, data);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -110,13 +110,13 @@ static int hw_register_write(struct ci13xxx *udc, u16 addr, u32 data)
  *
  *
  * This function returns an error code
  * This function returns an error code
  */
  */
-static int hw_intr_clear(struct ci13xxx *udc, int n)
+static int hw_intr_clear(struct ci13xxx *ci, int n)
 {
 {
 	if (n >= REG_BITS)
 	if (n >= REG_BITS)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	hw_write(udc, OP_USBINTR, BIT(n), 0);
-	hw_write(udc, OP_USBSTS,  BIT(n), BIT(n));
+	hw_write(ci, OP_USBINTR, BIT(n), 0);
+	hw_write(ci, OP_USBSTS,  BIT(n), BIT(n));
 	return 0;
 	return 0;
 }
 }
 
 
@@ -127,15 +127,15 @@ static int hw_intr_clear(struct ci13xxx *udc, int n)
  *
  *
  * This function returns an error code
  * This function returns an error code
  */
  */
-static int hw_intr_force(struct ci13xxx *udc, int n)
+static int hw_intr_force(struct ci13xxx *ci, int n)
 {
 {
 	if (n >= REG_BITS)
 	if (n >= REG_BITS)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
-	hw_write(udc, OP_USBINTR,  BIT(n), BIT(n));
-	hw_write(udc, OP_USBSTS,   BIT(n), BIT(n));
-	hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, 0);
+	hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
+	hw_write(ci, OP_USBINTR,  BIT(n), BIT(n));
+	hw_write(ci, OP_USBSTS,   BIT(n), BIT(n));
+	hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, 0);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -147,12 +147,12 @@ static int hw_intr_force(struct ci13xxx *udc, int n)
 static ssize_t show_device(struct device *dev, struct device_attribute *attr,
 static ssize_t show_device(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 			   char *buf)
 {
 {
-	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
-	struct usb_gadget *gadget = &udc->gadget;
+	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+	struct usb_gadget *gadget = &ci->gadget;
 	int n = 0;
 	int n = 0;
 
 
 	if (attr == NULL || buf == NULL) {
 	if (attr == NULL || buf == NULL) {
-		dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+		dev_err(ci->dev, "[%s] EINVAL\n", __func__);
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -188,8 +188,8 @@ static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
 static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
 static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 			   char *buf)
 {
 {
-	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
-	struct usb_gadget_driver *driver = udc->driver;
+	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+	struct usb_gadget_driver *driver = ci->driver;
 	int n = 0;
 	int n = 0;
 
 
 	if (attr == NULL || buf == NULL) {
 	if (attr == NULL || buf == NULL) {
@@ -412,22 +412,22 @@ static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
 static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
 static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 			   char *buf)
 {
 {
-	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
 	unsigned long flags;
 	unsigned long flags;
 	u32 intr;
 	u32 intr;
 	unsigned i, j, n = 0;
 	unsigned i, j, n = 0;
 
 
 	if (attr == NULL || buf == NULL) {
 	if (attr == NULL || buf == NULL) {
-		dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+		dev_err(ci->dev, "[%s] EINVAL\n", __func__);
 		return 0;
 		return 0;
 	}
 	}
 
 
-	spin_lock_irqsave(&udc->lock, flags);
+	spin_lock_irqsave(&ci->lock, flags);
 
 
 	/*n += scnprintf(buf + n, PAGE_SIZE - n,
 	/*n += scnprintf(buf + n, PAGE_SIZE - n,
-		       "status = %08x\n", hw_read_intr_status(udc));
+		       "status = %08x\n", hw_read_intr_status(ci));
 	n += scnprintf(buf + n, PAGE_SIZE - n,
 	n += scnprintf(buf + n, PAGE_SIZE - n,
-	"enable = %08x\n", hw_read_intr_enable(udc));*/
+	"enable = %08x\n", hw_read_intr_enable(ci));*/
 
 
 	n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
 	n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
 		       isr_statistics.test);
 		       isr_statistics.test);
@@ -471,7 +471,7 @@ static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
 			n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
 			n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
 	}
 	}
 
 
-	spin_unlock_irqrestore(&udc->lock, flags);
+	spin_unlock_irqrestore(&ci->lock, flags);
 
 
 	return n;
 	return n;
 }
 }
@@ -485,31 +485,31 @@ static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
 static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
 static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 			    const char *buf, size_t count)
 {
 {
-	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
 	unsigned long flags;
 	unsigned long flags;
 	unsigned en, bit;
 	unsigned en, bit;
 
 
 	if (attr == NULL || buf == NULL) {
 	if (attr == NULL || buf == NULL) {
-		dev_err(udc->dev, "EINVAL\n");
+		dev_err(ci->dev, "EINVAL\n");
 		goto done;
 		goto done;
 	}
 	}
 
 
 	if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
 	if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
-		dev_err(udc->dev, "<1|0> <bit>: enable|disable interrupt\n");
+		dev_err(ci->dev, "<1|0> <bit>: enable|disable interrupt\n");
 		goto done;
 		goto done;
 	}
 	}
 
 
-	spin_lock_irqsave(&udc->lock, flags);
+	spin_lock_irqsave(&ci->lock, flags);
 	if (en) {
 	if (en) {
-		if (hw_intr_force(udc, bit))
+		if (hw_intr_force(ci, bit))
 			dev_err(dev, "invalid bit number\n");
 			dev_err(dev, "invalid bit number\n");
 		else
 		else
 			isr_statistics.test++;
 			isr_statistics.test++;
 	} else {
 	} else {
-		if (hw_intr_clear(udc, bit))
+		if (hw_intr_clear(ci, bit))
 			dev_err(dev, "invalid bit number\n");
 			dev_err(dev, "invalid bit number\n");
 	}
 	}
-	spin_unlock_irqrestore(&udc->lock, flags);
+	spin_unlock_irqrestore(&ci->lock, flags);
 
 
  done:
  done:
 	return count;
 	return count;
@@ -524,18 +524,18 @@ static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
 static ssize_t show_port_test(struct device *dev,
 static ssize_t show_port_test(struct device *dev,
 			      struct device_attribute *attr, char *buf)
 			      struct device_attribute *attr, char *buf)
 {
 {
-	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
 	unsigned long flags;
 	unsigned long flags;
 	unsigned mode;
 	unsigned mode;
 
 
 	if (attr == NULL || buf == NULL) {
 	if (attr == NULL || buf == NULL) {
-		dev_err(udc->dev, "EINVAL\n");
+		dev_err(ci->dev, "EINVAL\n");
 		return 0;
 		return 0;
 	}
 	}
 
 
-	spin_lock_irqsave(&udc->lock, flags);
-	mode = hw_port_test_get(udc);
-	spin_unlock_irqrestore(&udc->lock, flags);
+	spin_lock_irqsave(&ci->lock, flags);
+	mode = hw_port_test_get(ci);
+	spin_unlock_irqrestore(&ci->lock, flags);
 
 
 	return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
 	return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
 }
 }
@@ -549,24 +549,24 @@ static ssize_t store_port_test(struct device *dev,
 			       struct device_attribute *attr,
 			       struct device_attribute *attr,
 			       const char *buf, size_t count)
 			       const char *buf, size_t count)
 {
 {
-	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
 	unsigned long flags;
 	unsigned long flags;
 	unsigned mode;
 	unsigned mode;
 
 
 	if (attr == NULL || buf == NULL) {
 	if (attr == NULL || buf == NULL) {
-		dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+		dev_err(ci->dev, "[%s] EINVAL\n", __func__);
 		goto done;
 		goto done;
 	}
 	}
 
 
 	if (sscanf(buf, "%u", &mode) != 1) {
 	if (sscanf(buf, "%u", &mode) != 1) {
-		dev_err(udc->dev, "<mode>: set port test mode");
+		dev_err(ci->dev, "<mode>: set port test mode");
 		goto done;
 		goto done;
 	}
 	}
 
 
-	spin_lock_irqsave(&udc->lock, flags);
-	if (hw_port_test_set(udc, mode))
-		dev_err(udc->dev, "invalid mode\n");
-	spin_unlock_irqrestore(&udc->lock, flags);
+	spin_lock_irqsave(&ci->lock, flags);
+	if (hw_port_test_set(ci, mode))
+		dev_err(ci->dev, "invalid mode\n");
+	spin_unlock_irqrestore(&ci->lock, flags);
 
 
  done:
  done:
 	return count;
 	return count;
@@ -582,20 +582,20 @@ static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
 static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
 static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 			   char *buf)
 {
 {
-	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
 	unsigned long flags;
 	unsigned long flags;
 	unsigned i, j, n = 0;
 	unsigned i, j, n = 0;
 
 
 	if (attr == NULL || buf == NULL) {
 	if (attr == NULL || buf == NULL) {
-		dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+		dev_err(ci->dev, "[%s] EINVAL\n", __func__);
 		return 0;
 		return 0;
 	}
 	}
 
 
-	spin_lock_irqsave(&udc->lock, flags);
-	for (i = 0; i < udc->hw_ep_max/2; i++) {
-		struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
+	spin_lock_irqsave(&ci->lock, flags);
+	for (i = 0; i < ci->hw_ep_max/2; i++) {
+		struct ci13xxx_ep *mEpRx = &ci->ci13xxx_ep[i];
 		struct ci13xxx_ep *mEpTx =
 		struct ci13xxx_ep *mEpTx =
-			&udc->ci13xxx_ep[i + udc->hw_ep_max/2];
+			&ci->ci13xxx_ep[i + ci->hw_ep_max/2];
 		n += scnprintf(buf + n, PAGE_SIZE - n,
 		n += scnprintf(buf + n, PAGE_SIZE - n,
 			       "EP=%02i: RX=%08X TX=%08X\n",
 			       "EP=%02i: RX=%08X TX=%08X\n",
 			       i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
 			       i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
@@ -606,7 +606,7 @@ static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
 				       *((u32 *)mEpTx->qh.ptr + j));
 				       *((u32 *)mEpTx->qh.ptr + j));
 		}
 		}
 	}
 	}
-	spin_unlock_irqrestore(&udc->lock, flags);
+	spin_unlock_irqrestore(&ci->lock, flags);
 
 
 	return n;
 	return n;
 }
 }
@@ -621,25 +621,25 @@ static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
 static ssize_t show_registers(struct device *dev,
 static ssize_t show_registers(struct device *dev,
 			      struct device_attribute *attr, char *buf)
 			      struct device_attribute *attr, char *buf)
 {
 {
-	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
 	unsigned long flags;
 	unsigned long flags;
 	u32 *dump;
 	u32 *dump;
 	unsigned i, k, n = 0;
 	unsigned i, k, n = 0;
 
 
 	if (attr == NULL || buf == NULL) {
 	if (attr == NULL || buf == NULL) {
-		dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+		dev_err(ci->dev, "[%s] EINVAL\n", __func__);
 		return 0;
 		return 0;
 	}
 	}
 
 
 	dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
 	dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
 	if (!dump) {
 	if (!dump) {
-		dev_err(udc->dev, "%s: out of memory\n", __func__);
+		dev_err(ci->dev, "%s: out of memory\n", __func__);
 		return 0;
 		return 0;
 	}
 	}
 
 
-	spin_lock_irqsave(&udc->lock, flags);
-	k = hw_register_read(udc, dump, DUMP_ENTRIES);
-	spin_unlock_irqrestore(&udc->lock, flags);
+	spin_lock_irqsave(&ci->lock, flags);
+	k = hw_register_read(ci, dump, DUMP_ENTRIES);
+	spin_unlock_irqrestore(&ci->lock, flags);
 
 
 	for (i = 0; i < k; i++) {
 	for (i = 0; i < k; i++) {
 		n += scnprintf(buf + n, PAGE_SIZE - n,
 		n += scnprintf(buf + n, PAGE_SIZE - n,
@@ -660,24 +660,24 @@ static ssize_t store_registers(struct device *dev,
 			       struct device_attribute *attr,
 			       struct device_attribute *attr,
 			       const char *buf, size_t count)
 			       const char *buf, size_t count)
 {
 {
-	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
 	unsigned long addr, data, flags;
 	unsigned long addr, data, flags;
 
 
 	if (attr == NULL || buf == NULL) {
 	if (attr == NULL || buf == NULL) {
-		dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+		dev_err(ci->dev, "[%s] EINVAL\n", __func__);
 		goto done;
 		goto done;
 	}
 	}
 
 
 	if (sscanf(buf, "%li %li", &addr, &data) != 2) {
 	if (sscanf(buf, "%li %li", &addr, &data) != 2) {
-		dev_err(udc->dev,
+		dev_err(ci->dev,
 			"<addr> <data>: write data to register address\n");
 			"<addr> <data>: write data to register address\n");
 		goto done;
 		goto done;
 	}
 	}
 
 
-	spin_lock_irqsave(&udc->lock, flags);
-	if (hw_register_write(udc, addr, data))
-		dev_err(udc->dev, "invalid address range\n");
-	spin_unlock_irqrestore(&udc->lock, flags);
+	spin_lock_irqsave(&ci->lock, flags);
+	if (hw_register_write(ci, addr, data))
+		dev_err(ci->dev, "invalid address range\n");
+	spin_unlock_irqrestore(&ci->lock, flags);
 
 
  done:
  done:
 	return count;
 	return count;
@@ -693,34 +693,34 @@ static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
 static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
 static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
 			     char *buf)
 			     char *buf)
 {
 {
-	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
 	unsigned long flags;
 	unsigned long flags;
 	struct list_head   *ptr = NULL;
 	struct list_head   *ptr = NULL;
 	struct ci13xxx_req *req = NULL;
 	struct ci13xxx_req *req = NULL;
 	unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
 	unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
 
 
 	if (attr == NULL || buf == NULL) {
 	if (attr == NULL || buf == NULL) {
-		dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+		dev_err(ci->dev, "[%s] EINVAL\n", __func__);
 		return 0;
 		return 0;
 	}
 	}
 
 
-	spin_lock_irqsave(&udc->lock, flags);
-	for (i = 0; i < udc->hw_ep_max; i++)
-		list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
+	spin_lock_irqsave(&ci->lock, flags);
+	for (i = 0; i < ci->hw_ep_max; i++)
+		list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue)
 		{
 		{
 			req = list_entry(ptr, struct ci13xxx_req, queue);
 			req = list_entry(ptr, struct ci13xxx_req, queue);
 
 
 			n += scnprintf(buf + n, PAGE_SIZE - n,
 			n += scnprintf(buf + n, PAGE_SIZE - n,
 					"EP=%02i: TD=%08X %s\n",
 					"EP=%02i: TD=%08X %s\n",
-					i % udc->hw_ep_max/2, (u32)req->dma,
-					((i < udc->hw_ep_max/2) ? "RX" : "TX"));
+					i % ci->hw_ep_max/2, (u32)req->dma,
+					((i < ci->hw_ep_max/2) ? "RX" : "TX"));
 
 
 			for (j = 0; j < qSize; j++)
 			for (j = 0; j < qSize; j++)
 				n += scnprintf(buf + n, PAGE_SIZE - n,
 				n += scnprintf(buf + n, PAGE_SIZE - n,
 						" %04X:    %08X\n", j,
 						" %04X:    %08X\n", j,
 						*((u32 *)req->ptr + j));
 						*((u32 *)req->ptr + j));
 		}
 		}
-	spin_unlock_irqrestore(&udc->lock, flags);
+	spin_unlock_irqrestore(&ci->lock, flags);
 
 
 	return n;
 	return n;
 }
 }

+ 2 - 1
drivers/usb/chipidea/host.c

@@ -116,7 +116,8 @@ static int host_start(struct ci13xxx *ci)
 	hcd->regs = ci->hw_bank.abs;
 	hcd->regs = ci->hw_bank.abs;
 	hcd->has_tt = 1;
 	hcd->has_tt = 1;
 
 
-	hcd->power_budget = ci->udc_driver->power_budget;
+	hcd->power_budget = ci->platdata->power_budget;
+	hcd->phy = ci->transceiver;
 
 
 	ehci = hcd_to_ehci(hcd);
 	ehci = hcd_to_ehci(hcd);
 	ehci->caps = ci->hw_bank.cap;
 	ehci->caps = ci->hw_bank.cap;

+ 318 - 317
drivers/usb/chipidea/udc.c

@@ -14,6 +14,7 @@
 #include <linux/device.h>
 #include <linux/device.h>
 #include <linux/dmapool.h>
 #include <linux/dmapool.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/module.h>
@@ -66,11 +67,11 @@ static inline int hw_ep_bit(int num, int dir)
 	return num + (dir ? 16 : 0);
 	return num + (dir ? 16 : 0);
 }
 }
 
 
-static inline int ep_to_bit(struct ci13xxx *udc, int n)
+static inline int ep_to_bit(struct ci13xxx *ci, int n)
 {
 {
-	int fill = 16 - udc->hw_ep_max / 2;
+	int fill = 16 - ci->hw_ep_max / 2;
 
 
-	if (n >= udc->hw_ep_max / 2)
+	if (n >= ci->hw_ep_max / 2)
 		n += fill;
 		n += fill;
 
 
 	return n;
 	return n;
@@ -83,17 +84,17 @@ static inline int ep_to_bit(struct ci13xxx *udc, int n)
  *
  *
  * This function returns an error code
  * This function returns an error code
  */
  */
-static int hw_device_state(struct ci13xxx *udc, u32 dma)
+static int hw_device_state(struct ci13xxx *ci, u32 dma)
 {
 {
 	if (dma) {
 	if (dma) {
-		hw_write(udc, OP_ENDPTLISTADDR, ~0, dma);
+		hw_write(ci, OP_ENDPTLISTADDR, ~0, dma);
 		/* interrupt, error, port change, reset, sleep/suspend */
 		/* interrupt, error, port change, reset, sleep/suspend */
-		hw_write(udc, OP_USBINTR, ~0,
+		hw_write(ci, OP_USBINTR, ~0,
 			     USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
 			     USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
-		hw_write(udc, OP_USBCMD, USBCMD_RS, USBCMD_RS);
+		hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
 	} else {
 	} else {
-		hw_write(udc, OP_USBCMD, USBCMD_RS, 0);
-		hw_write(udc, OP_USBINTR, ~0, 0);
+		hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
+		hw_write(ci, OP_USBINTR, ~0, 0);
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -105,16 +106,16 @@ static int hw_device_state(struct ci13xxx *udc, u32 dma)
  *
  *
  * This function returns an error code
  * This function returns an error code
  */
  */
-static int hw_ep_flush(struct ci13xxx *udc, int num, int dir)
+static int hw_ep_flush(struct ci13xxx *ci, int num, int dir)
 {
 {
 	int n = hw_ep_bit(num, dir);
 	int n = hw_ep_bit(num, dir);
 
 
 	do {
 	do {
 		/* flush any pending transfer */
 		/* flush any pending transfer */
-		hw_write(udc, OP_ENDPTFLUSH, BIT(n), BIT(n));
-		while (hw_read(udc, OP_ENDPTFLUSH, BIT(n)))
+		hw_write(ci, OP_ENDPTFLUSH, BIT(n), BIT(n));
+		while (hw_read(ci, OP_ENDPTFLUSH, BIT(n)))
 			cpu_relax();
 			cpu_relax();
-	} while (hw_read(udc, OP_ENDPTSTAT, BIT(n)));
+	} while (hw_read(ci, OP_ENDPTSTAT, BIT(n)));
 
 
 	return 0;
 	return 0;
 }
 }
@@ -126,10 +127,10 @@ static int hw_ep_flush(struct ci13xxx *udc, int num, int dir)
  *
  *
  * This function returns an error code
  * This function returns an error code
  */
  */
-static int hw_ep_disable(struct ci13xxx *udc, int num, int dir)
+static int hw_ep_disable(struct ci13xxx *ci, int num, int dir)
 {
 {
-	hw_ep_flush(udc, num, dir);
-	hw_write(udc, OP_ENDPTCTRL + num,
+	hw_ep_flush(ci, num, dir);
+	hw_write(ci, OP_ENDPTCTRL + num,
 		 dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0);
 		 dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0);
 	return 0;
 	return 0;
 }
 }
@@ -142,7 +143,7 @@ static int hw_ep_disable(struct ci13xxx *udc, int num, int dir)
  *
  *
  * This function returns an error code
  * This function returns an error code
  */
  */
-static int hw_ep_enable(struct ci13xxx *udc, int num, int dir, int type)
+static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type)
 {
 {
 	u32 mask, data;
 	u32 mask, data;
 
 
@@ -165,7 +166,7 @@ static int hw_ep_enable(struct ci13xxx *udc, int num, int dir, int type)
 		mask |= ENDPTCTRL_RXE;  /* enable  */
 		mask |= ENDPTCTRL_RXE;  /* enable  */
 		data |= ENDPTCTRL_RXE;
 		data |= ENDPTCTRL_RXE;
 	}
 	}
-	hw_write(udc, OP_ENDPTCTRL + num, mask, data);
+	hw_write(ci, OP_ENDPTCTRL + num, mask, data);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -176,11 +177,11 @@ static int hw_ep_enable(struct ci13xxx *udc, int num, int dir, int type)
  *
  *
  * This function returns 1 if endpoint halted
  * This function returns 1 if endpoint halted
  */
  */
-static int hw_ep_get_halt(struct ci13xxx *udc, int num, int dir)
+static int hw_ep_get_halt(struct ci13xxx *ci, int num, int dir)
 {
 {
 	u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
 	u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
 
 
-	return hw_read(udc, OP_ENDPTCTRL + num, mask) ? 1 : 0;
+	return hw_read(ci, OP_ENDPTCTRL + num, mask) ? 1 : 0;
 }
 }
 
 
 /**
 /**
@@ -190,10 +191,10 @@ static int hw_ep_get_halt(struct ci13xxx *udc, int num, int dir)
  *
  *
  * This function returns setup status
  * This function returns setup status
  */
  */
-static int hw_test_and_clear_setup_status(struct ci13xxx *udc, int n)
+static int hw_test_and_clear_setup_status(struct ci13xxx *ci, int n)
 {
 {
-	n = ep_to_bit(udc, n);
-	return hw_test_and_clear(udc, OP_ENDPTSETUPSTAT, BIT(n));
+	n = ep_to_bit(ci, n);
+	return hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(n));
 }
 }
 
 
 /**
 /**
@@ -204,18 +205,18 @@ static int hw_test_and_clear_setup_status(struct ci13xxx *udc, int n)
  *
  *
  * This function returns an error code
  * This function returns an error code
  */
  */
-static int hw_ep_prime(struct ci13xxx *udc, int num, int dir, int is_ctrl)
+static int hw_ep_prime(struct ci13xxx *ci, int num, int dir, int is_ctrl)
 {
 {
 	int n = hw_ep_bit(num, dir);
 	int n = hw_ep_bit(num, dir);
 
 
-	if (is_ctrl && dir == RX && hw_read(udc, OP_ENDPTSETUPSTAT, BIT(num)))
+	if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num)))
 		return -EAGAIN;
 		return -EAGAIN;
 
 
-	hw_write(udc, OP_ENDPTPRIME, BIT(n), BIT(n));
+	hw_write(ci, OP_ENDPTPRIME, BIT(n), BIT(n));
 
 
-	while (hw_read(udc, OP_ENDPTPRIME, BIT(n)))
+	while (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
 		cpu_relax();
 		cpu_relax();
-	if (is_ctrl && dir == RX && hw_read(udc, OP_ENDPTSETUPSTAT, BIT(num)))
+	if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num)))
 		return -EAGAIN;
 		return -EAGAIN;
 
 
 	/* status shoult be tested according with manual but it doesn't work */
 	/* status shoult be tested according with manual but it doesn't work */
@@ -231,7 +232,7 @@ static int hw_ep_prime(struct ci13xxx *udc, int num, int dir, int is_ctrl)
  *
  *
  * This function returns an error code
  * This function returns an error code
  */
  */
-static int hw_ep_set_halt(struct ci13xxx *udc, int num, int dir, int value)
+static int hw_ep_set_halt(struct ci13xxx *ci, int num, int dir, int value)
 {
 {
 	if (value != 0 && value != 1)
 	if (value != 0 && value != 1)
 		return -EINVAL;
 		return -EINVAL;
@@ -242,9 +243,9 @@ static int hw_ep_set_halt(struct ci13xxx *udc, int num, int dir, int value)
 		u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR;
 		u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR;
 
 
 		/* data toggle - reserved for EP0 but it's in ESS */
 		/* data toggle - reserved for EP0 but it's in ESS */
-		hw_write(udc, reg, mask_xs|mask_xr,
+		hw_write(ci, reg, mask_xs|mask_xr,
 			  value ? mask_xs : mask_xr);
 			  value ? mask_xs : mask_xr);
-	} while (value != hw_ep_get_halt(udc, num, dir));
+	} while (value != hw_ep_get_halt(ci, num, dir));
 
 
 	return 0;
 	return 0;
 }
 }
@@ -254,10 +255,10 @@ static int hw_ep_set_halt(struct ci13xxx *udc, int num, int dir, int value)
  *
  *
  * This function returns true if high speed port
  * This function returns true if high speed port
  */
  */
-static int hw_port_is_high_speed(struct ci13xxx *udc)
+static int hw_port_is_high_speed(struct ci13xxx *ci)
 {
 {
-	return udc->hw_bank.lpm ? hw_read(udc, OP_DEVLC, DEVLC_PSPD) :
-		hw_read(udc, OP_PORTSC, PORTSC_HSP);
+	return ci->hw_bank.lpm ? hw_read(ci, OP_DEVLC, DEVLC_PSPD) :
+		hw_read(ci, OP_PORTSC, PORTSC_HSP);
 }
 }
 
 
 /**
 /**
@@ -265,9 +266,9 @@ static int hw_port_is_high_speed(struct ci13xxx *udc)
  *
  *
  * This function returns register data
  * This function returns register data
  */
  */
-static u32 hw_read_intr_enable(struct ci13xxx *udc)
+static u32 hw_read_intr_enable(struct ci13xxx *ci)
 {
 {
-	return hw_read(udc, OP_USBINTR, ~0);
+	return hw_read(ci, OP_USBINTR, ~0);
 }
 }
 
 
 /**
 /**
@@ -275,9 +276,9 @@ static u32 hw_read_intr_enable(struct ci13xxx *udc)
  *
  *
  * This function returns register data
  * This function returns register data
  */
  */
-static u32 hw_read_intr_status(struct ci13xxx *udc)
+static u32 hw_read_intr_status(struct ci13xxx *ci)
 {
 {
-	return hw_read(udc, OP_USBSTS, ~0);
+	return hw_read(ci, OP_USBSTS, ~0);
 }
 }
 
 
 /**
 /**
@@ -287,10 +288,10 @@ static u32 hw_read_intr_status(struct ci13xxx *udc)
  *
  *
  * This function returns complete status
  * This function returns complete status
  */
  */
-static int hw_test_and_clear_complete(struct ci13xxx *udc, int n)
+static int hw_test_and_clear_complete(struct ci13xxx *ci, int n)
 {
 {
-	n = ep_to_bit(udc, n);
-	return hw_test_and_clear(udc, OP_ENDPTCOMPLETE, BIT(n));
+	n = ep_to_bit(ci, n);
+	return hw_test_and_clear(ci, OP_ENDPTCOMPLETE, BIT(n));
 }
 }
 
 
 /**
 /**
@@ -299,11 +300,11 @@ static int hw_test_and_clear_complete(struct ci13xxx *udc, int n)
  *
  *
  * This function returns active interrutps
  * This function returns active interrutps
  */
  */
-static u32 hw_test_and_clear_intr_active(struct ci13xxx *udc)
+static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci)
 {
 {
-	u32 reg = hw_read_intr_status(udc) & hw_read_intr_enable(udc);
+	u32 reg = hw_read_intr_status(ci) & hw_read_intr_enable(ci);
 
 
-	hw_write(udc, OP_USBSTS, ~0, reg);
+	hw_write(ci, OP_USBSTS, ~0, reg);
 	return reg;
 	return reg;
 }
 }
 
 
@@ -313,9 +314,9 @@ static u32 hw_test_and_clear_intr_active(struct ci13xxx *udc)
  *
  *
  * This function returns guard value
  * This function returns guard value
  */
  */
-static int hw_test_and_clear_setup_guard(struct ci13xxx *udc)
+static int hw_test_and_clear_setup_guard(struct ci13xxx *ci)
 {
 {
-	return hw_test_and_write(udc, OP_USBCMD, USBCMD_SUTW, 0);
+	return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, 0);
 }
 }
 
 
 /**
 /**
@@ -324,9 +325,9 @@ static int hw_test_and_clear_setup_guard(struct ci13xxx *udc)
  *
  *
  * This function returns guard value
  * This function returns guard value
  */
  */
-static int hw_test_and_set_setup_guard(struct ci13xxx *udc)
+static int hw_test_and_set_setup_guard(struct ci13xxx *ci)
 {
 {
-	return hw_test_and_write(udc, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW);
+	return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW);
 }
 }
 
 
 /**
 /**
@@ -336,9 +337,9 @@ static int hw_test_and_set_setup_guard(struct ci13xxx *udc)
  * This function explicitly sets the address, without the "USBADRA" (advance)
  * This function explicitly sets the address, without the "USBADRA" (advance)
  * feature, which is not supported by older versions of the controller.
  * feature, which is not supported by older versions of the controller.
  */
  */
-static void hw_usb_set_address(struct ci13xxx *udc, u8 value)
+static void hw_usb_set_address(struct ci13xxx *ci, u8 value)
 {
 {
-	hw_write(udc, OP_DEVICEADDR, DEVICEADDR_USBADR,
+	hw_write(ci, OP_DEVICEADDR, DEVICEADDR_USBADR,
 		 value << ffs_nr(DEVICEADDR_USBADR));
 		 value << ffs_nr(DEVICEADDR_USBADR));
 }
 }
 
 
@@ -348,21 +349,21 @@ static void hw_usb_set_address(struct ci13xxx *udc, u8 value)
  *
  *
  * This function returns an error code
  * This function returns an error code
  */
  */
-static int hw_usb_reset(struct ci13xxx *udc)
+static int hw_usb_reset(struct ci13xxx *ci)
 {
 {
-	hw_usb_set_address(udc, 0);
+	hw_usb_set_address(ci, 0);
 
 
 	/* ESS flushes only at end?!? */
 	/* ESS flushes only at end?!? */
-	hw_write(udc, OP_ENDPTFLUSH,    ~0, ~0);
+	hw_write(ci, OP_ENDPTFLUSH,    ~0, ~0);
 
 
 	/* clear setup token semaphores */
 	/* clear setup token semaphores */
-	hw_write(udc, OP_ENDPTSETUPSTAT, 0,  0);
+	hw_write(ci, OP_ENDPTSETUPSTAT, 0,  0);
 
 
 	/* clear complete status */
 	/* clear complete status */
-	hw_write(udc, OP_ENDPTCOMPLETE,  0,  0);
+	hw_write(ci, OP_ENDPTCOMPLETE,  0,  0);
 
 
 	/* wait until all bits cleared */
 	/* wait until all bits cleared */
-	while (hw_read(udc, OP_ENDPTPRIME, ~0))
+	while (hw_read(ci, OP_ENDPTPRIME, ~0))
 		udelay(10);             /* not RTOS friendly */
 		udelay(10);             /* not RTOS friendly */
 
 
 	/* reset all endpoints ? */
 	/* reset all endpoints ? */
@@ -394,7 +395,7 @@ static inline u8 _usb_addr(struct ci13xxx_ep *ep)
  */
  */
 static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 {
 {
-	struct ci13xxx *udc = mEp->udc;
+	struct ci13xxx *ci = mEp->ci;
 	unsigned i;
 	unsigned i;
 	int ret = 0;
 	int ret = 0;
 	unsigned length = mReq->req.length;
 	unsigned length = mReq->req.length;
@@ -417,7 +418,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 		if (!mReq->req.no_interrupt)
 		if (!mReq->req.no_interrupt)
 			mReq->zptr->token   |= TD_IOC;
 			mReq->zptr->token   |= TD_IOC;
 	}
 	}
-	ret = usb_gadget_map_request(&udc->gadget, &mReq->req, mEp->dir);
+	ret = usb_gadget_map_request(&ci->gadget, &mReq->req, mEp->dir);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
@@ -453,13 +454,13 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 		else
 		else
 			mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
 			mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
 		wmb();
 		wmb();
-		if (hw_read(udc, OP_ENDPTPRIME, BIT(n)))
+		if (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
 			goto done;
 			goto done;
 		do {
 		do {
-			hw_write(udc, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
-			tmp_stat = hw_read(udc, OP_ENDPTSTAT, BIT(n));
-		} while (!hw_read(udc, OP_USBCMD, USBCMD_ATDTW));
-		hw_write(udc, OP_USBCMD, USBCMD_ATDTW, 0);
+			hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
+			tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n));
+		} while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW));
+		hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0);
 		if (tmp_stat)
 		if (tmp_stat)
 			goto done;
 			goto done;
 	}
 	}
@@ -471,7 +472,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 
 
 	wmb();   /* synchronize before ep prime */
 	wmb();   /* synchronize before ep prime */
 
 
-	ret = hw_ep_prime(udc, mEp->num, mEp->dir,
+	ret = hw_ep_prime(ci, mEp->num, mEp->dir,
 			   mEp->type == USB_ENDPOINT_XFER_CONTROL);
 			   mEp->type == USB_ENDPOINT_XFER_CONTROL);
 done:
 done:
 	return ret;
 	return ret;
@@ -501,7 +502,7 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 
 
 	mReq->req.status = 0;
 	mReq->req.status = 0;
 
 
-	usb_gadget_unmap_request(&mEp->udc->gadget, &mReq->req, mEp->dir);
+	usb_gadget_unmap_request(&mEp->ci->gadget, &mReq->req, mEp->dir);
 
 
 	mReq->req.status = mReq->ptr->token & TD_STATUS;
 	mReq->req.status = mReq->ptr->token & TD_STATUS;
 	if ((TD_STATUS_HALTED & mReq->req.status) != 0)
 	if ((TD_STATUS_HALTED & mReq->req.status) != 0)
@@ -533,7 +534,7 @@ __acquires(mEp->lock)
 	if (mEp == NULL)
 	if (mEp == NULL)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
+	hw_ep_flush(mEp->ci, mEp->num, mEp->dir);
 
 
 	while (!list_empty(&mEp->qh.queue)) {
 	while (!list_empty(&mEp->qh.queue)) {
 
 
@@ -562,33 +563,33 @@ __acquires(mEp->lock)
 static int _gadget_stop_activity(struct usb_gadget *gadget)
 static int _gadget_stop_activity(struct usb_gadget *gadget)
 {
 {
 	struct usb_ep *ep;
 	struct usb_ep *ep;
-	struct ci13xxx    *udc = container_of(gadget, struct ci13xxx, gadget);
+	struct ci13xxx    *ci = container_of(gadget, struct ci13xxx, gadget);
 	unsigned long flags;
 	unsigned long flags;
 
 
-	spin_lock_irqsave(&udc->lock, flags);
-	udc->gadget.speed = USB_SPEED_UNKNOWN;
-	udc->remote_wakeup = 0;
-	udc->suspended = 0;
-	spin_unlock_irqrestore(&udc->lock, flags);
+	spin_lock_irqsave(&ci->lock, flags);
+	ci->gadget.speed = USB_SPEED_UNKNOWN;
+	ci->remote_wakeup = 0;
+	ci->suspended = 0;
+	spin_unlock_irqrestore(&ci->lock, flags);
 
 
 	/* flush all endpoints */
 	/* flush all endpoints */
 	gadget_for_each_ep(ep, gadget) {
 	gadget_for_each_ep(ep, gadget) {
 		usb_ep_fifo_flush(ep);
 		usb_ep_fifo_flush(ep);
 	}
 	}
-	usb_ep_fifo_flush(&udc->ep0out->ep);
-	usb_ep_fifo_flush(&udc->ep0in->ep);
+	usb_ep_fifo_flush(&ci->ep0out->ep);
+	usb_ep_fifo_flush(&ci->ep0in->ep);
 
 
-	if (udc->driver)
-		udc->driver->disconnect(gadget);
+	if (ci->driver)
+		ci->driver->disconnect(gadget);
 
 
 	/* make sure to disable all endpoints */
 	/* make sure to disable all endpoints */
 	gadget_for_each_ep(ep, gadget) {
 	gadget_for_each_ep(ep, gadget) {
 		usb_ep_disable(ep);
 		usb_ep_disable(ep);
 	}
 	}
 
 
-	if (udc->status != NULL) {
-		usb_ep_free_request(&udc->ep0in->ep, udc->status);
-		udc->status = NULL;
+	if (ci->status != NULL) {
+		usb_ep_free_request(&ci->ep0in->ep, ci->status);
+		ci->status = NULL;
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -599,36 +600,36 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
  *****************************************************************************/
  *****************************************************************************/
 /**
 /**
  * isr_reset_handler: USB reset interrupt handler
  * isr_reset_handler: USB reset interrupt handler
- * @udc: UDC device
+ * @ci: UDC device
  *
  *
  * This function resets USB engine after a bus reset occurred
  * This function resets USB engine after a bus reset occurred
  */
  */
-static void isr_reset_handler(struct ci13xxx *udc)
-__releases(udc->lock)
-__acquires(udc->lock)
+static void isr_reset_handler(struct ci13xxx *ci)
+__releases(ci->lock)
+__acquires(ci->lock)
 {
 {
 	int retval;
 	int retval;
 
 
 	dbg_event(0xFF, "BUS RST", 0);
 	dbg_event(0xFF, "BUS RST", 0);
 
 
-	spin_unlock(&udc->lock);
-	retval = _gadget_stop_activity(&udc->gadget);
+	spin_unlock(&ci->lock);
+	retval = _gadget_stop_activity(&ci->gadget);
 	if (retval)
 	if (retval)
 		goto done;
 		goto done;
 
 
-	retval = hw_usb_reset(udc);
+	retval = hw_usb_reset(ci);
 	if (retval)
 	if (retval)
 		goto done;
 		goto done;
 
 
-	udc->status = usb_ep_alloc_request(&udc->ep0in->ep, GFP_ATOMIC);
-	if (udc->status == NULL)
+	ci->status = usb_ep_alloc_request(&ci->ep0in->ep, GFP_ATOMIC);
+	if (ci->status == NULL)
 		retval = -ENOMEM;
 		retval = -ENOMEM;
 
 
 done:
 done:
-	spin_lock(&udc->lock);
+	spin_lock(&ci->lock);
 
 
 	if (retval)
 	if (retval)
-		dev_err(udc->dev, "error: %i\n", retval);
+		dev_err(ci->dev, "error: %i\n", retval);
 }
 }
 
 
 /**
 /**
@@ -649,17 +650,17 @@ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
 
 
 /**
 /**
  * isr_get_status_response: get_status request response
  * isr_get_status_response: get_status request response
- * @udc: udc struct
+ * @ci: ci struct
  * @setup: setup request packet
  * @setup: setup request packet
  *
  *
  * This function returns an error code
  * This function returns an error code
  */
  */
-static int isr_get_status_response(struct ci13xxx *udc,
+static int isr_get_status_response(struct ci13xxx *ci,
 				   struct usb_ctrlrequest *setup)
 				   struct usb_ctrlrequest *setup)
 __releases(mEp->lock)
 __releases(mEp->lock)
 __acquires(mEp->lock)
 __acquires(mEp->lock)
 {
 {
-	struct ci13xxx_ep *mEp = udc->ep0in;
+	struct ci13xxx_ep *mEp = ci->ep0in;
 	struct usb_request *req = NULL;
 	struct usb_request *req = NULL;
 	gfp_t gfp_flags = GFP_ATOMIC;
 	gfp_t gfp_flags = GFP_ATOMIC;
 	int dir, num, retval;
 	int dir, num, retval;
@@ -683,14 +684,14 @@ __acquires(mEp->lock)
 
 
 	if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
 	if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
 		/* Assume that device is bus powered for now. */
 		/* Assume that device is bus powered for now. */
-		*(u16 *)req->buf = udc->remote_wakeup << 1;
+		*(u16 *)req->buf = ci->remote_wakeup << 1;
 		retval = 0;
 		retval = 0;
 	} else if ((setup->bRequestType & USB_RECIP_MASK) \
 	} else if ((setup->bRequestType & USB_RECIP_MASK) \
 		   == USB_RECIP_ENDPOINT) {
 		   == USB_RECIP_ENDPOINT) {
 		dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
 		dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
 			TX : RX;
 			TX : RX;
 		num =  le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
 		num =  le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
-		*(u16 *)req->buf = hw_ep_get_halt(udc, num, dir);
+		*(u16 *)req->buf = hw_ep_get_halt(ci, num, dir);
 	}
 	}
 	/* else do nothing; reserved for future use */
 	/* else do nothing; reserved for future use */
 
 
@@ -722,39 +723,39 @@ __acquires(mEp->lock)
 static void
 static void
 isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
 isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
 {
 {
-	struct ci13xxx *udc = req->context;
+	struct ci13xxx *ci = req->context;
 	unsigned long flags;
 	unsigned long flags;
 
 
-	if (udc->setaddr) {
-		hw_usb_set_address(udc, udc->address);
-		udc->setaddr = false;
+	if (ci->setaddr) {
+		hw_usb_set_address(ci, ci->address);
+		ci->setaddr = false;
 	}
 	}
 
 
-	spin_lock_irqsave(&udc->lock, flags);
-	if (udc->test_mode)
-		hw_port_test_set(udc, udc->test_mode);
-	spin_unlock_irqrestore(&udc->lock, flags);
+	spin_lock_irqsave(&ci->lock, flags);
+	if (ci->test_mode)
+		hw_port_test_set(ci, ci->test_mode);
+	spin_unlock_irqrestore(&ci->lock, flags);
 }
 }
 
 
 /**
 /**
  * isr_setup_status_phase: queues the status phase of a setup transation
  * isr_setup_status_phase: queues the status phase of a setup transation
- * @udc: udc struct
+ * @ci: ci struct
  *
  *
  * This function returns an error code
  * This function returns an error code
  */
  */
-static int isr_setup_status_phase(struct ci13xxx *udc)
+static int isr_setup_status_phase(struct ci13xxx *ci)
 __releases(mEp->lock)
 __releases(mEp->lock)
 __acquires(mEp->lock)
 __acquires(mEp->lock)
 {
 {
 	int retval;
 	int retval;
 	struct ci13xxx_ep *mEp;
 	struct ci13xxx_ep *mEp;
 
 
-	mEp = (udc->ep0_dir == TX) ? udc->ep0out : udc->ep0in;
-	udc->status->context = udc;
-	udc->status->complete = isr_setup_status_complete;
+	mEp = (ci->ep0_dir == TX) ? ci->ep0out : ci->ep0in;
+	ci->status->context = ci;
+	ci->status->complete = isr_setup_status_complete;
 
 
 	spin_unlock(mEp->lock);
 	spin_unlock(mEp->lock);
-	retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
+	retval = usb_ep_queue(&mEp->ep, ci->status, GFP_ATOMIC);
 	spin_lock(mEp->lock);
 	spin_lock(mEp->lock);
 
 
 	return retval;
 	return retval;
@@ -789,7 +790,7 @@ __acquires(mEp->lock)
 			spin_unlock(mEp->lock);
 			spin_unlock(mEp->lock);
 			if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
 			if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
 					mReq->req.length)
 					mReq->req.length)
-				mEpTemp = mEp->udc->ep0in;
+				mEpTemp = mEp->ci->ep0in;
 			mReq->req.complete(&mEpTemp->ep, &mReq->req);
 			mReq->req.complete(&mEpTemp->ep, &mReq->req);
 			spin_lock(mEp->lock);
 			spin_lock(mEp->lock);
 		}
 		}
@@ -805,48 +806,48 @@ __acquires(mEp->lock)
 
 
 /**
 /**
  * isr_tr_complete_handler: transaction complete interrupt handler
  * isr_tr_complete_handler: transaction complete interrupt handler
- * @udc: UDC descriptor
+ * @ci: UDC descriptor
  *
  *
  * This function handles traffic events
  * This function handles traffic events
  */
  */
-static void isr_tr_complete_handler(struct ci13xxx *udc)
-__releases(udc->lock)
-__acquires(udc->lock)
+static void isr_tr_complete_handler(struct ci13xxx *ci)
+__releases(ci->lock)
+__acquires(ci->lock)
 {
 {
 	unsigned i;
 	unsigned i;
 	u8 tmode = 0;
 	u8 tmode = 0;
 
 
-	for (i = 0; i < udc->hw_ep_max; i++) {
-		struct ci13xxx_ep *mEp  = &udc->ci13xxx_ep[i];
+	for (i = 0; i < ci->hw_ep_max; i++) {
+		struct ci13xxx_ep *mEp  = &ci->ci13xxx_ep[i];
 		int type, num, dir, err = -EINVAL;
 		int type, num, dir, err = -EINVAL;
 		struct usb_ctrlrequest req;
 		struct usb_ctrlrequest req;
 
 
 		if (mEp->ep.desc == NULL)
 		if (mEp->ep.desc == NULL)
 			continue;   /* not configured */
 			continue;   /* not configured */
 
 
-		if (hw_test_and_clear_complete(udc, i)) {
+		if (hw_test_and_clear_complete(ci, i)) {
 			err = isr_tr_complete_low(mEp);
 			err = isr_tr_complete_low(mEp);
 			if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
 			if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
 				if (err > 0)   /* needs status phase */
 				if (err > 0)   /* needs status phase */
-					err = isr_setup_status_phase(udc);
+					err = isr_setup_status_phase(ci);
 				if (err < 0) {
 				if (err < 0) {
 					dbg_event(_usb_addr(mEp),
 					dbg_event(_usb_addr(mEp),
 						  "ERROR", err);
 						  "ERROR", err);
-					spin_unlock(&udc->lock);
+					spin_unlock(&ci->lock);
 					if (usb_ep_set_halt(&mEp->ep))
 					if (usb_ep_set_halt(&mEp->ep))
-						dev_err(udc->dev,
+						dev_err(ci->dev,
 							"error: ep_set_halt\n");
 							"error: ep_set_halt\n");
-					spin_lock(&udc->lock);
+					spin_lock(&ci->lock);
 				}
 				}
 			}
 			}
 		}
 		}
 
 
 		if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
 		if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
-		    !hw_test_and_clear_setup_status(udc, i))
+		    !hw_test_and_clear_setup_status(ci, i))
 			continue;
 			continue;
 
 
 		if (i != 0) {
 		if (i != 0) {
-			dev_warn(udc->dev, "ctrl traffic at endpoint %d\n", i);
+			dev_warn(ci->dev, "ctrl traffic at endpoint %d\n", i);
 			continue;
 			continue;
 		}
 		}
 
 
@@ -854,18 +855,18 @@ __acquires(udc->lock)
 		 * Flush data and handshake transactions of previous
 		 * Flush data and handshake transactions of previous
 		 * setup packet.
 		 * setup packet.
 		 */
 		 */
-		_ep_nuke(udc->ep0out);
-		_ep_nuke(udc->ep0in);
+		_ep_nuke(ci->ep0out);
+		_ep_nuke(ci->ep0in);
 
 
 		/* read_setup_packet */
 		/* read_setup_packet */
 		do {
 		do {
-			hw_test_and_set_setup_guard(udc);
+			hw_test_and_set_setup_guard(ci);
 			memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
 			memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
-		} while (!hw_test_and_clear_setup_guard(udc));
+		} while (!hw_test_and_clear_setup_guard(ci));
 
 
 		type = req.bRequestType;
 		type = req.bRequestType;
 
 
-		udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
+		ci->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
 
 
 		dbg_setup(_usb_addr(mEp), &req);
 		dbg_setup(_usb_addr(mEp), &req);
 
 
@@ -880,23 +881,23 @@ __acquires(udc->lock)
 				dir = num & USB_ENDPOINT_DIR_MASK;
 				dir = num & USB_ENDPOINT_DIR_MASK;
 				num &= USB_ENDPOINT_NUMBER_MASK;
 				num &= USB_ENDPOINT_NUMBER_MASK;
 				if (dir) /* TX */
 				if (dir) /* TX */
-					num += udc->hw_ep_max/2;
-				if (!udc->ci13xxx_ep[num].wedge) {
-					spin_unlock(&udc->lock);
+					num += ci->hw_ep_max/2;
+				if (!ci->ci13xxx_ep[num].wedge) {
+					spin_unlock(&ci->lock);
 					err = usb_ep_clear_halt(
 					err = usb_ep_clear_halt(
-						&udc->ci13xxx_ep[num].ep);
-					spin_lock(&udc->lock);
+						&ci->ci13xxx_ep[num].ep);
+					spin_lock(&ci->lock);
 					if (err)
 					if (err)
 						break;
 						break;
 				}
 				}
-				err = isr_setup_status_phase(udc);
+				err = isr_setup_status_phase(ci);
 			} else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
 			} else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
 					le16_to_cpu(req.wValue) ==
 					le16_to_cpu(req.wValue) ==
 					USB_DEVICE_REMOTE_WAKEUP) {
 					USB_DEVICE_REMOTE_WAKEUP) {
 				if (req.wLength != 0)
 				if (req.wLength != 0)
 					break;
 					break;
-				udc->remote_wakeup = 0;
-				err = isr_setup_status_phase(udc);
+				ci->remote_wakeup = 0;
+				err = isr_setup_status_phase(ci);
 			} else {
 			} else {
 				goto delegate;
 				goto delegate;
 			}
 			}
@@ -909,7 +910,7 @@ __acquires(udc->lock)
 			if (le16_to_cpu(req.wLength) != 2 ||
 			if (le16_to_cpu(req.wLength) != 2 ||
 			    le16_to_cpu(req.wValue)  != 0)
 			    le16_to_cpu(req.wValue)  != 0)
 				break;
 				break;
-			err = isr_get_status_response(udc, &req);
+			err = isr_get_status_response(ci, &req);
 			break;
 			break;
 		case USB_REQ_SET_ADDRESS:
 		case USB_REQ_SET_ADDRESS:
 			if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
 			if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
@@ -917,9 +918,9 @@ __acquires(udc->lock)
 			if (le16_to_cpu(req.wLength) != 0 ||
 			if (le16_to_cpu(req.wLength) != 0 ||
 			    le16_to_cpu(req.wIndex)  != 0)
 			    le16_to_cpu(req.wIndex)  != 0)
 				break;
 				break;
-			udc->address = (u8)le16_to_cpu(req.wValue);
-			udc->setaddr = true;
-			err = isr_setup_status_phase(udc);
+			ci->address = (u8)le16_to_cpu(req.wValue);
+			ci->setaddr = true;
+			err = isr_setup_status_phase(ci);
 			break;
 			break;
 		case USB_REQ_SET_FEATURE:
 		case USB_REQ_SET_FEATURE:
 			if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
 			if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
@@ -931,20 +932,20 @@ __acquires(udc->lock)
 				dir = num & USB_ENDPOINT_DIR_MASK;
 				dir = num & USB_ENDPOINT_DIR_MASK;
 				num &= USB_ENDPOINT_NUMBER_MASK;
 				num &= USB_ENDPOINT_NUMBER_MASK;
 				if (dir) /* TX */
 				if (dir) /* TX */
-					num += udc->hw_ep_max/2;
+					num += ci->hw_ep_max/2;
 
 
-				spin_unlock(&udc->lock);
-				err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
-				spin_lock(&udc->lock);
+				spin_unlock(&ci->lock);
+				err = usb_ep_set_halt(&ci->ci13xxx_ep[num].ep);
+				spin_lock(&ci->lock);
 				if (!err)
 				if (!err)
-					isr_setup_status_phase(udc);
+					isr_setup_status_phase(ci);
 			} else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
 			} else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
 				if (req.wLength != 0)
 				if (req.wLength != 0)
 					break;
 					break;
 				switch (le16_to_cpu(req.wValue)) {
 				switch (le16_to_cpu(req.wValue)) {
 				case USB_DEVICE_REMOTE_WAKEUP:
 				case USB_DEVICE_REMOTE_WAKEUP:
-					udc->remote_wakeup = 1;
-					err = isr_setup_status_phase(udc);
+					ci->remote_wakeup = 1;
+					err = isr_setup_status_phase(ci);
 					break;
 					break;
 				case USB_DEVICE_TEST_MODE:
 				case USB_DEVICE_TEST_MODE:
 					tmode = le16_to_cpu(req.wIndex) >> 8;
 					tmode = le16_to_cpu(req.wIndex) >> 8;
@@ -954,9 +955,9 @@ __acquires(udc->lock)
 					case TEST_SE0_NAK:
 					case TEST_SE0_NAK:
 					case TEST_PACKET:
 					case TEST_PACKET:
 					case TEST_FORCE_EN:
 					case TEST_FORCE_EN:
-						udc->test_mode = tmode;
+						ci->test_mode = tmode;
 						err = isr_setup_status_phase(
 						err = isr_setup_status_phase(
-								udc);
+								ci);
 						break;
 						break;
 					default:
 					default:
 						break;
 						break;
@@ -971,21 +972,21 @@ __acquires(udc->lock)
 		default:
 		default:
 delegate:
 delegate:
 			if (req.wLength == 0)   /* no data phase */
 			if (req.wLength == 0)   /* no data phase */
-				udc->ep0_dir = TX;
+				ci->ep0_dir = TX;
 
 
-			spin_unlock(&udc->lock);
-			err = udc->driver->setup(&udc->gadget, &req);
-			spin_lock(&udc->lock);
+			spin_unlock(&ci->lock);
+			err = ci->driver->setup(&ci->gadget, &req);
+			spin_lock(&ci->lock);
 			break;
 			break;
 		}
 		}
 
 
 		if (err < 0) {
 		if (err < 0) {
 			dbg_event(_usb_addr(mEp), "ERROR", err);
 			dbg_event(_usb_addr(mEp), "ERROR", err);
 
 
-			spin_unlock(&udc->lock);
+			spin_unlock(&ci->lock);
 			if (usb_ep_set_halt(&mEp->ep))
 			if (usb_ep_set_halt(&mEp->ep))
-				dev_err(udc->dev, "error: ep_set_halt\n");
-			spin_lock(&udc->lock);
+				dev_err(ci->dev, "error: ep_set_halt\n");
+			spin_lock(&ci->lock);
 		}
 		}
 	}
 	}
 }
 }
@@ -1015,7 +1016,7 @@ static int ep_enable(struct usb_ep *ep,
 	mEp->ep.desc = desc;
 	mEp->ep.desc = desc;
 
 
 	if (!list_empty(&mEp->qh.queue))
 	if (!list_empty(&mEp->qh.queue))
-		dev_warn(mEp->udc->dev, "enabling a non-empty endpoint!\n");
+		dev_warn(mEp->ci->dev, "enabling a non-empty endpoint!\n");
 
 
 	mEp->dir  = usb_endpoint_dir_in(desc) ? TX : RX;
 	mEp->dir  = usb_endpoint_dir_in(desc) ? TX : RX;
 	mEp->num  = usb_endpoint_num(desc);
 	mEp->num  = usb_endpoint_num(desc);
@@ -1043,7 +1044,7 @@ static int ep_enable(struct usb_ep *ep,
 	 * is always enabled
 	 * is always enabled
 	 */
 	 */
 	if (mEp->num)
 	if (mEp->num)
-		retval |= hw_ep_enable(mEp->udc, mEp->num, mEp->dir, mEp->type);
+		retval |= hw_ep_enable(mEp->ci, mEp->num, mEp->dir, mEp->type);
 
 
 	spin_unlock_irqrestore(mEp->lock, flags);
 	spin_unlock_irqrestore(mEp->lock, flags);
 	return retval;
 	return retval;
@@ -1074,7 +1075,7 @@ static int ep_disable(struct usb_ep *ep)
 		dbg_event(_usb_addr(mEp), "DISABLE", 0);
 		dbg_event(_usb_addr(mEp), "DISABLE", 0);
 
 
 		retval |= _ep_nuke(mEp);
 		retval |= _ep_nuke(mEp);
-		retval |= hw_ep_disable(mEp->udc, mEp->num, mEp->dir);
+		retval |= hw_ep_disable(mEp->ci, mEp->num, mEp->dir);
 
 
 		if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
 		if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
 			mEp->dir = (mEp->dir == TX) ? RX : TX;
 			mEp->dir = (mEp->dir == TX) ? RX : TX;
@@ -1131,7 +1132,7 @@ static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
 	if (ep == NULL || req == NULL) {
 	if (ep == NULL || req == NULL) {
 		return;
 		return;
 	} else if (!list_empty(&mReq->queue)) {
 	} else if (!list_empty(&mReq->queue)) {
-		dev_err(mEp->udc->dev, "freeing queued request\n");
+		dev_err(mEp->ci->dev, "freeing queued request\n");
 		return;
 		return;
 	}
 	}
 
 
@@ -1156,7 +1157,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
 {
 {
 	struct ci13xxx_ep  *mEp  = container_of(ep,  struct ci13xxx_ep, ep);
 	struct ci13xxx_ep  *mEp  = container_of(ep,  struct ci13xxx_ep, ep);
 	struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
 	struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
-	struct ci13xxx *udc = mEp->udc;
+	struct ci13xxx *ci = mEp->ci;
 	int retval = 0;
 	int retval = 0;
 	unsigned long flags;
 	unsigned long flags;
 
 
@@ -1167,12 +1168,12 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
 
 
 	if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
 	if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
 		if (req->length)
 		if (req->length)
-			mEp = (udc->ep0_dir == RX) ?
-			       udc->ep0out : udc->ep0in;
+			mEp = (ci->ep0_dir == RX) ?
+			       ci->ep0out : ci->ep0in;
 		if (!list_empty(&mEp->qh.queue)) {
 		if (!list_empty(&mEp->qh.queue)) {
 			_ep_nuke(mEp);
 			_ep_nuke(mEp);
 			retval = -EOVERFLOW;
 			retval = -EOVERFLOW;
-			dev_warn(mEp->udc->dev, "endpoint ctrl %X nuked\n",
+			dev_warn(mEp->ci->dev, "endpoint ctrl %X nuked\n",
 				 _usb_addr(mEp));
 				 _usb_addr(mEp));
 		}
 		}
 	}
 	}
@@ -1180,14 +1181,14 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
 	/* first nuke then test link, e.g. previous status has not sent */
 	/* first nuke then test link, e.g. previous status has not sent */
 	if (!list_empty(&mReq->queue)) {
 	if (!list_empty(&mReq->queue)) {
 		retval = -EBUSY;
 		retval = -EBUSY;
-		dev_err(mEp->udc->dev, "request already in queue\n");
+		dev_err(mEp->ci->dev, "request already in queue\n");
 		goto done;
 		goto done;
 	}
 	}
 
 
 	if (req->length > 4 * CI13XXX_PAGE_SIZE) {
 	if (req->length > 4 * CI13XXX_PAGE_SIZE) {
 		req->length = 4 * CI13XXX_PAGE_SIZE;
 		req->length = 4 * CI13XXX_PAGE_SIZE;
 		retval = -EMSGSIZE;
 		retval = -EMSGSIZE;
-		dev_warn(mEp->udc->dev, "request length truncated\n");
+		dev_warn(mEp->ci->dev, "request length truncated\n");
 	}
 	}
 
 
 	dbg_queue(_usb_addr(mEp), req, retval);
 	dbg_queue(_usb_addr(mEp), req, retval);
@@ -1230,12 +1231,12 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
 
 
 	dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
 	dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
 
 
-	hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
+	hw_ep_flush(mEp->ci, mEp->num, mEp->dir);
 
 
 	/* pop request */
 	/* pop request */
 	list_del_init(&mReq->queue);
 	list_del_init(&mReq->queue);
 
 
-	usb_gadget_unmap_request(&mEp->udc->gadget, req, mEp->dir);
+	usb_gadget_unmap_request(&mEp->ci->gadget, req, mEp->dir);
 
 
 	req->status = -ECONNRESET;
 	req->status = -ECONNRESET;
 
 
@@ -1277,7 +1278,7 @@ static int ep_set_halt(struct usb_ep *ep, int value)
 	direction = mEp->dir;
 	direction = mEp->dir;
 	do {
 	do {
 		dbg_event(_usb_addr(mEp), "HALT", value);
 		dbg_event(_usb_addr(mEp), "HALT", value);
-		retval |= hw_ep_set_halt(mEp->udc, mEp->num, mEp->dir, value);
+		retval |= hw_ep_set_halt(mEp->ci, mEp->num, mEp->dir, value);
 
 
 		if (!value)
 		if (!value)
 			mEp->wedge = 0;
 			mEp->wedge = 0;
@@ -1325,14 +1326,14 @@ static void ep_fifo_flush(struct usb_ep *ep)
 	unsigned long flags;
 	unsigned long flags;
 
 
 	if (ep == NULL) {
 	if (ep == NULL) {
-		dev_err(mEp->udc->dev, "%02X: -EINVAL\n", _usb_addr(mEp));
+		dev_err(mEp->ci->dev, "%02X: -EINVAL\n", _usb_addr(mEp));
 		return;
 		return;
 	}
 	}
 
 
 	spin_lock_irqsave(mEp->lock, flags);
 	spin_lock_irqsave(mEp->lock, flags);
 
 
 	dbg_event(_usb_addr(mEp), "FFLUSH", 0);
 	dbg_event(_usb_addr(mEp), "FFLUSH", 0);
-	hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
+	hw_ep_flush(mEp->ci, mEp->num, mEp->dir);
 
 
 	spin_unlock_irqrestore(mEp->lock, flags);
 	spin_unlock_irqrestore(mEp->lock, flags);
 }
 }
@@ -1358,30 +1359,30 @@ static const struct usb_ep_ops usb_ep_ops = {
  *****************************************************************************/
  *****************************************************************************/
 static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
 static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
 {
 {
-	struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+	struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget);
 	unsigned long flags;
 	unsigned long flags;
 	int gadget_ready = 0;
 	int gadget_ready = 0;
 
 
-	if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
+	if (!(ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS))
 		return -EOPNOTSUPP;
 		return -EOPNOTSUPP;
 
 
-	spin_lock_irqsave(&udc->lock, flags);
-	udc->vbus_active = is_active;
-	if (udc->driver)
+	spin_lock_irqsave(&ci->lock, flags);
+	ci->vbus_active = is_active;
+	if (ci->driver)
 		gadget_ready = 1;
 		gadget_ready = 1;
-	spin_unlock_irqrestore(&udc->lock, flags);
+	spin_unlock_irqrestore(&ci->lock, flags);
 
 
 	if (gadget_ready) {
 	if (gadget_ready) {
 		if (is_active) {
 		if (is_active) {
 			pm_runtime_get_sync(&_gadget->dev);
 			pm_runtime_get_sync(&_gadget->dev);
-			hw_device_reset(udc, USBMODE_CM_DC);
-			hw_device_state(udc, udc->ep0out->qh.dma);
+			hw_device_reset(ci, USBMODE_CM_DC);
+			hw_device_state(ci, ci->ep0out->qh.dma);
 		} else {
 		} else {
-			hw_device_state(udc, 0);
-			if (udc->udc_driver->notify_event)
-				udc->udc_driver->notify_event(udc,
+			hw_device_state(ci, 0);
+			if (ci->platdata->notify_event)
+				ci->platdata->notify_event(ci,
 				CI13XXX_CONTROLLER_STOPPED_EVENT);
 				CI13XXX_CONTROLLER_STOPPED_EVENT);
-			_gadget_stop_activity(&udc->gadget);
+			_gadget_stop_activity(&ci->gadget);
 			pm_runtime_put_sync(&_gadget->dev);
 			pm_runtime_put_sync(&_gadget->dev);
 		}
 		}
 	}
 	}
@@ -1391,31 +1392,31 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
 
 
 static int ci13xxx_wakeup(struct usb_gadget *_gadget)
 static int ci13xxx_wakeup(struct usb_gadget *_gadget)
 {
 {
-	struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+	struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget);
 	unsigned long flags;
 	unsigned long flags;
 	int ret = 0;
 	int ret = 0;
 
 
-	spin_lock_irqsave(&udc->lock, flags);
-	if (!udc->remote_wakeup) {
+	spin_lock_irqsave(&ci->lock, flags);
+	if (!ci->remote_wakeup) {
 		ret = -EOPNOTSUPP;
 		ret = -EOPNOTSUPP;
 		goto out;
 		goto out;
 	}
 	}
-	if (!hw_read(udc, OP_PORTSC, PORTSC_SUSP)) {
+	if (!hw_read(ci, OP_PORTSC, PORTSC_SUSP)) {
 		ret = -EINVAL;
 		ret = -EINVAL;
 		goto out;
 		goto out;
 	}
 	}
-	hw_write(udc, OP_PORTSC, PORTSC_FPR, PORTSC_FPR);
+	hw_write(ci, OP_PORTSC, PORTSC_FPR, PORTSC_FPR);
 out:
 out:
-	spin_unlock_irqrestore(&udc->lock, flags);
+	spin_unlock_irqrestore(&ci->lock, flags);
 	return ret;
 	return ret;
 }
 }
 
 
 static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
 static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
 {
 {
-	struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+	struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget);
 
 
-	if (udc->transceiver)
-		return usb_phy_set_power(udc->transceiver, mA);
+	if (ci->transceiver)
+		return usb_phy_set_power(ci->transceiver, mA);
 	return -ENOTSUPP;
 	return -ENOTSUPP;
 }
 }
 
 
@@ -1436,28 +1437,28 @@ static const struct usb_gadget_ops usb_gadget_ops = {
 	.udc_stop	= ci13xxx_stop,
 	.udc_stop	= ci13xxx_stop,
 };
 };
 
 
-static int init_eps(struct ci13xxx *udc)
+static int init_eps(struct ci13xxx *ci)
 {
 {
 	int retval = 0, i, j;
 	int retval = 0, i, j;
 
 
-	for (i = 0; i < udc->hw_ep_max/2; i++)
+	for (i = 0; i < ci->hw_ep_max/2; i++)
 		for (j = RX; j <= TX; j++) {
 		for (j = RX; j <= TX; j++) {
-			int k = i + j * udc->hw_ep_max/2;
-			struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
+			int k = i + j * ci->hw_ep_max/2;
+			struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[k];
 
 
 			scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
 			scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
 					(j == TX)  ? "in" : "out");
 					(j == TX)  ? "in" : "out");
 
 
-			mEp->udc          = udc;
-			mEp->lock         = &udc->lock;
-			mEp->td_pool      = udc->td_pool;
+			mEp->ci          = ci;
+			mEp->lock         = &ci->lock;
+			mEp->td_pool      = ci->td_pool;
 
 
 			mEp->ep.name      = mEp->name;
 			mEp->ep.name      = mEp->name;
 			mEp->ep.ops       = &usb_ep_ops;
 			mEp->ep.ops       = &usb_ep_ops;
 			mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
 			mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
 
 
 			INIT_LIST_HEAD(&mEp->qh.queue);
 			INIT_LIST_HEAD(&mEp->qh.queue);
-			mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
+			mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL,
 						     &mEp->qh.dma);
 						     &mEp->qh.dma);
 			if (mEp->qh.ptr == NULL)
 			if (mEp->qh.ptr == NULL)
 				retval = -ENOMEM;
 				retval = -ENOMEM;
@@ -1470,14 +1471,14 @@ static int init_eps(struct ci13xxx *udc)
 			 */
 			 */
 			if (i == 0) {
 			if (i == 0) {
 				if (j == RX)
 				if (j == RX)
-					udc->ep0out = mEp;
+					ci->ep0out = mEp;
 				else
 				else
-					udc->ep0in = mEp;
+					ci->ep0in = mEp;
 
 
 				continue;
 				continue;
 			}
 			}
 
 
-			list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
+			list_add_tail(&mEp->ep.ep_list, &ci->gadget.ep_list);
 		}
 		}
 
 
 	return retval;
 	return retval;
@@ -1493,7 +1494,7 @@ static int init_eps(struct ci13xxx *udc)
 static int ci13xxx_start(struct usb_gadget *gadget,
 static int ci13xxx_start(struct usb_gadget *gadget,
 			 struct usb_gadget_driver *driver)
 			 struct usb_gadget_driver *driver)
 {
 {
-	struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
+	struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget);
 	unsigned long flags;
 	unsigned long flags;
 	int retval = -ENOMEM;
 	int retval = -ENOMEM;
 
 
@@ -1501,35 +1502,35 @@ static int ci13xxx_start(struct usb_gadget *gadget,
 		return -EINVAL;
 		return -EINVAL;
 
 
 
 
-	udc->ep0out->ep.desc = &ctrl_endpt_out_desc;
-	retval = usb_ep_enable(&udc->ep0out->ep);
+	ci->ep0out->ep.desc = &ctrl_endpt_out_desc;
+	retval = usb_ep_enable(&ci->ep0out->ep);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 
-	udc->ep0in->ep.desc = &ctrl_endpt_in_desc;
-	retval = usb_ep_enable(&udc->ep0in->ep);
+	ci->ep0in->ep.desc = &ctrl_endpt_in_desc;
+	retval = usb_ep_enable(&ci->ep0in->ep);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
-	spin_lock_irqsave(&udc->lock, flags);
-
-	udc->driver = driver;
-	pm_runtime_get_sync(&udc->gadget.dev);
-	if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
-		if (udc->vbus_active) {
-			if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
-				hw_device_reset(udc, USBMODE_CM_DC);
+	spin_lock_irqsave(&ci->lock, flags);
+
+	ci->driver = driver;
+	pm_runtime_get_sync(&ci->gadget.dev);
+	if (ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) {
+		if (ci->vbus_active) {
+			if (ci->platdata->flags & CI13XXX_REGS_SHARED)
+				hw_device_reset(ci, USBMODE_CM_DC);
 		} else {
 		} else {
-			pm_runtime_put_sync(&udc->gadget.dev);
+			pm_runtime_put_sync(&ci->gadget.dev);
 			goto done;
 			goto done;
 		}
 		}
 	}
 	}
 
 
-	retval = hw_device_state(udc, udc->ep0out->qh.dma);
+	retval = hw_device_state(ci, ci->ep0out->qh.dma);
 	if (retval)
 	if (retval)
-		pm_runtime_put_sync(&udc->gadget.dev);
+		pm_runtime_put_sync(&ci->gadget.dev);
 
 
  done:
  done:
-	spin_unlock_irqrestore(&udc->lock, flags);
+	spin_unlock_irqrestore(&ci->lock, flags);
 	return retval;
 	return retval;
 }
 }
 
 
@@ -1539,25 +1540,25 @@ static int ci13xxx_start(struct usb_gadget *gadget,
 static int ci13xxx_stop(struct usb_gadget *gadget,
 static int ci13xxx_stop(struct usb_gadget *gadget,
 			struct usb_gadget_driver *driver)
 			struct usb_gadget_driver *driver)
 {
 {
-	struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
+	struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget);
 	unsigned long flags;
 	unsigned long flags;
 
 
-	spin_lock_irqsave(&udc->lock, flags);
+	spin_lock_irqsave(&ci->lock, flags);
 
 
-	if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
-			udc->vbus_active) {
-		hw_device_state(udc, 0);
-		if (udc->udc_driver->notify_event)
-			udc->udc_driver->notify_event(udc,
+	if (!(ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) ||
+			ci->vbus_active) {
+		hw_device_state(ci, 0);
+		if (ci->platdata->notify_event)
+			ci->platdata->notify_event(ci,
 			CI13XXX_CONTROLLER_STOPPED_EVENT);
 			CI13XXX_CONTROLLER_STOPPED_EVENT);
-		udc->driver = NULL;
-		spin_unlock_irqrestore(&udc->lock, flags);
-		_gadget_stop_activity(&udc->gadget);
-		spin_lock_irqsave(&udc->lock, flags);
-		pm_runtime_put(&udc->gadget.dev);
+		ci->driver = NULL;
+		spin_unlock_irqrestore(&ci->lock, flags);
+		_gadget_stop_activity(&ci->gadget);
+		spin_lock_irqsave(&ci->lock, flags);
+		pm_runtime_put(&ci->gadget.dev);
 	}
 	}
 
 
-	spin_unlock_irqrestore(&udc->lock, flags);
+	spin_unlock_irqrestore(&ci->lock, flags);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1566,64 +1567,64 @@ static int ci13xxx_stop(struct usb_gadget *gadget,
  * BUS block
  * BUS block
  *****************************************************************************/
  *****************************************************************************/
 /**
 /**
- * udc_irq: udc interrupt handler
+ * udc_irq: ci interrupt handler
  *
  *
  * This function returns IRQ_HANDLED if the IRQ has been handled
  * This function returns IRQ_HANDLED if the IRQ has been handled
  * It locks access to registers
  * It locks access to registers
  */
  */
-static irqreturn_t udc_irq(struct ci13xxx *udc)
+static irqreturn_t udc_irq(struct ci13xxx *ci)
 {
 {
 	irqreturn_t retval;
 	irqreturn_t retval;
 	u32 intr;
 	u32 intr;
 
 
-	if (udc == NULL)
+	if (ci == NULL)
 		return IRQ_HANDLED;
 		return IRQ_HANDLED;
 
 
-	spin_lock(&udc->lock);
+	spin_lock(&ci->lock);
 
 
-	if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
-		if (hw_read(udc, OP_USBMODE, USBMODE_CM) !=
+	if (ci->platdata->flags & CI13XXX_REGS_SHARED) {
+		if (hw_read(ci, OP_USBMODE, USBMODE_CM) !=
 				USBMODE_CM_DC) {
 				USBMODE_CM_DC) {
-			spin_unlock(&udc->lock);
+			spin_unlock(&ci->lock);
 			return IRQ_NONE;
 			return IRQ_NONE;
 		}
 		}
 	}
 	}
-	intr = hw_test_and_clear_intr_active(udc);
+	intr = hw_test_and_clear_intr_active(ci);
 	dbg_interrupt(intr);
 	dbg_interrupt(intr);
 
 
 	if (intr) {
 	if (intr) {
 		/* order defines priority - do NOT change it */
 		/* order defines priority - do NOT change it */
 		if (USBi_URI & intr)
 		if (USBi_URI & intr)
-			isr_reset_handler(udc);
+			isr_reset_handler(ci);
 
 
 		if (USBi_PCI & intr) {
 		if (USBi_PCI & intr) {
-			udc->gadget.speed = hw_port_is_high_speed(udc) ?
+			ci->gadget.speed = hw_port_is_high_speed(ci) ?
 				USB_SPEED_HIGH : USB_SPEED_FULL;
 				USB_SPEED_HIGH : USB_SPEED_FULL;
-			if (udc->suspended && udc->driver->resume) {
-				spin_unlock(&udc->lock);
-				udc->driver->resume(&udc->gadget);
-				spin_lock(&udc->lock);
-				udc->suspended = 0;
+			if (ci->suspended && ci->driver->resume) {
+				spin_unlock(&ci->lock);
+				ci->driver->resume(&ci->gadget);
+				spin_lock(&ci->lock);
+				ci->suspended = 0;
 			}
 			}
 		}
 		}
 
 
 		if (USBi_UI  & intr)
 		if (USBi_UI  & intr)
-			isr_tr_complete_handler(udc);
+			isr_tr_complete_handler(ci);
 
 
 		if (USBi_SLI & intr) {
 		if (USBi_SLI & intr) {
-			if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
-			    udc->driver->suspend) {
-				udc->suspended = 1;
-				spin_unlock(&udc->lock);
-				udc->driver->suspend(&udc->gadget);
-				spin_lock(&udc->lock);
+			if (ci->gadget.speed != USB_SPEED_UNKNOWN &&
+			    ci->driver->suspend) {
+				ci->suspended = 1;
+				spin_unlock(&ci->lock);
+				ci->driver->suspend(&ci->gadget);
+				spin_lock(&ci->lock);
 			}
 			}
 		}
 		}
 		retval = IRQ_HANDLED;
 		retval = IRQ_HANDLED;
 	} else {
 	} else {
 		retval = IRQ_NONE;
 		retval = IRQ_NONE;
 	}
 	}
-	spin_unlock(&udc->lock);
+	spin_unlock(&ci->lock);
 
 
 	return retval;
 	return retval;
 }
 }
@@ -1640,112 +1641,111 @@ static void udc_release(struct device *dev)
 
 
 /**
 /**
  * udc_start: initialize gadget role
  * udc_start: initialize gadget role
- * @udc: chipidea controller
+ * @ci: chipidea controller
  */
  */
-static int udc_start(struct ci13xxx *udc)
+static int udc_start(struct ci13xxx *ci)
 {
 {
-	struct device *dev = udc->dev;
+	struct device *dev = ci->dev;
 	int retval = 0;
 	int retval = 0;
 
 
-	if (!udc)
-		return -EINVAL;
-
-	spin_lock_init(&udc->lock);
+	spin_lock_init(&ci->lock);
 
 
-	udc->gadget.ops          = &usb_gadget_ops;
-	udc->gadget.speed        = USB_SPEED_UNKNOWN;
-	udc->gadget.max_speed    = USB_SPEED_HIGH;
-	udc->gadget.is_otg       = 0;
-	udc->gadget.name         = udc->udc_driver->name;
+	ci->gadget.ops          = &usb_gadget_ops;
+	ci->gadget.speed        = USB_SPEED_UNKNOWN;
+	ci->gadget.max_speed    = USB_SPEED_HIGH;
+	ci->gadget.is_otg       = 0;
+	ci->gadget.name         = ci->platdata->name;
 
 
-	INIT_LIST_HEAD(&udc->gadget.ep_list);
+	INIT_LIST_HEAD(&ci->gadget.ep_list);
 
 
-	dev_set_name(&udc->gadget.dev, "gadget");
-	udc->gadget.dev.dma_mask = dev->dma_mask;
-	udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
-	udc->gadget.dev.parent   = dev;
-	udc->gadget.dev.release  = udc_release;
+	dev_set_name(&ci->gadget.dev, "gadget");
+	ci->gadget.dev.dma_mask = dev->dma_mask;
+	ci->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
+	ci->gadget.dev.parent   = dev;
+	ci->gadget.dev.release  = udc_release;
 
 
 	/* alloc resources */
 	/* alloc resources */
-	udc->qh_pool = dma_pool_create("ci13xxx_qh", dev,
+	ci->qh_pool = dma_pool_create("ci13xxx_qh", dev,
 				       sizeof(struct ci13xxx_qh),
 				       sizeof(struct ci13xxx_qh),
 				       64, CI13XXX_PAGE_SIZE);
 				       64, CI13XXX_PAGE_SIZE);
-	if (udc->qh_pool == NULL)
+	if (ci->qh_pool == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	udc->td_pool = dma_pool_create("ci13xxx_td", dev,
+	ci->td_pool = dma_pool_create("ci13xxx_td", dev,
 				       sizeof(struct ci13xxx_td),
 				       sizeof(struct ci13xxx_td),
 				       64, CI13XXX_PAGE_SIZE);
 				       64, CI13XXX_PAGE_SIZE);
-	if (udc->td_pool == NULL) {
+	if (ci->td_pool == NULL) {
 		retval = -ENOMEM;
 		retval = -ENOMEM;
 		goto free_qh_pool;
 		goto free_qh_pool;
 	}
 	}
 
 
-	retval = init_eps(udc);
+	retval = init_eps(ci);
 	if (retval)
 	if (retval)
 		goto free_pools;
 		goto free_pools;
 
 
-	udc->gadget.ep0 = &udc->ep0in->ep;
+	ci->gadget.ep0 = &ci->ep0in->ep;
 
 
-	udc->transceiver = usb_get_transceiver();
+	if (ci->global_phy)
+		ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 
 
-	if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
-		if (udc->transceiver == NULL) {
+	if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
+		if (ci->transceiver == NULL) {
 			retval = -ENODEV;
 			retval = -ENODEV;
 			goto free_pools;
 			goto free_pools;
 		}
 		}
 	}
 	}
 
 
-	if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
-		retval = hw_device_reset(udc, USBMODE_CM_DC);
+	if (!(ci->platdata->flags & CI13XXX_REGS_SHARED)) {
+		retval = hw_device_reset(ci, USBMODE_CM_DC);
 		if (retval)
 		if (retval)
 			goto put_transceiver;
 			goto put_transceiver;
 	}
 	}
 
 
-	retval = device_register(&udc->gadget.dev);
+	retval = device_register(&ci->gadget.dev);
 	if (retval) {
 	if (retval) {
-		put_device(&udc->gadget.dev);
+		put_device(&ci->gadget.dev);
 		goto put_transceiver;
 		goto put_transceiver;
 	}
 	}
 
 
-	retval = dbg_create_files(&udc->gadget.dev);
+	retval = dbg_create_files(&ci->gadget.dev);
 	if (retval)
 	if (retval)
 		goto unreg_device;
 		goto unreg_device;
 
 
-	if (udc->transceiver) {
-		retval = otg_set_peripheral(udc->transceiver->otg,
-						&udc->gadget);
+	if (!IS_ERR_OR_NULL(ci->transceiver)) {
+		retval = otg_set_peripheral(ci->transceiver->otg,
+						&ci->gadget);
 		if (retval)
 		if (retval)
 			goto remove_dbg;
 			goto remove_dbg;
 	}
 	}
 
 
-	retval = usb_add_gadget_udc(dev, &udc->gadget);
+	retval = usb_add_gadget_udc(dev, &ci->gadget);
 	if (retval)
 	if (retval)
 		goto remove_trans;
 		goto remove_trans;
 
 
-	pm_runtime_no_callbacks(&udc->gadget.dev);
-	pm_runtime_enable(&udc->gadget.dev);
+	pm_runtime_no_callbacks(&ci->gadget.dev);
+	pm_runtime_enable(&ci->gadget.dev);
 
 
 	return retval;
 	return retval;
 
 
 remove_trans:
 remove_trans:
-	if (udc->transceiver) {
-		otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
-		usb_put_transceiver(udc->transceiver);
+	if (!IS_ERR_OR_NULL(ci->transceiver)) {
+		otg_set_peripheral(ci->transceiver->otg, &ci->gadget);
+		if (ci->global_phy)
+			usb_put_phy(ci->transceiver);
 	}
 	}
 
 
 	dev_err(dev, "error = %i\n", retval);
 	dev_err(dev, "error = %i\n", retval);
 remove_dbg:
 remove_dbg:
-	dbg_remove_files(&udc->gadget.dev);
+	dbg_remove_files(&ci->gadget.dev);
 unreg_device:
 unreg_device:
-	device_unregister(&udc->gadget.dev);
+	device_unregister(&ci->gadget.dev);
 put_transceiver:
 put_transceiver:
-	if (udc->transceiver)
-		usb_put_transceiver(udc->transceiver);
+	if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)
+		usb_put_phy(ci->transceiver);
 free_pools:
 free_pools:
-	dma_pool_destroy(udc->td_pool);
+	dma_pool_destroy(ci->td_pool);
 free_qh_pool:
 free_qh_pool:
-	dma_pool_destroy(udc->qh_pool);
+	dma_pool_destroy(ci->qh_pool);
 	return retval;
 	return retval;
 }
 }
 
 
@@ -1754,32 +1754,33 @@ free_qh_pool:
  *
  *
  * No interrupts active, the IRQ has been released
  * No interrupts active, the IRQ has been released
  */
  */
-static void udc_stop(struct ci13xxx *udc)
+static void udc_stop(struct ci13xxx *ci)
 {
 {
 	int i;
 	int i;
 
 
-	if (udc == NULL)
+	if (ci == NULL)
 		return;
 		return;
 
 
-	usb_del_gadget_udc(&udc->gadget);
+	usb_del_gadget_udc(&ci->gadget);
 
 
-	for (i = 0; i < udc->hw_ep_max; i++) {
-		struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
+	for (i = 0; i < ci->hw_ep_max; i++) {
+		struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i];
 
 
-		dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
+		dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma);
 	}
 	}
 
 
-	dma_pool_destroy(udc->td_pool);
-	dma_pool_destroy(udc->qh_pool);
+	dma_pool_destroy(ci->td_pool);
+	dma_pool_destroy(ci->qh_pool);
 
 
-	if (udc->transceiver) {
-		otg_set_peripheral(udc->transceiver->otg, NULL);
-		usb_put_transceiver(udc->transceiver);
+	if (!IS_ERR_OR_NULL(ci->transceiver)) {
+		otg_set_peripheral(ci->transceiver->otg, NULL);
+		if (ci->global_phy)
+			usb_put_phy(ci->transceiver);
 	}
 	}
-	dbg_remove_files(&udc->gadget.dev);
-	device_unregister(&udc->gadget.dev);
+	dbg_remove_files(&ci->gadget.dev);
+	device_unregister(&ci->gadget.dev);
 	/* my kobject is dynamic, I swear! */
 	/* my kobject is dynamic, I swear! */
-	memset(&udc->gadget, 0, sizeof(udc->gadget));
+	memset(&ci->gadget, 0, sizeof(ci->gadget));
 }
 }
 
 
 /**
 /**

+ 1 - 1
drivers/usb/class/cdc-acm.c

@@ -996,7 +996,7 @@ static int acm_probe(struct usb_interface *intf,
 		case USB_CDC_CALL_MANAGEMENT_TYPE:
 		case USB_CDC_CALL_MANAGEMENT_TYPE:
 			call_management_function = buffer[3];
 			call_management_function = buffer[3];
 			call_interface_num = buffer[4];
 			call_interface_num = buffer[4];
-			if ( (quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3)
+			if ((quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3)
 				dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n");
 				dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n");
 			break;
 			break;
 		default:
 		default:

+ 0 - 25
drivers/usb/class/cdc-wdm.c

@@ -32,8 +32,6 @@
 #define DRIVER_AUTHOR "Oliver Neukum"
 #define DRIVER_AUTHOR "Oliver Neukum"
 #define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management"
 #define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management"
 
 
-#define HUAWEI_VENDOR_ID	0x12D1
-
 static const struct usb_device_id wdm_ids[] = {
 static const struct usb_device_id wdm_ids[] = {
 	{
 	{
 		.match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
 		.match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
@@ -41,29 +39,6 @@ static const struct usb_device_id wdm_ids[] = {
 		.bInterfaceClass = USB_CLASS_COMM,
 		.bInterfaceClass = USB_CLASS_COMM,
 		.bInterfaceSubClass = USB_CDC_SUBCLASS_DMM
 		.bInterfaceSubClass = USB_CDC_SUBCLASS_DMM
 	},
 	},
-	{
-		/* 
-		 * Huawei E392, E398 and possibly other Qualcomm based modems
-		 * embed the Qualcomm QMI protocol inside CDC on CDC ECM like
-		 * control interfaces.  Userspace access to this is required
-		 * to configure the accompanying data interface
-		 */
-		.match_flags        = USB_DEVICE_ID_MATCH_VENDOR |
-					USB_DEVICE_ID_MATCH_INT_INFO,
-		.idVendor           = HUAWEI_VENDOR_ID,
-		.bInterfaceClass    = USB_CLASS_VENDOR_SPEC,
-		.bInterfaceSubClass = 1,
-		.bInterfaceProtocol = 9, /* NOTE: CDC ECM control interface! */
-	},
-	{
-		 /* Vodafone/Huawei K5005 (12d1:14c8) and similar modems */
-		.match_flags        = USB_DEVICE_ID_MATCH_VENDOR |
-				      USB_DEVICE_ID_MATCH_INT_INFO,
-		.idVendor           = HUAWEI_VENDOR_ID,
-		.bInterfaceClass    = USB_CLASS_VENDOR_SPEC,
-		.bInterfaceSubClass = 1,
-		.bInterfaceProtocol = 57, /* NOTE: CDC ECM control interface! */
-	},
 	{ }
 	{ }
 };
 };
 
 

+ 140 - 29
drivers/usb/core/devio.c

@@ -47,6 +47,7 @@
 #include <linux/notifier.h>
 #include <linux/notifier.h>
 #include <linux/security.h>
 #include <linux/security.h>
 #include <linux/user_namespace.h>
 #include <linux/user_namespace.h>
+#include <linux/scatterlist.h>
 #include <asm/uaccess.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 #include <asm/byteorder.h>
 #include <linux/moduleparam.h>
 #include <linux/moduleparam.h>
@@ -55,6 +56,7 @@
 
 
 #define USB_MAXBUS			64
 #define USB_MAXBUS			64
 #define USB_DEVICE_MAX			USB_MAXBUS * 128
 #define USB_DEVICE_MAX			USB_MAXBUS * 128
+#define USB_SG_SIZE			16384 /* split-size for large txs */
 
 
 /* Mutual exclusion for removal, open, and release */
 /* Mutual exclusion for removal, open, and release */
 DEFINE_MUTEX(usbfs_mutex);
 DEFINE_MUTEX(usbfs_mutex);
@@ -285,9 +287,16 @@ static struct async *alloc_async(unsigned int numisoframes)
 
 
 static void free_async(struct async *as)
 static void free_async(struct async *as)
 {
 {
+	int i;
+
 	put_pid(as->pid);
 	put_pid(as->pid);
 	if (as->cred)
 	if (as->cred)
 		put_cred(as->cred);
 		put_cred(as->cred);
+	for (i = 0; i < as->urb->num_sgs; i++) {
+		if (sg_page(&as->urb->sg[i]))
+			kfree(sg_virt(&as->urb->sg[i]));
+	}
+	kfree(as->urb->sg);
 	kfree(as->urb->transfer_buffer);
 	kfree(as->urb->transfer_buffer);
 	kfree(as->urb->setup_packet);
 	kfree(as->urb->setup_packet);
 	usb_free_urb(as->urb);
 	usb_free_urb(as->urb);
@@ -388,6 +397,53 @@ static void snoop_urb(struct usb_device *udev,
 	}
 	}
 }
 }
 
 
+static void snoop_urb_data(struct urb *urb, unsigned len)
+{
+	int i, size;
+
+	if (!usbfs_snoop)
+		return;
+
+	if (urb->num_sgs == 0) {
+		print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, 32, 1,
+			urb->transfer_buffer, len, 1);
+		return;
+	}
+
+	for (i = 0; i < urb->num_sgs && len; i++) {
+		size = (len > USB_SG_SIZE) ? USB_SG_SIZE : len;
+		print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, 32, 1,
+			sg_virt(&urb->sg[i]), size, 1);
+		len -= size;
+	}
+}
+
+static int copy_urb_data_to_user(u8 __user *userbuffer, struct urb *urb)
+{
+	unsigned i, len, size;
+
+	if (urb->number_of_packets > 0)		/* Isochronous */
+		len = urb->transfer_buffer_length;
+	else					/* Non-Isoc */
+		len = urb->actual_length;
+
+	if (urb->num_sgs == 0) {
+		if (copy_to_user(userbuffer, urb->transfer_buffer, len))
+			return -EFAULT;
+		return 0;
+	}
+
+	for (i = 0; i < urb->num_sgs && len; i++) {
+		size = (len > USB_SG_SIZE) ? USB_SG_SIZE : len;
+		if (copy_to_user(userbuffer, sg_virt(&urb->sg[i]), size))
+			return -EFAULT;
+		userbuffer += size;
+		len -= size;
+	}
+
+	return 0;
+}
+
 #define AS_CONTINUATION	1
 #define AS_CONTINUATION	1
 #define AS_UNLINK	2
 #define AS_UNLINK	2
 
 
@@ -454,9 +510,10 @@ static void async_completed(struct urb *urb)
 	}
 	}
 	snoop(&urb->dev->dev, "urb complete\n");
 	snoop(&urb->dev->dev, "urb complete\n");
 	snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length,
 	snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length,
-			as->status, COMPLETE,
-			((urb->transfer_flags & URB_DIR_MASK) == USB_DIR_OUT) ?
-				NULL : urb->transfer_buffer, urb->actual_length);
+			as->status, COMPLETE, NULL, 0);
+	if ((urb->transfer_flags & URB_DIR_MASK) == USB_DIR_IN)
+		snoop_urb_data(urb, urb->actual_length);
+
 	if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET &&
 	if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET &&
 			as->status != -ENOENT)
 			as->status != -ENOENT)
 		cancel_bulk_urbs(ps, as->bulk_addr);
 		cancel_bulk_urbs(ps, as->bulk_addr);
@@ -1114,8 +1171,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 	struct async *as = NULL;
 	struct async *as = NULL;
 	struct usb_ctrlrequest *dr = NULL;
 	struct usb_ctrlrequest *dr = NULL;
 	unsigned int u, totlen, isofrmlen;
 	unsigned int u, totlen, isofrmlen;
-	int ret, ifnum = -1;
-	int is_in;
+	int i, ret, is_in, num_sgs = 0, ifnum = -1;
+	void *buf;
 
 
 	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP |
 	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP |
 				USBDEVFS_URB_SHORT_NOT_OK |
 				USBDEVFS_URB_SHORT_NOT_OK |
@@ -1199,6 +1256,9 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 			goto interrupt_urb;
 			goto interrupt_urb;
 		}
 		}
 		uurb->number_of_packets = 0;
 		uurb->number_of_packets = 0;
+		num_sgs = DIV_ROUND_UP(uurb->buffer_length, USB_SG_SIZE);
+		if (num_sgs == 1 || num_sgs > ps->dev->bus->sg_tablesize)
+			num_sgs = 0;
 		break;
 		break;
 
 
 	case USBDEVFS_URB_TYPE_INTERRUPT:
 	case USBDEVFS_URB_TYPE_INTERRUPT:
@@ -1255,26 +1315,67 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 		ret = -ENOMEM;
 		ret = -ENOMEM;
 		goto error;
 		goto error;
 	}
 	}
-	u += sizeof(struct async) + sizeof(struct urb) + uurb->buffer_length;
+
+	u += sizeof(struct async) + sizeof(struct urb) + uurb->buffer_length +
+	     num_sgs * sizeof(struct scatterlist);
 	ret = usbfs_increase_memory_usage(u);
 	ret = usbfs_increase_memory_usage(u);
 	if (ret)
 	if (ret)
 		goto error;
 		goto error;
 	as->mem_usage = u;
 	as->mem_usage = u;
 
 
-	if (uurb->buffer_length > 0) {
+	if (num_sgs) {
+		as->urb->sg = kmalloc(num_sgs * sizeof(struct scatterlist),
+				      GFP_KERNEL);
+		if (!as->urb->sg) {
+			ret = -ENOMEM;
+			goto error;
+		}
+		as->urb->num_sgs = num_sgs;
+		sg_init_table(as->urb->sg, as->urb->num_sgs);
+
+		totlen = uurb->buffer_length;
+		for (i = 0; i < as->urb->num_sgs; i++) {
+			u = (totlen > USB_SG_SIZE) ? USB_SG_SIZE : totlen;
+			buf = kmalloc(u, GFP_KERNEL);
+			if (!buf) {
+				ret = -ENOMEM;
+				goto error;
+			}
+			sg_set_buf(&as->urb->sg[i], buf, u);
+
+			if (!is_in) {
+				if (copy_from_user(buf, uurb->buffer, u)) {
+					ret = -EFAULT;
+					goto error;
+				}
+			}
+			totlen -= u;
+		}
+	} else if (uurb->buffer_length > 0) {
 		as->urb->transfer_buffer = kmalloc(uurb->buffer_length,
 		as->urb->transfer_buffer = kmalloc(uurb->buffer_length,
 				GFP_KERNEL);
 				GFP_KERNEL);
 		if (!as->urb->transfer_buffer) {
 		if (!as->urb->transfer_buffer) {
 			ret = -ENOMEM;
 			ret = -ENOMEM;
 			goto error;
 			goto error;
 		}
 		}
-		/* Isochronous input data may end up being discontiguous
-		 * if some of the packets are short.  Clear the buffer so
-		 * that the gaps don't leak kernel data to userspace.
-		 */
-		if (is_in && uurb->type == USBDEVFS_URB_TYPE_ISO)
+
+		if (!is_in) {
+			if (copy_from_user(as->urb->transfer_buffer,
+					   uurb->buffer,
+					   uurb->buffer_length)) {
+				ret = -EFAULT;
+				goto error;
+			}
+		} else if (uurb->type == USBDEVFS_URB_TYPE_ISO) {
+			/*
+			 * Isochronous input data may end up being
+			 * discontiguous if some of the packets are short.
+			 * Clear the buffer so that the gaps don't leak
+			 * kernel data to userspace.
+			 */
 			memset(as->urb->transfer_buffer, 0,
 			memset(as->urb->transfer_buffer, 0,
 					uurb->buffer_length);
 					uurb->buffer_length);
+		}
 	}
 	}
 	as->urb->dev = ps->dev;
 	as->urb->dev = ps->dev;
 	as->urb->pipe = (uurb->type << 30) |
 	as->urb->pipe = (uurb->type << 30) |
@@ -1328,17 +1429,12 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 	as->pid = get_pid(task_pid(current));
 	as->pid = get_pid(task_pid(current));
 	as->cred = get_current_cred();
 	as->cred = get_current_cred();
 	security_task_getsecid(current, &as->secid);
 	security_task_getsecid(current, &as->secid);
-	if (!is_in && uurb->buffer_length > 0) {
-		if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
-				uurb->buffer_length)) {
-			ret = -EFAULT;
-			goto error;
-		}
-	}
 	snoop_urb(ps->dev, as->userurb, as->urb->pipe,
 	snoop_urb(ps->dev, as->userurb, as->urb->pipe,
 			as->urb->transfer_buffer_length, 0, SUBMIT,
 			as->urb->transfer_buffer_length, 0, SUBMIT,
-			is_in ? NULL : as->urb->transfer_buffer,
-				uurb->buffer_length);
+			NULL, 0);
+	if (!is_in)
+		snoop_urb_data(as->urb, as->urb->transfer_buffer_length);
+
 	async_newpending(as);
 	async_newpending(as);
 
 
 	if (usb_endpoint_xfer_bulk(&ep->desc)) {
 	if (usb_endpoint_xfer_bulk(&ep->desc)) {
@@ -1433,11 +1529,7 @@ static int processcompl(struct async *as, void __user * __user *arg)
 	unsigned int i;
 	unsigned int i;
 
 
 	if (as->userbuffer && urb->actual_length) {
 	if (as->userbuffer && urb->actual_length) {
-		if (urb->number_of_packets > 0)		/* Isochronous */
-			i = urb->transfer_buffer_length;
-		else					/* Non-Isoc */
-			i = urb->actual_length;
-		if (copy_to_user(as->userbuffer, urb->transfer_buffer, i))
+		if (copy_urb_data_to_user(as->userbuffer, urb))
 			goto err_out;
 			goto err_out;
 	}
 	}
 	if (put_user(as->status, &userurb->status))
 	if (put_user(as->status, &userurb->status))
@@ -1604,10 +1696,10 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
 	void __user *addr = as->userurb;
 	void __user *addr = as->userurb;
 	unsigned int i;
 	unsigned int i;
 
 
-	if (as->userbuffer && urb->actual_length)
-		if (copy_to_user(as->userbuffer, urb->transfer_buffer,
-				 urb->actual_length))
+	if (as->userbuffer && urb->actual_length) {
+		if (copy_urb_data_to_user(as->userbuffer, urb))
 			return -EFAULT;
 			return -EFAULT;
+	}
 	if (put_user(as->status, &userurb->status))
 	if (put_user(as->status, &userurb->status))
 		return -EFAULT;
 		return -EFAULT;
 	if (put_user(urb->actual_length, &userurb->actual_length))
 	if (put_user(urb->actual_length, &userurb->actual_length))
@@ -1820,6 +1912,22 @@ static int proc_release_port(struct dev_state *ps, void __user *arg)
 	return usb_hub_release_port(ps->dev, portnum, ps);
 	return usb_hub_release_port(ps->dev, portnum, ps);
 }
 }
 
 
+static int proc_get_capabilities(struct dev_state *ps, void __user *arg)
+{
+	__u32 caps;
+
+	caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM;
+	if (!ps->dev->bus->no_stop_on_short)
+		caps |= USBDEVFS_CAP_BULK_CONTINUATION;
+	if (ps->dev->bus->sg_tablesize)
+		caps |= USBDEVFS_CAP_BULK_SCATTER_GATHER;
+
+	if (put_user(caps, (__u32 __user *)arg))
+		return -EFAULT;
+
+	return 0;
+}
+
 /*
 /*
  * NOTE:  All requests here that have interface numbers as parameters
  * NOTE:  All requests here that have interface numbers as parameters
  * are assuming that somehow the configuration has been prevented from
  * are assuming that somehow the configuration has been prevented from
@@ -1990,6 +2098,9 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
 		snoop(&dev->dev, "%s: RELEASE_PORT\n", __func__);
 		snoop(&dev->dev, "%s: RELEASE_PORT\n", __func__);
 		ret = proc_release_port(ps, p);
 		ret = proc_release_port(ps, p);
 		break;
 		break;
+	case USBDEVFS_GET_CAPABILITIES:
+		ret = proc_get_capabilities(ps, p);
+		break;
 	}
 	}
 	usb_unlock_device(dev);
 	usb_unlock_device(dev);
 	if (ret >= 0)
 	if (ret >= 0)

+ 8 - 2
drivers/usb/core/driver.c

@@ -367,6 +367,7 @@ static int usb_probe_interface(struct device *dev)
 	return error;
 	return error;
 
 
  err:
  err:
+	usb_set_intfdata(intf, NULL);
 	intf->needs_remote_wakeup = 0;
 	intf->needs_remote_wakeup = 0;
 	intf->condition = USB_INTERFACE_UNBOUND;
 	intf->condition = USB_INTERFACE_UNBOUND;
 	usb_cancel_queued_reset(intf);
 	usb_cancel_queued_reset(intf);
@@ -622,14 +623,15 @@ int usb_match_one_id(struct usb_interface *interface,
 	if (!usb_match_device(dev, id))
 	if (!usb_match_device(dev, id))
 		return 0;
 		return 0;
 
 
-	/* The interface class, subclass, and protocol should never be
+	/* The interface class, subclass, protocol and number should never be
 	 * checked for a match if the device class is Vendor Specific,
 	 * checked for a match if the device class is Vendor Specific,
 	 * unless the match record specifies the Vendor ID. */
 	 * unless the match record specifies the Vendor ID. */
 	if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC &&
 	if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC &&
 			!(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
 			!(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
 			(id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS |
 			(id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS |
 				USB_DEVICE_ID_MATCH_INT_SUBCLASS |
 				USB_DEVICE_ID_MATCH_INT_SUBCLASS |
-				USB_DEVICE_ID_MATCH_INT_PROTOCOL)))
+				USB_DEVICE_ID_MATCH_INT_PROTOCOL |
+				USB_DEVICE_ID_MATCH_INT_NUMBER)))
 		return 0;
 		return 0;
 
 
 	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
 	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
@@ -644,6 +646,10 @@ int usb_match_one_id(struct usb_interface *interface,
 	    (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
 	    (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
 		return 0;
 		return 0;
 
 
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER) &&
+	    (id->bInterfaceNumber != intf->desc.bInterfaceNumber))
+		return 0;
+
 	return 1;
 	return 1;
 }
 }
 EXPORT_SYMBOL_GPL(usb_match_one_id);
 EXPORT_SYMBOL_GPL(usb_match_one_id);

+ 1 - 1
drivers/usb/core/file.c

@@ -92,7 +92,7 @@ static int init_usb_class(void)
 	}
 	}
 
 
 	kref_init(&usb_class->kref);
 	kref_init(&usb_class->kref);
-	usb_class->class = class_create(THIS_MODULE, "usb");
+	usb_class->class = class_create(THIS_MODULE, "usbmisc");
 	if (IS_ERR(usb_class->class)) {
 	if (IS_ERR(usb_class->class)) {
 		result = IS_ERR(usb_class->class);
 		result = IS_ERR(usb_class->class);
 		printk(KERN_ERR "class_create failed for usb devices\n");
 		printk(KERN_ERR "class_create failed for usb devices\n");

+ 9 - 1
drivers/usb/core/hcd.c

@@ -1398,7 +1398,15 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
 	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
 	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
 		if (hcd->self.uses_dma) {
 		if (hcd->self.uses_dma) {
 			if (urb->num_sgs) {
 			if (urb->num_sgs) {
-				int n = dma_map_sg(
+				int n;
+
+				/* We don't support sg for isoc transfers ! */
+				if (usb_endpoint_xfer_isoc(&urb->ep->desc)) {
+					WARN_ON(1);
+					return -EINVAL;
+				}
+
+				n = dma_map_sg(
 						hcd->self.controller,
 						hcd->self.controller,
 						urb->sg,
 						urb->sg,
 						urb->num_sgs,
 						urb->num_sgs,

+ 12 - 9
drivers/usb/core/hub.c

@@ -81,7 +81,7 @@ struct usb_hub {
 	u8			indicator[USB_MAXCHILDREN];
 	u8			indicator[USB_MAXCHILDREN];
 	struct delayed_work	leds;
 	struct delayed_work	leds;
 	struct delayed_work	init_work;
 	struct delayed_work	init_work;
-	void			**port_owners;
+	struct dev_state	**port_owners;
 };
 };
 
 
 static inline int hub_is_superspeed(struct usb_device *hdev)
 static inline int hub_is_superspeed(struct usb_device *hdev)
@@ -1271,7 +1271,8 @@ static int hub_configure(struct usb_hub *hub,
 
 
 	hdev->children = kzalloc(hdev->maxchild *
 	hdev->children = kzalloc(hdev->maxchild *
 				sizeof(struct usb_device *), GFP_KERNEL);
 				sizeof(struct usb_device *), GFP_KERNEL);
-	hub->port_owners = kzalloc(hdev->maxchild * sizeof(void *), GFP_KERNEL);
+	hub->port_owners = kzalloc(hdev->maxchild * sizeof(struct dev_state *),
+				GFP_KERNEL);
 	if (!hdev->children || !hub->port_owners) {
 	if (!hdev->children || !hub->port_owners) {
 		ret = -ENOMEM;
 		ret = -ENOMEM;
 		goto fail;
 		goto fail;
@@ -1649,7 +1650,7 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
  * to one of these "claimed" ports, the program will "own" the device.
  * to one of these "claimed" ports, the program will "own" the device.
  */
  */
 static int find_port_owner(struct usb_device *hdev, unsigned port1,
 static int find_port_owner(struct usb_device *hdev, unsigned port1,
-		void ***ppowner)
+		struct dev_state ***ppowner)
 {
 {
 	if (hdev->state == USB_STATE_NOTATTACHED)
 	if (hdev->state == USB_STATE_NOTATTACHED)
 		return -ENODEV;
 		return -ENODEV;
@@ -1664,10 +1665,11 @@ static int find_port_owner(struct usb_device *hdev, unsigned port1,
 }
 }
 
 
 /* In the following three functions, the caller must hold hdev's lock */
 /* In the following three functions, the caller must hold hdev's lock */
-int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, void *owner)
+int usb_hub_claim_port(struct usb_device *hdev, unsigned port1,
+		       struct dev_state *owner)
 {
 {
 	int rc;
 	int rc;
-	void **powner;
+	struct dev_state **powner;
 
 
 	rc = find_port_owner(hdev, port1, &powner);
 	rc = find_port_owner(hdev, port1, &powner);
 	if (rc)
 	if (rc)
@@ -1678,10 +1680,11 @@ int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, void *owner)
 	return rc;
 	return rc;
 }
 }
 
 
-int usb_hub_release_port(struct usb_device *hdev, unsigned port1, void *owner)
+int usb_hub_release_port(struct usb_device *hdev, unsigned port1,
+			 struct dev_state *owner)
 {
 {
 	int rc;
 	int rc;
-	void **powner;
+	struct dev_state **powner;
 
 
 	rc = find_port_owner(hdev, port1, &powner);
 	rc = find_port_owner(hdev, port1, &powner);
 	if (rc)
 	if (rc)
@@ -1692,10 +1695,10 @@ int usb_hub_release_port(struct usb_device *hdev, unsigned port1, void *owner)
 	return rc;
 	return rc;
 }
 }
 
 
-void usb_hub_release_all_ports(struct usb_device *hdev, void *owner)
+void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner)
 {
 {
 	int n;
 	int n;
-	void **powner;
+	struct dev_state **powner;
 
 
 	n = find_port_owner(hdev, 1, &powner);
 	n = find_port_owner(hdev, 1, &powner);
 	if (n == 0) {
 	if (n == 0) {

+ 3 - 2
drivers/usb/core/message.c

@@ -1559,7 +1559,7 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
 
 
 	if (add_uevent_var(env,
 	if (add_uevent_var(env,
 		   "MODALIAS=usb:"
 		   "MODALIAS=usb:"
-		   "v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+		   "v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02Xin%02X",
 		   le16_to_cpu(usb_dev->descriptor.idVendor),
 		   le16_to_cpu(usb_dev->descriptor.idVendor),
 		   le16_to_cpu(usb_dev->descriptor.idProduct),
 		   le16_to_cpu(usb_dev->descriptor.idProduct),
 		   le16_to_cpu(usb_dev->descriptor.bcdDevice),
 		   le16_to_cpu(usb_dev->descriptor.bcdDevice),
@@ -1568,7 +1568,8 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
 		   usb_dev->descriptor.bDeviceProtocol,
 		   usb_dev->descriptor.bDeviceProtocol,
 		   alt->desc.bInterfaceClass,
 		   alt->desc.bInterfaceClass,
 		   alt->desc.bInterfaceSubClass,
 		   alt->desc.bInterfaceSubClass,
-		   alt->desc.bInterfaceProtocol))
+		   alt->desc.bInterfaceProtocol,
+		   alt->desc.bInterfaceNumber))
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	return 0;
 	return 0;

+ 3 - 2
drivers/usb/core/sysfs.c

@@ -840,7 +840,7 @@ static ssize_t show_modalias(struct device *dev,
 	alt = intf->cur_altsetting;
 	alt = intf->cur_altsetting;
 
 
 	return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X"
 	return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X"
-			"ic%02Xisc%02Xip%02X\n",
+			"ic%02Xisc%02Xip%02Xin%02X\n",
 			le16_to_cpu(udev->descriptor.idVendor),
 			le16_to_cpu(udev->descriptor.idVendor),
 			le16_to_cpu(udev->descriptor.idProduct),
 			le16_to_cpu(udev->descriptor.idProduct),
 			le16_to_cpu(udev->descriptor.bcdDevice),
 			le16_to_cpu(udev->descriptor.bcdDevice),
@@ -849,7 +849,8 @@ static ssize_t show_modalias(struct device *dev,
 			udev->descriptor.bDeviceProtocol,
 			udev->descriptor.bDeviceProtocol,
 			alt->desc.bInterfaceClass,
 			alt->desc.bInterfaceClass,
 			alt->desc.bInterfaceSubClass,
 			alt->desc.bInterfaceSubClass,
-			alt->desc.bInterfaceProtocol);
+			alt->desc.bInterfaceProtocol,
+			alt->desc.bInterfaceNumber);
 }
 }
 static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
 static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
 
 

+ 6 - 3
drivers/usb/core/usb.h

@@ -1,5 +1,7 @@
 #include <linux/pm.h>
 #include <linux/pm.h>
 
 
+struct dev_state;
+
 /* Functions local to drivers/usb/core/ */
 /* Functions local to drivers/usb/core/ */
 
 
 extern int usb_create_sysfs_dev_files(struct usb_device *dev);
 extern int usb_create_sysfs_dev_files(struct usb_device *dev);
@@ -41,10 +43,11 @@ extern void usb_forced_unbind_intf(struct usb_interface *intf);
 extern void usb_rebind_intf(struct usb_interface *intf);
 extern void usb_rebind_intf(struct usb_interface *intf);
 
 
 extern int usb_hub_claim_port(struct usb_device *hdev, unsigned port,
 extern int usb_hub_claim_port(struct usb_device *hdev, unsigned port,
-		void *owner);
+		struct dev_state *owner);
 extern int usb_hub_release_port(struct usb_device *hdev, unsigned port,
 extern int usb_hub_release_port(struct usb_device *hdev, unsigned port,
-		void *owner);
-extern void usb_hub_release_all_ports(struct usb_device *hdev, void *owner);
+		struct dev_state *owner);
+extern void usb_hub_release_all_ports(struct usb_device *hdev,
+		struct dev_state *owner);
 extern bool usb_device_is_owned(struct usb_device *udev);
 extern bool usb_device_is_owned(struct usb_device *udev);
 
 
 extern int  usb_hub_init(void);
 extern int  usb_hub_init(void);

+ 10 - 3
drivers/usb/dwc3/core.c

@@ -148,6 +148,8 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
 	reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
 	reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
 	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 
 
+	mdelay(100);
+
 	/* After PHYs are stable we can take Core out of reset state */
 	/* After PHYs are stable we can take Core out of reset state */
 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
 	reg &= ~DWC3_GCTL_CORESOFTRESET;
 	reg &= ~DWC3_GCTL_CORESOFTRESET;
@@ -255,7 +257,7 @@ static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
  *
  *
  * Returns 0 on success otherwise negative errno.
  * Returns 0 on success otherwise negative errno.
  */
  */
-static int __devinit dwc3_event_buffers_setup(struct dwc3 *dwc)
+static int dwc3_event_buffers_setup(struct dwc3 *dwc)
 {
 {
 	struct dwc3_event_buffer	*evt;
 	struct dwc3_event_buffer	*evt;
 	int				n;
 	int				n;
@@ -266,6 +268,8 @@ static int __devinit dwc3_event_buffers_setup(struct dwc3 *dwc)
 				evt->buf, (unsigned long long) evt->dma,
 				evt->buf, (unsigned long long) evt->dma,
 				evt->length);
 				evt->length);
 
 
+		evt->lpos = 0;
+
 		dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n),
 		dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n),
 				lower_32_bits(evt->dma));
 				lower_32_bits(evt->dma));
 		dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
 		dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
@@ -285,6 +289,9 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
 
 
 	for (n = 0; n < dwc->num_event_buffers; n++) {
 	for (n = 0; n < dwc->num_event_buffers; n++) {
 		evt = dwc->ev_buffs[n];
 		evt = dwc->ev_buffs[n];
+
+		evt->lpos = 0;
+
 		dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
 		dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
 		dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
 		dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
 		dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0);
 		dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0);
@@ -328,8 +335,6 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc)
 	}
 	}
 	dwc->revision = reg;
 	dwc->revision = reg;
 
 
-	dwc3_core_soft_reset(dwc);
-
 	/* issue device SoftReset too */
 	/* issue device SoftReset too */
 	timeout = jiffies + msecs_to_jiffies(500);
 	timeout = jiffies + msecs_to_jiffies(500);
 	dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
 	dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
@@ -347,6 +352,8 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc)
 		cpu_relax();
 		cpu_relax();
 	} while (true);
 	} while (true);
 
 
+	dwc3_core_soft_reset(dwc);
+
 	dwc3_cache_hwparams(dwc);
 	dwc3_cache_hwparams(dwc);
 
 
 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);

+ 83 - 24
drivers/usb/dwc3/core.h

@@ -67,6 +67,7 @@
 #define DWC3_DEVICE_EVENT_CONNECT_DONE		2
 #define DWC3_DEVICE_EVENT_CONNECT_DONE		2
 #define DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE	3
 #define DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE	3
 #define DWC3_DEVICE_EVENT_WAKEUP		4
 #define DWC3_DEVICE_EVENT_WAKEUP		4
+#define DWC3_DEVICE_EVENT_HIBER_REQ		5
 #define DWC3_DEVICE_EVENT_EOPF			6
 #define DWC3_DEVICE_EVENT_EOPF			6
 #define DWC3_DEVICE_EVENT_SOF			7
 #define DWC3_DEVICE_EVENT_SOF			7
 #define DWC3_DEVICE_EVENT_ERRATIC_ERROR		9
 #define DWC3_DEVICE_EVENT_ERRATIC_ERROR		9
@@ -171,28 +172,36 @@
 #define DWC3_GCTL_PRTCAP_DEVICE	2
 #define DWC3_GCTL_PRTCAP_DEVICE	2
 #define DWC3_GCTL_PRTCAP_OTG	3
 #define DWC3_GCTL_PRTCAP_OTG	3
 
 
-#define DWC3_GCTL_CORESOFTRESET	(1 << 11)
-#define DWC3_GCTL_SCALEDOWN(n)	((n) << 4)
-#define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3)
-#define DWC3_GCTL_DISSCRAMBLE	(1 << 3)
-#define DWC3_GCTL_DSBLCLKGTNG	(1 << 0)
+#define DWC3_GCTL_CORESOFTRESET		(1 << 11)
+#define DWC3_GCTL_SCALEDOWN(n)		((n) << 4)
+#define DWC3_GCTL_SCALEDOWN_MASK	DWC3_GCTL_SCALEDOWN(3)
+#define DWC3_GCTL_DISSCRAMBLE		(1 << 3)
+#define DWC3_GCTL_GBLHIBERNATIONEN	(1 << 1)
+#define DWC3_GCTL_DSBLCLKGTNG		(1 << 0)
 
 
 /* Global USB2 PHY Configuration Register */
 /* Global USB2 PHY Configuration Register */
-#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31)
-#define DWC3_GUSB2PHYCFG_SUSPHY	(1 << 6)
+#define DWC3_GUSB2PHYCFG_PHYSOFTRST	(1 << 31)
+#define DWC3_GUSB2PHYCFG_SUSPHY		(1 << 6)
 
 
 /* Global USB3 PIPE Control Register */
 /* Global USB3 PIPE Control Register */
-#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31)
-#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17)
+#define DWC3_GUSB3PIPECTL_PHYSOFTRST	(1 << 31)
+#define DWC3_GUSB3PIPECTL_SUSPHY	(1 << 17)
 
 
 /* Global TX Fifo Size Register */
 /* Global TX Fifo Size Register */
-#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff)
-#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000)
+#define DWC3_GTXFIFOSIZ_TXFDEF(n)	((n) & 0xffff)
+#define DWC3_GTXFIFOSIZ_TXFSTADDR(n)	((n) & 0xffff0000)
 
 
 /* Global HWPARAMS1 Register */
 /* Global HWPARAMS1 Register */
 #define DWC3_GHWPARAMS1_EN_PWROPT(n)	(((n) & (3 << 24)) >> 24)
 #define DWC3_GHWPARAMS1_EN_PWROPT(n)	(((n) & (3 << 24)) >> 24)
 #define DWC3_GHWPARAMS1_EN_PWROPT_NO	0
 #define DWC3_GHWPARAMS1_EN_PWROPT_NO	0
 #define DWC3_GHWPARAMS1_EN_PWROPT_CLK	1
 #define DWC3_GHWPARAMS1_EN_PWROPT_CLK	1
+#define DWC3_GHWPARAMS1_EN_PWROPT_HIB	2
+#define DWC3_GHWPARAMS1_PWROPT(n)	((n) << 24)
+#define DWC3_GHWPARAMS1_PWROPT_MASK	DWC3_GHWPARAMS1_PWROPT(3)
+
+/* Global HWPARAMS4 Register */
+#define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n)	(((n) & (0x0f << 13)) >> 13)
+#define DWC3_MAX_HIBER_SCRATCHBUFS		15
 
 
 /* Device Configuration Register */
 /* Device Configuration Register */
 #define DWC3_DCFG_LPM_CAP	(1 << 22)
 #define DWC3_DCFG_LPM_CAP	(1 << 22)
@@ -206,24 +215,32 @@
 #define DWC3_DCFG_LOWSPEED	(2 << 0)
 #define DWC3_DCFG_LOWSPEED	(2 << 0)
 #define DWC3_DCFG_FULLSPEED1	(3 << 0)
 #define DWC3_DCFG_FULLSPEED1	(3 << 0)
 
 
+#define DWC3_DCFG_LPM_CAP	(1 << 22)
+
 /* Device Control Register */
 /* Device Control Register */
 #define DWC3_DCTL_RUN_STOP	(1 << 31)
 #define DWC3_DCTL_RUN_STOP	(1 << 31)
 #define DWC3_DCTL_CSFTRST	(1 << 30)
 #define DWC3_DCTL_CSFTRST	(1 << 30)
 #define DWC3_DCTL_LSFTRST	(1 << 29)
 #define DWC3_DCTL_LSFTRST	(1 << 29)
 
 
 #define DWC3_DCTL_HIRD_THRES_MASK	(0x1f << 24)
 #define DWC3_DCTL_HIRD_THRES_MASK	(0x1f << 24)
-#define DWC3_DCTL_HIRD_THRES(n)	(((n) & DWC3_DCTL_HIRD_THRES_MASK) >> 24)
+#define DWC3_DCTL_HIRD_THRES(n)	((n) << 24)
 
 
 #define DWC3_DCTL_APPL1RES	(1 << 23)
 #define DWC3_DCTL_APPL1RES	(1 << 23)
 
 
-#define DWC3_DCTL_TRGTULST_MASK	(0x0f << 17)
-#define DWC3_DCTL_TRGTULST(n)	((n) << 17)
-
-#define DWC3_DCTL_TRGTULST_U2	(DWC3_DCTL_TRGTULST(2))
-#define DWC3_DCTL_TRGTULST_U3	(DWC3_DCTL_TRGTULST(3))
-#define DWC3_DCTL_TRGTULST_SS_DIS (DWC3_DCTL_TRGTULST(4))
-#define DWC3_DCTL_TRGTULST_RX_DET (DWC3_DCTL_TRGTULST(5))
-#define DWC3_DCTL_TRGTULST_SS_INACT (DWC3_DCTL_TRGTULST(6))
+/* These apply for core versions 1.87a and earlier */
+#define DWC3_DCTL_TRGTULST_MASK		(0x0f << 17)
+#define DWC3_DCTL_TRGTULST(n)		((n) << 17)
+#define DWC3_DCTL_TRGTULST_U2		(DWC3_DCTL_TRGTULST(2))
+#define DWC3_DCTL_TRGTULST_U3		(DWC3_DCTL_TRGTULST(3))
+#define DWC3_DCTL_TRGTULST_SS_DIS	(DWC3_DCTL_TRGTULST(4))
+#define DWC3_DCTL_TRGTULST_RX_DET	(DWC3_DCTL_TRGTULST(5))
+#define DWC3_DCTL_TRGTULST_SS_INACT	(DWC3_DCTL_TRGTULST(6))
+
+/* These apply for core versions 1.94a and later */
+#define DWC3_DCTL_KEEP_CONNECT	(1 << 19)
+#define DWC3_DCTL_L1_HIBER_EN	(1 << 18)
+#define DWC3_DCTL_CRS		(1 << 17)
+#define DWC3_DCTL_CSS		(1 << 16)
 
 
 #define DWC3_DCTL_INITU2ENA	(1 << 12)
 #define DWC3_DCTL_INITU2ENA	(1 << 12)
 #define DWC3_DCTL_ACCEPTU2ENA	(1 << 11)
 #define DWC3_DCTL_ACCEPTU2ENA	(1 << 11)
@@ -249,6 +266,7 @@
 #define DWC3_DEVTEN_ERRTICERREN		(1 << 9)
 #define DWC3_DEVTEN_ERRTICERREN		(1 << 9)
 #define DWC3_DEVTEN_SOFEN		(1 << 7)
 #define DWC3_DEVTEN_SOFEN		(1 << 7)
 #define DWC3_DEVTEN_EOPFEN		(1 << 6)
 #define DWC3_DEVTEN_EOPFEN		(1 << 6)
+#define DWC3_DEVTEN_HIBERNATIONREQEVTEN	(1 << 5)
 #define DWC3_DEVTEN_WKUPEVTEN		(1 << 4)
 #define DWC3_DEVTEN_WKUPEVTEN		(1 << 4)
 #define DWC3_DEVTEN_ULSTCNGEN		(1 << 3)
 #define DWC3_DEVTEN_ULSTCNGEN		(1 << 3)
 #define DWC3_DEVTEN_CONNECTDONEEN	(1 << 2)
 #define DWC3_DEVTEN_CONNECTDONEEN	(1 << 2)
@@ -256,7 +274,15 @@
 #define DWC3_DEVTEN_DISCONNEVTEN	(1 << 0)
 #define DWC3_DEVTEN_DISCONNEVTEN	(1 << 0)
 
 
 /* Device Status Register */
 /* Device Status Register */
+#define DWC3_DSTS_DCNRD			(1 << 29)
+
+/* This applies for core versions 1.87a and earlier */
 #define DWC3_DSTS_PWRUPREQ		(1 << 24)
 #define DWC3_DSTS_PWRUPREQ		(1 << 24)
+
+/* These apply for core versions 1.94a and later */
+#define DWC3_DSTS_RSS			(1 << 25)
+#define DWC3_DSTS_SSS			(1 << 24)
+
 #define DWC3_DSTS_COREIDLE		(1 << 23)
 #define DWC3_DSTS_COREIDLE		(1 << 23)
 #define DWC3_DSTS_DEVCTRLHLT		(1 << 22)
 #define DWC3_DSTS_DEVCTRLHLT		(1 << 22)
 
 
@@ -265,7 +291,7 @@
 
 
 #define DWC3_DSTS_RXFIFOEMPTY		(1 << 17)
 #define DWC3_DSTS_RXFIFOEMPTY		(1 << 17)
 
 
-#define DWC3_DSTS_SOFFN_MASK		(0x3ff << 3)
+#define DWC3_DSTS_SOFFN_MASK		(0x3fff << 3)
 #define DWC3_DSTS_SOFFN(n)		(((n) & DWC3_DSTS_SOFFN_MASK) >> 3)
 #define DWC3_DSTS_SOFFN(n)		(((n) & DWC3_DSTS_SOFFN_MASK) >> 3)
 
 
 #define DWC3_DSTS_CONNECTSPD		(7 << 0)
 #define DWC3_DSTS_CONNECTSPD		(7 << 0)
@@ -280,6 +306,11 @@
 #define DWC3_DGCMD_SET_LMP		0x01
 #define DWC3_DGCMD_SET_LMP		0x01
 #define DWC3_DGCMD_SET_PERIODIC_PAR	0x02
 #define DWC3_DGCMD_SET_PERIODIC_PAR	0x02
 #define DWC3_DGCMD_XMIT_FUNCTION	0x03
 #define DWC3_DGCMD_XMIT_FUNCTION	0x03
+
+/* These apply for core versions 1.94a and later */
+#define DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO	0x04
+#define DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI	0x05
+
 #define DWC3_DGCMD_SELECTED_FIFO_FLUSH	0x09
 #define DWC3_DGCMD_SELECTED_FIFO_FLUSH	0x09
 #define DWC3_DGCMD_ALL_FIFO_FLUSH	0x0a
 #define DWC3_DGCMD_ALL_FIFO_FLUSH	0x0a
 #define DWC3_DGCMD_SET_ENDPOINT_NRDY	0x0c
 #define DWC3_DGCMD_SET_ENDPOINT_NRDY	0x0c
@@ -287,6 +318,15 @@
 
 
 #define DWC3_DGCMD_STATUS(n)		(((n) >> 15) & 1)
 #define DWC3_DGCMD_STATUS(n)		(((n) >> 15) & 1)
 #define DWC3_DGCMD_CMDACT		(1 << 10)
 #define DWC3_DGCMD_CMDACT		(1 << 10)
+#define DWC3_DGCMD_CMDIOC		(1 << 8)
+
+/* Device Generic Command Parameter Register */
+#define DWC3_DGCMDPAR_FORCE_LINKPM_ACCEPT	(1 << 0)
+#define DWC3_DGCMDPAR_FIFO_NUM(n)		((n) << 0)
+#define DWC3_DGCMDPAR_RX_FIFO			(0 << 5)
+#define DWC3_DGCMDPAR_TX_FIFO			(1 << 5)
+#define DWC3_DGCMDPAR_LOOPBACK_DIS		(0 << 0)
+#define DWC3_DGCMDPAR_LOOPBACK_ENA		(1 << 0)
 
 
 /* Device Endpoint Command Register */
 /* Device Endpoint Command Register */
 #define DWC3_DEPCMD_PARAM_SHIFT		16
 #define DWC3_DEPCMD_PARAM_SHIFT		16
@@ -303,7 +343,10 @@
 #define DWC3_DEPCMD_STARTTRANSFER	(0x06 << 0)
 #define DWC3_DEPCMD_STARTTRANSFER	(0x06 << 0)
 #define DWC3_DEPCMD_CLEARSTALL		(0x05 << 0)
 #define DWC3_DEPCMD_CLEARSTALL		(0x05 << 0)
 #define DWC3_DEPCMD_SETSTALL		(0x04 << 0)
 #define DWC3_DEPCMD_SETSTALL		(0x04 << 0)
+/* This applies for core versions 1.90a and earlier */
 #define DWC3_DEPCMD_GETSEQNUMBER	(0x03 << 0)
 #define DWC3_DEPCMD_GETSEQNUMBER	(0x03 << 0)
+/* This applies for core versions 1.94a and later */
+#define DWC3_DEPCMD_GETEPSTATE		(0x03 << 0)
 #define DWC3_DEPCMD_SETTRANSFRESOURCE	(0x02 << 0)
 #define DWC3_DEPCMD_SETTRANSFRESOURCE	(0x02 << 0)
 #define DWC3_DEPCMD_SETEPCONFIG		(0x01 << 0)
 #define DWC3_DEPCMD_SETEPCONFIG		(0x01 << 0)
 
 
@@ -361,7 +404,8 @@ struct dwc3_event_buffer {
  * @current_trb: index of current used trb
  * @current_trb: index of current used trb
  * @number: endpoint number (1 - 15)
  * @number: endpoint number (1 - 15)
  * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
  * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
- * @res_trans_idx: Resource transfer index
+ * @resource_index: Resource transfer index
+ * @current_uf: Current uf received through last event parameter
  * @interval: the intervall on which the ISOC transfer is started
  * @interval: the intervall on which the ISOC transfer is started
  * @name: a human readable name e.g. ep1out-bulk
  * @name: a human readable name e.g. ep1out-bulk
  * @direction: true for TX, false for RX
  * @direction: true for TX, false for RX
@@ -385,6 +429,7 @@ struct dwc3_ep {
 #define DWC3_EP_WEDGE		(1 << 2)
 #define DWC3_EP_WEDGE		(1 << 2)
 #define DWC3_EP_BUSY		(1 << 4)
 #define DWC3_EP_BUSY		(1 << 4)
 #define DWC3_EP_PENDING_REQUEST	(1 << 5)
 #define DWC3_EP_PENDING_REQUEST	(1 << 5)
+#define DWC3_EP_MISSED_ISOC	(1 << 6)
 
 
 	/* This last one is specific to EP0 */
 	/* This last one is specific to EP0 */
 #define DWC3_EP0_DIR_IN		(1 << 31)
 #define DWC3_EP0_DIR_IN		(1 << 31)
@@ -393,7 +438,8 @@ struct dwc3_ep {
 
 
 	u8			number;
 	u8			number;
 	u8			type;
 	u8			type;
-	u8			res_trans_idx;
+	u8			resource_index;
+	u16			current_uf;
 	u32			interval;
 	u32			interval;
 
 
 	char			name[20];
 	char			name[20];
@@ -437,6 +483,8 @@ enum dwc3_link_state {
 	DWC3_LINK_STATE_HRESET		= 0x09,
 	DWC3_LINK_STATE_HRESET		= 0x09,
 	DWC3_LINK_STATE_CMPLY		= 0x0a,
 	DWC3_LINK_STATE_CMPLY		= 0x0a,
 	DWC3_LINK_STATE_LPBK		= 0x0b,
 	DWC3_LINK_STATE_LPBK		= 0x0b,
+	DWC3_LINK_STATE_RESET		= 0x0e,
+	DWC3_LINK_STATE_RESUME		= 0x0f,
 	DWC3_LINK_STATE_MASK		= 0x0f,
 	DWC3_LINK_STATE_MASK		= 0x0f,
 };
 };
 
 
@@ -450,11 +498,12 @@ enum dwc3_device_state {
 #define DWC3_TRB_SIZE_MASK	(0x00ffffff)
 #define DWC3_TRB_SIZE_MASK	(0x00ffffff)
 #define DWC3_TRB_SIZE_LENGTH(n)	((n) & DWC3_TRB_SIZE_MASK)
 #define DWC3_TRB_SIZE_LENGTH(n)	((n) & DWC3_TRB_SIZE_MASK)
 #define DWC3_TRB_SIZE_PCM1(n)	(((n) & 0x03) << 24)
 #define DWC3_TRB_SIZE_PCM1(n)	(((n) & 0x03) << 24)
-#define DWC3_TRB_SIZE_TRBSTS(n)	(((n) & (0x0f << 28) >> 28))
+#define DWC3_TRB_SIZE_TRBSTS(n)	(((n) & (0x0f << 28)) >> 28)
 
 
 #define DWC3_TRBSTS_OK			0
 #define DWC3_TRBSTS_OK			0
 #define DWC3_TRBSTS_MISSED_ISOC		1
 #define DWC3_TRBSTS_MISSED_ISOC		1
 #define DWC3_TRBSTS_SETUP_PENDING	2
 #define DWC3_TRBSTS_SETUP_PENDING	2
+#define DWC3_TRB_STS_XFER_IN_PROG	4
 
 
 /* TRB Control */
 /* TRB Control */
 #define DWC3_TRB_CTRL_HWO		(1 << 0)
 #define DWC3_TRB_CTRL_HWO		(1 << 0)
@@ -543,6 +592,14 @@ struct dwc3_request {
 	unsigned		queued:1;
 	unsigned		queued:1;
 };
 };
 
 
+/*
+ * struct dwc3_scratchpad_array - hibernation scratchpad array
+ * (format defined by hw)
+ */
+struct dwc3_scratchpad_array {
+	__le64	dma_adr[DWC3_MAX_HIBER_SCRATCHBUFS];
+};
+
 /**
 /**
  * struct dwc3 - representation of our controller
  * struct dwc3 - representation of our controller
  * @ctrl_req: usb control request which is used for ep0
  * @ctrl_req: usb control request which is used for ep0
@@ -624,8 +681,10 @@ struct dwc3 {
 #define DWC3_REVISION_180A	0x5533180a
 #define DWC3_REVISION_180A	0x5533180a
 #define DWC3_REVISION_183A	0x5533183a
 #define DWC3_REVISION_183A	0x5533183a
 #define DWC3_REVISION_185A	0x5533185a
 #define DWC3_REVISION_185A	0x5533185a
+#define DWC3_REVISION_187A	0x5533187a
 #define DWC3_REVISION_188A	0x5533188a
 #define DWC3_REVISION_188A	0x5533188a
 #define DWC3_REVISION_190A	0x5533190a
 #define DWC3_REVISION_190A	0x5533190a
+#define DWC3_REVISION_194A	0x5533194a
 #define DWC3_REVISION_200A	0x5533200a
 #define DWC3_REVISION_200A	0x5533200a
 #define DWC3_REVISION_202A	0x5533202a
 #define DWC3_REVISION_202A	0x5533202a
 #define DWC3_REVISION_210A	0x5533210a
 #define DWC3_REVISION_210A	0x5533210a

+ 0 - 1
drivers/usb/dwc3/dwc3-exynos.c

@@ -18,7 +18,6 @@
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/dwc3-exynos.h>
 #include <linux/platform_data/dwc3-exynos.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
-#include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 
 
 #include "core.h"
 #include "core.h"

+ 92 - 54
drivers/usb/dwc3/ep0.c

@@ -54,7 +54,9 @@
 #include "gadget.h"
 #include "gadget.h"
 #include "io.h"
 #include "io.h"
 
 
-static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum);
+static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep);
+static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
+		struct dwc3_ep *dep, struct dwc3_request *req);
 
 
 static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
 static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
 {
 {
@@ -111,7 +113,7 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
 	}
 	}
 
 
 	dep->flags |= DWC3_EP_BUSY;
 	dep->flags |= DWC3_EP_BUSY;
-	dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc,
+	dep->resource_index = dwc3_gadget_ep_get_transfer_index(dwc,
 			dep->number);
 			dep->number);
 
 
 	dwc->ep0_next_event = DWC3_EP0_COMPLETE;
 	dwc->ep0_next_event = DWC3_EP0_COMPLETE;
@@ -150,16 +152,15 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
 			return 0;
 			return 0;
 		}
 		}
 
 
-		ret = dwc3_ep0_start_trans(dwc, direction,
-				req->request.dma, req->request.length,
-				DWC3_TRBCTL_CONTROL_DATA);
+		__dwc3_ep0_do_control_data(dwc, dwc->eps[direction], req);
+
 		dep->flags &= ~(DWC3_EP_PENDING_REQUEST |
 		dep->flags &= ~(DWC3_EP_PENDING_REQUEST |
 				DWC3_EP0_DIR_IN);
 				DWC3_EP0_DIR_IN);
 	} else if (dwc->delayed_status) {
 	} else if (dwc->delayed_status) {
 		dwc->delayed_status = false;
 		dwc->delayed_status = false;
 
 
 		if (dwc->ep0state == EP0_STATUS_PHASE)
 		if (dwc->ep0state == EP0_STATUS_PHASE)
-			dwc3_ep0_do_control_status(dwc, 1);
+			__dwc3_ep0_do_control_status(dwc, dwc->eps[1]);
 		else
 		else
 			dev_dbg(dwc->dev, "too early for delayed status\n");
 			dev_dbg(dwc->dev, "too early for delayed status\n");
 	}
 	}
@@ -224,6 +225,16 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
 	dwc3_ep0_out_start(dwc);
 	dwc3_ep0_out_start(dwc);
 }
 }
 
 
+int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value)
+{
+	struct dwc3_ep			*dep = to_dwc3_ep(ep);
+	struct dwc3			*dwc = dep->dwc;
+
+	dwc3_ep0_stall_and_restart(dwc);
+
+	return 0;
+}
+
 void dwc3_ep0_out_start(struct dwc3 *dwc)
 void dwc3_ep0_out_start(struct dwc3 *dwc)
 {
 {
 	int				ret;
 	int				ret;
@@ -463,6 +474,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 {
 {
 	u32 cfg;
 	u32 cfg;
 	int ret;
 	int ret;
+	u32 reg;
 
 
 	dwc->start_config_issued = false;
 	dwc->start_config_issued = false;
 	cfg = le16_to_cpu(ctrl->wValue);
 	cfg = le16_to_cpu(ctrl->wValue);
@@ -477,6 +489,14 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 		/* if the cfg matches and the cfg is non zero */
 		/* if the cfg matches and the cfg is non zero */
 		if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
 		if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
 			dwc->dev_state = DWC3_CONFIGURED_STATE;
 			dwc->dev_state = DWC3_CONFIGURED_STATE;
+			/*
+			 * Enable transition to U1/U2 state when
+			 * nothing is pending from application.
+			 */
+			reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+			reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA);
+			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
 			dwc->resize_fifos = true;
 			dwc->resize_fifos = true;
 			dev_dbg(dwc->dev, "resize fifos flag SET\n");
 			dev_dbg(dwc->dev, "resize fifos flag SET\n");
 		}
 		}
@@ -514,8 +534,8 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req)
 
 
 	dwc->u1sel = timing.u1sel;
 	dwc->u1sel = timing.u1sel;
 	dwc->u1pel = timing.u1pel;
 	dwc->u1pel = timing.u1pel;
-	dwc->u2sel = timing.u2sel;
-	dwc->u2pel = timing.u2pel;
+	dwc->u2sel = le16_to_cpu(timing.u2sel);
+	dwc->u2pel = le16_to_cpu(timing.u2pel);
 
 
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	if (reg & DWC3_DCTL_INITU2ENA)
 	if (reg & DWC3_DCTL_INITU2ENA)
@@ -640,11 +660,11 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
 		const struct dwc3_event_depevt *event)
 		const struct dwc3_event_depevt *event)
 {
 {
 	struct usb_ctrlrequest *ctrl = dwc->ctrl_req;
 	struct usb_ctrlrequest *ctrl = dwc->ctrl_req;
-	int ret;
+	int ret = -EINVAL;
 	u32 len;
 	u32 len;
 
 
 	if (!dwc->gadget_driver)
 	if (!dwc->gadget_driver)
-		goto err;
+		goto out;
 
 
 	len = le16_to_cpu(ctrl->wLength);
 	len = le16_to_cpu(ctrl->wLength);
 	if (!len) {
 	if (!len) {
@@ -665,11 +685,9 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
 	if (ret == USB_GADGET_DELAYED_STATUS)
 	if (ret == USB_GADGET_DELAYED_STATUS)
 		dwc->delayed_status = true;
 		dwc->delayed_status = true;
 
 
-	if (ret >= 0)
-		return;
-
-err:
-	dwc3_ep0_stall_and_restart(dwc);
+out:
+	if (ret < 0)
+		dwc3_ep0_stall_and_restart(dwc);
 }
 }
 
 
 static void dwc3_ep0_complete_data(struct dwc3 *dwc,
 static void dwc3_ep0_complete_data(struct dwc3 *dwc,
@@ -723,7 +741,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
 	}
 	}
 }
 }
 
 
-static void dwc3_ep0_complete_req(struct dwc3 *dwc,
+static void dwc3_ep0_complete_status(struct dwc3 *dwc,
 		const struct dwc3_event_depevt *event)
 		const struct dwc3_event_depevt *event)
 {
 {
 	struct dwc3_request	*r;
 	struct dwc3_request	*r;
@@ -745,6 +763,7 @@ static void dwc3_ep0_complete_req(struct dwc3 *dwc,
 			dev_dbg(dwc->dev, "Invalid Test #%d\n",
 			dev_dbg(dwc->dev, "Invalid Test #%d\n",
 					dwc->test_mode_nr);
 					dwc->test_mode_nr);
 			dwc3_ep0_stall_and_restart(dwc);
 			dwc3_ep0_stall_and_restart(dwc);
+			return;
 		}
 		}
 	}
 	}
 
 
@@ -758,7 +777,7 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc,
 	struct dwc3_ep		*dep = dwc->eps[event->endpoint_number];
 	struct dwc3_ep		*dep = dwc->eps[event->endpoint_number];
 
 
 	dep->flags &= ~DWC3_EP_BUSY;
 	dep->flags &= ~DWC3_EP_BUSY;
-	dep->res_trans_idx = 0;
+	dep->resource_index = 0;
 	dwc->setup_packet_pending = false;
 	dwc->setup_packet_pending = false;
 
 
 	switch (dwc->ep0state) {
 	switch (dwc->ep0state) {
@@ -774,7 +793,7 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc,
 
 
 	case EP0_STATUS_PHASE:
 	case EP0_STATUS_PHASE:
 		dev_vdbg(dwc->dev, "Status Phase\n");
 		dev_vdbg(dwc->dev, "Status Phase\n");
-		dwc3_ep0_complete_req(dwc, event);
+		dwc3_ep0_complete_status(dwc, event);
 		break;
 		break;
 	default:
 	default:
 		WARN(true, "UNKNOWN ep0state %d\n", dwc->ep0state);
 		WARN(true, "UNKNOWN ep0state %d\n", dwc->ep0state);
@@ -787,68 +806,81 @@ static void dwc3_ep0_do_control_setup(struct dwc3 *dwc,
 	dwc3_ep0_out_start(dwc);
 	dwc3_ep0_out_start(dwc);
 }
 }
 
 
-static void dwc3_ep0_do_control_data(struct dwc3 *dwc,
-		const struct dwc3_event_depevt *event)
+static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
+		struct dwc3_ep *dep, struct dwc3_request *req)
 {
 {
-	struct dwc3_ep		*dep;
-	struct dwc3_request	*req;
 	int			ret;
 	int			ret;
 
 
-	dep = dwc->eps[0];
-
-	if (list_empty(&dep->request_list)) {
-		dev_vdbg(dwc->dev, "pending request for EP0 Data phase\n");
-		dep->flags |= DWC3_EP_PENDING_REQUEST;
-
-		if (event->endpoint_number)
-			dep->flags |= DWC3_EP0_DIR_IN;
-		return;
-	}
-
-	req = next_request(&dep->request_list);
-	req->direction = !!event->endpoint_number;
+	req->direction = !!dep->number;
 
 
 	if (req->request.length == 0) {
 	if (req->request.length == 0) {
-		ret = dwc3_ep0_start_trans(dwc, event->endpoint_number,
+		ret = dwc3_ep0_start_trans(dwc, dep->number,
 				dwc->ctrl_req_addr, 0,
 				dwc->ctrl_req_addr, 0,
 				DWC3_TRBCTL_CONTROL_DATA);
 				DWC3_TRBCTL_CONTROL_DATA);
-	} else if ((req->request.length % dep->endpoint.maxpacket)
-			&& (event->endpoint_number == 0)) {
+	} else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
+			&& (dep->number == 0)) {
+		u32		transfer_size;
+
 		ret = usb_gadget_map_request(&dwc->gadget, &req->request,
 		ret = usb_gadget_map_request(&dwc->gadget, &req->request,
-				event->endpoint_number);
+				dep->number);
 		if (ret) {
 		if (ret) {
 			dev_dbg(dwc->dev, "failed to map request\n");
 			dev_dbg(dwc->dev, "failed to map request\n");
 			return;
 			return;
 		}
 		}
 
 
-		WARN_ON(req->request.length > dep->endpoint.maxpacket);
+		WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE);
+
+		transfer_size = roundup(req->request.length,
+				(u32) dep->endpoint.maxpacket);
 
 
 		dwc->ep0_bounced = true;
 		dwc->ep0_bounced = true;
 
 
 		/*
 		/*
-		 * REVISIT in case request length is bigger than EP0
-		 * wMaxPacketSize, we will need two chained TRBs to handle
-		 * the transfer.
+		 * REVISIT in case request length is bigger than
+		 * DWC3_EP0_BOUNCE_SIZE we will need two chained
+		 * TRBs to handle the transfer.
 		 */
 		 */
-		ret = dwc3_ep0_start_trans(dwc, event->endpoint_number,
-				dwc->ep0_bounce_addr, dep->endpoint.maxpacket,
+		ret = dwc3_ep0_start_trans(dwc, dep->number,
+				dwc->ep0_bounce_addr, transfer_size,
 				DWC3_TRBCTL_CONTROL_DATA);
 				DWC3_TRBCTL_CONTROL_DATA);
 	} else {
 	} else {
 		ret = usb_gadget_map_request(&dwc->gadget, &req->request,
 		ret = usb_gadget_map_request(&dwc->gadget, &req->request,
-				event->endpoint_number);
+				dep->number);
 		if (ret) {
 		if (ret) {
 			dev_dbg(dwc->dev, "failed to map request\n");
 			dev_dbg(dwc->dev, "failed to map request\n");
 			return;
 			return;
 		}
 		}
 
 
-		ret = dwc3_ep0_start_trans(dwc, event->endpoint_number,
-				req->request.dma, req->request.length,
-				DWC3_TRBCTL_CONTROL_DATA);
+		ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma,
+				req->request.length, DWC3_TRBCTL_CONTROL_DATA);
 	}
 	}
 
 
 	WARN_ON(ret < 0);
 	WARN_ON(ret < 0);
 }
 }
 
 
+static void dwc3_ep0_do_control_data(struct dwc3 *dwc,
+		const struct dwc3_event_depevt *event)
+{
+	struct dwc3_ep		*dep;
+	struct dwc3_request	*req;
+
+	dep = dwc->eps[0];
+
+	if (list_empty(&dep->request_list)) {
+		dev_vdbg(dwc->dev, "pending request for EP0 Data phase\n");
+		dep->flags |= DWC3_EP_PENDING_REQUEST;
+
+		if (event->endpoint_number)
+			dep->flags |= DWC3_EP0_DIR_IN;
+		return;
+	}
+
+	req = next_request(&dep->request_list);
+	dep = dwc->eps[event->endpoint_number];
+
+	__dwc3_ep0_do_control_data(dwc, dep, req);
+}
+
 static int dwc3_ep0_start_control_status(struct dwc3_ep *dep)
 static int dwc3_ep0_start_control_status(struct dwc3_ep *dep)
 {
 {
 	struct dwc3		*dwc = dep->dwc;
 	struct dwc3		*dwc = dep->dwc;
@@ -861,10 +893,8 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep)
 			dwc->ctrl_req_addr, 0, type);
 			dwc->ctrl_req_addr, 0, type);
 }
 }
 
 
-static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum)
+static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep)
 {
 {
-	struct dwc3_ep		*dep = dwc->eps[epnum];
-
 	if (dwc->resize_fifos) {
 	if (dwc->resize_fifos) {
 		dev_dbg(dwc->dev, "starting to resize fifos\n");
 		dev_dbg(dwc->dev, "starting to resize fifos\n");
 		dwc3_gadget_resize_tx_fifos(dwc);
 		dwc3_gadget_resize_tx_fifos(dwc);
@@ -874,13 +904,21 @@ static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum)
 	WARN_ON(dwc3_ep0_start_control_status(dep));
 	WARN_ON(dwc3_ep0_start_control_status(dep));
 }
 }
 
 
+static void dwc3_ep0_do_control_status(struct dwc3 *dwc,
+		const struct dwc3_event_depevt *event)
+{
+	struct dwc3_ep		*dep = dwc->eps[event->endpoint_number];
+
+	__dwc3_ep0_do_control_status(dwc, dep);
+}
+
 static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
 static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
 		const struct dwc3_event_depevt *event)
 		const struct dwc3_event_depevt *event)
 {
 {
 	dwc->setup_packet_pending = true;
 	dwc->setup_packet_pending = true;
 
 
 	/*
 	/*
-	 * This part is very tricky: If we has just handled
+	 * This part is very tricky: If we have just handled
 	 * XferNotReady(Setup) and we're now expecting a
 	 * XferNotReady(Setup) and we're now expecting a
 	 * XferComplete but, instead, we receive another
 	 * XferComplete but, instead, we receive another
 	 * XferNotReady(Setup), we should STALL and restart
 	 * XferNotReady(Setup), we should STALL and restart
@@ -974,7 +1012,7 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
 			return;
 			return;
 		}
 		}
 
 
-		dwc3_ep0_do_control_status(dwc, event->endpoint_number);
+		dwc3_ep0_do_control_status(dwc, event);
 	}
 	}
 }
 }
 
 

+ 217 - 148
drivers/usb/dwc3/gadget.c

@@ -100,6 +100,23 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state)
 	int		retries = 10000;
 	int		retries = 10000;
 	u32		reg;
 	u32		reg;
 
 
+	/*
+	 * Wait until device controller is ready. Only applies to 1.94a and
+	 * later RTL.
+	 */
+	if (dwc->revision >= DWC3_REVISION_194A) {
+		while (--retries) {
+			reg = dwc3_readl(dwc->regs, DWC3_DSTS);
+			if (reg & DWC3_DSTS_DCNRD)
+				udelay(5);
+			else
+				break;
+		}
+
+		if (retries <= 0)
+			return -ETIMEDOUT;
+	}
+
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
 	reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
 
 
@@ -107,7 +124,15 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state)
 	reg |= DWC3_DCTL_ULSTCHNGREQ(state);
 	reg |= DWC3_DCTL_ULSTCHNGREQ(state);
 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 
 
+	/*
+	 * The following code is racy when called from dwc3_gadget_wakeup,
+	 * and is not needed, at least on newer versions
+	 */
+	if (dwc->revision >= DWC3_REVISION_194A)
+		return 0;
+
 	/* wait for a change in DSTS */
 	/* wait for a change in DSTS */
+	retries = 10000;
 	while (--retries) {
 	while (--retries) {
 		reg = dwc3_readl(dwc->regs, DWC3_DSTS);
 		reg = dwc3_readl(dwc->regs, DWC3_DSTS);
 
 
@@ -265,8 +290,8 @@ static const char *dwc3_gadget_ep_cmd_string(u8 cmd)
 		return "Clear Stall";
 		return "Clear Stall";
 	case DWC3_DEPCMD_SETSTALL:
 	case DWC3_DEPCMD_SETSTALL:
 		return "Set Stall";
 		return "Set Stall";
-	case DWC3_DEPCMD_GETSEQNUMBER:
-		return "Get Data Sequence Number";
+	case DWC3_DEPCMD_GETEPSTATE:
+		return "Get Endpoint State";
 	case DWC3_DEPCMD_SETTRANSFRESOURCE:
 	case DWC3_DEPCMD_SETTRANSFRESOURCE:
 		return "Set Endpoint Transfer Resource";
 		return "Set Endpoint Transfer Resource";
 	case DWC3_DEPCMD_SETEPCONFIG:
 	case DWC3_DEPCMD_SETEPCONFIG:
@@ -414,7 +439,7 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep,
 
 
 	params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc))
 	params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc))
 		| DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc))
 		| DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc))
-		| DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst);
+		| DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst - 1);
 
 
 	params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN
 	params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN
 		| DWC3_DEPCFG_XFER_NOT_READY_EN;
 		| DWC3_DEPCFG_XFER_NOT_READY_EN;
@@ -530,9 +555,37 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
 {
 {
 	struct dwc3_request		*req;
 	struct dwc3_request		*req;
 
 
-	if (!list_empty(&dep->req_queued))
+	if (!list_empty(&dep->req_queued)) {
 		dwc3_stop_active_transfer(dwc, dep->number);
 		dwc3_stop_active_transfer(dwc, dep->number);
 
 
+		/*
+		 * NOTICE: We are violating what the Databook says about the
+		 * EndTransfer command. Ideally we would _always_ wait for the
+		 * EndTransfer Command Completion IRQ, but that's causing too
+		 * much trouble synchronizing between us and gadget driver.
+		 *
+		 * We have discussed this with the IP Provider and it was
+		 * suggested to giveback all requests here, but give HW some
+		 * extra time to synchronize with the interconnect. We're using
+		 * an arbitraty 100us delay for that.
+		 *
+		 * Note also that a similar handling was tested by Synopsys
+		 * (thanks a lot Paul) and nothing bad has come out of it.
+		 * In short, what we're doing is:
+		 *
+		 * - Issue EndTransfer WITH CMDIOC bit set
+		 * - Wait 100us
+		 * - giveback all requests to gadget driver
+		 */
+		udelay(100);
+
+		while (!list_empty(&dep->req_queued)) {
+			req = next_request(&dep->req_queued);
+
+			dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
+		}
+	}
+
 	while (!list_empty(&dep->request_list)) {
 	while (!list_empty(&dep->request_list)) {
 		req = next_request(&dep->request_list);
 		req = next_request(&dep->request_list);
 
 
@@ -741,8 +794,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 	case USB_ENDPOINT_XFER_ISOC:
 	case USB_ENDPOINT_XFER_ISOC:
 		trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST;
 		trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST;
 
 
-		/* IOC every DWC3_TRB_NUM / 4 so we can refill */
-		if (!(cur_slot % (DWC3_TRB_NUM / 4)))
+		if (!req->request.no_interrupt)
 			trb->ctrl |= DWC3_TRB_CTRL_IOC;
 			trb->ctrl |= DWC3_TRB_CTRL_IOC;
 		break;
 		break;
 
 
@@ -958,14 +1010,42 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
 	dep->flags |= DWC3_EP_BUSY;
 	dep->flags |= DWC3_EP_BUSY;
 
 
 	if (start_new) {
 	if (start_new) {
-		dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc,
+		dep->resource_index = dwc3_gadget_ep_get_transfer_index(dwc,
 				dep->number);
 				dep->number);
-		WARN_ON_ONCE(!dep->res_trans_idx);
+		WARN_ON_ONCE(!dep->resource_index);
 	}
 	}
 
 
 	return 0;
 	return 0;
 }
 }
 
 
+static void __dwc3_gadget_start_isoc(struct dwc3 *dwc,
+		struct dwc3_ep *dep, u32 cur_uf)
+{
+	u32 uf;
+
+	if (list_empty(&dep->request_list)) {
+		dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n",
+			dep->name);
+		return;
+	}
+
+	/* 4 micro frames in the future */
+	uf = cur_uf + dep->interval * 4;
+
+	__dwc3_gadget_kick_transfer(dep, uf, 1);
+}
+
+static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
+		struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
+{
+	u32 cur_uf, mask;
+
+	mask = ~(dep->interval - 1);
+	cur_uf = event->parameters & mask;
+
+	__dwc3_gadget_start_isoc(dwc, dep, cur_uf);
+}
+
 static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 {
 {
 	struct dwc3		*dwc = dep->dwc;
 	struct dwc3		*dwc = dep->dwc;
@@ -995,11 +1075,8 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 
 
 	list_add_tail(&req->list, &dep->request_list);
 	list_add_tail(&req->list, &dep->request_list);
 
 
-	if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && (dep->flags & DWC3_EP_BUSY))
-		dep->flags |= DWC3_EP_PENDING_REQUEST;
-
 	/*
 	/*
-	 * There are two special cases:
+	 * There are a few special cases:
 	 *
 	 *
 	 * 1. XferNotReady with empty list of requests. We need to kick the
 	 * 1. XferNotReady with empty list of requests. We need to kick the
 	 *    transfer here in that situation, otherwise we will be NAKing
 	 *    transfer here in that situation, otherwise we will be NAKing
@@ -1008,31 +1085,46 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 	 *    able to receive the data until the next request is queued.
 	 *    able to receive the data until the next request is queued.
 	 *    The following code is handling exactly that.
 	 *    The following code is handling exactly that.
 	 *
 	 *
-	 * 2. XferInProgress on Isoc EP with an active transfer. We need to
-	 *    kick the transfer here after queuing a request, otherwise the
-	 *    core may not see the modified TRB(s).
 	 */
 	 */
 	if (dep->flags & DWC3_EP_PENDING_REQUEST) {
 	if (dep->flags & DWC3_EP_PENDING_REQUEST) {
 		int	ret;
 		int	ret;
-		int	start_trans = 1;
-		u8	trans_idx = dep->res_trans_idx;
 
 
-		if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
-				(dep->flags & DWC3_EP_BUSY)) {
-			start_trans = 0;
-			WARN_ON_ONCE(!trans_idx);
-		} else {
-			trans_idx = 0;
+		ret = __dwc3_gadget_kick_transfer(dep, 0, true);
+		if (ret && ret != -EBUSY) {
+			struct dwc3	*dwc = dep->dwc;
+
+			dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
+					dep->name);
 		}
 		}
+	}
 
 
-		ret = __dwc3_gadget_kick_transfer(dep, trans_idx, start_trans);
+	/*
+	 * 2. XferInProgress on Isoc EP with an active transfer. We need to
+	 *    kick the transfer here after queuing a request, otherwise the
+	 *    core may not see the modified TRB(s).
+	 */
+	if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
+			(dep->flags & DWC3_EP_BUSY)) {
+		WARN_ON_ONCE(!dep->resource_index);
+		ret = __dwc3_gadget_kick_transfer(dep, dep->resource_index,
+				false);
 		if (ret && ret != -EBUSY) {
 		if (ret && ret != -EBUSY) {
 			struct dwc3	*dwc = dep->dwc;
 			struct dwc3	*dwc = dep->dwc;
 
 
 			dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
 			dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
 					dep->name);
 					dep->name);
 		}
 		}
-	};
+	}
+
+	/*
+	 * 3. Missed ISOC Handling. We need to start isoc transfer on the saved
+	 * uframe number.
+	 */
+	if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
+		(dep->flags & DWC3_EP_MISSED_ISOC)) {
+			__dwc3_gadget_start_isoc(dwc, dep, dep->current_uf);
+			dep->flags &= ~DWC3_EP_MISSED_ISOC;
+	}
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1118,15 +1210,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
 	memset(&params, 0x00, sizeof(params));
 	memset(&params, 0x00, sizeof(params));
 
 
 	if (value) {
 	if (value) {
-		if (dep->number == 0 || dep->number == 1) {
-			/*
-			 * Whenever EP0 is stalled, we will restart
-			 * the state machine, thus moving back to
-			 * Setup Phase
-			 */
-			dwc->ep0state = EP0_SETUP_PHASE;
-		}
-
 		ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
 		ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
 			DWC3_DEPCMD_SETSTALL, &params);
 			DWC3_DEPCMD_SETSTALL, &params);
 		if (ret)
 		if (ret)
@@ -1186,7 +1269,10 @@ static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep)
 	dep->flags |= DWC3_EP_WEDGE;
 	dep->flags |= DWC3_EP_WEDGE;
 	spin_unlock_irqrestore(&dwc->lock, flags);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
 
-	return dwc3_gadget_ep_set_halt(ep, 1);
+	if (dep->number == 0 || dep->number == 1)
+		return dwc3_gadget_ep0_set_halt(ep, 1);
+	else
+		return dwc3_gadget_ep_set_halt(ep, 1);
 }
 }
 
 
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
@@ -1204,7 +1290,7 @@ static const struct usb_ep_ops dwc3_gadget_ep0_ops = {
 	.free_request	= dwc3_gadget_ep_free_request,
 	.free_request	= dwc3_gadget_ep_free_request,
 	.queue		= dwc3_gadget_ep0_queue,
 	.queue		= dwc3_gadget_ep0_queue,
 	.dequeue	= dwc3_gadget_ep_dequeue,
 	.dequeue	= dwc3_gadget_ep_dequeue,
-	.set_halt	= dwc3_gadget_ep_set_halt,
+	.set_halt	= dwc3_gadget_ep0_set_halt,
 	.set_wedge	= dwc3_gadget_ep_set_wedge,
 	.set_wedge	= dwc3_gadget_ep_set_wedge,
 };
 };
 
 
@@ -1280,9 +1366,13 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g)
 		goto out;
 		goto out;
 	}
 	}
 
 
-	/* write zeroes to Link Change Request */
-	reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
-	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+	/* Recent versions do this automatically */
+	if (dwc->revision < DWC3_REVISION_194A) {
+		/* write zeroes to Link Change Request */
+		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+		reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
+		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+	}
 
 
 	/* poll until Link State changes to ON */
 	/* poll until Link State changes to ON */
 	timeout = jiffies + msecs_to_jiffies(100);
 	timeout = jiffies + msecs_to_jiffies(100);
@@ -1319,16 +1409,21 @@ static int dwc3_gadget_set_selfpowered(struct usb_gadget *g,
 	return 0;
 	return 0;
 }
 }
 
 
-static void dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
+static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
 {
 {
 	u32			reg;
 	u32			reg;
 	u32			timeout = 500;
 	u32			timeout = 500;
 
 
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	if (is_on) {
 	if (is_on) {
-		reg &= ~DWC3_DCTL_TRGTULST_MASK;
-		reg |= (DWC3_DCTL_RUN_STOP
-				| DWC3_DCTL_TRGTULST_RX_DET);
+		if (dwc->revision <= DWC3_REVISION_187A) {
+			reg &= ~DWC3_DCTL_TRGTULST_MASK;
+			reg |= DWC3_DCTL_TRGTULST_RX_DET;
+		}
+
+		if (dwc->revision >= DWC3_REVISION_194A)
+			reg &= ~DWC3_DCTL_KEEP_CONNECT;
+		reg |= DWC3_DCTL_RUN_STOP;
 	} else {
 	} else {
 		reg &= ~DWC3_DCTL_RUN_STOP;
 		reg &= ~DWC3_DCTL_RUN_STOP;
 	}
 	}
@@ -1346,7 +1441,7 @@ static void dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
 		}
 		}
 		timeout--;
 		timeout--;
 		if (!timeout)
 		if (!timeout)
-			break;
+			return -ETIMEDOUT;
 		udelay(1);
 		udelay(1);
 	} while (1);
 	} while (1);
 
 
@@ -1354,20 +1449,23 @@ static void dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
 			dwc->gadget_driver
 			dwc->gadget_driver
 			? dwc->gadget_driver->function : "no-function",
 			? dwc->gadget_driver->function : "no-function",
 			is_on ? "connect" : "disconnect");
 			is_on ? "connect" : "disconnect");
+
+	return 0;
 }
 }
 
 
 static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 {
 {
 	struct dwc3		*dwc = gadget_to_dwc(g);
 	struct dwc3		*dwc = gadget_to_dwc(g);
 	unsigned long		flags;
 	unsigned long		flags;
+	int			ret;
 
 
 	is_on = !!is_on;
 	is_on = !!is_on;
 
 
 	spin_lock_irqsave(&dwc->lock, flags);
 	spin_lock_irqsave(&dwc->lock, flags);
-	dwc3_gadget_run_stop(dwc, is_on);
+	ret = dwc3_gadget_run_stop(dwc, is_on);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
 
-	return 0;
+	return ret;
 }
 }
 
 
 static int dwc3_gadget_start(struct usb_gadget *g,
 static int dwc3_gadget_start(struct usb_gadget *g,
@@ -1468,6 +1566,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
 
 
 	return 0;
 	return 0;
 }
 }
+
 static const struct usb_gadget_ops dwc3_gadget_ops = {
 static const struct usb_gadget_ops dwc3_gadget_ops = {
 	.get_frame		= dwc3_gadget_get_frame,
 	.get_frame		= dwc3_gadget_get_frame,
 	.wakeup			= dwc3_gadget_wakeup,
 	.wakeup			= dwc3_gadget_wakeup,
@@ -1558,6 +1657,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
 	struct dwc3_trb		*trb;
 	struct dwc3_trb		*trb;
 	unsigned int		count;
 	unsigned int		count;
 	unsigned int		s_pkt = 0;
 	unsigned int		s_pkt = 0;
+	unsigned int		trb_status;
 
 
 	do {
 	do {
 		req = next_request(&dep->req_queued);
 		req = next_request(&dep->req_queued);
@@ -1583,9 +1683,18 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
 
 
 		if (dep->direction) {
 		if (dep->direction) {
 			if (count) {
 			if (count) {
-				dev_err(dwc->dev, "incomplete IN transfer %s\n",
-						dep->name);
-				status = -ECONNRESET;
+				trb_status = DWC3_TRB_SIZE_TRBSTS(trb->size);
+				if (trb_status == DWC3_TRBSTS_MISSED_ISOC) {
+					dev_dbg(dwc->dev, "incomplete IN transfer %s\n",
+							dep->name);
+					dep->current_uf = event->parameters &
+						~(dep->interval - 1);
+					dep->flags |= DWC3_EP_MISSED_ISOC;
+				} else {
+					dev_err(dwc->dev, "incomplete IN transfer %s\n",
+							dep->name);
+					status = -ECONNRESET;
+				}
 			}
 			}
 		} else {
 		} else {
 			if (count && (event->status & DEPEVT_STATUS_SHORT))
 			if (count && (event->status & DEPEVT_STATUS_SHORT))
@@ -1604,7 +1713,8 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
 		if (s_pkt)
 		if (s_pkt)
 			break;
 			break;
 		if ((event->status & DEPEVT_STATUS_LST) &&
 		if ((event->status & DEPEVT_STATUS_LST) &&
-				(trb->ctrl & DWC3_TRB_CTRL_LST))
+				(trb->ctrl & (DWC3_TRB_CTRL_LST |
+						DWC3_TRB_CTRL_HWO)))
 			break;
 			break;
 		if ((event->status & DEPEVT_STATUS_IOC) &&
 		if ((event->status & DEPEVT_STATUS_IOC) &&
 				(trb->ctrl & DWC3_TRB_CTRL_IOC))
 				(trb->ctrl & DWC3_TRB_CTRL_IOC))
@@ -1657,65 +1767,6 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
 	}
 	}
 }
 }
 
 
-static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
-		struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
-{
-	u32 uf, mask;
-
-	if (list_empty(&dep->request_list)) {
-		dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n",
-			dep->name);
-		return;
-	}
-
-	mask = ~(dep->interval - 1);
-	uf = event->parameters & mask;
-	/* 4 micro frames in the future */
-	uf += dep->interval * 4;
-
-	__dwc3_gadget_kick_transfer(dep, uf, 1);
-}
-
-static void dwc3_process_ep_cmd_complete(struct dwc3_ep *dep,
-		const struct dwc3_event_depevt *event)
-{
-	struct dwc3 *dwc = dep->dwc;
-	struct dwc3_event_depevt mod_ev = *event;
-
-	/*
-	 * We were asked to remove one request. It is possible that this
-	 * request and a few others were started together and have the same
-	 * transfer index. Since we stopped the complete endpoint we don't
-	 * know how many requests were already completed (and not yet)
-	 * reported and how could be done (later). We purge them all until
-	 * the end of the list.
-	 */
-	mod_ev.status = DEPEVT_STATUS_LST;
-	dwc3_cleanup_done_reqs(dwc, dep, &mod_ev, -ESHUTDOWN);
-	dep->flags &= ~DWC3_EP_BUSY;
-	/* pending requests are ignored and are queued on XferNotReady */
-}
-
-static void dwc3_ep_cmd_compl(struct dwc3_ep *dep,
-		const struct dwc3_event_depevt *event)
-{
-	u32 param = event->parameters;
-	u32 cmd_type = (param >> 8) & ((1 << 5) - 1);
-
-	switch (cmd_type) {
-	case DWC3_DEPCMD_ENDTRANSFER:
-		dwc3_process_ep_cmd_complete(dep, event);
-		break;
-	case DWC3_DEPCMD_STARTTRANSFER:
-		dep->res_trans_idx = param & 0x7f;
-		break;
-	default:
-		printk(KERN_ERR "%s() unknown /unexpected type: %d\n",
-				__func__, cmd_type);
-		break;
-	};
-}
-
 static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 		const struct dwc3_event_depevt *event)
 		const struct dwc3_event_depevt *event)
 {
 {
@@ -1724,6 +1775,9 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 
 
 	dep = dwc->eps[epnum];
 	dep = dwc->eps[epnum];
 
 
+	if (!(dep->flags & DWC3_EP_ENABLED))
+		return;
+
 	dev_vdbg(dwc->dev, "%s: %s\n", dep->name,
 	dev_vdbg(dwc->dev, "%s: %s\n", dep->name,
 			dwc3_ep_event_string(event->endpoint_event));
 			dwc3_ep_event_string(event->endpoint_event));
 
 
@@ -1734,7 +1788,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 
 
 	switch (event->endpoint_event) {
 	switch (event->endpoint_event) {
 	case DWC3_DEPEVT_XFERCOMPLETE:
 	case DWC3_DEPEVT_XFERCOMPLETE:
-		dep->res_trans_idx = 0;
+		dep->resource_index = 0;
 
 
 		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
 		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
 			dev_dbg(dwc->dev, "%s is an Isochronous endpoint\n",
 			dev_dbg(dwc->dev, "%s is an Isochronous endpoint\n",
@@ -1797,7 +1851,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 		dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name);
 		dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name);
 		break;
 		break;
 	case DWC3_DEPEVT_EPCMDCMPLT:
 	case DWC3_DEPEVT_EPCMDCMPLT:
-		dwc3_ep_cmd_compl(dep, event);
+		dev_vdbg(dwc->dev, "Endpoint Command Complete\n");
 		break;
 		break;
 	}
 	}
 }
 }
@@ -1820,16 +1874,16 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum)
 
 
 	dep = dwc->eps[epnum];
 	dep = dwc->eps[epnum];
 
 
-	WARN_ON(!dep->res_trans_idx);
-	if (dep->res_trans_idx) {
-		cmd = DWC3_DEPCMD_ENDTRANSFER;
-		cmd |= DWC3_DEPCMD_HIPRI_FORCERM | DWC3_DEPCMD_CMDIOC;
-		cmd |= DWC3_DEPCMD_PARAM(dep->res_trans_idx);
-		memset(&params, 0, sizeof(params));
-		ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, &params);
-		WARN_ON_ONCE(ret);
-		dep->res_trans_idx = 0;
-	}
+	if (!dep->resource_index)
+		return;
+
+	cmd = DWC3_DEPCMD_ENDTRANSFER;
+	cmd |= DWC3_DEPCMD_HIPRI_FORCERM | DWC3_DEPCMD_CMDIOC;
+	cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
+	memset(&params, 0, sizeof(params));
+	ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, &params);
+	WARN_ON_ONCE(ret);
+	dep->resource_index = 0;
 }
 }
 
 
 static void dwc3_stop_active_transfers(struct dwc3 *dwc)
 static void dwc3_stop_active_transfers(struct dwc3 *dwc)
@@ -1872,11 +1926,9 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
 
 
 static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
 static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
 {
 {
+	int			reg;
+
 	dev_vdbg(dwc->dev, "%s\n", __func__);
 	dev_vdbg(dwc->dev, "%s\n", __func__);
-#if 0
-	XXX
-	U1/U2 is powersave optimization. Skip it for now. Anyway we need to
-	enable it before we can disable it.
 
 
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	reg &= ~DWC3_DCTL_INITU1ENA;
 	reg &= ~DWC3_DCTL_INITU1ENA;
@@ -1884,9 +1936,7 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
 
 
 	reg &= ~DWC3_DCTL_INITU2ENA;
 	reg &= ~DWC3_DCTL_INITU2ENA;
 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
-#endif
 
 
-	dwc3_stop_active_transfers(dwc);
 	dwc3_disconnect_gadget(dwc);
 	dwc3_disconnect_gadget(dwc);
 	dwc->start_config_issued = false;
 	dwc->start_config_issued = false;
 
 
@@ -1894,30 +1944,30 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
 	dwc->setup_packet_pending = false;
 	dwc->setup_packet_pending = false;
 }
 }
 
 
-static void dwc3_gadget_usb3_phy_power(struct dwc3 *dwc, int on)
+static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend)
 {
 {
 	u32			reg;
 	u32			reg;
 
 
 	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
 	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
 
 
-	if (on)
-		reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
-	else
+	if (suspend)
 		reg |= DWC3_GUSB3PIPECTL_SUSPHY;
 		reg |= DWC3_GUSB3PIPECTL_SUSPHY;
+	else
+		reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
 
 
 	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
 	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
 }
 }
 
 
-static void dwc3_gadget_usb2_phy_power(struct dwc3 *dwc, int on)
+static void dwc3_gadget_usb2_phy_suspend(struct dwc3 *dwc, int suspend)
 {
 {
 	u32			reg;
 	u32			reg;
 
 
 	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
 	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
 
 
-	if (on)
-		reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
-	else
+	if (suspend)
 		reg |= DWC3_GUSB2PHYCFG_SUSPHY;
 		reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+	else
+		reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
 
 
 	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 }
 }
@@ -1962,16 +2012,18 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 	/* after reset -> Default State */
 	/* after reset -> Default State */
 	dwc->dev_state = DWC3_DEFAULT_STATE;
 	dwc->dev_state = DWC3_DEFAULT_STATE;
 
 
-	/* Enable PHYs */
-	dwc3_gadget_usb2_phy_power(dwc, true);
-	dwc3_gadget_usb3_phy_power(dwc, true);
+	/* Recent versions support automatic phy suspend and don't need this */
+	if (dwc->revision < DWC3_REVISION_194A) {
+		/* Resume PHYs */
+		dwc3_gadget_usb2_phy_suspend(dwc, false);
+		dwc3_gadget_usb3_phy_suspend(dwc, false);
+	}
 
 
 	if (dwc->gadget.speed != USB_SPEED_UNKNOWN)
 	if (dwc->gadget.speed != USB_SPEED_UNKNOWN)
 		dwc3_disconnect_gadget(dwc);
 		dwc3_disconnect_gadget(dwc);
 
 
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	reg &= ~DWC3_DCTL_TSTCTRL_MASK;
 	reg &= ~DWC3_DCTL_TSTCTRL_MASK;
-	reg &= ~(DWC3_DCTL_INITU1ENA | DWC3_DCTL_INITU2ENA);
 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 	dwc->test_mode = false;
 	dwc->test_mode = false;
 
 
@@ -2010,16 +2062,16 @@ static void dwc3_update_ram_clk_sel(struct dwc3 *dwc, u32 speed)
 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 }
 }
 
 
-static void dwc3_gadget_disable_phy(struct dwc3 *dwc, u8 speed)
+static void dwc3_gadget_phy_suspend(struct dwc3 *dwc, u8 speed)
 {
 {
 	switch (speed) {
 	switch (speed) {
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER:
-		dwc3_gadget_usb2_phy_power(dwc, false);
+		dwc3_gadget_usb2_phy_suspend(dwc, true);
 		break;
 		break;
 	case USB_SPEED_HIGH:
 	case USB_SPEED_HIGH:
 	case USB_SPEED_FULL:
 	case USB_SPEED_FULL:
 	case USB_SPEED_LOW:
 	case USB_SPEED_LOW:
-		dwc3_gadget_usb3_phy_power(dwc, false);
+		dwc3_gadget_usb3_phy_suspend(dwc, true);
 		break;
 		break;
 	}
 	}
 }
 }
@@ -2082,8 +2134,11 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 		break;
 		break;
 	}
 	}
 
 
-	/* Disable unneded PHY */
-	dwc3_gadget_disable_phy(dwc, dwc->gadget.speed);
+	/* Recent versions support automatic phy suspend and don't need this */
+	if (dwc->revision < DWC3_REVISION_194A) {
+		/* Suspend unneeded PHY */
+		dwc3_gadget_phy_suspend(dwc, dwc->gadget.speed);
+	}
 
 
 	dep = dwc->eps[0];
 	dep = dwc->eps[0];
 	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL);
 	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL);
@@ -2373,10 +2428,6 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
 	reg |= DWC3_DCFG_LPM_CAP;
 	reg |= DWC3_DCFG_LPM_CAP;
 	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 
 
-	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-	reg |= DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA;
-	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
-
 	/* Enable all but Start and End of Frame IRQs */
 	/* Enable all but Start and End of Frame IRQs */
 	reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
 	reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
 			DWC3_DEVTEN_EVNTOVERFLOWEN |
 			DWC3_DEVTEN_EVNTOVERFLOWEN |
@@ -2389,6 +2440,24 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
 			DWC3_DEVTEN_DISCONNEVTEN);
 			DWC3_DEVTEN_DISCONNEVTEN);
 	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
 	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
 
 
+	/* Enable USB2 LPM and automatic phy suspend only on recent versions */
+	if (dwc->revision >= DWC3_REVISION_194A) {
+		reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+		reg |= DWC3_DCFG_LPM_CAP;
+		dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+
+		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+		reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN);
+
+		/* TODO: This should be configurable */
+		reg |= DWC3_DCTL_HIRD_THRES(28);
+
+		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
+		dwc3_gadget_usb2_phy_suspend(dwc, false);
+		dwc3_gadget_usb3_phy_suspend(dwc, false);
+	}
+
 	ret = device_register(&dwc->gadget.dev);
 	ret = device_register(&dwc->gadget.dev);
 	if (ret) {
 	if (ret) {
 		dev_err(dwc->dev, "failed to register gadget device\n");
 		dev_err(dwc->dev, "failed to register gadget device\n");

+ 6 - 0
drivers/usb/dwc3/gadget.h

@@ -66,7 +66,12 @@ struct dwc3;
 #define DWC3_DEPCFG_FIFO_NUMBER(n)	((n) << 17)
 #define DWC3_DEPCFG_FIFO_NUMBER(n)	((n) << 17)
 #define DWC3_DEPCFG_BURST_SIZE(n)	((n) << 22)
 #define DWC3_DEPCFG_BURST_SIZE(n)	((n) << 22)
 #define DWC3_DEPCFG_DATA_SEQ_NUM(n)	((n) << 26)
 #define DWC3_DEPCFG_DATA_SEQ_NUM(n)	((n) << 26)
+/* This applies for core versions earlier than 1.94a */
 #define DWC3_DEPCFG_IGN_SEQ_NUM		(1 << 31)
 #define DWC3_DEPCFG_IGN_SEQ_NUM		(1 << 31)
+/* These apply for core versions 1.94a and later */
+#define DWC3_DEPCFG_ACTION_INIT		(0 << 30)
+#define DWC3_DEPCFG_ACTION_RESTORE	(1 << 30)
+#define DWC3_DEPCFG_ACTION_MODIFY	(2 << 30)
 
 
 /* DEPXFERCFG parameter 0 */
 /* DEPXFERCFG parameter 0 */
 #define DWC3_DEPXFERCFG_NUM_XFER_RES(n)	((n) & 0xffff)
 #define DWC3_DEPXFERCFG_NUM_XFER_RES(n)	((n) & 0xffff)
@@ -106,6 +111,7 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state);
 void dwc3_ep0_interrupt(struct dwc3 *dwc,
 void dwc3_ep0_interrupt(struct dwc3 *dwc,
 		const struct dwc3_event_depevt *event);
 		const struct dwc3_event_depevt *event);
 void dwc3_ep0_out_start(struct dwc3 *dwc);
 void dwc3_ep0_out_start(struct dwc3 *dwc);
+int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value);
 int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
 int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
 		gfp_t gfp_flags);
 		gfp_t gfp_flags);
 int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value);
 int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value);

+ 1 - 1
drivers/usb/early/ehci-dbgp.c

@@ -334,7 +334,7 @@ static int dbgp_control_msg(unsigned devnum, int requesttype,
 	int ret;
 	int ret;
 
 
 	read = (requesttype & USB_DIR_IN) != 0;
 	read = (requesttype & USB_DIR_IN) != 0;
-	if (size > (read ? DBGP_MAX_PACKET:0))
+	if (size > (read ? DBGP_MAX_PACKET : 0))
 		return -1;
 		return -1;
 
 
 	/* Compute the control message */
 	/* Compute the control message */

+ 9 - 0
drivers/usb/gadget/Kconfig

@@ -321,6 +321,15 @@ config USB_MV_UDC
 	  USB2.0 OTG controller, which can be configured as high speed or
 	  USB2.0 OTG controller, which can be configured as high speed or
 	  full speed USB peripheral.
 	  full speed USB peripheral.
 
 
+config USB_MV_U3D
+	tristate "MARVELL PXA2128 USB 3.0 controller"
+	depends on CPU_MMP3
+	select USB_GADGET_DUALSPEED
+	select USB_GADGET_SUPERSPEED
+	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
 # Controllers available in both integrated and discrete versions
 #
 #

+ 1 - 0
drivers/usb/gadget/Makefile

@@ -29,6 +29,7 @@ obj-$(CONFIG_USB_EG20T)		+= pch_udc.o
 obj-$(CONFIG_USB_MV_UDC)	+= mv_udc.o
 obj-$(CONFIG_USB_MV_UDC)	+= mv_udc.o
 mv_udc-y			:= mv_udc_core.o
 mv_udc-y			:= mv_udc_core.o
 obj-$(CONFIG_USB_FUSB300)	+= fusb300_udc.o
 obj-$(CONFIG_USB_FUSB300)	+= fusb300_udc.o
+obj-$(CONFIG_USB_MV_U3D)	+= mv_u3d_core.o
 
 
 #
 #
 # USB gadget drivers
 # USB gadget drivers

+ 1 - 0
drivers/usb/gadget/acm_ms.c

@@ -235,6 +235,7 @@ static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
 static struct usb_composite_driver acm_ms_driver = {
 static struct usb_composite_driver acm_ms_driver = {
 	.name		= "g_acm_ms",
 	.name		= "g_acm_ms",
 	.dev		= &device_desc,
 	.dev		= &device_desc,
+	.max_speed	= USB_SPEED_SUPER,
 	.strings	= dev_strings,
 	.strings	= dev_strings,
 	.unbind		= __exit_p(acm_ms_unbind),
 	.unbind		= __exit_p(acm_ms_unbind),
 };
 };

+ 1 - 0
drivers/usb/gadget/at91_udc.c

@@ -1634,6 +1634,7 @@ static int at91_start(struct usb_gadget *gadget,
 	udc = container_of(gadget, struct at91_udc, gadget);
 	udc = container_of(gadget, struct at91_udc, gadget);
 	udc->driver = driver;
 	udc->driver = driver;
 	udc->gadget.dev.driver = &driver->driver;
 	udc->gadget.dev.driver = &driver->driver;
+	udc->gadget.dev.of_node = udc->pdev->dev.of_node;
 	dev_set_drvdata(&udc->gadget.dev, &driver->driver);
 	dev_set_drvdata(&udc->gadget.dev, &driver->driver);
 	udc->enabled = 1;
 	udc->enabled = 1;
 	udc->selfpowered = 1;
 	udc->selfpowered = 1;

+ 5 - 2
drivers/usb/gadget/composite.c

@@ -117,6 +117,7 @@ int config_ep_by_speed(struct usb_gadget *g,
 			struct usb_function *f,
 			struct usb_function *f,
 			struct usb_ep *_ep)
 			struct usb_ep *_ep)
 {
 {
+	struct usb_composite_dev	*cdev = get_gadget_data(g);
 	struct usb_endpoint_descriptor *chosen_desc = NULL;
 	struct usb_endpoint_descriptor *chosen_desc = NULL;
 	struct usb_descriptor_header **speed_desc = NULL;
 	struct usb_descriptor_header **speed_desc = NULL;
 
 
@@ -180,10 +181,12 @@ ep_found:
 			_ep->mult = comp_desc->bmAttributes & 0x3;
 			_ep->mult = comp_desc->bmAttributes & 0x3;
 		case USB_ENDPOINT_XFER_BULK:
 		case USB_ENDPOINT_XFER_BULK:
 		case USB_ENDPOINT_XFER_INT:
 		case USB_ENDPOINT_XFER_INT:
-			_ep->maxburst = comp_desc->bMaxBurst;
+			_ep->maxburst = comp_desc->bMaxBurst + 1;
 			break;
 			break;
 		default:
 		default:
-			/* Do nothing for control endpoints */
+			if (comp_desc->bMaxBurst != 0)
+				ERROR(cdev, "ep0 bMaxBurst must be 0\n");
+			_ep->maxburst = 1;
 			break;
 			break;
 		}
 		}
 	}
 	}

+ 7 - 0
drivers/usb/gadget/f_fs.c

@@ -21,6 +21,7 @@
 #include <linux/blkdev.h>
 #include <linux/blkdev.h>
 #include <linux/pagemap.h>
 #include <linux/pagemap.h>
 #include <linux/export.h>
 #include <linux/export.h>
+#include <linux/hid.h>
 #include <asm/unaligned.h>
 #include <asm/unaligned.h>
 
 
 #include <linux/usb/composite.h>
 #include <linux/usb/composite.h>
@@ -1671,6 +1672,12 @@ static int __must_check ffs_do_desc(char *data, unsigned len,
 	}
 	}
 		break;
 		break;
 
 
+	case HID_DT_HID:
+		pr_vdebug("hid descriptor\n");
+		if (length != sizeof(struct hid_descriptor))
+			goto inv_length;
+		break;
+
 	case USB_DT_OTG:
 	case USB_DT_OTG:
 		if (length != sizeof(struct usb_otg_descriptor))
 		if (length != sizeof(struct usb_otg_descriptor))
 			goto inv_length;
 			goto inv_length;

+ 165 - 43
drivers/usb/gadget/f_hid.c

@@ -26,6 +26,12 @@ static struct class *hidg_class;
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 /*                            HID gadget struct                            */
 /*                            HID gadget struct                            */
 
 
+struct f_hidg_req_list {
+	struct usb_request	*req;
+	unsigned int		pos;
+	struct list_head 	list;
+};
+
 struct f_hidg {
 struct f_hidg {
 	/* configuration */
 	/* configuration */
 	unsigned char			bInterfaceSubClass;
 	unsigned char			bInterfaceSubClass;
@@ -35,10 +41,10 @@ struct f_hidg {
 	unsigned short			report_length;
 	unsigned short			report_length;
 
 
 	/* recv report */
 	/* recv report */
-	char				*set_report_buff;
-	unsigned short			set_report_length;
+	struct list_head		completed_out_req;
 	spinlock_t			spinlock;
 	spinlock_t			spinlock;
 	wait_queue_head_t		read_queue;
 	wait_queue_head_t		read_queue;
+	unsigned int			qlen;
 
 
 	/* send report */
 	/* send report */
 	struct mutex			lock;
 	struct mutex			lock;
@@ -49,7 +55,9 @@ struct f_hidg {
 	int				minor;
 	int				minor;
 	struct cdev			cdev;
 	struct cdev			cdev;
 	struct usb_function		func;
 	struct usb_function		func;
+
 	struct usb_ep			*in_ep;
 	struct usb_ep			*in_ep;
+	struct usb_ep			*out_ep;
 };
 };
 
 
 static inline struct f_hidg *func_to_hidg(struct usb_function *f)
 static inline struct f_hidg *func_to_hidg(struct usb_function *f)
@@ -65,7 +73,7 @@ static struct usb_interface_descriptor hidg_interface_desc = {
 	.bDescriptorType	= USB_DT_INTERFACE,
 	.bDescriptorType	= USB_DT_INTERFACE,
 	/* .bInterfaceNumber	= DYNAMIC */
 	/* .bInterfaceNumber	= DYNAMIC */
 	.bAlternateSetting	= 0,
 	.bAlternateSetting	= 0,
-	.bNumEndpoints		= 1,
+	.bNumEndpoints		= 2,
 	.bInterfaceClass	= USB_CLASS_HID,
 	.bInterfaceClass	= USB_CLASS_HID,
 	/* .bInterfaceSubClass	= DYNAMIC */
 	/* .bInterfaceSubClass	= DYNAMIC */
 	/* .bInterfaceProtocol	= DYNAMIC */
 	/* .bInterfaceProtocol	= DYNAMIC */
@@ -96,10 +104,23 @@ static struct usb_endpoint_descriptor hidg_hs_in_ep_desc = {
 				      */
 				      */
 };
 };
 
 
+static struct usb_endpoint_descriptor hidg_hs_out_ep_desc = {
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
+	.bEndpointAddress	= USB_DIR_OUT,
+	.bmAttributes		= USB_ENDPOINT_XFER_INT,
+	/*.wMaxPacketSize	= DYNAMIC */
+	.bInterval		= 4, /* FIXME: Add this field in the
+				      * HID gadget configuration?
+				      * (struct hidg_func_descriptor)
+				      */
+};
+
 static struct usb_descriptor_header *hidg_hs_descriptors[] = {
 static struct usb_descriptor_header *hidg_hs_descriptors[] = {
 	(struct usb_descriptor_header *)&hidg_interface_desc,
 	(struct usb_descriptor_header *)&hidg_interface_desc,
 	(struct usb_descriptor_header *)&hidg_desc,
 	(struct usb_descriptor_header *)&hidg_desc,
 	(struct usb_descriptor_header *)&hidg_hs_in_ep_desc,
 	(struct usb_descriptor_header *)&hidg_hs_in_ep_desc,
+	(struct usb_descriptor_header *)&hidg_hs_out_ep_desc,
 	NULL,
 	NULL,
 };
 };
 
 
@@ -117,10 +138,23 @@ static struct usb_endpoint_descriptor hidg_fs_in_ep_desc = {
 				       */
 				       */
 };
 };
 
 
+static struct usb_endpoint_descriptor hidg_fs_out_ep_desc = {
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
+	.bEndpointAddress	= USB_DIR_OUT,
+	.bmAttributes		= USB_ENDPOINT_XFER_INT,
+	/*.wMaxPacketSize	= DYNAMIC */
+	.bInterval		= 10, /* FIXME: Add this field in the
+				       * HID gadget configuration?
+				       * (struct hidg_func_descriptor)
+				       */
+};
+
 static struct usb_descriptor_header *hidg_fs_descriptors[] = {
 static struct usb_descriptor_header *hidg_fs_descriptors[] = {
 	(struct usb_descriptor_header *)&hidg_interface_desc,
 	(struct usb_descriptor_header *)&hidg_interface_desc,
 	(struct usb_descriptor_header *)&hidg_desc,
 	(struct usb_descriptor_header *)&hidg_desc,
 	(struct usb_descriptor_header *)&hidg_fs_in_ep_desc,
 	(struct usb_descriptor_header *)&hidg_fs_in_ep_desc,
+	(struct usb_descriptor_header *)&hidg_fs_out_ep_desc,
 	NULL,
 	NULL,
 };
 };
 
 
@@ -130,9 +164,11 @@ static struct usb_descriptor_header *hidg_fs_descriptors[] = {
 static ssize_t f_hidg_read(struct file *file, char __user *buffer,
 static ssize_t f_hidg_read(struct file *file, char __user *buffer,
 			size_t count, loff_t *ptr)
 			size_t count, loff_t *ptr)
 {
 {
-	struct f_hidg	*hidg     = file->private_data;
-	char		*tmp_buff = NULL;
-	unsigned long	flags;
+	struct f_hidg *hidg = file->private_data;
+	struct f_hidg_req_list *list;
+	struct usb_request *req;
+	unsigned long flags;
+	int ret;
 
 
 	if (!count)
 	if (!count)
 		return 0;
 		return 0;
@@ -142,8 +178,9 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
 
 
 	spin_lock_irqsave(&hidg->spinlock, flags);
 	spin_lock_irqsave(&hidg->spinlock, flags);
 
 
-#define READ_COND (hidg->set_report_buff != NULL)
+#define READ_COND (!list_empty(&hidg->completed_out_req))
 
 
+	/* wait for at least one buffer to complete */
 	while (!READ_COND) {
 	while (!READ_COND) {
 		spin_unlock_irqrestore(&hidg->spinlock, flags);
 		spin_unlock_irqrestore(&hidg->spinlock, flags);
 		if (file->f_flags & O_NONBLOCK)
 		if (file->f_flags & O_NONBLOCK)
@@ -155,19 +192,34 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
 		spin_lock_irqsave(&hidg->spinlock, flags);
 		spin_lock_irqsave(&hidg->spinlock, flags);
 	}
 	}
 
 
-
-	count = min_t(unsigned, count, hidg->set_report_length);
-	tmp_buff = hidg->set_report_buff;
-	hidg->set_report_buff = NULL;
-
+	/* pick the first one */
+	list = list_first_entry(&hidg->completed_out_req,
+				struct f_hidg_req_list, list);
+	req = list->req;
+	count = min_t(unsigned int, count, req->actual - list->pos);
 	spin_unlock_irqrestore(&hidg->spinlock, flags);
 	spin_unlock_irqrestore(&hidg->spinlock, flags);
 
 
-	if (tmp_buff != NULL) {
-		/* copy to user outside spinlock */
-		count -= copy_to_user(buffer, tmp_buff, count);
-		kfree(tmp_buff);
-	} else
-		count = -ENOMEM;
+	/* copy to user outside spinlock */
+	count -= copy_to_user(buffer, req->buf + list->pos, count);
+	list->pos += count;
+
+	/*
+	 * if this request is completely handled and transfered to
+	 * userspace, remove its entry from the list and requeue it
+	 * again. Otherwise, we will revisit it again upon the next
+	 * call, taking into account its current read position.
+	 */
+	if (list->pos == req->actual) {
+		spin_lock_irqsave(&hidg->spinlock, flags);
+		list_del(&list->list);
+		kfree(list);
+		spin_unlock_irqrestore(&hidg->spinlock, flags);
+
+		req->length = hidg->report_length;
+		ret = usb_ep_queue(hidg->out_ep, req, GFP_KERNEL);
+		if (ret < 0)
+			return ret;
+	}
 
 
 	return count;
 	return count;
 }
 }
@@ -282,28 +334,37 @@ static int f_hidg_open(struct inode *inode, struct file *fd)
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 /*                                usb_function                             */
 /*                                usb_function                             */
 
 
-static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req)
+static struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep, unsigned length)
 {
 {
-	struct f_hidg *hidg = (struct f_hidg *)req->context;
-
-	if (req->status != 0 || req->buf == NULL || req->actual == 0) {
-		ERROR(hidg->func.config->cdev, "%s FAILED\n", __func__);
-		return;
+	struct usb_request *req;
+
+	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+	if (req) {
+		req->length = length;
+		req->buf = kmalloc(length, GFP_ATOMIC);
+		if (!req->buf) {
+			usb_ep_free_request(ep, req);
+			req = NULL;
+		}
 	}
 	}
+	return req;
+}
 
 
-	spin_lock(&hidg->spinlock);
-
-	hidg->set_report_buff = krealloc(hidg->set_report_buff,
-					 req->actual, GFP_ATOMIC);
+static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_hidg *hidg = (struct f_hidg *) req->context;
+	struct f_hidg_req_list *req_list;
+	unsigned long flags;
 
 
-	if (hidg->set_report_buff == NULL) {
-		spin_unlock(&hidg->spinlock);
+	req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC);
+	if (!req_list)
 		return;
 		return;
-	}
-	hidg->set_report_length = req->actual;
-	memcpy(hidg->set_report_buff, req->buf, req->actual);
 
 
-	spin_unlock(&hidg->spinlock);
+	req_list->req = req;
+
+	spin_lock_irqsave(&hidg->spinlock, flags);
+	list_add_tail(&req_list->list, &hidg->completed_out_req);
+	spin_unlock_irqrestore(&hidg->spinlock, flags);
 
 
 	wake_up(&hidg->read_queue);
 	wake_up(&hidg->read_queue);
 }
 }
@@ -344,9 +405,7 @@ static int hidg_setup(struct usb_function *f,
 	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
 	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
 		  | HID_REQ_SET_REPORT):
 		  | HID_REQ_SET_REPORT):
 		VDBG(cdev, "set_report | wLenght=%d\n", ctrl->wLength);
 		VDBG(cdev, "set_report | wLenght=%d\n", ctrl->wLength);
-		req->context  = hidg;
-		req->complete = hidg_set_report_complete;
-		goto respond;
+		goto stall;
 		break;
 		break;
 
 
 	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
 	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
@@ -403,16 +462,25 @@ respond:
 static void hidg_disable(struct usb_function *f)
 static void hidg_disable(struct usb_function *f)
 {
 {
 	struct f_hidg *hidg = func_to_hidg(f);
 	struct f_hidg *hidg = func_to_hidg(f);
+	struct f_hidg_req_list *list, *next;
 
 
 	usb_ep_disable(hidg->in_ep);
 	usb_ep_disable(hidg->in_ep);
 	hidg->in_ep->driver_data = NULL;
 	hidg->in_ep->driver_data = NULL;
+
+	usb_ep_disable(hidg->out_ep);
+	hidg->out_ep->driver_data = NULL;
+
+	list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) {
+		list_del(&list->list);
+		kfree(list);
+	}
 }
 }
 
 
 static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 {
 {
 	struct usb_composite_dev		*cdev = f->config->cdev;
 	struct usb_composite_dev		*cdev = f->config->cdev;
 	struct f_hidg				*hidg = func_to_hidg(f);
 	struct f_hidg				*hidg = func_to_hidg(f);
-	int status = 0;
+	int i, status = 0;
 
 
 	VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt);
 	VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt);
 
 
@@ -429,11 +497,55 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 		}
 		}
 		status = usb_ep_enable(hidg->in_ep);
 		status = usb_ep_enable(hidg->in_ep);
 		if (status < 0) {
 		if (status < 0) {
-			ERROR(cdev, "Enable endpoint FAILED!\n");
+			ERROR(cdev, "Enable IN endpoint FAILED!\n");
 			goto fail;
 			goto fail;
 		}
 		}
 		hidg->in_ep->driver_data = hidg;
 		hidg->in_ep->driver_data = hidg;
 	}
 	}
+
+
+	if (hidg->out_ep != NULL) {
+		/* restart endpoint */
+		if (hidg->out_ep->driver_data != NULL)
+			usb_ep_disable(hidg->out_ep);
+
+		status = config_ep_by_speed(f->config->cdev->gadget, f,
+					    hidg->out_ep);
+		if (status) {
+			ERROR(cdev, "config_ep_by_speed FAILED!\n");
+			goto fail;
+		}
+		status = usb_ep_enable(hidg->out_ep);
+		if (status < 0) {
+			ERROR(cdev, "Enable IN endpoint FAILED!\n");
+			goto fail;
+		}
+		hidg->out_ep->driver_data = hidg;
+
+		/*
+		 * allocate a bunch of read buffers and queue them all at once.
+		 */
+		for (i = 0; i < hidg->qlen && status == 0; i++) {
+			struct usb_request *req =
+					hidg_alloc_ep_req(hidg->out_ep,
+							  hidg->report_length);
+			if (req) {
+				req->complete = hidg_set_report_complete;
+				req->context  = hidg;
+				status = usb_ep_queue(hidg->out_ep, req,
+						      GFP_ATOMIC);
+				if (status)
+					ERROR(cdev, "%s queue req --> %d\n",
+						hidg->out_ep->name, status);
+			} else {
+				usb_ep_disable(hidg->out_ep);
+				hidg->out_ep->driver_data = NULL;
+				status = -ENOMEM;
+				goto fail;
+			}
+		}
+	}
+
 fail:
 fail:
 	return status;
 	return status;
 }
 }
@@ -470,13 +582,18 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
 	ep->driver_data = c->cdev;	/* claim */
 	ep->driver_data = c->cdev;	/* claim */
 	hidg->in_ep = ep;
 	hidg->in_ep = ep;
 
 
+	ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_out_ep_desc);
+	if (!ep)
+		goto fail;
+	ep->driver_data = c->cdev;	/* claim */
+	hidg->out_ep = ep;
+
 	/* preallocate request and buffer */
 	/* preallocate request and buffer */
 	status = -ENOMEM;
 	status = -ENOMEM;
 	hidg->req = usb_ep_alloc_request(hidg->in_ep, GFP_KERNEL);
 	hidg->req = usb_ep_alloc_request(hidg->in_ep, GFP_KERNEL);
 	if (!hidg->req)
 	if (!hidg->req)
 		goto fail;
 		goto fail;
 
 
-
 	hidg->req->buf = kmalloc(hidg->report_length, GFP_KERNEL);
 	hidg->req->buf = kmalloc(hidg->report_length, GFP_KERNEL);
 	if (!hidg->req->buf)
 	if (!hidg->req->buf)
 		goto fail;
 		goto fail;
@@ -486,12 +603,12 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
 	hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
 	hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
 	hidg_hs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
 	hidg_hs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
 	hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
 	hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
+	hidg_hs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
+	hidg_fs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
 	hidg_desc.desc[0].bDescriptorType = HID_DT_REPORT;
 	hidg_desc.desc[0].bDescriptorType = HID_DT_REPORT;
 	hidg_desc.desc[0].wDescriptorLength =
 	hidg_desc.desc[0].wDescriptorLength =
 		cpu_to_le16(hidg->report_desc_length);
 		cpu_to_le16(hidg->report_desc_length);
 
 
-	hidg->set_report_buff = NULL;
-
 	/* copy descriptors */
 	/* copy descriptors */
 	f->descriptors = usb_copy_descriptors(hidg_fs_descriptors);
 	f->descriptors = usb_copy_descriptors(hidg_fs_descriptors);
 	if (!f->descriptors)
 	if (!f->descriptors)
@@ -500,6 +617,8 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
 	if (gadget_is_dualspeed(c->cdev->gadget)) {
 	if (gadget_is_dualspeed(c->cdev->gadget)) {
 		hidg_hs_in_ep_desc.bEndpointAddress =
 		hidg_hs_in_ep_desc.bEndpointAddress =
 			hidg_fs_in_ep_desc.bEndpointAddress;
 			hidg_fs_in_ep_desc.bEndpointAddress;
+		hidg_hs_out_ep_desc.bEndpointAddress =
+			hidg_fs_out_ep_desc.bEndpointAddress;
 		f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors);
 		f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors);
 		if (!f->hs_descriptors)
 		if (!f->hs_descriptors)
 			goto fail;
 			goto fail;
@@ -509,6 +628,7 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
 	spin_lock_init(&hidg->spinlock);
 	spin_lock_init(&hidg->spinlock);
 	init_waitqueue_head(&hidg->write_queue);
 	init_waitqueue_head(&hidg->write_queue);
 	init_waitqueue_head(&hidg->read_queue);
 	init_waitqueue_head(&hidg->read_queue);
+	INIT_LIST_HEAD(&hidg->completed_out_req);
 
 
 	/* create char device */
 	/* create char device */
 	cdev_init(&hidg->cdev, &f_hidg_fops);
 	cdev_init(&hidg->cdev, &f_hidg_fops);
@@ -553,7 +673,6 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
 	usb_free_descriptors(f->descriptors);
 	usb_free_descriptors(f->descriptors);
 
 
 	kfree(hidg->report_desc);
 	kfree(hidg->report_desc);
-	kfree(hidg->set_report_buff);
 	kfree(hidg);
 	kfree(hidg);
 }
 }
 
 
@@ -624,6 +743,9 @@ int __init hidg_bind_config(struct usb_configuration *c,
 	hidg->func.disable = hidg_disable;
 	hidg->func.disable = hidg_disable;
 	hidg->func.setup   = hidg_setup;
 	hidg->func.setup   = hidg_setup;
 
 
+	/* this could me made configurable at some point */
+	hidg->qlen	   = 4;
+
 	status = usb_add_function(c, &hidg->func);
 	status = usb_add_function(c, &hidg->func);
 	if (status)
 	if (status)
 		kfree(hidg);
 		kfree(hidg);

+ 31 - 102
drivers/usb/gadget/f_mass_storage.c

@@ -44,12 +44,12 @@
  * function for a USB device, it also illustrates a technique of
  * function for a USB device, it also illustrates a technique of
  * double-buffering for increased throughput.
  * double-buffering for increased throughput.
  *
  *
- * Function supports multiple logical units (LUNs).  Backing storage
- * for each LUN is provided by a regular file or a block device.
- * Access for each LUN can be limited to read-only.  Moreover, the
- * function can indicate that LUN is removable and/or CD-ROM.  (The
- * later implies read-only access.)
- *
+ * For more information about MSF and in particular its module
+ * parameters and sysfs interface read the
+ * <Documentation/usb/mass-storage.txt> file.
+ */
+
+/*
  * MSF is configured by specifying a fsg_config structure.  It has the
  * MSF is configured by specifying a fsg_config structure.  It has the
  * following fields:
  * following fields:
  *
  *
@@ -75,25 +75,6 @@
  *	->nofua		Flag specifying that FUA flag in SCSI WRITE(10,12)
  *	->nofua		Flag specifying that FUA flag in SCSI WRITE(10,12)
  *				commands for this LUN shall be ignored.
  *				commands for this LUN shall be ignored.
  *
  *
- *	lun_name_format	A printf-like format for names of the LUN
- *				devices.  This determines how the
- *				directory in sysfs will be named.
- *				Unless you are using several MSFs in
- *				a single gadget (as opposed to single
- *				MSF in many configurations) you may
- *				leave it as NULL (in which case
- *				"lun%d" will be used).  In the format
- *				you can use "%d" to index LUNs for
- *				MSF's with more than one LUN.  (Beware
- *				that there is only one integer given
- *				as an argument for the format and
- *				specifying invalid format may cause
- *				unspecified behaviour.)
- *	thread_name	Name of the kernel thread process used by the
- *				MSF.  You can safely set it to NULL
- *				(in which case default "file-storage"
- *				will be used).
- *
  *	vendor_name
  *	vendor_name
  *	product_name
  *	product_name
  *	release		Information used as a reply to INQUIRY
  *	release		Information used as a reply to INQUIRY
@@ -114,62 +95,6 @@
  * data track and no audio tracks; hence there need be only one
  * data track and no audio tracks; hence there need be only one
  * backing file per LUN.
  * backing file per LUN.
  *
  *
- *
- * MSF includes support for module parameters.  If gadget using it
- * decides to use it, the following module parameters will be
- * available:
- *
- *	file=filename[,filename...]
- *			Names of the files or block devices used for
- *				backing storage.
- *	ro=b[,b...]	Default false, boolean for read-only access.
- *	removable=b[,b...]
- *			Default true, boolean for removable media.
- *	cdrom=b[,b...]	Default false, boolean for whether to emulate
- *				a CD-ROM drive.
- *	nofua=b[,b...]	Default false, booleans for ignore FUA flag
- *				in SCSI WRITE(10,12) commands
- *	luns=N		Default N = number of filenames, number of
- *				LUNs to support.
- *	stall		Default determined according to the type of
- *				USB device controller (usually true),
- *				boolean to permit the driver to halt
- *				bulk endpoints.
- *
- * The module parameters may be prefixed with some string.  You need
- * to consult gadget's documentation or source to verify whether it is
- * using those module parameters and if it does what are the prefixes
- * (look for FSG_MODULE_PARAMETERS() macro usage, what's inside it is
- * the prefix).
- *
- *
- * Requirements are modest; only a bulk-in and a bulk-out endpoint are
- * needed.  The memory requirement amounts to two 16K buffers, size
- * configurable by a parameter.  Support is included for both
- * full-speed and high-speed operation.
- *
- * Note that the driver is slightly non-portable in that it assumes a
- * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
- * interrupt-in endpoints.  With most device controllers this isn't an
- * issue, but there may be some with hardware restrictions that prevent
- * a buffer from being used by more than one endpoint.
- *
- *
- * The pathnames of the backing files and the ro settings are
- * available in the attribute files "file" and "ro" in the lun<n> (or
- * to be more precise in a directory which name comes from
- * "lun_name_format" option!) subdirectory of the gadget's sysfs
- * directory.  If the "removable" option is set, writing to these
- * files will simulate ejecting/loading the medium (writing an empty
- * line means eject) and adjusting a write-enable tab.  Changes to the
- * ro setting are not allowed when the medium is loaded or if CD-ROM
- * emulation is being used.
- *
- * When a LUN receive an "eject" SCSI request (Start/Stop Unit),
- * if the LUN is removable, the backing file is released to simulate
- * ejection.
- *
- *
  * This function is heavily based on "File-backed Storage Gadget" by
  * This function is heavily based on "File-backed Storage Gadget" by
  * Alan Stern which in turn is heavily based on "Gadget Zero" by David
  * Alan Stern which in turn is heavily based on "Gadget Zero" by David
  * Brownell.  The driver's SCSI command interface was based on the
  * Brownell.  The driver's SCSI command interface was based on the
@@ -211,7 +136,7 @@
  * In normal operation the main thread is started during the gadget's
  * In normal operation the main thread is started during the gadget's
  * fsg_bind() callback and stopped during fsg_unbind().  But it can
  * fsg_bind() callback and stopped during fsg_unbind().  But it can
  * also exit when it receives a signal, and there's no point leaving
  * also exit when it receives a signal, and there's no point leaving
- * the gadget running when the thread is dead.  At of this moment, MSF
+ * the gadget running when the thread is dead.  As of this moment, MSF
  * provides no way to deregister the gadget when thread dies -- maybe
  * provides no way to deregister the gadget when thread dies -- maybe
  * a callback functions is needed.
  * a callback functions is needed.
  *
  *
@@ -417,9 +342,6 @@ struct fsg_config {
 		char nofua;
 		char nofua;
 	} luns[FSG_MAX_LUNS];
 	} luns[FSG_MAX_LUNS];
 
 
-	const char		*lun_name_format;
-	const char		*thread_name;
-
 	/* Callback functions. */
 	/* Callback functions. */
 	const struct fsg_operations	*ops;
 	const struct fsg_operations	*ops;
 	/* Gadget's private data. */
 	/* Gadget's private data. */
@@ -2687,11 +2609,15 @@ static int fsg_main_thread(void *common_)
 
 
 /*************************** DEVICE ATTRIBUTES ***************************/
 /*************************** DEVICE ATTRIBUTES ***************************/
 
 
-/* Write permission is checked per LUN in store_*() functions. */
 static DEVICE_ATTR(ro, 0644, fsg_show_ro, fsg_store_ro);
 static DEVICE_ATTR(ro, 0644, fsg_show_ro, fsg_store_ro);
 static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, fsg_store_nofua);
 static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, fsg_store_nofua);
 static DEVICE_ATTR(file, 0644, fsg_show_file, fsg_store_file);
 static DEVICE_ATTR(file, 0644, fsg_show_file, fsg_store_file);
 
 
+static struct device_attribute dev_attr_ro_cdrom =
+	__ATTR(ro, 0444, fsg_show_ro, NULL);
+static struct device_attribute dev_attr_file_nonremovable =
+	__ATTR(file, 0444, fsg_show_file, NULL);
+
 
 
 /****************************** FSG COMMON ******************************/
 /****************************** FSG COMMON ******************************/
 
 
@@ -2792,11 +2718,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
 		curlun->dev.parent = &gadget->dev;
 		curlun->dev.parent = &gadget->dev;
 		/* curlun->dev.driver = &fsg_driver.driver; XXX */
 		/* curlun->dev.driver = &fsg_driver.driver; XXX */
 		dev_set_drvdata(&curlun->dev, &common->filesem);
 		dev_set_drvdata(&curlun->dev, &common->filesem);
-		dev_set_name(&curlun->dev,
-			     cfg->lun_name_format
-			   ? cfg->lun_name_format
-			   : "lun%d",
-			     i);
+		dev_set_name(&curlun->dev, "lun%d", i);
 
 
 		rc = device_register(&curlun->dev);
 		rc = device_register(&curlun->dev);
 		if (rc) {
 		if (rc) {
@@ -2806,10 +2728,16 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
 			goto error_release;
 			goto error_release;
 		}
 		}
 
 
-		rc = device_create_file(&curlun->dev, &dev_attr_ro);
+		rc = device_create_file(&curlun->dev,
+					curlun->cdrom
+				      ? &dev_attr_ro_cdrom
+				      : &dev_attr_ro);
 		if (rc)
 		if (rc)
 			goto error_luns;
 			goto error_luns;
-		rc = device_create_file(&curlun->dev, &dev_attr_file);
+		rc = device_create_file(&curlun->dev,
+					curlun->removable
+				      ? &dev_attr_file
+				      : &dev_attr_file_nonremovable);
 		if (rc)
 		if (rc)
 			goto error_luns;
 			goto error_luns;
 		rc = device_create_file(&curlun->dev, &dev_attr_nofua);
 		rc = device_create_file(&curlun->dev, &dev_attr_nofua);
@@ -2878,8 +2806,7 @@ buffhds_first_it:
 
 
 	/* Tell the thread to start working */
 	/* Tell the thread to start working */
 	common->thread_task =
 	common->thread_task =
-		kthread_create(fsg_main_thread, common,
-			       cfg->thread_name ?: "file-storage");
+		kthread_create(fsg_main_thread, common, "file-storage");
 	if (IS_ERR(common->thread_task)) {
 	if (IS_ERR(common->thread_task)) {
 		rc = PTR_ERR(common->thread_task);
 		rc = PTR_ERR(common->thread_task);
 		goto error_release;
 		goto error_release;
@@ -2945,8 +2872,14 @@ static void fsg_common_release(struct kref *ref)
 		/* In error recovery common->nluns may be zero. */
 		/* In error recovery common->nluns may be zero. */
 		for (; i; --i, ++lun) {
 		for (; i; --i, ++lun) {
 			device_remove_file(&lun->dev, &dev_attr_nofua);
 			device_remove_file(&lun->dev, &dev_attr_nofua);
-			device_remove_file(&lun->dev, &dev_attr_ro);
-			device_remove_file(&lun->dev, &dev_attr_file);
+			device_remove_file(&lun->dev,
+					   lun->cdrom
+					 ? &dev_attr_ro_cdrom
+					 : &dev_attr_ro);
+			device_remove_file(&lun->dev,
+					   lun->removable
+					 ? &dev_attr_file
+					 : &dev_attr_file_nonremovable);
 			fsg_lun_close(lun);
 			fsg_lun_close(lun);
 			device_unregister(&lun->dev);
 			device_unregister(&lun->dev);
 		}
 		}
@@ -3167,8 +3100,7 @@ fsg_config_from_params(struct fsg_config *cfg,
 	for (i = 0, lun = cfg->luns; i < cfg->nluns; ++i, ++lun) {
 	for (i = 0, lun = cfg->luns; i < cfg->nluns; ++i, ++lun) {
 		lun->ro = !!params->ro[i];
 		lun->ro = !!params->ro[i];
 		lun->cdrom = !!params->cdrom[i];
 		lun->cdrom = !!params->cdrom[i];
-		lun->removable = /* Removable by default */
-			params->removable_count <= i || params->removable[i];
+		lun->removable = !!params->removable[i];
 		lun->filename =
 		lun->filename =
 			params->file_count > i && params->file[i][0]
 			params->file_count > i && params->file[i][0]
 			? params->file[i]
 			? params->file[i]
@@ -3176,8 +3108,6 @@ fsg_config_from_params(struct fsg_config *cfg,
 	}
 	}
 
 
 	/* Let MSF use defaults */
 	/* Let MSF use defaults */
-	cfg->lun_name_format = 0;
-	cfg->thread_name = 0;
 	cfg->vendor_name = 0;
 	cfg->vendor_name = 0;
 	cfg->product_name = 0;
 	cfg->product_name = 0;
 	cfg->release = 0xffff;
 	cfg->release = 0xffff;
@@ -3203,4 +3133,3 @@ fsg_common_from_params(struct fsg_common *common,
 	fsg_config_from_params(&cfg, params);
 	fsg_config_from_params(&cfg, params);
 	return fsg_common_init(common, cdev, &cfg);
 	return fsg_common_init(common, cdev, &cfg);
 }
 }
-

+ 241 - 46
drivers/usb/gadget/f_uvc.c

@@ -29,6 +29,25 @@
 
 
 unsigned int uvc_gadget_trace_param;
 unsigned int uvc_gadget_trace_param;
 
 
+/*-------------------------------------------------------------------------*/
+
+/* module parameters specific to the Video streaming endpoint */
+static unsigned streaming_interval = 1;
+module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(streaming_interval, "1 - 16");
+
+static unsigned streaming_maxpacket = 1024;
+module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(streaming_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
+
+static unsigned streaming_mult;
+module_param(streaming_mult, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(streaming_mult, "0 - 2 (hs/ss only)");
+
+static unsigned streaming_maxburst;
+module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
+
 /* --------------------------------------------------------------------------
 /* --------------------------------------------------------------------------
  * Function descriptors
  * Function descriptors
  */
  */
@@ -59,6 +78,8 @@ static struct usb_gadget_strings *uvc_function_strings[] = {
 #define UVC_INTF_VIDEO_CONTROL			0
 #define UVC_INTF_VIDEO_CONTROL			0
 #define UVC_INTF_VIDEO_STREAMING		1
 #define UVC_INTF_VIDEO_STREAMING		1
 
 
+#define STATUS_BYTECOUNT			16	/* 16 bytes status */
+
 static struct usb_interface_assoc_descriptor uvc_iad __initdata = {
 static struct usb_interface_assoc_descriptor uvc_iad __initdata = {
 	.bLength		= sizeof(uvc_iad),
 	.bLength		= sizeof(uvc_iad),
 	.bDescriptorType	= USB_DT_INTERFACE_ASSOCIATION,
 	.bDescriptorType	= USB_DT_INTERFACE_ASSOCIATION,
@@ -82,12 +103,12 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = {
 	.iInterface		= 0,
 	.iInterface		= 0,
 };
 };
 
 
-static struct usb_endpoint_descriptor uvc_control_ep __initdata = {
+static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bEndpointAddress	= USB_DIR_IN,
 	.bEndpointAddress	= USB_DIR_IN,
 	.bmAttributes		= USB_ENDPOINT_XFER_INT,
 	.bmAttributes		= USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize		= cpu_to_le16(16),
+	.wMaxPacketSize		= cpu_to_le16(STATUS_BYTECOUNT),
 	.bInterval		= 8,
 	.bInterval		= 8,
 };
 };
 
 
@@ -95,7 +116,7 @@ static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = {
 	.bLength		= UVC_DT_CONTROL_ENDPOINT_SIZE,
 	.bLength		= UVC_DT_CONTROL_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_CS_ENDPOINT,
 	.bDescriptorType	= USB_DT_CS_ENDPOINT,
 	.bDescriptorSubType	= UVC_EP_INTERRUPT,
 	.bDescriptorSubType	= UVC_EP_INTERRUPT,
-	.wMaxTransferSize	= cpu_to_le16(16),
+	.wMaxTransferSize	= cpu_to_le16(STATUS_BYTECOUNT),
 };
 };
 
 
 static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = {
 static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = {
@@ -122,7 +143,7 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = {
 	.iInterface		= 0,
 	.iInterface		= 0,
 };
 };
 
 
-static struct usb_endpoint_descriptor uvc_streaming_ep = {
+static struct usb_endpoint_descriptor uvc_fs_streaming_ep = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bEndpointAddress	= USB_DIR_IN,
 	.bEndpointAddress	= USB_DIR_IN,
@@ -131,15 +152,72 @@ static struct usb_endpoint_descriptor uvc_streaming_ep = {
 	.bInterval		= 1,
 	.bInterval		= 1,
 };
 };
 
 
+static struct usb_endpoint_descriptor uvc_hs_streaming_ep = {
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
+	.bEndpointAddress	= USB_DIR_IN,
+	.bmAttributes		= USB_ENDPOINT_XFER_ISOC,
+	.wMaxPacketSize		= cpu_to_le16(1024),
+	.bInterval		= 1,
+};
+
+/* super speed support */
+static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	cpu_to_le16(STATUS_BYTECOUNT),
+	.bInterval =		8,
+};
+
+static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = {
+	.bLength =		sizeof uvc_ss_control_comp,
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+
+	/* the following 3 values can be tweaked if necessary */
+	/* .bMaxBurst =		0, */
+	/* .bmAttributes =	0, */
+	.wBytesPerInterval =	cpu_to_le16(STATUS_BYTECOUNT),
+};
+
+static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_ISOC,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+	.bInterval =		4,
+};
+
+static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = {
+	.bLength =		sizeof uvc_ss_streaming_comp,
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+
+	/* the following 3 values can be tweaked if necessary */
+	.bMaxBurst =		0,
+	.bmAttributes =	0,
+	.wBytesPerInterval =	cpu_to_le16(1024),
+};
+
 static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
 static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
 	(struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
 	(struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
-	(struct usb_descriptor_header *) &uvc_streaming_ep,
+	(struct usb_descriptor_header *) &uvc_fs_streaming_ep,
 	NULL,
 	NULL,
 };
 };
 
 
 static const struct usb_descriptor_header * const uvc_hs_streaming[] = {
 static const struct usb_descriptor_header * const uvc_hs_streaming[] = {
 	(struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
 	(struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
-	(struct usb_descriptor_header *) &uvc_streaming_ep,
+	(struct usb_descriptor_header *) &uvc_hs_streaming_ep,
+	NULL,
+};
+
+static const struct usb_descriptor_header * const uvc_ss_streaming[] = {
+	(struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
+	(struct usb_descriptor_header *) &uvc_ss_streaming_ep,
+	(struct usb_descriptor_header *) &uvc_ss_streaming_comp,
 	NULL,
 	NULL,
 };
 };
 
 
@@ -215,6 +293,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
 	struct uvc_device *uvc = to_uvc(f);
 	struct uvc_device *uvc = to_uvc(f);
 	struct v4l2_event v4l2_event;
 	struct v4l2_event v4l2_event;
 	struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
 	struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
+	int ret;
 
 
 	INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
 	INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
 
 
@@ -262,7 +341,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
 			return 0;
 			return 0;
 
 
 		if (uvc->video.ep) {
 		if (uvc->video.ep) {
-			uvc->video.ep->desc = &uvc_streaming_ep;
+			ret = config_ep_by_speed(f->config->cdev->gadget,
+					&(uvc->func), uvc->video.ep);
+			if (ret)
+				return ret;
 			usb_ep_enable(uvc->video.ep);
 			usb_ep_enable(uvc->video.ep);
 		}
 		}
 
 
@@ -368,9 +450,11 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 {
 {
 	struct uvc_input_header_descriptor *uvc_streaming_header;
 	struct uvc_input_header_descriptor *uvc_streaming_header;
 	struct uvc_header_descriptor *uvc_control_header;
 	struct uvc_header_descriptor *uvc_control_header;
+	const struct uvc_descriptor_header * const *uvc_control_desc;
 	const struct uvc_descriptor_header * const *uvc_streaming_cls;
 	const struct uvc_descriptor_header * const *uvc_streaming_cls;
 	const struct usb_descriptor_header * const *uvc_streaming_std;
 	const struct usb_descriptor_header * const *uvc_streaming_std;
 	const struct usb_descriptor_header * const *src;
 	const struct usb_descriptor_header * const *src;
+	static struct usb_endpoint_descriptor *uvc_control_ep;
 	struct usb_descriptor_header **dst;
 	struct usb_descriptor_header **dst;
 	struct usb_descriptor_header **hdr;
 	struct usb_descriptor_header **hdr;
 	unsigned int control_size;
 	unsigned int control_size;
@@ -379,10 +463,29 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	unsigned int bytes;
 	unsigned int bytes;
 	void *mem;
 	void *mem;
 
 
-	uvc_streaming_cls = (speed == USB_SPEED_FULL)
-			  ? uvc->desc.fs_streaming : uvc->desc.hs_streaming;
-	uvc_streaming_std = (speed == USB_SPEED_FULL)
-			  ? uvc_fs_streaming : uvc_hs_streaming;
+	switch (speed) {
+	case USB_SPEED_SUPER:
+		uvc_control_desc = uvc->desc.ss_control;
+		uvc_streaming_cls = uvc->desc.ss_streaming;
+		uvc_streaming_std = uvc_ss_streaming;
+		uvc_control_ep = &uvc_ss_control_ep;
+		break;
+
+	case USB_SPEED_HIGH:
+		uvc_control_desc = uvc->desc.fs_control;
+		uvc_streaming_cls = uvc->desc.hs_streaming;
+		uvc_streaming_std = uvc_hs_streaming;
+		uvc_control_ep = &uvc_fs_control_ep;
+		break;
+
+	case USB_SPEED_FULL:
+	default:
+		uvc_control_desc = uvc->desc.fs_control;
+		uvc_streaming_cls = uvc->desc.fs_streaming;
+		uvc_streaming_std = uvc_fs_streaming;
+		uvc_control_ep = &uvc_fs_control_ep;
+		break;
+	}
 
 
 	/* Descriptors layout
 	/* Descriptors layout
 	 *
 	 *
@@ -400,16 +503,24 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	control_size = 0;
 	control_size = 0;
 	streaming_size = 0;
 	streaming_size = 0;
 	bytes = uvc_iad.bLength + uvc_control_intf.bLength
 	bytes = uvc_iad.bLength + uvc_control_intf.bLength
-	      + uvc_control_ep.bLength + uvc_control_cs_ep.bLength
+	      + uvc_control_ep->bLength + uvc_control_cs_ep.bLength
 	      + uvc_streaming_intf_alt0.bLength;
 	      + uvc_streaming_intf_alt0.bLength;
-	n_desc = 5;
 
 
-	for (src = (const struct usb_descriptor_header**)uvc->desc.control; *src; ++src) {
+	if (speed == USB_SPEED_SUPER) {
+		bytes += uvc_ss_control_comp.bLength;
+		n_desc = 6;
+	} else {
+		n_desc = 5;
+	}
+
+	for (src = (const struct usb_descriptor_header **)uvc_control_desc;
+			*src; ++src) {
 		control_size += (*src)->bLength;
 		control_size += (*src)->bLength;
 		bytes += (*src)->bLength;
 		bytes += (*src)->bLength;
 		n_desc++;
 		n_desc++;
 	}
 	}
-	for (src = (const struct usb_descriptor_header**)uvc_streaming_cls; *src; ++src) {
+	for (src = (const struct usb_descriptor_header **)uvc_streaming_cls;
+			*src; ++src) {
 		streaming_size += (*src)->bLength;
 		streaming_size += (*src)->bLength;
 		bytes += (*src)->bLength;
 		bytes += (*src)->bLength;
 		n_desc++;
 		n_desc++;
@@ -433,12 +544,15 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 
 
 	uvc_control_header = mem;
 	uvc_control_header = mem;
 	UVC_COPY_DESCRIPTORS(mem, dst,
 	UVC_COPY_DESCRIPTORS(mem, dst,
-		(const struct usb_descriptor_header**)uvc->desc.control);
+		(const struct usb_descriptor_header **)uvc_control_desc);
 	uvc_control_header->wTotalLength = cpu_to_le16(control_size);
 	uvc_control_header->wTotalLength = cpu_to_le16(control_size);
 	uvc_control_header->bInCollection = 1;
 	uvc_control_header->bInCollection = 1;
 	uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
 	uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
 
 
-	UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep);
+	UVC_COPY_DESCRIPTOR(mem, dst, uvc_control_ep);
+	if (speed == USB_SPEED_SUPER)
+		UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp);
+
 	UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_cs_ep);
 	UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_cs_ep);
 	UVC_COPY_DESCRIPTOR(mem, dst, &uvc_streaming_intf_alt0);
 	UVC_COPY_DESCRIPTOR(mem, dst, &uvc_streaming_intf_alt0);
 
 
@@ -446,7 +560,8 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	UVC_COPY_DESCRIPTORS(mem, dst,
 	UVC_COPY_DESCRIPTORS(mem, dst,
 		(const struct usb_descriptor_header**)uvc_streaming_cls);
 		(const struct usb_descriptor_header**)uvc_streaming_cls);
 	uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size);
 	uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size);
-	uvc_streaming_header->bEndpointAddress = uvc_streaming_ep.bEndpointAddress;
+	uvc_streaming_header->bEndpointAddress =
+		uvc_fs_streaming_ep.bEndpointAddress;
 
 
 	UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std);
 	UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std);
 
 
@@ -482,6 +597,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
 
 
 	kfree(f->descriptors);
 	kfree(f->descriptors);
 	kfree(f->hs_descriptors);
 	kfree(f->hs_descriptors);
+	kfree(f->ss_descriptors);
 
 
 	kfree(uvc);
 	kfree(uvc);
 }
 }
@@ -496,8 +612,26 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 
 
 	INFO(cdev, "uvc_function_bind\n");
 	INFO(cdev, "uvc_function_bind\n");
 
 
+	/* sanity check the streaming endpoint module parameters */
+	if (streaming_interval < 1)
+		streaming_interval = 1;
+	if (streaming_interval > 16)
+		streaming_interval = 16;
+	if (streaming_mult > 2)
+		streaming_mult = 2;
+	if (streaming_maxburst > 15)
+		streaming_maxburst = 15;
+
+	/*
+	 * fill in the FS video streaming specific descriptors from the
+	 * module parameters
+	 */
+	uvc_fs_streaming_ep.wMaxPacketSize = streaming_maxpacket > 1023 ?
+						1023 : streaming_maxpacket;
+	uvc_fs_streaming_ep.bInterval = streaming_interval;
+
 	/* Allocate endpoints. */
 	/* Allocate endpoints. */
-	ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);
+	ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_control_ep);
 	if (!ep) {
 	if (!ep) {
 		INFO(cdev, "Unable to allocate control EP\n");
 		INFO(cdev, "Unable to allocate control EP\n");
 		goto error;
 		goto error;
@@ -505,7 +639,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 	uvc->control_ep = ep;
 	uvc->control_ep = ep;
 	ep->driver_data = uvc;
 	ep->driver_data = uvc;
 
 
-	ep = usb_ep_autoconfig(cdev->gadget, &uvc_streaming_ep);
+	ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
 	if (!ep) {
 	if (!ep) {
 		INFO(cdev, "Unable to allocate streaming EP\n");
 		INFO(cdev, "Unable to allocate streaming EP\n");
 		goto error;
 		goto error;
@@ -526,9 +660,52 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 	uvc_streaming_intf_alt1.bInterfaceNumber = ret;
 	uvc_streaming_intf_alt1.bInterfaceNumber = ret;
 	uvc->streaming_intf = ret;
 	uvc->streaming_intf = ret;
 
 
-	/* Copy descriptors. */
+	/* sanity check the streaming endpoint module parameters */
+	if (streaming_maxpacket > 1024)
+		streaming_maxpacket = 1024;
+
+	/* Copy descriptors for FS. */
 	f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
 	f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
-	f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
+
+	/* support high speed hardware */
+	if (gadget_is_dualspeed(cdev->gadget)) {
+		/*
+		 * Fill in the HS descriptors from the module parameters for the
+		 * Video Streaming endpoint.
+		 * NOTE: We assume that the user knows what they are doing and
+		 * won't give parameters that their UDC doesn't support.
+		 */
+		uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
+		uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
+		uvc_hs_streaming_ep.bInterval = streaming_interval;
+		uvc_hs_streaming_ep.bEndpointAddress =
+				uvc_fs_streaming_ep.bEndpointAddress;
+
+		/* Copy descriptors. */
+		f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
+	}
+
+	/* support super speed hardware */
+	if (gadget_is_superspeed(c->cdev->gadget)) {
+		/*
+		 * Fill in the SS descriptors from the module parameters for the
+		 * Video Streaming endpoint.
+		 * NOTE: We assume that the user knows what they are doing and
+		 * won't give parameters that their UDC doesn't support.
+		 */
+		uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
+		uvc_ss_streaming_ep.bInterval = streaming_interval;
+		uvc_ss_streaming_comp.bmAttributes = streaming_mult;
+		uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
+		uvc_ss_streaming_comp.wBytesPerInterval =
+			streaming_maxpacket * (streaming_mult + 1) *
+			(streaming_maxburst + 1);
+		uvc_ss_streaming_ep.bEndpointAddress =
+				uvc_fs_streaming_ep.bEndpointAddress;
+
+		/* Copy descriptors. */
+		f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER);
+	}
 
 
 	/* Preallocate control endpoint request. */
 	/* Preallocate control endpoint request. */
 	uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
 	uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
@@ -583,9 +760,11 @@ error:
  */
  */
 int __init
 int __init
 uvc_bind_config(struct usb_configuration *c,
 uvc_bind_config(struct usb_configuration *c,
-		const struct uvc_descriptor_header * const *control,
+		const struct uvc_descriptor_header * const *fs_control,
+		const struct uvc_descriptor_header * const *ss_control,
 		const struct uvc_descriptor_header * const *fs_streaming,
 		const struct uvc_descriptor_header * const *fs_streaming,
-		const struct uvc_descriptor_header * const *hs_streaming)
+		const struct uvc_descriptor_header * const *hs_streaming,
+		const struct uvc_descriptor_header * const *ss_streaming)
 {
 {
 	struct uvc_device *uvc;
 	struct uvc_device *uvc;
 	int ret = 0;
 	int ret = 0;
@@ -603,38 +782,54 @@ uvc_bind_config(struct usb_configuration *c,
 	uvc->state = UVC_STATE_DISCONNECTED;
 	uvc->state = UVC_STATE_DISCONNECTED;
 
 
 	/* Validate the descriptors. */
 	/* Validate the descriptors. */
-	if (control == NULL || control[0] == NULL ||
-	    control[0]->bDescriptorSubType != UVC_VC_HEADER)
+	if (fs_control == NULL || fs_control[0] == NULL ||
+		fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
 		goto error;
 		goto error;
 
 
-	if (fs_streaming == NULL || fs_streaming[0] == NULL ||
-	    fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+	if (ss_control == NULL || ss_control[0] == NULL ||
+		ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
 		goto error;
 		goto error;
 
 
-	if (hs_streaming == NULL || hs_streaming[0] == NULL ||
-	    hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+	if (fs_streaming == NULL || fs_streaming[0] == NULL ||
+		fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 		goto error;
 		goto error;
 
 
-	uvc->desc.control = control;
-	uvc->desc.fs_streaming = fs_streaming;
-	uvc->desc.hs_streaming = hs_streaming;
-
-	/* Allocate string descriptor numbers. */
-	if ((ret = usb_string_id(c->cdev)) < 0)
+	if (hs_streaming == NULL || hs_streaming[0] == NULL ||
+		hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 		goto error;
 		goto error;
-	uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret;
-	uvc_iad.iFunction = ret;
 
 
-	if ((ret = usb_string_id(c->cdev)) < 0)
+	if (ss_streaming == NULL || ss_streaming[0] == NULL ||
+		ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 		goto error;
 		goto error;
-	uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret;
-	uvc_control_intf.iInterface = ret;
 
 
-	if ((ret = usb_string_id(c->cdev)) < 0)
-		goto error;
-	uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret;
-	uvc_streaming_intf_alt0.iInterface = ret;
-	uvc_streaming_intf_alt1.iInterface = ret;
+	uvc->desc.fs_control = fs_control;
+	uvc->desc.ss_control = ss_control;
+	uvc->desc.fs_streaming = fs_streaming;
+	uvc->desc.hs_streaming = hs_streaming;
+	uvc->desc.ss_streaming = ss_streaming;
+
+	/* maybe allocate device-global string IDs, and patch descriptors */
+	if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) {
+		/* Allocate string descriptor numbers. */
+		ret = usb_string_id(c->cdev);
+		if (ret < 0)
+			goto error;
+		uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret;
+		uvc_iad.iFunction = ret;
+
+		ret = usb_string_id(c->cdev);
+		if (ret < 0)
+			goto error;
+		uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret;
+		uvc_control_intf.iInterface = ret;
+
+		ret = usb_string_id(c->cdev);
+		if (ret < 0)
+			goto error;
+		uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret;
+		uvc_streaming_intf_alt0.iInterface = ret;
+		uvc_streaming_intf_alt1.iInterface = ret;
+	}
 
 
 	/* Register the function. */
 	/* Register the function. */
 	uvc->func.name = "uvc";
 	uvc->func.name = "uvc";

+ 5 - 3
drivers/usb/gadget/f_uvc.h

@@ -17,9 +17,11 @@
 #include <linux/usb/video.h>
 #include <linux/usb/video.h>
 
 
 extern int uvc_bind_config(struct usb_configuration *c,
 extern int uvc_bind_config(struct usb_configuration *c,
-			   const struct uvc_descriptor_header * const *control,
-			   const struct uvc_descriptor_header * const *fs_streaming,
-			   const struct uvc_descriptor_header * const *hs_streaming);
+		   const struct uvc_descriptor_header * const *fs_control,
+		   const struct uvc_descriptor_header * const *hs_control,
+		   const struct uvc_descriptor_header * const *fs_streaming,
+		   const struct uvc_descriptor_header * const *hs_streaming,
+		   const struct uvc_descriptor_header * const *ss_streaming);
 
 
 #endif /* _F_UVC_H_ */
 #endif /* _F_UVC_H_ */
 
 

+ 31 - 43
drivers/usb/gadget/fsl_mxc_udc.c

@@ -21,7 +21,8 @@
 #include <mach/hardware.h>
 #include <mach/hardware.h>
 
 
 static struct clk *mxc_ahb_clk;
 static struct clk *mxc_ahb_clk;
-static struct clk *mxc_usb_clk;
+static struct clk *mxc_per_clk;
+static struct clk *mxc_ipg_clk;
 
 
 /* workaround ENGcm09152 for i.MX35 */
 /* workaround ENGcm09152 for i.MX35 */
 #define USBPHYCTRL_OTGBASE_OFFSET	0x608
 #define USBPHYCTRL_OTGBASE_OFFSET	0x608
@@ -35,28 +36,31 @@ int fsl_udc_clk_init(struct platform_device *pdev)
 
 
 	pdata = pdev->dev.platform_data;
 	pdata = pdev->dev.platform_data;
 
 
-	if (!cpu_is_mx35() && !cpu_is_mx25()) {
-		mxc_ahb_clk = clk_get(&pdev->dev, "usb_ahb");
-		if (IS_ERR(mxc_ahb_clk))
-			return PTR_ERR(mxc_ahb_clk);
+	mxc_ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(mxc_ipg_clk)) {
+		dev_err(&pdev->dev, "clk_get(\"ipg\") failed\n");
+		return PTR_ERR(mxc_ipg_clk);
+	}
 
 
-		ret = clk_enable(mxc_ahb_clk);
-		if (ret < 0) {
-			dev_err(&pdev->dev, "clk_enable(\"usb_ahb\") failed\n");
-			goto eenahb;
-		}
+	mxc_ahb_clk = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(mxc_ahb_clk)) {
+		dev_err(&pdev->dev, "clk_get(\"ahb\") failed\n");
+		return PTR_ERR(mxc_ahb_clk);
 	}
 	}
 
 
-	/* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */
-	mxc_usb_clk = clk_get(&pdev->dev, "usb");
-	if (IS_ERR(mxc_usb_clk)) {
-		dev_err(&pdev->dev, "clk_get(\"usb\") failed\n");
-		ret = PTR_ERR(mxc_usb_clk);
-		goto egusb;
+	mxc_per_clk = devm_clk_get(&pdev->dev, "per");
+	if (IS_ERR(mxc_per_clk)) {
+		dev_err(&pdev->dev, "clk_get(\"per\") failed\n");
+		return PTR_ERR(mxc_per_clk);
 	}
 	}
 
 
+	clk_prepare_enable(mxc_ipg_clk);
+	clk_prepare_enable(mxc_ahb_clk);
+	clk_prepare_enable(mxc_per_clk);
+
+	/* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */
 	if (!cpu_is_mx51()) {
 	if (!cpu_is_mx51()) {
-		freq = clk_get_rate(mxc_usb_clk);
+		freq = clk_get_rate(mxc_per_clk);
 		if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
 		if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
 		    (freq < 59999000 || freq > 60001000)) {
 		    (freq < 59999000 || freq > 60001000)) {
 			dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq);
 			dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq);
@@ -65,24 +69,13 @@ int fsl_udc_clk_init(struct platform_device *pdev)
 		}
 		}
 	}
 	}
 
 
-	ret = clk_enable(mxc_usb_clk);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "clk_enable(\"usb_clk\") failed\n");
-		goto eenusb;
-	}
-
 	return 0;
 	return 0;
 
 
-eenusb:
 eclkrate:
 eclkrate:
-	clk_put(mxc_usb_clk);
-	mxc_usb_clk = NULL;
-egusb:
-	if (!cpu_is_mx35())
-		clk_disable(mxc_ahb_clk);
-eenahb:
-	if (!cpu_is_mx35())
-		clk_put(mxc_ahb_clk);
+	clk_disable_unprepare(mxc_ipg_clk);
+	clk_disable_unprepare(mxc_ahb_clk);
+	clk_disable_unprepare(mxc_per_clk);
+	mxc_per_clk = NULL;
 	return ret;
 	return ret;
 }
 }
 
 
@@ -104,20 +97,15 @@ void fsl_udc_clk_finalize(struct platform_device *pdev)
 
 
 	/* ULPI transceivers don't need usbpll */
 	/* ULPI transceivers don't need usbpll */
 	if (pdata->phy_mode == FSL_USB2_PHY_ULPI) {
 	if (pdata->phy_mode == FSL_USB2_PHY_ULPI) {
-		clk_disable(mxc_usb_clk);
-		clk_put(mxc_usb_clk);
-		mxc_usb_clk = NULL;
+		clk_disable_unprepare(mxc_per_clk);
+		mxc_per_clk = NULL;
 	}
 	}
 }
 }
 
 
 void fsl_udc_clk_release(void)
 void fsl_udc_clk_release(void)
 {
 {
-	if (mxc_usb_clk) {
-		clk_disable(mxc_usb_clk);
-		clk_put(mxc_usb_clk);
-	}
-	if (!cpu_is_mx35()) {
-		clk_disable(mxc_ahb_clk);
-		clk_put(mxc_ahb_clk);
-	}
+	if (mxc_per_clk)
+		clk_disable_unprepare(mxc_per_clk);
+	clk_disable_unprepare(mxc_ahb_clk);
+	clk_disable_unprepare(mxc_ipg_clk);
 }
 }

+ 10 - 8
drivers/usb/gadget/fsl_udc_core.c

@@ -24,6 +24,7 @@
 #include <linux/ioport.h>
 #include <linux/ioport.h>
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
+#include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/list.h>
@@ -1229,7 +1230,7 @@ static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 	struct fsl_udc *udc;
 	struct fsl_udc *udc;
 
 
 	udc = container_of(gadget, struct fsl_udc, gadget);
 	udc = container_of(gadget, struct fsl_udc, gadget);
-	if (udc->transceiver)
+	if (!IS_ERR_OR_NULL(udc->transceiver))
 		return usb_phy_set_power(udc->transceiver, mA);
 		return usb_phy_set_power(udc->transceiver, mA);
 	return -ENOTSUPP;
 	return -ENOTSUPP;
 }
 }
@@ -1983,13 +1984,13 @@ static int fsl_start(struct usb_gadget_driver *driver,
 		goto out;
 		goto out;
 	}
 	}
 
 
-	if (udc_controller->transceiver) {
+	if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
 		/* Suspend the controller until OTG enable it */
 		/* Suspend the controller until OTG enable it */
 		udc_controller->stopped = 1;
 		udc_controller->stopped = 1;
 		printk(KERN_INFO "Suspend udc for OTG auto detect\n");
 		printk(KERN_INFO "Suspend udc for OTG auto detect\n");
 
 
 		/* connect to bus through transceiver */
 		/* connect to bus through transceiver */
-		if (udc_controller->transceiver) {
+		if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
 			retval = otg_set_peripheral(
 			retval = otg_set_peripheral(
 					udc_controller->transceiver->otg,
 					udc_controller->transceiver->otg,
 						    &udc_controller->gadget);
 						    &udc_controller->gadget);
@@ -2030,7 +2031,7 @@ static int fsl_stop(struct usb_gadget_driver *driver)
 	if (!driver || driver != udc_controller->driver || !driver->unbind)
 	if (!driver || driver != udc_controller->driver || !driver->unbind)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	if (udc_controller->transceiver)
+	if (!IS_ERR_OR_NULL(udc_controller->transceiver))
 		otg_set_peripheral(udc_controller->transceiver->otg, NULL);
 		otg_set_peripheral(udc_controller->transceiver->otg, NULL);
 
 
 	/* stop DR, disable intr */
 	/* stop DR, disable intr */
@@ -2455,8 +2456,8 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 
 
 #ifdef CONFIG_USB_OTG
 #ifdef CONFIG_USB_OTG
 	if (pdata->operating_mode == FSL_USB2_DR_OTG) {
 	if (pdata->operating_mode == FSL_USB2_DR_OTG) {
-		udc_controller->transceiver = usb_get_transceiver();
-		if (!udc_controller->transceiver) {
+		udc_controller->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+		if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
 			ERR("Can't find OTG driver!\n");
 			ERR("Can't find OTG driver!\n");
 			ret = -ENODEV;
 			ret = -ENODEV;
 			goto err_kfree;
 			goto err_kfree;
@@ -2540,7 +2541,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 		goto err_free_irq;
 		goto err_free_irq;
 	}
 	}
 
 
-	if (!udc_controller->transceiver) {
+	if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
 		/* initialize usb hw reg except for regs for EP,
 		/* initialize usb hw reg except for regs for EP,
 		 * leave usbintr reg untouched */
 		 * leave usbintr reg untouched */
 		dr_controller_setup(udc_controller);
 		dr_controller_setup(udc_controller);
@@ -2560,11 +2561,12 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 	dev_set_name(&udc_controller->gadget.dev, "gadget");
 	dev_set_name(&udc_controller->gadget.dev, "gadget");
 	udc_controller->gadget.dev.release = fsl_udc_release;
 	udc_controller->gadget.dev.release = fsl_udc_release;
 	udc_controller->gadget.dev.parent = &pdev->dev;
 	udc_controller->gadget.dev.parent = &pdev->dev;
+	udc_controller->gadget.dev.of_node = pdev->dev.of_node;
 	ret = device_register(&udc_controller->gadget.dev);
 	ret = device_register(&udc_controller->gadget.dev);
 	if (ret < 0)
 	if (ret < 0)
 		goto err_free_irq;
 		goto err_free_irq;
 
 
-	if (udc_controller->transceiver)
+	if (!IS_ERR_OR_NULL(udc_controller->transceiver))
 		udc_controller->gadget.is_otg = 1;
 		udc_controller->gadget.is_otg = 1;
 
 
 	/* setup QH and epctrl for ep0 */
 	/* setup QH and epctrl for ep0 */

+ 3 - 3
drivers/usb/gadget/imx_udc.c

@@ -1432,7 +1432,7 @@ static int __init imx_udc_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "can't get USB clock\n");
 		dev_err(&pdev->dev, "can't get USB clock\n");
 		goto fail2;
 		goto fail2;
 	}
 	}
-	clk_enable(clk);
+	clk_prepare_enable(clk);
 
 
 	if (clk_get_rate(clk) != 48000000) {
 	if (clk_get_rate(clk) != 48000000) {
 		D_INI(&pdev->dev,
 		D_INI(&pdev->dev,
@@ -1496,7 +1496,7 @@ fail4:
 		free_irq(imx_usb->usbd_int[i], imx_usb);
 		free_irq(imx_usb->usbd_int[i], imx_usb);
 fail3:
 fail3:
 	clk_put(clk);
 	clk_put(clk);
-	clk_disable(clk);
+	clk_disable_unprepare(clk);
 fail2:
 fail2:
 	iounmap(base);
 	iounmap(base);
 fail1:
 fail1:
@@ -1521,7 +1521,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
 		free_irq(imx_usb->usbd_int[i], imx_usb);
 		free_irq(imx_usb->usbd_int[i], imx_usb);
 
 
 	clk_put(imx_usb->clk);
 	clk_put(imx_usb->clk);
-	clk_disable(imx_usb->clk);
+	clk_disable_unprepare(imx_usb->clk);
 	iounmap(imx_usb->base);
 	iounmap(imx_usb->base);
 
 
 	release_mem_region(imx_usb->res->start, resource_size(imx_usb->res));
 	release_mem_region(imx_usb->res->start, resource_size(imx_usb->res));

+ 25 - 60
drivers/usb/gadget/lpc32xx_udc.c

@@ -165,6 +165,7 @@ struct lpc32xx_udc {
 	int			udp_irq[4];
 	int			udp_irq[4];
 	struct clk		*usb_pll_clk;
 	struct clk		*usb_pll_clk;
 	struct clk		*usb_slv_clk;
 	struct clk		*usb_slv_clk;
+	struct clk		*usb_otg_clk;
 
 
 	/* DMA support */
 	/* DMA support */
 	u32			*udca_v_base;
 	u32			*udca_v_base;
@@ -227,33 +228,15 @@ static inline struct lpc32xx_udc *to_udc(struct usb_gadget *g)
 #define UDCA_BUFF_SIZE (128)
 #define UDCA_BUFF_SIZE (128)
 
 
 /* TODO: When the clock framework is introduced in LPC32xx, IO_ADDRESS will
 /* TODO: When the clock framework is introduced in LPC32xx, IO_ADDRESS will
- * be replaced with an inremap()ed pointer, see USB_OTG_CLK_CTRL()
+ * be replaced with an inremap()ed pointer
  * */
  * */
 #define USB_CTRL		IO_ADDRESS(LPC32XX_CLK_PM_BASE + 0x64)
 #define USB_CTRL		IO_ADDRESS(LPC32XX_CLK_PM_BASE + 0x64)
-#define USB_CLOCK_MASK		(AHB_M_CLOCK_ON | OTG_CLOCK_ON | \
-				 DEV_CLOCK_ON | I2C_CLOCK_ON)
 
 
 /* USB_CTRL bit defines */
 /* USB_CTRL bit defines */
 #define USB_SLAVE_HCLK_EN	(1 << 24)
 #define USB_SLAVE_HCLK_EN	(1 << 24)
 #define USB_HOST_NEED_CLK_EN	(1 << 21)
 #define USB_HOST_NEED_CLK_EN	(1 << 21)
 #define USB_DEV_NEED_CLK_EN	(1 << 22)
 #define USB_DEV_NEED_CLK_EN	(1 << 22)
 
 
-#define USB_OTG_CLK_CTRL(udc)	((udc)->udp_baseaddr + 0xFF4)
-#define USB_OTG_CLK_STAT(udc)	((udc)->udp_baseaddr + 0xFF8)
-
-/* USB_OTG_CLK_CTRL bit defines */
-#define AHB_M_CLOCK_ON		(1 << 4)
-#define OTG_CLOCK_ON		(1 << 3)
-#define I2C_CLOCK_ON		(1 << 2)
-#define DEV_CLOCK_ON		(1 << 1)
-#define HOST_CLOCK_ON		(1 << 0)
-
-#define USB_OTG_STAT_CONTROL(udc) (udc->udp_baseaddr + 0x110)
-
-/* USB_OTG_STAT_CONTROL bit defines */
-#define TRANSPARENT_I2C_EN	(1 << 7)
-#define HOST_EN			(1 << 0)
-
 /**********************************************************************
 /**********************************************************************
  * USB device controller register offsets
  * USB device controller register offsets
  **********************************************************************/
  **********************************************************************/
@@ -677,7 +660,7 @@ static void isp1301_udc_configure(struct lpc32xx_udc *udc)
 		ISP1301_I2C_INTERRUPT_RISING, INT_VBUS_VLD);
 		ISP1301_I2C_INTERRUPT_RISING, INT_VBUS_VLD);
 
 
 	/* Enable usb_need_clk clock after transceiver is initialized */
 	/* Enable usb_need_clk clock after transceiver is initialized */
-	writel((readl(USB_CTRL) | (1 << 22)), USB_CTRL);
+	writel((readl(USB_CTRL) | USB_DEV_NEED_CLK_EN), USB_CTRL);
 
 
 	dev_info(udc->dev, "ISP1301 Vendor ID  : 0x%04x\n",
 	dev_info(udc->dev, "ISP1301 Vendor ID  : 0x%04x\n",
 		 i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00));
 		 i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00));
@@ -1010,11 +993,8 @@ static void udc_dd_free(struct lpc32xx_udc *udc, struct lpc32xx_usbd_dd_gad *dd)
 /* Enables or disables most of the USB system clocks when low power mode is
 /* Enables or disables most of the USB system clocks when low power mode is
  * needed. Clocks are typically started on a connection event, and disabled
  * needed. Clocks are typically started on a connection event, and disabled
  * when a cable is disconnected */
  * when a cable is disconnected */
-#define OTGOFF_CLK_MASK (AHB_M_CLOCK_ON | I2C_CLOCK_ON)
 static void udc_clk_set(struct lpc32xx_udc *udc, int enable)
 static void udc_clk_set(struct lpc32xx_udc *udc, int enable)
 {
 {
-	int to = 1000;
-
 	if (enable != 0) {
 	if (enable != 0) {
 		if (udc->clocked)
 		if (udc->clocked)
 			return;
 			return;
@@ -1028,14 +1008,7 @@ static void udc_clk_set(struct lpc32xx_udc *udc, int enable)
 		writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN,
 		writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN,
 			     USB_CTRL);
 			     USB_CTRL);
 
 
-		/* Set to enable all needed USB OTG clocks */
-		writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL(udc));
-
-		while (((readl(USB_OTG_CLK_STAT(udc)) & USB_CLOCK_MASK) !=
-			USB_CLOCK_MASK) && (to > 0))
-			to--;
-		if (!to)
-			dev_dbg(udc->dev, "Cannot enable USB OTG clocking\n");
+		clk_enable(udc->usb_otg_clk);
 	} else {
 	} else {
 		if (!udc->clocked)
 		if (!udc->clocked)
 			return;
 			return;
@@ -1047,19 +1020,11 @@ static void udc_clk_set(struct lpc32xx_udc *udc, int enable)
 		/* 48MHz PLL dpwn */
 		/* 48MHz PLL dpwn */
 		clk_disable(udc->usb_pll_clk);
 		clk_disable(udc->usb_pll_clk);
 
 
-		/* Enable the USB device clock */
+		/* Disable the USB device clock */
 		writel(readl(USB_CTRL) & ~USB_DEV_NEED_CLK_EN,
 		writel(readl(USB_CTRL) & ~USB_DEV_NEED_CLK_EN,
 			     USB_CTRL);
 			     USB_CTRL);
 
 
-		/* Set to enable all needed USB OTG clocks */
-		writel(OTGOFF_CLK_MASK, USB_OTG_CLK_CTRL(udc));
-
-		while (((readl(USB_OTG_CLK_STAT(udc)) &
-			 OTGOFF_CLK_MASK) !=
-			OTGOFF_CLK_MASK) && (to > 0))
-			to--;
-		if (!to)
-			dev_dbg(udc->dev, "Cannot disable USB OTG clocking\n");
+		clk_disable(udc->usb_otg_clk);
 	}
 	}
 }
 }
 
 
@@ -3041,6 +3006,7 @@ static int lpc32xx_start(struct usb_gadget_driver *driver,
 
 
 	udc->driver = driver;
 	udc->driver = driver;
 	udc->gadget.dev.driver = &driver->driver;
 	udc->gadget.dev.driver = &driver->driver;
+	udc->gadget.dev.of_node = udc->dev->of_node;
 	udc->enabled = 1;
 	udc->enabled = 1;
 	udc->selfpowered = 1;
 	udc->selfpowered = 1;
 	udc->vbus = 0;
 	udc->vbus = 0;
@@ -3239,6 +3205,12 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
 		retval = PTR_ERR(udc->usb_slv_clk);
 		retval = PTR_ERR(udc->usb_slv_clk);
 		goto usb_clk_get_fail;
 		goto usb_clk_get_fail;
 	}
 	}
+	udc->usb_otg_clk = clk_get(&pdev->dev, "ck_usb_otg");
+	if (IS_ERR(udc->usb_otg_clk)) {
+		dev_err(udc->dev, "failed to acquire USB otg clock\n");
+		retval = PTR_ERR(udc->usb_slv_clk);
+		goto usb_otg_clk_get_fail;
+	}
 
 
 	/* Setup PLL clock to 48MHz */
 	/* Setup PLL clock to 48MHz */
 	retval = clk_enable(udc->usb_pll_clk);
 	retval = clk_enable(udc->usb_pll_clk);
@@ -3262,15 +3234,12 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
 		goto usb_clk_enable_fail;
 		goto usb_clk_enable_fail;
 	}
 	}
 
 
-	/* Set to enable all needed USB OTG clocks */
-	writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL(udc));
-
-	i = 1000;
-	while (((readl(USB_OTG_CLK_STAT(udc)) & USB_CLOCK_MASK) !=
-		USB_CLOCK_MASK) && (i > 0))
-		i--;
-	if (!i)
-		dev_dbg(udc->dev, "USB OTG clocks not correctly enabled\n");
+	/* Enable USB OTG clock */
+	retval = clk_enable(udc->usb_otg_clk);
+	if (retval < 0) {
+		dev_err(udc->dev, "failed to start USB otg clock\n");
+		goto usb_otg_clk_enable_fail;
+	}
 
 
 	/* Setup deferred workqueue data */
 	/* Setup deferred workqueue data */
 	udc->poweron = udc->pullup = 0;
 	udc->poweron = udc->pullup = 0;
@@ -3390,12 +3359,16 @@ dma_alloc_fail:
 	dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
 	dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
 			  udc->udca_v_base, udc->udca_p_base);
 			  udc->udca_v_base, udc->udca_p_base);
 i2c_fail:
 i2c_fail:
+	clk_disable(udc->usb_otg_clk);
+usb_otg_clk_enable_fail:
 	clk_disable(udc->usb_slv_clk);
 	clk_disable(udc->usb_slv_clk);
 usb_clk_enable_fail:
 usb_clk_enable_fail:
 pll_set_fail:
 pll_set_fail:
 	clk_disable(udc->usb_pll_clk);
 	clk_disable(udc->usb_pll_clk);
 pll_enable_fail:
 pll_enable_fail:
 	clk_put(udc->usb_slv_clk);
 	clk_put(udc->usb_slv_clk);
+usb_otg_clk_get_fail:
+	clk_put(udc->usb_otg_clk);
 usb_clk_get_fail:
 usb_clk_get_fail:
 	clk_put(udc->usb_pll_clk);
 	clk_put(udc->usb_pll_clk);
 pll_get_fail:
 pll_get_fail:
@@ -3433,6 +3406,8 @@ static int __devexit lpc32xx_udc_remove(struct platform_device *pdev)
 
 
 	device_unregister(&udc->gadget.dev);
 	device_unregister(&udc->gadget.dev);
 
 
+	clk_disable(udc->usb_otg_clk);
+	clk_put(udc->usb_otg_clk);
 	clk_disable(udc->usb_slv_clk);
 	clk_disable(udc->usb_slv_clk);
 	clk_put(udc->usb_slv_clk);
 	clk_put(udc->usb_slv_clk);
 	clk_disable(udc->usb_pll_clk);
 	clk_disable(udc->usb_pll_clk);
@@ -3446,7 +3421,6 @@ static int __devexit lpc32xx_udc_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
 static int lpc32xx_udc_suspend(struct platform_device *pdev, pm_message_t mesg)
 static int lpc32xx_udc_suspend(struct platform_device *pdev, pm_message_t mesg)
 {
 {
-	int to = 1000;
 	struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
 	struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
 
 
 	if (udc->clocked) {
 	if (udc->clocked) {
@@ -3461,15 +3435,6 @@ static int lpc32xx_udc_suspend(struct platform_device *pdev, pm_message_t mesg)
 		   on resume */
 		   on resume */
 		udc->clocked = 1;
 		udc->clocked = 1;
 
 
-		/* Kill OTG and I2C clocks */
-		writel(0, USB_OTG_CLK_CTRL(udc));
-		while (((readl(USB_OTG_CLK_STAT(udc)) & OTGOFF_CLK_MASK) !=
-			OTGOFF_CLK_MASK) && (to > 0))
-			to--;
-		if (!to)
-			dev_dbg(udc->dev,
-				"USB OTG clocks not correctly enabled\n");
-
 		/* Kill global USB clock */
 		/* Kill global USB clock */
 		clk_disable(udc->usb_slv_clk);
 		clk_disable(udc->usb_slv_clk);
 	}
 	}

+ 320 - 0
drivers/usb/gadget/mv_u3d.h

@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#ifndef __MV_U3D_H
+#define __MV_U3D_H
+
+#define MV_U3D_EP_CONTEXT_ALIGNMENT	32
+#define MV_U3D_TRB_ALIGNMENT	16
+#define MV_U3D_DMA_BOUNDARY	4096
+#define MV_U3D_EP0_MAX_PKT_SIZE	512
+
+/* ep0 transfer state */
+#define MV_U3D_WAIT_FOR_SETUP		0
+#define MV_U3D_DATA_STATE_XMIT		1
+#define MV_U3D_DATA_STATE_NEED_ZLP	2
+#define MV_U3D_WAIT_FOR_OUT_STATUS	3
+#define MV_U3D_DATA_STATE_RECV		4
+#define MV_U3D_STATUS_STAGE		5
+
+#define MV_U3D_EP_MAX_LENGTH_TRANSFER	0x10000
+
+/* USB3 Interrupt Status */
+#define MV_U3D_USBINT_SETUP		0x00000001
+#define MV_U3D_USBINT_RX_COMPLETE	0x00000002
+#define MV_U3D_USBINT_TX_COMPLETE	0x00000004
+#define MV_U3D_USBINT_UNDER_RUN	0x00000008
+#define MV_U3D_USBINT_RXDESC_ERR	0x00000010
+#define MV_U3D_USBINT_TXDESC_ERR	0x00000020
+#define MV_U3D_USBINT_RX_TRB_COMPLETE	0x00000040
+#define MV_U3D_USBINT_TX_TRB_COMPLETE	0x00000080
+#define MV_U3D_USBINT_VBUS_VALID	0x00010000
+#define MV_U3D_USBINT_STORAGE_CMD_FULL	0x00020000
+#define MV_U3D_USBINT_LINK_CHG		0x01000000
+
+/* USB3 Interrupt Enable */
+#define MV_U3D_INTR_ENABLE_SETUP		0x00000001
+#define MV_U3D_INTR_ENABLE_RX_COMPLETE		0x00000002
+#define MV_U3D_INTR_ENABLE_TX_COMPLETE		0x00000004
+#define MV_U3D_INTR_ENABLE_UNDER_RUN		0x00000008
+#define MV_U3D_INTR_ENABLE_RXDESC_ERR		0x00000010
+#define MV_U3D_INTR_ENABLE_TXDESC_ERR		0x00000020
+#define MV_U3D_INTR_ENABLE_RX_TRB_COMPLETE	0x00000040
+#define MV_U3D_INTR_ENABLE_TX_TRB_COMPLETE	0x00000080
+#define MV_U3D_INTR_ENABLE_RX_BUFFER_ERR	0x00000100
+#define MV_U3D_INTR_ENABLE_VBUS_VALID		0x00010000
+#define MV_U3D_INTR_ENABLE_STORAGE_CMD_FULL	0x00020000
+#define MV_U3D_INTR_ENABLE_LINK_CHG		0x01000000
+#define MV_U3D_INTR_ENABLE_PRIME_STATUS	0x02000000
+
+/* USB3 Link Change */
+#define MV_U3D_LINK_CHANGE_LINK_UP		0x00000001
+#define MV_U3D_LINK_CHANGE_SUSPEND		0x00000002
+#define MV_U3D_LINK_CHANGE_RESUME		0x00000004
+#define MV_U3D_LINK_CHANGE_WRESET		0x00000008
+#define MV_U3D_LINK_CHANGE_HRESET		0x00000010
+#define MV_U3D_LINK_CHANGE_VBUS_INVALID	0x00000020
+#define MV_U3D_LINK_CHANGE_INACT		0x00000040
+#define MV_U3D_LINK_CHANGE_DISABLE_AFTER_U0	0x00000080
+#define MV_U3D_LINK_CHANGE_U1			0x00000100
+#define MV_U3D_LINK_CHANGE_U2			0x00000200
+#define MV_U3D_LINK_CHANGE_U3			0x00000400
+
+/* bridge setting */
+#define MV_U3D_BRIDGE_SETTING_VBUS_VALID	(1 << 16)
+
+/* Command Register Bit Masks */
+#define MV_U3D_CMD_RUN_STOP		0x00000001
+#define MV_U3D_CMD_CTRL_RESET		0x00000002
+
+/* ep control register */
+#define MV_U3D_EPXCR_EP_TYPE_CONTROL		0
+#define MV_U3D_EPXCR_EP_TYPE_ISOC		1
+#define MV_U3D_EPXCR_EP_TYPE_BULK		2
+#define MV_U3D_EPXCR_EP_TYPE_INT		3
+#define MV_U3D_EPXCR_EP_ENABLE_SHIFT		4
+#define MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT	12
+#define MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT	16
+#define MV_U3D_USB_BULK_BURST_OUT		6
+#define MV_U3D_USB_BULK_BURST_IN		14
+
+#define MV_U3D_EPXCR_EP_FLUSH		(1 << 7)
+#define MV_U3D_EPXCR_EP_HALT		(1 << 1)
+#define MV_U3D_EPXCR_EP_INIT		(1)
+
+/* TX/RX Status Register */
+#define MV_U3D_XFERSTATUS_COMPLETE_SHIFT	24
+#define MV_U3D_COMPLETE_INVALID	0
+#define MV_U3D_COMPLETE_SUCCESS	1
+#define MV_U3D_COMPLETE_BUFF_ERR	2
+#define MV_U3D_COMPLETE_SHORT_PACKET	3
+#define MV_U3D_COMPLETE_TRB_ERR	5
+#define MV_U3D_XFERSTATUS_TRB_LENGTH_MASK	(0xFFFFFF)
+
+#define MV_U3D_USB_LINK_BYPASS_VBUS	0x8
+
+#define MV_U3D_LTSSM_PHY_INIT_DONE		0x80000000
+#define MV_U3D_LTSSM_NEVER_GO_COMPLIANCE	0x40000000
+
+#define MV_U3D_USB3_OP_REGS_OFFSET	0x100
+#define MV_U3D_USB3_PHY_OFFSET		0xB800
+
+#define DCS_ENABLE	0x1
+
+/* timeout */
+#define MV_U3D_RESET_TIMEOUT		10000
+#define MV_U3D_FLUSH_TIMEOUT		100000
+#define MV_U3D_OWN_TIMEOUT		10000
+#define LOOPS_USEC_SHIFT	4
+#define LOOPS_USEC		(1 << LOOPS_USEC_SHIFT)
+#define LOOPS(timeout)		((timeout) >> LOOPS_USEC_SHIFT)
+
+/* ep direction */
+#define MV_U3D_EP_DIR_IN		1
+#define MV_U3D_EP_DIR_OUT		0
+#define mv_u3d_ep_dir(ep)	(((ep)->ep_num == 0) ? \
+				((ep)->u3d->ep0_dir) : ((ep)->direction))
+
+/* usb capability registers */
+struct mv_u3d_cap_regs {
+	u32	rsvd[5];
+	u32	dboff;	/* doorbell register offset */
+	u32	rtsoff;	/* runtime register offset */
+	u32	vuoff;	/* vendor unique register offset */
+};
+
+/* operation registers */
+struct mv_u3d_op_regs {
+	u32	usbcmd;		/* Command register */
+	u32	rsvd1[11];
+	u32	dcbaapl;	/* Device Context Base Address low register */
+	u32	dcbaaph;	/* Device Context Base Address high register */
+	u32	rsvd2[243];
+	u32	portsc;		/* port status and control register*/
+	u32	portlinkinfo;	/* port link info register*/
+	u32	rsvd3[9917];
+	u32	doorbell;	/* doorbell register */
+};
+
+/* control enpoint enable registers */
+struct epxcr {
+	u32	epxoutcr0;	/* ep out control 0 register */
+	u32	epxoutcr1;	/* ep out control 1 register */
+	u32	epxincr0;	/* ep in control 0 register */
+	u32	epxincr1;	/* ep in control 1 register */
+};
+
+/* transfer status registers */
+struct xferstatus {
+	u32	curdeqlo;	/* current TRB pointer low */
+	u32	curdeqhi;	/* current TRB pointer high */
+	u32	statuslo;	/* transfer status low */
+	u32	statushi;	/* transfer status high */
+};
+
+/* vendor unique control registers */
+struct mv_u3d_vuc_regs {
+	u32	ctrlepenable;	/* control endpoint enable register */
+	u32	setuplock;	/* setup lock register */
+	u32	endcomplete;	/* endpoint transfer complete register */
+	u32	intrcause;	/* interrupt cause register */
+	u32	intrenable;	/* interrupt enable register */
+	u32	trbcomplete;	/* TRB complete register */
+	u32	linkchange;	/* link change register */
+	u32	rsvd1[5];
+	u32	trbunderrun;	/* TRB underrun register */
+	u32	rsvd2[43];
+	u32	bridgesetting;	/* bridge setting register */
+	u32	rsvd3[7];
+	struct xferstatus	txst[16];	/* TX status register */
+	struct xferstatus	rxst[16];	/* RX status register */
+	u32	ltssm;		/* LTSSM control register */
+	u32	pipe;		/* PIPE control register */
+	u32	linkcr0;	/* link control 0 register */
+	u32	linkcr1;	/* link control 1 register */
+	u32	rsvd6[60];
+	u32	mib0;		/* MIB0 counter register */
+	u32	usblink;	/* usb link control register */
+	u32	ltssmstate;	/* LTSSM state register */
+	u32	linkerrorcause;	/* link error cause register */
+	u32	rsvd7[60];
+	u32	devaddrtiebrkr;	/* device address and tie breaker */
+	u32	itpinfo0;	/* ITP info 0 register */
+	u32	itpinfo1;	/* ITP info 1 register */
+	u32	rsvd8[61];
+	struct epxcr	epcr[16];	/* ep control register */
+	u32	rsvd9[64];
+	u32	phyaddr;	/* PHY address register */
+	u32	phydata;	/* PHY data register */
+};
+
+/* Endpoint context structure */
+struct mv_u3d_ep_context {
+	u32	rsvd0;
+	u32	rsvd1;
+	u32	trb_addr_lo;		/* TRB address low 32 bit */
+	u32	trb_addr_hi;		/* TRB address high 32 bit */
+	u32	rsvd2;
+	u32	rsvd3;
+	struct usb_ctrlrequest setup_buffer;	/* setup data buffer */
+};
+
+/* TRB control data structure */
+struct mv_u3d_trb_ctrl {
+	u32	own:1;		/* owner of TRB */
+	u32	rsvd1:3;
+	u32	chain:1;	/* associate this TRB with the
+				next TRB on the Ring */
+	u32	ioc:1;		/* interrupt on complete */
+	u32	rsvd2:4;
+	u32	type:6;		/* TRB type */
+#define TYPE_NORMAL	1
+#define TYPE_DATA	3
+#define TYPE_LINK	6
+	u32	dir:1;		/* Working at data stage of control endpoint
+				operation. 0 is OUT and 1 is IN. */
+	u32	rsvd3:15;
+};
+
+/* TRB data structure
+ * For multiple TRB, all the TRBs' physical address should be continuous.
+ */
+struct mv_u3d_trb_hw {
+	u32	buf_addr_lo;	/* data buffer address low 32 bit */
+	u32	buf_addr_hi;	/* data buffer address high 32 bit */
+	u32	trb_len;	/* transfer length */
+	struct mv_u3d_trb_ctrl	ctrl;	/* TRB control data */
+};
+
+/* TRB structure */
+struct mv_u3d_trb {
+	struct mv_u3d_trb_hw *trb_hw;	/* point to the trb_hw structure */
+	dma_addr_t trb_dma;		/* dma address for this trb_hw */
+	struct list_head trb_list;	/* trb list */
+};
+
+/* device data structure */
+struct mv_u3d {
+	struct usb_gadget		gadget;
+	struct usb_gadget_driver	*driver;
+	spinlock_t			lock;	/* device lock */
+	struct completion		*done;
+	struct device			*dev;
+	int				irq;
+
+	/* usb controller registers */
+	struct mv_u3d_cap_regs __iomem	*cap_regs;
+	struct mv_u3d_op_regs __iomem	*op_regs;
+	struct mv_u3d_vuc_regs __iomem	*vuc_regs;
+	void __iomem			*phy_regs;
+
+	unsigned int			max_eps;
+	struct mv_u3d_ep_context	*ep_context;
+	size_t				ep_context_size;
+	dma_addr_t			ep_context_dma;
+
+	struct dma_pool			*trb_pool; /* for TRB data structure */
+	struct mv_u3d_ep		*eps;
+
+	struct mv_u3d_req		*status_req; /* ep0 status request */
+	struct usb_ctrlrequest		local_setup_buff; /* store setup data*/
+
+	unsigned int		resume_state;	/* USB state to resume */
+	unsigned int		usb_state;	/* USB current state */
+	unsigned int		ep0_state;	/* Endpoint zero state */
+	unsigned int		ep0_dir;
+
+	unsigned int		dev_addr;	/* device address */
+
+	unsigned int		errors;
+
+	unsigned		softconnect:1;
+	unsigned		vbus_active:1;	/* vbus is active or not */
+	unsigned		remote_wakeup:1; /* support remote wakeup */
+	unsigned		clock_gating:1;	/* clock gating or not */
+	unsigned		active:1;	/* udc is active or not */
+	unsigned		vbus_valid_detect:1; /* udc vbus detection */
+
+	struct mv_usb_addon_irq *vbus;
+	unsigned int		power;
+
+	struct clk		*clk;
+};
+
+/* endpoint data structure */
+struct mv_u3d_ep {
+	struct usb_ep		ep;
+	struct mv_u3d		*u3d;
+	struct list_head	queue;	/* ep request queued hardware */
+	struct list_head	req_list; /* list of ep request */
+	struct mv_u3d_ep_context	*ep_context; /* ep context */
+	u32			direction;
+	char			name[14];
+	u32			processing; /* there is ep request
+						queued on haredware */
+	spinlock_t		req_lock; /* ep lock */
+	unsigned		wedge:1;
+	unsigned		enabled:1;
+	unsigned		ep_type:2;
+	unsigned		ep_num:8;
+};
+
+/* request data structure */
+struct mv_u3d_req {
+	struct usb_request	req;
+	struct mv_u3d_ep	*ep;
+	struct list_head	queue;	/* ep requst queued on hardware */
+	struct list_head	list;	/* ep request list */
+	struct list_head	trb_list; /* trb list of a request */
+
+	struct mv_u3d_trb	*trb_head; /* point to first trb of a request */
+	unsigned		trb_count; /* TRB number in the chain */
+	unsigned		chain;	   /* TRB chain or not */
+};
+
+#endif

+ 2098 - 0
drivers/usb/gadget/mv_u3d_core.c

@@ -0,0 +1,2098 @@
+/*
+ * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/notifier.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/pm.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/mv_usb.h>
+#include <linux/clk.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+
+#include "mv_u3d.h"
+
+#define DRIVER_DESC		"Marvell PXA USB3.0 Device Controller driver"
+
+static const char driver_name[] = "mv_u3d";
+static const char driver_desc[] = DRIVER_DESC;
+
+static void mv_u3d_nuke(struct mv_u3d_ep *ep, int status);
+static void mv_u3d_stop_activity(struct mv_u3d *u3d,
+			struct usb_gadget_driver *driver);
+
+/* for endpoint 0 operations */
+static const struct usb_endpoint_descriptor mv_u3d_ep0_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	0,
+	.bmAttributes =		USB_ENDPOINT_XFER_CONTROL,
+	.wMaxPacketSize =	MV_U3D_EP0_MAX_PKT_SIZE,
+};
+
+static void mv_u3d_ep0_reset(struct mv_u3d *u3d)
+{
+	struct mv_u3d_ep *ep;
+	u32 epxcr;
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		ep = &u3d->eps[i];
+		ep->u3d = u3d;
+
+		/* ep0 ep context, ep0 in and out share the same ep context */
+		ep->ep_context = &u3d->ep_context[1];
+	}
+
+	/* reset ep state machine */
+	/* reset ep0 out */
+	epxcr = ioread32(&u3d->vuc_regs->epcr[0].epxoutcr0);
+	epxcr |= MV_U3D_EPXCR_EP_INIT;
+	iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxoutcr0);
+	udelay(5);
+	epxcr &= ~MV_U3D_EPXCR_EP_INIT;
+	iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxoutcr0);
+
+	epxcr = ((MV_U3D_EP0_MAX_PKT_SIZE
+		<< MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT)
+		| (1 << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT)
+		| (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
+		| MV_U3D_EPXCR_EP_TYPE_CONTROL);
+	iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxoutcr1);
+
+	/* reset ep0 in */
+	epxcr = ioread32(&u3d->vuc_regs->epcr[0].epxincr0);
+	epxcr |= MV_U3D_EPXCR_EP_INIT;
+	iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxincr0);
+	udelay(5);
+	epxcr &= ~MV_U3D_EPXCR_EP_INIT;
+	iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxincr0);
+
+	epxcr = ((MV_U3D_EP0_MAX_PKT_SIZE
+		<< MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT)
+		| (1 << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT)
+		| (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
+		| MV_U3D_EPXCR_EP_TYPE_CONTROL);
+	iowrite32(epxcr, &u3d->vuc_regs->epcr[0].epxincr1);
+}
+
+static void mv_u3d_ep0_stall(struct mv_u3d *u3d)
+{
+	u32 tmp;
+	dev_dbg(u3d->dev, "%s\n", __func__);
+
+	/* set TX and RX to stall */
+	tmp = ioread32(&u3d->vuc_regs->epcr[0].epxoutcr0);
+	tmp |= MV_U3D_EPXCR_EP_HALT;
+	iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxoutcr0);
+
+	tmp = ioread32(&u3d->vuc_regs->epcr[0].epxincr0);
+	tmp |= MV_U3D_EPXCR_EP_HALT;
+	iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxincr0);
+
+	/* update ep0 state */
+	u3d->ep0_state = MV_U3D_WAIT_FOR_SETUP;
+	u3d->ep0_dir = MV_U3D_EP_DIR_OUT;
+}
+
+static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
+	struct mv_u3d_req *curr_req)
+{
+	struct mv_u3d_trb	*curr_trb;
+	dma_addr_t cur_deq_lo;
+	struct mv_u3d_ep_context	*curr_ep_context;
+	int trb_complete, actual, remaining_length;
+	int direction, ep_num;
+	int retval = 0;
+	u32 tmp, status, length;
+
+	curr_ep_context = &u3d->ep_context[index];
+	direction = index % 2;
+	ep_num = index / 2;
+
+	trb_complete = 0;
+	actual = curr_req->req.length;
+
+	while (!list_empty(&curr_req->trb_list)) {
+		curr_trb = list_entry(curr_req->trb_list.next,
+					struct mv_u3d_trb, trb_list);
+		if (!curr_trb->trb_hw->ctrl.own) {
+			dev_err(u3d->dev, "%s, TRB own error!\n",
+				u3d->eps[index].name);
+			return 1;
+		}
+
+		curr_trb->trb_hw->ctrl.own = 0;
+		if (direction == MV_U3D_EP_DIR_OUT) {
+			tmp = ioread32(&u3d->vuc_regs->rxst[ep_num].statuslo);
+			cur_deq_lo =
+				ioread32(&u3d->vuc_regs->rxst[ep_num].curdeqlo);
+		} else {
+			tmp = ioread32(&u3d->vuc_regs->txst[ep_num].statuslo);
+			cur_deq_lo =
+				ioread32(&u3d->vuc_regs->txst[ep_num].curdeqlo);
+		}
+
+		status = tmp >> MV_U3D_XFERSTATUS_COMPLETE_SHIFT;
+		length = tmp & MV_U3D_XFERSTATUS_TRB_LENGTH_MASK;
+
+		if (status == MV_U3D_COMPLETE_SUCCESS ||
+			(status == MV_U3D_COMPLETE_SHORT_PACKET &&
+			direction == MV_U3D_EP_DIR_OUT)) {
+			remaining_length += length;
+			actual -= remaining_length;
+		} else {
+			dev_err(u3d->dev,
+				"complete_tr error: ep=%d %s: error = 0x%x\n",
+				index >> 1, direction ? "SEND" : "RECV",
+				status);
+			retval = -EPROTO;
+		}
+
+		list_del_init(&curr_trb->trb_list);
+	}
+	if (retval)
+		return retval;
+
+	curr_req->req.actual = actual;
+	return 0;
+}
+
+/*
+ * mv_u3d_done() - retire a request; caller blocked irqs
+ * @status : request status to be set, only works when
+ * request is still in progress.
+ */
+static
+void mv_u3d_done(struct mv_u3d_ep *ep, struct mv_u3d_req *req, int status)
+{
+	struct mv_u3d *u3d = (struct mv_u3d *)ep->u3d;
+
+	dev_dbg(u3d->dev, "mv_u3d_done: remove req->queue\n");
+	/* Removed the req from ep queue */
+	list_del_init(&req->queue);
+
+	/* req.status should be set as -EINPROGRESS in ep_queue() */
+	if (req->req.status == -EINPROGRESS)
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	/* Free trb for the request */
+	if (!req->chain)
+		dma_pool_free(u3d->trb_pool,
+			req->trb_head->trb_hw, req->trb_head->trb_dma);
+	else {
+		dma_unmap_single(ep->u3d->gadget.dev.parent,
+			(dma_addr_t)req->trb_head->trb_dma,
+			req->trb_count * sizeof(struct mv_u3d_trb_hw),
+			DMA_BIDIRECTIONAL);
+		kfree(req->trb_head->trb_hw);
+	}
+	kfree(req->trb_head);
+
+	usb_gadget_unmap_request(&u3d->gadget, &req->req, mv_u3d_ep_dir(ep));
+
+	if (status && (status != -ESHUTDOWN)) {
+		dev_dbg(u3d->dev, "complete %s req %p stat %d len %u/%u",
+			ep->ep.name, &req->req, status,
+			req->req.actual, req->req.length);
+	}
+
+	spin_unlock(&ep->u3d->lock);
+	/*
+	 * complete() is from gadget layer,
+	 * eg fsg->bulk_in_complete()
+	 */
+	if (req->req.complete)
+		req->req.complete(&ep->ep, &req->req);
+
+	spin_lock(&ep->u3d->lock);
+}
+
+static int mv_u3d_queue_trb(struct mv_u3d_ep *ep, struct mv_u3d_req *req)
+{
+	u32 tmp, direction;
+	struct mv_u3d *u3d;
+	struct mv_u3d_ep_context *ep_context;
+	int retval = 0;
+
+	u3d = ep->u3d;
+	direction = mv_u3d_ep_dir(ep);
+
+	/* ep0 in and out share the same ep context slot 1*/
+	if (ep->ep_num == 0)
+		ep_context = &(u3d->ep_context[1]);
+	else
+		ep_context = &(u3d->ep_context[ep->ep_num * 2 + direction]);
+
+	/* check if the pipe is empty or not */
+	if (!list_empty(&ep->queue)) {
+		dev_err(u3d->dev, "add trb to non-empty queue!\n");
+		retval = -ENOMEM;
+		WARN_ON(1);
+	} else {
+		ep_context->rsvd0 = cpu_to_le32(1);
+		ep_context->rsvd1 = 0;
+
+		/* Configure the trb address and set the DCS bit.
+		 * Both DCS bit and own bit in trb should be set.
+		 */
+		ep_context->trb_addr_lo =
+			cpu_to_le32(req->trb_head->trb_dma | DCS_ENABLE);
+		ep_context->trb_addr_hi = 0;
+
+		/* Ensure that updates to the EP Context will
+		 * occure before Ring Bell.
+		 */
+		wmb();
+
+		/* ring bell the ep */
+		if (ep->ep_num == 0)
+			tmp = 0x1;
+		else
+			tmp = ep->ep_num * 2
+				+ ((direction == MV_U3D_EP_DIR_OUT) ? 0 : 1);
+
+		iowrite32(tmp, &u3d->op_regs->doorbell);
+	}
+	return retval;
+}
+
+static struct mv_u3d_trb *mv_u3d_build_trb_one(struct mv_u3d_req *req,
+				unsigned *length, dma_addr_t *dma)
+{
+	u32 temp;
+	unsigned int direction;
+	struct mv_u3d_trb *trb;
+	struct mv_u3d_trb_hw *trb_hw;
+	struct mv_u3d *u3d;
+
+	/* how big will this transfer be? */
+	*length = req->req.length - req->req.actual;
+	BUG_ON(*length > (unsigned)MV_U3D_EP_MAX_LENGTH_TRANSFER);
+
+	u3d = req->ep->u3d;
+
+	trb = kzalloc(sizeof(*trb), GFP_ATOMIC);
+	if (!trb) {
+		dev_err(u3d->dev, "%s, trb alloc fail\n", __func__);
+		return NULL;
+	}
+
+	/*
+	 * Be careful that no _GFP_HIGHMEM is set,
+	 * or we can not use dma_to_virt
+	 * cannot use GFP_KERNEL in spin lock
+	 */
+	trb_hw = dma_pool_alloc(u3d->trb_pool, GFP_ATOMIC, dma);
+	if (!trb_hw) {
+		dev_err(u3d->dev,
+			"%s, dma_pool_alloc fail\n", __func__);
+		return NULL;
+	}
+	trb->trb_dma = *dma;
+	trb->trb_hw = trb_hw;
+
+	/* initialize buffer page pointers */
+	temp = (u32)(req->req.dma + req->req.actual);
+
+	trb_hw->buf_addr_lo = cpu_to_le32(temp);
+	trb_hw->buf_addr_hi = 0;
+	trb_hw->trb_len = cpu_to_le32(*length);
+	trb_hw->ctrl.own = 1;
+
+	if (req->ep->ep_num == 0)
+		trb_hw->ctrl.type = TYPE_DATA;
+	else
+		trb_hw->ctrl.type = TYPE_NORMAL;
+
+	req->req.actual += *length;
+
+	direction = mv_u3d_ep_dir(req->ep);
+	if (direction == MV_U3D_EP_DIR_IN)
+		trb_hw->ctrl.dir = 1;
+	else
+		trb_hw->ctrl.dir = 0;
+
+	/* Enable interrupt for the last trb of a request */
+	if (!req->req.no_interrupt)
+		trb_hw->ctrl.ioc = 1;
+
+	trb_hw->ctrl.chain = 0;
+
+	wmb();
+	return trb;
+}
+
+static int mv_u3d_build_trb_chain(struct mv_u3d_req *req, unsigned *length,
+		struct mv_u3d_trb *trb, int *is_last)
+{
+	u32 temp;
+	unsigned int direction;
+	struct mv_u3d *u3d;
+
+	/* how big will this transfer be? */
+	*length = min(req->req.length - req->req.actual,
+			(unsigned)MV_U3D_EP_MAX_LENGTH_TRANSFER);
+
+	u3d = req->ep->u3d;
+
+	trb->trb_dma = 0;
+
+	/* initialize buffer page pointers */
+	temp = (u32)(req->req.dma + req->req.actual);
+
+	trb->trb_hw->buf_addr_lo = cpu_to_le32(temp);
+	trb->trb_hw->buf_addr_hi = 0;
+	trb->trb_hw->trb_len = cpu_to_le32(*length);
+	trb->trb_hw->ctrl.own = 1;
+
+	if (req->ep->ep_num == 0)
+		trb->trb_hw->ctrl.type = TYPE_DATA;
+	else
+		trb->trb_hw->ctrl.type = TYPE_NORMAL;
+
+	req->req.actual += *length;
+
+	direction = mv_u3d_ep_dir(req->ep);
+	if (direction == MV_U3D_EP_DIR_IN)
+		trb->trb_hw->ctrl.dir = 1;
+	else
+		trb->trb_hw->ctrl.dir = 0;
+
+	/* zlp is needed if req->req.zero is set */
+	if (req->req.zero) {
+		if (*length == 0 || (*length % req->ep->ep.maxpacket) != 0)
+			*is_last = 1;
+		else
+			*is_last = 0;
+	} else if (req->req.length == req->req.actual)
+		*is_last = 1;
+	else
+		*is_last = 0;
+
+	/* Enable interrupt for the last trb of a request */
+	if (*is_last && !req->req.no_interrupt)
+		trb->trb_hw->ctrl.ioc = 1;
+
+	if (*is_last)
+		trb->trb_hw->ctrl.chain = 0;
+	else {
+		trb->trb_hw->ctrl.chain = 1;
+		dev_dbg(u3d->dev, "chain trb\n");
+	}
+
+	wmb();
+
+	return 0;
+}
+
+/* generate TRB linked list for a request
+ * usb controller only supports continous trb chain,
+ * that trb structure physical address should be continous.
+ */
+static int mv_u3d_req_to_trb(struct mv_u3d_req *req)
+{
+	unsigned count;
+	int is_last;
+	struct mv_u3d_trb *trb;
+	struct mv_u3d_trb_hw *trb_hw;
+	struct mv_u3d *u3d;
+	dma_addr_t dma;
+	unsigned length;
+	unsigned trb_num;
+
+	u3d = req->ep->u3d;
+
+	INIT_LIST_HEAD(&req->trb_list);
+
+	length = req->req.length - req->req.actual;
+	/* normally the request transfer length is less than 16KB.
+	 * we use buil_trb_one() to optimize it.
+	 */
+	if (length <= (unsigned)MV_U3D_EP_MAX_LENGTH_TRANSFER) {
+		trb = mv_u3d_build_trb_one(req, &count, &dma);
+		list_add_tail(&trb->trb_list, &req->trb_list);
+		req->trb_head = trb;
+		req->trb_count = 1;
+		req->chain = 0;
+	} else {
+		trb_num = length / MV_U3D_EP_MAX_LENGTH_TRANSFER;
+		if (length % MV_U3D_EP_MAX_LENGTH_TRANSFER)
+			trb_num++;
+
+		trb = kcalloc(trb_num, sizeof(*trb), GFP_ATOMIC);
+		if (!trb) {
+			dev_err(u3d->dev,
+					"%s, trb alloc fail\n", __func__);
+			return -ENOMEM;
+		}
+
+		trb_hw = kcalloc(trb_num, sizeof(*trb_hw), GFP_ATOMIC);
+		if (!trb_hw) {
+			dev_err(u3d->dev,
+					"%s, trb_hw alloc fail\n", __func__);
+			return -ENOMEM;
+		}
+
+		do {
+			trb->trb_hw = trb_hw;
+			if (mv_u3d_build_trb_chain(req, &count,
+						trb, &is_last)) {
+				dev_err(u3d->dev,
+					"%s, mv_u3d_build_trb_chain fail\n",
+					__func__);
+				return -EIO;
+			}
+
+			list_add_tail(&trb->trb_list, &req->trb_list);
+			req->trb_count++;
+			trb++;
+			trb_hw++;
+		} while (!is_last);
+
+		req->trb_head = list_entry(req->trb_list.next,
+					struct mv_u3d_trb, trb_list);
+		req->trb_head->trb_dma = dma_map_single(u3d->gadget.dev.parent,
+					req->trb_head->trb_hw,
+					trb_num * sizeof(*trb_hw),
+					DMA_BIDIRECTIONAL);
+
+		req->chain = 1;
+	}
+
+	return 0;
+}
+
+static int
+mv_u3d_start_queue(struct mv_u3d_ep *ep)
+{
+	struct mv_u3d *u3d = ep->u3d;
+	struct mv_u3d_req *req;
+	int ret;
+
+	if (!list_empty(&ep->req_list) && !ep->processing)
+		req = list_entry(ep->req_list.next, struct mv_u3d_req, list);
+	else
+		return 0;
+
+	ep->processing = 1;
+
+	/* set up dma mapping */
+	ret = usb_gadget_map_request(&u3d->gadget, &req->req,
+					mv_u3d_ep_dir(ep));
+	if (ret)
+		return ret;
+
+	req->req.status = -EINPROGRESS;
+	req->req.actual = 0;
+	req->trb_count = 0;
+
+	/* build trbs and push them to device queue */
+	if (!mv_u3d_req_to_trb(req)) {
+		ret = mv_u3d_queue_trb(ep, req);
+		if (ret) {
+			ep->processing = 0;
+			return ret;
+		}
+	} else {
+		ep->processing = 0;
+		dev_err(u3d->dev, "%s, mv_u3d_req_to_trb fail\n", __func__);
+		return -ENOMEM;
+	}
+
+	/* irq handler advances the queue */
+	if (req)
+		list_add_tail(&req->queue, &ep->queue);
+
+	return 0;
+}
+
+static int mv_u3d_ep_enable(struct usb_ep *_ep,
+		const struct usb_endpoint_descriptor *desc)
+{
+	struct mv_u3d *u3d;
+	struct mv_u3d_ep *ep;
+	struct mv_u3d_ep_context *ep_context;
+	u16 max = 0;
+	unsigned maxburst = 0;
+	u32 epxcr, direction;
+
+	if (!_ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT)
+		return -EINVAL;
+
+	ep = container_of(_ep, struct mv_u3d_ep, ep);
+	u3d = ep->u3d;
+
+	if (!u3d->driver || u3d->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	direction = mv_u3d_ep_dir(ep);
+	max = le16_to_cpu(desc->wMaxPacketSize);
+
+	if (!_ep->maxburst)
+		_ep->maxburst = 1;
+	maxburst = _ep->maxburst;
+
+	/* Get the endpoint context address */
+	ep_context = (struct mv_u3d_ep_context *)ep->ep_context;
+
+	/* Set the max burst size */
+	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	case USB_ENDPOINT_XFER_BULK:
+		if (maxburst > 16) {
+			dev_dbg(u3d->dev,
+				"max burst should not be greater "
+				"than 16 on bulk ep\n");
+			maxburst = 1;
+			_ep->maxburst = maxburst;
+		}
+		dev_dbg(u3d->dev,
+			"maxburst: %d on bulk %s\n", maxburst, ep->name);
+		break;
+	case USB_ENDPOINT_XFER_CONTROL:
+		/* control transfer only supports maxburst as one */
+		maxburst = 1;
+		_ep->maxburst = maxburst;
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		if (maxburst != 1) {
+			dev_dbg(u3d->dev,
+				"max burst should be 1 on int ep "
+				"if transfer size is not 1024\n");
+			maxburst = 1;
+			_ep->maxburst = maxburst;
+		}
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		if (maxburst != 1) {
+			dev_dbg(u3d->dev,
+				"max burst should be 1 on isoc ep "
+				"if transfer size is not 1024\n");
+			maxburst = 1;
+			_ep->maxburst = maxburst;
+		}
+		break;
+	default:
+		goto en_done;
+	}
+
+	ep->ep.maxpacket = max;
+	ep->ep.desc = desc;
+	ep->enabled = 1;
+
+	/* Enable the endpoint for Rx or Tx and set the endpoint type */
+	if (direction == MV_U3D_EP_DIR_OUT) {
+		epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
+		epxcr |= MV_U3D_EPXCR_EP_INIT;
+		iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
+		udelay(5);
+		epxcr &= ~MV_U3D_EPXCR_EP_INIT;
+		iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
+
+		epxcr = ((max << MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT)
+		      | ((maxburst - 1) << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT)
+		      | (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
+		      | (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK));
+		iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr1);
+	} else {
+		epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
+		epxcr |= MV_U3D_EPXCR_EP_INIT;
+		iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
+		udelay(5);
+		epxcr &= ~MV_U3D_EPXCR_EP_INIT;
+		iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
+
+		epxcr = ((max << MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT)
+		      | ((maxburst - 1) << MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT)
+		      | (1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
+		      | (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK));
+		iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr1);
+	}
+
+	return 0;
+en_done:
+	return -EINVAL;
+}
+
+static int  mv_u3d_ep_disable(struct usb_ep *_ep)
+{
+	struct mv_u3d *u3d;
+	struct mv_u3d_ep *ep;
+	struct mv_u3d_ep_context *ep_context;
+	u32 epxcr, direction;
+
+	if (!_ep)
+		return -EINVAL;
+
+	ep = container_of(_ep, struct mv_u3d_ep, ep);
+	if (!ep->ep.desc)
+		return -EINVAL;
+
+	u3d = ep->u3d;
+
+	/* Get the endpoint context address */
+	ep_context = ep->ep_context;
+
+	direction = mv_u3d_ep_dir(ep);
+
+	/* nuke all pending requests (does flush) */
+	mv_u3d_nuke(ep, -ESHUTDOWN);
+
+	/* Disable the endpoint for Rx or Tx and reset the endpoint type */
+	if (direction == MV_U3D_EP_DIR_OUT) {
+		epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr1);
+		epxcr &= ~((1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
+		      | USB_ENDPOINT_XFERTYPE_MASK);
+		iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr1);
+	} else {
+		epxcr = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr1);
+		epxcr &= ~((1 << MV_U3D_EPXCR_EP_ENABLE_SHIFT)
+		      | USB_ENDPOINT_XFERTYPE_MASK);
+		iowrite32(epxcr, &u3d->vuc_regs->epcr[ep->ep_num].epxincr1);
+	}
+
+	ep->enabled = 0;
+
+	ep->ep.desc = NULL;
+	return 0;
+}
+
+static struct usb_request *
+mv_u3d_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+	struct mv_u3d_req *req = NULL;
+
+	req = kzalloc(sizeof *req, gfp_flags);
+	if (!req)
+		return NULL;
+
+	INIT_LIST_HEAD(&req->queue);
+
+	return &req->req;
+}
+
+static void mv_u3d_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct mv_u3d_req *req = container_of(_req, struct mv_u3d_req, req);
+
+	kfree(req);
+}
+
+static void mv_u3d_ep_fifo_flush(struct usb_ep *_ep)
+{
+	struct mv_u3d *u3d;
+	u32 direction;
+	struct mv_u3d_ep *ep = container_of(_ep, struct mv_u3d_ep, ep);
+	unsigned int loops;
+	u32 tmp;
+
+	/* if endpoint is not enabled, cannot flush endpoint */
+	if (!ep->enabled)
+		return;
+
+	u3d = ep->u3d;
+	direction = mv_u3d_ep_dir(ep);
+
+	/* ep0 need clear bit after flushing fifo. */
+	if (!ep->ep_num) {
+		if (direction == MV_U3D_EP_DIR_OUT) {
+			tmp = ioread32(&u3d->vuc_regs->epcr[0].epxoutcr0);
+			tmp |= MV_U3D_EPXCR_EP_FLUSH;
+			iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxoutcr0);
+			udelay(10);
+			tmp &= ~MV_U3D_EPXCR_EP_FLUSH;
+			iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxoutcr0);
+		} else {
+			tmp = ioread32(&u3d->vuc_regs->epcr[0].epxincr0);
+			tmp |= MV_U3D_EPXCR_EP_FLUSH;
+			iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxincr0);
+			udelay(10);
+			tmp &= ~MV_U3D_EPXCR_EP_FLUSH;
+			iowrite32(tmp, &u3d->vuc_regs->epcr[0].epxincr0);
+		}
+		return;
+	}
+
+	if (direction == MV_U3D_EP_DIR_OUT) {
+		tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
+		tmp |= MV_U3D_EPXCR_EP_FLUSH;
+		iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
+
+		/* Wait until flushing completed */
+		loops = LOOPS(MV_U3D_FLUSH_TIMEOUT);
+		while (ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0) &
+			MV_U3D_EPXCR_EP_FLUSH) {
+			/*
+			 * EP_FLUSH bit should be cleared to indicate this
+			 * operation is complete
+			 */
+			if (loops == 0) {
+				dev_dbg(u3d->dev,
+				    "EP FLUSH TIMEOUT for ep%d%s\n", ep->ep_num,
+				    direction ? "in" : "out");
+				return;
+			}
+			loops--;
+			udelay(LOOPS_USEC);
+		}
+	} else {	/* EP_DIR_IN */
+		tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
+		tmp |= MV_U3D_EPXCR_EP_FLUSH;
+		iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
+
+		/* Wait until flushing completed */
+		loops = LOOPS(MV_U3D_FLUSH_TIMEOUT);
+		while (ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0) &
+			MV_U3D_EPXCR_EP_FLUSH) {
+			/*
+			* EP_FLUSH bit should be cleared to indicate this
+			* operation is complete
+			*/
+			if (loops == 0) {
+				dev_dbg(u3d->dev,
+				    "EP FLUSH TIMEOUT for ep%d%s\n", ep->ep_num,
+				    direction ? "in" : "out");
+				return;
+			}
+			loops--;
+			udelay(LOOPS_USEC);
+		}
+	}
+}
+
+/* queues (submits) an I/O request to an endpoint */
+static int
+mv_u3d_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+	struct mv_u3d_ep *ep;
+	struct mv_u3d_req *req;
+	struct mv_u3d *u3d;
+	unsigned long flags;
+	int is_first_req = 0;
+
+	if (unlikely(!_ep || !_req))
+		return -EINVAL;
+
+	ep = container_of(_ep, struct mv_u3d_ep, ep);
+	u3d = ep->u3d;
+
+	req = container_of(_req, struct mv_u3d_req, req);
+
+	if (!ep->ep_num
+		&& u3d->ep0_state == MV_U3D_STATUS_STAGE
+		&& !_req->length) {
+		dev_dbg(u3d->dev, "ep0 status stage\n");
+		u3d->ep0_state = MV_U3D_WAIT_FOR_SETUP;
+		return 0;
+	}
+
+	dev_dbg(u3d->dev, "%s: %s, req: 0x%x\n",
+			__func__, _ep->name, (u32)req);
+
+	/* catch various bogus parameters */
+	if (!req->req.complete || !req->req.buf
+			|| !list_empty(&req->queue)) {
+		dev_err(u3d->dev,
+			"%s, bad params, _req: 0x%x,"
+			"req->req.complete: 0x%x, req->req.buf: 0x%x,"
+			"list_empty: 0x%x\n",
+			__func__, (u32)_req,
+			(u32)req->req.complete, (u32)req->req.buf,
+			(u32)list_empty(&req->queue));
+		return -EINVAL;
+	}
+	if (unlikely(!ep->ep.desc)) {
+		dev_err(u3d->dev, "%s, bad ep\n", __func__);
+		return -EINVAL;
+	}
+	if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+		if (req->req.length > ep->ep.maxpacket)
+			return -EMSGSIZE;
+	}
+
+	if (!u3d->driver || u3d->gadget.speed == USB_SPEED_UNKNOWN) {
+		dev_err(u3d->dev,
+			"bad params of driver/speed\n");
+		return -ESHUTDOWN;
+	}
+
+	req->ep = ep;
+
+	/* Software list handles usb request. */
+	spin_lock_irqsave(&ep->req_lock, flags);
+	is_first_req = list_empty(&ep->req_list);
+	list_add_tail(&req->list, &ep->req_list);
+	spin_unlock_irqrestore(&ep->req_lock, flags);
+	if (!is_first_req) {
+		dev_dbg(u3d->dev, "list is not empty\n");
+		return 0;
+	}
+
+	dev_dbg(u3d->dev, "call mv_u3d_start_queue from usb_ep_queue\n");
+	spin_lock_irqsave(&u3d->lock, flags);
+	mv_u3d_start_queue(ep);
+	spin_unlock_irqrestore(&u3d->lock, flags);
+	return 0;
+}
+
+/* dequeues (cancels, unlinks) an I/O request from an endpoint */
+static int mv_u3d_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct mv_u3d_ep *ep;
+	struct mv_u3d_req *req;
+	struct mv_u3d *u3d;
+	struct mv_u3d_ep_context *ep_context;
+	struct mv_u3d_req *next_req;
+
+	unsigned long flags;
+	int ret = 0;
+
+	if (!_ep || !_req)
+		return -EINVAL;
+
+	ep = container_of(_ep, struct mv_u3d_ep, ep);
+	u3d = ep->u3d;
+
+	spin_lock_irqsave(&ep->u3d->lock, flags);
+
+	/* make sure it's actually queued on this endpoint */
+	list_for_each_entry(req, &ep->queue, queue) {
+		if (&req->req == _req)
+			break;
+	}
+	if (&req->req != _req) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* The request is in progress, or completed but not dequeued */
+	if (ep->queue.next == &req->queue) {
+		_req->status = -ECONNRESET;
+		mv_u3d_ep_fifo_flush(_ep);
+
+		/* The request isn't the last request in this ep queue */
+		if (req->queue.next != &ep->queue) {
+			dev_dbg(u3d->dev,
+				"it is the last request in this ep queue\n");
+			ep_context = ep->ep_context;
+			next_req = list_entry(req->queue.next,
+					struct mv_u3d_req, queue);
+
+			/* Point first TRB of next request to the EP context. */
+			iowrite32((u32) next_req->trb_head,
+					&ep_context->trb_addr_lo);
+		} else {
+			struct mv_u3d_ep_context *ep_context;
+			ep_context = ep->ep_context;
+			ep_context->trb_addr_lo = 0;
+			ep_context->trb_addr_hi = 0;
+		}
+
+	} else
+		WARN_ON(1);
+
+	mv_u3d_done(ep, req, -ECONNRESET);
+
+	/* remove the req from the ep req list */
+	if (!list_empty(&ep->req_list)) {
+		struct mv_u3d_req *curr_req;
+		curr_req = list_entry(ep->req_list.next,
+					struct mv_u3d_req, list);
+		if (curr_req == req) {
+			list_del_init(&req->list);
+			ep->processing = 0;
+		}
+	}
+
+out:
+	spin_unlock_irqrestore(&ep->u3d->lock, flags);
+	return ret;
+}
+
+static void
+mv_u3d_ep_set_stall(struct mv_u3d *u3d, u8 ep_num, u8 direction, int stall)
+{
+	u32 tmp;
+	struct mv_u3d_ep *ep = u3d->eps;
+
+	dev_dbg(u3d->dev, "%s\n", __func__);
+	if (direction == MV_U3D_EP_DIR_OUT) {
+		tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
+		if (stall)
+			tmp |= MV_U3D_EPXCR_EP_HALT;
+		else
+			tmp &= ~MV_U3D_EPXCR_EP_HALT;
+		iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxoutcr0);
+	} else {
+		tmp = ioread32(&u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
+		if (stall)
+			tmp |= MV_U3D_EPXCR_EP_HALT;
+		else
+			tmp &= ~MV_U3D_EPXCR_EP_HALT;
+		iowrite32(tmp, &u3d->vuc_regs->epcr[ep->ep_num].epxincr0);
+	}
+}
+
+static int mv_u3d_ep_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge)
+{
+	struct mv_u3d_ep *ep;
+	unsigned long flags = 0;
+	int status = 0;
+	struct mv_u3d *u3d;
+
+	ep = container_of(_ep, struct mv_u3d_ep, ep);
+	u3d = ep->u3d;
+	if (!ep->ep.desc) {
+		status = -EINVAL;
+		goto out;
+	}
+
+	if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+		status = -EOPNOTSUPP;
+		goto out;
+	}
+
+	/*
+	 * Attempt to halt IN ep will fail if any transfer requests
+	 * are still queue
+	 */
+	if (halt && (mv_u3d_ep_dir(ep) == MV_U3D_EP_DIR_IN)
+			&& !list_empty(&ep->queue)) {
+		status = -EAGAIN;
+		goto out;
+	}
+
+	spin_lock_irqsave(&ep->u3d->lock, flags);
+	mv_u3d_ep_set_stall(u3d, ep->ep_num, mv_u3d_ep_dir(ep), halt);
+	if (halt && wedge)
+		ep->wedge = 1;
+	else if (!halt)
+		ep->wedge = 0;
+	spin_unlock_irqrestore(&ep->u3d->lock, flags);
+
+	if (ep->ep_num == 0)
+		u3d->ep0_dir = MV_U3D_EP_DIR_OUT;
+out:
+	return status;
+}
+
+static int mv_u3d_ep_set_halt(struct usb_ep *_ep, int halt)
+{
+	return mv_u3d_ep_set_halt_wedge(_ep, halt, 0);
+}
+
+static int mv_u3d_ep_set_wedge(struct usb_ep *_ep)
+{
+	return mv_u3d_ep_set_halt_wedge(_ep, 1, 1);
+}
+
+static struct usb_ep_ops mv_u3d_ep_ops = {
+	.enable		= mv_u3d_ep_enable,
+	.disable	= mv_u3d_ep_disable,
+
+	.alloc_request	= mv_u3d_alloc_request,
+	.free_request	= mv_u3d_free_request,
+
+	.queue		= mv_u3d_ep_queue,
+	.dequeue	= mv_u3d_ep_dequeue,
+
+	.set_wedge	= mv_u3d_ep_set_wedge,
+	.set_halt	= mv_u3d_ep_set_halt,
+	.fifo_flush	= mv_u3d_ep_fifo_flush,
+};
+
+static void mv_u3d_controller_stop(struct mv_u3d *u3d)
+{
+	u32 tmp;
+
+	if (!u3d->clock_gating && u3d->vbus_valid_detect)
+		iowrite32(MV_U3D_INTR_ENABLE_VBUS_VALID,
+				&u3d->vuc_regs->intrenable);
+	else
+		iowrite32(0, &u3d->vuc_regs->intrenable);
+	iowrite32(~0x0, &u3d->vuc_regs->endcomplete);
+	iowrite32(~0x0, &u3d->vuc_regs->trbunderrun);
+	iowrite32(~0x0, &u3d->vuc_regs->trbcomplete);
+	iowrite32(~0x0, &u3d->vuc_regs->linkchange);
+	iowrite32(0x1, &u3d->vuc_regs->setuplock);
+
+	/* Reset the RUN bit in the command register to stop USB */
+	tmp = ioread32(&u3d->op_regs->usbcmd);
+	tmp &= ~MV_U3D_CMD_RUN_STOP;
+	iowrite32(tmp, &u3d->op_regs->usbcmd);
+	dev_dbg(u3d->dev, "after u3d_stop, USBCMD 0x%x\n",
+		ioread32(&u3d->op_regs->usbcmd));
+}
+
+static void mv_u3d_controller_start(struct mv_u3d *u3d)
+{
+	u32 usbintr;
+	u32 temp;
+
+	/* enable link LTSSM state machine */
+	temp = ioread32(&u3d->vuc_regs->ltssm);
+	temp |= MV_U3D_LTSSM_PHY_INIT_DONE;
+	iowrite32(temp, &u3d->vuc_regs->ltssm);
+
+	/* Enable interrupts */
+	usbintr = MV_U3D_INTR_ENABLE_LINK_CHG | MV_U3D_INTR_ENABLE_TXDESC_ERR |
+		MV_U3D_INTR_ENABLE_RXDESC_ERR | MV_U3D_INTR_ENABLE_TX_COMPLETE |
+		MV_U3D_INTR_ENABLE_RX_COMPLETE | MV_U3D_INTR_ENABLE_SETUP |
+		(u3d->vbus_valid_detect ? MV_U3D_INTR_ENABLE_VBUS_VALID : 0);
+	iowrite32(usbintr, &u3d->vuc_regs->intrenable);
+
+	/* Enable ctrl ep */
+	iowrite32(0x1, &u3d->vuc_regs->ctrlepenable);
+
+	/* Set the Run bit in the command register */
+	iowrite32(MV_U3D_CMD_RUN_STOP, &u3d->op_regs->usbcmd);
+	dev_dbg(u3d->dev, "after u3d_start, USBCMD 0x%x\n",
+		ioread32(&u3d->op_regs->usbcmd));
+}
+
+static int mv_u3d_controller_reset(struct mv_u3d *u3d)
+{
+	unsigned int loops;
+	u32 tmp;
+
+	/* Stop the controller */
+	tmp = ioread32(&u3d->op_regs->usbcmd);
+	tmp &= ~MV_U3D_CMD_RUN_STOP;
+	iowrite32(tmp, &u3d->op_regs->usbcmd);
+
+	/* Reset the controller to get default values */
+	iowrite32(MV_U3D_CMD_CTRL_RESET, &u3d->op_regs->usbcmd);
+
+	/* wait for reset to complete */
+	loops = LOOPS(MV_U3D_RESET_TIMEOUT);
+	while (ioread32(&u3d->op_regs->usbcmd) & MV_U3D_CMD_CTRL_RESET) {
+		if (loops == 0) {
+			dev_err(u3d->dev,
+				"Wait for RESET completed TIMEOUT\n");
+			return -ETIMEDOUT;
+		}
+		loops--;
+		udelay(LOOPS_USEC);
+	}
+
+	/* Configure the Endpoint Context Address */
+	iowrite32(u3d->ep_context_dma, &u3d->op_regs->dcbaapl);
+	iowrite32(0, &u3d->op_regs->dcbaaph);
+
+	return 0;
+}
+
+static int mv_u3d_enable(struct mv_u3d *u3d)
+{
+	struct mv_usb_platform_data *pdata = u3d->dev->platform_data;
+	int retval;
+
+	if (u3d->active)
+		return 0;
+
+	if (!u3d->clock_gating) {
+		u3d->active = 1;
+		return 0;
+	}
+
+	dev_dbg(u3d->dev, "enable u3d\n");
+	clk_enable(u3d->clk);
+	if (pdata->phy_init) {
+		retval = pdata->phy_init(u3d->phy_regs);
+		if (retval) {
+			dev_err(u3d->dev,
+				"init phy error %d\n", retval);
+			clk_disable(u3d->clk);
+			return retval;
+		}
+	}
+	u3d->active = 1;
+
+	return 0;
+}
+
+static void mv_u3d_disable(struct mv_u3d *u3d)
+{
+	struct mv_usb_platform_data *pdata = u3d->dev->platform_data;
+	if (u3d->clock_gating && u3d->active) {
+		dev_dbg(u3d->dev, "disable u3d\n");
+		if (pdata->phy_deinit)
+			pdata->phy_deinit(u3d->phy_regs);
+		clk_disable(u3d->clk);
+		u3d->active = 0;
+	}
+}
+
+static int mv_u3d_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+	struct mv_u3d *u3d;
+	unsigned long flags;
+	int retval = 0;
+
+	u3d = container_of(gadget, struct mv_u3d, gadget);
+
+	spin_lock_irqsave(&u3d->lock, flags);
+
+	u3d->vbus_active = (is_active != 0);
+	dev_dbg(u3d->dev, "%s: softconnect %d, vbus_active %d\n",
+		__func__, u3d->softconnect, u3d->vbus_active);
+	/*
+	 * 1. external VBUS detect: we can disable/enable clock on demand.
+	 * 2. UDC VBUS detect: we have to enable clock all the time.
+	 * 3. No VBUS detect: we have to enable clock all the time.
+	 */
+	if (u3d->driver && u3d->softconnect && u3d->vbus_active) {
+		retval = mv_u3d_enable(u3d);
+		if (retval == 0) {
+			/*
+			 * after clock is disabled, we lost all the register
+			 *  context. We have to re-init registers
+			 */
+			mv_u3d_controller_reset(u3d);
+			mv_u3d_ep0_reset(u3d);
+			mv_u3d_controller_start(u3d);
+		}
+	} else if (u3d->driver && u3d->softconnect) {
+		if (!u3d->active)
+			goto out;
+
+		/* stop all the transfer in queue*/
+		mv_u3d_stop_activity(u3d, u3d->driver);
+		mv_u3d_controller_stop(u3d);
+		mv_u3d_disable(u3d);
+	}
+
+out:
+	spin_unlock_irqrestore(&u3d->lock, flags);
+	return retval;
+}
+
+/* constrain controller's VBUS power usage
+ * This call is used by gadget drivers during SET_CONFIGURATION calls,
+ * reporting how much power the device may consume.  For example, this
+ * could affect how quickly batteries are recharged.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static int mv_u3d_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+	struct mv_u3d *u3d = container_of(gadget, struct mv_u3d, gadget);
+
+	u3d->power = mA;
+
+	return 0;
+}
+
+static int mv_u3d_pullup(struct usb_gadget *gadget, int is_on)
+{
+	struct mv_u3d *u3d = container_of(gadget, struct mv_u3d, gadget);
+	unsigned long flags;
+	int retval = 0;
+
+	spin_lock_irqsave(&u3d->lock, flags);
+
+	dev_dbg(u3d->dev, "%s: softconnect %d, vbus_active %d\n",
+		__func__, u3d->softconnect, u3d->vbus_active);
+	u3d->softconnect = (is_on != 0);
+	if (u3d->driver && u3d->softconnect && u3d->vbus_active) {
+		retval = mv_u3d_enable(u3d);
+		if (retval == 0) {
+			/*
+			 * after clock is disabled, we lost all the register
+			 *  context. We have to re-init registers
+			 */
+			mv_u3d_controller_reset(u3d);
+			mv_u3d_ep0_reset(u3d);
+			mv_u3d_controller_start(u3d);
+		}
+	} else if (u3d->driver && u3d->vbus_active) {
+		/* stop all the transfer in queue*/
+		mv_u3d_stop_activity(u3d, u3d->driver);
+		mv_u3d_controller_stop(u3d);
+		mv_u3d_disable(u3d);
+	}
+
+	spin_unlock_irqrestore(&u3d->lock, flags);
+
+	return retval;
+}
+
+static int mv_u3d_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
+{
+	struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget);
+	struct mv_usb_platform_data *pdata = u3d->dev->platform_data;
+	unsigned long flags;
+
+	if (u3d->driver)
+		return -EBUSY;
+
+	spin_lock_irqsave(&u3d->lock, flags);
+
+	if (!u3d->clock_gating) {
+		clk_enable(u3d->clk);
+		if (pdata->phy_init)
+			pdata->phy_init(u3d->phy_regs);
+	}
+
+	/* hook up the driver ... */
+	driver->driver.bus = NULL;
+	u3d->driver = driver;
+	u3d->gadget.dev.driver = &driver->driver;
+
+	u3d->ep0_dir = USB_DIR_OUT;
+
+	spin_unlock_irqrestore(&u3d->lock, flags);
+
+	u3d->vbus_valid_detect = 1;
+
+	return 0;
+}
+
+static int mv_u3d_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
+{
+	struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget);
+	struct mv_usb_platform_data *pdata = u3d->dev->platform_data;
+	unsigned long flags;
+
+	u3d->vbus_valid_detect = 0;
+	spin_lock_irqsave(&u3d->lock, flags);
+
+	/* enable clock to access controller register */
+	clk_enable(u3d->clk);
+	if (pdata->phy_init)
+		pdata->phy_init(u3d->phy_regs);
+
+	mv_u3d_controller_stop(u3d);
+	/* stop all usb activities */
+	u3d->gadget.speed = USB_SPEED_UNKNOWN;
+	mv_u3d_stop_activity(u3d, driver);
+	mv_u3d_disable(u3d);
+
+	if (pdata->phy_deinit)
+		pdata->phy_deinit(u3d->phy_regs);
+	clk_disable(u3d->clk);
+
+	spin_unlock_irqrestore(&u3d->lock, flags);
+
+	u3d->gadget.dev.driver = NULL;
+	u3d->driver = NULL;
+
+	return 0;
+}
+
+/* device controller usb_gadget_ops structure */
+static const struct usb_gadget_ops mv_u3d_ops = {
+	/* notify controller that VBUS is powered or not */
+	.vbus_session	= mv_u3d_vbus_session,
+
+	/* constrain controller's VBUS power usage */
+	.vbus_draw	= mv_u3d_vbus_draw,
+
+	.pullup		= mv_u3d_pullup,
+	.udc_start	= mv_u3d_start,
+	.udc_stop	= mv_u3d_stop,
+};
+
+static int mv_u3d_eps_init(struct mv_u3d *u3d)
+{
+	struct mv_u3d_ep	*ep;
+	char name[14];
+	int i;
+
+	/* initialize ep0, ep0 in/out use eps[1] */
+	ep = &u3d->eps[1];
+	ep->u3d = u3d;
+	strncpy(ep->name, "ep0", sizeof(ep->name));
+	ep->ep.name = ep->name;
+	ep->ep.ops = &mv_u3d_ep_ops;
+	ep->wedge = 0;
+	ep->ep.maxpacket = MV_U3D_EP0_MAX_PKT_SIZE;
+	ep->ep_num = 0;
+	ep->ep.desc = &mv_u3d_ep0_desc;
+	INIT_LIST_HEAD(&ep->queue);
+	INIT_LIST_HEAD(&ep->req_list);
+	ep->ep_type = USB_ENDPOINT_XFER_CONTROL;
+
+	/* add ep0 ep_context */
+	ep->ep_context = &u3d->ep_context[1];
+
+	/* initialize other endpoints */
+	for (i = 2; i < u3d->max_eps * 2; i++) {
+		ep = &u3d->eps[i];
+		if (i & 1) {
+			snprintf(name, sizeof(name), "ep%din", i >> 1);
+			ep->direction = MV_U3D_EP_DIR_IN;
+		} else {
+			snprintf(name, sizeof(name), "ep%dout", i >> 1);
+			ep->direction = MV_U3D_EP_DIR_OUT;
+		}
+		ep->u3d = u3d;
+		strncpy(ep->name, name, sizeof(ep->name));
+		ep->ep.name = ep->name;
+
+		ep->ep.ops = &mv_u3d_ep_ops;
+		ep->ep.maxpacket = (unsigned short) ~0;
+		ep->ep_num = i / 2;
+
+		INIT_LIST_HEAD(&ep->queue);
+		list_add_tail(&ep->ep.ep_list, &u3d->gadget.ep_list);
+
+		INIT_LIST_HEAD(&ep->req_list);
+		spin_lock_init(&ep->req_lock);
+		ep->ep_context = &u3d->ep_context[i];
+	}
+
+	return 0;
+}
+
+/* delete all endpoint requests, called with spinlock held */
+static void mv_u3d_nuke(struct mv_u3d_ep *ep, int status)
+{
+	/* endpoint fifo flush */
+	mv_u3d_ep_fifo_flush(&ep->ep);
+
+	while (!list_empty(&ep->queue)) {
+		struct mv_u3d_req *req = NULL;
+		req = list_entry(ep->queue.next, struct mv_u3d_req, queue);
+		mv_u3d_done(ep, req, status);
+	}
+}
+
+/* stop all USB activities */
+static
+void mv_u3d_stop_activity(struct mv_u3d *u3d, struct usb_gadget_driver *driver)
+{
+	struct mv_u3d_ep	*ep;
+
+	mv_u3d_nuke(&u3d->eps[1], -ESHUTDOWN);
+
+	list_for_each_entry(ep, &u3d->gadget.ep_list, ep.ep_list) {
+		mv_u3d_nuke(ep, -ESHUTDOWN);
+	}
+
+	/* report disconnect; the driver is already quiesced */
+	if (driver) {
+		spin_unlock(&u3d->lock);
+		driver->disconnect(&u3d->gadget);
+		spin_lock(&u3d->lock);
+	}
+}
+
+static void mv_u3d_irq_process_error(struct mv_u3d *u3d)
+{
+	/* Increment the error count */
+	u3d->errors++;
+	dev_err(u3d->dev, "%s\n", __func__);
+}
+
+static void mv_u3d_irq_process_link_change(struct mv_u3d *u3d)
+{
+	u32 linkchange;
+
+	linkchange = ioread32(&u3d->vuc_regs->linkchange);
+	iowrite32(linkchange, &u3d->vuc_regs->linkchange);
+
+	dev_dbg(u3d->dev, "linkchange: 0x%x\n", linkchange);
+
+	if (linkchange & MV_U3D_LINK_CHANGE_LINK_UP) {
+		dev_dbg(u3d->dev, "link up: ltssm state: 0x%x\n",
+			ioread32(&u3d->vuc_regs->ltssmstate));
+
+		u3d->usb_state = USB_STATE_DEFAULT;
+		u3d->ep0_dir = MV_U3D_EP_DIR_OUT;
+		u3d->ep0_state = MV_U3D_WAIT_FOR_SETUP;
+
+		/* set speed */
+		u3d->gadget.speed = USB_SPEED_SUPER;
+	}
+
+	if (linkchange & MV_U3D_LINK_CHANGE_SUSPEND) {
+		dev_dbg(u3d->dev, "link suspend\n");
+		u3d->resume_state = u3d->usb_state;
+		u3d->usb_state = USB_STATE_SUSPENDED;
+	}
+
+	if (linkchange & MV_U3D_LINK_CHANGE_RESUME) {
+		dev_dbg(u3d->dev, "link resume\n");
+		u3d->usb_state = u3d->resume_state;
+		u3d->resume_state = 0;
+	}
+
+	if (linkchange & MV_U3D_LINK_CHANGE_WRESET) {
+		dev_dbg(u3d->dev, "warm reset\n");
+		u3d->usb_state = USB_STATE_POWERED;
+	}
+
+	if (linkchange & MV_U3D_LINK_CHANGE_HRESET) {
+		dev_dbg(u3d->dev, "hot reset\n");
+		u3d->usb_state = USB_STATE_DEFAULT;
+	}
+
+	if (linkchange & MV_U3D_LINK_CHANGE_INACT)
+		dev_dbg(u3d->dev, "inactive\n");
+
+	if (linkchange & MV_U3D_LINK_CHANGE_DISABLE_AFTER_U0)
+		dev_dbg(u3d->dev, "ss.disabled\n");
+
+	if (linkchange & MV_U3D_LINK_CHANGE_VBUS_INVALID) {
+		dev_dbg(u3d->dev, "vbus invalid\n");
+		u3d->usb_state = USB_STATE_ATTACHED;
+		u3d->vbus_valid_detect = 1;
+		/* if external vbus detect is not supported,
+		 * we handle it here.
+		 */
+		if (!u3d->vbus) {
+			spin_unlock(&u3d->lock);
+			mv_u3d_vbus_session(&u3d->gadget, 0);
+			spin_lock(&u3d->lock);
+		}
+	}
+}
+
+static void mv_u3d_ch9setaddress(struct mv_u3d *u3d,
+				struct usb_ctrlrequest *setup)
+{
+	u32 tmp;
+
+	if (u3d->usb_state != USB_STATE_DEFAULT) {
+		dev_err(u3d->dev,
+			"%s, cannot setaddr in this state (%d)\n",
+			__func__, u3d->usb_state);
+		goto err;
+	}
+
+	u3d->dev_addr = (u8)setup->wValue;
+
+	dev_dbg(u3d->dev, "%s: 0x%x\n", __func__, u3d->dev_addr);
+
+	if (u3d->dev_addr > 127) {
+		dev_err(u3d->dev,
+			"%s, u3d address is wrong (out of range)\n", __func__);
+		u3d->dev_addr = 0;
+		goto err;
+	}
+
+	/* update usb state */
+	u3d->usb_state = USB_STATE_ADDRESS;
+
+	/* set the new address */
+	tmp = ioread32(&u3d->vuc_regs->devaddrtiebrkr);
+	tmp &= ~0x7F;
+	tmp |= (u32)u3d->dev_addr;
+	iowrite32(tmp, &u3d->vuc_regs->devaddrtiebrkr);
+
+	return;
+err:
+	mv_u3d_ep0_stall(u3d);
+}
+
+static int mv_u3d_is_set_configuration(struct usb_ctrlrequest *setup)
+{
+	if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD)
+		if (setup->bRequest == USB_REQ_SET_CONFIGURATION)
+			return 1;
+
+	return 0;
+}
+
+static void mv_u3d_handle_setup_packet(struct mv_u3d *u3d, u8 ep_num,
+	struct usb_ctrlrequest *setup)
+{
+	bool delegate = false;
+
+	mv_u3d_nuke(&u3d->eps[ep_num * 2 + MV_U3D_EP_DIR_IN], -ESHUTDOWN);
+
+	dev_dbg(u3d->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
+			setup->bRequestType, setup->bRequest,
+			setup->wValue, setup->wIndex, setup->wLength);
+
+	/* We process some stardard setup requests here */
+	if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+		switch (setup->bRequest) {
+		case USB_REQ_GET_STATUS:
+			delegate = true;
+			break;
+
+		case USB_REQ_SET_ADDRESS:
+			mv_u3d_ch9setaddress(u3d, setup);
+			break;
+
+		case USB_REQ_CLEAR_FEATURE:
+			delegate = true;
+			break;
+
+		case USB_REQ_SET_FEATURE:
+			delegate = true;
+			break;
+
+		default:
+			delegate = true;
+		}
+	} else
+		delegate = true;
+
+	/* delegate USB standard requests to the gadget driver */
+	if (delegate == true) {
+		/* USB requests handled by gadget */
+		if (setup->wLength) {
+			/* DATA phase from gadget, STATUS phase from u3d */
+			u3d->ep0_dir = (setup->bRequestType & USB_DIR_IN)
+					? MV_U3D_EP_DIR_IN : MV_U3D_EP_DIR_OUT;
+			spin_unlock(&u3d->lock);
+			if (u3d->driver->setup(&u3d->gadget,
+				&u3d->local_setup_buff) < 0) {
+				dev_err(u3d->dev, "setup error!\n");
+				mv_u3d_ep0_stall(u3d);
+			}
+			spin_lock(&u3d->lock);
+		} else {
+			/* no DATA phase, STATUS phase from gadget */
+			u3d->ep0_dir = MV_U3D_EP_DIR_IN;
+			u3d->ep0_state = MV_U3D_STATUS_STAGE;
+			spin_unlock(&u3d->lock);
+			if (u3d->driver->setup(&u3d->gadget,
+				&u3d->local_setup_buff) < 0)
+				mv_u3d_ep0_stall(u3d);
+			spin_lock(&u3d->lock);
+		}
+
+		if (mv_u3d_is_set_configuration(setup)) {
+			dev_dbg(u3d->dev, "u3d configured\n");
+			u3d->usb_state = USB_STATE_CONFIGURED;
+		}
+	}
+}
+
+static void mv_u3d_get_setup_data(struct mv_u3d *u3d, u8 ep_num, u8 *buffer_ptr)
+{
+	struct mv_u3d_ep_context *epcontext;
+
+	epcontext = &u3d->ep_context[ep_num * 2 + MV_U3D_EP_DIR_IN];
+
+	/* Copy the setup packet to local buffer */
+	memcpy(buffer_ptr, (u8 *) &epcontext->setup_buffer, 8);
+}
+
+static void mv_u3d_irq_process_setup(struct mv_u3d *u3d)
+{
+	u32 tmp, i;
+	/* Process all Setup packet received interrupts */
+	tmp = ioread32(&u3d->vuc_regs->setuplock);
+	if (tmp) {
+		for (i = 0; i < u3d->max_eps; i++) {
+			if (tmp & (1 << i)) {
+				mv_u3d_get_setup_data(u3d, i,
+					(u8 *)(&u3d->local_setup_buff));
+				mv_u3d_handle_setup_packet(u3d, i,
+					&u3d->local_setup_buff);
+			}
+		}
+	}
+
+	iowrite32(tmp, &u3d->vuc_regs->setuplock);
+}
+
+static void mv_u3d_irq_process_tr_complete(struct mv_u3d *u3d)
+{
+	u32 tmp, bit_pos;
+	int i, ep_num = 0, direction = 0;
+	struct mv_u3d_ep	*curr_ep;
+	struct mv_u3d_req *curr_req, *temp_req;
+	int status;
+
+	tmp = ioread32(&u3d->vuc_regs->endcomplete);
+
+	dev_dbg(u3d->dev, "tr_complete: ep: 0x%x\n", tmp);
+	if (!tmp)
+		return;
+	iowrite32(tmp, &u3d->vuc_regs->endcomplete);
+
+	for (i = 0; i < u3d->max_eps * 2; i++) {
+		ep_num = i >> 1;
+		direction = i % 2;
+
+		bit_pos = 1 << (ep_num + 16 * direction);
+
+		if (!(bit_pos & tmp))
+			continue;
+
+		if (i == 0)
+			curr_ep = &u3d->eps[1];
+		else
+			curr_ep = &u3d->eps[i];
+
+		/* remove req out of ep request list after completion */
+		dev_dbg(u3d->dev, "tr comp: check req_list\n");
+		spin_lock(&curr_ep->req_lock);
+		if (!list_empty(&curr_ep->req_list)) {
+			struct mv_u3d_req *req;
+			req = list_entry(curr_ep->req_list.next,
+						struct mv_u3d_req, list);
+			list_del_init(&req->list);
+			curr_ep->processing = 0;
+		}
+		spin_unlock(&curr_ep->req_lock);
+
+		/* process the req queue until an uncomplete request */
+		list_for_each_entry_safe(curr_req, temp_req,
+			&curr_ep->queue, queue) {
+			status = mv_u3d_process_ep_req(u3d, i, curr_req);
+			if (status)
+				break;
+			/* write back status to req */
+			curr_req->req.status = status;
+
+			/* ep0 request completion */
+			if (ep_num == 0) {
+				mv_u3d_done(curr_ep, curr_req, 0);
+				break;
+			} else {
+				mv_u3d_done(curr_ep, curr_req, status);
+			}
+		}
+
+		dev_dbg(u3d->dev, "call mv_u3d_start_queue from ep complete\n");
+		mv_u3d_start_queue(curr_ep);
+	}
+}
+
+static irqreturn_t mv_u3d_irq(int irq, void *dev)
+{
+	struct mv_u3d *u3d = (struct mv_u3d *)dev;
+	u32 status, intr;
+	u32 bridgesetting;
+	u32 trbunderrun;
+
+	spin_lock(&u3d->lock);
+
+	status = ioread32(&u3d->vuc_regs->intrcause);
+	intr = ioread32(&u3d->vuc_regs->intrenable);
+	status &= intr;
+
+	if (status == 0) {
+		spin_unlock(&u3d->lock);
+		dev_err(u3d->dev, "irq error!\n");
+		return IRQ_NONE;
+	}
+
+	if (status & MV_U3D_USBINT_VBUS_VALID) {
+		bridgesetting = ioread32(&u3d->vuc_regs->bridgesetting);
+		if (bridgesetting & MV_U3D_BRIDGE_SETTING_VBUS_VALID) {
+			/* write vbus valid bit of bridge setting to clear */
+			bridgesetting = MV_U3D_BRIDGE_SETTING_VBUS_VALID;
+			iowrite32(bridgesetting, &u3d->vuc_regs->bridgesetting);
+			dev_dbg(u3d->dev, "vbus valid\n");
+
+			u3d->usb_state = USB_STATE_POWERED;
+			u3d->vbus_valid_detect = 0;
+			/* if external vbus detect is not supported,
+			 * we handle it here.
+			 */
+			if (!u3d->vbus) {
+				spin_unlock(&u3d->lock);
+				mv_u3d_vbus_session(&u3d->gadget, 1);
+				spin_lock(&u3d->lock);
+			}
+		} else
+			dev_err(u3d->dev, "vbus bit is not set\n");
+	}
+
+	/* RX data is already in the 16KB FIFO.*/
+	if (status & MV_U3D_USBINT_UNDER_RUN) {
+		trbunderrun = ioread32(&u3d->vuc_regs->trbunderrun);
+		dev_err(u3d->dev, "under run, ep%d\n", trbunderrun);
+		iowrite32(trbunderrun, &u3d->vuc_regs->trbunderrun);
+		mv_u3d_irq_process_error(u3d);
+	}
+
+	if (status & (MV_U3D_USBINT_RXDESC_ERR | MV_U3D_USBINT_TXDESC_ERR)) {
+		/* write one to clear */
+		iowrite32(status & (MV_U3D_USBINT_RXDESC_ERR
+			| MV_U3D_USBINT_TXDESC_ERR),
+			&u3d->vuc_regs->intrcause);
+		dev_err(u3d->dev, "desc err 0x%x\n", status);
+		mv_u3d_irq_process_error(u3d);
+	}
+
+	if (status & MV_U3D_USBINT_LINK_CHG)
+		mv_u3d_irq_process_link_change(u3d);
+
+	if (status & MV_U3D_USBINT_TX_COMPLETE)
+		mv_u3d_irq_process_tr_complete(u3d);
+
+	if (status & MV_U3D_USBINT_RX_COMPLETE)
+		mv_u3d_irq_process_tr_complete(u3d);
+
+	if (status & MV_U3D_USBINT_SETUP)
+		mv_u3d_irq_process_setup(u3d);
+
+	spin_unlock(&u3d->lock);
+	return IRQ_HANDLED;
+}
+
+static void mv_u3d_gadget_release(struct device *dev)
+{
+	dev_dbg(dev, "%s\n", __func__);
+}
+
+static __devexit int mv_u3d_remove(struct platform_device *dev)
+{
+	struct mv_u3d *u3d = platform_get_drvdata(dev);
+
+	BUG_ON(u3d == NULL);
+
+	usb_del_gadget_udc(&u3d->gadget);
+
+	/* free memory allocated in probe */
+	if (u3d->trb_pool)
+		dma_pool_destroy(u3d->trb_pool);
+
+	if (u3d->ep_context)
+		dma_free_coherent(&dev->dev, u3d->ep_context_size,
+			u3d->ep_context, u3d->ep_context_dma);
+
+	kfree(u3d->eps);
+
+	if (u3d->irq)
+		free_irq(u3d->irq, &dev->dev);
+
+	if (u3d->cap_regs)
+		iounmap(u3d->cap_regs);
+	u3d->cap_regs = NULL;
+
+	kfree(u3d->status_req);
+
+	clk_put(u3d->clk);
+
+	device_unregister(&u3d->gadget.dev);
+
+	platform_set_drvdata(dev, NULL);
+
+	kfree(u3d);
+
+	return 0;
+}
+
+static int mv_u3d_probe(struct platform_device *dev)
+{
+	struct mv_u3d *u3d = NULL;
+	struct mv_usb_platform_data *pdata = dev->dev.platform_data;
+	int retval = 0;
+	struct resource *r;
+	size_t size;
+
+	if (!dev->dev.platform_data) {
+		dev_err(&dev->dev, "missing platform_data\n");
+		retval = -ENODEV;
+		goto err_pdata;
+	}
+
+	u3d = kzalloc(sizeof(*u3d), GFP_KERNEL);
+	if (!u3d) {
+		dev_err(&dev->dev, "failed to allocate memory for u3d\n");
+		retval = -ENOMEM;
+		goto err_alloc_private;
+	}
+
+	spin_lock_init(&u3d->lock);
+
+	platform_set_drvdata(dev, u3d);
+
+	u3d->dev = &dev->dev;
+	u3d->vbus = pdata->vbus;
+
+	u3d->clk = clk_get(&dev->dev, pdata->clkname[0]);
+	if (IS_ERR(u3d->clk)) {
+		retval = PTR_ERR(u3d->clk);
+		goto err_get_clk;
+	}
+
+	r = platform_get_resource_byname(dev, IORESOURCE_MEM, "capregs");
+	if (!r) {
+		dev_err(&dev->dev, "no I/O memory resource defined\n");
+		retval = -ENODEV;
+		goto err_get_cap_regs;
+	}
+
+	u3d->cap_regs = (struct mv_u3d_cap_regs __iomem *)
+		ioremap(r->start, resource_size(r));
+	if (!u3d->cap_regs) {
+		dev_err(&dev->dev, "failed to map I/O memory\n");
+		retval = -EBUSY;
+		goto err_map_cap_regs;
+	} else {
+		dev_dbg(&dev->dev, "cap_regs address: 0x%x/0x%x\n",
+			(unsigned int)r->start, (unsigned int)u3d->cap_regs);
+	}
+
+	/* we will access controller register, so enable the u3d controller */
+	clk_enable(u3d->clk);
+
+	if (pdata->phy_init) {
+		retval = pdata->phy_init(u3d->phy_regs);
+		if (retval) {
+			dev_err(&dev->dev, "init phy error %d\n", retval);
+			goto err_u3d_enable;
+		}
+	}
+
+	u3d->op_regs = (struct mv_u3d_op_regs __iomem *)((u32)u3d->cap_regs
+		+ MV_U3D_USB3_OP_REGS_OFFSET);
+
+	u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)((u32)u3d->cap_regs
+		+ ioread32(&u3d->cap_regs->vuoff));
+
+	u3d->max_eps = 16;
+
+	/*
+	 * some platform will use usb to download image, it may not disconnect
+	 * usb gadget before loading kernel. So first stop u3d here.
+	 */
+	mv_u3d_controller_stop(u3d);
+	iowrite32(0xFFFFFFFF, &u3d->vuc_regs->intrcause);
+
+	if (pdata->phy_deinit)
+		pdata->phy_deinit(u3d->phy_regs);
+	clk_disable(u3d->clk);
+
+	size = u3d->max_eps * sizeof(struct mv_u3d_ep_context) * 2;
+	size = (size + MV_U3D_EP_CONTEXT_ALIGNMENT - 1)
+		& ~(MV_U3D_EP_CONTEXT_ALIGNMENT - 1);
+	u3d->ep_context = dma_alloc_coherent(&dev->dev, size,
+					&u3d->ep_context_dma, GFP_KERNEL);
+	if (!u3d->ep_context) {
+		dev_err(&dev->dev, "allocate ep context memory failed\n");
+		retval = -ENOMEM;
+		goto err_alloc_ep_context;
+	}
+	u3d->ep_context_size = size;
+
+	/* create TRB dma_pool resource */
+	u3d->trb_pool = dma_pool_create("u3d_trb",
+			&dev->dev,
+			sizeof(struct mv_u3d_trb_hw),
+			MV_U3D_TRB_ALIGNMENT,
+			MV_U3D_DMA_BOUNDARY);
+
+	if (!u3d->trb_pool) {
+		retval = -ENOMEM;
+		goto err_alloc_trb_pool;
+	}
+
+	size = u3d->max_eps * sizeof(struct mv_u3d_ep) * 2;
+	u3d->eps = kzalloc(size, GFP_KERNEL);
+	if (!u3d->eps) {
+		dev_err(&dev->dev, "allocate ep memory failed\n");
+		retval = -ENOMEM;
+		goto err_alloc_eps;
+	}
+
+	/* initialize ep0 status request structure */
+	u3d->status_req = kzalloc(sizeof(struct mv_u3d_req) + 8, GFP_KERNEL);
+	if (!u3d->status_req) {
+		dev_err(&dev->dev, "allocate status_req memory failed\n");
+		retval = -ENOMEM;
+		goto err_alloc_status_req;
+	}
+	INIT_LIST_HEAD(&u3d->status_req->queue);
+
+	/* allocate a small amount of memory to get valid address */
+	u3d->status_req->req.buf = (char *)u3d->status_req
+					+ sizeof(struct mv_u3d_req);
+	u3d->status_req->req.dma = virt_to_phys(u3d->status_req->req.buf);
+
+	u3d->resume_state = USB_STATE_NOTATTACHED;
+	u3d->usb_state = USB_STATE_ATTACHED;
+	u3d->ep0_dir = MV_U3D_EP_DIR_OUT;
+	u3d->remote_wakeup = 0;
+
+	r = platform_get_resource(dev, IORESOURCE_IRQ, 0);
+	if (!r) {
+		dev_err(&dev->dev, "no IRQ resource defined\n");
+		retval = -ENODEV;
+		goto err_get_irq;
+	}
+	u3d->irq = r->start;
+	if (request_irq(u3d->irq, mv_u3d_irq,
+		IRQF_DISABLED | IRQF_SHARED, driver_name, u3d)) {
+		u3d->irq = 0;
+		dev_err(&dev->dev, "Request irq %d for u3d failed\n",
+			u3d->irq);
+		retval = -ENODEV;
+		goto err_request_irq;
+	}
+
+	/* initialize gadget structure */
+	u3d->gadget.ops = &mv_u3d_ops;	/* usb_gadget_ops */
+	u3d->gadget.ep0 = &u3d->eps[1].ep;	/* gadget ep0 */
+	INIT_LIST_HEAD(&u3d->gadget.ep_list);	/* ep_list */
+	u3d->gadget.speed = USB_SPEED_UNKNOWN;	/* speed */
+
+	/* the "gadget" abstracts/virtualizes the controller */
+	dev_set_name(&u3d->gadget.dev, "gadget");
+	u3d->gadget.dev.parent = &dev->dev;
+	u3d->gadget.dev.dma_mask = dev->dev.dma_mask;
+	u3d->gadget.dev.release = mv_u3d_gadget_release;
+	u3d->gadget.name = driver_name;		/* gadget name */
+
+	retval = device_register(&u3d->gadget.dev);
+	if (retval)
+		goto err_register_gadget_device;
+
+	mv_u3d_eps_init(u3d);
+
+	/* external vbus detection */
+	if (u3d->vbus) {
+		u3d->clock_gating = 1;
+		dev_err(&dev->dev, "external vbus detection\n");
+	}
+
+	if (!u3d->clock_gating)
+		u3d->vbus_active = 1;
+
+	/* enable usb3 controller vbus detection */
+	u3d->vbus_valid_detect = 1;
+
+	retval = usb_add_gadget_udc(&dev->dev, &u3d->gadget);
+	if (retval)
+		goto err_unregister;
+
+	dev_dbg(&dev->dev, "successful probe usb3 device %s clock gating.\n",
+		u3d->clock_gating ? "with" : "without");
+
+	return 0;
+
+err_unregister:
+	device_unregister(&u3d->gadget.dev);
+err_register_gadget_device:
+	free_irq(u3d->irq, &dev->dev);
+err_request_irq:
+err_get_irq:
+	kfree(u3d->status_req);
+err_alloc_status_req:
+	kfree(u3d->eps);
+err_alloc_eps:
+	dma_pool_destroy(u3d->trb_pool);
+err_alloc_trb_pool:
+	dma_free_coherent(&dev->dev, u3d->ep_context_size,
+		u3d->ep_context, u3d->ep_context_dma);
+err_alloc_ep_context:
+	if (pdata->phy_deinit)
+		pdata->phy_deinit(u3d->phy_regs);
+	clk_disable(u3d->clk);
+err_u3d_enable:
+	iounmap(u3d->cap_regs);
+err_map_cap_regs:
+err_get_cap_regs:
+err_get_clk:
+	clk_put(u3d->clk);
+	platform_set_drvdata(dev, NULL);
+	kfree(u3d);
+err_alloc_private:
+err_pdata:
+	return retval;
+}
+
+#ifdef CONFIG_PM
+static int mv_u3d_suspend(struct device *dev)
+{
+	struct mv_u3d *u3d = dev_get_drvdata(dev);
+
+	/*
+	 * only cable is unplugged, usb can suspend.
+	 * So do not care about clock_gating == 1, it is handled by
+	 * vbus session.
+	 */
+	if (!u3d->clock_gating) {
+		mv_u3d_controller_stop(u3d);
+
+		spin_lock_irq(&u3d->lock);
+		/* stop all usb activities */
+		mv_u3d_stop_activity(u3d, u3d->driver);
+		spin_unlock_irq(&u3d->lock);
+
+		mv_u3d_disable(u3d);
+	}
+
+	return 0;
+}
+
+static int mv_u3d_resume(struct device *dev)
+{
+	struct mv_u3d *u3d = dev_get_drvdata(dev);
+	int retval;
+
+	if (!u3d->clock_gating) {
+		retval = mv_u3d_enable(u3d);
+		if (retval)
+			return retval;
+
+		if (u3d->driver && u3d->softconnect) {
+			mv_u3d_controller_reset(u3d);
+			mv_u3d_ep0_reset(u3d);
+			mv_u3d_controller_start(u3d);
+		}
+	}
+
+	return 0;
+}
+
+SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
+#endif
+
+static void mv_u3d_shutdown(struct platform_device *dev)
+{
+	struct mv_u3d *u3d = dev_get_drvdata(&dev->dev);
+	u32 tmp;
+
+	tmp = ioread32(&u3d->op_regs->usbcmd);
+	tmp &= ~MV_U3D_CMD_RUN_STOP;
+	iowrite32(tmp, &u3d->op_regs->usbcmd);
+}
+
+static struct platform_driver mv_u3d_driver = {
+	.probe		= mv_u3d_probe,
+	.remove		= __exit_p(mv_u3d_remove),
+	.shutdown	= mv_u3d_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "mv-u3d",
+#ifdef CONFIG_PM
+		.pm	= &mv_u3d_pm_ops,
+#endif
+	},
+};
+
+module_platform_driver(mv_u3d_driver);
+MODULE_ALIAS("platform:mv-u3d");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Yu Xu <yuxu@marvell.com>");
+MODULE_LICENSE("GPL");

+ 8 - 7
drivers/usb/gadget/mv_udc_core.c

@@ -19,6 +19,7 @@
 #include <linux/sched.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/timer.h>
 #include <linux/timer.h>
 #include <linux/list.h>
 #include <linux/list.h>
@@ -1381,7 +1382,7 @@ static int mv_udc_start(struct usb_gadget_driver *driver,
 		return retval;
 		return retval;
 	}
 	}
 
 
-	if (udc->transceiver) {
+	if (!IS_ERR_OR_NULL(udc->transceiver)) {
 		retval = otg_set_peripheral(udc->transceiver->otg,
 		retval = otg_set_peripheral(udc->transceiver->otg,
 					&udc->gadget);
 					&udc->gadget);
 		if (retval) {
 		if (retval) {
@@ -2107,7 +2108,7 @@ static int __devexit mv_udc_remove(struct platform_device *dev)
 	 * then vbus irq will not be requested in udc driver.
 	 * then vbus irq will not be requested in udc driver.
 	 */
 	 */
 	if (udc->pdata && udc->pdata->vbus
 	if (udc->pdata && udc->pdata->vbus
-		&& udc->clock_gating && udc->transceiver == NULL)
+		&& udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
 		free_irq(udc->pdata->vbus->irq, &dev->dev);
 		free_irq(udc->pdata->vbus->irq, &dev->dev);
 
 
 	/* free memory allocated in probe */
 	/* free memory allocated in probe */
@@ -2180,7 +2181,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
 
 
 #ifdef CONFIG_USB_OTG_UTILS
 #ifdef CONFIG_USB_OTG_UTILS
 	if (pdata->mode == MV_USB_MODE_OTG)
 	if (pdata->mode == MV_USB_MODE_OTG)
-		udc->transceiver = usb_get_transceiver();
+		udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 #endif
 #endif
 
 
 	udc->clknum = pdata->clknum;
 	udc->clknum = pdata->clknum;
@@ -2325,7 +2326,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
 	eps_init(udc);
 	eps_init(udc);
 
 
 	/* VBUS detect: we can disable/enable clock on demand.*/
 	/* VBUS detect: we can disable/enable clock on demand.*/
-	if (udc->transceiver)
+	if (!IS_ERR_OR_NULL(udc->transceiver))
 		udc->clock_gating = 1;
 		udc->clock_gating = 1;
 	else if (pdata->vbus) {
 	else if (pdata->vbus) {
 		udc->clock_gating = 1;
 		udc->clock_gating = 1;
@@ -2369,7 +2370,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
 
 
 err_unregister:
 err_unregister:
 	if (udc->pdata && udc->pdata->vbus
 	if (udc->pdata && udc->pdata->vbus
-		&& udc->clock_gating && udc->transceiver == NULL)
+		&& udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
 		free_irq(pdata->vbus->irq, &dev->dev);
 		free_irq(pdata->vbus->irq, &dev->dev);
 	device_unregister(&udc->gadget.dev);
 	device_unregister(&udc->gadget.dev);
 err_free_irq:
 err_free_irq:
@@ -2404,7 +2405,7 @@ static int mv_udc_suspend(struct device *_dev)
 	struct mv_udc *udc = the_controller;
 	struct mv_udc *udc = the_controller;
 
 
 	/* if OTG is enabled, the following will be done in OTG driver*/
 	/* if OTG is enabled, the following will be done in OTG driver*/
-	if (udc->transceiver)
+	if (!IS_ERR_OR_NULL(udc->transceiver))
 		return 0;
 		return 0;
 
 
 	if (udc->pdata->vbus && udc->pdata->vbus->poll)
 	if (udc->pdata->vbus && udc->pdata->vbus->poll)
@@ -2437,7 +2438,7 @@ static int mv_udc_resume(struct device *_dev)
 	int retval;
 	int retval;
 
 
 	/* if OTG is enabled, the following will be done in OTG driver*/
 	/* if OTG is enabled, the following will be done in OTG driver*/
-	if (udc->transceiver)
+	if (!IS_ERR_OR_NULL(udc->transceiver))
 		return 0;
 		return 0;
 
 
 	if (!udc->clock_gating) {
 	if (!udc->clock_gating) {

+ 181 - 253
drivers/usb/gadget/omap_udc.c

@@ -35,10 +35,11 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/otg.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
+#include <linux/err.h>
 #include <linux/prefetch.h>
 #include <linux/prefetch.h>
+#include <linux/io.h>
 
 
 #include <asm/byteorder.h>
 #include <asm/byteorder.h>
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/irq.h>
 #include <asm/unaligned.h>
 #include <asm/unaligned.h>
 #include <asm/mach-types.h>
 #include <asm/mach-types.h>
@@ -59,11 +60,6 @@
 #define	DRIVER_DESC	"OMAP UDC driver"
 #define	DRIVER_DESC	"OMAP UDC driver"
 #define	DRIVER_VERSION	"4 October 2004"
 #define	DRIVER_VERSION	"4 October 2004"
 
 
-#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
-
-#define OMAP2_DMA_CH(ch)	(((ch) - 1) << 1)
-#define OMAP24XX_DMA(name, ch)	(OMAP24XX_DMA_##name + OMAP2_DMA_CH(ch))
-
 /*
 /*
  * The OMAP UDC needs _very_ early endpoint setup:  before enabling the
  * The OMAP UDC needs _very_ early endpoint setup:  before enabling the
  * D+ pullup to allow enumeration.  That's too early for the gadget
  * D+ pullup to allow enumeration.  That's too early for the gadget
@@ -87,14 +83,14 @@
 #ifdef	USE_ISO
 #ifdef	USE_ISO
 static unsigned fifo_mode = 3;
 static unsigned fifo_mode = 3;
 #else
 #else
-static unsigned fifo_mode = 0;
+static unsigned fifo_mode;
 #endif
 #endif
 
 
 /* "modprobe omap_udc fifo_mode=42", or else as a kernel
 /* "modprobe omap_udc fifo_mode=42", or else as a kernel
  * boot parameter "omap_udc:fifo_mode=42"
  * boot parameter "omap_udc:fifo_mode=42"
  */
  */
-module_param (fifo_mode, uint, 0);
-MODULE_PARM_DESC (fifo_mode, "endpoint configuration");
+module_param(fifo_mode, uint, 0);
+MODULE_PARM_DESC(fifo_mode, "endpoint configuration");
 
 
 #ifdef	USE_DMA
 #ifdef	USE_DMA
 static bool use_dma = 1;
 static bool use_dma = 1;
@@ -102,8 +98,8 @@ static bool use_dma = 1;
 /* "modprobe omap_udc use_dma=y", or else as a kernel
 /* "modprobe omap_udc use_dma=y", or else as a kernel
  * boot parameter "omap_udc:use_dma=y"
  * boot parameter "omap_udc:use_dma=y"
  */
  */
-module_param (use_dma, bool, 0);
-MODULE_PARM_DESC (use_dma, "enable/disable DMA");
+module_param(use_dma, bool, 0);
+MODULE_PARM_DESC(use_dma, "enable/disable DMA");
 #else	/* !USE_DMA */
 #else	/* !USE_DMA */
 
 
 /* save a bit of code */
 /* save a bit of code */
@@ -111,8 +107,8 @@ MODULE_PARM_DESC (use_dma, "enable/disable DMA");
 #endif	/* !USE_DMA */
 #endif	/* !USE_DMA */
 
 
 
 
-static const char driver_name [] = "omap_udc";
-static const char driver_desc [] = DRIVER_DESC;
+static const char driver_name[] = "omap_udc";
+static const char driver_desc[] = DRIVER_DESC;
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
@@ -250,7 +246,7 @@ static int omap_ep_disable(struct usb_ep *_ep)
 
 
 	spin_lock_irqsave(&ep->udc->lock, flags);
 	spin_lock_irqsave(&ep->udc->lock, flags);
 	ep->ep.desc = NULL;
 	ep->ep.desc = NULL;
-	nuke (ep, -ESHUTDOWN);
+	nuke(ep, -ESHUTDOWN);
 	ep->ep.maxpacket = ep->maxpacket;
 	ep->ep.maxpacket = ep->maxpacket;
 	ep->has_dma = 0;
 	ep->has_dma = 0;
 	omap_writew(UDC_SET_HALT, UDC_CTRL);
 	omap_writew(UDC_SET_HALT, UDC_CTRL);
@@ -271,10 +267,11 @@ omap_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
 	struct omap_req	*req;
 	struct omap_req	*req;
 
 
 	req = kzalloc(sizeof(*req), gfp_flags);
 	req = kzalloc(sizeof(*req), gfp_flags);
-	if (req) {
-		req->req.dma = DMA_ADDR_INVALID;
-		INIT_LIST_HEAD (&req->queue);
-	}
+	if (!req)
+		return NULL;
+
+	INIT_LIST_HEAD(&req->queue);
+
 	return &req->req;
 	return &req->req;
 }
 }
 
 
@@ -283,8 +280,7 @@ omap_free_request(struct usb_ep *ep, struct usb_request *_req)
 {
 {
 	struct omap_req	*req = container_of(_req, struct omap_req, req);
 	struct omap_req	*req = container_of(_req, struct omap_req, req);
 
 
-	if (_req)
-		kfree (req);
+	kfree(req);
 }
 }
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
@@ -292,6 +288,7 @@ omap_free_request(struct usb_ep *ep, struct usb_request *_req)
 static void
 static void
 done(struct omap_ep *ep, struct omap_req *req, int status)
 done(struct omap_ep *ep, struct omap_req *req, int status)
 {
 {
+	struct omap_udc		*udc = ep->udc;
 	unsigned		stopped = ep->stopped;
 	unsigned		stopped = ep->stopped;
 
 
 	list_del_init(&req->queue);
 	list_del_init(&req->queue);
@@ -301,22 +298,9 @@ done(struct omap_ep *ep, struct omap_req *req, int status)
 	else
 	else
 		status = req->req.status;
 		status = req->req.status;
 
 
-	if (use_dma && ep->has_dma) {
-		if (req->mapped) {
-			dma_unmap_single(ep->udc->gadget.dev.parent,
-				req->req.dma, req->req.length,
-				(ep->bEndpointAddress & USB_DIR_IN)
-					? DMA_TO_DEVICE
-					: DMA_FROM_DEVICE);
-			req->req.dma = DMA_ADDR_INVALID;
-			req->mapped = 0;
-		} else
-			dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
-				req->req.dma, req->req.length,
-				(ep->bEndpointAddress & USB_DIR_IN)
-					? DMA_TO_DEVICE
-					: DMA_FROM_DEVICE);
-	}
+	if (use_dma && ep->has_dma)
+		usb_gadget_unmap_request(&udc->gadget, &req->req,
+				(ep->bEndpointAddress & USB_DIR_IN));
 
 
 #ifndef	USB_TRACE
 #ifndef	USB_TRACE
 	if (status && status != -ESHUTDOWN)
 	if (status && status != -ESHUTDOWN)
@@ -364,10 +348,10 @@ write_packet(u8 *buf, struct omap_req *req, unsigned max)
 	return len;
 	return len;
 }
 }
 
 
-// FIXME change r/w fifo calling convention
+/* FIXME change r/w fifo calling convention */
 
 
 
 
-// return:  0 = still running, 1 = completed, negative = errno
+/* return:  0 = still running, 1 = completed, negative = errno */
 static int write_fifo(struct omap_ep *ep, struct omap_req *req)
 static int write_fifo(struct omap_ep *ep, struct omap_req *req)
 {
 {
 	u8		*buf;
 	u8		*buf;
@@ -429,7 +413,7 @@ read_packet(u8 *buf, struct omap_req *req, unsigned avail)
 	return len;
 	return len;
 }
 }
 
 
-// return:  0 = still running, 1 = queue empty, negative = errno
+/* return:  0 = still running, 1 = queue empty, negative = errno */
 static int read_fifo(struct omap_ep *ep, struct omap_req *req)
 static int read_fifo(struct omap_ep *ep, struct omap_req *req)
 {
 {
 	u8		*buf;
 	u8		*buf;
@@ -536,12 +520,8 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req)
 				: OMAP_DMA_SYNC_ELEMENT;
 				: OMAP_DMA_SYNC_ELEMENT;
 	int		dma_trigger = 0;
 	int		dma_trigger = 0;
 
 
-	if (cpu_is_omap24xx())
-		dma_trigger = OMAP24XX_DMA(USB_W2FC_TX0, ep->dma_channel);
-
 	/* measure length in either bytes or packets */
 	/* measure length in either bytes or packets */
 	if ((cpu_is_omap16xx() && length <= UDC_TXN_TSC)
 	if ((cpu_is_omap16xx() && length <= UDC_TXN_TSC)
-			|| (cpu_is_omap24xx() && length < ep->maxpacket)
 			|| (cpu_is_omap15xx() && length < ep->maxpacket)) {
 			|| (cpu_is_omap15xx() && length < ep->maxpacket)) {
 		txdma_ctrl = UDC_TXN_EOT | length;
 		txdma_ctrl = UDC_TXN_EOT | length;
 		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
 		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
@@ -600,28 +580,14 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
 	int dma_trigger = 0;
 	int dma_trigger = 0;
 	u16 w;
 	u16 w;
 
 
-	if (cpu_is_omap24xx())
-		dma_trigger = OMAP24XX_DMA(USB_W2FC_RX0, ep->dma_channel);
-
-	/* NOTE:  we filtered out "short reads" before, so we know
-	 * the buffer has only whole numbers of packets.
-	 * except MODE SELECT(6) sent the 24 bytes data in OMAP24XX DMA mode
-	 */
-	if (cpu_is_omap24xx() && packets < ep->maxpacket) {
-		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
-				packets, 1, OMAP_DMA_SYNC_ELEMENT,
-				dma_trigger, 0);
-		req->dma_bytes = packets;
-	} else {
-		/* set up this DMA transfer, enable the fifo, start */
-		packets /= ep->ep.maxpacket;
-		packets = min(packets, (unsigned)UDC_RXN_TC + 1);
-		req->dma_bytes = packets * ep->ep.maxpacket;
-		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
-				ep->ep.maxpacket >> 1, packets,
-				OMAP_DMA_SYNC_ELEMENT,
-				dma_trigger, 0);
-	}
+	/* set up this DMA transfer, enable the fifo, start */
+	packets /= ep->ep.maxpacket;
+	packets = min(packets, (unsigned)UDC_RXN_TC + 1);
+	req->dma_bytes = packets * ep->ep.maxpacket;
+	omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
+			ep->ep.maxpacket >> 1, packets,
+			OMAP_DMA_SYNC_ELEMENT,
+			dma_trigger, 0);
 	omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
 	omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
 		OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
 		OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
 		0, 0);
 		0, 0);
@@ -683,7 +649,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src)
 		}
 		}
 		omap_writew(UDC_TXN_DONE, UDC_IRQ_SRC);
 		omap_writew(UDC_TXN_DONE, UDC_IRQ_SRC);
 
 
-		if (!list_empty (&ep->queue)) {
+		if (!list_empty(&ep->queue)) {
 			req = container_of(ep->queue.next,
 			req = container_of(ep->queue.next,
 					struct omap_req, queue);
 					struct omap_req, queue);
 			next_in_dma(ep, req);
 			next_in_dma(ep, req);
@@ -702,7 +668,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src)
 		}
 		}
 		omap_writew(UDC_RXN_EOT, UDC_IRQ_SRC);
 		omap_writew(UDC_RXN_EOT, UDC_IRQ_SRC);
 
 
-		if (!list_empty (&ep->queue)) {
+		if (!list_empty(&ep->queue)) {
 			req = container_of(ep->queue.next,
 			req = container_of(ep->queue.next,
 					struct omap_req, queue);
 					struct omap_req, queue);
 			next_out_dma(ep, req);
 			next_out_dma(ep, req);
@@ -760,10 +726,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
 	ep->dma_channel = channel;
 	ep->dma_channel = channel;
 
 
 	if (is_in) {
 	if (is_in) {
-		if (cpu_is_omap24xx())
-			dma_channel = OMAP24XX_DMA(USB_W2FC_TX0, channel);
-		else
-			dma_channel = OMAP_DMA_USB_W2FC_TX0 - 1 + channel;
+		dma_channel = OMAP_DMA_USB_W2FC_TX0 - 1 + channel;
 		status = omap_request_dma(dma_channel,
 		status = omap_request_dma(dma_channel,
 			ep->ep.name, dma_error, ep, &ep->lch);
 			ep->ep.name, dma_error, ep, &ep->lch);
 		if (status == 0) {
 		if (status == 0) {
@@ -780,11 +743,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
 				0, 0);
 				0, 0);
 		}
 		}
 	} else {
 	} else {
-		if (cpu_is_omap24xx())
-			dma_channel = OMAP24XX_DMA(USB_W2FC_RX0, channel);
-		else
-			dma_channel = OMAP_DMA_USB_W2FC_RX0 - 1 + channel;
-
+		dma_channel = OMAP_DMA_USB_W2FC_RX0 - 1 + channel;
 		status = omap_request_dma(dma_channel,
 		status = omap_request_dma(dma_channel,
 			ep->ep.name, dma_error, ep, &ep->lch);
 			ep->ep.name, dma_error, ep, &ep->lch);
 		if (status == 0) {
 		if (status == 0) {
@@ -808,7 +767,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
 		omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ);
 		omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ);
 
 
 		/* channel type P: hw synch (fifo) */
 		/* channel type P: hw synch (fifo) */
-		if (cpu_class_is_omap1() && !cpu_is_omap15xx())
+		if (!cpu_is_omap15xx())
 			omap_set_dma_channel_mode(ep->lch, OMAP_DMA_LCH_P);
 			omap_set_dma_channel_mode(ep->lch, OMAP_DMA_LCH_P);
 	}
 	}
 
 
@@ -928,13 +887,11 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
 
 	/* this isn't bogus, but OMAP DMA isn't the only hardware to
 	/* this isn't bogus, but OMAP DMA isn't the only hardware to
 	 * have a hard time with partial packet reads...  reject it.
 	 * have a hard time with partial packet reads...  reject it.
-	 * Except OMAP2 can handle the small packets.
 	 */
 	 */
 	if (use_dma
 	if (use_dma
 			&& ep->has_dma
 			&& ep->has_dma
 			&& ep->bEndpointAddress != 0
 			&& ep->bEndpointAddress != 0
 			&& (ep->bEndpointAddress & USB_DIR_IN) == 0
 			&& (ep->bEndpointAddress & USB_DIR_IN) == 0
-			&& !cpu_class_is_omap2()
 			&& (req->req.length % ep->ep.maxpacket) != 0) {
 			&& (req->req.length % ep->ep.maxpacket) != 0) {
 		DBG("%s, no partial packet OUT reads\n", __func__);
 		DBG("%s, no partial packet OUT reads\n", __func__);
 		return -EMSGSIZE;
 		return -EMSGSIZE;
@@ -944,26 +901,9 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
 	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
 		return -ESHUTDOWN;
 		return -ESHUTDOWN;
 
 
-	if (use_dma && ep->has_dma) {
-		if (req->req.dma == DMA_ADDR_INVALID) {
-			req->req.dma = dma_map_single(
-				ep->udc->gadget.dev.parent,
-				req->req.buf,
-				req->req.length,
-				(ep->bEndpointAddress & USB_DIR_IN)
-					? DMA_TO_DEVICE
-					: DMA_FROM_DEVICE);
-			req->mapped = 1;
-		} else {
-			dma_sync_single_for_device(
-				ep->udc->gadget.dev.parent,
-				req->req.dma, req->req.length,
-				(ep->bEndpointAddress & USB_DIR_IN)
-					? DMA_TO_DEVICE
-					: DMA_FROM_DEVICE);
-			req->mapped = 0;
-		}
-	}
+	if (use_dma && ep->has_dma)
+		usb_gadget_map_request(&udc->gadget, &req->req,
+				(ep->bEndpointAddress & USB_DIR_IN));
 
 
 	VDBG("%s queue req %p, len %d buf %p\n",
 	VDBG("%s queue req %p, len %d buf %p\n",
 		ep->ep.name, _req, _req->length, _req->buf);
 		ep->ep.name, _req, _req->length, _req->buf);
@@ -984,7 +924,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 		int	is_in;
 		int	is_in;
 
 
 		if (ep->bEndpointAddress == 0) {
 		if (ep->bEndpointAddress == 0) {
-			if (!udc->ep0_pending || !list_empty (&ep->queue)) {
+			if (!udc->ep0_pending || !list_empty(&ep->queue)) {
 				spin_unlock_irqrestore(&udc->lock, flags);
 				spin_unlock_irqrestore(&udc->lock, flags);
 				return -EL2HLT;
 				return -EL2HLT;
 			}
 			}
@@ -1011,7 +951,8 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 				 * always an IN ... even for IN transfers,
 				 * always an IN ... even for IN transfers,
 				 * a weird case which seem to stall OMAP.
 				 * a weird case which seem to stall OMAP.
 				 */
 				 */
-				omap_writew(UDC_EP_SEL | UDC_EP_DIR, UDC_EP_NUM);
+				omap_writew(UDC_EP_SEL | UDC_EP_DIR,
+						UDC_EP_NUM);
 				omap_writew(UDC_CLR_EP, UDC_CTRL);
 				omap_writew(UDC_CLR_EP, UDC_CTRL);
 				omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
 				omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
 				omap_writew(UDC_EP_DIR, UDC_EP_NUM);
 				omap_writew(UDC_EP_DIR, UDC_EP_NUM);
@@ -1023,7 +964,8 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
 
 			/* non-empty DATA stage */
 			/* non-empty DATA stage */
 			} else if (is_in) {
 			} else if (is_in) {
-				omap_writew(UDC_EP_SEL | UDC_EP_DIR, UDC_EP_NUM);
+				omap_writew(UDC_EP_SEL | UDC_EP_DIR,
+						UDC_EP_NUM);
 			} else {
 			} else {
 				if (udc->ep0_setup)
 				if (udc->ep0_setup)
 					goto irq_wait;
 					goto irq_wait;
@@ -1071,7 +1013,7 @@ static int omap_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
 	spin_lock_irqsave(&ep->udc->lock, flags);
 	spin_lock_irqsave(&ep->udc->lock, flags);
 
 
 	/* make sure it's actually queued on this endpoint */
 	/* make sure it's actually queued on this endpoint */
-	list_for_each_entry (req, &ep->queue, queue) {
+	list_for_each_entry(req, &ep->queue, queue) {
 		if (&req->req == _req)
 		if (&req->req == _req)
 			break;
 			break;
 	}
 	}
@@ -1178,8 +1120,8 @@ static struct usb_ep_ops omap_ep_ops = {
 	.dequeue	= omap_ep_dequeue,
 	.dequeue	= omap_ep_dequeue,
 
 
 	.set_halt	= omap_ep_set_halt,
 	.set_halt	= omap_ep_set_halt,
-	// fifo_status ... report bytes in fifo
-	// fifo_flush ... flush fifo
+	/* fifo_status ... report bytes in fifo */
+	/* fifo_flush ... flush fifo */
 };
 };
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
@@ -1211,7 +1153,7 @@ static int omap_wakeup(struct usb_gadget *gadget)
 
 
 	/* NOTE:  non-OTG systems may use SRP TOO... */
 	/* NOTE:  non-OTG systems may use SRP TOO... */
 	} else if (!(udc->devstat & UDC_ATT)) {
 	} else if (!(udc->devstat & UDC_ATT)) {
-		if (udc->transceiver)
+		if (!IS_ERR_OR_NULL(udc->transceiver))
 			retval = otg_start_srp(udc->transceiver->otg);
 			retval = otg_start_srp(udc->transceiver->otg);
 	}
 	}
 	spin_unlock_irqrestore(&udc->lock, flags);
 	spin_unlock_irqrestore(&udc->lock, flags);
@@ -1343,7 +1285,7 @@ static int omap_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 	struct omap_udc	*udc;
 	struct omap_udc	*udc;
 
 
 	udc = container_of(gadget, struct omap_udc, gadget);
 	udc = container_of(gadget, struct omap_udc, gadget);
-	if (udc->transceiver)
+	if (!IS_ERR_OR_NULL(udc->transceiver))
 		return usb_phy_set_power(udc->transceiver, mA);
 		return usb_phy_set_power(udc->transceiver, mA);
 	return -EOPNOTSUPP;
 	return -EOPNOTSUPP;
 }
 }
@@ -1409,7 +1351,7 @@ static void udc_quiesce(struct omap_udc *udc)
 
 
 	udc->gadget.speed = USB_SPEED_UNKNOWN;
 	udc->gadget.speed = USB_SPEED_UNKNOWN;
 	nuke(&udc->ep[0], -ESHUTDOWN);
 	nuke(&udc->ep[0], -ESHUTDOWN);
-	list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list)
+	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list)
 		nuke(ep, -ESHUTDOWN);
 		nuke(ep, -ESHUTDOWN);
 }
 }
 
 
@@ -1525,7 +1467,8 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
 				/* read next OUT packet of request, maybe
 				/* read next OUT packet of request, maybe
 				 * reactiviting the fifo; stall on errors.
 				 * reactiviting the fifo; stall on errors.
 				 */
 				 */
-				if (!req || (stat = read_fifo(ep0, req)) < 0) {
+				stat = read_fifo(ep0, req);
+				if (!req || stat < 0) {
 					omap_writew(UDC_STALL_CMD, UDC_SYSCON2);
 					omap_writew(UDC_STALL_CMD, UDC_SYSCON2);
 					udc->ep0_pending = 0;
 					udc->ep0_pending = 0;
 					stat = 0;
 					stat = 0;
@@ -1658,7 +1601,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
 				/* this has rude side-effects (aborts) and
 				/* this has rude side-effects (aborts) and
 				 * can't really work if DMA-IN is active
 				 * can't really work if DMA-IN is active
 				 */
 				 */
-				DBG("%s host set_halt, NYET \n", ep->name);
+				DBG("%s host set_halt, NYET\n", ep->name);
 				goto do_stall;
 				goto do_stall;
 			}
 			}
 			use_ep(ep, 0);
 			use_ep(ep, 0);
@@ -1749,7 +1692,7 @@ delegate:
 			 */
 			 */
 			udc->ep0_setup = 1;
 			udc->ep0_setup = 1;
 			spin_unlock(&udc->lock);
 			spin_unlock(&udc->lock);
-			status = udc->driver->setup (&udc->gadget, &u.r);
+			status = udc->driver->setup(&udc->gadget, &u.r);
 			spin_lock(&udc->lock);
 			spin_lock(&udc->lock);
 			udc->ep0_setup = 0;
 			udc->ep0_setup = 0;
 		}
 		}
@@ -1792,12 +1735,12 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
 			if (devstat & UDC_ATT) {
 			if (devstat & UDC_ATT) {
 				udc->gadget.speed = USB_SPEED_FULL;
 				udc->gadget.speed = USB_SPEED_FULL;
 				VDBG("connect\n");
 				VDBG("connect\n");
-				if (!udc->transceiver)
+				if (IS_ERR_OR_NULL(udc->transceiver))
 					pullup_enable(udc);
 					pullup_enable(udc);
-				// if (driver->connect) call it
+				/* if (driver->connect) call it */
 			} else if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
 			} else if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
 				udc->gadget.speed = USB_SPEED_UNKNOWN;
 				udc->gadget.speed = USB_SPEED_UNKNOWN;
-				if (!udc->transceiver)
+				if (IS_ERR_OR_NULL(udc->transceiver))
 					pullup_disable(udc);
 					pullup_disable(udc);
 				DBG("disconnect, gadget %s\n",
 				DBG("disconnect, gadget %s\n",
 					udc->driver->driver.name);
 					udc->driver->driver.name);
@@ -1826,7 +1769,7 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
 	}
 	}
 	if (change & UDC_SUS) {
 	if (change & UDC_SUS) {
 		if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
 		if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
-			// FIXME tell isp1301 to suspend/resume (?)
+			/* FIXME tell isp1301 to suspend/resume (?) */
 			if (devstat & UDC_SUS) {
 			if (devstat & UDC_SUS) {
 				VDBG("suspend\n");
 				VDBG("suspend\n");
 				update_otg(udc);
 				update_otg(udc);
@@ -1837,12 +1780,12 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
 					udc->driver->suspend(&udc->gadget);
 					udc->driver->suspend(&udc->gadget);
 					spin_lock(&udc->lock);
 					spin_lock(&udc->lock);
 				}
 				}
-				if (udc->transceiver)
+				if (!IS_ERR_OR_NULL(udc->transceiver))
 					usb_phy_set_suspend(
 					usb_phy_set_suspend(
 							udc->transceiver, 1);
 							udc->transceiver, 1);
 			} else {
 			} else {
 				VDBG("resume\n");
 				VDBG("resume\n");
-				if (udc->transceiver)
+				if (!IS_ERR_OR_NULL(udc->transceiver))
 					usb_phy_set_suspend(
 					usb_phy_set_suspend(
 							udc->transceiver, 0);
 							udc->transceiver, 0);
 				if (udc->gadget.speed == USB_SPEED_FULL
 				if (udc->gadget.speed == USB_SPEED_FULL
@@ -2029,7 +1972,7 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev)
 	spin_lock_irqsave(&udc->lock, flags);
 	spin_lock_irqsave(&udc->lock, flags);
 
 
 	/* handle all non-DMA ISO transfers */
 	/* handle all non-DMA ISO transfers */
-	list_for_each_entry (ep, &udc->iso, iso) {
+	list_for_each_entry(ep, &udc->iso, iso) {
 		u16		stat;
 		u16		stat;
 		struct omap_req	*req;
 		struct omap_req	*req;
 
 
@@ -2088,15 +2031,11 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev)
 
 
 static inline int machine_without_vbus_sense(void)
 static inline int machine_without_vbus_sense(void)
 {
 {
-	return (machine_is_omap_innovator()
+	return machine_is_omap_innovator()
 		|| machine_is_omap_osk()
 		|| machine_is_omap_osk()
-		|| machine_is_omap_apollon()
-#ifndef CONFIG_MACH_OMAP_H4_OTG
-		|| machine_is_omap_h4()
-#endif
 		|| machine_is_sx1()
 		|| machine_is_sx1()
-		|| cpu_is_omap7xx() /* No known omap7xx boards with vbus sense */
-		);
+		/* No known omap7xx boards with vbus sense */
+		|| cpu_is_omap7xx();
 }
 }
 
 
 static int omap_udc_start(struct usb_gadget_driver *driver,
 static int omap_udc_start(struct usb_gadget_driver *driver,
@@ -2110,7 +2049,7 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
 	if (!udc)
 	if (!udc)
 		return -ENODEV;
 		return -ENODEV;
 	if (!driver
 	if (!driver
-			// FIXME if otg, check:  driver->is_otg
+			/* FIXME if otg, check:  driver->is_otg */
 			|| driver->max_speed < USB_SPEED_FULL
 			|| driver->max_speed < USB_SPEED_FULL
 			|| !bind || !driver->setup)
 			|| !bind || !driver->setup)
 		return -EINVAL;
 		return -EINVAL;
@@ -2122,7 +2061,7 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
 	}
 	}
 
 
 	/* reset state */
 	/* reset state */
-	list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) {
+	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
 		ep->irqs = 0;
 		ep->irqs = 0;
 		if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
 		if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
 			continue;
 			continue;
@@ -2154,13 +2093,13 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
 	omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
 	omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
 
 
 	/* connect to bus through transceiver */
 	/* connect to bus through transceiver */
-	if (udc->transceiver) {
+	if (!IS_ERR_OR_NULL(udc->transceiver)) {
 		status = otg_set_peripheral(udc->transceiver->otg,
 		status = otg_set_peripheral(udc->transceiver->otg,
 						&udc->gadget);
 						&udc->gadget);
 		if (status < 0) {
 		if (status < 0) {
 			ERR("can't bind to transceiver\n");
 			ERR("can't bind to transceiver\n");
 			if (driver->unbind) {
 			if (driver->unbind) {
-				driver->unbind (&udc->gadget);
+				driver->unbind(&udc->gadget);
 				udc->gadget.dev.driver = NULL;
 				udc->gadget.dev.driver = NULL;
 				udc->driver = NULL;
 				udc->driver = NULL;
 			}
 			}
@@ -2168,9 +2107,9 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
 		}
 		}
 	} else {
 	} else {
 		if (can_pullup(udc))
 		if (can_pullup(udc))
-			pullup_enable (udc);
+			pullup_enable(udc);
 		else
 		else
-			pullup_disable (udc);
+			pullup_disable(udc);
 	}
 	}
 
 
 	/* boards that don't have VBUS sensing can't autogate 48MHz;
 	/* boards that don't have VBUS sensing can't autogate 48MHz;
@@ -2201,7 +2140,7 @@ static int omap_udc_stop(struct usb_gadget_driver *driver)
 	if (machine_without_vbus_sense())
 	if (machine_without_vbus_sense())
 		omap_vbus_session(&udc->gadget, 0);
 		omap_vbus_session(&udc->gadget, 0);
 
 
-	if (udc->transceiver)
+	if (!IS_ERR_OR_NULL(udc->transceiver))
 		(void) otg_set_peripheral(udc->transceiver->otg, NULL);
 		(void) otg_set_peripheral(udc->transceiver->otg, NULL);
 	else
 	else
 		pullup_disable(udc);
 		pullup_disable(udc);
@@ -2229,7 +2168,7 @@ static int omap_udc_stop(struct usb_gadget_driver *driver)
 static const char proc_filename[] = "driver/udc";
 static const char proc_filename[] = "driver/udc";
 
 
 #define FOURBITS "%s%s%s%s"
 #define FOURBITS "%s%s%s%s"
-#define EIGHTBITS FOURBITS FOURBITS
+#define EIGHTBITS "%s%s%s%s%s%s%s%s"
 
 
 static void proc_ep_show(struct seq_file *s, struct omap_ep *ep)
 static void proc_ep_show(struct seq_file *s, struct omap_ep *ep)
 {
 {
@@ -2251,12 +2190,21 @@ static void proc_ep_show(struct seq_file *s, struct omap_ep *ep)
 		"\n%s %s%s%sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n",
 		"\n%s %s%s%sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n",
 		ep->name, buf,
 		ep->name, buf,
 		ep->double_buf ? "dbuf " : "",
 		ep->double_buf ? "dbuf " : "",
-		({char *s; switch(ep->ackwait){
-		case 0: s = ""; break;
-		case 1: s = "(ackw) "; break;
-		case 2: s = "(ackw2) "; break;
-		default: s = "(?) "; break;
-		} s;}),
+		({ char *s;
+		switch (ep->ackwait) {
+		case 0:
+			s = "";
+			break;
+		case 1:
+			s = "(ackw) ";
+			break;
+		case 2:
+			s = "(ackw2) ";
+			break;
+		default:
+			s = "(?) ";
+			break;
+		} s; }),
 		ep->irqs, stat_flg,
 		ep->irqs, stat_flg,
 		(stat_flg & UDC_NO_RXPACKET) ? "no_rxpacket " : "",
 		(stat_flg & UDC_NO_RXPACKET) ? "no_rxpacket " : "",
 		(stat_flg & UDC_MISS_IN) ? "miss_in " : "",
 		(stat_flg & UDC_MISS_IN) ? "miss_in " : "",
@@ -2272,10 +2220,10 @@ static void proc_ep_show(struct seq_file *s, struct omap_ep *ep)
 		(stat_flg & UDC_NON_ISO_FIFO_EMPTY) ? "fifo_empty " : "",
 		(stat_flg & UDC_NON_ISO_FIFO_EMPTY) ? "fifo_empty " : "",
 		(stat_flg & UDC_NON_ISO_FIFO_FULL) ? "fifo_full " : "");
 		(stat_flg & UDC_NON_ISO_FIFO_FULL) ? "fifo_full " : "");
 
 
-	if (list_empty (&ep->queue))
+	if (list_empty(&ep->queue))
 		seq_printf(s, "\t(queue empty)\n");
 		seq_printf(s, "\t(queue empty)\n");
 	else
 	else
-		list_for_each_entry (req, &ep->queue, queue) {
+		list_for_each_entry(req, &ep->queue, queue) {
 			unsigned	length = req->req.actual;
 			unsigned	length = req->req.actual;
 
 
 			if (use_dma && buf[0]) {
 			if (use_dma && buf[0]) {
@@ -2293,11 +2241,16 @@ static void proc_ep_show(struct seq_file *s, struct omap_ep *ep)
 static char *trx_mode(unsigned m, int enabled)
 static char *trx_mode(unsigned m, int enabled)
 {
 {
 	switch (m) {
 	switch (m) {
-	case 0:		return enabled ? "*6wire" : "unused";
-	case 1:		return "4wire";
-	case 2:		return "3wire";
-	case 3:		return "6wire";
-	default:	return "unknown";
+	case 0:
+		return enabled ? "*6wire" : "unused";
+	case 1:
+		return "4wire";
+	case 2:
+		return "3wire";
+	case 3:
+		return "6wire";
+	default:
+		return "unknown";
 	}
 	}
 }
 }
 
 
@@ -2307,12 +2260,9 @@ static int proc_otg_show(struct seq_file *s)
 	u32		trans = 0;
 	u32		trans = 0;
 	char		*ctrl_name = "(UNKNOWN)";
 	char		*ctrl_name = "(UNKNOWN)";
 
 
-	/* XXX This needs major revision for OMAP2+ */
 	tmp = omap_readl(OTG_REV);
 	tmp = omap_readl(OTG_REV);
-	if (cpu_class_is_omap1()) {
-		ctrl_name = "tranceiver_ctrl";
-		trans = omap_readw(USB_TRANSCEIVER_CTRL);
-	}
+	ctrl_name = "tranceiver_ctrl";
+	trans = omap_readw(USB_TRANSCEIVER_CTRL);
 	seq_printf(s, "\nOTG rev %d.%d, %s %05x\n",
 	seq_printf(s, "\nOTG rev %d.%d, %s %05x\n",
 		tmp >> 4, tmp & 0xf, ctrl_name, trans);
 		tmp >> 4, tmp & 0xf, ctrl_name, trans);
 	tmp = omap_readw(OTG_SYSCON_1);
 	tmp = omap_readw(OTG_SYSCON_1);
@@ -2332,7 +2282,7 @@ static int proc_otg_show(struct seq_file *s)
 			" b_ase_brst=%d hmc=%d\n", tmp,
 			" b_ase_brst=%d hmc=%d\n", tmp,
 		(tmp & OTG_EN) ? " otg_en" : "",
 		(tmp & OTG_EN) ? " otg_en" : "",
 		(tmp & USBX_SYNCHRO) ? " synchro" : "",
 		(tmp & USBX_SYNCHRO) ? " synchro" : "",
-		// much more SRP stuff
+		/* much more SRP stuff */
 		(tmp & SRP_DATA) ? " srp_data" : "",
 		(tmp & SRP_DATA) ? " srp_data" : "",
 		(tmp & SRP_VBUS) ? " srp_vbus" : "",
 		(tmp & SRP_VBUS) ? " srp_vbus" : "",
 		(tmp & OTG_PADEN) ? " otg_paden" : "",
 		(tmp & OTG_PADEN) ? " otg_paden" : "",
@@ -2399,14 +2349,12 @@ static int proc_udc_show(struct seq_file *s, void *_)
 		HMC,
 		HMC,
 		udc->transceiver
 		udc->transceiver
 			? udc->transceiver->label
 			? udc->transceiver->label
-			: ((cpu_is_omap1710() || cpu_is_omap24xx())
+			: (cpu_is_omap1710()
 				? "external" : "(none)"));
 				? "external" : "(none)"));
-	if (cpu_class_is_omap1()) {
-		seq_printf(s, "ULPD control %04x req %04x status %04x\n",
-			omap_readw(ULPD_CLOCK_CTRL),
-			omap_readw(ULPD_SOFT_REQ),
-			omap_readw(ULPD_STATUS_REQ));
-	}
+	seq_printf(s, "ULPD control %04x req %04x status %04x\n",
+		omap_readw(ULPD_CLOCK_CTRL),
+		omap_readw(ULPD_SOFT_REQ),
+		omap_readw(ULPD_STATUS_REQ));
 
 
 	/* OTG controller registers */
 	/* OTG controller registers */
 	if (!cpu_is_omap15xx())
 	if (!cpu_is_omap15xx())
@@ -2422,7 +2370,7 @@ static int proc_udc_show(struct seq_file *s, void *_)
 		(tmp & UDC_SELF_PWR) ? " self_pwr" : "",
 		(tmp & UDC_SELF_PWR) ? " self_pwr" : "",
 		(tmp & UDC_SOFF_DIS) ? " soff_dis" : "",
 		(tmp & UDC_SOFF_DIS) ? " soff_dis" : "",
 		(tmp & UDC_PULLUP_EN) ? " PULLUP" : "");
 		(tmp & UDC_PULLUP_EN) ? " PULLUP" : "");
-	// syscon2 is write-only
+	/* syscon2 is write-only */
 
 
 	/* UDC controller registers */
 	/* UDC controller registers */
 	if (!(tmp & UDC_PULLUP_EN)) {
 	if (!(tmp & UDC_PULLUP_EN)) {
@@ -2506,7 +2454,7 @@ static int proc_udc_show(struct seq_file *s, void *_)
 	if (tmp & UDC_ATT) {
 	if (tmp & UDC_ATT) {
 		proc_ep_show(s, &udc->ep[0]);
 		proc_ep_show(s, &udc->ep[0]);
 		if (tmp & UDC_ADD) {
 		if (tmp & UDC_ADD) {
-			list_for_each_entry (ep, &udc->gadget.ep_list,
+			list_for_each_entry(ep, &udc->gadget.ep_list,
 					ep.ep_list) {
 					ep.ep_list) {
 				if (ep->ep.desc)
 				if (ep->ep.desc)
 					proc_ep_show(s, ep);
 					proc_ep_show(s, ep);
@@ -2557,7 +2505,7 @@ static inline void remove_proc_file(void) {}
  * UDC_SYSCON_1.CFG_LOCK is set can now work.  We won't use that
  * UDC_SYSCON_1.CFG_LOCK is set can now work.  We won't use that
  * capability yet though.
  * capability yet though.
  */
  */
-static unsigned __init
+static unsigned __devinit
 omap_ep_setup(char *name, u8 addr, u8 type,
 omap_ep_setup(char *name, u8 addr, u8 type,
 		unsigned buf, unsigned maxp, int dbuf)
 		unsigned buf, unsigned maxp, int dbuf)
 {
 {
@@ -2575,14 +2523,29 @@ omap_ep_setup(char *name, u8 addr, u8 type,
 	/* chip setup ... bit values are same for IN, OUT */
 	/* chip setup ... bit values are same for IN, OUT */
 	if (type == USB_ENDPOINT_XFER_ISOC) {
 	if (type == USB_ENDPOINT_XFER_ISOC) {
 		switch (maxp) {
 		switch (maxp) {
-		case 8:		epn_rxtx = 0 << 12; break;
-		case 16:	epn_rxtx = 1 << 12; break;
-		case 32:	epn_rxtx = 2 << 12; break;
-		case 64:	epn_rxtx = 3 << 12; break;
-		case 128:	epn_rxtx = 4 << 12; break;
-		case 256:	epn_rxtx = 5 << 12; break;
-		case 512:	epn_rxtx = 6 << 12; break;
-		default:	BUG();
+		case 8:
+			epn_rxtx = 0 << 12;
+			break;
+		case 16:
+			epn_rxtx = 1 << 12;
+			break;
+		case 32:
+			epn_rxtx = 2 << 12;
+			break;
+		case 64:
+			epn_rxtx = 3 << 12;
+			break;
+		case 128:
+			epn_rxtx = 4 << 12;
+			break;
+		case 256:
+			epn_rxtx = 5 << 12;
+			break;
+		case 512:
+			epn_rxtx = 6 << 12;
+			break;
+		default:
+			BUG();
 		}
 		}
 		epn_rxtx |= UDC_EPN_RX_ISO;
 		epn_rxtx |= UDC_EPN_RX_ISO;
 		dbuf = 1;
 		dbuf = 1;
@@ -2591,15 +2554,24 @@ omap_ep_setup(char *name, u8 addr, u8 type,
 		 * and ignored for PIO-IN on newer chips
 		 * and ignored for PIO-IN on newer chips
 		 * (for more reliable behavior)
 		 * (for more reliable behavior)
 		 */
 		 */
-		if (!use_dma || cpu_is_omap15xx() || cpu_is_omap24xx())
+		if (!use_dma || cpu_is_omap15xx())
 			dbuf = 0;
 			dbuf = 0;
 
 
 		switch (maxp) {
 		switch (maxp) {
-		case 8:		epn_rxtx = 0 << 12; break;
-		case 16:	epn_rxtx = 1 << 12; break;
-		case 32:	epn_rxtx = 2 << 12; break;
-		case 64:	epn_rxtx = 3 << 12; break;
-		default:	BUG();
+		case 8:
+			epn_rxtx = 0 << 12;
+			break;
+		case 16:
+			epn_rxtx = 1 << 12;
+			break;
+		case 32:
+			epn_rxtx = 2 << 12;
+			break;
+		case 64:
+			epn_rxtx = 3 << 12;
+			break;
+		default:
+			BUG();
 		}
 		}
 		if (dbuf && addr)
 		if (dbuf && addr)
 			epn_rxtx |= UDC_EPN_RX_DB;
 			epn_rxtx |= UDC_EPN_RX_DB;
@@ -2639,7 +2611,7 @@ omap_ep_setup(char *name, u8 addr, u8 type,
 	ep->ep.name = ep->name;
 	ep->ep.name = ep->name;
 	ep->ep.ops = &omap_ep_ops;
 	ep->ep.ops = &omap_ep_ops;
 	ep->ep.maxpacket = ep->maxpacket = maxp;
 	ep->ep.maxpacket = ep->maxpacket = maxp;
-	list_add_tail (&ep->ep.ep_list, &udc->gadget.ep_list);
+	list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
 
 
 	return buf;
 	return buf;
 }
 }
@@ -2647,11 +2619,11 @@ omap_ep_setup(char *name, u8 addr, u8 type,
 static void omap_udc_release(struct device *dev)
 static void omap_udc_release(struct device *dev)
 {
 {
 	complete(udc->done);
 	complete(udc->done);
-	kfree (udc);
+	kfree(udc);
 	udc = NULL;
 	udc = NULL;
 }
 }
 
 
-static int __init
+static int __devinit
 omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
 omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
 {
 {
 	unsigned	tmp, buf;
 	unsigned	tmp, buf;
@@ -2665,13 +2637,13 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
 	omap_writew(0, UDC_TXDMA_CFG);
 	omap_writew(0, UDC_TXDMA_CFG);
 
 
 	/* UDC_PULLUP_EN gates the chip clock */
 	/* UDC_PULLUP_EN gates the chip clock */
-	// OTG_SYSCON_1 |= DEV_IDLE_EN;
+	/* OTG_SYSCON_1 |= DEV_IDLE_EN; */
 
 
 	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
 	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
 	if (!udc)
 	if (!udc)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	spin_lock_init (&udc->lock);
+	spin_lock_init(&udc->lock);
 
 
 	udc->gadget.ops = &omap_gadget_ops;
 	udc->gadget.ops = &omap_gadget_ops;
 	udc->gadget.ep0 = &udc->ep[0].ep;
 	udc->gadget.ep0 = &udc->ep[0].ep;
@@ -2701,13 +2673,13 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
 		omap_writew(0, UDC_EP_TX(tmp));
 		omap_writew(0, UDC_EP_TX(tmp));
 	}
 	}
 
 
-#define OMAP_BULK_EP(name,addr) \
+#define OMAP_BULK_EP(name, addr) \
 	buf = omap_ep_setup(name "-bulk", addr, \
 	buf = omap_ep_setup(name "-bulk", addr, \
 			USB_ENDPOINT_XFER_BULK, buf, 64, 1);
 			USB_ENDPOINT_XFER_BULK, buf, 64, 1);
-#define OMAP_INT_EP(name,addr, maxp) \
+#define OMAP_INT_EP(name, addr, maxp) \
 	buf = omap_ep_setup(name "-int", addr, \
 	buf = omap_ep_setup(name "-int", addr, \
 			USB_ENDPOINT_XFER_INT, buf, maxp, 0);
 			USB_ENDPOINT_XFER_INT, buf, maxp, 0);
-#define OMAP_ISO_EP(name,addr, maxp) \
+#define OMAP_ISO_EP(name, addr, maxp) \
 	buf = omap_ep_setup(name "-iso", addr, \
 	buf = omap_ep_setup(name "-iso", addr, \
 			USB_ENDPOINT_XFER_ISOC, buf, maxp, 1);
 			USB_ENDPOINT_XFER_ISOC, buf, maxp, 1);
 
 
@@ -2788,15 +2760,18 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
 	return 0;
 	return 0;
 }
 }
 
 
-static int __init omap_udc_probe(struct platform_device *pdev)
+static int __devinit omap_udc_probe(struct platform_device *pdev)
 {
 {
 	int			status = -ENODEV;
 	int			status = -ENODEV;
 	int			hmc;
 	int			hmc;
 	struct usb_phy		*xceiv = NULL;
 	struct usb_phy		*xceiv = NULL;
 	const char		*type = NULL;
 	const char		*type = NULL;
 	struct omap_usb_config	*config = pdev->dev.platform_data;
 	struct omap_usb_config	*config = pdev->dev.platform_data;
-	struct clk		*dc_clk;
-	struct clk		*hhc_clk;
+	struct clk		*dc_clk = NULL;
+	struct clk		*hhc_clk = NULL;
+
+	if (cpu_is_omap7xx())
+		use_dma = 0;
 
 
 	/* NOTE:  "knows" the order of the resources! */
 	/* NOTE:  "knows" the order of the resources! */
 	if (!request_mem_region(pdev->resource[0].start,
 	if (!request_mem_region(pdev->resource[0].start,
@@ -2816,16 +2791,6 @@ static int __init omap_udc_probe(struct platform_device *pdev)
 		udelay(100);
 		udelay(100);
 	}
 	}
 
 
-	if (cpu_is_omap24xx()) {
-		dc_clk = clk_get(&pdev->dev, "usb_fck");
-		hhc_clk = clk_get(&pdev->dev, "usb_l4_ick");
-		BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
-		/* can't use omap_udc_enable_clock yet */
-		clk_enable(dc_clk);
-		clk_enable(hhc_clk);
-		udelay(100);
-	}
-
 	if (cpu_is_omap7xx()) {
 	if (cpu_is_omap7xx()) {
 		dc_clk = clk_get(&pdev->dev, "usb_dc_ck");
 		dc_clk = clk_get(&pdev->dev, "usb_dc_ck");
 		hhc_clk = clk_get(&pdev->dev, "l3_ocpi_ck");
 		hhc_clk = clk_get(&pdev->dev, "l3_ocpi_ck");
@@ -2865,8 +2830,8 @@ static int __init omap_udc_probe(struct platform_device *pdev)
 		 * use it.  Except for OTG, we don't _need_ to talk to one;
 		 * use it.  Except for OTG, we don't _need_ to talk to one;
 		 * but not having one probably means no VBUS detection.
 		 * but not having one probably means no VBUS detection.
 		 */
 		 */
-		xceiv = usb_get_transceiver();
-		if (xceiv)
+		xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+		if (!IS_ERR_OR_NULL(xceiv))
 			type = xceiv->label;
 			type = xceiv->label;
 		else if (config->otg) {
 		else if (config->otg) {
 			DBG("OTG requires external transceiver!\n");
 			DBG("OTG requires external transceiver!\n");
@@ -2875,14 +2840,6 @@ static int __init omap_udc_probe(struct platform_device *pdev)
 
 
 		hmc = HMC_1610;
 		hmc = HMC_1610;
 
 
-		if (cpu_is_omap24xx()) {
-			/* this could be transceiverless in one of the
-			 * "we don't need to know" modes.
-			 */
-			type = "external";
-			goto known;
-		}
-
 		switch (hmc) {
 		switch (hmc) {
 		case 0:			/* POWERUP DEFAULT == 0 */
 		case 0:			/* POWERUP DEFAULT == 0 */
 		case 4:
 		case 4:
@@ -2898,7 +2855,7 @@ static int __init omap_udc_probe(struct platform_device *pdev)
 		case 16:
 		case 16:
 		case 19:
 		case 19:
 		case 25:
 		case 25:
-			if (!xceiv) {
+			if (IS_ERR_OR_NULL(xceiv)) {
 				DBG("external transceiver not registered!\n");
 				DBG("external transceiver not registered!\n");
 				type = "unknown";
 				type = "unknown";
 			}
 			}
@@ -2921,16 +2878,16 @@ bad_on_1710:
 			goto cleanup0;
 			goto cleanup0;
 		}
 		}
 	}
 	}
-known:
+
 	INFO("hmc mode %d, %s transceiver\n", hmc, type);
 	INFO("hmc mode %d, %s transceiver\n", hmc, type);
 
 
 	/* a "gadget" abstracts/virtualizes the controller */
 	/* a "gadget" abstracts/virtualizes the controller */
 	status = omap_udc_setup(pdev, xceiv);
 	status = omap_udc_setup(pdev, xceiv);
-	if (status) {
+	if (status)
 		goto cleanup0;
 		goto cleanup0;
-	}
+
 	xceiv = NULL;
 	xceiv = NULL;
-	// "udc" is now valid
+	/* "udc" is now valid */
 	pullup_disable(udc);
 	pullup_disable(udc);
 #if	defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
 #if	defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
 	udc->gadget.is_otg = (config->otg != 0);
 	udc->gadget.is_otg = (config->otg != 0);
@@ -2944,7 +2901,7 @@ known:
 
 
 	/* USB general purpose IRQ:  ep0, state changes, dma, etc */
 	/* USB general purpose IRQ:  ep0, state changes, dma, etc */
 	status = request_irq(pdev->resource[1].start, omap_udc_irq,
 	status = request_irq(pdev->resource[1].start, omap_udc_irq,
-			IRQF_SAMPLE_RANDOM, driver_name, udc);
+			0, driver_name, udc);
 	if (status != 0) {
 	if (status != 0) {
 		ERR("can't get irq %d, err %d\n",
 		ERR("can't get irq %d, err %d\n",
 			(int) pdev->resource[1].start, status);
 			(int) pdev->resource[1].start, status);
@@ -2953,7 +2910,7 @@ known:
 
 
 	/* USB "non-iso" IRQ (PIO for all but ep0) */
 	/* USB "non-iso" IRQ (PIO for all but ep0) */
 	status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
 	status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
-			IRQF_SAMPLE_RANDOM, "omap_udc pio", udc);
+			0, "omap_udc pio", udc);
 	if (status != 0) {
 	if (status != 0) {
 		ERR("can't get irq %d, err %d\n",
 		ERR("can't get irq %d, err %d\n",
 			(int) pdev->resource[2].start, status);
 			(int) pdev->resource[2].start, status);
@@ -2975,16 +2932,6 @@ known:
 		clk_disable(dc_clk);
 		clk_disable(dc_clk);
 	}
 	}
 
 
-	if (cpu_is_omap24xx()) {
-		udc->dc_clk = dc_clk;
-		udc->hhc_clk = hhc_clk;
-		/* FIXME OMAP2 don't release hhc & dc clock */
-#if 0
-		clk_disable(hhc_clk);
-		clk_disable(dc_clk);
-#endif
-	}
-
 	create_proc_file();
 	create_proc_file();
 	status = device_add(&udc->gadget.dev);
 	status = device_add(&udc->gadget.dev);
 	if (status)
 	if (status)
@@ -3006,14 +2953,14 @@ cleanup2:
 	free_irq(pdev->resource[1].start, udc);
 	free_irq(pdev->resource[1].start, udc);
 
 
 cleanup1:
 cleanup1:
-	kfree (udc);
+	kfree(udc);
 	udc = NULL;
 	udc = NULL;
 
 
 cleanup0:
 cleanup0:
-	if (xceiv)
-		usb_put_transceiver(xceiv);
+	if (!IS_ERR_OR_NULL(xceiv))
+		usb_put_phy(xceiv);
 
 
-	if (cpu_is_omap16xx() || cpu_is_omap24xx() || cpu_is_omap7xx()) {
+	if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
 		clk_disable(hhc_clk);
 		clk_disable(hhc_clk);
 		clk_disable(dc_clk);
 		clk_disable(dc_clk);
 		clk_put(hhc_clk);
 		clk_put(hhc_clk);
@@ -3026,7 +2973,7 @@ cleanup0:
 	return status;
 	return status;
 }
 }
 
 
-static int __exit omap_udc_remove(struct platform_device *pdev)
+static int __devexit omap_udc_remove(struct platform_device *pdev)
 {
 {
 	DECLARE_COMPLETION_ONSTACK(done);
 	DECLARE_COMPLETION_ONSTACK(done);
 
 
@@ -3040,8 +2987,8 @@ static int __exit omap_udc_remove(struct platform_device *pdev)
 	udc->done = &done;
 	udc->done = &done;
 
 
 	pullup_disable(udc);
 	pullup_disable(udc);
-	if (udc->transceiver) {
-		usb_put_transceiver(udc->transceiver);
+	if (!IS_ERR_OR_NULL(udc->transceiver)) {
+		usb_put_phy(udc->transceiver);
 		udc->transceiver = NULL;
 		udc->transceiver = NULL;
 	}
 	}
 	omap_writew(0, UDC_SYSCON1);
 	omap_writew(0, UDC_SYSCON1);
@@ -3111,7 +3058,8 @@ static int omap_udc_resume(struct platform_device *dev)
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
 static struct platform_driver udc_driver = {
 static struct platform_driver udc_driver = {
-	.remove		= __exit_p(omap_udc_remove),
+	.probe		= omap_udc_probe,
+	.remove		= __devexit_p(omap_udc_remove),
 	.suspend	= omap_udc_suspend,
 	.suspend	= omap_udc_suspend,
 	.resume		= omap_udc_resume,
 	.resume		= omap_udc_resume,
 	.driver		= {
 	.driver		= {
@@ -3120,27 +3068,7 @@ static struct platform_driver udc_driver = {
 	},
 	},
 };
 };
 
 
-static int __init udc_init(void)
-{
-	/* Disable DMA for omap7xx -- it doesn't work right. */
-	if (cpu_is_omap7xx())
-		use_dma = 0;
-
-	INFO("%s, version: " DRIVER_VERSION
-#ifdef	USE_ISO
-		" (iso)"
-#endif
-		"%s\n", driver_desc,
-		use_dma ?  " (dma)" : "");
-	return platform_driver_probe(&udc_driver, omap_udc_probe);
-}
-module_init(udc_init);
-
-static void __exit udc_exit(void)
-{
-	platform_driver_unregister(&udc_driver);
-}
-module_exit(udc_exit);
+module_platform_driver(udc_driver);
 
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 1 - 1
drivers/usb/gadget/pch_udc.c

@@ -2208,7 +2208,7 @@ static void pch_udc_complete_receiver(struct pch_udc_ep *ep)
 			return;
 			return;
 		}
 		}
 		if ((td->status & PCH_UDC_BUFF_STS) == PCH_UDC_BS_DMA_DONE)
 		if ((td->status & PCH_UDC_BUFF_STS) == PCH_UDC_BS_DMA_DONE)
-			if (td->status | PCH_UDC_DMA_LAST) {
+			if (td->status & PCH_UDC_DMA_LAST) {
 				count = td->status & PCH_UDC_RXTX_BYTES;
 				count = td->status & PCH_UDC_RXTX_BYTES;
 				break;
 				break;
 			}
 			}

+ 9 - 8
drivers/usb/gadget/pxa25x_udc.c

@@ -21,6 +21,7 @@
 #include <linux/ioport.h>
 #include <linux/ioport.h>
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
+#include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/init.h>
@@ -993,7 +994,7 @@ static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
 
 
 	udc = container_of(_gadget, struct pxa25x_udc, gadget);
 	udc = container_of(_gadget, struct pxa25x_udc, gadget);
 
 
-	if (udc->transceiver)
+	if (!IS_ERR_OR_NULL(udc->transceiver))
 		return usb_phy_set_power(udc->transceiver, mA);
 		return usb_phy_set_power(udc->transceiver, mA);
 	return -EOPNOTSUPP;
 	return -EOPNOTSUPP;
 }
 }
@@ -1299,7 +1300,7 @@ fail:
 	DMSG("registered gadget driver '%s'\n", driver->driver.name);
 	DMSG("registered gadget driver '%s'\n", driver->driver.name);
 
 
 	/* connect to bus through transceiver */
 	/* connect to bus through transceiver */
-	if (dev->transceiver) {
+	if (!IS_ERR_OR_NULL(dev->transceiver)) {
 		retval = otg_set_peripheral(dev->transceiver->otg,
 		retval = otg_set_peripheral(dev->transceiver->otg,
 						&dev->gadget);
 						&dev->gadget);
 		if (retval) {
 		if (retval) {
@@ -1359,7 +1360,7 @@ static int pxa25x_stop(struct usb_gadget_driver *driver)
 	stop_activity(dev, driver);
 	stop_activity(dev, driver);
 	local_irq_enable();
 	local_irq_enable();
 
 
-	if (dev->transceiver)
+	if (!IS_ERR_OR_NULL(dev->transceiver))
 		(void) otg_set_peripheral(dev->transceiver->otg, NULL);
 		(void) otg_set_peripheral(dev->transceiver->otg, NULL);
 
 
 	driver->unbind(&dev->gadget);
 	driver->unbind(&dev->gadget);
@@ -2159,7 +2160,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
 	dev->dev = &pdev->dev;
 	dev->dev = &pdev->dev;
 	dev->mach = pdev->dev.platform_data;
 	dev->mach = pdev->dev.platform_data;
 
 
-	dev->transceiver = usb_get_transceiver();
+	dev->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 
 
 	if (gpio_is_valid(dev->mach->gpio_pullup)) {
 	if (gpio_is_valid(dev->mach->gpio_pullup)) {
 		if ((retval = gpio_request(dev->mach->gpio_pullup,
 		if ((retval = gpio_request(dev->mach->gpio_pullup,
@@ -2237,8 +2238,8 @@ lubbock_fail0:
 	if (gpio_is_valid(dev->mach->gpio_pullup))
 	if (gpio_is_valid(dev->mach->gpio_pullup))
 		gpio_free(dev->mach->gpio_pullup);
 		gpio_free(dev->mach->gpio_pullup);
  err_gpio_pullup:
  err_gpio_pullup:
-	if (dev->transceiver) {
-		usb_put_transceiver(dev->transceiver);
+	if (!IS_ERR_OR_NULL(dev->transceiver)) {
+		usb_put_phy(dev->transceiver);
 		dev->transceiver = NULL;
 		dev->transceiver = NULL;
 	}
 	}
 	clk_put(dev->clk);
 	clk_put(dev->clk);
@@ -2279,8 +2280,8 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
 
 
 	clk_put(dev->clk);
 	clk_put(dev->clk);
 
 
-	if (dev->transceiver) {
-		usb_put_transceiver(dev->transceiver);
+	if (!IS_ERR_OR_NULL(dev->transceiver)) {
+		usb_put_phy(dev->transceiver);
 		dev->transceiver = NULL;
 		dev->transceiver = NULL;
 	}
 	}
 
 

+ 8 - 7
drivers/usb/gadget/pxa27x_udc.c

@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
+#include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/list.h>
@@ -1573,7 +1574,7 @@ static int should_enable_udc(struct pxa_udc *udc)
 	int put_on;
 	int put_on;
 
 
 	put_on = ((udc->pullup_on) && (udc->driver));
 	put_on = ((udc->pullup_on) && (udc->driver));
-	put_on &= ((udc->vbus_sensed) || (!udc->transceiver));
+	put_on &= ((udc->vbus_sensed) || (IS_ERR_OR_NULL(udc->transceiver)));
 	return put_on;
 	return put_on;
 }
 }
 
 
@@ -1594,7 +1595,7 @@ static int should_disable_udc(struct pxa_udc *udc)
 	int put_off;
 	int put_off;
 
 
 	put_off = ((!udc->pullup_on) || (!udc->driver));
 	put_off = ((!udc->pullup_on) || (!udc->driver));
-	put_off |= ((!udc->vbus_sensed) && (udc->transceiver));
+	put_off |= ((!udc->vbus_sensed) && (!IS_ERR_OR_NULL(udc->transceiver)));
 	return put_off;
 	return put_off;
 }
 }
 
 
@@ -1665,7 +1666,7 @@ static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
 	struct pxa_udc *udc;
 	struct pxa_udc *udc;
 
 
 	udc = to_gadget_udc(_gadget);
 	udc = to_gadget_udc(_gadget);
-	if (udc->transceiver)
+	if (!IS_ERR_OR_NULL(udc->transceiver))
 		return usb_phy_set_power(udc->transceiver, mA);
 		return usb_phy_set_power(udc->transceiver, mA);
 	return -EOPNOTSUPP;
 	return -EOPNOTSUPP;
 }
 }
@@ -1834,7 +1835,7 @@ static int pxa27x_udc_start(struct usb_gadget_driver *driver,
 	dev_dbg(udc->dev, "registered gadget driver '%s'\n",
 	dev_dbg(udc->dev, "registered gadget driver '%s'\n",
 		driver->driver.name);
 		driver->driver.name);
 
 
-	if (udc->transceiver) {
+	if (!IS_ERR_OR_NULL(udc->transceiver)) {
 		retval = otg_set_peripheral(udc->transceiver->otg,
 		retval = otg_set_peripheral(udc->transceiver->otg,
 						&udc->gadget);
 						&udc->gadget);
 		if (retval) {
 		if (retval) {
@@ -1908,7 +1909,7 @@ static int pxa27x_udc_stop(struct usb_gadget_driver *driver)
 	dev_info(udc->dev, "unregistered gadget driver '%s'\n",
 	dev_info(udc->dev, "unregistered gadget driver '%s'\n",
 		 driver->driver.name);
 		 driver->driver.name);
 
 
-	if (udc->transceiver)
+	if (!IS_ERR_OR_NULL(udc->transceiver))
 		return otg_set_peripheral(udc->transceiver->otg, NULL);
 		return otg_set_peripheral(udc->transceiver->otg, NULL);
 	return 0;
 	return 0;
 }
 }
@@ -2464,7 +2465,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
 
 
 	udc->dev = &pdev->dev;
 	udc->dev = &pdev->dev;
 	udc->mach = pdev->dev.platform_data;
 	udc->mach = pdev->dev.platform_data;
-	udc->transceiver = usb_get_transceiver();
+	udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 
 
 	gpio = udc->mach->gpio_pullup;
 	gpio = udc->mach->gpio_pullup;
 	if (gpio_is_valid(gpio)) {
 	if (gpio_is_valid(gpio)) {
@@ -2543,7 +2544,7 @@ static int __exit pxa_udc_remove(struct platform_device *_dev)
 	if (gpio_is_valid(gpio))
 	if (gpio_is_valid(gpio))
 		gpio_free(gpio);
 		gpio_free(gpio);
 
 
-	usb_put_transceiver(udc->transceiver);
+	usb_put_phy(udc->transceiver);
 
 
 	udc->transceiver = NULL;
 	udc->transceiver = NULL;
 	platform_set_drvdata(_dev, NULL);
 	platform_set_drvdata(_dev, NULL);

+ 110 - 105
drivers/usb/gadget/s3c-hsotg.c

@@ -112,7 +112,6 @@ struct s3c_hsotg_ep {
 	struct s3c_hsotg_req	*req;
 	struct s3c_hsotg_req	*req;
 	struct dentry		*debugfs;
 	struct dentry		*debugfs;
 
 
-	spinlock_t		lock;
 
 
 	unsigned long		total_data;
 	unsigned long		total_data;
 	unsigned int		size_loaded;
 	unsigned int		size_loaded;
@@ -136,7 +135,6 @@ struct s3c_hsotg_ep {
  * @driver: USB gadget driver
  * @driver: USB gadget driver
  * @plat: The platform specific configuration data.
  * @plat: The platform specific configuration data.
  * @regs: The memory area mapped for accessing registers.
  * @regs: The memory area mapped for accessing registers.
- * @regs_res: The resource that was allocated when claiming register space.
  * @irq: The IRQ number we are using
  * @irq: The IRQ number we are using
  * @supplies: Definition of USB power supplies
  * @supplies: Definition of USB power supplies
  * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
  * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
@@ -157,8 +155,9 @@ struct s3c_hsotg {
 	struct usb_gadget_driver *driver;
 	struct usb_gadget_driver *driver;
 	struct s3c_hsotg_plat	 *plat;
 	struct s3c_hsotg_plat	 *plat;
 
 
+	spinlock_t              lock;
+
 	void __iomem		*regs;
 	void __iomem		*regs;
-	struct resource		*regs_res;
 	int			irq;
 	int			irq;
 	struct clk		*clk;
 	struct clk		*clk;
 
 
@@ -896,7 +895,6 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
 	struct s3c_hsotg_req *hs_req = our_req(req);
 	struct s3c_hsotg_req *hs_req = our_req(req);
 	struct s3c_hsotg_ep *hs_ep = our_ep(ep);
 	struct s3c_hsotg_ep *hs_ep = our_ep(ep);
 	struct s3c_hsotg *hs = hs_ep->parent;
 	struct s3c_hsotg *hs = hs_ep->parent;
-	unsigned long irqflags;
 	bool first;
 	bool first;
 
 
 	dev_dbg(hs->dev, "%s: req %p: %d@%p, noi=%d, zero=%d, snok=%d\n",
 	dev_dbg(hs->dev, "%s: req %p: %d@%p, noi=%d, zero=%d, snok=%d\n",
@@ -915,19 +913,30 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
 			return ret;
 			return ret;
 	}
 	}
 
 
-	spin_lock_irqsave(&hs_ep->lock, irqflags);
-
 	first = list_empty(&hs_ep->queue);
 	first = list_empty(&hs_ep->queue);
 	list_add_tail(&hs_req->queue, &hs_ep->queue);
 	list_add_tail(&hs_req->queue, &hs_ep->queue);
 
 
 	if (first)
 	if (first)
 		s3c_hsotg_start_req(hs, hs_ep, hs_req, false);
 		s3c_hsotg_start_req(hs, hs_ep, hs_req, false);
 
 
-	spin_unlock_irqrestore(&hs_ep->lock, irqflags);
-
 	return 0;
 	return 0;
 }
 }
 
 
+static int s3c_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req,
+			      gfp_t gfp_flags)
+{
+	struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+	struct s3c_hsotg *hs = hs_ep->parent;
+	unsigned long flags = 0;
+	int ret = 0;
+
+	spin_lock_irqsave(&hs->lock, flags);
+	ret = s3c_hsotg_ep_queue(ep, req, gfp_flags);
+	spin_unlock_irqrestore(&hs->lock, flags);
+
+	return ret;
+}
+
 static void s3c_hsotg_ep_free_request(struct usb_ep *ep,
 static void s3c_hsotg_ep_free_request(struct usb_ep *ep,
 				      struct usb_request *req)
 				      struct usb_request *req)
 {
 {
@@ -1383,9 +1392,9 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
 	 */
 	 */
 
 
 	if (hs_req->req.complete) {
 	if (hs_req->req.complete) {
-		spin_unlock(&hs_ep->lock);
+		spin_unlock(&hsotg->lock);
 		hs_req->req.complete(&hs_ep->ep, &hs_req->req);
 		hs_req->req.complete(&hs_ep->ep, &hs_req->req);
-		spin_lock(&hs_ep->lock);
+		spin_lock(&hsotg->lock);
 	}
 	}
 
 
 	/*
 	/*
@@ -1403,28 +1412,6 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
 	}
 	}
 }
 }
 
 
-/**
- * s3c_hsotg_complete_request_lock - complete a request given to us (locked)
- * @hsotg: The device state.
- * @hs_ep: The endpoint the request was on.
- * @hs_req: The request to complete.
- * @result: The result code (0 => Ok, otherwise errno)
- *
- * See s3c_hsotg_complete_request(), but called with the endpoint's
- * lock held.
- */
-static void s3c_hsotg_complete_request_lock(struct s3c_hsotg *hsotg,
-					    struct s3c_hsotg_ep *hs_ep,
-					    struct s3c_hsotg_req *hs_req,
-					    int result)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&hs_ep->lock, flags);
-	s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result);
-	spin_unlock_irqrestore(&hs_ep->lock, flags);
-}
-
 /**
 /**
  * s3c_hsotg_rx_data - receive data from the FIFO for an endpoint
  * s3c_hsotg_rx_data - receive data from the FIFO for an endpoint
  * @hsotg: The device state.
  * @hsotg: The device state.
@@ -1444,6 +1431,7 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
 	int max_req;
 	int max_req;
 	int read_ptr;
 	int read_ptr;
 
 
+
 	if (!hs_req) {
 	if (!hs_req) {
 		u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx));
 		u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx));
 		int ptr;
 		int ptr;
@@ -1459,8 +1447,6 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
 		return;
 		return;
 	}
 	}
 
 
-	spin_lock(&hs_ep->lock);
-
 	to_read = size;
 	to_read = size;
 	read_ptr = hs_req->req.actual;
 	read_ptr = hs_req->req.actual;
 	max_req = hs_req->req.length - read_ptr;
 	max_req = hs_req->req.length - read_ptr;
@@ -1487,8 +1473,6 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
 	 * alignment of the data.
 	 * alignment of the data.
 	 */
 	 */
 	readsl(fifo, hs_req->req.buf + read_ptr, to_read);
 	readsl(fifo, hs_req->req.buf + read_ptr, to_read);
-
-	spin_unlock(&hs_ep->lock);
 }
 }
 
 
 /**
 /**
@@ -1609,7 +1593,7 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
 			s3c_hsotg_send_zlp(hsotg, hs_req);
 			s3c_hsotg_send_zlp(hsotg, hs_req);
 	}
 	}
 
 
-	s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, result);
+	s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result);
 }
 }
 
 
 /**
 /**
@@ -1864,7 +1848,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
 	/* Finish ZLP handling for IN EP0 transactions */
 	/* Finish ZLP handling for IN EP0 transactions */
 	if (hsotg->eps[0].sent_zlp) {
 	if (hsotg->eps[0].sent_zlp) {
 		dev_dbg(hsotg->dev, "zlp packet received\n");
 		dev_dbg(hsotg->dev, "zlp packet received\n");
-		s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0);
+		s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
 		return;
 		return;
 	}
 	}
 
 
@@ -1915,7 +1899,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
 		dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__);
 		dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__);
 		s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true);
 		s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true);
 	} else
 	} else
-		s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0);
+		s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
 }
 }
 
 
 /**
 /**
@@ -2123,9 +2107,6 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
 			      int result, bool force)
 			      int result, bool force)
 {
 {
 	struct s3c_hsotg_req *req, *treq;
 	struct s3c_hsotg_req *req, *treq;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ep->lock, flags);
 
 
 	list_for_each_entry_safe(req, treq, &ep->queue, queue) {
 	list_for_each_entry_safe(req, treq, &ep->queue, queue) {
 		/*
 		/*
@@ -2139,14 +2120,15 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
 		s3c_hsotg_complete_request(hsotg, ep, req,
 		s3c_hsotg_complete_request(hsotg, ep, req,
 					   result);
 					   result);
 	}
 	}
-
-	spin_unlock_irqrestore(&ep->lock, flags);
 }
 }
 
 
 #define call_gadget(_hs, _entry) \
 #define call_gadget(_hs, _entry) \
 	if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN &&	\
 	if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN &&	\
-	    (_hs)->driver && (_hs)->driver->_entry)	\
-		(_hs)->driver->_entry(&(_hs)->gadget);
+	    (_hs)->driver && (_hs)->driver->_entry) { \
+		spin_unlock(&_hs->lock); \
+		(_hs)->driver->_entry(&(_hs)->gadget); \
+		spin_lock(&_hs->lock); \
+		}
 
 
 /**
 /**
  * s3c_hsotg_disconnect - disconnect service
  * s3c_hsotg_disconnect - disconnect service
@@ -2388,6 +2370,7 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
 	u32 gintsts;
 	u32 gintsts;
 	u32 gintmsk;
 	u32 gintmsk;
 
 
+	spin_lock(&hsotg->lock);
 irq_retry:
 irq_retry:
 	gintsts = readl(hsotg->regs + GINTSTS);
 	gintsts = readl(hsotg->regs + GINTSTS);
 	gintmsk = readl(hsotg->regs + GINTMSK);
 	gintmsk = readl(hsotg->regs + GINTMSK);
@@ -2557,6 +2540,8 @@ irq_retry:
 	if (gintsts & IRQ_RETRY_MASK && --retry_count > 0)
 	if (gintsts & IRQ_RETRY_MASK && --retry_count > 0)
 			goto irq_retry;
 			goto irq_retry;
 
 
+	spin_unlock(&hsotg->lock);
+
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
@@ -2604,7 +2589,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
 	dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n",
 	dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n",
 		__func__, epctrl, epctrl_reg);
 		__func__, epctrl, epctrl_reg);
 
 
-	spin_lock_irqsave(&hs_ep->lock, flags);
+	spin_lock_irqsave(&hsotg->lock, flags);
 
 
 	epctrl &= ~(DxEPCTL_EPType_MASK | DxEPCTL_MPS_MASK);
 	epctrl &= ~(DxEPCTL_EPType_MASK | DxEPCTL_MPS_MASK);
 	epctrl |= DxEPCTL_MPS(mps);
 	epctrl |= DxEPCTL_MPS(mps);
@@ -2683,7 +2668,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
 	s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1);
 	s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1);
 
 
 out:
 out:
-	spin_unlock_irqrestore(&hs_ep->lock, flags);
+	spin_unlock_irqrestore(&hsotg->lock, flags);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -2710,10 +2695,10 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
 
 
 	epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
 	epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
 
 
+	spin_lock_irqsave(&hsotg->lock, flags);
 	/* terminate all requests with shutdown */
 	/* terminate all requests with shutdown */
 	kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false);
 	kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false);
 
 
-	spin_lock_irqsave(&hs_ep->lock, flags);
 
 
 	ctrl = readl(hsotg->regs + epctrl_reg);
 	ctrl = readl(hsotg->regs + epctrl_reg);
 	ctrl &= ~DxEPCTL_EPEna;
 	ctrl &= ~DxEPCTL_EPEna;
@@ -2726,7 +2711,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
 	/* disable endpoint interrupts */
 	/* disable endpoint interrupts */
 	s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0);
 	s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0);
 
 
-	spin_unlock_irqrestore(&hs_ep->lock, flags);
+	spin_unlock_irqrestore(&hsotg->lock, flags);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -2761,15 +2746,15 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
 
 
 	dev_info(hs->dev, "ep_dequeue(%p,%p)\n", ep, req);
 	dev_info(hs->dev, "ep_dequeue(%p,%p)\n", ep, req);
 
 
-	spin_lock_irqsave(&hs_ep->lock, flags);
+	spin_lock_irqsave(&hs->lock, flags);
 
 
 	if (!on_list(hs_ep, hs_req)) {
 	if (!on_list(hs_ep, hs_req)) {
-		spin_unlock_irqrestore(&hs_ep->lock, flags);
+		spin_unlock_irqrestore(&hs->lock, flags);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
 	s3c_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET);
 	s3c_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET);
-	spin_unlock_irqrestore(&hs_ep->lock, flags);
+	spin_unlock_irqrestore(&hs->lock, flags);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -2784,15 +2769,12 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
 	struct s3c_hsotg_ep *hs_ep = our_ep(ep);
 	struct s3c_hsotg_ep *hs_ep = our_ep(ep);
 	struct s3c_hsotg *hs = hs_ep->parent;
 	struct s3c_hsotg *hs = hs_ep->parent;
 	int index = hs_ep->index;
 	int index = hs_ep->index;
-	unsigned long irqflags;
 	u32 epreg;
 	u32 epreg;
 	u32 epctl;
 	u32 epctl;
 	u32 xfertype;
 	u32 xfertype;
 
 
 	dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value);
 	dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value);
 
 
-	spin_lock_irqsave(&hs_ep->lock, irqflags);
-
 	/* write both IN and OUT control registers */
 	/* write both IN and OUT control registers */
 
 
 	epreg = DIEPCTL(index);
 	epreg = DIEPCTL(index);
@@ -2827,19 +2809,36 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
 
 
 	writel(epctl, hs->regs + epreg);
 	writel(epctl, hs->regs + epreg);
 
 
-	spin_unlock_irqrestore(&hs_ep->lock, irqflags);
-
 	return 0;
 	return 0;
 }
 }
 
 
+/**
+ * s3c_hsotg_ep_sethalt_lock - set halt on a given endpoint with lock held
+ * @ep: The endpoint to set halt.
+ * @value: Set or unset the halt.
+ */
+static int s3c_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value)
+{
+	struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+	struct s3c_hsotg *hs = hs_ep->parent;
+	unsigned long flags = 0;
+	int ret = 0;
+
+	spin_lock_irqsave(&hs->lock, flags);
+	ret = s3c_hsotg_ep_sethalt(ep, value);
+	spin_unlock_irqrestore(&hs->lock, flags);
+
+	return ret;
+}
+
 static struct usb_ep_ops s3c_hsotg_ep_ops = {
 static struct usb_ep_ops s3c_hsotg_ep_ops = {
 	.enable		= s3c_hsotg_ep_enable,
 	.enable		= s3c_hsotg_ep_enable,
 	.disable	= s3c_hsotg_ep_disable,
 	.disable	= s3c_hsotg_ep_disable,
 	.alloc_request	= s3c_hsotg_ep_alloc_request,
 	.alloc_request	= s3c_hsotg_ep_alloc_request,
 	.free_request	= s3c_hsotg_ep_free_request,
 	.free_request	= s3c_hsotg_ep_free_request,
-	.queue		= s3c_hsotg_ep_queue,
+	.queue		= s3c_hsotg_ep_queue_lock,
 	.dequeue	= s3c_hsotg_ep_dequeue,
 	.dequeue	= s3c_hsotg_ep_dequeue,
-	.set_halt	= s3c_hsotg_ep_sethalt,
+	.set_halt	= s3c_hsotg_ep_sethalt_lock,
 	/* note, don't believe we have any call for the fifo routines */
 	/* note, don't believe we have any call for the fifo routines */
 };
 };
 
 
@@ -2954,6 +2953,7 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	hsotg->driver = driver;
 	hsotg->driver = driver;
 	hsotg->gadget.dev.driver = &driver->driver;
 	hsotg->gadget.dev.driver = &driver->driver;
+	hsotg->gadget.dev.of_node = hsotg->dev->of_node;
 	hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask;
 	hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask;
 	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 
 
@@ -2964,9 +2964,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
 		goto err;
 		goto err;
 	}
 	}
 
 
-	s3c_hsotg_phy_enable(hsotg);
-
-	s3c_hsotg_core_init(hsotg);
 	hsotg->last_rst = jiffies;
 	hsotg->last_rst = jiffies;
 	dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
 	dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
 	return 0;
 	return 0;
@@ -2988,6 +2985,7 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
 			  struct usb_gadget_driver *driver)
 			  struct usb_gadget_driver *driver)
 {
 {
 	struct s3c_hsotg *hsotg = to_hsotg(gadget);
 	struct s3c_hsotg *hsotg = to_hsotg(gadget);
+	unsigned long flags = 0;
 	int ep;
 	int ep;
 
 
 	if (!hsotg)
 	if (!hsotg)
@@ -3000,6 +2998,8 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
 	for (ep = 0; ep < hsotg->num_of_eps; ep++)
 	for (ep = 0; ep < hsotg->num_of_eps; ep++)
 		s3c_hsotg_ep_disable(&hsotg->eps[ep].ep);
 		s3c_hsotg_ep_disable(&hsotg->eps[ep].ep);
 
 
+	spin_lock_irqsave(&hsotg->lock, flags);
+
 	s3c_hsotg_phy_disable(hsotg);
 	s3c_hsotg_phy_disable(hsotg);
 	regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 	regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 
 
@@ -3007,6 +3007,8 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
 	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 	hsotg->gadget.dev.driver = NULL;
 	hsotg->gadget.dev.driver = NULL;
 
 
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+
 	dev_info(hsotg->dev, "unregistered gadget driver '%s'\n",
 	dev_info(hsotg->dev, "unregistered gadget driver '%s'\n",
 		 driver->driver.name);
 		 driver->driver.name);
 
 
@@ -3024,10 +3026,40 @@ static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget)
 	return s3c_hsotg_read_frameno(to_hsotg(gadget));
 	return s3c_hsotg_read_frameno(to_hsotg(gadget));
 }
 }
 
 
+/**
+ * s3c_hsotg_pullup - connect/disconnect the USB PHY
+ * @gadget: The usb gadget state
+ * @is_on: Current state of the USB PHY
+ *
+ * Connect/Disconnect the USB PHY pullup
+ */
+static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on)
+{
+	struct s3c_hsotg *hsotg = to_hsotg(gadget);
+	unsigned long flags = 0;
+
+	dev_dbg(hsotg->dev, "%s: is_in: %d\n", __func__, is_on);
+
+	spin_lock_irqsave(&hsotg->lock, flags);
+	if (is_on) {
+		s3c_hsotg_phy_enable(hsotg);
+		s3c_hsotg_core_init(hsotg);
+	} else {
+		s3c_hsotg_disconnect(hsotg);
+		s3c_hsotg_phy_disable(hsotg);
+	}
+
+	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+
+	return 0;
+}
+
 static struct usb_gadget_ops s3c_hsotg_gadget_ops = {
 static struct usb_gadget_ops s3c_hsotg_gadget_ops = {
 	.get_frame	= s3c_hsotg_gadget_getframe,
 	.get_frame	= s3c_hsotg_gadget_getframe,
 	.udc_start		= s3c_hsotg_udc_start,
 	.udc_start		= s3c_hsotg_udc_start,
 	.udc_stop		= s3c_hsotg_udc_stop,
 	.udc_stop		= s3c_hsotg_udc_stop,
+	.pullup                 = s3c_hsotg_pullup,
 };
 };
 
 
 /**
 /**
@@ -3063,8 +3095,6 @@ static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg,
 	INIT_LIST_HEAD(&hs_ep->queue);
 	INIT_LIST_HEAD(&hs_ep->queue);
 	INIT_LIST_HEAD(&hs_ep->ep.ep_list);
 	INIT_LIST_HEAD(&hs_ep->ep.ep_list);
 
 
-	spin_lock_init(&hs_ep->lock);
-
 	/* add to the list of endpoints known by the gadget driver */
 	/* add to the list of endpoints known by the gadget driver */
 	if (epnum)
 	if (epnum)
 		list_add_tail(&hs_ep->ep.ep_list, &hsotg->gadget.ep_list);
 		list_add_tail(&hs_ep->ep.ep_list, &hsotg->gadget.ep_list);
@@ -3342,7 +3372,7 @@ static int ep_show(struct seq_file *seq, void *v)
 	seq_printf(seq, "request list (%p,%p):\n",
 	seq_printf(seq, "request list (%p,%p):\n",
 		   ep->queue.next, ep->queue.prev);
 		   ep->queue.next, ep->queue.prev);
 
 
-	spin_lock_irqsave(&ep->lock, flags);
+	spin_lock_irqsave(&hsotg->lock, flags);
 
 
 	list_for_each_entry(req, &ep->queue, queue) {
 	list_for_each_entry(req, &ep->queue, queue) {
 		if (--show_limit < 0) {
 		if (--show_limit < 0) {
@@ -3357,7 +3387,7 @@ static int ep_show(struct seq_file *seq, void *v)
 			   req->req.actual, req->req.status);
 			   req->req.actual, req->req.status);
 	}
 	}
 
 
-	spin_unlock_irqrestore(&ep->lock, flags);
+	spin_unlock_irqrestore(&hsotg->lock, flags);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -3477,7 +3507,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	hsotg = kzalloc(sizeof(struct s3c_hsotg), GFP_KERNEL);
+	hsotg = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsotg), GFP_KERNEL);
 	if (!hsotg) {
 	if (!hsotg) {
 		dev_err(dev, "cannot get memory\n");
 		dev_err(dev, "cannot get memory\n");
 		return -ENOMEM;
 		return -ENOMEM;
@@ -3489,46 +3519,35 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
 	hsotg->clk = clk_get(&pdev->dev, "otg");
 	hsotg->clk = clk_get(&pdev->dev, "otg");
 	if (IS_ERR(hsotg->clk)) {
 	if (IS_ERR(hsotg->clk)) {
 		dev_err(dev, "cannot get otg clock\n");
 		dev_err(dev, "cannot get otg clock\n");
-		ret = PTR_ERR(hsotg->clk);
-		goto err_mem;
+		return PTR_ERR(hsotg->clk);
 	}
 	}
 
 
 	platform_set_drvdata(pdev, hsotg);
 	platform_set_drvdata(pdev, hsotg);
 
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "cannot find register resource 0\n");
-		ret = -EINVAL;
-		goto err_clk;
-	}
-
-	hsotg->regs_res = request_mem_region(res->start, resource_size(res),
-					     dev_name(dev));
-	if (!hsotg->regs_res) {
-		dev_err(dev, "cannot reserve registers\n");
-		ret = -ENOENT;
-		goto err_clk;
-	}
 
 
-	hsotg->regs = ioremap(res->start, resource_size(res));
+	hsotg->regs = devm_request_and_ioremap(&pdev->dev, res);
 	if (!hsotg->regs) {
 	if (!hsotg->regs) {
 		dev_err(dev, "cannot map registers\n");
 		dev_err(dev, "cannot map registers\n");
 		ret = -ENXIO;
 		ret = -ENXIO;
-		goto err_regs_res;
+		goto err_clk;
 	}
 	}
 
 
 	ret = platform_get_irq(pdev, 0);
 	ret = platform_get_irq(pdev, 0);
 	if (ret < 0) {
 	if (ret < 0) {
 		dev_err(dev, "cannot find IRQ\n");
 		dev_err(dev, "cannot find IRQ\n");
-		goto err_regs;
+		goto err_clk;
 	}
 	}
 
 
+	spin_lock_init(&hsotg->lock);
+
 	hsotg->irq = ret;
 	hsotg->irq = ret;
 
 
-	ret = request_irq(ret, s3c_hsotg_irq, 0, dev_name(dev), hsotg);
+	ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0,
+				dev_name(dev), hsotg);
 	if (ret < 0) {
 	if (ret < 0) {
 		dev_err(dev, "cannot claim IRQ\n");
 		dev_err(dev, "cannot claim IRQ\n");
-		goto err_regs;
+		goto err_clk;
 	}
 	}
 
 
 	dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
 	dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
@@ -3558,7 +3577,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
 				 hsotg->supplies);
 				 hsotg->supplies);
 	if (ret) {
 	if (ret) {
 		dev_err(dev, "failed to request supplies: %d\n", ret);
 		dev_err(dev, "failed to request supplies: %d\n", ret);
-		goto err_irq;
+		goto err_clk;
 	}
 	}
 
 
 	ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
 	ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
@@ -3642,19 +3661,11 @@ err_ep_mem:
 err_supplies:
 err_supplies:
 	s3c_hsotg_phy_disable(hsotg);
 	s3c_hsotg_phy_disable(hsotg);
 	regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 	regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
-err_irq:
-	free_irq(hsotg->irq, hsotg);
-err_regs:
-	iounmap(hsotg->regs);
-
-err_regs_res:
-	release_resource(hsotg->regs_res);
-	kfree(hsotg->regs_res);
+
 err_clk:
 err_clk:
 	clk_disable_unprepare(hsotg->clk);
 	clk_disable_unprepare(hsotg->clk);
 	clk_put(hsotg->clk);
 	clk_put(hsotg->clk);
-err_mem:
-	kfree(hsotg);
+
 	return ret;
 	return ret;
 }
 }
 
 
@@ -3675,12 +3686,6 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
 		usb_gadget_unregister_driver(hsotg->driver);
 		usb_gadget_unregister_driver(hsotg->driver);
 	}
 	}
 
 
-	free_irq(hsotg->irq, hsotg);
-	iounmap(hsotg->regs);
-
-	release_resource(hsotg->regs_res);
-	kfree(hsotg->regs_res);
-
 	s3c_hsotg_phy_disable(hsotg);
 	s3c_hsotg_phy_disable(hsotg);
 	regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 	regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 
 

+ 7 - 6
drivers/usb/gadget/s3c-hsudc.c

@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
+#include <linux/err.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/otg.h>
@@ -1165,7 +1166,7 @@ static int s3c_hsudc_start(struct usb_gadget *gadget,
 	}
 	}
 
 
 	/* connect to bus through transceiver */
 	/* connect to bus through transceiver */
-	if (hsudc->transceiver) {
+	if (!IS_ERR_OR_NULL(hsudc->transceiver)) {
 		ret = otg_set_peripheral(hsudc->transceiver->otg,
 		ret = otg_set_peripheral(hsudc->transceiver->otg,
 					&hsudc->gadget);
 					&hsudc->gadget);
 		if (ret) {
 		if (ret) {
@@ -1220,7 +1221,7 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget,
 	s3c_hsudc_stop_activity(hsudc);
 	s3c_hsudc_stop_activity(hsudc);
 	spin_unlock_irqrestore(&hsudc->lock, flags);
 	spin_unlock_irqrestore(&hsudc->lock, flags);
 
 
-	if (hsudc->transceiver)
+	if (!IS_ERR_OR_NULL(hsudc->transceiver))
 		(void) otg_set_peripheral(hsudc->transceiver->otg, NULL);
 		(void) otg_set_peripheral(hsudc->transceiver->otg, NULL);
 
 
 	disable_irq(hsudc->irq);
 	disable_irq(hsudc->irq);
@@ -1249,7 +1250,7 @@ static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 	if (!hsudc)
 	if (!hsudc)
 		return -ENODEV;
 		return -ENODEV;
 
 
-	if (hsudc->transceiver)
+	if (!IS_ERR_OR_NULL(hsudc->transceiver))
 		return usb_phy_set_power(hsudc->transceiver, mA);
 		return usb_phy_set_power(hsudc->transceiver, mA);
 
 
 	return -EOPNOTSUPP;
 	return -EOPNOTSUPP;
@@ -1282,7 +1283,7 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev)
 	hsudc->dev = dev;
 	hsudc->dev = dev;
 	hsudc->pd = pdev->dev.platform_data;
 	hsudc->pd = pdev->dev.platform_data;
 
 
-	hsudc->transceiver = usb_get_transceiver();
+	hsudc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 
 
 	for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++)
 	for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++)
 		hsudc->supplies[i].supply = s3c_hsudc_supply_names[i];
 		hsudc->supplies[i].supply = s3c_hsudc_supply_names[i];
@@ -1385,8 +1386,8 @@ err_irq:
 err_remap:
 err_remap:
 	release_mem_region(res->start, resource_size(res));
 	release_mem_region(res->start, resource_size(res));
 err_res:
 err_res:
-	if (hsudc->transceiver)
-		usb_put_transceiver(hsudc->transceiver);
+	if (!IS_ERR_OR_NULL(hsudc->transceiver))
+		usb_put_phy(hsudc->transceiver);
 
 
 	regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
 	regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
 err_supplies:
 err_supplies:

+ 29 - 34
drivers/usb/gadget/storage_common.c

@@ -37,12 +37,6 @@
  * When FSG_NO_OTG is defined fsg_otg_desc won't be defined.
  * When FSG_NO_OTG is defined fsg_otg_desc won't be defined.
  */
  */
 
 
-/*
- * When FSG_BUFFHD_STATIC_BUFFER is defined when this file is included
- * the fsg_buffhd structure's buf field will be an array of FSG_BUFLEN
- * characters rather then a pointer to void.
- */
-
 /*
 /*
  * When USB_GADGET_DEBUG_FILES is defined the module param num_buffers
  * When USB_GADGET_DEBUG_FILES is defined the module param num_buffers
  * sets the number of pipeline buffers (length of the fsg_buffhd array).
  * sets the number of pipeline buffers (length of the fsg_buffhd array).
@@ -260,11 +254,7 @@ enum fsg_buffer_state {
 };
 };
 
 
 struct fsg_buffhd {
 struct fsg_buffhd {
-#ifdef FSG_BUFFHD_STATIC_BUFFER
-	char				buf[FSG_BUFLEN];
-#else
 	void				*buf;
 	void				*buf;
-#endif
 	enum fsg_buffer_state		state;
 	enum fsg_buffer_state		state;
 	struct fsg_buffhd		*next;
 	struct fsg_buffhd		*next;
 
 
@@ -627,6 +617,16 @@ static struct usb_gadget_strings	fsg_stringtab = {
  * the caller must own fsg->filesem for writing.
  * the caller must own fsg->filesem for writing.
  */
  */
 
 
+static void fsg_lun_close(struct fsg_lun *curlun)
+{
+	if (curlun->filp) {
+		LDBG(curlun, "close backing file\n");
+		fput(curlun->filp);
+		curlun->filp = NULL;
+	}
+}
+
+
 static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
 static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
 {
 {
 	int				ro;
 	int				ro;
@@ -636,6 +636,8 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
 	loff_t				size;
 	loff_t				size;
 	loff_t				num_sectors;
 	loff_t				num_sectors;
 	loff_t				min_sectors;
 	loff_t				min_sectors;
+	unsigned int			blkbits;
+	unsigned int			blksize;
 
 
 	/* R/W if we can, R/O if we must */
 	/* R/W if we can, R/O if we must */
 	ro = curlun->initially_ro;
 	ro = curlun->initially_ro;
@@ -680,17 +682,17 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
 	}
 	}
 
 
 	if (curlun->cdrom) {
 	if (curlun->cdrom) {
-		curlun->blksize = 2048;
-		curlun->blkbits = 11;
+		blksize = 2048;
+		blkbits = 11;
 	} else if (inode->i_bdev) {
 	} else if (inode->i_bdev) {
-		curlun->blksize = bdev_logical_block_size(inode->i_bdev);
-		curlun->blkbits = blksize_bits(curlun->blksize);
+		blksize = bdev_logical_block_size(inode->i_bdev);
+		blkbits = blksize_bits(blksize);
 	} else {
 	} else {
-		curlun->blksize = 512;
-		curlun->blkbits = 9;
+		blksize = 512;
+		blkbits = 9;
 	}
 	}
 
 
-	num_sectors = size >> curlun->blkbits; /* File size in logic-block-size blocks */
+	num_sectors = size >> blkbits; /* File size in logic-block-size blocks */
 	min_sectors = 1;
 	min_sectors = 1;
 	if (curlun->cdrom) {
 	if (curlun->cdrom) {
 		min_sectors = 300;	/* Smallest track is 300 frames */
 		min_sectors = 300;	/* Smallest track is 300 frames */
@@ -707,7 +709,12 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
 		goto out;
 		goto out;
 	}
 	}
 
 
+	if (fsg_lun_is_open(curlun))
+		fsg_lun_close(curlun);
+
 	get_file(filp);
 	get_file(filp);
+	curlun->blksize = blksize;
+	curlun->blkbits = blkbits;
 	curlun->ro = ro;
 	curlun->ro = ro;
 	curlun->filp = filp;
 	curlun->filp = filp;
 	curlun->file_length = size;
 	curlun->file_length = size;
@@ -721,16 +728,6 @@ out:
 }
 }
 
 
 
 
-static void fsg_lun_close(struct fsg_lun *curlun)
-{
-	if (curlun->filp) {
-		LDBG(curlun, "close backing file\n");
-		fput(curlun->filp);
-		curlun->filp = NULL;
-	}
-}
-
-
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
 /*
 /*
@@ -881,19 +878,17 @@ static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr,
 	if (count > 0 && buf[count-1] == '\n')
 	if (count > 0 && buf[count-1] == '\n')
 		((char *) buf)[count-1] = 0;		/* Ugh! */
 		((char *) buf)[count-1] = 0;		/* Ugh! */
 
 
-	/* Eject current medium */
-	down_write(filesem);
-	if (fsg_lun_is_open(curlun)) {
-		fsg_lun_close(curlun);
-		curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
-	}
-
 	/* Load new medium */
 	/* Load new medium */
+	down_write(filesem);
 	if (count > 0 && buf[0]) {
 	if (count > 0 && buf[0]) {
+		/* fsg_lun_open() will close existing file if any. */
 		rc = fsg_lun_open(curlun, buf);
 		rc = fsg_lun_open(curlun, buf);
 		if (rc == 0)
 		if (rc == 0)
 			curlun->unit_attention_data =
 			curlun->unit_attention_data =
 					SS_NOT_READY_TO_READY_TRANSITION;
 					SS_NOT_READY_TO_READY_TRANSITION;
+	} else if (fsg_lun_is_open(curlun)) {
+		fsg_lun_close(curlun);
+		curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
 	}
 	}
 	up_write(filesem);
 	up_write(filesem);
 	return (rc < 0 ? rc : count);
 	return (rc < 0 ? rc : count);

+ 6 - 6
drivers/usb/gadget/u_ether.c

@@ -798,12 +798,6 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 
 
 	SET_ETHTOOL_OPS(net, &ops);
 	SET_ETHTOOL_OPS(net, &ops);
 
 
-	/* two kinds of host-initiated state changes:
-	 *  - iff DATA transfer is active, carrier is "on"
-	 *  - tx queueing enabled if open *and* carrier is "on"
-	 */
-	netif_carrier_off(net);
-
 	dev->gadget = g;
 	dev->gadget = g;
 	SET_NETDEV_DEV(net, &g->dev);
 	SET_NETDEV_DEV(net, &g->dev);
 	SET_NETDEV_DEVTYPE(net, &gadget_type);
 	SET_NETDEV_DEVTYPE(net, &gadget_type);
@@ -817,6 +811,12 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 		INFO(dev, "HOST MAC %pM\n", dev->host_mac);
 		INFO(dev, "HOST MAC %pM\n", dev->host_mac);
 
 
 		the_dev = dev;
 		the_dev = dev;
+
+		/* two kinds of host-initiated state changes:
+		 *  - iff DATA transfer is active, carrier is "on"
+		 *  - tx queueing enabled if open *and* carrier is "on"
+		 */
+		netif_carrier_off(net);
 	}
 	}
 
 
 	return status;
 	return status;

+ 3 - 1
drivers/usb/gadget/uvc.h

@@ -153,9 +153,11 @@ struct uvc_device
 
 
 	/* Descriptors */
 	/* Descriptors */
 	struct {
 	struct {
-		const struct uvc_descriptor_header * const *control;
+		const struct uvc_descriptor_header * const *fs_control;
+		const struct uvc_descriptor_header * const *ss_control;
 		const struct uvc_descriptor_header * const *fs_streaming;
 		const struct uvc_descriptor_header * const *fs_streaming;
 		const struct uvc_descriptor_header * const *hs_streaming;
 		const struct uvc_descriptor_header * const *hs_streaming;
+		const struct uvc_descriptor_header * const *ss_streaming;
 	} desc;
 	} desc;
 
 
 	unsigned int control_intf;
 	unsigned int control_intf;

+ 25 - 4
drivers/usb/gadget/webcam.c

@@ -272,7 +272,15 @@ static const struct uvc_color_matching_descriptor uvc_color_matching = {
 	.bMatrixCoefficients	= 4,
 	.bMatrixCoefficients	= 4,
 };
 };
 
 
-static const struct uvc_descriptor_header * const uvc_control_cls[] = {
+static const struct uvc_descriptor_header * const uvc_fs_control_cls[] = {
+	(const struct uvc_descriptor_header *) &uvc_control_header,
+	(const struct uvc_descriptor_header *) &uvc_camera_terminal,
+	(const struct uvc_descriptor_header *) &uvc_processing,
+	(const struct uvc_descriptor_header *) &uvc_output_terminal,
+	NULL,
+};
+
+static const struct uvc_descriptor_header * const uvc_ss_control_cls[] = {
 	(const struct uvc_descriptor_header *) &uvc_control_header,
 	(const struct uvc_descriptor_header *) &uvc_control_header,
 	(const struct uvc_descriptor_header *) &uvc_camera_terminal,
 	(const struct uvc_descriptor_header *) &uvc_camera_terminal,
 	(const struct uvc_descriptor_header *) &uvc_processing,
 	(const struct uvc_descriptor_header *) &uvc_processing,
@@ -304,6 +312,18 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = {
 	NULL,
 	NULL,
 };
 };
 
 
+static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = {
+	(const struct uvc_descriptor_header *) &uvc_input_header,
+	(const struct uvc_descriptor_header *) &uvc_format_yuv,
+	(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
+	(const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
+	(const struct uvc_descriptor_header *) &uvc_format_mjpg,
+	(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
+	(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
+	(const struct uvc_descriptor_header *) &uvc_color_matching,
+	NULL,
+};
+
 /* --------------------------------------------------------------------------
 /* --------------------------------------------------------------------------
  * USB configuration
  * USB configuration
  */
  */
@@ -311,8 +331,9 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = {
 static int __init
 static int __init
 webcam_config_bind(struct usb_configuration *c)
 webcam_config_bind(struct usb_configuration *c)
 {
 {
-	return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls,
-			       uvc_hs_streaming_cls);
+	return uvc_bind_config(c, uvc_fs_control_cls, uvc_ss_control_cls,
+		uvc_fs_streaming_cls, uvc_hs_streaming_cls,
+		uvc_ss_streaming_cls);
 }
 }
 
 
 static struct usb_configuration webcam_config_driver = {
 static struct usb_configuration webcam_config_driver = {
@@ -373,7 +394,7 @@ static struct usb_composite_driver webcam_driver = {
 	.name		= "g_webcam",
 	.name		= "g_webcam",
 	.dev		= &webcam_device_descriptor,
 	.dev		= &webcam_device_descriptor,
 	.strings	= webcam_device_strings,
 	.strings	= webcam_device_strings,
-	.max_speed	= USB_SPEED_HIGH,
+	.max_speed	= USB_SPEED_SUPER,
 	.unbind		= webcam_unbind,
 	.unbind		= webcam_unbind,
 };
 };
 
 

+ 2 - 2
drivers/usb/host/Kconfig

@@ -652,7 +652,7 @@ config USB_HCD_BCMA
 	select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
 	select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
 	select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
 	select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
 	help
 	help
-	  Enbale support for the EHCI and OCHI host controller on an bcma bus.
+	  Enable support for the EHCI and OCHI host controller on an bcma bus.
 	  It converts the bcma driver into two platform device drivers
 	  It converts the bcma driver into two platform device drivers
 	  for ehci and ohci.
 	  for ehci and ohci.
 
 
@@ -664,7 +664,7 @@ config USB_HCD_SSB
 	select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
 	select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
 	select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
 	select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
 	help
 	help
-	  Enbale support for the EHCI and OCHI host controller on an bcma bus.
+	  Enable support for the EHCI and OCHI host controller on an bcma bus.
 	  It converts the bcma driver into two platform device drivers
 	  It converts the bcma driver into two platform device drivers
 	  for ehci and ohci.
 	  for ehci and ohci.
 
 

+ 2 - 17
drivers/usb/host/ehci-atmel.c

@@ -53,30 +53,15 @@ static void atmel_stop_ehci(struct platform_device *pdev)
 static int ehci_atmel_setup(struct usb_hcd *hcd)
 static int ehci_atmel_setup(struct usb_hcd *hcd)
 {
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int retval = 0;
+	int retval;
 
 
 	/* registers start at offset 0x0 */
 	/* registers start at offset 0x0 */
 	ehci->caps = hcd->regs;
 	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs +
-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-	dbg_hcs_params(ehci, "reset");
-	dbg_hcc_params(ehci, "reset");
-
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
-	retval = ehci_halt(ehci);
-	if (retval)
-		return retval;
 
 
-	/* data structure init */
-	retval = ehci_init(hcd);
+	retval = ehci_setup(hcd);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 
-	ehci->sbrn = 0x20;
-
-	ehci_reset(ehci);
 	ehci_port_power(ehci, 0);
 	ehci_port_power(ehci, 0);
 
 
 	return retval;
 	return retval;

+ 8 - 79
drivers/usb/host/ehci-au1xxx.c

@@ -20,10 +20,12 @@ extern int usb_disabled(void);
 static int au1xxx_ehci_setup(struct usb_hcd *hcd)
 static int au1xxx_ehci_setup(struct usb_hcd *hcd)
 {
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int ret = ehci_init(hcd);
+	int ret;
+
+	ehci->caps = hcd->regs;
+	ret = ehci_setup(hcd);
 
 
 	ehci->need_io_watchdog = 0;
 	ehci->need_io_watchdog = 0;
-	ehci_reset(ehci);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -78,7 +80,6 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
 static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
 static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
 {
 {
 	struct usb_hcd *hcd;
 	struct usb_hcd *hcd;
-	struct ehci_hcd *ehci;
 	struct resource *res;
 	struct resource *res;
 	int ret;
 	int ret;
 
 
@@ -116,13 +117,6 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
 		goto err3;
 		goto err3;
 	}
 	}
 
 
-	ehci = hcd_to_ehci(hcd);
-	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs +
-		HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = readl(&ehci->caps->hcs_params);
-
 	ret = usb_add_hcd(hcd, pdev->resource[1].start,
 	ret = usb_add_hcd(hcd, pdev->resource[1].start,
 			  IRQF_SHARED);
 			  IRQF_SHARED);
 	if (ret == 0) {
 	if (ret == 0) {
@@ -158,28 +152,10 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
 static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
 static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
 {
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	unsigned long flags;
-	int rc = 0;
-
-	if (time_before(jiffies, ehci->next_statechange))
-		msleep(10);
-
-	/* Root hub was already suspended. Disable irq emission and
-	 * mark HW unaccessible.  The PM and USB cores make sure that
-	 * the root hub is either suspended or stopped.
-	 */
-	ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
-	spin_lock_irqsave(&ehci->lock, flags);
-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
-	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
-
-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	spin_unlock_irqrestore(&ehci->lock, flags);
-
-	// could save FLADJ in case of Vaux power loss
-	// ... we'd only use it to handle clock skew
+	bool do_wakeup = device_may_wakeup(dev);
+	int rc;
 
 
+	rc = ehci_suspend(hcd, do_wakeup);
 	alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
 	alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
 
 
 	return rc;
 	return rc;
@@ -188,56 +164,9 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
 static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
 static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
 {
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 
 
 	alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);
 	alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);
-
-	// maybe restore FLADJ
-
-	if (time_before(jiffies, ehci->next_statechange))
-		msleep(100);
-
-	/* Mark hardware accessible again as we are out of D3 state by now */
-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-	/* If CF is still set, we maintained PCI Vaux power.
-	 * Just undo the effect of ehci_pci_suspend().
-	 */
-	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
-		int	mask = INTR_MASK;
-
-		ehci_prepare_ports_for_controller_resume(ehci);
-		if (!hcd->self.root_hub->do_remote_wakeup)
-			mask &= ~STS_PCD;
-		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
-		ehci_readl(ehci, &ehci->regs->intr_enable);
-		return 0;
-	}
-
-	ehci_dbg(ehci, "lost power, restarting\n");
-	usb_root_hub_lost_power(hcd->self.root_hub);
-
-	/* Else reset, to cope with power loss or flush-to-storage
-	 * style "resume" having let BIOS kick in during reboot.
-	 */
-	(void) ehci_halt(ehci);
-	(void) ehci_reset(ehci);
-
-	/* emptying the schedule aborts any urbs */
-	spin_lock_irq(&ehci->lock);
-	if (ehci->reclaim)
-		end_unlink_async(ehci);
-	ehci_work(ehci);
-	spin_unlock_irq(&ehci->lock);
-
-	ehci_writel(ehci, ehci->command, &ehci->regs->command);
-	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
-	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
-
-	/* here we "know" root ports should always stay powered */
-	ehci_port_power(ehci, 1);
-
-	ehci->rh_state = EHCI_RH_SUSPENDED;
+	ehci_resume(hcd, false);
 
 
 	return 0;
 	return 0;
 }
 }

+ 1 - 5
drivers/usb/host/ehci-cns3xxx.c

@@ -33,14 +33,10 @@ static int cns3xxx_ehci_init(struct usb_hcd *hcd)
 	}
 	}
 
 
 	ehci->caps = hcd->regs;
 	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs
-		+ HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
 
 	hcd->has_tt = 0;
 	hcd->has_tt = 0;
-	ehci_reset(ehci);
 
 
-	retval = ehci_init(hcd);
+	retval = ehci_setup(hcd);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 

+ 12 - 28
drivers/usb/host/ehci-fsl.c

@@ -27,6 +27,7 @@
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/pm.h>
+#include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/fsl_devices.h>
 #include <linux/fsl_devices.h>
 
 
@@ -142,19 +143,19 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
 	if (pdata->operating_mode == FSL_USB2_DR_OTG) {
 	if (pdata->operating_mode == FSL_USB2_DR_OTG) {
 		struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 		struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 
 
-		ehci->transceiver = usb_get_transceiver();
-		dev_dbg(&pdev->dev, "hcd=0x%p  ehci=0x%p, transceiver=0x%p\n",
-			hcd, ehci, ehci->transceiver);
+		hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2);
+		dev_dbg(&pdev->dev, "hcd=0x%p  ehci=0x%p, phy=0x%p\n",
+			hcd, ehci, hcd->phy);
 
 
-		if (ehci->transceiver) {
-			retval = otg_set_host(ehci->transceiver->otg,
+		if (!IS_ERR_OR_NULL(hcd->phy)) {
+			retval = otg_set_host(hcd->phy->otg,
 					      &ehci_to_hcd(ehci)->self);
 					      &ehci_to_hcd(ehci)->self);
 			if (retval) {
 			if (retval) {
-				usb_put_transceiver(ehci->transceiver);
+				usb_put_phy(hcd->phy);
 				goto err4;
 				goto err4;
 			}
 			}
 		} else {
 		} else {
-			dev_err(&pdev->dev, "can't find transceiver\n");
+			dev_err(&pdev->dev, "can't find phy\n");
 			retval = -ENODEV;
 			retval = -ENODEV;
 			goto err4;
 			goto err4;
 		}
 		}
@@ -190,11 +191,10 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
 			       struct platform_device *pdev)
 			       struct platform_device *pdev)
 {
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 
 
-	if (ehci->transceiver) {
-		otg_set_host(ehci->transceiver->otg, NULL);
-		usb_put_transceiver(ehci->transceiver);
+	if (!IS_ERR_OR_NULL(hcd->phy)) {
+		otg_set_host(hcd->phy->otg, NULL);
+		usb_put_phy(hcd->phy);
 	}
 	}
 
 
 	usb_remove_hcd(hcd);
 	usb_remove_hcd(hcd);
@@ -348,29 +348,13 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
 
 
 	/* EHCI registers start at offset 0x100 */
 	/* EHCI registers start at offset 0x100 */
 	ehci->caps = hcd->regs + 0x100;
 	ehci->caps = hcd->regs + 0x100;
-	ehci->regs = hcd->regs + 0x100 +
-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-	dbg_hcs_params(ehci, "reset");
-	dbg_hcc_params(ehci, "reset");
-
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
 
 	hcd->has_tt = 1;
 	hcd->has_tt = 1;
 
 
-	retval = ehci_halt(ehci);
-	if (retval)
-		return retval;
-
-	/* data structure init */
-	retval = ehci_init(hcd);
+	retval = ehci_setup(hcd);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 
-	ehci->sbrn = 0x20;
-
-	ehci_reset(ehci);
-
 	if (of_device_is_compatible(dev->parent->of_node,
 	if (of_device_is_compatible(dev->parent->of_node,
 				    "fsl,mpc5121-usb2-dr")) {
 				    "fsl,mpc5121-usb2-dr")) {
 		/*
 		/*

+ 2 - 13
drivers/usb/host/ehci-grlib.c

@@ -40,18 +40,13 @@ static int ehci_grlib_setup(struct usb_hcd *hcd)
 	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
 	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
 	int		retval;
 	int		retval;
 
 
-	retval = ehci_halt(ehci);
+	retval = ehci_setup(hcd);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 
-	retval = ehci_init(hcd);
-	if (retval)
-		return retval;
-
-	ehci->sbrn = 0x20;
 	ehci_port_power(ehci, 1);
 	ehci_port_power(ehci, 1);
 
 
-	return ehci_reset(ehci);
+	return retval;
 }
 }
 
 
 
 
@@ -164,12 +159,6 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op)
 		ehci->big_endian_capbase = 1;
 		ehci->big_endian_capbase = 1;
 	}
 	}
 
 
-	ehci->regs = hcd->regs +
-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
 	rv = usb_add_hcd(hcd, irq, 0);
 	rv = usb_add_hcd(hcd, irq, 0);
 	if (rv)
 	if (rv)
 		goto err_ehci;
 		goto err_ehci;

+ 98 - 11
drivers/usb/host/ehci-hcd.c

@@ -203,11 +203,9 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
 /* check TDI/ARC silicon is in host mode */
 /* check TDI/ARC silicon is in host mode */
 static int tdi_in_host_mode (struct ehci_hcd *ehci)
 static int tdi_in_host_mode (struct ehci_hcd *ehci)
 {
 {
-	u32 __iomem	*reg_ptr;
 	u32		tmp;
 	u32		tmp;
 
 
-	reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
-	tmp = ehci_readl(ehci, reg_ptr);
+	tmp = ehci_readl(ehci, &ehci->regs->usbmode);
 	return (tmp & 3) == USBMODE_CM_HC;
 	return (tmp & 3) == USBMODE_CM_HC;
 }
 }
 
 
@@ -303,11 +301,9 @@ static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
 /* put TDI/ARC silicon into EHCI mode */
 /* put TDI/ARC silicon into EHCI mode */
 static void tdi_reset (struct ehci_hcd *ehci)
 static void tdi_reset (struct ehci_hcd *ehci)
 {
 {
-	u32 __iomem	*reg_ptr;
 	u32		tmp;
 	u32		tmp;
 
 
-	reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
-	tmp = ehci_readl(ehci, reg_ptr);
+	tmp = ehci_readl(ehci, &ehci->regs->usbmode);
 	tmp |= USBMODE_CM_HC;
 	tmp |= USBMODE_CM_HC;
 	/* The default byte access to MMR space is LE after
 	/* The default byte access to MMR space is LE after
 	 * controller reset. Set the required endian mode
 	 * controller reset. Set the required endian mode
@@ -315,7 +311,7 @@ static void tdi_reset (struct ehci_hcd *ehci)
 	 */
 	 */
 	if (ehci_big_endian_mmio(ehci))
 	if (ehci_big_endian_mmio(ehci))
 		tmp |= USBMODE_BE;
 		tmp |= USBMODE_BE;
-	ehci_writel(ehci, tmp, reg_ptr);
+	ehci_writel(ehci, tmp, &ehci->regs->usbmode);
 }
 }
 
 
 /* reset a non-running (STS_HALT == 1) controller */
 /* reset a non-running (STS_HALT == 1) controller */
@@ -339,9 +335,8 @@ static int ehci_reset (struct ehci_hcd *ehci)
 
 
 	if (ehci->has_hostpc) {
 	if (ehci->has_hostpc) {
 		ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS,
 		ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS,
-			(u32 __iomem *)(((u8 *)ehci->regs) + USBMODE_EX));
-		ehci_writel(ehci, TXFIFO_DEFAULT,
-			(u32 __iomem *)(((u8 *)ehci->regs) + TXFILLTUNING));
+				&ehci->regs->usbmode_ex);
+		ehci_writel(ehci, TXFIFO_DEFAULT, &ehci->regs->txfill_tuning);
 	}
 	}
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
@@ -813,7 +808,7 @@ static int ehci_run (struct usb_hcd *hcd)
 	return 0;
 	return 0;
 }
 }
 
 
-static int __maybe_unused ehci_setup (struct usb_hcd *hcd)
+static int ehci_setup(struct usb_hcd *hcd)
 {
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	int retval;
 	int retval;
@@ -837,6 +832,9 @@ static int __maybe_unused ehci_setup (struct usb_hcd *hcd)
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 
+	if (ehci_is_TDI(ehci))
+		tdi_reset(ehci);
+
 	ehci_reset(ehci);
 	ehci_reset(ehci);
 
 
 	return 0;
 	return 0;
@@ -1247,6 +1245,95 @@ static int ehci_get_frame (struct usb_hcd *hcd)
 }
 }
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_PM
+
+/* suspend/resume, section 4.3 */
+
+/* These routines handle the generic parts of controller suspend/resume */
+
+static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+
+	if (time_before(jiffies, ehci->next_statechange))
+		msleep(10);
+
+	/*
+	 * Root hub was already suspended.  Disable IRQ emission and
+	 * mark HW unaccessible.  The PM and USB cores make sure that
+	 * the root hub is either suspended or stopped.
+	 */
+	ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
+
+	spin_lock_irq(&ehci->lock);
+	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+	(void) ehci_readl(ehci, &ehci->regs->intr_enable);
+
+	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	spin_unlock_irq(&ehci->lock);
+
+	return 0;
+}
+
+/* Returns 0 if power was preserved, 1 if power was lost */
+static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+
+	if (time_before(jiffies, ehci->next_statechange))
+		msleep(100);
+
+	/* Mark hardware accessible again as we are back to full power by now */
+	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+	/*
+	 * If CF is still set and we aren't resuming from hibernation
+	 * then we maintained suspend power.
+	 * Just undo the effect of ehci_suspend().
+	 */
+	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
+			!hibernated) {
+		int	mask = INTR_MASK;
+
+		ehci_prepare_ports_for_controller_resume(ehci);
+		if (!hcd->self.root_hub->do_remote_wakeup)
+			mask &= ~STS_PCD;
+		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+		ehci_readl(ehci, &ehci->regs->intr_enable);
+		return 0;
+	}
+
+	/*
+	 * Else reset, to cope with power loss or resume from hibernation
+	 * having let the firmware kick in during reboot.
+	 */
+	usb_root_hub_lost_power(hcd->self.root_hub);
+	(void) ehci_halt(ehci);
+	(void) ehci_reset(ehci);
+
+	/* emptying the schedule aborts any urbs */
+	spin_lock_irq(&ehci->lock);
+	if (ehci->reclaim)
+		end_unlink_async(ehci);
+	ehci_work(ehci);
+	spin_unlock_irq(&ehci->lock);
+
+	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
+
+	/* here we "know" root ports should always stay powered */
+	ehci_port_power(ehci, 1);
+
+	ehci->rh_state = EHCI_RH_SUSPENDED;
+	return 1;
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 /*
 /*
  * The EHCI in ChipIdea HDRC cannot be a separate module or device,
  * The EHCI in ChipIdea HDRC cannot be a separate module or device,
  * because its registers (and irq) are shared between host/gadget/otg
  * because its registers (and irq) are shared between host/gadget/otg

+ 11 - 21
drivers/usb/host/ehci-hub.c

@@ -107,7 +107,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
 	ehci->owned_ports = 0;
 	ehci->owned_ports = 0;
 }
 }
 
 
-static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci)
+static int ehci_port_change(struct ehci_hcd *ehci)
 {
 {
 	int i = HCS_N_PORTS(ehci->hcs_params);
 	int i = HCS_N_PORTS(ehci->hcs_params);
 
 
@@ -128,7 +128,7 @@ static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci)
 	return 0;
 	return 0;
 }
 }
 
 
-static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
+static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
 		bool suspending, bool do_wakeup)
 		bool suspending, bool do_wakeup)
 {
 {
 	int		port;
 	int		port;
@@ -149,10 +149,8 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
 	if (ehci->has_hostpc) {
 	if (ehci->has_hostpc) {
 		port = HCS_N_PORTS(ehci->hcs_params);
 		port = HCS_N_PORTS(ehci->hcs_params);
 		while (port--) {
 		while (port--) {
-			u32 __iomem	*hostpc_reg;
+			u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[port];
 
 
-			hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
-					+ HOSTPC0 + 4 * port);
 			temp = ehci_readl(ehci, hostpc_reg);
 			temp = ehci_readl(ehci, hostpc_reg);
 			ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg);
 			ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg);
 		}
 		}
@@ -185,10 +183,8 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
 	if (ehci->has_hostpc) {
 	if (ehci->has_hostpc) {
 		port = HCS_N_PORTS(ehci->hcs_params);
 		port = HCS_N_PORTS(ehci->hcs_params);
 		while (port--) {
 		while (port--) {
-			u32 __iomem	*hostpc_reg;
+			u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[port];
 
 
-			hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
-					+ HOSTPC0 + 4 * port);
 			temp = ehci_readl(ehci, hostpc_reg);
 			temp = ehci_readl(ehci, hostpc_reg);
 			ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
 			ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
 		}
 		}
@@ -285,11 +281,9 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
 
 
 		port = HCS_N_PORTS(ehci->hcs_params);
 		port = HCS_N_PORTS(ehci->hcs_params);
 		while (port--) {
 		while (port--) {
-			u32 __iomem	*hostpc_reg;
+			u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[port];
 			u32		t3;
 			u32		t3;
 
 
-			hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
-					+ HOSTPC0 + 4 * port);
 			t3 = ehci_readl(ehci, hostpc_reg);
 			t3 = ehci_readl(ehci, hostpc_reg);
 			ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg);
 			ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg);
 			t3 = ehci_readl(ehci, hostpc_reg);
 			t3 = ehci_readl(ehci, hostpc_reg);
@@ -388,10 +382,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 		i = HCS_N_PORTS(ehci->hcs_params);
 		i = HCS_N_PORTS(ehci->hcs_params);
 		while (i--) {
 		while (i--) {
 			if (test_bit(i, &ehci->bus_suspended)) {
 			if (test_bit(i, &ehci->bus_suspended)) {
-				u32 __iomem	*hostpc_reg;
+				u32 __iomem	*hostpc_reg =
+							&ehci->regs->hostpc[i];
 
 
-				hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
-						+ HOSTPC0 + 4 * i);
 				temp = ehci_readl(ehci, hostpc_reg);
 				temp = ehci_readl(ehci, hostpc_reg);
 				ehci_writel(ehci, temp & ~HOSTPC_PHCD,
 				ehci_writel(ehci, temp & ~HOSTPC_PHCD,
 						hostpc_reg);
 						hostpc_reg);
@@ -667,7 +660,7 @@ static int ehci_hub_control (
 	int		ports = HCS_N_PORTS (ehci->hcs_params);
 	int		ports = HCS_N_PORTS (ehci->hcs_params);
 	u32 __iomem	*status_reg = &ehci->regs->port_status[
 	u32 __iomem	*status_reg = &ehci->regs->port_status[
 				(wIndex & 0xff) - 1];
 				(wIndex & 0xff) - 1];
-	u32 __iomem	*hostpc_reg = NULL;
+	u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[(wIndex & 0xff) - 1];
 	u32		temp, temp1, status;
 	u32		temp, temp1, status;
 	unsigned long	flags;
 	unsigned long	flags;
 	int		retval = 0;
 	int		retval = 0;
@@ -680,9 +673,6 @@ static int ehci_hub_control (
 	 * power, "this is the one", etc.  EHCI spec supports this.
 	 * power, "this is the one", etc.  EHCI spec supports this.
 	 */
 	 */
 
 
-	if (ehci->has_hostpc)
-		hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs
-				+ HOSTPC0 + 4 * ((wIndex & 0xff) - 1));
 	spin_lock_irqsave (&ehci->lock, flags);
 	spin_lock_irqsave (&ehci->lock, flags);
 	switch (typeReq) {
 	switch (typeReq) {
 	case ClearHubFeature:
 	case ClearHubFeature:
@@ -724,7 +714,7 @@ static int ehci_hub_control (
 #ifdef CONFIG_USB_OTG
 #ifdef CONFIG_USB_OTG
 			if ((hcd->self.otg_port == (wIndex + 1))
 			if ((hcd->self.otg_port == (wIndex + 1))
 			    && hcd->self.b_hnp_enable) {
 			    && hcd->self.b_hnp_enable) {
-				otg_start_hnp(ehci->transceiver->otg);
+				otg_start_hnp(hcd->phy->otg);
 				break;
 				break;
 			}
 			}
 #endif
 #endif
@@ -734,7 +724,7 @@ static int ehci_hub_control (
 				goto error;
 				goto error;
 
 
 			/* clear phy low-power mode before resume */
 			/* clear phy low-power mode before resume */
-			if (hostpc_reg) {
+			if (ehci->has_hostpc) {
 				temp1 = ehci_readl(ehci, hostpc_reg);
 				temp1 = ehci_readl(ehci, hostpc_reg);
 				ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
 				ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
 						hostpc_reg);
 						hostpc_reg);
@@ -984,7 +974,7 @@ static int ehci_hub_control (
 			temp &= ~PORT_WKCONN_E;
 			temp &= ~PORT_WKCONN_E;
 			temp |= PORT_WKDISC_E | PORT_WKOC_E;
 			temp |= PORT_WKDISC_E | PORT_WKOC_E;
 			ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
 			ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
-			if (hostpc_reg) {
+			if (ehci->has_hostpc) {
 				spin_unlock_irqrestore(&ehci->lock, flags);
 				spin_unlock_irqrestore(&ehci->lock, flags);
 				msleep(5);/* 5ms for HCD enter low pwr mode */
 				msleep(5);/* 5ms for HCD enter low pwr mode */
 				spin_lock_irqsave(&ehci->lock, flags);
 				spin_lock_irqsave(&ehci->lock, flags);

+ 1 - 5
drivers/usb/host/ehci-ixp4xx.c

@@ -22,14 +22,10 @@ static int ixp4xx_ehci_init(struct usb_hcd *hcd)
 	ehci->big_endian_mmio = 1;
 	ehci->big_endian_mmio = 1;
 
 
 	ehci->caps = hcd->regs + 0x100;
 	ehci->caps = hcd->regs + 0x100;
-	ehci->regs = hcd->regs + 0x100
-		+ HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
 
 	hcd->has_tt = 1;
 	hcd->has_tt = 1;
-	ehci_reset(ehci);
 
 
-	retval = ehci_init(hcd);
+	retval = ehci_setup(hcd);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 

+ 7 - 20
drivers/usb/host/ehci-msm.c

@@ -145,8 +145,8 @@ static int ehci_msm_probe(struct platform_device *pdev)
 	 * powering up VBUS, mapping of registers address space and power
 	 * powering up VBUS, mapping of registers address space and power
 	 * management.
 	 * management.
 	 */
 	 */
-	phy = usb_get_transceiver();
-	if (!phy) {
+	phy = usb_get_phy(USB_PHY_TYPE_USB2);
+	if (IS_ERR_OR_NULL(phy)) {
 		dev_err(&pdev->dev, "unable to find transceiver\n");
 		dev_err(&pdev->dev, "unable to find transceiver\n");
 		ret = -ENODEV;
 		ret = -ENODEV;
 		goto unmap;
 		goto unmap;
@@ -169,7 +169,7 @@ static int ehci_msm_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 
 
 put_transceiver:
 put_transceiver:
-	usb_put_transceiver(phy);
+	usb_put_phy(phy);
 unmap:
 unmap:
 	iounmap(hcd->regs);
 	iounmap(hcd->regs);
 put_hcd:
 put_hcd:
@@ -187,7 +187,7 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev)
 	pm_runtime_set_suspended(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 
 
 	otg_set_host(phy->otg, NULL);
 	otg_set_host(phy->otg, NULL);
-	usb_put_transceiver(phy);
+	usb_put_phy(phy);
 
 
 	usb_put_hcd(hcd);
 	usb_put_hcd(hcd);
 
 
@@ -198,24 +198,11 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev)
 static int ehci_msm_pm_suspend(struct device *dev)
 static int ehci_msm_pm_suspend(struct device *dev)
 {
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	bool wakeup = device_may_wakeup(dev);
+	bool do_wakeup = device_may_wakeup(dev);
 
 
 	dev_dbg(dev, "ehci-msm PM suspend\n");
 	dev_dbg(dev, "ehci-msm PM suspend\n");
 
 
-	/*
-	 * EHCI helper function has also the same check before manipulating
-	 * port wakeup flags.  We do check here the same condition before
-	 * calling the same helper function to avoid bringing hardware
-	 * from Low power mode when there is no need for adjusting port
-	 * wakeup flags.
-	 */
-	if (hcd->self.root_hub->do_remote_wakeup && !wakeup) {
-		pm_runtime_resume(dev);
-		ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd),
-				wakeup);
-	}
-
-	return 0;
+	return ehci_suspend(hcd, do_wakeup);
 }
 }
 
 
 static int ehci_msm_pm_resume(struct device *dev)
 static int ehci_msm_pm_resume(struct device *dev)
@@ -223,7 +210,7 @@ static int ehci_msm_pm_resume(struct device *dev)
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 
 
 	dev_dbg(dev, "ehci-msm PM resume\n");
 	dev_dbg(dev, "ehci-msm PM resume\n");
-	ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
+	ehci_resume(hcd, false);
 
 
 	return 0;
 	return 0;
 }
 }

+ 11 - 25
drivers/usb/host/ehci-mv.c

@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
+#include <linux/err.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/otg.h>
 #include <linux/platform_data/mv_usb.h>
 #include <linux/platform_data/mv_usb.h>
 
 
@@ -76,7 +77,6 @@ static void mv_ehci_disable(struct ehci_hcd_mv *ehci_mv)
 
 
 static int mv_ehci_reset(struct usb_hcd *hcd)
 static int mv_ehci_reset(struct usb_hcd *hcd)
 {
 {
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	struct device *dev = hcd->self.controller;
 	struct device *dev = hcd->self.controller;
 	struct ehci_hcd_mv *ehci_mv = dev_get_drvdata(dev);
 	struct ehci_hcd_mv *ehci_mv = dev_get_drvdata(dev);
 	int retval;
 	int retval;
@@ -86,25 +86,13 @@ static int mv_ehci_reset(struct usb_hcd *hcd)
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
-	/*
-	 * data structure init
-	 */
-	retval = ehci_init(hcd);
-	if (retval) {
-		dev_err(dev, "ehci_init failed %d\n", retval);
-		return retval;
-	}
-
 	hcd->has_tt = 1;
 	hcd->has_tt = 1;
-	ehci->sbrn = 0x20;
 
 
-	retval = ehci_reset(ehci);
-	if (retval) {
-		dev_err(dev, "ehci_reset failed %d\n", retval);
-		return retval;
-	}
+	retval = ehci_setup(hcd);
+	if (retval)
+		dev_err(dev, "ehci_setup failed %d\n", retval);
 
 
-	return 0;
+	return retval;
 }
 }
 
 
 static const struct hc_driver mv_ehci_hc_driver = {
 static const struct hc_driver mv_ehci_hc_driver = {
@@ -247,14 +235,12 @@ static int mv_ehci_probe(struct platform_device *pdev)
 
 
 	ehci = hcd_to_ehci(hcd);
 	ehci = hcd_to_ehci(hcd);
 	ehci->caps = (struct ehci_caps *) ehci_mv->cap_regs;
 	ehci->caps = (struct ehci_caps *) ehci_mv->cap_regs;
-	ehci->regs = (struct ehci_regs *) ehci_mv->op_regs;
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
 
 	ehci_mv->mode = pdata->mode;
 	ehci_mv->mode = pdata->mode;
 	if (ehci_mv->mode == MV_USB_MODE_OTG) {
 	if (ehci_mv->mode == MV_USB_MODE_OTG) {
 #ifdef CONFIG_USB_OTG_UTILS
 #ifdef CONFIG_USB_OTG_UTILS
-		ehci_mv->otg = usb_get_transceiver();
-		if (!ehci_mv->otg) {
+		ehci_mv->otg = usb_get_phy(USB_PHY_TYPE_USB2);
+		if (IS_ERR_OR_NULL(ehci_mv->otg)) {
 			dev_err(&pdev->dev,
 			dev_err(&pdev->dev,
 				"unable to find transceiver\n");
 				"unable to find transceiver\n");
 			retval = -ENODEV;
 			retval = -ENODEV;
@@ -302,8 +288,8 @@ err_set_vbus:
 		pdata->set_vbus(0);
 		pdata->set_vbus(0);
 #ifdef CONFIG_USB_OTG_UTILS
 #ifdef CONFIG_USB_OTG_UTILS
 err_put_transceiver:
 err_put_transceiver:
-	if (ehci_mv->otg)
-		usb_put_transceiver(ehci_mv->otg);
+	if (!IS_ERR_OR_NULL(ehci_mv->otg))
+		usb_put_phy(ehci_mv->otg);
 #endif
 #endif
 err_disable_clk:
 err_disable_clk:
 	mv_ehci_disable(ehci_mv);
 	mv_ehci_disable(ehci_mv);
@@ -331,9 +317,9 @@ static int mv_ehci_remove(struct platform_device *pdev)
 	if (hcd->rh_registered)
 	if (hcd->rh_registered)
 		usb_remove_hcd(hcd);
 		usb_remove_hcd(hcd);
 
 
-	if (ehci_mv->otg) {
+	if (!IS_ERR_OR_NULL(ehci_mv->otg)) {
 		otg_set_host(ehci_mv->otg->otg, NULL);
 		otg_set_host(ehci_mv->otg->otg, NULL);
-		usb_put_transceiver(ehci_mv->otg);
+		usb_put_phy(ehci_mv->otg);
 	}
 	}
 
 
 	if (ehci_mv->mode == MV_USB_MODE_HOST) {
 	if (ehci_mv->mode == MV_USB_MODE_HOST) {

+ 1 - 16
drivers/usb/host/ehci-mxc.c

@@ -42,27 +42,12 @@ static int ehci_mxc_setup(struct usb_hcd *hcd)
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	int retval;
 	int retval;
 
 
-	dbg_hcs_params(ehci, "reset");
-	dbg_hcc_params(ehci, "reset");
-
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
 	hcd->has_tt = 1;
 	hcd->has_tt = 1;
 
 
-	retval = ehci_halt(ehci);
+	retval = ehci_setup(hcd);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 
-	/* data structure init */
-	retval = ehci_init(hcd);
-	if (retval)
-		return retval;
-
-	ehci->sbrn = 0x20;
-
-	ehci_reset(ehci);
-
 	ehci_port_power(ehci, 0);
 	ehci_port_power(ehci, 0);
 	return 0;
 	return 0;
 }
 }

+ 1 - 7
drivers/usb/host/ehci-octeon.c

@@ -56,7 +56,7 @@ static const struct hc_driver ehci_octeon_hc_driver = {
 	/*
 	/*
 	 * basic lifecycle operations
 	 * basic lifecycle operations
 	 */
 	 */
-	.reset			= ehci_init,
+	.reset			= ehci_setup,
 	.start			= ehci_run,
 	.start			= ehci_run,
 	.stop			= ehci_stop,
 	.stop			= ehci_stop,
 	.shutdown		= ehci_shutdown,
 	.shutdown		= ehci_shutdown,
@@ -150,12 +150,6 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev)
 #endif
 #endif
 
 
 	ehci->caps = hcd->regs;
 	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs +
-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
-	ehci_reset(ehci);
 
 
 	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (ret) {
 	if (ret) {

+ 56 - 52
drivers/usb/host/ehci-omap.c

@@ -145,6 +145,56 @@ static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port)
 	}
 	}
 }
 }
 
 
+static int omap_ehci_init(struct usb_hcd *hcd)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+	int			rc;
+	struct ehci_hcd_omap_platform_data	*pdata;
+
+	pdata = hcd->self.controller->platform_data;
+	if (pdata->phy_reset) {
+		if (gpio_is_valid(pdata->reset_gpio_port[0]))
+			gpio_request_one(pdata->reset_gpio_port[0],
+					 GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
+
+		if (gpio_is_valid(pdata->reset_gpio_port[1]))
+			gpio_request_one(pdata->reset_gpio_port[1],
+					 GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
+
+		/* Hold the PHY in RESET for enough time till DIR is high */
+		udelay(10);
+	}
+
+	/* Soft reset the PHY using PHY reset command over ULPI */
+	if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
+		omap_ehci_soft_phy_reset(pdev, 0);
+	if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
+		omap_ehci_soft_phy_reset(pdev, 1);
+
+	/* we know this is the memory we want, no need to ioremap again */
+	ehci->caps = hcd->regs;
+
+	rc = ehci_setup(hcd);
+
+	if (pdata->phy_reset) {
+		/* Hold the PHY in RESET for enough time till
+		 * PHY is settled and ready
+		 */
+		udelay(10);
+
+		if (gpio_is_valid(pdata->reset_gpio_port[0]))
+			gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
+
+		if (gpio_is_valid(pdata->reset_gpio_port[1]))
+			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
+	}
+
+	/* root ports should always stay powered */
+	ehci_port_power(ehci, 1);
+
+	return rc;
+}
+
 static int omap_ehci_hub_control(
 static int omap_ehci_hub_control(
 	struct usb_hcd	*hcd,
 	struct usb_hcd	*hcd,
 	u16		typeReq,
 	u16		typeReq,
@@ -219,7 +269,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
 	struct resource				*res;
 	struct resource				*res;
 	struct usb_hcd				*hcd;
 	struct usb_hcd				*hcd;
 	void __iomem				*regs;
 	void __iomem				*regs;
-	struct ehci_hcd				*omap_ehci;
 	int					ret = -ENODEV;
 	int					ret = -ENODEV;
 	int					irq;
 	int					irq;
 	int					i;
 	int					i;
@@ -281,18 +330,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
 		}
 		}
 	}
 	}
 
 
-	/* Hold PHYs in reset while initializing EHCI controller */
-	if (pdata->phy_reset) {
-		if (gpio_is_valid(pdata->reset_gpio_port[0]))
-			gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0);
-
-		if (gpio_is_valid(pdata->reset_gpio_port[1]))
-			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0);
-
-		/* Hold the PHY in RESET for enough time till DIR is high */
-		udelay(10);
-	}
-
 	pm_runtime_enable(dev);
 	pm_runtime_enable(dev);
 	pm_runtime_get_sync(dev);
 	pm_runtime_get_sync(dev);
 
 
@@ -308,49 +345,12 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
 	ehci_write(regs, EHCI_INSNREG04,
 	ehci_write(regs, EHCI_INSNREG04,
 				EHCI_INSNREG04_DISABLE_UNSUSPEND);
 				EHCI_INSNREG04_DISABLE_UNSUSPEND);
 
 
-	/* Soft reset the PHY using PHY reset command over ULPI */
-	if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
-		omap_ehci_soft_phy_reset(pdev, 0);
-	if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
-		omap_ehci_soft_phy_reset(pdev, 1);
-
-	omap_ehci = hcd_to_ehci(hcd);
-	omap_ehci->sbrn = 0x20;
-
-	/* we know this is the memory we want, no need to ioremap again */
-	omap_ehci->caps = hcd->regs;
-	omap_ehci->regs = hcd->regs
-		+ HC_LENGTH(ehci, readl(&omap_ehci->caps->hc_capbase));
-
-	dbg_hcs_params(omap_ehci, "reset");
-	dbg_hcc_params(omap_ehci, "reset");
-
-	/* cache this readonly data; minimize chip reads */
-	omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params);
-
-	ehci_reset(omap_ehci);
 	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (ret) {
 	if (ret) {
 		dev_err(dev, "failed to add hcd with err %d\n", ret);
 		dev_err(dev, "failed to add hcd with err %d\n", ret);
-		goto err_add_hcd;
+		goto err_pm_runtime;
 	}
 	}
 
 
-	if (pdata->phy_reset) {
-		/* Hold the PHY in RESET for enough time till
-		 * PHY is settled and ready
-		 */
-		udelay(10);
-
-		if (gpio_is_valid(pdata->reset_gpio_port[0]))
-			gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
-
-		if (gpio_is_valid(pdata->reset_gpio_port[1]))
-			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
-	}
-
-	/* root ports should always stay powered */
-	ehci_port_power(omap_ehci, 1);
-
 	/* get clocks */
 	/* get clocks */
 	utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
 	utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
 	if (IS_ERR(utmi_p1_fck)) {
 	if (IS_ERR(utmi_p1_fck)) {
@@ -422,8 +422,12 @@ err_utmi_p1_fck:
 	clk_put(utmi_p1_fck);
 	clk_put(utmi_p1_fck);
 
 
 err_add_hcd:
 err_add_hcd:
+	usb_remove_hcd(hcd);
+
+err_pm_runtime:
 	disable_put_regulator(pdata);
 	disable_put_regulator(pdata);
 	pm_runtime_put_sync(dev);
 	pm_runtime_put_sync(dev);
+	usb_put_hcd(hcd);
 
 
 err_io:
 err_io:
 	iounmap(regs);
 	iounmap(regs);
@@ -506,7 +510,7 @@ static const struct hc_driver ehci_omap_hc_driver = {
 	/*
 	/*
 	 * basic lifecycle operations
 	 * basic lifecycle operations
 	 */
 	 */
-	.reset			= ehci_init,
+	.reset			= omap_ehci_init,
 	.start			= ehci_run,
 	.start			= ehci_run,
 	.stop			= ehci_stop,
 	.stop			= ehci_stop,
 	.shutdown		= ehci_shutdown,
 	.shutdown		= ehci_shutdown,

+ 1 - 16
drivers/usb/host/ehci-orion.c

@@ -106,21 +106,10 @@ static int ehci_orion_setup(struct usb_hcd *hcd)
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	int retval;
 	int retval;
 
 
-	hcd->has_tt = 1;
-
-	retval = ehci_halt(ehci);
-	if (retval)
-		return retval;
-
-	/*
-	 * data structure init
-	 */
-	retval = ehci_init(hcd);
+	retval = ehci_setup(ehci);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 
-	ehci_reset(ehci);
-
 	ehci_port_power(ehci, 0);
 	ehci_port_power(ehci, 0);
 
 
 	return retval;
 	return retval;
@@ -261,11 +250,7 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
 
 
 	ehci = hcd_to_ehci(hcd);
 	ehci = hcd_to_ehci(hcd);
 	ehci->caps = hcd->regs + 0x100;
 	ehci->caps = hcd->regs + 0x100;
-	ehci->regs = hcd->regs + 0x100 +
-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 	hcd->has_tt = 1;
 	hcd->has_tt = 1;
-	ehci->sbrn = 0x20;
 
 
 	/*
 	/*
 	 * (Re-)program MBUS remapping windows if we are asked to.
 	 * (Re-)program MBUS remapping windows if we are asked to.

+ 82 - 152
drivers/usb/host/ehci-pci.c

@@ -54,6 +54,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 	u32			temp;
 	u32			temp;
 	int			retval;
 	int			retval;
 
 
+	ehci->caps = hcd->regs;
+
+	/*
+	 * ehci_init() causes memory for DMA transfers to be
+	 * allocated.  Thus, any vendor-specific workarounds based on
+	 * limiting the type of memory used for DMA transfers must
+	 * happen before ehci_setup() is called.
+	 *
+	 * Most other workarounds can be done either before or after
+	 * init and reset; they are located here too.
+	 */
 	switch (pdev->vendor) {
 	switch (pdev->vendor) {
 	case PCI_VENDOR_ID_TOSHIBA_2:
 	case PCI_VENDOR_ID_TOSHIBA_2:
 		/* celleb's companion chip */
 		/* celleb's companion chip */
@@ -66,20 +77,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 #endif
 #endif
 		}
 		}
 		break;
 		break;
-	}
-
-	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs +
-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-
-	dbg_hcs_params(ehci, "reset");
-	dbg_hcc_params(ehci, "reset");
-
-        /* ehci_init() causes memory for DMA transfers to be
-         * allocated.  Thus, any vendor-specific workarounds based on
-         * limiting the type of memory used for DMA transfers must
-         * happen before ehci_init() is called. */
-	switch (pdev->vendor) {
 	case PCI_VENDOR_ID_NVIDIA:
 	case PCI_VENDOR_ID_NVIDIA:
 		/* NVidia reports that certain chips don't handle
 		/* NVidia reports that certain chips don't handle
 		 * QH, ITD, or SITD addresses above 2GB.  (But TD,
 		 * QH, ITD, or SITD addresses above 2GB.  (But TD,
@@ -95,61 +92,28 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 				ehci_warn(ehci, "can't enable NVidia "
 				ehci_warn(ehci, "can't enable NVidia "
 					"workaround for >2GB RAM\n");
 					"workaround for >2GB RAM\n");
 			break;
 			break;
-		}
-		break;
-	}
-
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
-	retval = ehci_halt(ehci);
-	if (retval)
-		return retval;
 
 
-	if ((pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x7808) ||
-	    (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x4396)) {
-		/* EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may
-		 * read/write memory space which does not belong to it when
-		 * there is NULL pointer with T-bit set to 1 in the frame list
-		 * table. To avoid the issue, the frame list link pointer
-		 * should always contain a valid pointer to a inactive qh.
+		/* Some NForce2 chips have problems with selective suspend;
+		 * fixed in newer silicon.
 		 */
 		 */
-		ehci->use_dummy_qh = 1;
-		ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI "
-				"dummy qh workaround\n");
-	}
-
-	/* data structure init */
-	retval = ehci_init(hcd);
-	if (retval)
-		return retval;
-
-	switch (pdev->vendor) {
-	case PCI_VENDOR_ID_NEC:
-		ehci->need_io_watchdog = 0;
+		case 0x0068:
+			if (pdev->revision < 0xa4)
+				ehci->no_selective_suspend = 1;
+			break;
+		}
 		break;
 		break;
 	case PCI_VENDOR_ID_INTEL:
 	case PCI_VENDOR_ID_INTEL:
-		ehci->need_io_watchdog = 0;
 		ehci->fs_i_thresh = 1;
 		ehci->fs_i_thresh = 1;
 		if (pdev->device == 0x27cc) {
 		if (pdev->device == 0x27cc) {
 			ehci->broken_periodic = 1;
 			ehci->broken_periodic = 1;
 			ehci_info(ehci, "using broken periodic workaround\n");
 			ehci_info(ehci, "using broken periodic workaround\n");
 		}
 		}
-		if (pdev->device == 0x0806 || pdev->device == 0x0811
-				|| pdev->device == 0x0829) {
-			ehci_info(ehci, "disable lpm for langwell/penwell\n");
-			ehci->has_lpm = 0;
-		}
-		if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) {
+		if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB)
 			hcd->has_tt = 1;
 			hcd->has_tt = 1;
-			tdi_reset(ehci);
-		}
 		break;
 		break;
 	case PCI_VENDOR_ID_TDI:
 	case PCI_VENDOR_ID_TDI:
-		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
+		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI)
 			hcd->has_tt = 1;
 			hcd->has_tt = 1;
-			tdi_reset(ehci);
-		}
 		break;
 		break;
 	case PCI_VENDOR_ID_AMD:
 	case PCI_VENDOR_ID_AMD:
 		/* AMD PLL quirk */
 		/* AMD PLL quirk */
@@ -161,28 +125,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 			retval = -EIO;
 			retval = -EIO;
 			goto done;
 			goto done;
 		}
 		}
-		break;
-	case PCI_VENDOR_ID_NVIDIA:
-		switch (pdev->device) {
-		/* Some NForce2 chips have problems with selective suspend;
-		 * fixed in newer silicon.
-		 */
-		case 0x0068:
-			if (pdev->revision < 0xa4)
-				ehci->no_selective_suspend = 1;
-			break;
 
 
-		/* MCP89 chips on the MacBookAir3,1 give EPROTO when
-		 * fetching device descriptors unless LPM is disabled.
-		 * There are also intermittent problems enumerating
-		 * devices with PPCD enabled.
+		/*
+		 * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may
+		 * read/write memory space which does not belong to it when
+		 * there is NULL pointer with T-bit set to 1 in the frame list
+		 * table. To avoid the issue, the frame list link pointer
+		 * should always contain a valid pointer to a inactive qh.
 		 */
 		 */
-		case 0x0d9d:
-			ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89");
-			ehci->has_lpm = 0;
-			ehci->has_ppcd = 0;
-			ehci->command &= ~CMD_PPCEE;
-			break;
+		if (pdev->device == 0x7808) {
+			ehci->use_dummy_qh = 1;
+			ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n");
 		}
 		}
 		break;
 		break;
 	case PCI_VENDOR_ID_VIA:
 	case PCI_VENDOR_ID_VIA:
@@ -203,6 +156,18 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 		/* AMD PLL quirk */
 		/* AMD PLL quirk */
 		if (usb_amd_find_chipset_info())
 		if (usb_amd_find_chipset_info())
 			ehci->amd_pll_fix = 1;
 			ehci->amd_pll_fix = 1;
+
+		/*
+		 * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may
+		 * read/write memory space which does not belong to it when
+		 * there is NULL pointer with T-bit set to 1 in the frame list
+		 * table. To avoid the issue, the frame list link pointer
+		 * should always contain a valid pointer to a inactive qh.
+		 */
+		if (pdev->device == 0x4396) {
+			ehci->use_dummy_qh = 1;
+			ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n");
+		}
 		/* SB600 and old version of SB700 have a bug in EHCI controller,
 		/* SB600 and old version of SB700 have a bug in EHCI controller,
 		 * which causes usb devices lose response in some cases.
 		 * which causes usb devices lose response in some cases.
 		 */
 		 */
@@ -231,6 +196,40 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 		break;
 		break;
 	}
 	}
 
 
+	retval = ehci_setup(hcd);
+	if (retval)
+		return retval;
+
+	/* These workarounds need to be applied after ehci_setup() */
+	switch (pdev->vendor) {
+	case PCI_VENDOR_ID_NEC:
+		ehci->need_io_watchdog = 0;
+		break;
+	case PCI_VENDOR_ID_INTEL:
+		ehci->need_io_watchdog = 0;
+		if (pdev->device == 0x0806 || pdev->device == 0x0811
+				|| pdev->device == 0x0829) {
+			ehci_info(ehci, "disable lpm for langwell/penwell\n");
+			ehci->has_lpm = 0;
+		}
+		break;
+	case PCI_VENDOR_ID_NVIDIA:
+		switch (pdev->device) {
+		/* MCP89 chips on the MacBookAir3,1 give EPROTO when
+		 * fetching device descriptors unless LPM is disabled.
+		 * There are also intermittent problems enumerating
+		 * devices with PPCD enabled.
+		 */
+		case 0x0d9d:
+			ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89");
+			ehci->has_lpm = 0;
+			ehci->has_ppcd = 0;
+			ehci->command &= ~CMD_PPCEE;
+			break;
+		}
+		break;
+	}
+
 	/* optional debug port, normally in the first BAR */
 	/* optional debug port, normally in the first BAR */
 	temp = pci_find_capability(pdev, 0x0a);
 	temp = pci_find_capability(pdev, 0x0a);
 	if (temp) {
 	if (temp) {
@@ -238,7 +237,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 		temp >>= 16;
 		temp >>= 16;
 		if ((temp & (3 << 13)) == (1 << 13)) {
 		if ((temp & (3 << 13)) == (1 << 13)) {
 			temp &= 0x1fff;
 			temp &= 0x1fff;
-			ehci->debug = ehci_to_hcd(ehci)->regs + temp;
+			ehci->debug = hcd->regs + temp;
 			temp = ehci_readl(ehci, &ehci->debug->control);
 			temp = ehci_readl(ehci, &ehci->debug->control);
 			ehci_info(ehci, "debug port %d%s\n",
 			ehci_info(ehci, "debug port %d%s\n",
 				HCS_DEBUG_PORT(ehci->hcs_params),
 				HCS_DEBUG_PORT(ehci->hcs_params),
@@ -250,8 +249,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 		}
 		}
 	}
 	}
 
 
-	ehci_reset(ehci);
-
 	/* at least the Genesys GL880S needs fixup here */
 	/* at least the Genesys GL880S needs fixup here */
 	temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
 	temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
 	temp &= 0x0f;
 	temp &= 0x0f;
@@ -275,10 +272,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 	}
 	}
 
 
 	/* Serial Bus Release Number is at PCI 0x60 offset */
 	/* Serial Bus Release Number is at PCI 0x60 offset */
-	pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
 	if (pdev->vendor == PCI_VENDOR_ID_STMICRO
 	if (pdev->vendor == PCI_VENDOR_ID_STMICRO
 	    && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST)
 	    && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST)
-		ehci->sbrn = 0x20; /* ConneXT has no sbrn register */
+		;	/* ConneXT has no sbrn register */
+	else
+		pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
 
 
 	/* Keep this around for a while just in case some EHCI
 	/* Keep this around for a while just in case some EHCI
 	 * implementation uses legacy PCI PM support.  This test
 	 * implementation uses legacy PCI PM support.  This test
@@ -331,29 +329,7 @@ done:
 
 
 static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
 {
-	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
-	unsigned long		flags;
-	int			rc = 0;
-
-	if (time_before(jiffies, ehci->next_statechange))
-		msleep(10);
-
-	/* Root hub was already suspended. Disable irq emission and
-	 * mark HW unaccessible.  The PM and USB cores make sure that
-	 * the root hub is either suspended or stopped.
-	 */
-	ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
-	spin_lock_irqsave (&ehci->lock, flags);
-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
-	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
-
-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	spin_unlock_irqrestore (&ehci->lock, flags);
-
-	// could save FLADJ in case of Vaux power loss
-	// ... we'd only use it to handle clock skew
-
-	return rc;
+	return ehci_suspend(hcd, do_wakeup);
 }
 }
 
 
 static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
 static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
@@ -402,54 +378,8 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
 	if (usb_is_intel_switchable_ehci(pdev))
 	if (usb_is_intel_switchable_ehci(pdev))
 		ehci_enable_xhci_companion();
 		ehci_enable_xhci_companion();
 
 
-	// maybe restore FLADJ
-
-	if (time_before(jiffies, ehci->next_statechange))
-		msleep(100);
-
-	/* Mark hardware accessible again as we are out of D3 state by now */
-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-	/* If CF is still set and we aren't resuming from hibernation
-	 * then we maintained PCI Vaux power.
-	 * Just undo the effect of ehci_pci_suspend().
-	 */
-	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
-				!hibernated) {
-		int	mask = INTR_MASK;
-
-		ehci_prepare_ports_for_controller_resume(ehci);
-		if (!hcd->self.root_hub->do_remote_wakeup)
-			mask &= ~STS_PCD;
-		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
-		ehci_readl(ehci, &ehci->regs->intr_enable);
-		return 0;
-	}
-
-	usb_root_hub_lost_power(hcd->self.root_hub);
-
-	/* Else reset, to cope with power loss or flush-to-storage
-	 * style "resume" having let BIOS kick in during reboot.
-	 */
-	(void) ehci_halt(ehci);
-	(void) ehci_reset(ehci);
-	(void) ehci_pci_reinit(ehci, pdev);
-
-	/* emptying the schedule aborts any urbs */
-	spin_lock_irq(&ehci->lock);
-	if (ehci->reclaim)
-		end_unlink_async(ehci);
-	ehci_work(ehci);
-	spin_unlock_irq(&ehci->lock);
-
-	ehci_writel(ehci, ehci->command, &ehci->regs->command);
-	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
-	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
-
-	/* here we "know" root ports should always stay powered */
-	ehci_port_power(ehci, 1);
-
-	ehci->rh_state = EHCI_RH_SUSPENDED;
+	if (ehci_resume(hcd, hibernated) != 0)
+		(void) ehci_pci_reinit(ehci, pdev);
 	return 0;
 	return 0;
 }
 }
 #endif
 #endif

+ 3 - 4
drivers/usb/host/ehci-platform.c

@@ -153,17 +153,16 @@ static int __devexit ehci_platform_remove(struct platform_device *dev)
 static int ehci_platform_suspend(struct device *dev)
 static int ehci_platform_suspend(struct device *dev)
 {
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	bool wakeup = device_may_wakeup(dev);
+	bool do_wakeup = device_may_wakeup(dev);
 
 
-	ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), wakeup);
-	return 0;
+	return ehci_suspend(hcd, do_wakeup);
 }
 }
 
 
 static int ehci_platform_resume(struct device *dev)
 static int ehci_platform_resume(struct device *dev)
 {
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 
 
-	ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
+	ehci_resume(hcd, false);
 	return 0;
 	return 0;
 }
 }
 
 

+ 2 - 15
drivers/usb/host/ehci-pmcmsp.c

@@ -78,27 +78,14 @@ static int ehci_msp_setup(struct usb_hcd *hcd)
 {
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 	int			retval;
 	int			retval;
+
 	ehci->big_endian_mmio = 1;
 	ehci->big_endian_mmio = 1;
 	ehci->big_endian_desc = 1;
 	ehci->big_endian_desc = 1;
 
 
 	ehci->caps = hcd->regs;
 	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs +
-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-	dbg_hcs_params(ehci, "reset");
-	dbg_hcc_params(ehci, "reset");
-
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 	hcd->has_tt = 1;
 	hcd->has_tt = 1;
 
 
-	retval = ehci_halt(ehci);
-	if (retval)
-		return retval;
-
-	ehci_reset(ehci);
-
-	/* data structure init */
-	retval = ehci_init(hcd);
+	retval = ehci_setup(hcd);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 

+ 1 - 24
drivers/usb/host/ehci-ppc-of.c

@@ -17,24 +17,6 @@
 #include <linux/of.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/of_platform.h>
 
 
-/* called during probe() after chip reset completes */
-static int ehci_ppc_of_setup(struct usb_hcd *hcd)
-{
-	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
-	int		retval;
-
-	retval = ehci_halt(ehci);
-	if (retval)
-		return retval;
-
-	retval = ehci_init(hcd);
-	if (retval)
-		return retval;
-
-	ehci->sbrn = 0x20;
-	return ehci_reset(ehci);
-}
-
 
 
 static const struct hc_driver ehci_ppc_of_hc_driver = {
 static const struct hc_driver ehci_ppc_of_hc_driver = {
 	.description		= hcd_name,
 	.description		= hcd_name,
@@ -50,7 +32,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
 	/*
 	/*
 	 * basic lifecycle operations
 	 * basic lifecycle operations
 	 */
 	 */
-	.reset			= ehci_ppc_of_setup,
+	.reset			= ehci_setup,
 	.start			= ehci_run,
 	.start			= ehci_run,
 	.stop			= ehci_stop,
 	.stop			= ehci_stop,
 	.shutdown		= ehci_shutdown,
 	.shutdown		= ehci_shutdown,
@@ -178,11 +160,6 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op)
 		ehci->big_endian_desc = 1;
 		ehci->big_endian_desc = 1;
 
 
 	ehci->caps = hcd->regs;
 	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs +
-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
 
 	if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) {
 	if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) {
 		rv = ppc44x_enable_bmt(dn);
 		rv = ppc44x_enable_bmt(dn);

+ 1 - 17
drivers/usb/host/ehci-ps3.c

@@ -55,28 +55,12 @@ static int ps3_ehci_hc_reset(struct usb_hcd *hcd)
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 
 
 	ehci->big_endian_mmio = 1;
 	ehci->big_endian_mmio = 1;
-
 	ehci->caps = hcd->regs;
 	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
-		&ehci->caps->hc_capbase));
-
-	dbg_hcs_params(ehci, "reset");
-	dbg_hcc_params(ehci, "reset");
-
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
-	result = ehci_halt(ehci);
 
 
+	result = ehci_setup(hcd);
 	if (result)
 	if (result)
 		return result;
 		return result;
 
 
-	result = ehci_init(hcd);
-
-	if (result)
-		return result;
-
-	ehci_reset(ehci);
-
 	ps3_ehci_setup_insnreg(ehci);
 	ps3_ehci_setup_insnreg(ehci);
 
 
 	return result;
 	return result;

+ 11 - 81
drivers/usb/host/ehci-s5p.c

@@ -40,7 +40,7 @@ static const struct hc_driver s5p_ehci_hc_driver = {
 	.irq			= ehci_irq,
 	.irq			= ehci_irq,
 	.flags			= HCD_MEMORY | HCD_USB2,
 	.flags			= HCD_MEMORY | HCD_USB2,
 
 
-	.reset			= ehci_init,
+	.reset			= ehci_setup,
 	.start			= ehci_run,
 	.start			= ehci_run,
 	.stop			= ehci_stop,
 	.stop			= ehci_stop,
 	.shutdown		= ehci_shutdown,
 	.shutdown		= ehci_shutdown,
@@ -79,7 +79,8 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	s5p_ehci = kzalloc(sizeof(struct s5p_ehci_hcd), GFP_KERNEL);
+	s5p_ehci = devm_kzalloc(&pdev->dev, sizeof(struct s5p_ehci_hcd),
+				GFP_KERNEL);
 	if (!s5p_ehci)
 	if (!s5p_ehci)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
@@ -89,8 +90,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
 					dev_name(&pdev->dev));
 					dev_name(&pdev->dev));
 	if (!hcd) {
 	if (!hcd) {
 		dev_err(&pdev->dev, "Unable to create HCD\n");
 		dev_err(&pdev->dev, "Unable to create HCD\n");
-		err = -ENOMEM;
-		goto fail_hcd;
+		return -ENOMEM;
 	}
 	}
 
 
 	s5p_ehci->hcd = hcd;
 	s5p_ehci->hcd = hcd;
@@ -115,7 +115,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
 
 
 	hcd->rsrc_start = res->start;
 	hcd->rsrc_start = res->start;
 	hcd->rsrc_len = resource_size(res);
 	hcd->rsrc_len = resource_size(res);
-	hcd->regs = ioremap(res->start, resource_size(res));
+	hcd->regs = devm_ioremap(&pdev->dev, res->start, hcd->rsrc_len);
 	if (!hcd->regs) {
 	if (!hcd->regs) {
 		dev_err(&pdev->dev, "Failed to remap I/O memory\n");
 		dev_err(&pdev->dev, "Failed to remap I/O memory\n");
 		err = -ENOMEM;
 		err = -ENOMEM;
@@ -126,7 +126,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
 	if (!irq) {
 	if (!irq) {
 		dev_err(&pdev->dev, "Failed to get IRQ\n");
 		dev_err(&pdev->dev, "Failed to get IRQ\n");
 		err = -ENODEV;
 		err = -ENODEV;
-		goto fail;
+		goto fail_io;
 	}
 	}
 
 
 	if (pdata->phy_init)
 	if (pdata->phy_init)
@@ -134,40 +134,26 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
 
 
 	ehci = hcd_to_ehci(hcd);
 	ehci = hcd_to_ehci(hcd);
 	ehci->caps = hcd->regs;
 	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs +
-		HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
 
 
 	/* DMA burst Enable */
 	/* DMA burst Enable */
 	writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
 	writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
 
 
-	dbg_hcs_params(ehci, "reset");
-	dbg_hcc_params(ehci, "reset");
-
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = readl(&ehci->caps->hcs_params);
-
-	ehci_reset(ehci);
-
 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (err) {
 	if (err) {
 		dev_err(&pdev->dev, "Failed to add USB HCD\n");
 		dev_err(&pdev->dev, "Failed to add USB HCD\n");
-		goto fail;
+		goto fail_io;
 	}
 	}
 
 
 	platform_set_drvdata(pdev, s5p_ehci);
 	platform_set_drvdata(pdev, s5p_ehci);
 
 
 	return 0;
 	return 0;
 
 
-fail:
-	iounmap(hcd->regs);
 fail_io:
 fail_io:
 	clk_disable(s5p_ehci->clk);
 	clk_disable(s5p_ehci->clk);
 fail_clken:
 fail_clken:
 	clk_put(s5p_ehci->clk);
 	clk_put(s5p_ehci->clk);
 fail_clk:
 fail_clk:
 	usb_put_hcd(hcd);
 	usb_put_hcd(hcd);
-fail_hcd:
-	kfree(s5p_ehci);
 	return err;
 	return err;
 }
 }
 
 
@@ -182,13 +168,10 @@ static int __devexit s5p_ehci_remove(struct platform_device *pdev)
 	if (pdata && pdata->phy_exit)
 	if (pdata && pdata->phy_exit)
 		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 
 
-	iounmap(hcd->regs);
-
 	clk_disable(s5p_ehci->clk);
 	clk_disable(s5p_ehci->clk);
 	clk_put(s5p_ehci->clk);
 	clk_put(s5p_ehci->clk);
 
 
 	usb_put_hcd(hcd);
 	usb_put_hcd(hcd);
-	kfree(s5p_ehci);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -207,27 +190,12 @@ static int s5p_ehci_suspend(struct device *dev)
 {
 {
 	struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
 	struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
 	struct usb_hcd *hcd = s5p_ehci->hcd;
 	struct usb_hcd *hcd = s5p_ehci->hcd;
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	bool do_wakeup = device_may_wakeup(dev);
 	struct platform_device *pdev = to_platform_device(dev);
 	struct platform_device *pdev = to_platform_device(dev);
 	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
 	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
-	unsigned long flags;
-	int rc = 0;
-
-	if (time_before(jiffies, ehci->next_statechange))
-		msleep(20);
+	int rc;
 
 
-	/*
-	 * Root hub was already suspended. Disable irq emission and
-	 * mark HW unaccessible.  The PM and USB cores make sure that
-	 * the root hub is either suspended or stopped.
-	 */
-	ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
-	spin_lock_irqsave(&ehci->lock, flags);
-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
-	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
-
-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	spin_unlock_irqrestore(&ehci->lock, flags);
+	rc = ehci_suspend(hcd, do_wakeup);
 
 
 	if (pdata && pdata->phy_exit)
 	if (pdata && pdata->phy_exit)
 		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
@@ -241,7 +209,6 @@ static int s5p_ehci_resume(struct device *dev)
 {
 {
 	struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
 	struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
 	struct usb_hcd *hcd = s5p_ehci->hcd;
 	struct usb_hcd *hcd = s5p_ehci->hcd;
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	struct platform_device *pdev = to_platform_device(dev);
 	struct platform_device *pdev = to_platform_device(dev);
 	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
 	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
 
 
@@ -253,44 +220,7 @@ static int s5p_ehci_resume(struct device *dev)
 	/* DMA burst Enable */
 	/* DMA burst Enable */
 	writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
 	writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
 
 
-	if (time_before(jiffies, ehci->next_statechange))
-		msleep(100);
-
-	/* Mark hardware accessible again as we are out of D3 state by now */
-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
-		int	mask = INTR_MASK;
-
-		ehci_prepare_ports_for_controller_resume(ehci);
-		if (!hcd->self.root_hub->do_remote_wakeup)
-			mask &= ~STS_PCD;
-		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
-		ehci_readl(ehci, &ehci->regs->intr_enable);
-		return 0;
-	}
-
-	usb_root_hub_lost_power(hcd->self.root_hub);
-
-	(void) ehci_halt(ehci);
-	(void) ehci_reset(ehci);
-
-	/* emptying the schedule aborts any urbs */
-	spin_lock_irq(&ehci->lock);
-	if (ehci->reclaim)
-		end_unlink_async(ehci);
-	ehci_work(ehci);
-	spin_unlock_irq(&ehci->lock);
-
-	ehci_writel(ehci, ehci->command, &ehci->regs->command);
-	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
-	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
-
-	/* here we "know" root ports should always stay powered */
-	ehci_port_power(ehci, 1);
-
-	ehci->rh_state = EHCI_RH_SUSPENDED;
-
+	ehci_resume(hcd, false);
 	return 0;
 	return 0;
 }
 }
 #else
 #else

+ 3 - 71
drivers/usb/host/ehci-sead3.c

@@ -160,84 +160,16 @@ static int ehci_hcd_sead3_drv_remove(struct platform_device *pdev)
 static int ehci_hcd_sead3_drv_suspend(struct device *dev)
 static int ehci_hcd_sead3_drv_suspend(struct device *dev)
 {
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	unsigned long flags;
-	int rc = 0;
-
-	if (time_before(jiffies, ehci->next_statechange))
-		msleep(20);
-
-	/* Root hub was already suspended. Disable irq emission and
-	 * mark HW unaccessible.  The PM and USB cores make sure that
-	 * the root hub is either suspended or stopped.
-	 */
-	ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
-	spin_lock_irqsave(&ehci->lock, flags);
-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
-	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
-
-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	spin_unlock_irqrestore(&ehci->lock, flags);
+	bool do_wakeup = device_may_wakeup(dev);
 
 
-	/* could save FLADJ in case of Vaux power loss
-	 * ... we'd only use it to handle clock skew
-	 */
-
-	return rc;
+	return ehci_suspend(hcd, do_wakeup);
 }
 }
 
 
 static int ehci_hcd_sead3_drv_resume(struct device *dev)
 static int ehci_hcd_sead3_drv_resume(struct device *dev)
 {
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-
-	/* maybe restore FLADJ. */
-
-	if (time_before(jiffies, ehci->next_statechange))
-		msleep(100);
-
-	/* Mark hardware accessible again as we are out of D3 state by now */
-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-	/* If CF is still set, we maintained PCI Vaux power.
-	 * Just undo the effect of ehci_pci_suspend().
-	 */
-	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
-		int	mask = INTR_MASK;
-
-		ehci_prepare_ports_for_controller_resume(ehci);
-		if (!hcd->self.root_hub->do_remote_wakeup)
-			mask &= ~STS_PCD;
-		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
-		ehci_readl(ehci, &ehci->regs->intr_enable);
-		return 0;
-	}
-
-	ehci_dbg(ehci, "lost power, restarting\n");
-	usb_root_hub_lost_power(hcd->self.root_hub);
-
-	/* Else reset, to cope with power loss or flush-to-storage
-	 * style "resume" having let BIOS kick in during reboot.
-	 */
-	(void) ehci_halt(ehci);
-	(void) ehci_reset(ehci);
-
-	/* emptying the schedule aborts any urbs */
-	spin_lock_irq(&ehci->lock);
-	if (ehci->reclaim)
-		end_unlink_async(ehci);
-	ehci_work(ehci);
-	spin_unlock_irq(&ehci->lock);
-
-	ehci_writel(ehci, ehci->command, &ehci->regs->command);
-	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
-	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
-
-	/* here we "know" root ports should always stay powered */
-	ehci_port_power(ehci, 1);
-
-	ehci->rh_state = EHCI_RH_SUSPENDED;
 
 
+	ehci_resume(hcd, false);
 	return 0;
 	return 0;
 }
 }
 
 

+ 1 - 15
drivers/usb/host/ehci-sh.c

@@ -24,25 +24,11 @@ static int ehci_sh_reset(struct usb_hcd *hcd)
 	int ret;
 	int ret;
 
 
 	ehci->caps = hcd->regs;
 	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
-		&ehci->caps->hc_capbase));
 
 
-	dbg_hcs_params(ehci, "reset");
-	dbg_hcc_params(ehci, "reset");
-
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
-	ret = ehci_halt(ehci);
-	if (unlikely(ret))
-		return ret;
-
-	ret = ehci_init(hcd);
+	ret = ehci_setup(hcd);
 	if (unlikely(ret))
 	if (unlikely(ret))
 		return ret;
 		return ret;
 
 
-	ehci->sbrn = 0x20;
-
-	ehci_reset(ehci);
 	ehci_port_power(ehci, 0);
 	ehci_port_power(ehci, 0);
 
 
 	return ret;
 	return ret;

+ 4 - 67
drivers/usb/host/ehci-spear.c

@@ -41,19 +41,11 @@ static int ehci_spear_setup(struct usb_hcd *hcd)
 
 
 	/* registers start at offset 0x0 */
 	/* registers start at offset 0x0 */
 	ehci->caps = hcd->regs;
 	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
-				&ehci->caps->hc_capbase));
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-	retval = ehci_halt(ehci);
-	if (retval)
-		return retval;
 
 
-	retval = ehci_init(hcd);
+	retval = ehci_setup(hcd);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 
-	ehci_reset(ehci);
 	ehci_port_power(ehci, 0);
 	ehci_port_power(ehci, 0);
 
 
 	return retval;
 	return retval;
@@ -97,71 +89,16 @@ static const struct hc_driver ehci_spear_hc_driver = {
 static int ehci_spear_drv_suspend(struct device *dev)
 static int ehci_spear_drv_suspend(struct device *dev)
 {
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	unsigned long flags;
-	int rc = 0;
+	bool do_wakeup = device_may_wakeup(dev);
 
 
-	if (time_before(jiffies, ehci->next_statechange))
-		msleep(10);
-
-	/*
-	 * Root hub was already suspended. Disable irq emission and mark HW
-	 * unaccessible. The PM and USB cores make sure that the root hub is
-	 * either suspended or stopped.
-	 */
-	spin_lock_irqsave(&ehci->lock, flags);
-	ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
-	ehci_readl(ehci, &ehci->regs->intr_enable);
-	spin_unlock_irqrestore(&ehci->lock, flags);
-
-	return rc;
+	return ehci_suspend(hcd, do_wakeup);
 }
 }
 
 
 static int ehci_spear_drv_resume(struct device *dev)
 static int ehci_spear_drv_resume(struct device *dev)
 {
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-
-	if (time_before(jiffies, ehci->next_statechange))
-		msleep(100);
-
-	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
-		int mask = INTR_MASK;
-
-		ehci_prepare_ports_for_controller_resume(ehci);
-
-		if (!hcd->self.root_hub->do_remote_wakeup)
-			mask &= ~STS_PCD;
-
-		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
-		ehci_readl(ehci, &ehci->regs->intr_enable);
-		return 0;
-	}
-
-	usb_root_hub_lost_power(hcd->self.root_hub);
-
-	/*
-	 * Else reset, to cope with power loss or flush-to-storage style
-	 * "resume" having let BIOS kick in during reboot.
-	 */
-	ehci_halt(ehci);
-	ehci_reset(ehci);
-
-	/* emptying the schedule aborts any urbs */
-	spin_lock_irq(&ehci->lock);
-	if (ehci->reclaim)
-		end_unlink_async(ehci);
-
-	ehci_work(ehci);
-	spin_unlock_irq(&ehci->lock);
-
-	ehci_writel(ehci, ehci->command, &ehci->regs->command);
-	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
-	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
 
 
-	/* here we "know" root ports should always stay powered */
-	ehci_port_power(ehci, 1);
+	ehci_resume(hcd, false);
 	return 0;
 	return 0;
 }
 }
 #endif /* CONFIG_PM */
 #endif /* CONFIG_PM */

+ 8 - 23
drivers/usb/host/ehci-tegra.c

@@ -17,6 +17,7 @@
  */
  */
 
 
 #include <linux/clk.h>
 #include <linux/clk.h>
+#include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/tegra_usb.h>
 #include <linux/platform_data/tegra_usb.h>
 #include <linux/irq.h>
 #include <linux/irq.h>
@@ -280,30 +281,14 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
 
 
 	/* EHCI registers start at offset 0x100 */
 	/* EHCI registers start at offset 0x100 */
 	ehci->caps = hcd->regs + 0x100;
 	ehci->caps = hcd->regs + 0x100;
-	ehci->regs = hcd->regs + 0x100 +
-		HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
-
-	dbg_hcs_params(ehci, "reset");
-	dbg_hcc_params(ehci, "reset");
-
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = readl(&ehci->caps->hcs_params);
 
 
 	/* switch to host mode */
 	/* switch to host mode */
 	hcd->has_tt = 1;
 	hcd->has_tt = 1;
-	ehci_reset(ehci);
 
 
-	retval = ehci_halt(ehci);
+	retval = ehci_setup(ehci);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 
-	/* data structure init */
-	retval = ehci_init(hcd);
-	if (retval)
-		return retval;
-
-	ehci->sbrn = 0x20;
-
 	ehci_port_power(ehci, 1);
 	ehci_port_power(ehci, 1);
 	return retval;
 	return retval;
 }
 }
@@ -749,8 +734,8 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 
 
 #ifdef CONFIG_USB_OTG_UTILS
 #ifdef CONFIG_USB_OTG_UTILS
 	if (pdata->operating_mode == TEGRA_USB_OTG) {
 	if (pdata->operating_mode == TEGRA_USB_OTG) {
-		tegra->transceiver = usb_get_transceiver();
-		if (tegra->transceiver)
+		tegra->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+		if (!IS_ERR_OR_NULL(tegra->transceiver))
 			otg_set_host(tegra->transceiver->otg, &hcd->self);
 			otg_set_host(tegra->transceiver->otg, &hcd->self);
 	}
 	}
 #endif
 #endif
@@ -773,9 +758,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 
 
 fail:
 fail:
 #ifdef CONFIG_USB_OTG_UTILS
 #ifdef CONFIG_USB_OTG_UTILS
-	if (tegra->transceiver) {
+	if (!IS_ERR_OR_NULL(tegra->transceiver)) {
 		otg_set_host(tegra->transceiver->otg, NULL);
 		otg_set_host(tegra->transceiver->otg, NULL);
-		usb_put_transceiver(tegra->transceiver);
+		usb_put_phy(tegra->transceiver);
 	}
 	}
 #endif
 #endif
 	tegra_usb_phy_close(tegra->phy);
 	tegra_usb_phy_close(tegra->phy);
@@ -808,9 +793,9 @@ static int tegra_ehci_remove(struct platform_device *pdev)
 	pm_runtime_put_noidle(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
 
 
 #ifdef CONFIG_USB_OTG_UTILS
 #ifdef CONFIG_USB_OTG_UTILS
-	if (tegra->transceiver) {
+	if (!IS_ERR_OR_NULL(tegra->transceiver)) {
 		otg_set_host(tegra->transceiver->otg, NULL);
 		otg_set_host(tegra->transceiver->otg, NULL);
-		usb_put_transceiver(tegra->transceiver);
+		usb_put_phy(tegra->transceiver);
 	}
 	}
 #endif
 #endif
 
 

+ 1 - 13
drivers/usb/host/ehci-vt8500.c

@@ -48,7 +48,7 @@ static const struct hc_driver vt8500_ehci_hc_driver = {
 	/*
 	/*
 	 * basic lifecycle operations
 	 * basic lifecycle operations
 	 */
 	 */
-	.reset			= ehci_init,
+	.reset			= ehci_setup,
 	.start			= ehci_run,
 	.start			= ehci_run,
 	.stop			= ehci_stop,
 	.stop			= ehci_stop,
 	.shutdown		= ehci_shutdown,
 	.shutdown		= ehci_shutdown,
@@ -121,18 +121,6 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev)
 
 
 	ehci = hcd_to_ehci(hcd);
 	ehci = hcd_to_ehci(hcd);
 	ehci->caps = hcd->regs;
 	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs +
-		HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
-
-	dbg_hcs_params(ehci, "reset");
-	dbg_hcc_params(ehci, "reset");
-
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = readl(&ehci->caps->hcs_params);
-
-	ehci_port_power(ehci, 1);
-
-	ehci_reset(ehci);
 
 
 	ret = usb_add_hcd(hcd, pdev->resource[1].start,
 	ret = usb_add_hcd(hcd, pdev->resource[1].start,
 			  IRQF_SHARED);
 			  IRQF_SHARED);

+ 1 - 8
drivers/usb/host/ehci-w90x900.c

@@ -71,21 +71,14 @@ static int __devinit usb_w90x900_probe(const struct hc_driver *driver,
 	val |= ENPHY;
 	val |= ENPHY;
 	__raw_writel(val, ehci->regs+PHY1_CTR);
 	__raw_writel(val, ehci->regs+PHY1_CTR);
 
 
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-	ehci->sbrn = 0x20;
-
 	irq = platform_get_irq(pdev, 0);
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
 	if (irq < 0)
 		goto err4;
 		goto err4;
 
 
-	ehci_reset(ehci);
-
 	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (retval != 0)
 	if (retval != 0)
 		goto err4;
 		goto err4;
 
 
-	ehci_writel(ehci, 1, &ehci->regs->configured_flag);
-
 	return retval;
 	return retval;
 err4:
 err4:
 	iounmap(hcd->regs);
 	iounmap(hcd->regs);
@@ -120,7 +113,7 @@ static const struct hc_driver ehci_w90x900_hc_driver = {
 	/*
 	/*
 	 * basic lifecycle operations
 	 * basic lifecycle operations
 	 */
 	 */
-	.reset = ehci_init,
+	.reset = ehci_setup,
 	.start = ehci_run,
 	.start = ehci_run,
 
 
 	.stop = ehci_stop,
 	.stop = ehci_stop,

+ 1 - 30
drivers/usb/host/ehci-xilinx-of.c

@@ -31,30 +31,6 @@
 #include <linux/of_platform.h>
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include <linux/of_address.h>
 
 
-/**
- * ehci_xilinx_of_setup - Initialize the device for ehci_reset()
- * @hcd:	Pointer to the usb_hcd device to which the host controller bound
- *
- * called during probe() after chip reset completes.
- */
-static int ehci_xilinx_of_setup(struct usb_hcd *hcd)
-{
-	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
-	int		retval;
-
-	retval = ehci_halt(ehci);
-	if (retval)
-		return retval;
-
-	retval = ehci_init(hcd);
-	if (retval)
-		return retval;
-
-	ehci->sbrn = 0x20;
-
-	return ehci_reset(ehci);
-}
-
 /**
 /**
  * ehci_xilinx_port_handed_over - hand the port out if failed to enable it
  * ehci_xilinx_port_handed_over - hand the port out if failed to enable it
  * @hcd:	Pointer to the usb_hcd device to which the host controller bound
  * @hcd:	Pointer to the usb_hcd device to which the host controller bound
@@ -107,7 +83,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = {
 	/*
 	/*
 	 * basic lifecycle operations
 	 * basic lifecycle operations
 	 */
 	 */
-	.reset			= ehci_xilinx_of_setup,
+	.reset			= ehci_setup,
 	.start			= ehci_run,
 	.start			= ehci_run,
 	.stop			= ehci_stop,
 	.stop			= ehci_stop,
 	.shutdown		= ehci_shutdown,
 	.shutdown		= ehci_shutdown,
@@ -219,11 +195,6 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op)
 	/* Debug registers are at the first 0x100 region
 	/* Debug registers are at the first 0x100 region
 	 */
 	 */
 	ehci->caps = hcd->regs + 0x100;
 	ehci->caps = hcd->regs + 0x100;
-	ehci->regs = hcd->regs + 0x100 +
-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
 
 	rv = usb_add_hcd(hcd, irq, 0);
 	rv = usb_add_hcd(hcd, irq, 0);
 	if (rv == 0)
 	if (rv == 0)

+ 1 - 20
drivers/usb/host/ehci-xls.c

@@ -14,30 +14,11 @@
 
 
 static int ehci_xls_setup(struct usb_hcd *hcd)
 static int ehci_xls_setup(struct usb_hcd *hcd)
 {
 {
-	int	retval;
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 
 
 	ehci->caps = hcd->regs;
 	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs +
-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-	dbg_hcs_params(ehci, "reset");
-	dbg_hcc_params(ehci, "reset");
 
 
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
-	retval = ehci_halt(ehci);
-	if (retval)
-		return retval;
-
-	/* data structure init */
-	retval = ehci_init(hcd);
-	if (retval)
-		return retval;
-
-	ehci_reset(ehci);
-
-	return retval;
+	return ehci_setup(ehci);
 }
 }
 
 
 int ehci_xls_probe_internal(const struct hc_driver *driver,
 int ehci_xls_probe_internal(const struct hc_driver *driver,

+ 0 - 4
drivers/usb/host/ehci.h

@@ -175,10 +175,6 @@ struct ehci_hcd {			/* one per controller */
 #ifdef DEBUG
 #ifdef DEBUG
 	struct dentry		*debug_dir;
 	struct dentry		*debug_dir;
 #endif
 #endif
-	/*
-	 * OTG controllers and transceivers need software interaction
-	 */
-	struct usb_phy	*transceiver;
 };
 };
 
 
 /* convert between an HCD pointer and the corresponding EHCI_HCD */
 /* convert between an HCD pointer and the corresponding EHCI_HCD */

+ 6 - 6
drivers/usb/host/fhci-dbg.c

@@ -41,7 +41,7 @@ void fhci_dbg_isr(struct fhci_hcd *fhci, int usb_er)
 static int fhci_dfs_regs_show(struct seq_file *s, void *v)
 static int fhci_dfs_regs_show(struct seq_file *s, void *v)
 {
 {
 	struct fhci_hcd *fhci = s->private;
 	struct fhci_hcd *fhci = s->private;
-	struct fhci_regs __iomem *regs = fhci->regs;
+	struct qe_usb_ctlr __iomem *regs = fhci->regs;
 
 
 	seq_printf(s,
 	seq_printf(s,
 		"mode: 0x%x\n" "addr: 0x%x\n"
 		"mode: 0x%x\n" "addr: 0x%x\n"
@@ -50,11 +50,11 @@ static int fhci_dfs_regs_show(struct seq_file *s, void *v)
 		"status: 0x%x\n" "SOF timer: %d\n"
 		"status: 0x%x\n" "SOF timer: %d\n"
 		"frame number: %d\n"
 		"frame number: %d\n"
 		"lines status: 0x%x\n",
 		"lines status: 0x%x\n",
-		in_8(&regs->usb_mod), in_8(&regs->usb_addr),
-		in_8(&regs->usb_comm), in_be16(&regs->usb_ep[0]),
-		in_be16(&regs->usb_event), in_be16(&regs->usb_mask),
-		in_8(&regs->usb_status), in_be16(&regs->usb_sof_tmr),
-		in_be16(&regs->usb_frame_num),
+		in_8(&regs->usb_usmod), in_8(&regs->usb_usadr),
+		in_8(&regs->usb_uscom), in_be16(&regs->usb_usep[0]),
+		in_be16(&regs->usb_usber), in_be16(&regs->usb_usbmr),
+		in_8(&regs->usb_usbs), in_be16(&regs->usb_ussft),
+		in_be16(&regs->usb_usfrn),
 		fhci_ioports_check_bus_state(fhci));
 		fhci_ioports_check_bus_state(fhci));
 
 
 	return 0;
 	return 0;

+ 16 - 16
drivers/usb/host/fhci-hcd.c

@@ -40,8 +40,8 @@ void fhci_start_sof_timer(struct fhci_hcd *fhci)
 	/* clear frame_n */
 	/* clear frame_n */
 	out_be16(&fhci->pram->frame_num, 0);
 	out_be16(&fhci->pram->frame_num, 0);
 
 
-	out_be16(&fhci->regs->usb_sof_tmr, 0);
-	setbits8(&fhci->regs->usb_mod, USB_MODE_SFTE);
+	out_be16(&fhci->regs->usb_ussft, 0);
+	setbits8(&fhci->regs->usb_usmod, USB_MODE_SFTE);
 
 
 	fhci_dbg(fhci, "<- %s\n", __func__);
 	fhci_dbg(fhci, "<- %s\n", __func__);
 }
 }
@@ -50,7 +50,7 @@ void fhci_stop_sof_timer(struct fhci_hcd *fhci)
 {
 {
 	fhci_dbg(fhci, "-> %s\n", __func__);
 	fhci_dbg(fhci, "-> %s\n", __func__);
 
 
-	clrbits8(&fhci->regs->usb_mod, USB_MODE_SFTE);
+	clrbits8(&fhci->regs->usb_usmod, USB_MODE_SFTE);
 	gtm_stop_timer16(fhci->timer);
 	gtm_stop_timer16(fhci->timer);
 
 
 	fhci_dbg(fhci, "<- %s\n", __func__);
 	fhci_dbg(fhci, "<- %s\n", __func__);
@@ -58,7 +58,7 @@ void fhci_stop_sof_timer(struct fhci_hcd *fhci)
 
 
 u16 fhci_get_sof_timer_count(struct fhci_usb *usb)
 u16 fhci_get_sof_timer_count(struct fhci_usb *usb)
 {
 {
-	return be16_to_cpu(in_be16(&usb->fhci->regs->usb_sof_tmr) / 12);
+	return be16_to_cpu(in_be16(&usb->fhci->regs->usb_ussft) / 12);
 }
 }
 
 
 /* initialize the endpoint zero */
 /* initialize the endpoint zero */
@@ -88,8 +88,8 @@ void fhci_usb_enable_interrupt(struct fhci_usb *usb)
 		enable_irq(fhci_to_hcd(fhci)->irq);
 		enable_irq(fhci_to_hcd(fhci)->irq);
 
 
 		/* initialize the event register and mask register */
 		/* initialize the event register and mask register */
-		out_be16(&usb->fhci->regs->usb_event, 0xffff);
-		out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk);
+		out_be16(&usb->fhci->regs->usb_usber, 0xffff);
+		out_be16(&usb->fhci->regs->usb_usbmr, usb->saved_msk);
 
 
 		/* enable the timer interrupts */
 		/* enable the timer interrupts */
 		enable_irq(fhci->timer->irq);
 		enable_irq(fhci->timer->irq);
@@ -109,7 +109,7 @@ void fhci_usb_disable_interrupt(struct fhci_usb *usb)
 
 
 		/* disable the usb interrupt */
 		/* disable the usb interrupt */
 		disable_irq_nosync(fhci_to_hcd(fhci)->irq);
 		disable_irq_nosync(fhci_to_hcd(fhci)->irq);
-		out_be16(&usb->fhci->regs->usb_mask, 0);
+		out_be16(&usb->fhci->regs->usb_usbmr, 0);
 	}
 	}
 	usb->intr_nesting_cnt++;
 	usb->intr_nesting_cnt++;
 }
 }
@@ -119,9 +119,9 @@ static u32 fhci_usb_enable(struct fhci_hcd *fhci)
 {
 {
 	struct fhci_usb *usb = fhci->usb_lld;
 	struct fhci_usb *usb = fhci->usb_lld;
 
 
-	out_be16(&usb->fhci->regs->usb_event, 0xffff);
-	out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk);
-	setbits8(&usb->fhci->regs->usb_mod, USB_MODE_EN);
+	out_be16(&usb->fhci->regs->usb_usber, 0xffff);
+	out_be16(&usb->fhci->regs->usb_usbmr, usb->saved_msk);
+	setbits8(&usb->fhci->regs->usb_usmod, USB_MODE_EN);
 
 
 	mdelay(100);
 	mdelay(100);
 
 
@@ -141,7 +141,7 @@ static u32 fhci_usb_disable(struct fhci_hcd *fhci)
 			usb->port_status == FHCI_PORT_LOW)
 			usb->port_status == FHCI_PORT_LOW)
 		fhci_device_disconnected_interrupt(fhci);
 		fhci_device_disconnected_interrupt(fhci);
 
 
-	clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_EN);
+	clrbits8(&usb->fhci->regs->usb_usmod, USB_MODE_EN);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -285,13 +285,13 @@ static int fhci_usb_init(struct fhci_hcd *fhci)
 			  USB_E_IDLE_MASK |
 			  USB_E_IDLE_MASK |
 			  USB_E_RESET_MASK | USB_E_SFT_MASK | USB_E_MSF_MASK);
 			  USB_E_RESET_MASK | USB_E_SFT_MASK | USB_E_MSF_MASK);
 
 
-	out_8(&usb->fhci->regs->usb_mod, USB_MODE_HOST | USB_MODE_EN);
+	out_8(&usb->fhci->regs->usb_usmod, USB_MODE_HOST | USB_MODE_EN);
 
 
 	/* clearing the mask register */
 	/* clearing the mask register */
-	out_be16(&usb->fhci->regs->usb_mask, 0);
+	out_be16(&usb->fhci->regs->usb_usbmr, 0);
 
 
 	/* initialing the event register */
 	/* initialing the event register */
-	out_be16(&usb->fhci->regs->usb_event, 0xffff);
+	out_be16(&usb->fhci->regs->usb_usber, 0xffff);
 
 
 	if (endpoint_zero_init(usb, DEFAULT_DATA_MEM, DEFAULT_RING_LEN) != 0) {
 	if (endpoint_zero_init(usb, DEFAULT_DATA_MEM, DEFAULT_RING_LEN) != 0) {
 		fhci_usb_free(usb);
 		fhci_usb_free(usb);
@@ -745,8 +745,8 @@ static int __devinit of_fhci_probe(struct platform_device *ofdev)
 	}
 	}
 
 
 	/* Clear and disable any pending interrupts. */
 	/* Clear and disable any pending interrupts. */
-	out_be16(&fhci->regs->usb_event, 0xffff);
-	out_be16(&fhci->regs->usb_mask, 0);
+	out_be16(&fhci->regs->usb_usber, 0xffff);
+	out_be16(&fhci->regs->usb_usbmr, 0);
 
 
 	ret = usb_add_hcd(hcd, usb_irq, 0);
 	ret = usb_add_hcd(hcd, usb_irq, 0);
 	if (ret < 0)
 	if (ret < 0)

+ 8 - 8
drivers/usb/host/fhci-hub.c

@@ -97,7 +97,7 @@ void fhci_port_disable(struct fhci_hcd *fhci)
 
 
 	/* Enable IDLE since we want to know if something comes along */
 	/* Enable IDLE since we want to know if something comes along */
 	usb->saved_msk |= USB_E_IDLE_MASK;
 	usb->saved_msk |= USB_E_IDLE_MASK;
-	out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk);
+	out_be16(&usb->fhci->regs->usb_usbmr, usb->saved_msk);
 
 
 	/* check if during the disconnection process attached new device */
 	/* check if during the disconnection process attached new device */
 	if (port_status == FHCI_PORT_WAITING)
 	if (port_status == FHCI_PORT_WAITING)
@@ -158,21 +158,21 @@ void fhci_port_reset(void *lld)
 
 
 	fhci_stop_sof_timer(fhci);
 	fhci_stop_sof_timer(fhci);
 	/* disable the USB controller */
 	/* disable the USB controller */
-	mode = in_8(&fhci->regs->usb_mod);
-	out_8(&fhci->regs->usb_mod, mode & (~USB_MODE_EN));
+	mode = in_8(&fhci->regs->usb_usmod);
+	out_8(&fhci->regs->usb_usmod, mode & (~USB_MODE_EN));
 
 
 	/* disable idle interrupts */
 	/* disable idle interrupts */
-	mask = in_be16(&fhci->regs->usb_mask);
-	out_be16(&fhci->regs->usb_mask, mask & (~USB_E_IDLE_MASK));
+	mask = in_be16(&fhci->regs->usb_usbmr);
+	out_be16(&fhci->regs->usb_usbmr, mask & (~USB_E_IDLE_MASK));
 
 
 	fhci_io_port_generate_reset(fhci);
 	fhci_io_port_generate_reset(fhci);
 
 
 	/* enable interrupt on this endpoint */
 	/* enable interrupt on this endpoint */
-	out_be16(&fhci->regs->usb_mask, mask);
+	out_be16(&fhci->regs->usb_usbmr, mask);
 
 
 	/* enable the USB controller */
 	/* enable the USB controller */
-	mode = in_8(&fhci->regs->usb_mod);
-	out_8(&fhci->regs->usb_mod, mode | USB_MODE_EN);
+	mode = in_8(&fhci->regs->usb_usmod);
+	out_8(&fhci->regs->usb_usmod, mode | USB_MODE_EN);
 	fhci_start_sof_timer(fhci);
 	fhci_start_sof_timer(fhci);
 
 
 	fhci_dbg(fhci, "<- %s\n", __func__);
 	fhci_dbg(fhci, "<- %s\n", __func__);

+ 15 - 15
drivers/usb/host/fhci-sched.c

@@ -132,8 +132,8 @@ void fhci_flush_all_transmissions(struct fhci_usb *usb)
 	u8 mode;
 	u8 mode;
 	struct td *td;
 	struct td *td;
 
 
-	mode = in_8(&usb->fhci->regs->usb_mod);
-	clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_EN);
+	mode = in_8(&usb->fhci->regs->usb_usmod);
+	clrbits8(&usb->fhci->regs->usb_usmod, USB_MODE_EN);
 
 
 	fhci_flush_bds(usb);
 	fhci_flush_bds(usb);
 
 
@@ -147,9 +147,9 @@ void fhci_flush_all_transmissions(struct fhci_usb *usb)
 	usb->actual_frame->frame_status = FRAME_END_TRANSMISSION;
 	usb->actual_frame->frame_status = FRAME_END_TRANSMISSION;
 
 
 	/* reset the event register */
 	/* reset the event register */
-	out_be16(&usb->fhci->regs->usb_event, 0xffff);
+	out_be16(&usb->fhci->regs->usb_usber, 0xffff);
 	/* enable the USB controller */
 	/* enable the USB controller */
-	out_8(&usb->fhci->regs->usb_mod, mode | USB_MODE_EN);
+	out_8(&usb->fhci->regs->usb_usmod, mode | USB_MODE_EN);
 }
 }
 
 
 /*
 /*
@@ -414,7 +414,7 @@ static void sof_interrupt(struct fhci_hcd *fhci)
 			usb->port_status = FHCI_PORT_FULL;
 			usb->port_status = FHCI_PORT_FULL;
 		/* Disable IDLE */
 		/* Disable IDLE */
 		usb->saved_msk &= ~USB_E_IDLE_MASK;
 		usb->saved_msk &= ~USB_E_IDLE_MASK;
-		out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk);
+		out_be16(&usb->fhci->regs->usb_usbmr, usb->saved_msk);
 	}
 	}
 
 
 	gtm_set_exact_timer16(fhci->timer, usb->max_frame_usage, false);
 	gtm_set_exact_timer16(fhci->timer, usb->max_frame_usage, false);
@@ -433,14 +433,14 @@ void fhci_device_disconnected_interrupt(struct fhci_hcd *fhci)
 	fhci_dbg(fhci, "-> %s\n", __func__);
 	fhci_dbg(fhci, "-> %s\n", __func__);
 
 
 	fhci_usb_disable_interrupt(usb);
 	fhci_usb_disable_interrupt(usb);
-	clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_LSS);
+	clrbits8(&usb->fhci->regs->usb_usmod, USB_MODE_LSS);
 	usb->port_status = FHCI_PORT_DISABLED;
 	usb->port_status = FHCI_PORT_DISABLED;
 
 
 	fhci_stop_sof_timer(fhci);
 	fhci_stop_sof_timer(fhci);
 
 
 	/* Enable IDLE since we want to know if something comes along */
 	/* Enable IDLE since we want to know if something comes along */
 	usb->saved_msk |= USB_E_IDLE_MASK;
 	usb->saved_msk |= USB_E_IDLE_MASK;
-	out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk);
+	out_be16(&usb->fhci->regs->usb_usbmr, usb->saved_msk);
 
 
 	usb->vroot_hub->port.wPortStatus &= ~USB_PORT_STAT_CONNECTION;
 	usb->vroot_hub->port.wPortStatus &= ~USB_PORT_STAT_CONNECTION;
 	usb->vroot_hub->port.wPortChange |= USB_PORT_STAT_C_CONNECTION;
 	usb->vroot_hub->port.wPortChange |= USB_PORT_STAT_C_CONNECTION;
@@ -473,7 +473,7 @@ void fhci_device_connected_interrupt(struct fhci_hcd *fhci)
 		}
 		}
 
 
 		usb->port_status = FHCI_PORT_LOW;
 		usb->port_status = FHCI_PORT_LOW;
-		setbits8(&usb->fhci->regs->usb_mod, USB_MODE_LSS);
+		setbits8(&usb->fhci->regs->usb_usmod, USB_MODE_LSS);
 		usb->vroot_hub->port.wPortStatus |=
 		usb->vroot_hub->port.wPortStatus |=
 		    (USB_PORT_STAT_LOW_SPEED |
 		    (USB_PORT_STAT_LOW_SPEED |
 		     USB_PORT_STAT_CONNECTION);
 		     USB_PORT_STAT_CONNECTION);
@@ -491,7 +491,7 @@ void fhci_device_connected_interrupt(struct fhci_hcd *fhci)
 		}
 		}
 
 
 		usb->port_status = FHCI_PORT_FULL;
 		usb->port_status = FHCI_PORT_FULL;
-		clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_LSS);
+		clrbits8(&usb->fhci->regs->usb_usmod, USB_MODE_LSS);
 		usb->vroot_hub->port.wPortStatus &=
 		usb->vroot_hub->port.wPortStatus &=
 		    ~USB_PORT_STAT_LOW_SPEED;
 		    ~USB_PORT_STAT_LOW_SPEED;
 		usb->vroot_hub->port.wPortStatus |=
 		usb->vroot_hub->port.wPortStatus |=
@@ -535,7 +535,7 @@ static void abort_transmission(struct fhci_usb *usb)
 	/* issue stop Tx command */
 	/* issue stop Tx command */
 	qe_issue_cmd(QE_USB_STOP_TX, QE_CR_SUBBLOCK_USB, EP_ZERO, 0);
 	qe_issue_cmd(QE_USB_STOP_TX, QE_CR_SUBBLOCK_USB, EP_ZERO, 0);
 	/* flush Tx FIFOs */
 	/* flush Tx FIFOs */
-	out_8(&usb->fhci->regs->usb_comm, USB_CMD_FLUSH_FIFO | EP_ZERO);
+	out_8(&usb->fhci->regs->usb_uscom, USB_CMD_FLUSH_FIFO | EP_ZERO);
 	udelay(1000);
 	udelay(1000);
 	/* reset Tx BDs */
 	/* reset Tx BDs */
 	fhci_flush_bds(usb);
 	fhci_flush_bds(usb);
@@ -555,11 +555,11 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd)
 
 
 	usb = fhci->usb_lld;
 	usb = fhci->usb_lld;
 
 
-	usb_er |= in_be16(&usb->fhci->regs->usb_event) &
-		  in_be16(&usb->fhci->regs->usb_mask);
+	usb_er |= in_be16(&usb->fhci->regs->usb_usber) &
+		  in_be16(&usb->fhci->regs->usb_usbmr);
 
 
 	/* clear event bits for next time */
 	/* clear event bits for next time */
-	out_be16(&usb->fhci->regs->usb_event, usb_er);
+	out_be16(&usb->fhci->regs->usb_usber, usb_er);
 
 
 	fhci_dbg_isr(fhci, usb_er);
 	fhci_dbg_isr(fhci, usb_er);
 
 
@@ -573,7 +573,7 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd)
 
 
 			/* Turn on IDLE since we want to disconnect */
 			/* Turn on IDLE since we want to disconnect */
 			usb->saved_msk |= USB_E_IDLE_MASK;
 			usb->saved_msk |= USB_E_IDLE_MASK;
-			out_be16(&usb->fhci->regs->usb_event,
+			out_be16(&usb->fhci->regs->usb_usber,
 				 usb->saved_msk);
 				 usb->saved_msk);
 		} else if (usb->port_status == FHCI_PORT_DISABLED) {
 		} else if (usb->port_status == FHCI_PORT_DISABLED) {
 			if (fhci_ioports_check_bus_state(fhci) == 1)
 			if (fhci_ioports_check_bus_state(fhci) == 1)
@@ -611,7 +611,7 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd)
 			/* XXX usb->port_status = FHCI_PORT_WAITING; */
 			/* XXX usb->port_status = FHCI_PORT_WAITING; */
 			/* Disable IDLE */
 			/* Disable IDLE */
 			usb->saved_msk &= ~USB_E_IDLE_MASK;
 			usb->saved_msk &= ~USB_E_IDLE_MASK;
-			out_be16(&usb->fhci->regs->usb_mask,
+			out_be16(&usb->fhci->regs->usb_usbmr,
 				 usb->saved_msk);
 				 usb->saved_msk);
 		} else {
 		} else {
 			fhci_dbg_isr(fhci, -1);
 			fhci_dbg_isr(fhci, -1);

+ 7 - 7
drivers/usb/host/fhci-tds.c

@@ -249,7 +249,7 @@ void fhci_init_ep_registers(struct fhci_usb *usb, struct endpoint *ep,
 	u8 rt;
 	u8 rt;
 
 
 	/* set the endpoint registers according to the endpoint */
 	/* set the endpoint registers according to the endpoint */
-	out_be16(&usb->fhci->regs->usb_ep[0],
+	out_be16(&usb->fhci->regs->usb_usep[0],
 		 USB_TRANS_CTR | USB_EP_MF | USB_EP_RTE);
 		 USB_TRANS_CTR | USB_EP_MF | USB_EP_RTE);
 	out_be16(&usb->fhci->pram->ep_ptr[0],
 	out_be16(&usb->fhci->pram->ep_ptr[0],
 		 cpm_muram_offset(ep->ep_pram_ptr));
 		 cpm_muram_offset(ep->ep_pram_ptr));
@@ -463,7 +463,7 @@ u32 fhci_host_transaction(struct fhci_usb *usb,
 	cq_put(&ep->conf_frame_Q, pkt);
 	cq_put(&ep->conf_frame_Q, pkt);
 
 
 	if (cq_howmany(&ep->conf_frame_Q) == 1)
 	if (cq_howmany(&ep->conf_frame_Q) == 1)
-		out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO);
+		out_8(&usb->fhci->regs->usb_uscom, USB_CMD_STR_FIFO);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -535,8 +535,8 @@ void fhci_flush_actual_frame(struct fhci_usb *usb)
 	struct endpoint *ep = usb->ep0;
 	struct endpoint *ep = usb->ep0;
 
 
 	/* disable the USB controller */
 	/* disable the USB controller */
-	mode = in_8(&usb->fhci->regs->usb_mod);
-	out_8(&usb->fhci->regs->usb_mod, mode & ~USB_MODE_EN);
+	mode = in_8(&usb->fhci->regs->usb_usmod);
+	out_8(&usb->fhci->regs->usb_usmod, mode & ~USB_MODE_EN);
 
 
 	tb_ptr = in_be16(&ep->ep_pram_ptr->tx_bd_ptr);
 	tb_ptr = in_be16(&ep->ep_pram_ptr->tx_bd_ptr);
 	td = cpm_muram_addr(tb_ptr);
 	td = cpm_muram_addr(tb_ptr);
@@ -571,9 +571,9 @@ void fhci_flush_actual_frame(struct fhci_usb *usb)
 	usb->actual_frame->frame_status = FRAME_TIMER_END_TRANSMISSION;
 	usb->actual_frame->frame_status = FRAME_TIMER_END_TRANSMISSION;
 
 
 	/* reset the event register */
 	/* reset the event register */
-	out_be16(&usb->fhci->regs->usb_event, 0xffff);
+	out_be16(&usb->fhci->regs->usb_usber, 0xffff);
 	/* enable the USB controller */
 	/* enable the USB controller */
-	out_8(&usb->fhci->regs->usb_mod, mode | USB_MODE_EN);
+	out_8(&usb->fhci->regs->usb_usmod, mode | USB_MODE_EN);
 }
 }
 
 
 /* handles Tx confirm and Tx error interrupt */
 /* handles Tx confirm and Tx error interrupt */
@@ -613,7 +613,7 @@ void fhci_host_transmit_actual_frame(struct fhci_usb *usb)
 
 
 		/* start transmit only if we have something in the TDs */
 		/* start transmit only if we have something in the TDs */
 		if (in_be16(&td->status) & TD_R)
 		if (in_be16(&td->status) & TD_R)
-			out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO);
+			out_8(&usb->fhci->regs->usb_uscom, USB_CMD_STR_FIFO);
 
 
 		if (in_be32(&ep->conf_td->buf_ptr) == DUMMY_BD_BUFFER) {
 		if (in_be32(&ep->conf_td->buf_ptr) == DUMMY_BD_BUFFER) {
 			out_be32(&old_td->buf_ptr, 0);
 			out_be32(&old_td->buf_ptr, 0);

+ 2 - 20
drivers/usb/host/fhci.h

@@ -28,6 +28,7 @@
 #include <linux/usb.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
 #include <linux/usb/hcd.h>
 #include <asm/qe.h>
 #include <asm/qe.h>
+#include <asm/immap_qe.h>
 
 
 #define USB_CLOCK	48000000
 #define USB_CLOCK	48000000
 
 
@@ -173,25 +174,6 @@
 #define USB_E_TXB_MASK		0x0002
 #define USB_E_TXB_MASK		0x0002
 #define USB_E_RXB_MASK		0x0001
 #define USB_E_RXB_MASK		0x0001
 
 
-/* Freescale USB Host controller registers */
-struct fhci_regs {
-	u8 usb_mod;		/* mode register */
-	u8 usb_addr;		/* address register */
-	u8 usb_comm;		/* command register */
-	u8 reserved1[1];
-	__be16 usb_ep[4];	/* endpoint register */
-	u8 reserved2[4];
-	__be16 usb_event;	/* event register */
-	u8 reserved3[2];
-	__be16 usb_mask;	/* mask register */
-	u8 reserved4[1];
-	u8 usb_status;		/* status register */
-	__be16 usb_sof_tmr;	/* Start Of Frame timer */
-	u8 reserved5[2];
-	__be16 usb_frame_num;	/* frame number register */
-	u8 reserved6[1];
-};
-
 /* Freescale USB HOST */
 /* Freescale USB HOST */
 struct fhci_pram {
 struct fhci_pram {
 	__be16 ep_ptr[4];	/* Endpoint porter reg */
 	__be16 ep_ptr[4];	/* Endpoint porter reg */
@@ -267,7 +249,7 @@ struct fhci_hcd {
 	int gpios[NUM_GPIOS];
 	int gpios[NUM_GPIOS];
 	bool alow_gpios[NUM_GPIOS];
 	bool alow_gpios[NUM_GPIOS];
 
 
-	struct fhci_regs __iomem *regs;	/* I/O memory used to communicate */
+	struct qe_usb_ctlr __iomem *regs; /* I/O memory used to communicate */
 	struct fhci_pram __iomem *pram;	/* Parameter RAM */
 	struct fhci_pram __iomem *pram;	/* Parameter RAM */
 	struct gtm_timer *timer;
 	struct gtm_timer *timer;
 
 

+ 3 - 3
drivers/usb/host/imx21-hcd.c

@@ -1811,7 +1811,7 @@ static int imx21_remove(struct platform_device *pdev)
 	usb_remove_hcd(hcd);
 	usb_remove_hcd(hcd);
 
 
 	if (res != NULL) {
 	if (res != NULL) {
-		clk_disable(imx21->clk);
+		clk_disable_unprepare(imx21->clk);
 		clk_put(imx21->clk);
 		clk_put(imx21->clk);
 		iounmap(imx21->regs);
 		iounmap(imx21->regs);
 		release_mem_region(res->start, resource_size(res));
 		release_mem_region(res->start, resource_size(res));
@@ -1884,7 +1884,7 @@ static int imx21_probe(struct platform_device *pdev)
 	ret = clk_set_rate(imx21->clk, clk_round_rate(imx21->clk, 48000000));
 	ret = clk_set_rate(imx21->clk, clk_round_rate(imx21->clk, 48000000));
 	if (ret)
 	if (ret)
 		goto failed_clock_set;
 		goto failed_clock_set;
-	ret = clk_enable(imx21->clk);
+	ret = clk_prepare_enable(imx21->clk);
 	if (ret)
 	if (ret)
 		goto failed_clock_enable;
 		goto failed_clock_enable;
 
 
@@ -1900,7 +1900,7 @@ static int imx21_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 
 
 failed_add_hcd:
 failed_add_hcd:
-	clk_disable(imx21->clk);
+	clk_disable_unprepare(imx21->clk);
 failed_clock_enable:
 failed_clock_enable:
 failed_clock_set:
 failed_clock_set:
 	clk_put(imx21->clk);
 	clk_put(imx21->clk);

+ 11 - 13
drivers/usb/host/ohci-exynos.c

@@ -87,7 +87,8 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	exynos_ohci = kzalloc(sizeof(struct exynos_ohci_hcd), GFP_KERNEL);
+	exynos_ohci = devm_kzalloc(&pdev->dev, sizeof(struct exynos_ohci_hcd),
+					GFP_KERNEL);
 	if (!exynos_ohci)
 	if (!exynos_ohci)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
@@ -97,8 +98,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
 					dev_name(&pdev->dev));
 					dev_name(&pdev->dev));
 	if (!hcd) {
 	if (!hcd) {
 		dev_err(&pdev->dev, "Unable to create HCD\n");
 		dev_err(&pdev->dev, "Unable to create HCD\n");
-		err = -ENOMEM;
-		goto fail_hcd;
+		return -ENOMEM;
 	}
 	}
 
 
 	exynos_ohci->hcd = hcd;
 	exynos_ohci->hcd = hcd;
@@ -123,7 +123,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
 
 
 	hcd->rsrc_start = res->start;
 	hcd->rsrc_start = res->start;
 	hcd->rsrc_len = resource_size(res);
 	hcd->rsrc_len = resource_size(res);
-	hcd->regs = ioremap(res->start, resource_size(res));
+	hcd->regs = devm_ioremap(&pdev->dev, res->start, hcd->rsrc_len);
 	if (!hcd->regs) {
 	if (!hcd->regs) {
 		dev_err(&pdev->dev, "Failed to remap I/O memory\n");
 		dev_err(&pdev->dev, "Failed to remap I/O memory\n");
 		err = -ENOMEM;
 		err = -ENOMEM;
@@ -134,7 +134,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
 	if (!irq) {
 	if (!irq) {
 		dev_err(&pdev->dev, "Failed to get IRQ\n");
 		dev_err(&pdev->dev, "Failed to get IRQ\n");
 		err = -ENODEV;
 		err = -ENODEV;
-		goto fail;
+		goto fail_io;
 	}
 	}
 
 
 	if (pdata->phy_init)
 	if (pdata->phy_init)
@@ -146,23 +146,19 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (err) {
 	if (err) {
 		dev_err(&pdev->dev, "Failed to add USB HCD\n");
 		dev_err(&pdev->dev, "Failed to add USB HCD\n");
-		goto fail;
+		goto fail_io;
 	}
 	}
 
 
 	platform_set_drvdata(pdev, exynos_ohci);
 	platform_set_drvdata(pdev, exynos_ohci);
 
 
 	return 0;
 	return 0;
 
 
-fail:
-	iounmap(hcd->regs);
 fail_io:
 fail_io:
 	clk_disable(exynos_ohci->clk);
 	clk_disable(exynos_ohci->clk);
 fail_clken:
 fail_clken:
 	clk_put(exynos_ohci->clk);
 	clk_put(exynos_ohci->clk);
 fail_clk:
 fail_clk:
 	usb_put_hcd(hcd);
 	usb_put_hcd(hcd);
-fail_hcd:
-	kfree(exynos_ohci);
 	return err;
 	return err;
 }
 }
 
 
@@ -177,13 +173,10 @@ static int __devexit exynos_ohci_remove(struct platform_device *pdev)
 	if (pdata && pdata->phy_exit)
 	if (pdata && pdata->phy_exit)
 		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 
 
-	iounmap(hcd->regs);
-
 	clk_disable(exynos_ohci->clk);
 	clk_disable(exynos_ohci->clk);
 	clk_put(exynos_ohci->clk);
 	clk_put(exynos_ohci->clk);
 
 
 	usb_put_hcd(hcd);
 	usb_put_hcd(hcd);
-	kfree(exynos_ohci);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -225,6 +218,9 @@ static int exynos_ohci_suspend(struct device *dev)
 
 
 	if (pdata && pdata->phy_exit)
 	if (pdata && pdata->phy_exit)
 		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
+
+	clk_disable(exynos_ohci->clk);
+
 fail:
 fail:
 	spin_unlock_irqrestore(&ohci->lock, flags);
 	spin_unlock_irqrestore(&ohci->lock, flags);
 
 
@@ -238,6 +234,8 @@ static int exynos_ohci_resume(struct device *dev)
 	struct platform_device *pdev = to_platform_device(dev);
 	struct platform_device *pdev = to_platform_device(dev);
 	struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
 	struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
 
 
+	clk_enable(exynos_ohci->clk);
+
 	if (pdata && pdata->phy_init)
 	if (pdata && pdata->phy_init)
 		pdata->phy_init(pdev, S5P_USB_PHY_HOST);
 		pdata->phy_init(pdev, S5P_USB_PHY_HOST);
 
 

Some files were not shown because too many files changed in this diff