Browse Source

Merge tag 'usb-for-v3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

Felipe writes:

usb: patches for v3.12 merge window

All patches here have been pending on linux-usb
and sitting in linux-next for a while now.

The biggest things in this tag are:

DWC3 learned proper usage of threaded IRQ
handlers and now we spend very little time
in hardirq context.

MUSB now has proper support for BeagleBone and
Beaglebone Black.

Tegra's USB support also got quite a bit of love
and is learning to use PHY layer and generic DT
attributes.

Other than that, the usual pack of cleanups and
non-critical fixes follow.

Signed-of-by: Felipe Balbi <balbi@ti.com>

Conflicts:
	drivers/usb/gadget/udc-core.c
	drivers/usb/host/ehci-tegra.c
	drivers/usb/musb/omap2430.c
	drivers/usb/musb/tusb6010.c
Greg Kroah-Hartman 12 years ago
parent
commit
165f60642a
100 changed files with 3119 additions and 3218 deletions
  1. 5 3
      Documentation/devicetree/bindings/usb/dwc3.txt
  2. 24 0
      Documentation/devicetree/bindings/usb/generic.txt
  3. 13 4
      Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt
  4. 40 0
      Documentation/devicetree/bindings/usb/samsung-hsotg.txt
  5. 16 0
      arch/arm/boot/dts/am335x-bone.dts
  6. 28 0
      arch/arm/boot/dts/am335x-evm.dts
  7. 16 0
      arch/arm/boot/dts/am335x-evmsk.dts
  8. 144 14
      arch/arm/boot/dts/am33xx.dtsi
  9. 1 1
      arch/arm/boot/dts/omap5.dtsi
  10. 0 1
      arch/arm/boot/dts/tegra20-seaboard.dts
  11. 0 1
      arch/arm/boot/dts/tegra20-trimslice.dts
  12. 0 2
      arch/arm/boot/dts/tegra20-whistler.dts
  13. 14 14
      arch/arm/boot/dts/tegra20.dtsi
  14. 2 2
      arch/arm/mach-omap2/board-omap3beagle.c
  15. 2 2
      arch/arm/mach-omap2/board-omap3evm.c
  16. 1 1
      arch/arm/mach-omap2/board-omap3pandora.c
  17. 5 5
      arch/arm/mach-omap2/usb-host.c
  18. 1 37
      arch/arm/mach-tegra/tegra.c
  19. 8 0
      drivers/dma/Kconfig
  20. 1 0
      drivers/dma/Makefile
  21. 1048 0
      drivers/dma/cppi41.c
  22. 1 1
      drivers/usb/Makefile
  23. 1 0
      drivers/usb/chipidea/host.c
  24. 32 0
      drivers/usb/dwc3/Kconfig
  25. 3 10
      drivers/usb/dwc3/Makefile
  26. 86 107
      drivers/usb/dwc3/core.c
  27. 16 37
      drivers/usb/dwc3/core.h
  28. 7 27
      drivers/usb/dwc3/debug.h
  29. 7 27
      drivers/usb/dwc3/debugfs.c
  30. 13 9
      drivers/usb/dwc3/dwc3-exynos.c
  31. 11 33
      drivers/usb/dwc3/dwc3-omap.c
  32. 15 39
      drivers/usb/dwc3/dwc3-pci.c
  33. 19 30
      drivers/usb/dwc3/ep0.c
  34. 106 151
      drivers/usb/dwc3/gadget.c
  35. 7 27
      drivers/usb/dwc3/gadget.h
  36. 7 27
      drivers/usb/dwc3/host.c
  37. 7 27
      drivers/usb/dwc3/io.h
  38. 27 0
      drivers/usb/dwc3/platform_data.h
  39. 0 17
      drivers/usb/gadget/Kconfig
  40. 0 1
      drivers/usb/gadget/Makefile
  41. 2 2
      drivers/usb/gadget/amd5536udc.c
  42. 21 4
      drivers/usb/gadget/at91_udc.c
  43. 1 1
      drivers/usb/gadget/at91_udc.h
  44. 22 8
      drivers/usb/gadget/atmel_usba_udc.c
  45. 1 1
      drivers/usb/gadget/bcm63xx_udc.c
  46. 3 3
      drivers/usb/gadget/f_mass_storage.c
  47. 2 2
      drivers/usb/gadget/f_uac1.c
  48. 2 2
      drivers/usb/gadget/fsl_mxc_udc.c
  49. 3 3
      drivers/usb/gadget/fsl_udc_core.c
  50. 1 1
      drivers/usb/gadget/fusb300_udc.c
  51. 1 1
      drivers/usb/gadget/goku_udc.c
  52. 1 1
      drivers/usb/gadget/hid.c
  53. 0 1544
      drivers/usb/gadget/imx_udc.c
  54. 0 351
      drivers/usb/gadget/imx_udc.h
  55. 2 2
      drivers/usb/gadget/m66592-udc.c
  56. 6 6
      drivers/usb/gadget/mv_u3d_core.c
  57. 2 2
      drivers/usb/gadget/mv_udc_core.c
  58. 1 1
      drivers/usb/gadget/omap_udc.c
  59. 1 1
      drivers/usb/gadget/pxa25x_udc.c
  60. 1 1
      drivers/usb/gadget/pxa27x_udc.c
  61. 1 1
      drivers/usb/gadget/r8a66597-udc.c
  62. 2 2
      drivers/usb/gadget/rndis.c
  63. 12 2
      drivers/usb/gadget/s3c-hsotg.c
  64. 2 2
      drivers/usb/gadget/s3c-hsudc.c
  65. 1 1
      drivers/usb/gadget/s3c2410_udc.c
  66. 1 1
      drivers/usb/gadget/u_uac1.c
  67. 11 1
      drivers/usb/gadget/udc-core.c
  68. 5 1
      drivers/usb/gadget/uvc_queue.c
  69. 1 4
      drivers/usb/host/Kconfig
  70. 7 7
      drivers/usb/host/ehci-hub.c
  71. 31 64
      drivers/usb/host/ehci-tegra.c
  72. 1 0
      drivers/usb/host/ehci.h
  73. 9 0
      drivers/usb/musb/Kconfig
  74. 4 0
      drivers/usb/musb/Makefile
  75. 8 8
      drivers/usb/musb/am35x.c
  76. 2 2
      drivers/usb/musb/blackfin.c
  77. 5 13
      drivers/usb/musb/cppi_dma.c
  78. 2 2
      drivers/usb/musb/da8xx.c
  79. 2 2
      drivers/usb/musb/davinci.c
  80. 55 0
      drivers/usb/musb/musb_am335x.c
  81. 7 23
      drivers/usb/musb/musb_core.c
  82. 0 8
      drivers/usb/musb/musb_core.h
  83. 555 0
      drivers/usb/musb/musb_cppi41.c
  84. 15 6
      drivers/usb/musb/musb_dma.h
  85. 103 279
      drivers/usb/musb/musb_dsps.c
  86. 45 42
      drivers/usb/musb/musb_gadget.c
  87. 2 15
      drivers/usb/musb/musbhsdma.c
  88. 4 4
      drivers/usb/musb/omap2430.c
  89. 2 2
      drivers/usb/musb/tusb6010.c
  90. 0 24
      drivers/usb/musb/tusb6010_omap.c
  91. 1 1
      drivers/usb/musb/ux500.c
  92. 9 12
      drivers/usb/musb/ux500_dma.c
  93. 32 16
      drivers/usb/phy/Kconfig
  94. 3 1
      drivers/usb/phy/Makefile
  95. 21 0
      drivers/usb/phy/am35x-phy-control.h
  96. 137 0
      drivers/usb/phy/phy-am335x-control.c
  97. 99 0
      drivers/usb/phy/phy-am335x.c
  98. 3 3
      drivers/usb/phy/phy-fsl-usb.c
  99. 92 75
      drivers/usb/phy/phy-generic.c
  100. 20 0
      drivers/usb/phy/phy-generic.h

+ 5 - 3
Documentation/devicetree/bindings/usb/dwc3.txt

@@ -3,10 +3,12 @@ synopsys DWC3 CORE
 DWC3- USB3 CONTROLLER
 
 Required properties:
- - compatible: must be "synopsys,dwc3"
+ - compatible: must be "snps,dwc3"
  - reg : Address and length of the register set for the device
  - interrupts: Interrupts used by the dwc3 controller.
- - usb-phy : array of phandle for the PHY device
+ - usb-phy : array of phandle for the PHY device.  The first element
+   in the array is expected to be a handle to the USB2/HS PHY and
+   the second element is expected to be a handle to the USB3/SS PHY
 
 Optional properties:
  - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
@@ -14,7 +16,7 @@ Optional properties:
 This is usually a subnode to DWC3 glue to which it is connected.
 
 dwc3@4a030000 {
-	compatible = "synopsys,dwc3";
+	compatible = "snps,dwc3";
 	reg = <0x4a030000 0xcfff>;
 	interrupts = <0 92 4>
 	usb-phy = <&usb2_phy>, <&usb3,phy>;

+ 24 - 0
Documentation/devicetree/bindings/usb/generic.txt

@@ -0,0 +1,24 @@
+Generic USB Properties
+
+Optional properties:
+ - maximum-speed: tells USB controllers we want to work up to a certain
+			speed. Valid arguments are "super-speed", "high-speed",
+			"full-speed" and "low-speed". In case this isn't passed
+			via DT, USB controllers should default to their maximum
+			HW capability.
+ - dr_mode: tells Dual-Role USB controllers that we want to work on a
+			particular mode. Valid arguments are "host",
+			"peripheral" and "otg". In case this attribute isn't
+			passed via DT, USB DRD controllers should default to
+			OTG.
+
+This is an attribute to a USB controller such as:
+
+dwc3@4a030000 {
+	compatible = "synopsys,dwc3";
+	reg = <0x4a030000 0xcfff>;
+	interrupts = <0 92 4>
+	usb-phy = <&usb2_phy>, <&usb3,phy>;
+	maximum-speed = "super-speed";
+	dr_mode = "otg";
+};

+ 13 - 4
Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt

@@ -3,7 +3,7 @@ Tegra SOC USB PHY
 The device node for Tegra SOC USB PHY:
 
 Required properties :
- - compatible : Should be "nvidia,tegra20-usb-phy".
+ - compatible : Should be "nvidia,tegra<chip>-usb-phy".
  - reg : Defines the following set of registers, in the order listed:
    - The PHY's own register set.
      Always present.
@@ -24,17 +24,26 @@ Required properties :
 Required properties for phy_type == ulpi:
   - nvidia,phy-reset-gpio : The GPIO used to reset the PHY.
 
-Required PHY timing params for utmi phy:
+Required PHY timing params for utmi phy, for all chips:
   - nvidia,hssync-start-delay : Number of 480 Mhz clock cycles to wait before
     start of sync launches RxActive
   - nvidia,elastic-limit : Variable FIFO Depth of elastic input store
   - nvidia,idle-wait-delay : Number of 480 Mhz clock cycles of idle to wait
     before declare IDLE.
   - nvidia,term-range-adj : Range adjusment on terminations
-  - nvidia,xcvr-setup : HS driver output control
+  - Either one of the following for HS driver output control:
+    - nvidia,xcvr-setup : integer, uses the provided value.
+    - nvidia,xcvr-setup-use-fuses : boolean, indicates that the value is read
+      from the on-chip fuses
+    If both are provided, nvidia,xcvr-setup-use-fuses takes precedence.
   - nvidia,xcvr-lsfslew : LS falling slew rate control.
   - nvidia,xcvr-lsrslew :  LS rising slew rate control.
 
+Required PHY timing params for utmi phy, only on Tegra30 and above:
+  - nvidia,xcvr-hsslew : HS slew rate control.
+  - nvidia,hssquelch-level : HS squelch detector level.
+  - nvidia,hsdiscon-level : HS disconnect detector level.
+
 Optional properties:
   - nvidia,has-legacy-mode : boolean indicates whether this controller can
     operate in legacy mode (as APX 2500 / 2600). In legacy mode some
@@ -48,5 +57,5 @@ Optional properties:
       peripheral means it is device controller
       otg means it can operate as either ("on the go")
 
-Required properties for dr_mode == otg:
+VBUS control (required for dr_mode == otg, optional for dr_mode == host):
   - vbus-supply: regulator for VBUS

+ 40 - 0
Documentation/devicetree/bindings/usb/samsung-hsotg.txt

@@ -0,0 +1,40 @@
+Samsung High Speed USB OTG controller
+-----------------------------
+
+The Samsung HSOTG IP can be found on Samsung SoCs, from S3C6400 onwards.
+It gives functionality of OTG-compliant USB 2.0 host and device with
+support for USB 2.0 high-speed (480Mbps) and full-speed (12 Mbps)
+operation.
+
+Currently only device mode is supported.
+
+Binding details
+-----
+
+Required properties:
+- compatible: "samsung,s3c6400-hsotg" should be used for all currently
+    supported SoC,
+- interrupt-parent: phandle for the interrupt controller to which the
+    interrupt signal of the HSOTG block is routed,
+- interrupts: specifier of interrupt signal of interrupt controller,
+    according to bindings of interrupt controller,
+- clocks: contains an array of clock specifiers:
+    - first entry: OTG clock
+- clock-names: contains array of clock names:
+    - first entry: must be "otg"
+- vusb_d-supply: phandle to voltage regulator of digital section,
+- vusb_a-supply: phandle to voltage regulator of analog section.
+
+Example
+-----
+
+	hsotg@12480000 {
+		compatible = "samsung,s3c6400-hsotg";
+		reg = <0x12480000 0x20000>;
+		interrupts = <0 71 0>;
+		clocks = <&clock 305>;
+		clock-names = "otg";
+		vusb_d-supply = <&vusb_reg>;
+		vusb_a-supply = <&vusbdac_reg>;
+	};
+

+ 16 - 0
arch/arm/boot/dts/am335x-bone.dts

@@ -120,6 +120,22 @@
 			status = "okay";
 		};
 
+		musb: usb@47400000 {
+			status = "okay";
+
+			control@44e10000 {
+				status = "okay";
+			};
+
+			phy@47401300 {
+				status = "okay";
+			};
+
+			usb@47401000 {
+				status = "okay";
+			};
+		};
+
 		i2c0: i2c@44e0b000 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&i2c0_pins>;

+ 28 - 0
arch/arm/boot/dts/am335x-evm.dts

@@ -171,6 +171,34 @@
 			};
 		};
 
+		musb: usb@47400000 {
+			status = "okay";
+
+			control@44e10000 {
+				status = "okay";
+			};
+
+			phy@47401300 {
+				status = "okay";
+			};
+
+			phy@47401b00 {
+				status = "okay";
+			};
+
+			usb@47401000 {
+				status = "okay";
+			};
+
+			usb@47401800 {
+				status = "okay";
+			};
+
+			dma@07402000  {
+				status = "okay";
+			};
+		};
+
 		i2c1: i2c@4802a000 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&i2c1_pins>;

+ 16 - 0
arch/arm/boot/dts/am335x-evmsk.dts

@@ -207,6 +207,22 @@
 			};
 		};
 
+		musb: usb@47400000 {
+			status = "okay";
+
+			control@44e10000 {
+				status = "okay";
+			};
+
+			phy@47401300 {
+				status = "okay";
+			};
+
+			usb@47401000 {
+				status = "okay";
+			};
+		};
+
 		epwmss2: epwmss@48304000 {
 			status = "okay";
 

+ 144 - 14
arch/arm/boot/dts/am33xx.dtsi

@@ -26,6 +26,10 @@
 		serial5 = &uart5;
 		d_can0 = &dcan0;
 		d_can1 = &dcan1;
+		usb0 = &usb0;
+		usb1 = &usb1;
+		phy0 = &usb0_phy;
+		phy1 = &usb1_phy;
 	};
 
 	cpus {
@@ -333,21 +337,147 @@
 			status = "disabled";
 		};
 
-		usb@47400000 {
-			compatible = "ti,musb-am33xx";
-			reg = <0x47400000 0x1000	/* usbss */
-			       0x47401000 0x800		/* musb instance 0 */
-			       0x47401800 0x800>;	/* musb instance 1 */
-			interrupts = <17		/* usbss */
-				      18		/* musb instance 0 */
-				      19>;		/* musb instance 1 */
-			multipoint = <1>;
-			num-eps = <16>;
-			ram-bits = <12>;
-			port0-mode = <3>;
-			port1-mode = <3>;
-			power = <250>;
+		usb: usb@47400000 {
+			compatible = "ti,am33xx-usb";
+			reg = <0x47400000 0x1000>;
+			ranges;
+			#address-cells = <1>;
+			#size-cells = <1>;
 			ti,hwmods = "usb_otg_hs";
+			status = "disabled";
+
+			ctrl_mod: control@44e10000 {
+				compatible = "ti,am335x-usb-ctrl-module";
+				reg = <0x44e10620 0x10
+					0x44e10648 0x4>;
+				reg-names = "phy_ctrl", "wakeup";
+				status = "disabled";
+			};
+
+			usb0_phy: phy@47401300 {
+				compatible = "ti,am335x-usb-phy";
+				reg = <0x47401300 0x100>;
+				reg-names = "phy";
+				status = "disabled";
+				ti,ctrl_mod = <&ctrl_mod>;
+			};
+
+			usb0: usb@47401000 {
+				compatible = "ti,musb-am33xx";
+				ranges;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x47401000 0x200>;
+				reg-names = "control";
+				status = "disabled";
+
+				musb0: usb@47401400 {
+					compatible = "mg,musbmhdrc";
+					reg = <0x47401400 0x400>;
+					reg-names = "mc";
+					interrupts = <18>;
+					interrupt-names = "mc";
+					multipoint = <1>;
+					num-eps = <16>;
+					ram-bits = <12>;
+					port-mode = <3>;
+					power = <250>;
+					phys = <&usb0_phy>;
+
+				dmas = <&cppi41dma  0 0 &cppi41dma  1 0
+					&cppi41dma  2 0 &cppi41dma  3 0
+					&cppi41dma  4 0 &cppi41dma  5 0
+					&cppi41dma  6 0 &cppi41dma  7 0
+					&cppi41dma  8 0 &cppi41dma  9 0
+					&cppi41dma 10 0 &cppi41dma 11 0
+					&cppi41dma 12 0 &cppi41dma 13 0
+					&cppi41dma 14 0 &cppi41dma  0 1
+					&cppi41dma  1 1 &cppi41dma  2 1
+					&cppi41dma  3 1 &cppi41dma  4 1
+					&cppi41dma  5 1 &cppi41dma  6 1
+					&cppi41dma  7 1 &cppi41dma  8 1
+					&cppi41dma  9 1 &cppi41dma 10 1
+					&cppi41dma 11 1 &cppi41dma 12 1
+					&cppi41dma 13 1 &cppi41dma 14 1>;
+				dma-names =
+					"rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
+					"rx8", "rx9", "rx10", "rx11", "rx12", "rx13",
+					"rx14", "rx15",
+					"tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7",
+					"tx8", "tx9", "tx10", "tx11", "tx12", "tx13",
+					"tx14", "tx15";
+				};
+			};
+
+			usb1_phy: phy@47401b00 {
+				compatible = "ti,am335x-usb-phy";
+				reg = <0x47401b00 0x100>;
+				reg-names = "phy";
+				status = "disabled";
+				ti,ctrl_mod = <&ctrl_mod>;
+			};
+
+			usb1: usb@47401800 {
+				compatible = "ti,musb-am33xx";
+				ranges;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x47401800 0x200>;
+				reg-names = "control";
+				status = "disabled";
+
+				musb1: usb@47401c00 {
+					compatible = "mg,musbmhdrc";
+					reg = <0x47401c00 0x400>;
+					reg-names = "mc";
+					interrupts = <19>;
+					interrupt-names = "mc";
+					multipoint = <1>;
+					num-eps = <16>;
+					ram-bits = <12>;
+					port-mode = <3>;
+					power = <250>;
+					phys = <&usb1_phy>;
+
+				dmas = <&cppi41dma 15 0 &cppi41dma 16 0
+					&cppi41dma 17 0 &cppi41dma 18 0
+					&cppi41dma 19 0 &cppi41dma 20 0
+					&cppi41dma 21 0 &cppi41dma 22 0
+					&cppi41dma 23 0 &cppi41dma 24 0
+					&cppi41dma 25 0 &cppi41dma 26 0
+					&cppi41dma 27 0 &cppi41dma 28 0
+					&cppi41dma 29 0 &cppi41dma 15 1
+					&cppi41dma 16 1 &cppi41dma 17 1
+					&cppi41dma 18 1 &cppi41dma 19 1
+					&cppi41dma 20 1 &cppi41dma 21 1
+					&cppi41dma 22 1 &cppi41dma 23 1
+					&cppi41dma 24 1 &cppi41dma 25 1
+					&cppi41dma 26 1 &cppi41dma 27 1
+					&cppi41dma 28 1 &cppi41dma 29 1>;
+				dma-names =
+					"rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
+					"rx8", "rx9", "rx10", "rx11", "rx12", "rx13",
+					"rx14", "rx15",
+					"tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7",
+					"tx8", "tx9", "tx10", "tx11", "tx12", "tx13",
+					"tx14", "tx15";
+				};
+			};
+
+			cppi41dma: dma@07402000 {
+				compatible = "ti,am3359-cppi41";
+				reg =  <0x47400000 0x1000
+					0x47402000 0x1000
+					0x47403000 0x1000
+					0x47404000 0x4000>;
+				reg-names = "glue controller scheduler queuemgr";
+				interrupts = <17>;
+				interrupt-names = "glue";
+				#dma-cells = <2>;
+				#dma-channels = <30>;
+				#dma-requests = <256>;
+				status = "disabled";
+			};
 		};
 
 		epwmss0: epwmss@48300000 {

+ 1 - 1
arch/arm/boot/dts/omap5.dtsi

@@ -644,7 +644,7 @@
 			utmi-mode = <2>;
 			ranges;
 			dwc3@4a030000 {
-				compatible = "synopsys,dwc3";
+				compatible = "snps,dwc3";
 				reg = <0x4a030000 0x1000>;
 				interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
 				usb-phy = <&usb2_phy>, <&usb3_phy>;

+ 0 - 1
arch/arm/boot/dts/tegra20-seaboard.dts

@@ -566,7 +566,6 @@
 
 	usb@c5000000 {
 		status = "okay";
-		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
 		dr_mode = "otg";
 	};
 

+ 0 - 1
arch/arm/boot/dts/tegra20-trimslice.dts

@@ -312,7 +312,6 @@
 
 	usb@c5000000 {
 		status = "okay";
-		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
 	};
 
 	usb-phy@c5000000 {

+ 0 - 2
arch/arm/boot/dts/tegra20-whistler.dts

@@ -509,7 +509,6 @@
 
 	usb@c5000000 {
 		status = "okay";
-		nvidia,vbus-gpio = <&tca6416 0 GPIO_ACTIVE_HIGH>;
 	};
 
 	usb-phy@c5000000 {
@@ -519,7 +518,6 @@
 
 	usb@c5008000 {
 		status = "okay";
-		nvidia,vbus-gpio = <&tca6416 1 GPIO_ACTIVE_HIGH>;
 	};
 
 	usb-phy@c5008000 {

+ 14 - 14
arch/arm/boot/dts/tegra20.dtsi

@@ -477,13 +477,13 @@
 			 <&tegra_car TEGRA20_CLK_USBD>;
 		clock-names = "reg", "pll_u", "timer", "utmi-pads";
 		nvidia,has-legacy-mode;
-		hssync_start_delay = <9>;
-		idle_wait_delay = <17>;
-		elastic_limit = <16>;
-		term_range_adj = <6>;
-		xcvr_setup = <9>;
-		xcvr_lsfslew = <1>;
-		xcvr_lsrslew = <1>;
+		nvidia,hssync-start-delay = <9>;
+		nvidia,idle-wait-delay = <17>;
+		nvidia,elastic-limit = <16>;
+		nvidia,term-range-adj = <6>;
+		nvidia,xcvr-setup = <9>;
+		nvidia,xcvr-lsfslew = <1>;
+		nvidia,xcvr-lsrslew = <1>;
 		status = "disabled";
 	};
 
@@ -527,13 +527,13 @@
 			 <&tegra_car TEGRA20_CLK_CLK_M>,
 			 <&tegra_car TEGRA20_CLK_USBD>;
 		clock-names = "reg", "pll_u", "timer", "utmi-pads";
-		hssync_start_delay = <9>;
-		idle_wait_delay = <17>;
-		elastic_limit = <16>;
-		term_range_adj = <6>;
-		xcvr_setup = <9>;
-		xcvr_lsfslew = <2>;
-		xcvr_lsrslew = <2>;
+		nvidia,hssync-start-delay = <9>;
+		nvidia,idle-wait-delay = <17>;
+		nvidia,elastic-limit = <16>;
+		nvidia,term-range-adj = <6>;
+		nvidia,xcvr-setup = <9>;
+		nvidia,xcvr-lsfslew = <2>;
+		nvidia,xcvr-lsrslew = <2>;
 		status = "disabled";
 	};
 

+ 2 - 2
arch/arm/mach-omap2/board-omap3beagle.c

@@ -33,7 +33,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mmc/host.h>
 #include <linux/usb/phy.h>
-#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
@@ -279,7 +279,7 @@ static struct regulator_consumer_supply beagle_vsim_supply[] = {
 static struct gpio_led gpio_leds[];
 
 /* PHY's VCC regulator might be added later, so flag that we need it */
-static struct nop_usb_xceiv_platform_data hsusb2_phy_data = {
+static struct usb_phy_gen_xceiv_platform_data hsusb2_phy_data = {
 	.needs_vcc = true,
 };
 

+ 2 - 2
arch/arm/mach-omap2/board-omap3evm.c

@@ -33,7 +33,7 @@
 #include <linux/i2c/twl.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/musb.h>
-#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
 #include <linux/smsc911x.h>
 
 #include <linux/wl12xx.h>
@@ -468,7 +468,7 @@ struct wl12xx_platform_data omap3evm_wlan_data __initdata = {
 static struct regulator_consumer_supply omap3evm_vaux2_supplies[] = {
 	REGULATOR_SUPPLY("VDD_CSIPHY1", "omap3isp"),	/* OMAP ISP */
 	REGULATOR_SUPPLY("VDD_CSIPHY2", "omap3isp"),	/* OMAP ISP */
-	REGULATOR_SUPPLY("vcc", "nop_usb_xceiv.2"),	/* hsusb port 2 */
+	REGULATOR_SUPPLY("vcc", "usb_phy_gen_xceiv.2"),	/* hsusb port 2 */
 	REGULATOR_SUPPLY("vaux2", NULL),
 };
 

+ 1 - 1
arch/arm/mach-omap2/board-omap3pandora.c

@@ -352,7 +352,7 @@ static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = {
 };
 
 static struct regulator_consumer_supply pandora_usb_phy_supply[] = {
-	REGULATOR_SUPPLY("vcc", "nop_usb_xceiv.2"),	/* hsusb port 2 */
+	REGULATOR_SUPPLY("vcc", "usb_phy_gen_xceiv.2"),	/* hsusb port 2 */
 };
 
 /* ads7846 on SPI and 2 nub controllers on I2C */

+ 5 - 5
arch/arm/mach-omap2/usb-host.c

@@ -28,7 +28,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/usb/phy.h>
-#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
 
 #include "soc.h"
 #include "omap_device.h"
@@ -349,7 +349,7 @@ static struct fixed_voltage_config hsusb_reg_config = {
 	/* .init_data filled later */
 };
 
-static const char *nop_name = "nop_usb_xceiv"; /* NOP PHY driver */
+static const char *nop_name = "usb_phy_gen_xceiv"; /* NOP PHY driver */
 static const char *reg_name = "reg-fixed-voltage"; /* Regulator driver */
 
 /**
@@ -460,9 +460,9 @@ int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys)
 		pdevinfo.name = nop_name;
 		pdevinfo.id = phy->port;
 		pdevinfo.data = phy->platform_data;
-		pdevinfo.size_data = sizeof(struct nop_usb_xceiv_platform_data);
-
-		scnprintf(phy_id, MAX_STR, "nop_usb_xceiv.%d",
+		pdevinfo.size_data =
+			sizeof(struct usb_phy_gen_xceiv_platform_data);
+		scnprintf(phy_id, MAX_STR, "usb_phy_gen_xceiv.%d",
 					phy->port);
 		pdev = platform_device_register_full(&pdevinfo);
 		if (IS_ERR(pdev)) {

+ 1 - 37
arch/arm/mach-tegra/tegra.c

@@ -29,7 +29,6 @@
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 #include <linux/pda_power.h>
-#include <linux/platform_data/tegra_usb.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/sys_soc.h>
@@ -46,40 +45,6 @@
 #include "fuse.h"
 #include "iomap.h"
 
-static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
-	.operating_mode = TEGRA_USB_OTG,
-	.power_down_on_bus_suspend = 1,
-	.vbus_gpio = -1,
-};
-
-static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
-	.reset_gpio = -1,
-	.clk = "cdev2",
-};
-
-static struct tegra_ehci_platform_data tegra_ehci2_pdata = {
-	.phy_config = &tegra_ehci2_ulpi_phy_config,
-	.operating_mode = TEGRA_USB_HOST,
-	.power_down_on_bus_suspend = 1,
-	.vbus_gpio = -1,
-};
-
-static struct tegra_ehci_platform_data tegra_ehci3_pdata = {
-	.operating_mode = TEGRA_USB_HOST,
-	.power_down_on_bus_suspend = 1,
-	.vbus_gpio = -1,
-};
-
-static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5000000, "tegra-ehci.0",
-		       &tegra_ehci1_pdata),
-	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5004000, "tegra-ehci.1",
-		       &tegra_ehci2_pdata),
-	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5008000, "tegra-ehci.2",
-		       &tegra_ehci3_pdata),
-	{}
-};
-
 static void __init tegra_dt_init(void)
 {
 	struct soc_device_attribute *soc_dev_attr;
@@ -112,8 +77,7 @@ static void __init tegra_dt_init(void)
 	 * devices
 	 */
 out:
-	of_platform_populate(NULL, of_default_bus_match_table,
-				tegra20_auxdata_lookup, parent);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
 }
 
 static void __init trimslice_init(void)

+ 8 - 0
drivers/dma/Kconfig

@@ -287,6 +287,14 @@ config DMA_OMAP
 	select DMA_ENGINE
 	select DMA_VIRTUAL_CHANNELS
 
+config TI_CPPI41
+	tristate "AM33xx CPPI41 DMA support"
+	depends on ARCH_OMAP
+	select DMA_ENGINE
+	help
+	  The Communications Port Programming Interface (CPPI) 4.1 DMA engine
+	  is currently used by the USB driver on AM335x platforms.
+
 config MMP_PDMA
 	bool "MMP PDMA support"
 	depends on (ARCH_MMP || ARCH_PXA)

+ 1 - 0
drivers/dma/Makefile

@@ -39,3 +39,4 @@ obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o
 obj-$(CONFIG_DMA_OMAP) += omap-dma.o
 obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
 obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
+obj-$(CONFIG_TI_CPPI41) += cppi41.o

+ 1048 - 0
drivers/dma/cppi41.c

@@ -0,0 +1,1048 @@
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/of_dma.h>
+#include <linux/of_irq.h>
+#include <linux/dmapool.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include "dmaengine.h"
+
+#define DESC_TYPE	27
+#define DESC_TYPE_HOST	0x10
+#define DESC_TYPE_TEARD	0x13
+
+#define TD_DESC_IS_RX	(1 << 16)
+#define TD_DESC_DMA_NUM	10
+
+#define DESC_LENGTH_BITS_NUM	21
+
+#define DESC_TYPE_USB	(5 << 26)
+#define DESC_PD_COMPLETE	(1 << 31)
+
+/* DMA engine */
+#define DMA_TDFDQ	4
+#define DMA_TXGCR(x)	(0x800 + (x) * 0x20)
+#define DMA_RXGCR(x)	(0x808 + (x) * 0x20)
+#define RXHPCRA0		4
+
+#define GCR_CHAN_ENABLE		(1 << 31)
+#define GCR_TEARDOWN		(1 << 30)
+#define GCR_STARV_RETRY		(1 << 24)
+#define GCR_DESC_TYPE_HOST	(1 << 14)
+
+/* DMA scheduler */
+#define DMA_SCHED_CTRL		0
+#define DMA_SCHED_CTRL_EN	(1 << 31)
+#define DMA_SCHED_WORD(x)	((x) * 4 + 0x800)
+
+#define SCHED_ENTRY0_CHAN(x)	((x) << 0)
+#define SCHED_ENTRY0_IS_RX	(1 << 7)
+
+#define SCHED_ENTRY1_CHAN(x)	((x) << 8)
+#define SCHED_ENTRY1_IS_RX	(1 << 15)
+
+#define SCHED_ENTRY2_CHAN(x)	((x) << 16)
+#define SCHED_ENTRY2_IS_RX	(1 << 23)
+
+#define SCHED_ENTRY3_CHAN(x)	((x) << 24)
+#define SCHED_ENTRY3_IS_RX	(1 << 31)
+
+/* Queue manager */
+/* 4 KiB of memory for descriptors, 2 for each endpoint */
+#define ALLOC_DECS_NUM		128
+#define DESCS_AREAS		1
+#define TOTAL_DESCS_NUM		(ALLOC_DECS_NUM * DESCS_AREAS)
+#define QMGR_SCRATCH_SIZE	(TOTAL_DESCS_NUM * 4)
+
+#define QMGR_LRAM0_BASE		0x80
+#define QMGR_LRAM_SIZE		0x84
+#define QMGR_LRAM1_BASE		0x88
+#define QMGR_MEMBASE(x)		(0x1000 + (x) * 0x10)
+#define QMGR_MEMCTRL(x)		(0x1004 + (x) * 0x10)
+#define QMGR_MEMCTRL_IDX_SH	16
+#define QMGR_MEMCTRL_DESC_SH	8
+
+#define QMGR_NUM_PEND	5
+#define QMGR_PEND(x)	(0x90 + (x) * 4)
+
+#define QMGR_PENDING_SLOT_Q(x)	(x / 32)
+#define QMGR_PENDING_BIT_Q(x)	(x % 32)
+
+#define QMGR_QUEUE_A(n)	(0x2000 + (n) * 0x10)
+#define QMGR_QUEUE_B(n)	(0x2004 + (n) * 0x10)
+#define QMGR_QUEUE_C(n)	(0x2008 + (n) * 0x10)
+#define QMGR_QUEUE_D(n)	(0x200c + (n) * 0x10)
+
+/* Glue layer specific */
+/* USBSS  / USB AM335x */
+#define USBSS_IRQ_STATUS	0x28
+#define USBSS_IRQ_ENABLER	0x2c
+#define USBSS_IRQ_CLEARR	0x30
+
+#define USBSS_IRQ_PD_COMP	(1 <<  2)
+
+struct cppi41_channel {
+	struct dma_chan chan;
+	struct dma_async_tx_descriptor txd;
+	struct cppi41_dd *cdd;
+	struct cppi41_desc *desc;
+	dma_addr_t desc_phys;
+	void __iomem *gcr_reg;
+	int is_tx;
+	u32 residue;
+
+	unsigned int q_num;
+	unsigned int q_comp_num;
+	unsigned int port_num;
+
+	unsigned td_retry;
+	unsigned td_queued:1;
+	unsigned td_seen:1;
+	unsigned td_desc_seen:1;
+};
+
+struct cppi41_desc {
+	u32 pd0;
+	u32 pd1;
+	u32 pd2;
+	u32 pd3;
+	u32 pd4;
+	u32 pd5;
+	u32 pd6;
+	u32 pd7;
+} __aligned(32);
+
+struct chan_queues {
+	u16 submit;
+	u16 complete;
+};
+
+struct cppi41_dd {
+	struct dma_device ddev;
+
+	void *qmgr_scratch;
+	dma_addr_t scratch_phys;
+
+	struct cppi41_desc *cd;
+	dma_addr_t descs_phys;
+	u32 first_td_desc;
+	struct cppi41_channel *chan_busy[ALLOC_DECS_NUM];
+
+	void __iomem *usbss_mem;
+	void __iomem *ctrl_mem;
+	void __iomem *sched_mem;
+	void __iomem *qmgr_mem;
+	unsigned int irq;
+	const struct chan_queues *queues_rx;
+	const struct chan_queues *queues_tx;
+	struct chan_queues td_queue;
+};
+
+#define FIST_COMPLETION_QUEUE	93
+static struct chan_queues usb_queues_tx[] = {
+	/* USB0 ENDP 1 */
+	[ 0] = { .submit = 32, .complete =  93},
+	[ 1] = { .submit = 34, .complete =  94},
+	[ 2] = { .submit = 36, .complete =  95},
+	[ 3] = { .submit = 38, .complete =  96},
+	[ 4] = { .submit = 40, .complete =  97},
+	[ 5] = { .submit = 42, .complete =  98},
+	[ 6] = { .submit = 44, .complete =  99},
+	[ 7] = { .submit = 46, .complete = 100},
+	[ 8] = { .submit = 48, .complete = 101},
+	[ 9] = { .submit = 50, .complete = 102},
+	[10] = { .submit = 52, .complete = 103},
+	[11] = { .submit = 54, .complete = 104},
+	[12] = { .submit = 56, .complete = 105},
+	[13] = { .submit = 58, .complete = 106},
+	[14] = { .submit = 60, .complete = 107},
+
+	/* USB1 ENDP1 */
+	[15] = { .submit = 62, .complete = 125},
+	[16] = { .submit = 64, .complete = 126},
+	[17] = { .submit = 66, .complete = 127},
+	[18] = { .submit = 68, .complete = 128},
+	[19] = { .submit = 70, .complete = 129},
+	[20] = { .submit = 72, .complete = 130},
+	[21] = { .submit = 74, .complete = 131},
+	[22] = { .submit = 76, .complete = 132},
+	[23] = { .submit = 78, .complete = 133},
+	[24] = { .submit = 80, .complete = 134},
+	[25] = { .submit = 82, .complete = 135},
+	[26] = { .submit = 84, .complete = 136},
+	[27] = { .submit = 86, .complete = 137},
+	[28] = { .submit = 88, .complete = 138},
+	[29] = { .submit = 90, .complete = 139},
+};
+
+static const struct chan_queues usb_queues_rx[] = {
+	/* USB0 ENDP 1 */
+	[ 0] = { .submit =  1, .complete = 109},
+	[ 1] = { .submit =  2, .complete = 110},
+	[ 2] = { .submit =  3, .complete = 111},
+	[ 3] = { .submit =  4, .complete = 112},
+	[ 4] = { .submit =  5, .complete = 113},
+	[ 5] = { .submit =  6, .complete = 114},
+	[ 6] = { .submit =  7, .complete = 115},
+	[ 7] = { .submit =  8, .complete = 116},
+	[ 8] = { .submit =  9, .complete = 117},
+	[ 9] = { .submit = 10, .complete = 118},
+	[10] = { .submit = 11, .complete = 119},
+	[11] = { .submit = 12, .complete = 120},
+	[12] = { .submit = 13, .complete = 121},
+	[13] = { .submit = 14, .complete = 122},
+	[14] = { .submit = 15, .complete = 123},
+
+	/* USB1 ENDP 1 */
+	[15] = { .submit = 16, .complete = 141},
+	[16] = { .submit = 17, .complete = 142},
+	[17] = { .submit = 18, .complete = 143},
+	[18] = { .submit = 19, .complete = 144},
+	[19] = { .submit = 20, .complete = 145},
+	[20] = { .submit = 21, .complete = 146},
+	[21] = { .submit = 22, .complete = 147},
+	[22] = { .submit = 23, .complete = 148},
+	[23] = { .submit = 24, .complete = 149},
+	[24] = { .submit = 25, .complete = 150},
+	[25] = { .submit = 26, .complete = 151},
+	[26] = { .submit = 27, .complete = 152},
+	[27] = { .submit = 28, .complete = 153},
+	[28] = { .submit = 29, .complete = 154},
+	[29] = { .submit = 30, .complete = 155},
+};
+
+struct cppi_glue_infos {
+	irqreturn_t (*isr)(int irq, void *data);
+	const struct chan_queues *queues_rx;
+	const struct chan_queues *queues_tx;
+	struct chan_queues td_queue;
+};
+
+static struct cppi41_channel *to_cpp41_chan(struct dma_chan *c)
+{
+	return container_of(c, struct cppi41_channel, chan);
+}
+
+static struct cppi41_channel *desc_to_chan(struct cppi41_dd *cdd, u32 desc)
+{
+	struct cppi41_channel *c;
+	u32 descs_size;
+	u32 desc_num;
+
+	descs_size = sizeof(struct cppi41_desc) * ALLOC_DECS_NUM;
+
+	if (!((desc >= cdd->descs_phys) &&
+			(desc < (cdd->descs_phys + descs_size)))) {
+		return NULL;
+	}
+
+	desc_num = (desc - cdd->descs_phys) / sizeof(struct cppi41_desc);
+	BUG_ON(desc_num > ALLOC_DECS_NUM);
+	c = cdd->chan_busy[desc_num];
+	cdd->chan_busy[desc_num] = NULL;
+	return c;
+}
+
+static void cppi_writel(u32 val, void *__iomem *mem)
+{
+	__raw_writel(val, mem);
+}
+
+static u32 cppi_readl(void *__iomem *mem)
+{
+	return __raw_readl(mem);
+}
+
+static u32 pd_trans_len(u32 val)
+{
+	return val & ((1 << (DESC_LENGTH_BITS_NUM + 1)) - 1);
+}
+
+static irqreturn_t cppi41_irq(int irq, void *data)
+{
+	struct cppi41_dd *cdd = data;
+	struct cppi41_channel *c;
+	u32 status;
+	int i;
+
+	status = cppi_readl(cdd->usbss_mem + USBSS_IRQ_STATUS);
+	if (!(status & USBSS_IRQ_PD_COMP))
+		return IRQ_NONE;
+	cppi_writel(status, cdd->usbss_mem + USBSS_IRQ_STATUS);
+
+	for (i = QMGR_PENDING_SLOT_Q(FIST_COMPLETION_QUEUE); i < QMGR_NUM_PEND;
+			i++) {
+		u32 val;
+		u32 q_num;
+
+		val = cppi_readl(cdd->qmgr_mem + QMGR_PEND(i));
+		if (i == QMGR_PENDING_SLOT_Q(FIST_COMPLETION_QUEUE) && val) {
+			u32 mask;
+			/* set corresponding bit for completetion Q 93 */
+			mask = 1 << QMGR_PENDING_BIT_Q(FIST_COMPLETION_QUEUE);
+			/* not set all bits for queues less than Q 93 */
+			mask--;
+			/* now invert and keep only Q 93+ set */
+			val &= ~mask;
+		}
+
+		if (val)
+			__iormb();
+
+		while (val) {
+			u32 desc;
+
+			q_num = __fls(val);
+			val &= ~(1 << q_num);
+			q_num += 32 * i;
+			desc = cppi_readl(cdd->qmgr_mem + QMGR_QUEUE_D(q_num));
+			desc &= ~0x1f;
+			c = desc_to_chan(cdd, desc);
+			if (WARN_ON(!c)) {
+				pr_err("%s() q %d desc %08x\n", __func__,
+						q_num, desc);
+				continue;
+			}
+			c->residue = pd_trans_len(c->desc->pd6) -
+				pd_trans_len(c->desc->pd0);
+
+			dma_cookie_complete(&c->txd);
+			c->txd.callback(c->txd.callback_param);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static dma_cookie_t cppi41_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	dma_cookie_t cookie;
+
+	cookie = dma_cookie_assign(tx);
+
+	return cookie;
+}
+
+static int cppi41_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct cppi41_channel *c = to_cpp41_chan(chan);
+
+	dma_cookie_init(chan);
+	dma_async_tx_descriptor_init(&c->txd, chan);
+	c->txd.tx_submit = cppi41_tx_submit;
+
+	if (!c->is_tx)
+		cppi_writel(c->q_num, c->gcr_reg + RXHPCRA0);
+
+	return 0;
+}
+
+static void cppi41_dma_free_chan_resources(struct dma_chan *chan)
+{
+}
+
+static enum dma_status cppi41_dma_tx_status(struct dma_chan *chan,
+	dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+	struct cppi41_channel *c = to_cpp41_chan(chan);
+	enum dma_status ret;
+
+	/* lock */
+	ret = dma_cookie_status(chan, cookie, txstate);
+	if (txstate && ret == DMA_SUCCESS)
+		txstate->residue = c->residue;
+	/* unlock */
+
+	return ret;
+}
+
+static void push_desc_queue(struct cppi41_channel *c)
+{
+	struct cppi41_dd *cdd = c->cdd;
+	u32 desc_num;
+	u32 desc_phys;
+	u32 reg;
+
+	desc_phys = lower_32_bits(c->desc_phys);
+	desc_num = (desc_phys - cdd->descs_phys) / sizeof(struct cppi41_desc);
+	WARN_ON(cdd->chan_busy[desc_num]);
+	cdd->chan_busy[desc_num] = c;
+
+	reg = (sizeof(struct cppi41_desc) - 24) / 4;
+	reg |= desc_phys;
+	cppi_writel(reg, cdd->qmgr_mem + QMGR_QUEUE_D(c->q_num));
+}
+
+static void cppi41_dma_issue_pending(struct dma_chan *chan)
+{
+	struct cppi41_channel *c = to_cpp41_chan(chan);
+	u32 reg;
+
+	c->residue = 0;
+
+	reg = GCR_CHAN_ENABLE;
+	if (!c->is_tx) {
+		reg |= GCR_STARV_RETRY;
+		reg |= GCR_DESC_TYPE_HOST;
+		reg |= c->q_comp_num;
+	}
+
+	cppi_writel(reg, c->gcr_reg);
+
+	/*
+	 * We don't use writel() but __raw_writel() so we have to make sure
+	 * that the DMA descriptor in coherent memory made to the main memory
+	 * before starting the dma engine.
+	 */
+	__iowmb();
+	push_desc_queue(c);
+}
+
+static u32 get_host_pd0(u32 length)
+{
+	u32 reg;
+
+	reg = DESC_TYPE_HOST << DESC_TYPE;
+	reg |= length;
+
+	return reg;
+}
+
+static u32 get_host_pd1(struct cppi41_channel *c)
+{
+	u32 reg;
+
+	reg = 0;
+
+	return reg;
+}
+
+static u32 get_host_pd2(struct cppi41_channel *c)
+{
+	u32 reg;
+
+	reg = DESC_TYPE_USB;
+	reg |= c->q_comp_num;
+
+	return reg;
+}
+
+static u32 get_host_pd3(u32 length)
+{
+	u32 reg;
+
+	/* PD3 = packet size */
+	reg = length;
+
+	return reg;
+}
+
+static u32 get_host_pd6(u32 length)
+{
+	u32 reg;
+
+	/* PD6 buffer size */
+	reg = DESC_PD_COMPLETE;
+	reg |= length;
+
+	return reg;
+}
+
+static u32 get_host_pd4_or_7(u32 addr)
+{
+	u32 reg;
+
+	reg = addr;
+
+	return reg;
+}
+
+static u32 get_host_pd5(void)
+{
+	u32 reg;
+
+	reg = 0;
+
+	return reg;
+}
+
+static struct dma_async_tx_descriptor *cppi41_dma_prep_slave_sg(
+	struct dma_chan *chan, struct scatterlist *sgl, unsigned sg_len,
+	enum dma_transfer_direction dir, unsigned long tx_flags, void *context)
+{
+	struct cppi41_channel *c = to_cpp41_chan(chan);
+	struct cppi41_desc *d;
+	struct scatterlist *sg;
+	unsigned int i;
+	unsigned int num;
+
+	num = 0;
+	d = c->desc;
+	for_each_sg(sgl, sg, sg_len, i) {
+		u32 addr;
+		u32 len;
+
+		/* We need to use more than one desc once musb supports sg */
+		BUG_ON(num > 0);
+		addr = lower_32_bits(sg_dma_address(sg));
+		len = sg_dma_len(sg);
+
+		d->pd0 = get_host_pd0(len);
+		d->pd1 = get_host_pd1(c);
+		d->pd2 = get_host_pd2(c);
+		d->pd3 = get_host_pd3(len);
+		d->pd4 = get_host_pd4_or_7(addr);
+		d->pd5 = get_host_pd5();
+		d->pd6 = get_host_pd6(len);
+		d->pd7 = get_host_pd4_or_7(addr);
+
+		d++;
+	}
+
+	return &c->txd;
+}
+
+static int cpp41_cfg_chan(struct cppi41_channel *c,
+		struct dma_slave_config *cfg)
+{
+	return 0;
+}
+
+static void cppi41_compute_td_desc(struct cppi41_desc *d)
+{
+	d->pd0 = DESC_TYPE_TEARD << DESC_TYPE;
+}
+
+static u32 cppi41_pop_desc(struct cppi41_dd *cdd, unsigned queue_num)
+{
+	u32 desc;
+
+	desc = cppi_readl(cdd->qmgr_mem + QMGR_QUEUE_D(queue_num));
+	desc &= ~0x1f;
+	return desc;
+}
+
+static int cppi41_tear_down_chan(struct cppi41_channel *c)
+{
+	struct cppi41_dd *cdd = c->cdd;
+	struct cppi41_desc *td;
+	u32 reg;
+	u32 desc_phys;
+	u32 td_desc_phys;
+
+	td = cdd->cd;
+	td += cdd->first_td_desc;
+
+	td_desc_phys = cdd->descs_phys;
+	td_desc_phys += cdd->first_td_desc * sizeof(struct cppi41_desc);
+
+	if (!c->td_queued) {
+		cppi41_compute_td_desc(td);
+		__iowmb();
+
+		reg = (sizeof(struct cppi41_desc) - 24) / 4;
+		reg |= td_desc_phys;
+		cppi_writel(reg, cdd->qmgr_mem +
+				QMGR_QUEUE_D(cdd->td_queue.submit));
+
+		reg = GCR_CHAN_ENABLE;
+		if (!c->is_tx) {
+			reg |= GCR_STARV_RETRY;
+			reg |= GCR_DESC_TYPE_HOST;
+			reg |= c->q_comp_num;
+		}
+		reg |= GCR_TEARDOWN;
+		cppi_writel(reg, c->gcr_reg);
+		c->td_queued = 1;
+		c->td_retry = 100;
+	}
+
+	if (!c->td_seen) {
+		unsigned td_comp_queue;
+
+		if (c->is_tx)
+			td_comp_queue =  cdd->td_queue.complete;
+		else
+			td_comp_queue =  c->q_comp_num;
+
+		desc_phys = cppi41_pop_desc(cdd, td_comp_queue);
+		if (desc_phys) {
+			__iormb();
+
+			if (desc_phys == td_desc_phys) {
+				u32 pd0;
+				pd0 = td->pd0;
+				WARN_ON((pd0 >> DESC_TYPE) != DESC_TYPE_TEARD);
+				WARN_ON(!c->is_tx && !(pd0 & TD_DESC_IS_RX));
+				WARN_ON((pd0 & 0x1f) != c->port_num);
+			} else {
+				__WARN();
+			}
+			c->td_seen = 1;
+		}
+	}
+	if (!c->td_desc_seen) {
+		desc_phys = cppi41_pop_desc(cdd, c->q_comp_num);
+		if (desc_phys) {
+			__iormb();
+			WARN_ON(c->desc_phys != desc_phys);
+			c->td_desc_seen = 1;
+		}
+	}
+	c->td_retry--;
+	/*
+	 * If the TX descriptor / channel is in use, the caller needs to poke
+	 * his TD bit multiple times. After that he hardware releases the
+	 * transfer descriptor followed by TD descriptor. Waiting seems not to
+	 * cause any difference.
+	 * RX seems to be thrown out right away. However once the TearDown
+	 * descriptor gets through we are done. If we have seens the transfer
+	 * descriptor before the TD we fetch it from enqueue, it has to be
+	 * there waiting for us.
+	 */
+	if (!c->td_seen && c->td_retry)
+		return -EAGAIN;
+
+	WARN_ON(!c->td_retry);
+	if (!c->td_desc_seen) {
+		desc_phys = cppi_readl(cdd->qmgr_mem + QMGR_QUEUE_D(c->q_num));
+		WARN_ON(!desc_phys);
+	}
+
+	c->td_queued = 0;
+	c->td_seen = 0;
+	c->td_desc_seen = 0;
+	cppi_writel(0, c->gcr_reg);
+	return 0;
+}
+
+static int cppi41_stop_chan(struct dma_chan *chan)
+{
+	struct cppi41_channel *c = to_cpp41_chan(chan);
+	struct cppi41_dd *cdd = c->cdd;
+	u32 desc_num;
+	u32 desc_phys;
+	int ret;
+
+	ret = cppi41_tear_down_chan(c);
+	if (ret)
+		return ret;
+
+	desc_phys = lower_32_bits(c->desc_phys);
+	desc_num = (desc_phys - cdd->descs_phys) / sizeof(struct cppi41_desc);
+	WARN_ON(!cdd->chan_busy[desc_num]);
+	cdd->chan_busy[desc_num] = NULL;
+
+	return 0;
+}
+
+static int cppi41_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+	unsigned long arg)
+{
+	struct cppi41_channel *c = to_cpp41_chan(chan);
+	int ret;
+
+	switch (cmd) {
+	case DMA_SLAVE_CONFIG:
+		ret = cpp41_cfg_chan(c, (struct dma_slave_config *) arg);
+		break;
+
+	case DMA_TERMINATE_ALL:
+		ret = cppi41_stop_chan(chan);
+		break;
+
+	default:
+		ret = -ENXIO;
+		break;
+	}
+	return ret;
+}
+
+static void cleanup_chans(struct cppi41_dd *cdd)
+{
+	while (!list_empty(&cdd->ddev.channels)) {
+		struct cppi41_channel *cchan;
+
+		cchan = list_first_entry(&cdd->ddev.channels,
+				struct cppi41_channel, chan.device_node);
+		list_del(&cchan->chan.device_node);
+		kfree(cchan);
+	}
+}
+
+static int cppi41_add_chans(struct platform_device *pdev, struct cppi41_dd *cdd)
+{
+	struct cppi41_channel *cchan;
+	int i;
+	int ret;
+	u32 n_chans;
+
+	ret = of_property_read_u32(pdev->dev.of_node, "#dma-channels",
+			&n_chans);
+	if (ret)
+		return ret;
+	/*
+	 * The channels can only be used as TX or as RX. So we add twice
+	 * that much dma channels because USB can only do RX or TX.
+	 */
+	n_chans *= 2;
+
+	for (i = 0; i < n_chans; i++) {
+		cchan = kzalloc(sizeof(*cchan), GFP_KERNEL);
+		if (!cchan)
+			goto err;
+
+		cchan->cdd = cdd;
+		if (i & 1) {
+			cchan->gcr_reg = cdd->ctrl_mem + DMA_TXGCR(i >> 1);
+			cchan->is_tx = 1;
+		} else {
+			cchan->gcr_reg = cdd->ctrl_mem + DMA_RXGCR(i >> 1);
+			cchan->is_tx = 0;
+		}
+		cchan->port_num = i >> 1;
+		cchan->desc = &cdd->cd[i];
+		cchan->desc_phys = cdd->descs_phys;
+		cchan->desc_phys += i * sizeof(struct cppi41_desc);
+		cchan->chan.device = &cdd->ddev;
+		list_add_tail(&cchan->chan.device_node, &cdd->ddev.channels);
+	}
+	cdd->first_td_desc = n_chans;
+
+	return 0;
+err:
+	cleanup_chans(cdd);
+	return -ENOMEM;
+}
+
+static void purge_descs(struct platform_device *pdev, struct cppi41_dd *cdd)
+{
+	unsigned int mem_decs;
+	int i;
+
+	mem_decs = ALLOC_DECS_NUM * sizeof(struct cppi41_desc);
+
+	for (i = 0; i < DESCS_AREAS; i++) {
+
+		cppi_writel(0, cdd->qmgr_mem + QMGR_MEMBASE(i));
+		cppi_writel(0, cdd->qmgr_mem + QMGR_MEMCTRL(i));
+
+		dma_free_coherent(&pdev->dev, mem_decs, cdd->cd,
+				cdd->descs_phys);
+	}
+}
+
+static void disable_sched(struct cppi41_dd *cdd)
+{
+	cppi_writel(0, cdd->sched_mem + DMA_SCHED_CTRL);
+}
+
+static void deinit_cpii41(struct platform_device *pdev, struct cppi41_dd *cdd)
+{
+	disable_sched(cdd);
+
+	purge_descs(pdev, cdd);
+
+	cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM0_BASE);
+	cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM0_BASE);
+	dma_free_coherent(&pdev->dev, QMGR_SCRATCH_SIZE, cdd->qmgr_scratch,
+			cdd->scratch_phys);
+}
+
+static int init_descs(struct platform_device *pdev, struct cppi41_dd *cdd)
+{
+	unsigned int desc_size;
+	unsigned int mem_decs;
+	int i;
+	u32 reg;
+	u32 idx;
+
+	BUILD_BUG_ON(sizeof(struct cppi41_desc) &
+			(sizeof(struct cppi41_desc) - 1));
+	BUILD_BUG_ON(sizeof(struct cppi41_desc) < 32);
+	BUILD_BUG_ON(ALLOC_DECS_NUM < 32);
+
+	desc_size = sizeof(struct cppi41_desc);
+	mem_decs = ALLOC_DECS_NUM * desc_size;
+
+	idx = 0;
+	for (i = 0; i < DESCS_AREAS; i++) {
+
+		reg = idx << QMGR_MEMCTRL_IDX_SH;
+		reg |= (ilog2(desc_size) - 5) << QMGR_MEMCTRL_DESC_SH;
+		reg |= ilog2(ALLOC_DECS_NUM) - 5;
+
+		BUILD_BUG_ON(DESCS_AREAS != 1);
+		cdd->cd = dma_alloc_coherent(&pdev->dev, mem_decs,
+				&cdd->descs_phys, GFP_KERNEL);
+		if (!cdd->cd)
+			return -ENOMEM;
+
+		cppi_writel(cdd->descs_phys, cdd->qmgr_mem + QMGR_MEMBASE(i));
+		cppi_writel(reg, cdd->qmgr_mem + QMGR_MEMCTRL(i));
+
+		idx += ALLOC_DECS_NUM;
+	}
+	return 0;
+}
+
+static void init_sched(struct cppi41_dd *cdd)
+{
+	unsigned ch;
+	unsigned word;
+	u32 reg;
+
+	word = 0;
+	cppi_writel(0, cdd->sched_mem + DMA_SCHED_CTRL);
+	for (ch = 0; ch < 15 * 2; ch += 2) {
+
+		reg = SCHED_ENTRY0_CHAN(ch);
+		reg |= SCHED_ENTRY1_CHAN(ch) | SCHED_ENTRY1_IS_RX;
+
+		reg |= SCHED_ENTRY2_CHAN(ch + 1);
+		reg |= SCHED_ENTRY3_CHAN(ch + 1) | SCHED_ENTRY3_IS_RX;
+		cppi_writel(reg, cdd->sched_mem + DMA_SCHED_WORD(word));
+		word++;
+	}
+	reg = 15 * 2 * 2 - 1;
+	reg |= DMA_SCHED_CTRL_EN;
+	cppi_writel(reg, cdd->sched_mem + DMA_SCHED_CTRL);
+}
+
+static int init_cppi41(struct platform_device *pdev, struct cppi41_dd *cdd)
+{
+	int ret;
+
+	BUILD_BUG_ON(QMGR_SCRATCH_SIZE > ((1 << 14) - 1));
+	cdd->qmgr_scratch = dma_alloc_coherent(&pdev->dev, QMGR_SCRATCH_SIZE,
+			&cdd->scratch_phys, GFP_KERNEL);
+	if (!cdd->qmgr_scratch)
+		return -ENOMEM;
+
+	cppi_writel(cdd->scratch_phys, cdd->qmgr_mem + QMGR_LRAM0_BASE);
+	cppi_writel(QMGR_SCRATCH_SIZE, cdd->qmgr_mem + QMGR_LRAM_SIZE);
+	cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM1_BASE);
+
+	ret = init_descs(pdev, cdd);
+	if (ret)
+		goto err_td;
+
+	cppi_writel(cdd->td_queue.submit, cdd->ctrl_mem + DMA_TDFDQ);
+	init_sched(cdd);
+	return 0;
+err_td:
+	deinit_cpii41(pdev, cdd);
+	return ret;
+}
+
+static struct platform_driver cpp41_dma_driver;
+/*
+ * The param format is:
+ * X Y
+ * X: Port
+ * Y: 0 = RX else TX
+ */
+#define INFO_PORT	0
+#define INFO_IS_TX	1
+
+static bool cpp41_dma_filter_fn(struct dma_chan *chan, void *param)
+{
+	struct cppi41_channel *cchan;
+	struct cppi41_dd *cdd;
+	const struct chan_queues *queues;
+	u32 *num = param;
+
+	if (chan->device->dev->driver != &cpp41_dma_driver.driver)
+		return false;
+
+	cchan = to_cpp41_chan(chan);
+
+	if (cchan->port_num != num[INFO_PORT])
+		return false;
+
+	if (cchan->is_tx && !num[INFO_IS_TX])
+		return false;
+	cdd = cchan->cdd;
+	if (cchan->is_tx)
+		queues = cdd->queues_tx;
+	else
+		queues = cdd->queues_rx;
+
+	BUILD_BUG_ON(ARRAY_SIZE(usb_queues_rx) != ARRAY_SIZE(usb_queues_tx));
+	if (WARN_ON(cchan->port_num > ARRAY_SIZE(usb_queues_rx)))
+		return false;
+
+	cchan->q_num = queues[cchan->port_num].submit;
+	cchan->q_comp_num = queues[cchan->port_num].complete;
+	return true;
+}
+
+static struct of_dma_filter_info cpp41_dma_info = {
+	.filter_fn = cpp41_dma_filter_fn,
+};
+
+static struct dma_chan *cppi41_dma_xlate(struct of_phandle_args *dma_spec,
+		struct of_dma *ofdma)
+{
+	int count = dma_spec->args_count;
+	struct of_dma_filter_info *info = ofdma->of_dma_data;
+
+	if (!info || !info->filter_fn)
+		return NULL;
+
+	if (count != 2)
+		return NULL;
+
+	return dma_request_channel(info->dma_cap, info->filter_fn,
+			&dma_spec->args[0]);
+}
+
+static const struct cppi_glue_infos usb_infos = {
+	.isr = cppi41_irq,
+	.queues_rx = usb_queues_rx,
+	.queues_tx = usb_queues_tx,
+	.td_queue = { .submit = 31, .complete = 0 },
+};
+
+static const struct of_device_id cppi41_dma_ids[] = {
+	{ .compatible = "ti,am3359-cppi41", .data = &usb_infos},
+	{},
+};
+MODULE_DEVICE_TABLE(of, cppi41_dma_ids);
+
+static const struct cppi_glue_infos *get_glue_info(struct platform_device *pdev)
+{
+	const struct of_device_id *of_id;
+
+	of_id = of_match_node(cppi41_dma_ids, pdev->dev.of_node);
+	if (!of_id)
+		return NULL;
+	return of_id->data;
+}
+
+static int cppi41_dma_probe(struct platform_device *pdev)
+{
+	struct cppi41_dd *cdd;
+	const struct cppi_glue_infos *glue_info;
+	int irq;
+	int ret;
+
+	glue_info = get_glue_info(pdev);
+	if (!glue_info)
+		return -EINVAL;
+
+	cdd = kzalloc(sizeof(*cdd), GFP_KERNEL);
+	if (!cdd)
+		return -ENOMEM;
+
+	dma_cap_set(DMA_SLAVE, cdd->ddev.cap_mask);
+	cdd->ddev.device_alloc_chan_resources = cppi41_dma_alloc_chan_resources;
+	cdd->ddev.device_free_chan_resources = cppi41_dma_free_chan_resources;
+	cdd->ddev.device_tx_status = cppi41_dma_tx_status;
+	cdd->ddev.device_issue_pending = cppi41_dma_issue_pending;
+	cdd->ddev.device_prep_slave_sg = cppi41_dma_prep_slave_sg;
+	cdd->ddev.device_control = cppi41_dma_control;
+	cdd->ddev.dev = &pdev->dev;
+	INIT_LIST_HEAD(&cdd->ddev.channels);
+	cpp41_dma_info.dma_cap = cdd->ddev.cap_mask;
+
+	cdd->usbss_mem = of_iomap(pdev->dev.of_node, 0);
+	cdd->ctrl_mem = of_iomap(pdev->dev.of_node, 1);
+	cdd->sched_mem = of_iomap(pdev->dev.of_node, 2);
+	cdd->qmgr_mem = of_iomap(pdev->dev.of_node, 3);
+
+	if (!cdd->usbss_mem || !cdd->ctrl_mem || !cdd->sched_mem ||
+			!cdd->qmgr_mem) {
+		ret = -ENXIO;
+		goto err_remap;
+	}
+
+	cdd->queues_rx = glue_info->queues_rx;
+	cdd->queues_tx = glue_info->queues_tx;
+	cdd->td_queue = glue_info->td_queue;
+
+	ret = init_cppi41(pdev, cdd);
+	if (ret)
+		goto err_init_cppi;
+
+	ret = cppi41_add_chans(pdev, cdd);
+	if (ret)
+		goto err_chans;
+
+	irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+	if (!irq)
+		goto err_irq;
+
+	cppi_writel(USBSS_IRQ_PD_COMP, cdd->usbss_mem + USBSS_IRQ_ENABLER);
+
+	ret = request_irq(irq, glue_info->isr, IRQF_SHARED,
+			dev_name(&pdev->dev), cdd);
+	if (ret)
+		goto err_irq;
+	cdd->irq = irq;
+
+	ret = dma_async_device_register(&cdd->ddev);
+	if (ret)
+		goto err_dma_reg;
+
+	ret = of_dma_controller_register(pdev->dev.of_node,
+			cppi41_dma_xlate, &cpp41_dma_info);
+	if (ret)
+		goto err_of;
+
+	platform_set_drvdata(pdev, cdd);
+	return 0;
+err_of:
+	dma_async_device_unregister(&cdd->ddev);
+err_dma_reg:
+	free_irq(irq, cdd);
+err_irq:
+	cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR);
+	cleanup_chans(cdd);
+err_chans:
+	deinit_cpii41(pdev, cdd);
+err_init_cppi:
+	iounmap(cdd->usbss_mem);
+	iounmap(cdd->ctrl_mem);
+	iounmap(cdd->sched_mem);
+	iounmap(cdd->qmgr_mem);
+err_remap:
+	kfree(cdd);
+	return ret;
+}
+
+static int cppi41_dma_remove(struct platform_device *pdev)
+{
+	struct cppi41_dd *cdd = platform_get_drvdata(pdev);
+
+	of_dma_controller_free(pdev->dev.of_node);
+	dma_async_device_unregister(&cdd->ddev);
+
+	cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR);
+	free_irq(cdd->irq, cdd);
+	cleanup_chans(cdd);
+	deinit_cpii41(pdev, cdd);
+	iounmap(cdd->usbss_mem);
+	iounmap(cdd->ctrl_mem);
+	iounmap(cdd->sched_mem);
+	iounmap(cdd->qmgr_mem);
+	kfree(cdd);
+	return 0;
+}
+
+static struct platform_driver cpp41_dma_driver = {
+	.probe  = cppi41_dma_probe,
+	.remove = cppi41_dma_remove,
+	.driver = {
+		.name = "cppi41-dma-engine",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(cppi41_dma_ids),
+	},
+};
+
+module_platform_driver(cpp41_dma_driver);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");

+ 1 - 1
drivers/usb/Makefile

@@ -46,7 +46,7 @@ obj-$(CONFIG_USB_MICROTEK)	+= image/
 obj-$(CONFIG_USB_SERIAL)	+= serial/
 
 obj-$(CONFIG_USB)		+= misc/
-obj-$(CONFIG_USB_PHY)		+= phy/
+obj-$(CONFIG_USB_SUPPORT)	+= phy/
 obj-$(CONFIG_EARLY_PRINTK_DBGP)	+= early/
 
 obj-$(CONFIG_USB_ATM)		+= atm/

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

@@ -63,6 +63,7 @@ static int host_start(struct ci_hdrc *ci)
 	ehci = hcd_to_ehci(hcd);
 	ehci->caps = ci->hw_bank.cap;
 	ehci->has_hostpc = ci->hw_bank.lpm;
+	ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
 
 	ret = usb_add_hcd(hcd, 0, 0);
 	if (ret)

+ 32 - 0
drivers/usb/dwc3/Kconfig

@@ -40,6 +40,38 @@ config USB_DWC3_DUAL_ROLE
 
 endchoice
 
+comment "Platform Glue Driver Support"
+
+config USB_DWC3_OMAP
+	tristate "Texas Instruments OMAP5 and similar Platforms"
+	depends on EXTCON
+	default USB_DWC3
+	help
+	  Some platforms from Texas Instruments like OMAP5, DRA7xxx and
+	  AM437x use this IP for USB2/3 functionality.
+
+	  Say 'Y' or 'M' here if you have one such device
+
+config USB_DWC3_EXYNOS
+	tristate "Samsung Exynos Platform"
+	default USB_DWC3
+	help
+	  Recent Exynos5 SoCs ship with one DesignWare Core USB3 IP inside,
+	  say 'Y' or 'M' if you have one such device.
+
+config USB_DWC3_PCI
+	tristate "PCIe-based Platforms"
+	depends on PCI
+	default USB_DWC3
+	help
+	  If you're using the DesignWare Core IP with a PCIe, please say
+	  'Y' or 'M' here.
+
+	  One such PCIe-based platform is Synopsys' PCIe HAPS model of
+	  this IP.
+
+comment "Debugging features"
+
 config USB_DWC3_DEBUG
 	bool "Enable Debugging Messages"
 	help

+ 3 - 10
drivers/usb/dwc3/Makefile

@@ -27,15 +27,8 @@ endif
 # the entire driver (with all its glue layers) on several architectures
 # and make sure it compiles fine. This will also help with allmodconfig
 # and allyesconfig builds.
-#
-# The only exception is the PCI glue layer, but that's only because
-# PCI doesn't provide nops if CONFIG_PCI isn't enabled.
 ##
 
-obj-$(CONFIG_USB_DWC3)		+= dwc3-omap.o
-obj-$(CONFIG_USB_DWC3)		+= dwc3-exynos.o
-
-ifneq ($(CONFIG_PCI),)
-	obj-$(CONFIG_USB_DWC3)		+= dwc3-pci.o
-endif
-
+obj-$(CONFIG_USB_DWC3_OMAP)		+= dwc3-omap.o
+obj-$(CONFIG_USB_DWC3_EXYNOS)		+= dwc3-exynos.o
+obj-$(CONFIG_USB_DWC3_PCI)		+= dwc3-pci.o

+ 86 - 107
drivers/usb/dwc3/core.c

@@ -6,34 +6,17 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/module.h>
@@ -53,17 +36,16 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/of.h>
+#include <linux/usb/otg.h>
 
+#include "platform_data.h"
 #include "core.h"
 #include "gadget.h"
 #include "io.h"
 
 #include "debug.h"
 
-static char *maximum_speed = "super";
-module_param(maximum_speed, charp, 0);
-MODULE_PARM_DESC(maximum_speed, "Maximum supported speed.");
-
 /* -------------------------------------------------------------------------- */
 
 void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
@@ -236,7 +218,7 @@ static int dwc3_event_buffers_setup(struct dwc3 *dwc)
 		dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
 				upper_32_bits(evt->dma));
 		dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
-				evt->length & 0xffff);
+				DWC3_GEVNTSIZ_SIZE(evt->length));
 		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
 	}
 
@@ -255,7 +237,8 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
 
 		dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
 		dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
-		dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0);
+		dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK
+				| DWC3_GEVNTSIZ_SIZE(0));
 		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
 	}
 }
@@ -367,18 +350,17 @@ static void dwc3_core_exit(struct dwc3 *dwc)
 
 static int dwc3_probe(struct platform_device *pdev)
 {
-	struct device_node	*node = pdev->dev.of_node;
+	struct device		*dev = &pdev->dev;
+	struct dwc3_platform_data *pdata = dev_get_platdata(dev);
+	struct device_node	*node = dev->of_node;
 	struct resource		*res;
 	struct dwc3		*dwc;
-	struct device		*dev = &pdev->dev;
 
 	int			ret = -ENOMEM;
 
 	void __iomem		*regs;
 	void			*mem;
 
-	u8			mode;
-
 	mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
 	if (!mem) {
 		dev_err(dev, "not enough memory\n");
@@ -402,38 +384,29 @@ static int dwc3_probe(struct platform_device *pdev)
 		dev_err(dev, "missing memory resource\n");
 		return -ENODEV;
 	}
-	dwc->xhci_resources[0].start = res->start;
-	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
-					DWC3_XHCI_REGS_END;
-	dwc->xhci_resources[0].flags = res->flags;
-	dwc->xhci_resources[0].name = res->name;
-
-	 /*
-	  * Request memory region but exclude xHCI regs,
-	  * since it will be requested by the xhci-plat driver.
-	  */
-	res = devm_request_mem_region(dev, res->start + DWC3_GLOBALS_REGS_START,
-			resource_size(res) - DWC3_GLOBALS_REGS_START,
-			dev_name(dev));
-	if (!res) {
-		dev_err(dev, "can't request mem region\n");
-		return -ENOMEM;
-	}
-
-	regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
-	if (!regs) {
-		dev_err(dev, "ioremap failed\n");
-		return -ENOMEM;
-	}
 
 	if (node) {
+		dwc->maximum_speed = of_usb_get_maximum_speed(node);
+
 		dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
 		dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
+
+		dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
+		dwc->dr_mode = of_usb_get_dr_mode(node);
 	} else {
+		dwc->maximum_speed = pdata->maximum_speed;
+
 		dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 		dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
+
+		dwc->needs_fifo_resize = pdata->tx_fifo_resize;
+		dwc->dr_mode = pdata->dr_mode;
 	}
 
+	/* default to superspeed if no maximum_speed passed */
+	if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
+		dwc->maximum_speed = USB_SPEED_SUPER;
+
 	if (IS_ERR(dwc->usb2_phy)) {
 		ret = PTR_ERR(dwc->usb2_phy);
 
@@ -464,6 +437,22 @@ static int dwc3_probe(struct platform_device *pdev)
 		return -EPROBE_DEFER;
 	}
 
+	dwc->xhci_resources[0].start = res->start;
+	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
+					DWC3_XHCI_REGS_END;
+	dwc->xhci_resources[0].flags = res->flags;
+	dwc->xhci_resources[0].name = res->name;
+
+	res->start += DWC3_GLOBALS_REGS_START;
+
+	/*
+	 * Request memory region but exclude xHCI regs,
+	 * since it will be requested by the xhci-plat driver.
+	 */
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
 	usb_phy_set_suspend(dwc->usb2_phy, 0);
 	usb_phy_set_suspend(dwc->usb3_phy, 0);
 
@@ -478,19 +467,6 @@ static int dwc3_probe(struct platform_device *pdev)
 	dev->dma_parms	= dev->parent->dma_parms;
 	dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
 
-	if (!strncmp("super", maximum_speed, 5))
-		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
-	else if (!strncmp("high", maximum_speed, 4))
-		dwc->maximum_speed = DWC3_DCFG_HIGHSPEED;
-	else if (!strncmp("full", maximum_speed, 4))
-		dwc->maximum_speed = DWC3_DCFG_FULLSPEED1;
-	else if (!strncmp("low", maximum_speed, 3))
-		dwc->maximum_speed = DWC3_DCFG_LOWSPEED;
-	else
-		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
-
-	dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
-
 	pm_runtime_enable(dev);
 	pm_runtime_get_sync(dev);
 	pm_runtime_forbid(dev);
@@ -517,14 +493,15 @@ static int dwc3_probe(struct platform_device *pdev)
 	}
 
 	if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
-		mode = DWC3_MODE_HOST;
+		dwc->dr_mode = USB_DR_MODE_HOST;
 	else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
-		mode = DWC3_MODE_DEVICE;
-	else
-		mode = DWC3_MODE_DRD;
+		dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
+
+	if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
+		dwc->dr_mode = USB_DR_MODE_OTG;
 
-	switch (mode) {
-	case DWC3_MODE_DEVICE:
+	switch (dwc->dr_mode) {
+	case USB_DR_MODE_PERIPHERAL:
 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
 		ret = dwc3_gadget_init(dwc);
 		if (ret) {
@@ -532,7 +509,7 @@ static int dwc3_probe(struct platform_device *pdev)
 			goto err2;
 		}
 		break;
-	case DWC3_MODE_HOST:
+	case USB_DR_MODE_HOST:
 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
 		ret = dwc3_host_init(dwc);
 		if (ret) {
@@ -540,7 +517,7 @@ static int dwc3_probe(struct platform_device *pdev)
 			goto err2;
 		}
 		break;
-	case DWC3_MODE_DRD:
+	case USB_DR_MODE_OTG:
 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
 		ret = dwc3_host_init(dwc);
 		if (ret) {
@@ -555,10 +532,9 @@ static int dwc3_probe(struct platform_device *pdev)
 		}
 		break;
 	default:
-		dev_err(dev, "Unsupported mode of operation %d\n", mode);
+		dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
 		goto err2;
 	}
-	dwc->mode = mode;
 
 	ret = dwc3_debugfs_init(dwc);
 	if (ret) {
@@ -571,14 +547,14 @@ static int dwc3_probe(struct platform_device *pdev)
 	return 0;
 
 err3:
-	switch (mode) {
-	case DWC3_MODE_DEVICE:
+	switch (dwc->dr_mode) {
+	case USB_DR_MODE_PERIPHERAL:
 		dwc3_gadget_exit(dwc);
 		break;
-	case DWC3_MODE_HOST:
+	case USB_DR_MODE_HOST:
 		dwc3_host_exit(dwc);
 		break;
-	case DWC3_MODE_DRD:
+	case USB_DR_MODE_OTG:
 		dwc3_host_exit(dwc);
 		dwc3_gadget_exit(dwc);
 		break;
@@ -611,14 +587,14 @@ static int dwc3_remove(struct platform_device *pdev)
 
 	dwc3_debugfs_exit(dwc);
 
-	switch (dwc->mode) {
-	case DWC3_MODE_DEVICE:
+	switch (dwc->dr_mode) {
+	case USB_DR_MODE_PERIPHERAL:
 		dwc3_gadget_exit(dwc);
 		break;
-	case DWC3_MODE_HOST:
+	case USB_DR_MODE_HOST:
 		dwc3_host_exit(dwc);
 		break;
-	case DWC3_MODE_DRD:
+	case USB_DR_MODE_OTG:
 		dwc3_host_exit(dwc);
 		dwc3_gadget_exit(dwc);
 		break;
@@ -642,12 +618,12 @@ static int dwc3_prepare(struct device *dev)
 
 	spin_lock_irqsave(&dwc->lock, flags);
 
-	switch (dwc->mode) {
-	case DWC3_MODE_DEVICE:
-	case DWC3_MODE_DRD:
+	switch (dwc->dr_mode) {
+	case USB_DR_MODE_PERIPHERAL:
+	case USB_DR_MODE_OTG:
 		dwc3_gadget_prepare(dwc);
 		/* FALLTHROUGH */
-	case DWC3_MODE_HOST:
+	case USB_DR_MODE_HOST:
 	default:
 		dwc3_event_buffers_cleanup(dwc);
 		break;
@@ -665,12 +641,12 @@ static void dwc3_complete(struct device *dev)
 
 	spin_lock_irqsave(&dwc->lock, flags);
 
-	switch (dwc->mode) {
-	case DWC3_MODE_DEVICE:
-	case DWC3_MODE_DRD:
+	switch (dwc->dr_mode) {
+	case USB_DR_MODE_PERIPHERAL:
+	case USB_DR_MODE_OTG:
 		dwc3_gadget_complete(dwc);
 		/* FALLTHROUGH */
-	case DWC3_MODE_HOST:
+	case USB_DR_MODE_HOST:
 	default:
 		dwc3_event_buffers_setup(dwc);
 		break;
@@ -686,12 +662,12 @@ static int dwc3_suspend(struct device *dev)
 
 	spin_lock_irqsave(&dwc->lock, flags);
 
-	switch (dwc->mode) {
-	case DWC3_MODE_DEVICE:
-	case DWC3_MODE_DRD:
+	switch (dwc->dr_mode) {
+	case USB_DR_MODE_PERIPHERAL:
+	case USB_DR_MODE_OTG:
 		dwc3_gadget_suspend(dwc);
 		/* FALLTHROUGH */
-	case DWC3_MODE_HOST:
+	case USB_DR_MODE_HOST:
 	default:
 		/* do nothing */
 		break;
@@ -719,12 +695,12 @@ static int dwc3_resume(struct device *dev)
 
 	dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl);
 
-	switch (dwc->mode) {
-	case DWC3_MODE_DEVICE:
-	case DWC3_MODE_DRD:
+	switch (dwc->dr_mode) {
+	case USB_DR_MODE_PERIPHERAL:
+	case USB_DR_MODE_OTG:
 		dwc3_gadget_resume(dwc);
 		/* FALLTHROUGH */
-	case DWC3_MODE_HOST:
+	case USB_DR_MODE_HOST:
 	default:
 		/* do nothing */
 		break;
@@ -753,6 +729,9 @@ static const struct dev_pm_ops dwc3_dev_pm_ops = {
 
 #ifdef CONFIG_OF
 static const struct of_device_id of_dwc3_match[] = {
+	{
+		.compatible = "snps,dwc3"
+	},
 	{
 		.compatible = "synopsys,dwc3"
 	},
@@ -775,5 +754,5 @@ module_platform_driver(dwc3_driver);
 
 MODULE_ALIAS("platform:dwc3");
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
-MODULE_LICENSE("Dual BSD/GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");

+ 16 - 37
drivers/usb/dwc3/core.h

@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef __DRIVERS_USB_DWC3_CORE_H
@@ -49,6 +29,7 @@
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
 
 /* Global constants */
 #define DWC3_EP0_BOUNCE_SIZE	512
@@ -194,6 +175,10 @@
 #define DWC3_GTXFIFOSIZ_TXFDEF(n)	((n) & 0xffff)
 #define DWC3_GTXFIFOSIZ_TXFSTADDR(n)	((n) & 0xffff0000)
 
+/* Global Event Size Registers */
+#define DWC3_GEVNTSIZ_INTMASK		(1 << 31)
+#define DWC3_GEVNTSIZ_SIZE(n)		((n) & 0xffff)
+
 /* Global HWPARAMS1 Register */
 #define DWC3_GHWPARAMS1_EN_PWROPT(n)	(((n) & (3 << 24)) >> 24)
 #define DWC3_GHWPARAMS1_EN_PWROPT_NO	0
@@ -207,7 +192,6 @@
 #define DWC3_MAX_HIBER_SCRATCHBUFS		15
 
 /* Device Configuration Register */
-#define DWC3_DCFG_LPM_CAP	(1 << 22)
 #define DWC3_DCFG_DEVADDR(addr)	((addr) << 3)
 #define DWC3_DCFG_DEVADDR_MASK	DWC3_DCFG_DEVADDR(0x7f)
 
@@ -367,7 +351,6 @@ struct dwc3_trb;
 
 /**
  * struct dwc3_event_buffer - Software event buffer representation
- * @list: a list of event buffers
  * @buf: _THE_ buffer
  * @length: size of this buffer
  * @lpos: event offset
@@ -415,7 +398,7 @@ struct dwc3_event_buffer {
  * @number: endpoint number (1 - 15)
  * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
  * @resource_index: Resource transfer index
- * @interval: the intervall on which the ISOC transfer is started
+ * @interval: the interval on which the ISOC transfer is started
  * @name: a human readable name e.g. ep1out-bulk
  * @direction: true for TX, false for RX
  * @stream_capable: true when streams are enabled
@@ -566,11 +549,6 @@ struct dwc3_hwparams {
 /* HWPARAMS0 */
 #define DWC3_MODE(n)		((n) & 0x7)
 
-#define DWC3_MODE_DEVICE	0
-#define DWC3_MODE_HOST		1
-#define DWC3_MODE_DRD		2
-#define DWC3_MODE_HUB		3
-
 #define DWC3_MDWIDTH(n)		(((n) & 0xff00) >> 8)
 
 /* HWPARAMS1 */
@@ -632,7 +610,7 @@ struct dwc3_scratchpad_array {
  * @u1u2: only used on revisions <1.83a for workaround
  * @maximum_speed: maximum speed requested (mainly for testing purposes)
  * @revision: revision register contents
- * @mode: mode of operation
+ * @dr_mode: requested mode of operation
  * @usb2_phy: pointer to USB2 PHY
  * @usb3_phy: pointer to USB3 PHY
  * @dcfg: saved contents of DCFG register
@@ -690,6 +668,8 @@ struct dwc3 {
 	void __iomem		*regs;
 	size_t			regs_size;
 
+	enum usb_dr_mode	dr_mode;
+
 	/* used for suspend/resume */
 	u32			dcfg;
 	u32			gctl;
@@ -698,7 +678,6 @@ struct dwc3 {
 	u32			u1u2;
 	u32			maximum_speed;
 	u32			revision;
-	u32			mode;
 
 #define DWC3_REVISION_173A	0x5533173a
 #define DWC3_REVISION_175A	0x5533175a

+ 7 - 27
drivers/usb/dwc3/debug.h

@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include "core.h"

+ 7 - 27
drivers/usb/dwc3/debugfs.c

@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/kernel.h>

+ 13 - 9
drivers/usb/dwc3/dwc3-exynos.c

@@ -6,10 +6,14 @@
  *
  * Author: Anton Tikhomirov <av.tikhomirov@samsung.com>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
@@ -20,7 +24,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
 #include <linux/usb/otg.h>
-#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 
@@ -34,13 +38,13 @@ struct dwc3_exynos {
 
 static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
 {
-	struct nop_usb_xceiv_platform_data pdata;
+	struct usb_phy_gen_xceiv_platform_data pdata;
 	struct platform_device	*pdev;
 	int			ret;
 
 	memset(&pdata, 0x00, sizeof(pdata));
 
-	pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
+	pdev = platform_device_alloc("usb_phy_gen_xceiv", PLATFORM_DEVID_AUTO);
 	if (!pdev)
 		return -ENOMEM;
 
@@ -51,7 +55,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
 	if (ret)
 		goto err1;
 
-	pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
+	pdev = platform_device_alloc("usb_phy_gen_xceiv", PLATFORM_DEVID_AUTO);
 	if (!pdev) {
 		ret = -ENOMEM;
 		goto err1;
@@ -228,5 +232,5 @@ module_platform_driver(dwc3_exynos_driver);
 
 MODULE_ALIAS("platform:exynos-dwc3");
 MODULE_AUTHOR("Anton Tikhomirov <av.tikhomirov@samsung.com>");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("DesignWare USB3 EXYNOS Glue Layer");

+ 11 - 33
drivers/usb/dwc3/dwc3-omap.c

@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/module.h>
@@ -409,11 +389,9 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	base = devm_ioremap_nocache(dev, res->start, resource_size(res));
-	if (!base) {
-		dev_err(dev, "ioremap failed\n");
-		return -ENOMEM;
-	}
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
 	spin_lock_init(&omap->lock);
 
@@ -610,5 +588,5 @@ module_platform_driver(dwc3_omap_driver);
 
 MODULE_ALIAS("platform:omap-dwc3");
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
-MODULE_LICENSE("Dual BSD/GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("DesignWare USB3 OMAP Glue Layer");

+ 15 - 39
drivers/usb/dwc3/dwc3-pci.c

@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/kernel.h>
@@ -43,7 +23,7 @@
 #include <linux/platform_device.h>
 
 #include <linux/usb/otg.h>
-#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
 
 /* FIXME define these in <linux/pci_ids.h> */
 #define PCI_VENDOR_ID_SYNOPSYS		0x16c3
@@ -58,13 +38,13 @@ struct dwc3_pci {
 
 static int dwc3_pci_register_phys(struct dwc3_pci *glue)
 {
-	struct nop_usb_xceiv_platform_data pdata;
+	struct usb_phy_gen_xceiv_platform_data pdata;
 	struct platform_device	*pdev;
 	int			ret;
 
 	memset(&pdata, 0x00, sizeof(pdata));
 
-	pdev = platform_device_alloc("nop_usb_xceiv", 0);
+	pdev = platform_device_alloc("usb_phy_gen_xceiv", 0);
 	if (!pdev)
 		return -ENOMEM;
 
@@ -75,7 +55,7 @@ static int dwc3_pci_register_phys(struct dwc3_pci *glue)
 	if (ret)
 		goto err1;
 
-	pdev = platform_device_alloc("nop_usb_xceiv", 1);
+	pdev = platform_device_alloc("usb_phy_gen_xceiv", 1);
 	if (!pdev) {
 		ret = -ENOMEM;
 		goto err1;
@@ -211,7 +191,7 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
 };
 MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int dwc3_pci_suspend(struct device *dev)
 {
 	struct pci_dev	*pci = to_pci_dev(dev);
@@ -236,28 +216,24 @@ static int dwc3_pci_resume(struct device *dev)
 
 	return 0;
 }
+#endif /* CONFIG_PM_SLEEP */
 
 static const struct dev_pm_ops dwc3_pci_dev_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
 };
 
-#define DEV_PM_OPS	(&dwc3_pci_dev_pm_ops)
-#else
-#define DEV_PM_OPS	NULL
-#endif /* CONFIG_PM */
-
 static struct pci_driver dwc3_pci_driver = {
 	.name		= "dwc3-pci",
 	.id_table	= dwc3_pci_id_table,
 	.probe		= dwc3_pci_probe,
 	.remove		= dwc3_pci_remove,
 	.driver		= {
-		.pm	= DEV_PM_OPS,
+		.pm	= &dwc3_pci_dev_pm_ops,
 	},
 };
 
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
-MODULE_LICENSE("Dual BSD/GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer");
 
 module_pci_driver(dwc3_pci_driver);

+ 19 - 30
drivers/usb/dwc3/ep0.c

@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/kernel.h>
@@ -168,6 +148,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
 
 		direction = !dwc->ep0_expect_in;
 		dwc->delayed_status = false;
+		usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED);
 
 		if (dwc->ep0state == EP0_STATUS_PHASE)
 			__dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
@@ -553,8 +534,16 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 		ret = dwc3_ep0_delegate_req(dwc, ctrl);
 		/* if the cfg matches and the cfg is non zero */
 		if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
-			usb_gadget_set_state(&dwc->gadget,
-					USB_STATE_CONFIGURED);
+
+			/*
+			 * only change state if set_config has already
+			 * been processed. If gadget driver returns
+			 * USB_GADGET_DELAYED_STATUS, we will wait
+			 * to change the state on the next usb_ep_queue()
+			 */
+			if (ret == 0)
+				usb_gadget_set_state(&dwc->gadget,
+						USB_STATE_CONFIGURED);
 
 			/*
 			 * Enable transition to U1/U2 state when
@@ -571,7 +560,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 
 	case USB_STATE_CONFIGURED:
 		ret = dwc3_ep0_delegate_req(dwc, ctrl);
-		if (!cfg)
+		if (!cfg && !ret)
 			usb_gadget_set_state(&dwc->gadget,
 					USB_STATE_ADDRESS);
 		break;

+ 106 - 151
drivers/usb/dwc3/gadget.c

@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/kernel.h>
@@ -520,6 +500,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
 	u32			reg;
 	int			ret = -ENOMEM;
 
+	dev_vdbg(dwc->dev, "Enabling %s\n", dep->name);
+
 	if (!(dep->flags & DWC3_EP_ENABLED)) {
 		ret = dwc3_gadget_start_config(dwc, dep);
 		if (ret)
@@ -676,8 +658,6 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
 		dev_err(dwc->dev, "invalid endpoint transfer type\n");
 	}
 
-	dev_vdbg(dwc->dev, "Enabling %s\n", dep->name);
-
 	spin_lock_irqsave(&dwc->lock, flags);
 	ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false);
 	spin_unlock_irqrestore(&dwc->lock, flags);
@@ -1508,6 +1488,15 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 	int			irq;
 	u32			reg;
 
+	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+	ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
+			IRQF_SHARED, "dwc3", dwc);
+	if (ret) {
+		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+				irq, ret);
+		goto err0;
+	}
+
 	spin_lock_irqsave(&dwc->lock, flags);
 
 	if (dwc->gadget_driver) {
@@ -1515,7 +1504,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 				dwc->gadget.name,
 				dwc->gadget_driver->driver.name);
 		ret = -EBUSY;
-		goto err0;
+		goto err1;
 	}
 
 	dwc->gadget_driver	= driver;
@@ -1536,10 +1525,25 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 	 * STAR#9000525659: Clock Domain Crossing on DCTL in
 	 * USB 2.0 Mode
 	 */
-	if (dwc->revision < DWC3_REVISION_220A)
+	if (dwc->revision < DWC3_REVISION_220A) {
 		reg |= DWC3_DCFG_SUPERSPEED;
-	else
-		reg |= dwc->maximum_speed;
+	} else {
+		switch (dwc->maximum_speed) {
+		case USB_SPEED_LOW:
+			reg |= DWC3_DSTS_LOWSPEED;
+			break;
+		case USB_SPEED_FULL:
+			reg |= DWC3_DSTS_FULLSPEED1;
+			break;
+		case USB_SPEED_HIGH:
+			reg |= DWC3_DSTS_HIGHSPEED;
+			break;
+		case USB_SPEED_SUPER:	/* FALLTHROUGH */
+		case USB_SPEED_UNKNOWN:	/* FALTHROUGH */
+		default:
+			reg |= DWC3_DSTS_SUPERSPEED;
+		}
+	}
 	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 
 	dwc->start_config_issued = false;
@@ -1551,42 +1555,38 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
 	if (ret) {
 		dev_err(dwc->dev, "failed to enable %s\n", dep->name);
-		goto err0;
+		goto err2;
 	}
 
 	dep = dwc->eps[1];
 	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
 	if (ret) {
 		dev_err(dwc->dev, "failed to enable %s\n", dep->name);
-		goto err1;
+		goto err3;
 	}
 
 	/* begin to receive SETUP packets */
 	dwc->ep0state = EP0_SETUP_PHASE;
 	dwc3_ep0_out_start(dwc);
 
-	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-	ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
-			IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
-	if (ret) {
-		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
-				irq, ret);
-		goto err1;
-	}
-
 	dwc3_gadget_enable_irq(dwc);
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
 	return 0;
 
-err1:
+err3:
 	__dwc3_gadget_ep_disable(dwc->eps[0]);
 
-err0:
+err2:
 	dwc->gadget_driver = NULL;
+
+err1:
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
+	free_irq(irq, dwc);
+
+err0:
 	return ret;
 }
 
@@ -1600,9 +1600,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
 	spin_lock_irqsave(&dwc->lock, flags);
 
 	dwc3_gadget_disable_irq(dwc);
-	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-	free_irq(irq, dwc);
-
 	__dwc3_gadget_ep_disable(dwc->eps[0]);
 	__dwc3_gadget_ep_disable(dwc->eps[1]);
 
@@ -1610,6 +1607,9 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
+	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+	free_irq(irq, dwc);
+
 	return 0;
 }
 
@@ -1642,13 +1642,15 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
 
 		dep->dwc = dwc;
 		dep->number = epnum;
+		dep->direction = !!direction;
 		dwc->eps[epnum] = dep;
 
 		snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
 				(epnum & 1) ? "in" : "out");
 
 		dep->endpoint.name = dep->name;
-		dep->direction = (epnum & 1);
+
+		dev_vdbg(dwc->dev, "initializing %s\n", dep->name);
 
 		if (epnum == 0 || epnum == 1) {
 			dep->endpoint.maxpacket = 512;
@@ -2105,34 +2107,6 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
 	dwc->setup_packet_pending = false;
 }
 
-static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend)
-{
-	u32			reg;
-
-	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
-
-	if (suspend)
-		reg |= DWC3_GUSB3PIPECTL_SUSPHY;
-	else
-		reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
-
-	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
-}
-
-static void dwc3_gadget_usb2_phy_suspend(struct dwc3 *dwc, int suspend)
-{
-	u32			reg;
-
-	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
-
-	if (suspend)
-		reg |= DWC3_GUSB2PHYCFG_SUSPHY;
-	else
-		reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
-
-	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
-}
-
 static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 {
 	u32			reg;
@@ -2173,13 +2147,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 	/* after reset -> Default State */
 	usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
 
-	/* 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)
 		dwc3_disconnect_gadget(dwc);
 
@@ -2223,20 +2190,6 @@ static void dwc3_update_ram_clk_sel(struct dwc3 *dwc, u32 speed)
 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 }
 
-static void dwc3_gadget_phy_suspend(struct dwc3 *dwc, u8 speed)
-{
-	switch (speed) {
-	case USB_SPEED_SUPER:
-		dwc3_gadget_usb2_phy_suspend(dwc, true);
-		break;
-	case USB_SPEED_HIGH:
-	case USB_SPEED_FULL:
-	case USB_SPEED_LOW:
-		dwc3_gadget_usb3_phy_suspend(dwc, true);
-		break;
-	}
-}
-
 static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 {
 	struct dwc3_ep		*dep;
@@ -2312,12 +2265,6 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 	}
 
-	/* 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];
 	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true);
 	if (ret) {
@@ -2495,61 +2442,75 @@ static void dwc3_process_event_entry(struct dwc3 *dwc,
 	}
 }
 
-static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
+static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
 {
-	struct dwc3 *dwc = _dwc;
-	unsigned long flags;
+	struct dwc3_event_buffer *evt;
 	irqreturn_t ret = IRQ_NONE;
-	int i;
+	int left;
+	u32 reg;
 
-	spin_lock_irqsave(&dwc->lock, flags);
+	evt = dwc->ev_buffs[buf];
+	left = evt->count;
 
-	for (i = 0; i < dwc->num_event_buffers; i++) {
-		struct dwc3_event_buffer *evt;
-		int			left;
+	if (!(evt->flags & DWC3_EVENT_PENDING))
+		return IRQ_NONE;
 
-		evt = dwc->ev_buffs[i];
-		left = evt->count;
+	while (left > 0) {
+		union dwc3_event event;
 
-		if (!(evt->flags & DWC3_EVENT_PENDING))
-			continue;
+		event.raw = *(u32 *) (evt->buf + evt->lpos);
 
-		while (left > 0) {
-			union dwc3_event event;
+		dwc3_process_event_entry(dwc, &event);
 
-			event.raw = *(u32 *) (evt->buf + evt->lpos);
+		/*
+		 * FIXME we wrap around correctly to the next entry as
+		 * almost all entries are 4 bytes in size. There is one
+		 * entry which has 12 bytes which is a regular entry
+		 * followed by 8 bytes data. ATM I don't know how
+		 * things are organized if we get next to the a
+		 * boundary so I worry about that once we try to handle
+		 * that.
+		 */
+		evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
+		left -= 4;
 
-			dwc3_process_event_entry(dwc, &event);
+		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4);
+	}
 
-			/*
-			 * FIXME we wrap around correctly to the next entry as
-			 * almost all entries are 4 bytes in size. There is one
-			 * entry which has 12 bytes which is a regular entry
-			 * followed by 8 bytes data. ATM I don't know how
-			 * things are organized if we get next to the a
-			 * boundary so I worry about that once we try to handle
-			 * that.
-			 */
-			evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
-			left -= 4;
+	evt->count = 0;
+	evt->flags &= ~DWC3_EVENT_PENDING;
+	ret = IRQ_HANDLED;
 
-			dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(i), 4);
-		}
+	/* Unmask interrupt */
+	reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(buf));
+	reg &= ~DWC3_GEVNTSIZ_INTMASK;
+	dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg);
 
-		evt->count = 0;
-		evt->flags &= ~DWC3_EVENT_PENDING;
-		ret = IRQ_HANDLED;
-	}
+	return ret;
+}
+
+static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
+{
+	struct dwc3 *dwc = _dwc;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_NONE;
+	int i;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	for (i = 0; i < dwc->num_event_buffers; i++)
+		ret |= dwc3_process_event_buf(dwc, i);
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
 	return ret;
 }
 
-static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
+static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc, u32 buf)
 {
 	struct dwc3_event_buffer *evt;
 	u32 count;
+	u32 reg;
 
 	evt = dwc->ev_buffs[buf];
 
@@ -2561,6 +2522,11 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
 	evt->count = count;
 	evt->flags |= DWC3_EVENT_PENDING;
 
+	/* Mask interrupt */
+	reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(buf));
+	reg |= DWC3_GEVNTSIZ_INTMASK;
+	dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg);
+
 	return IRQ_WAKE_THREAD;
 }
 
@@ -2575,7 +2541,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
 	for (i = 0; i < dwc->num_event_buffers; i++) {
 		irqreturn_t status;
 
-		status = dwc3_process_event_buf(dwc, i);
+		status = dwc3_check_event_buf(dwc, i);
 		if (status == IRQ_WAKE_THREAD)
 			ret = status;
 	}
@@ -2593,7 +2559,6 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
  */
 int dwc3_gadget_init(struct dwc3 *dwc)
 {
-	u32					reg;
 	int					ret;
 
 	dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
@@ -2643,16 +2608,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 	if (ret)
 		goto err4;
 
-	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
-	reg |= DWC3_DCFG_LPM_CAP;
-	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
-
-	/* Enable USB2 LPM and automatic phy suspend only on recent versions */
-	if (dwc->revision >= DWC3_REVISION_194A) {
-		dwc3_gadget_usb2_phy_suspend(dwc, false);
-		dwc3_gadget_usb3_phy_suspend(dwc, false);
-	}
-
 	ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
 	if (ret) {
 		dev_err(dwc->dev, "failed to register udc\n");

+ 7 - 27
drivers/usb/dwc3/gadget.h

@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef __DRIVERS_USB_DWC3_GADGET_H

+ 7 - 27
drivers/usb/dwc3/host.c

@@ -5,34 +5,14 @@
  *
  * Authors: Felipe Balbi <balbi@ti.com>,
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/platform_device.h>

+ 7 - 27
drivers/usb/dwc3/io.h

@@ -6,34 +6,14 @@
  * Authors: Felipe Balbi <balbi@ti.com>,
  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
  *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2, as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef __DRIVERS_USB_DWC3_IO_H

+ 27 - 0
drivers/usb/dwc3/platform_data.h

@@ -0,0 +1,27 @@
+/**
+ * platform_data.h - USB DWC3 Platform Data Support
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Felipe Balbi <balbi@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/otg.h>
+
+struct dwc3_platform_data {
+	enum usb_device_speed maximum_speed;
+	enum usb_dr_mode dr_mode;
+	bool tx_fifo_resize;
+};

+ 0 - 17
drivers/usb/gadget/Kconfig

@@ -144,7 +144,6 @@ config USB_AT91
 config USB_LPC32XX
 	tristate "LPC32XX USB Peripheral Controller"
 	depends on ARCH_LPC32XX
-	depends on USB_PHY
 	select USB_ISP1301
 	help
 	   This option selects the USB device controller in the LPC32xx SoC.
@@ -206,7 +205,6 @@ config USB_FOTG210_UDC
 config USB_OMAP
 	tristate "OMAP USB Device Controller"
 	depends on ARCH_OMAP1
-	depends on USB_PHY
 	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
 	help
 	   Many Texas Instruments OMAP processors have flexible full
@@ -287,21 +285,6 @@ config USB_S3C_HSOTG
 	  The Samsung S3C64XX USB2.0 high-speed gadget controller
 	  integrated into the S3C64XX series SoC.
 
-config USB_IMX
-	tristate "Freescale i.MX1 USB Peripheral Controller"
-	depends on ARCH_MXC
-	depends on BROKEN
-	help
-	   Freescale's i.MX1 includes an integrated full speed
-	   USB 1.1 device controller.
-
-	   It has Six fixed-function endpoints, as well as endpoint
-	   zero (for control transfers).
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "imx_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
 config USB_S3C2410
 	tristate "S3C2410 USB Device Controller"
 	depends on ARCH_S3C24XX

+ 0 - 1
drivers/usb/gadget/Makefile

@@ -13,7 +13,6 @@ obj-$(CONFIG_USB_NET2280)	+= net2280.o
 obj-$(CONFIG_USB_AMD5536UDC)	+= amd5536udc.o
 obj-$(CONFIG_USB_PXA25X)	+= pxa25x_udc.o
 obj-$(CONFIG_USB_PXA27X)	+= pxa27x_udc.o
-obj-$(CONFIG_USB_IMX)		+= imx_udc.o
 obj-$(CONFIG_USB_GOKU)		+= goku_udc.o
 obj-$(CONFIG_USB_OMAP)		+= omap_udc.o
 obj-$(CONFIG_USB_S3C2410)	+= s3c2410_udc.o

+ 2 - 2
drivers/usb/gadget/amd5536udc.c

@@ -1122,7 +1122,7 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
 			goto finished;
 		}
 		if (ep->dma) {
-			retval = prep_dma(ep, req, gfp);
+			retval = prep_dma(ep, req, GFP_ATOMIC);
 			if (retval != 0)
 				goto finished;
 			/* write desc pointer to enable DMA */
@@ -1190,7 +1190,7 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
 		 * for PPB modes, because of chain creation reasons
 		 */
 		if (ep->in) {
-			retval = prep_dma(ep, req, gfp);
+			retval = prep_dma(ep, req, GFP_ATOMIC);
 			if (retval != 0)
 				goto finished;
 		}

+ 21 - 4
drivers/usb/gadget/at91_udc.c

@@ -870,6 +870,11 @@ static void clk_on(struct at91_udc *udc)
 	if (udc->clocked)
 		return;
 	udc->clocked = 1;
+
+	if (IS_ENABLED(CONFIG_COMMON_CLK)) {
+		clk_set_rate(udc->uclk, 48000000);
+		clk_prepare_enable(udc->uclk);
+	}
 	clk_prepare_enable(udc->iclk);
 	clk_prepare_enable(udc->fclk);
 }
@@ -882,6 +887,8 @@ static void clk_off(struct at91_udc *udc)
 	udc->gadget.speed = USB_SPEED_UNKNOWN;
 	clk_disable_unprepare(udc->fclk);
 	clk_disable_unprepare(udc->iclk);
+	if (IS_ENABLED(CONFIG_COMMON_CLK))
+		clk_disable_unprepare(udc->uclk);
 }
 
 /*
@@ -1697,7 +1704,7 @@ static int at91udc_probe(struct platform_device *pdev)
 	int		retval;
 	struct resource	*res;
 
-	if (!dev->platform_data && !pdev->dev.of_node) {
+	if (!dev_get_platdata(dev) && !pdev->dev.of_node) {
 		/* small (so we copy it) but critical! */
 		DBG("missing platform_data\n");
 		return -ENODEV;
@@ -1728,7 +1735,7 @@ static int at91udc_probe(struct platform_device *pdev)
 	if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
 		at91udc_of_init(udc, pdev->dev.of_node);
 	else
-		memcpy(&udc->board, dev->platform_data,
+		memcpy(&udc->board, dev_get_platdata(dev),
 		       sizeof(struct at91_udc_data));
 	udc->pdev = pdev;
 	udc->enabled = 0;
@@ -1774,10 +1781,12 @@ static int at91udc_probe(struct platform_device *pdev)
 	/* get interface and function clocks */
 	udc->iclk = clk_get(dev, "udc_clk");
 	udc->fclk = clk_get(dev, "udpck");
-	if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) {
+	if (IS_ENABLED(CONFIG_COMMON_CLK))
+		udc->uclk = clk_get(dev, "usb_clk");
+	if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk) ||
+	    (IS_ENABLED(CONFIG_COMMON_CLK) && IS_ERR(udc->uclk))) {
 		DBG("clocks missing\n");
 		retval = -ENODEV;
-		/* NOTE: we "know" here that refcounts on these are NOPs */
 		goto fail1;
 	}
 
@@ -1851,6 +1860,12 @@ fail3:
 fail2:
 	free_irq(udc->udp_irq, udc);
 fail1:
+	if (IS_ENABLED(CONFIG_COMMON_CLK) && !IS_ERR(udc->uclk))
+		clk_put(udc->uclk);
+	if (!IS_ERR(udc->fclk))
+		clk_put(udc->fclk);
+	if (!IS_ERR(udc->iclk))
+		clk_put(udc->iclk);
 	iounmap(udc->udp_baseaddr);
 fail0a:
 	if (cpu_is_at91rm9200())
@@ -1894,6 +1909,8 @@ static int __exit at91udc_remove(struct platform_device *pdev)
 
 	clk_put(udc->iclk);
 	clk_put(udc->fclk);
+	if (IS_ENABLED(CONFIG_COMMON_CLK))
+		clk_put(udc->uclk);
 
 	return 0;
 }

+ 1 - 1
drivers/usb/gadget/at91_udc.h

@@ -126,7 +126,7 @@ struct at91_udc {
 	unsigned			active_suspend:1;
 	u8				addr;
 	struct at91_udc_data		board;
-	struct clk			*iclk, *fclk;
+	struct clk			*iclk, *fclk, *uclk;
 	struct platform_device		*pdev;
 	struct proc_dir_entry		*pde;
 	void __iomem			*udp_baseaddr;

+ 22 - 8
drivers/usb/gadget/atmel_usba_udc.c

@@ -1772,6 +1772,7 @@ out:
 static int atmel_usba_start(struct usb_gadget *gadget,
 		struct usb_gadget_driver *driver)
 {
+	int ret = 0;
 	struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
 	unsigned long flags;
 
@@ -1781,8 +1782,14 @@ static int atmel_usba_start(struct usb_gadget *gadget,
 	udc->driver = driver;
 	spin_unlock_irqrestore(&udc->lock, flags);
 
-	clk_enable(udc->pclk);
-	clk_enable(udc->hclk);
+	ret = clk_prepare_enable(udc->pclk);
+	if (ret)
+		goto out;
+	ret = clk_prepare_enable(udc->hclk);
+	if (ret) {
+		clk_disable_unprepare(udc->pclk);
+		goto out;
+	}
 
 	DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name);
 
@@ -1797,9 +1804,11 @@ static int atmel_usba_start(struct usb_gadget *gadget,
 		usba_writel(udc, CTRL, USBA_ENABLE_MASK);
 		usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
 	}
+
+out:
 	spin_unlock_irqrestore(&udc->lock, flags);
 
-	return 0;
+	return ret;
 }
 
 static int atmel_usba_stop(struct usb_gadget *gadget,
@@ -1822,8 +1831,8 @@ static int atmel_usba_stop(struct usb_gadget *gadget,
 
 	udc->driver = NULL;
 
-	clk_disable(udc->hclk);
-	clk_disable(udc->pclk);
+	clk_disable_unprepare(udc->hclk);
+	clk_disable_unprepare(udc->pclk);
 
 	DBG(DBG_GADGET, "unregistered driver `%s'\n", driver->driver.name);
 
@@ -1922,7 +1931,7 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
 static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
 						 struct usba_udc *udc)
 {
-	struct usba_platform_data *pdata = pdev->dev.platform_data;
+	struct usba_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct usba_ep *eps;
 	int i;
 
@@ -2022,10 +2031,14 @@ static int __init usba_udc_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, udc);
 
 	/* Make sure we start from a clean slate */
-	clk_enable(pclk);
+	ret = clk_prepare_enable(pclk);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to enable pclk, aborting.\n");
+		goto err_clk_enable;
+	}
 	toggle_bias(0);
 	usba_writel(udc, CTRL, USBA_DISABLE_MASK);
-	clk_disable(pclk);
+	clk_disable_unprepare(pclk);
 
 	if (pdev->dev.of_node)
 		udc->usba_ep = atmel_udc_of_init(pdev, udc);
@@ -2081,6 +2094,7 @@ err_add_udc:
 	free_irq(irq, udc);
 err_request_irq:
 err_alloc_ep:
+err_clk_enable:
 	iounmap(udc->fifo);
 err_map_fifo:
 	iounmap(udc->regs);

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

@@ -2313,7 +2313,7 @@ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc)
 static int bcm63xx_udc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct bcm63xx_usbd_platform_data *pd = dev->platform_data;
+	struct bcm63xx_usbd_platform_data *pd = dev_get_platdata(dev);
 	struct bcm63xx_udc *udc;
 	struct resource *res;
 	int rc = -ENOMEM, i, irq;

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

@@ -3043,12 +3043,12 @@ fsg_config_from_params(struct fsg_config *cfg,
 		lun->filename =
 			params->file_count > i && params->file[i][0]
 			? params->file[i]
-			: 0;
+			: NULL;
 	}
 
 	/* Let MSF use defaults */
-	cfg->vendor_name = 0;
-	cfg->product_name = 0;
+	cfg->vendor_name = NULL;
+	cfg->product_name = NULL;
 
 	cfg->ops = NULL;
 	cfg->private_data = NULL;

+ 2 - 2
drivers/usb/gadget/f_uac1.c

@@ -695,7 +695,7 @@ static int generic_get_cmd(struct usb_audio_control *con, u8 cmd)
 }
 
 /* Todo: add more control selecotor dynamically */
-int __init control_selector_init(struct f_audio *audio)
+static int __init control_selector_init(struct f_audio *audio)
 {
 	INIT_LIST_HEAD(&audio->cs);
 	list_add(&feature_unit.list, &audio->cs);
@@ -719,7 +719,7 @@ int __init control_selector_init(struct f_audio *audio)
  *
  * Returns zero on success, else negative errno.
  */
-int __init audio_bind_config(struct usb_configuration *c)
+static int __init audio_bind_config(struct usb_configuration *c)
 {
 	struct f_audio *audio;
 	int status;

+ 2 - 2
drivers/usb/gadget/fsl_mxc_udc.c

@@ -33,7 +33,7 @@ int fsl_udc_clk_init(struct platform_device *pdev)
 	unsigned long freq;
 	int ret;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 
 	mxc_ipg_clk = devm_clk_get(&pdev->dev, "ipg");
 	if (IS_ERR(mxc_ipg_clk)) {
@@ -80,7 +80,7 @@ eclkrate:
 
 int fsl_udc_clk_finalize(struct platform_device *pdev)
 {
-	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	int ret = 0;
 
 	/* workaround ENGcm09152 for i.MX35 */

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

@@ -2248,7 +2248,7 @@ static int __init struct_udc_setup(struct fsl_udc *udc,
 	struct fsl_usb2_platform_data *pdata;
 	size_t size;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	udc->phy_mode = pdata->phy_mode;
 
 	udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);
@@ -2343,7 +2343,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	udc_controller->pdata = pdata;
 	spin_lock_init(&udc_controller->lock);
 	udc_controller->stopped = 1;
@@ -2524,7 +2524,7 @@ err_kfree:
 static int __exit fsl_udc_remove(struct platform_device *pdev)
 {
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 	DECLARE_COMPLETION(done);
 

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

@@ -557,7 +557,7 @@ static void fusb300_set_cxdone(struct fusb300 *fusb300)
 }
 
 /* read data from cx fifo */
-void fusb300_rdcxf(struct fusb300 *fusb300,
+static void fusb300_rdcxf(struct fusb300 *fusb300,
 		   u8 *buffer, u32 length)
 {
 	int i = 0;

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

@@ -772,7 +772,7 @@ goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
 	} /* else pio or dma irq handler advances the queue. */
 
-	if (likely(req != 0))
+	if (likely(req != NULL))
 		list_add_tail(&req->queue, &ep->queue);
 
 	if (likely(!list_empty(&ep->queue))

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

@@ -185,7 +185,7 @@ static int __exit hid_unbind(struct usb_composite_dev *cdev)
 
 static int __init hidg_plat_driver_probe(struct platform_device *pdev)
 {
-	struct hidg_func_descriptor *func = pdev->dev.platform_data;
+	struct hidg_func_descriptor *func = dev_get_platdata(&pdev->dev);
 	struct hidg_func_node *entry;
 
 	if (!func) {

+ 0 - 1544
drivers/usb/gadget/imx_udc.c

@@ -1,1544 +0,0 @@
-/*
- *	driver/usb/gadget/imx_udc.c
- *
- *	Copyright (C) 2005 Mike Lee <eemike@gmail.com>
- *	Copyright (C) 2008 Darius Augulis <augulis.darius@gmail.com>
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	This program is distributed in the hope that it will be useful,
- *	but WITHOUT ANY WARRANTY; without even the implied warranty of
- *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *	GNU General Public License for more details.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/slab.h>
-#include <linux/prefetch.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include <linux/platform_data/usb-imx_udc.h>
-#include <mach/hardware.h>
-
-#include "imx_udc.h"
-
-static const char driver_name[] = "imx_udc";
-static const char ep0name[] = "ep0";
-
-void ep0_chg_stat(const char *label, struct imx_udc_struct *imx_usb,
-							enum ep0_state stat);
-
-/*******************************************************************************
- * IMX UDC hardware related functions
- *******************************************************************************
- */
-
-void imx_udc_enable(struct imx_udc_struct *imx_usb)
-{
-	int temp = __raw_readl(imx_usb->base + USB_CTRL);
-	__raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA,
-						imx_usb->base + USB_CTRL);
-	imx_usb->gadget.speed = USB_SPEED_FULL;
-}
-
-void imx_udc_disable(struct imx_udc_struct *imx_usb)
-{
-	int temp = __raw_readl(imx_usb->base + USB_CTRL);
-
-	__raw_writel(temp & ~(CTRL_FE_ENA | CTRL_AFE_ENA),
-		 imx_usb->base + USB_CTRL);
-
-	ep0_chg_stat(__func__, imx_usb, EP0_IDLE);
-	imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
-}
-
-void imx_udc_reset(struct imx_udc_struct *imx_usb)
-{
-	int temp = __raw_readl(imx_usb->base + USB_ENAB);
-
-	/* set RST bit */
-	__raw_writel(temp | ENAB_RST, imx_usb->base + USB_ENAB);
-
-	/* wait RST bit to clear */
-	do {} while (__raw_readl(imx_usb->base + USB_ENAB) & ENAB_RST);
-
-	/* wait CFG bit to assert */
-	do {} while (!(__raw_readl(imx_usb->base + USB_DADR) & DADR_CFG));
-
-	/* udc module is now ready */
-}
-
-void imx_udc_config(struct imx_udc_struct *imx_usb)
-{
-	u8 ep_conf[5];
-	u8 i, j, cfg;
-	struct imx_ep_struct *imx_ep;
-
-	/* wait CFG bit to assert */
-	do {} while (!(__raw_readl(imx_usb->base + USB_DADR) & DADR_CFG));
-
-	/* Download the endpoint buffer for endpoint 0. */
-	for (j = 0; j < 5; j++) {
-		i = (j == 2 ? imx_usb->imx_ep[0].fifosize : 0x00);
-		__raw_writeb(i, imx_usb->base + USB_DDAT);
-		do {} while (__raw_readl(imx_usb->base + USB_DADR) & DADR_BSY);
-	}
-
-	/* Download the endpoint buffers for endpoints 1-5.
-	 * We specify two configurations, one interface
-	 */
-	for (cfg = 1; cfg < 3; cfg++) {
-		for (i = 1; i < IMX_USB_NB_EP; i++) {
-			imx_ep = &imx_usb->imx_ep[i];
-			/* EP no | Config no */
-			ep_conf[0] = (i << 4) | (cfg << 2);
-			/* Type | Direction */
-			ep_conf[1] = (imx_ep->bmAttributes << 3) |
-					(EP_DIR(imx_ep) << 2);
-			/* Max packet size */
-			ep_conf[2] = imx_ep->fifosize;
-			/* TRXTYP */
-			ep_conf[3] = 0xC0;
-			/* FIFO no */
-			ep_conf[4] = i;
-
-			D_INI(imx_usb->dev,
-				"<%s> ep%d_conf[%d]:"
-				"[%02x-%02x-%02x-%02x-%02x]\n",
-				__func__, i, cfg,
-				ep_conf[0], ep_conf[1], ep_conf[2],
-				ep_conf[3], ep_conf[4]);
-
-			for (j = 0; j < 5; j++) {
-				__raw_writeb(ep_conf[j],
-					imx_usb->base + USB_DDAT);
-				do {} while (__raw_readl(imx_usb->base
-								+ USB_DADR)
-					& DADR_BSY);
-			}
-		}
-	}
-
-	/* wait CFG bit to clear */
-	do {} while (__raw_readl(imx_usb->base + USB_DADR) & DADR_CFG);
-}
-
-void imx_udc_init_irq(struct imx_udc_struct *imx_usb)
-{
-	int i;
-
-	/* Mask and clear all irqs */
-	__raw_writel(0xFFFFFFFF, imx_usb->base + USB_MASK);
-	__raw_writel(0xFFFFFFFF, imx_usb->base + USB_INTR);
-	for (i = 0; i < IMX_USB_NB_EP; i++) {
-		__raw_writel(0x1FF, imx_usb->base + USB_EP_MASK(i));
-		__raw_writel(0x1FF, imx_usb->base + USB_EP_INTR(i));
-	}
-
-	/* Enable USB irqs */
-	__raw_writel(INTR_MSOF | INTR_FRAME_MATCH, imx_usb->base + USB_MASK);
-
-	/* Enable EP0 irqs */
-	__raw_writel(0x1FF & ~(EPINTR_DEVREQ | EPINTR_MDEVREQ | EPINTR_EOT
-		| EPINTR_EOF | EPINTR_FIFO_EMPTY | EPINTR_FIFO_FULL),
-		imx_usb->base + USB_EP_MASK(0));
-}
-
-void imx_udc_init_ep(struct imx_udc_struct *imx_usb)
-{
-	int i, max, temp;
-	struct imx_ep_struct *imx_ep;
-	for (i = 0; i < IMX_USB_NB_EP; i++) {
-		imx_ep = &imx_usb->imx_ep[i];
-		switch (imx_ep->fifosize) {
-		case 8:
-			max = 0;
-			break;
-		case 16:
-			max = 1;
-			break;
-		case 32:
-			max = 2;
-			break;
-		case 64:
-			max = 3;
-			break;
-		default:
-			max = 1;
-			break;
-		}
-		temp = (EP_DIR(imx_ep) << 7) | (max << 5)
-			| (imx_ep->bmAttributes << 3);
-		__raw_writel(temp, imx_usb->base + USB_EP_STAT(i));
-		__raw_writel(temp | EPSTAT_FLUSH,
-						imx_usb->base + USB_EP_STAT(i));
-		D_INI(imx_usb->dev, "<%s> ep%d_stat %08x\n", __func__, i,
-			__raw_readl(imx_usb->base + USB_EP_STAT(i)));
-	}
-}
-
-void imx_udc_init_fifo(struct imx_udc_struct *imx_usb)
-{
-	int i, temp;
-	struct imx_ep_struct *imx_ep;
-	for (i = 0; i < IMX_USB_NB_EP; i++) {
-		imx_ep = &imx_usb->imx_ep[i];
-
-		/* Fifo control */
-		temp = EP_DIR(imx_ep) ? 0x0B000000 : 0x0F000000;
-		__raw_writel(temp, imx_usb->base + USB_EP_FCTRL(i));
-		D_INI(imx_usb->dev, "<%s> ep%d_fctrl %08x\n", __func__, i,
-			__raw_readl(imx_usb->base + USB_EP_FCTRL(i)));
-
-		/* Fifo alarm */
-		temp = (i ? imx_ep->fifosize / 2 : 0);
-		__raw_writel(temp, imx_usb->base + USB_EP_FALRM(i));
-		D_INI(imx_usb->dev, "<%s> ep%d_falrm %08x\n", __func__, i,
-			__raw_readl(imx_usb->base + USB_EP_FALRM(i)));
-	}
-}
-
-static void imx_udc_init(struct imx_udc_struct *imx_usb)
-{
-	/* Reset UDC */
-	imx_udc_reset(imx_usb);
-
-	/* Download config to enpoint buffer */
-	imx_udc_config(imx_usb);
-
-	/* Setup interrups */
-	imx_udc_init_irq(imx_usb);
-
-	/* Setup endpoints */
-	imx_udc_init_ep(imx_usb);
-
-	/* Setup fifos */
-	imx_udc_init_fifo(imx_usb);
-}
-
-void imx_ep_irq_enable(struct imx_ep_struct *imx_ep)
-{
-
-	int i = EP_NO(imx_ep);
-
-	__raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_MASK(i));
-	__raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_INTR(i));
-	__raw_writel(0x1FF & ~(EPINTR_EOT | EPINTR_EOF),
-		imx_ep->imx_usb->base + USB_EP_MASK(i));
-}
-
-void imx_ep_irq_disable(struct imx_ep_struct *imx_ep)
-{
-
-	int i = EP_NO(imx_ep);
-
-	__raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_MASK(i));
-	__raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_INTR(i));
-}
-
-int imx_ep_empty(struct imx_ep_struct *imx_ep)
-{
-	struct imx_udc_struct *imx_usb = imx_ep->imx_usb;
-
-	return __raw_readl(imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep)))
-			& FSTAT_EMPTY;
-}
-
-unsigned imx_fifo_bcount(struct imx_ep_struct *imx_ep)
-{
-	struct imx_udc_struct *imx_usb = imx_ep->imx_usb;
-
-	return (__raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)))
-			& EPSTAT_BCOUNT) >> 16;
-}
-
-void imx_flush(struct imx_ep_struct *imx_ep)
-{
-	struct imx_udc_struct *imx_usb = imx_ep->imx_usb;
-
-	int temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
-	__raw_writel(temp | EPSTAT_FLUSH,
-		imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
-}
-
-void imx_ep_stall(struct imx_ep_struct *imx_ep)
-{
-	struct imx_udc_struct *imx_usb = imx_ep->imx_usb;
-	int temp, i;
-
-	D_ERR(imx_usb->dev,
-		"<%s> Forced stall on %s\n", __func__, imx_ep->ep.name);
-
-	imx_flush(imx_ep);
-
-	/* Special care for ep0 */
-	if (!EP_NO(imx_ep)) {
-		temp = __raw_readl(imx_usb->base + USB_CTRL);
-		__raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR,
-						imx_usb->base + USB_CTRL);
-		do { } while (__raw_readl(imx_usb->base + USB_CTRL)
-						& CTRL_CMDOVER);
-		temp = __raw_readl(imx_usb->base + USB_CTRL);
-		__raw_writel(temp & ~CTRL_CMDERROR, imx_usb->base + USB_CTRL);
-	}
-	else {
-		temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
-		__raw_writel(temp | EPSTAT_STALL,
-			imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
-
-		for (i = 0; i < 100; i ++) {
-			temp = __raw_readl(imx_usb->base
-						+ USB_EP_STAT(EP_NO(imx_ep)));
-			if (!(temp & EPSTAT_STALL))
-	 			break;
-	 		udelay(20);
-	 	}
-		if (i == 100)
-			D_ERR(imx_usb->dev, "<%s> Non finished stall on %s\n",
-				__func__, imx_ep->ep.name);
-	}
-}
-
-static int imx_udc_get_frame(struct usb_gadget *_gadget)
-{
-	struct imx_udc_struct *imx_usb = container_of(_gadget,
-			struct imx_udc_struct, gadget);
-
-	return __raw_readl(imx_usb->base + USB_FRAME) & 0x7FF;
-}
-
-static int imx_udc_wakeup(struct usb_gadget *_gadget)
-{
-	return 0;
-}
-
-/*******************************************************************************
- * USB request control functions
- *******************************************************************************
- */
-
-static void ep_add_request(struct imx_ep_struct *imx_ep,
-							struct imx_request *req)
-{
-	if (unlikely(!req))
-		return;
-
-	req->in_use = 1;
-	list_add_tail(&req->queue, &imx_ep->queue);
-}
-
-static void ep_del_request(struct imx_ep_struct *imx_ep,
-							struct imx_request *req)
-{
-	if (unlikely(!req))
-		return;
-
-	list_del_init(&req->queue);
-	req->in_use = 0;
-}
-
-static void done(struct imx_ep_struct *imx_ep,
-					struct imx_request *req, int status)
-{
-	ep_del_request(imx_ep, req);
-
-	if (likely(req->req.status == -EINPROGRESS))
-		req->req.status = status;
-	else
-		status = req->req.status;
-
-	if (status && status != -ESHUTDOWN)
-		D_ERR(imx_ep->imx_usb->dev,
-			"<%s> complete %s req %p stat %d len %u/%u\n", __func__,
-			imx_ep->ep.name, &req->req, status,
-			req->req.actual, req->req.length);
-
-	req->req.complete(&imx_ep->ep, &req->req);
-}
-
-static void nuke(struct imx_ep_struct *imx_ep, int status)
-{
-	struct imx_request *req;
-
-	while (!list_empty(&imx_ep->queue)) {
-		req = list_entry(imx_ep->queue.next, struct imx_request, queue);
-		done(imx_ep, req, status);
-	}
-}
-
-/*******************************************************************************
- * Data tansfer over USB functions
- *******************************************************************************
- */
-static int read_packet(struct imx_ep_struct *imx_ep, struct imx_request *req)
-{
-	u8	*buf;
-	int	bytes_ep, bufferspace, count, i;
-
-	bytes_ep = imx_fifo_bcount(imx_ep);
-	bufferspace = req->req.length - req->req.actual;
-
-	buf = req->req.buf + req->req.actual;
-	prefetchw(buf);
-
-	if (unlikely(imx_ep_empty(imx_ep)))
-		count = 0;	/* zlp */
-	else
-		count = min(bytes_ep, bufferspace);
-
-	for (i = count; i > 0; i--)
-		*buf++ = __raw_readb(imx_ep->imx_usb->base
-						+ USB_EP_FDAT0(EP_NO(imx_ep)));
-	req->req.actual += count;
-
-	return count;
-}
-
-static int write_packet(struct imx_ep_struct *imx_ep, struct imx_request *req)
-{
-	u8	*buf;
-	int	length, count, temp;
-
-	if (unlikely(__raw_readl(imx_ep->imx_usb->base +
-				 USB_EP_STAT(EP_NO(imx_ep))) & EPSTAT_ZLPS)) {
-		D_TRX(imx_ep->imx_usb->dev, "<%s> zlp still queued in EP %s\n",
-			__func__, imx_ep->ep.name);
-		return -1;
-	}
-
-	buf = req->req.buf + req->req.actual;
-	prefetch(buf);
-
-	length = min(req->req.length - req->req.actual, (u32)imx_ep->fifosize);
-
-	if (imx_fifo_bcount(imx_ep) + length > imx_ep->fifosize) {
-		D_TRX(imx_ep->imx_usb->dev, "<%s> packet overfill %s fifo\n",
-			__func__, imx_ep->ep.name);
-		return -1;
-	}
-
-	req->req.actual += length;
-	count = length;
-
-	if (!count && req->req.zero) {	/* zlp */
-		temp = __raw_readl(imx_ep->imx_usb->base
-			+ USB_EP_STAT(EP_NO(imx_ep)));
-		__raw_writel(temp | EPSTAT_ZLPS, imx_ep->imx_usb->base
-			+ USB_EP_STAT(EP_NO(imx_ep)));
-		D_TRX(imx_ep->imx_usb->dev, "<%s> zero packet\n", __func__);
-		return 0;
-	}
-
-	while (count--) {
-		if (count == 0) {	/* last byte */
-			temp = __raw_readl(imx_ep->imx_usb->base
-				+ USB_EP_FCTRL(EP_NO(imx_ep)));
-			__raw_writel(temp | FCTRL_WFR, imx_ep->imx_usb->base
-				+ USB_EP_FCTRL(EP_NO(imx_ep)));
-		}
-		__raw_writeb(*buf++,
-			imx_ep->imx_usb->base + USB_EP_FDAT0(EP_NO(imx_ep)));
-	}
-
-	return length;
-}
-
-static int read_fifo(struct imx_ep_struct *imx_ep, struct imx_request *req)
-{
-	int 	bytes = 0,
-		count,
-		completed = 0;
-
-	while (__raw_readl(imx_ep->imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep)))
-		& FSTAT_FR) {
-			count = read_packet(imx_ep, req);
-			bytes += count;
-
-			completed = (count != imx_ep->fifosize);
-			if (completed || req->req.actual == req->req.length) {
-				completed = 1;
-				break;
-			}
-	}
-
-	if (completed || !req->req.length) {
-		done(imx_ep, req, 0);
-		D_REQ(imx_ep->imx_usb->dev, "<%s> %s req<%p> %s\n",
-			__func__, imx_ep->ep.name, req,
-			completed ? "completed" : "not completed");
-		if (!EP_NO(imx_ep))
-			ep0_chg_stat(__func__, imx_ep->imx_usb, EP0_IDLE);
-	}
-
-	D_TRX(imx_ep->imx_usb->dev, "<%s> bytes read: %d\n", __func__, bytes);
-
-	return completed;
-}
-
-static int write_fifo(struct imx_ep_struct *imx_ep, struct imx_request *req)
-{
-	int	bytes = 0,
-		count,
-		completed = 0;
-
-	while (!completed) {
-		count = write_packet(imx_ep, req);
-		if (count < 0)
-			break; /* busy */
-		bytes += count;
-
-		/* last packet "must be" short (or a zlp) */
-		completed = (count != imx_ep->fifosize);
-
-		if (unlikely(completed)) {
-			done(imx_ep, req, 0);
-			D_REQ(imx_ep->imx_usb->dev, "<%s> %s req<%p> %s\n",
-				__func__, imx_ep->ep.name, req,
-				completed ? "completed" : "not completed");
-			if (!EP_NO(imx_ep))
-				ep0_chg_stat(__func__,
-						imx_ep->imx_usb, EP0_IDLE);
-		}
-	}
-
-	D_TRX(imx_ep->imx_usb->dev, "<%s> bytes sent: %d\n", __func__, bytes);
-
-	return completed;
-}
-
-/*******************************************************************************
- * Endpoint handlers
- *******************************************************************************
- */
-static int handle_ep(struct imx_ep_struct *imx_ep)
-{
-	struct imx_request *req;
-	int completed = 0;
-
-	do {
-		if (!list_empty(&imx_ep->queue))
-			req = list_entry(imx_ep->queue.next,
-				struct imx_request, queue);
-		else {
-			D_REQ(imx_ep->imx_usb->dev, "<%s> no request on %s\n",
-				__func__, imx_ep->ep.name);
-			return 0;
-		}
-
-		if (EP_DIR(imx_ep))	/* to host */
-			completed = write_fifo(imx_ep, req);
-		else			/* to device */
-			completed = read_fifo(imx_ep, req);
-
-		dump_ep_stat(__func__, imx_ep);
-
-	} while (completed);
-
-	return 0;
-}
-
-static int handle_ep0(struct imx_ep_struct *imx_ep)
-{
-	struct imx_request *req = NULL;
-	int ret = 0;
-
-	if (!list_empty(&imx_ep->queue)) {
-		req = list_entry(imx_ep->queue.next, struct imx_request, queue);
-
-		switch (imx_ep->imx_usb->ep0state) {
-
-		case EP0_IN_DATA_PHASE:			/* GET_DESCRIPTOR */
-			write_fifo(imx_ep, req);
-			break;
-		case EP0_OUT_DATA_PHASE:		/* SET_DESCRIPTOR */
-			read_fifo(imx_ep, req);
-			break;
-		default:
-			D_EP0(imx_ep->imx_usb->dev,
-				"<%s> ep0 i/o, odd state %d\n",
-				__func__, imx_ep->imx_usb->ep0state);
-			ep_del_request(imx_ep, req);
-			ret = -EL2HLT;
-			break;
-		}
-	}
-
-	else
-		D_ERR(imx_ep->imx_usb->dev, "<%s> no request on %s\n",
-						__func__, imx_ep->ep.name);
-
-	return ret;
-}
-
-static void handle_ep0_devreq(struct imx_udc_struct *imx_usb)
-{
-	struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[0];
-	union {
-		struct usb_ctrlrequest	r;
-		u8			raw[8];
-		u32			word[2];
-	} u;
-	int temp, i;
-
-	nuke(imx_ep, -EPROTO);
-
-	/* read SETUP packet */
-	for (i = 0; i < 2; i++) {
-		if (imx_ep_empty(imx_ep)) {
-			D_ERR(imx_usb->dev,
-				"<%s> no setup packet received\n", __func__);
-			goto stall;
-		}
-		u.word[i] = __raw_readl(imx_usb->base
-						+ USB_EP_FDAT(EP_NO(imx_ep)));
-	}
-
-	temp = imx_ep_empty(imx_ep);
-	while (!imx_ep_empty(imx_ep)) {
-		i = __raw_readl(imx_usb->base +	USB_EP_FDAT(EP_NO(imx_ep)));
-		D_ERR(imx_usb->dev,
-			"<%s> wrong to have extra bytes for setup : 0x%08x\n",
-			__func__, i);
-	}
-	if (!temp)
-		goto stall;
-
-	le16_to_cpus(&u.r.wValue);
-	le16_to_cpus(&u.r.wIndex);
-	le16_to_cpus(&u.r.wLength);
-
-	D_REQ(imx_usb->dev, "<%s> SETUP %02x.%02x v%04x i%04x l%04x\n",
-		__func__, u.r.bRequestType, u.r.bRequest,
-		u.r.wValue, u.r.wIndex, u.r.wLength);
-
-	if (imx_usb->set_config) {
-		/* NACK the host by using CMDOVER */
-		temp = __raw_readl(imx_usb->base + USB_CTRL);
-		__raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL);
-
-		D_ERR(imx_usb->dev,
-			"<%s> set config req is pending, NACK the host\n",
-			__func__);
-		return;
-	}
-
-	if (u.r.bRequestType & USB_DIR_IN)
-		ep0_chg_stat(__func__, imx_usb, EP0_IN_DATA_PHASE);
-	else
-		ep0_chg_stat(__func__, imx_usb, EP0_OUT_DATA_PHASE);
-
-	i = imx_usb->driver->setup(&imx_usb->gadget, &u.r);
-	if (i < 0) {
-		D_ERR(imx_usb->dev, "<%s> device setup error %d\n",
-			__func__, i);
-		goto stall;
-	}
-
-	return;
-stall:
-	D_ERR(imx_usb->dev, "<%s> protocol STALL\n", __func__);
-	imx_ep_stall(imx_ep);
-	ep0_chg_stat(__func__, imx_usb, EP0_STALL);
-	return;
-}
-
-/*******************************************************************************
- * USB gadget callback functions
- *******************************************************************************
- */
-
-static int imx_ep_enable(struct usb_ep *usb_ep,
-				const struct usb_endpoint_descriptor *desc)
-{
-	struct imx_ep_struct *imx_ep = container_of(usb_ep,
-						struct imx_ep_struct, ep);
-	struct imx_udc_struct *imx_usb = imx_ep->imx_usb;
-	unsigned long flags;
-
-	if (!usb_ep
-		|| !desc
-		|| !EP_NO(imx_ep)
-		|| desc->bDescriptorType != USB_DT_ENDPOINT
-		|| imx_ep->bEndpointAddress != desc->bEndpointAddress) {
-			D_ERR(imx_usb->dev,
-				"<%s> bad ep or descriptor\n", __func__);
-			return -EINVAL;
-	}
-
-	if (imx_ep->bmAttributes != desc->bmAttributes) {
-		D_ERR(imx_usb->dev,
-			"<%s> %s type mismatch\n", __func__, usb_ep->name);
-		return -EINVAL;
-	}
-
-	if (imx_ep->fifosize < usb_endpoint_maxp(desc)) {
-		D_ERR(imx_usb->dev,
-			"<%s> bad %s maxpacket\n", __func__, usb_ep->name);
-		return -ERANGE;
-	}
-
-	if (!imx_usb->driver || imx_usb->gadget.speed == USB_SPEED_UNKNOWN) {
-		D_ERR(imx_usb->dev, "<%s> bogus device state\n", __func__);
-		return -ESHUTDOWN;
-	}
-
-	local_irq_save(flags);
-
-	imx_ep->stopped = 0;
-	imx_flush(imx_ep);
-	imx_ep_irq_enable(imx_ep);
-
-	local_irq_restore(flags);
-
-	D_EPX(imx_usb->dev, "<%s> ENABLED %s\n", __func__, usb_ep->name);
-	return 0;
-}
-
-static int imx_ep_disable(struct usb_ep *usb_ep)
-{
-	struct imx_ep_struct *imx_ep = container_of(usb_ep,
-						struct imx_ep_struct, ep);
-	unsigned long flags;
-
-	if (!usb_ep || !EP_NO(imx_ep) || !list_empty(&imx_ep->queue)) {
-		D_ERR(imx_ep->imx_usb->dev, "<%s> %s can not be disabled\n",
-			__func__, usb_ep ? imx_ep->ep.name : NULL);
-		return -EINVAL;
-	}
-
-	local_irq_save(flags);
-
-	imx_ep->stopped = 1;
-	nuke(imx_ep, -ESHUTDOWN);
-	imx_flush(imx_ep);
-	imx_ep_irq_disable(imx_ep);
-
-	local_irq_restore(flags);
-
-	D_EPX(imx_ep->imx_usb->dev,
-		"<%s> DISABLED %s\n", __func__, usb_ep->name);
-	return 0;
-}
-
-static struct usb_request *imx_ep_alloc_request
-					(struct usb_ep *usb_ep, gfp_t gfp_flags)
-{
-	struct imx_request *req;
-
-	if (!usb_ep)
-		return NULL;
-
-	req = kzalloc(sizeof *req, gfp_flags);
-	if (!req)
-		return NULL;
-
-	INIT_LIST_HEAD(&req->queue);
-	req->in_use = 0;
-
-	return &req->req;
-}
-
-static void imx_ep_free_request
-			(struct usb_ep *usb_ep, struct usb_request *usb_req)
-{
-	struct imx_request *req;
-
-	req = container_of(usb_req, struct imx_request, req);
-	WARN_ON(!list_empty(&req->queue));
-	kfree(req);
-}
-
-static int imx_ep_queue
-	(struct usb_ep *usb_ep, struct usb_request *usb_req, gfp_t gfp_flags)
-{
-	struct imx_ep_struct	*imx_ep;
-	struct imx_udc_struct	*imx_usb;
-	struct imx_request	*req;
-	unsigned long		flags;
-	int			ret = 0;
-
-	imx_ep = container_of(usb_ep, struct imx_ep_struct, ep);
-	imx_usb = imx_ep->imx_usb;
-	req = container_of(usb_req, struct imx_request, req);
-
-	/*
-	  Special care on IMX udc.
-	  Ignore enqueue when after set configuration from the
-	  host. This assume all gadget drivers reply set
-	  configuration with the next ep0 req enqueue.
-	*/
-	if (imx_usb->set_config && !EP_NO(imx_ep)) {
-		imx_usb->set_config = 0;
-		D_ERR(imx_usb->dev,
-			"<%s> gadget reply set config\n", __func__);
-		return 0;
-	}
-
-	if (unlikely(!usb_req || !req || !usb_req->complete || !usb_req->buf)) {
-		D_ERR(imx_usb->dev, "<%s> bad params\n", __func__);
-		return -EINVAL;
-	}
-
-	if (unlikely(!usb_ep || !imx_ep)) {
-		D_ERR(imx_usb->dev, "<%s> bad ep\n", __func__);
-		return -EINVAL;
-	}
-
-	if (!imx_usb->driver || imx_usb->gadget.speed == USB_SPEED_UNKNOWN) {
-		D_ERR(imx_usb->dev, "<%s> bogus device state\n", __func__);
-		return -ESHUTDOWN;
-	}
-
-	/* Debug */
-	D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n",
-		__func__, EP_NO(imx_ep),
-		((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state
-							== EP0_IN_DATA_PHASE)
-		|| (EP_NO(imx_ep) && EP_DIR(imx_ep)))
-					? "IN" : "OUT", usb_req->length);
-	dump_req(__func__, imx_ep, usb_req);
-
-	if (imx_ep->stopped) {
-		usb_req->status = -ESHUTDOWN;
-		return -ESHUTDOWN;
-	}
-
-	if (req->in_use) {
-		D_ERR(imx_usb->dev,
-			"<%s> refusing to queue req %p (already queued)\n",
-			__func__, req);
-		return 0;
-	}
-
-	local_irq_save(flags);
-
-	usb_req->status = -EINPROGRESS;
-	usb_req->actual = 0;
-
-	ep_add_request(imx_ep, req);
-
-	if (!EP_NO(imx_ep))
-		ret = handle_ep0(imx_ep);
-	else
-		ret = handle_ep(imx_ep);
-
-	local_irq_restore(flags);
-	return ret;
-}
-
-static int imx_ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req)
-{
-
-	struct imx_ep_struct *imx_ep = container_of
-					(usb_ep, struct imx_ep_struct, ep);
-	struct imx_request *req;
-	unsigned long flags;
-
-	if (unlikely(!usb_ep || !EP_NO(imx_ep))) {
-		D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__);
-		return -EINVAL;
-	}
-
-	local_irq_save(flags);
-
-	/* make sure it's actually queued on this endpoint */
-	list_for_each_entry(req, &imx_ep->queue, queue) {
-		if (&req->req == usb_req)
-			break;
-	}
-	if (&req->req != usb_req) {
-		local_irq_restore(flags);
-		return -EINVAL;
-	}
-
-	done(imx_ep, req, -ECONNRESET);
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-static int imx_ep_set_halt(struct usb_ep *usb_ep, int value)
-{
-	struct imx_ep_struct *imx_ep = container_of
-					(usb_ep, struct imx_ep_struct, ep);
-	unsigned long flags;
-
-	if (unlikely(!usb_ep || !EP_NO(imx_ep))) {
-		D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__);
-		return -EINVAL;
-	}
-
-	local_irq_save(flags);
-
-	if ((imx_ep->bEndpointAddress & USB_DIR_IN)
-		&& !list_empty(&imx_ep->queue)) {
-			local_irq_restore(flags);
-			return -EAGAIN;
-	}
-
-	imx_ep_stall(imx_ep);
-
-	local_irq_restore(flags);
-
-	D_EPX(imx_ep->imx_usb->dev, "<%s> %s halt\n", __func__, usb_ep->name);
-	return 0;
-}
-
-static int imx_ep_fifo_status(struct usb_ep *usb_ep)
-{
-	struct imx_ep_struct *imx_ep = container_of
-					(usb_ep, struct imx_ep_struct, ep);
-
-	if (!usb_ep) {
-		D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__);
-		return -ENODEV;
-	}
-
-	if (imx_ep->imx_usb->gadget.speed == USB_SPEED_UNKNOWN)
-		return 0;
-	else
-		return imx_fifo_bcount(imx_ep);
-}
-
-static void imx_ep_fifo_flush(struct usb_ep *usb_ep)
-{
-	struct imx_ep_struct *imx_ep = container_of
-					(usb_ep, struct imx_ep_struct, ep);
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	if (!usb_ep || !EP_NO(imx_ep) || !list_empty(&imx_ep->queue)) {
-		D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__);
-		local_irq_restore(flags);
-		return;
-	}
-
-	/* toggle and halt bits stay unchanged */
-	imx_flush(imx_ep);
-
-	local_irq_restore(flags);
-}
-
-static struct usb_ep_ops imx_ep_ops = {
-	.enable		= imx_ep_enable,
-	.disable	= imx_ep_disable,
-
-	.alloc_request	= imx_ep_alloc_request,
-	.free_request	= imx_ep_free_request,
-
-	.queue		= imx_ep_queue,
-	.dequeue	= imx_ep_dequeue,
-
-	.set_halt	= imx_ep_set_halt,
-	.fifo_status	= imx_ep_fifo_status,
-	.fifo_flush	= imx_ep_fifo_flush,
-};
-
-/*******************************************************************************
- * USB endpoint control functions
- *******************************************************************************
- */
-
-void ep0_chg_stat(const char *label,
-			struct imx_udc_struct *imx_usb, enum ep0_state stat)
-{
-	D_EP0(imx_usb->dev, "<%s> from %15s to %15s\n",
-		label, state_name[imx_usb->ep0state], state_name[stat]);
-
-	if (imx_usb->ep0state == stat)
-		return;
-
-	imx_usb->ep0state = stat;
-}
-
-static void usb_init_data(struct imx_udc_struct *imx_usb)
-{
-	struct imx_ep_struct *imx_ep;
-	u8 i;
-
-	/* device/ep0 records init */
-	INIT_LIST_HEAD(&imx_usb->gadget.ep_list);
-	INIT_LIST_HEAD(&imx_usb->gadget.ep0->ep_list);
-	ep0_chg_stat(__func__, imx_usb, EP0_IDLE);
-
-	/* basic endpoint records init */
-	for (i = 0; i < IMX_USB_NB_EP; i++) {
-		imx_ep = &imx_usb->imx_ep[i];
-
-		if (i) {
-			list_add_tail(&imx_ep->ep.ep_list,
-				&imx_usb->gadget.ep_list);
-			imx_ep->stopped = 1;
-		} else
-			imx_ep->stopped = 0;
-
-		INIT_LIST_HEAD(&imx_ep->queue);
-	}
-}
-
-static void udc_stop_activity(struct imx_udc_struct *imx_usb,
-					struct usb_gadget_driver *driver)
-{
-	struct imx_ep_struct *imx_ep;
-	int i;
-
-	if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN)
-		driver = NULL;
-
-	/* prevent new request submissions, kill any outstanding requests  */
-	for (i = 1; i < IMX_USB_NB_EP; i++) {
-		imx_ep = &imx_usb->imx_ep[i];
-		imx_flush(imx_ep);
-		imx_ep->stopped = 1;
-		imx_ep_irq_disable(imx_ep);
-		nuke(imx_ep, -ESHUTDOWN);
-	}
-
-	imx_usb->cfg = 0;
-	imx_usb->intf = 0;
-	imx_usb->alt = 0;
-
-	if (driver)
-		driver->disconnect(&imx_usb->gadget);
-}
-
-/*******************************************************************************
- * Interrupt handlers
- *******************************************************************************
- */
-
-/*
- * Called when timer expires.
- * Timer is started when CFG_CHG is received.
- */
-static void handle_config(unsigned long data)
-{
-	struct imx_udc_struct *imx_usb = (void *)data;
-	struct usb_ctrlrequest u;
-	int temp, cfg, intf, alt;
-
-	local_irq_disable();
-
-	temp = __raw_readl(imx_usb->base + USB_STAT);
-	cfg  = (temp & STAT_CFG) >> 5;
-	intf = (temp & STAT_INTF) >> 3;
-	alt  =  temp & STAT_ALTSET;
-
-	D_REQ(imx_usb->dev,
-		"<%s> orig config C=%d, I=%d, A=%d / "
-		"req config C=%d, I=%d, A=%d\n",
-		__func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt,
-		cfg, intf, alt);
-
-	if (cfg == 1 || cfg == 2) {
-
-		if (imx_usb->cfg != cfg) {
-			u.bRequest = USB_REQ_SET_CONFIGURATION;
-			u.bRequestType = USB_DIR_OUT |
-					USB_TYPE_STANDARD |
-					USB_RECIP_DEVICE;
-			u.wValue = cfg;
-			u.wIndex = 0;
-			u.wLength = 0;
-			imx_usb->cfg = cfg;
-			imx_usb->driver->setup(&imx_usb->gadget, &u);
-
-		}
-		if (imx_usb->intf != intf || imx_usb->alt != alt) {
-			u.bRequest = USB_REQ_SET_INTERFACE;
-			u.bRequestType = USB_DIR_OUT |
-					  USB_TYPE_STANDARD |
-					  USB_RECIP_INTERFACE;
-			u.wValue = alt;
-			u.wIndex = intf;
-			u.wLength = 0;
-			imx_usb->intf = intf;
-			imx_usb->alt = alt;
-			imx_usb->driver->setup(&imx_usb->gadget, &u);
-		}
-	}
-
-	imx_usb->set_config = 0;
-
-	local_irq_enable();
-}
-
-static irqreturn_t imx_udc_irq(int irq, void *dev)
-{
-	struct imx_udc_struct *imx_usb = dev;
-	int intr = __raw_readl(imx_usb->base + USB_INTR);
-	int temp;
-
-	if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START
-			| INTR_RESET_STOP | INTR_CFG_CHG)) {
-				dump_intr(__func__, intr, imx_usb->dev);
-				dump_usb_stat(__func__, imx_usb);
-	}
-
-	if (!imx_usb->driver)
-		goto end_irq;
-
-	if (intr & INTR_SOF) {
-		/* Copy from Freescale BSP.
-		   We must enable SOF intr and set CMDOVER.
-		   Datasheet don't specifiy this action, but it
-		   is done in Freescale BSP, so just copy it.
-		*/
-		if (imx_usb->ep0state == EP0_IDLE) {
-			temp = __raw_readl(imx_usb->base + USB_CTRL);
-			__raw_writel(temp | CTRL_CMDOVER,
-						imx_usb->base + USB_CTRL);
-		}
-	}
-
-	if (intr & INTR_CFG_CHG) {
-		/* A workaround of serious IMX UDC bug.
-		   Handling of CFG_CHG should be delayed for some time, because
-		   IMX does not NACK the host when CFG_CHG interrupt is pending.
-		   There is no time to handle current CFG_CHG
-		   if next CFG_CHG or SETUP packed is send immediately.
-		   We have to clear CFG_CHG, start the timer and
-		   NACK the host by setting CTRL_CMDOVER
-		   if it sends any SETUP packet.
-		   When timer expires, handler is called to handle configuration
-		   changes. While CFG_CHG is not handled (set_config=1),
-		   we must NACK the host to every SETUP packed.
-		   This delay prevents from going out of sync with host.
-		 */
-		__raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR);
-		imx_usb->set_config = 1;
-		mod_timer(&imx_usb->timer, jiffies + 5);
-		goto end_irq;
-	}
-
-	if (intr & INTR_WAKEUP) {
-		if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN
-			&& imx_usb->driver && imx_usb->driver->resume)
-				imx_usb->driver->resume(&imx_usb->gadget);
-		imx_usb->set_config = 0;
-		del_timer(&imx_usb->timer);
-		imx_usb->gadget.speed = USB_SPEED_FULL;
-	}
-
-	if (intr & INTR_SUSPEND) {
-		if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN
-			&& imx_usb->driver && imx_usb->driver->suspend)
-				imx_usb->driver->suspend(&imx_usb->gadget);
-		imx_usb->set_config = 0;
-		del_timer(&imx_usb->timer);
-		imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
-	}
-
-	if (intr & INTR_RESET_START) {
-		__raw_writel(intr, imx_usb->base + USB_INTR);
-		udc_stop_activity(imx_usb, imx_usb->driver);
-		imx_usb->set_config = 0;
-		del_timer(&imx_usb->timer);
-		imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
-	}
-
-	if (intr & INTR_RESET_STOP)
-		imx_usb->gadget.speed = USB_SPEED_FULL;
-
-end_irq:
-	__raw_writel(intr, imx_usb->base + USB_INTR);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev)
-{
-	struct imx_udc_struct *imx_usb = dev;
-	struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[0];
-	int intr = __raw_readl(imx_usb->base + USB_EP_INTR(0));
-
-	dump_ep_intr(__func__, 0, intr, imx_usb->dev);
-
-	if (!imx_usb->driver) {
-		__raw_writel(intr, imx_usb->base + USB_EP_INTR(0));
-		return IRQ_HANDLED;
-	}
-
-	/* DEVREQ has highest priority */
-	if (intr & (EPINTR_DEVREQ | EPINTR_MDEVREQ))
-		handle_ep0_devreq(imx_usb);
-	/* Seem i.MX is missing EOF interrupt sometimes.
-	 * Therefore we don't monitor EOF.
-	 * We call handle_ep0() only if a request is queued for ep0.
-	 */
-	else if (!list_empty(&imx_ep->queue))
-		handle_ep0(imx_ep);
-
-	__raw_writel(intr, imx_usb->base + USB_EP_INTR(0));
-
-	return IRQ_HANDLED;
-}
-
-#ifndef MX1_INT_USBD0
-#define MX1_INT_USBD0 MX1_USBD_INT0
-#endif
-
-static irqreturn_t imx_udc_bulk_irq(int irq, void *dev)
-{
-	struct imx_udc_struct *imx_usb = dev;
-	struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[irq - MX1_INT_USBD0];
-	int intr = __raw_readl(imx_usb->base + USB_EP_INTR(EP_NO(imx_ep)));
-
-	dump_ep_intr(__func__, irq - MX1_INT_USBD0, intr, imx_usb->dev);
-
-	if (!imx_usb->driver) {
-		__raw_writel(intr, imx_usb->base + USB_EP_INTR(EP_NO(imx_ep)));
-		return IRQ_HANDLED;
-	}
-
-	handle_ep(imx_ep);
-
-	__raw_writel(intr, imx_usb->base + USB_EP_INTR(EP_NO(imx_ep)));
-
-	return IRQ_HANDLED;
-}
-
-irq_handler_t intr_handler(int i)
-{
-	switch (i) {
-	case 0:
-		return imx_udc_ctrl_irq;
-	case 1:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-		return imx_udc_bulk_irq;
-	default:
-		return imx_udc_irq;
-	}
-}
-
-/*******************************************************************************
- * Static defined IMX UDC structure
- *******************************************************************************
- */
-
-static int imx_udc_start(struct usb_gadget *gadget,
-		struct usb_gadget_driver *driver);
-static int imx_udc_stop(struct usb_gadget *gadget,
-		struct usb_gadget_driver *driver);
-static const struct usb_gadget_ops imx_udc_ops = {
-	.get_frame	= imx_udc_get_frame,
-	.wakeup		= imx_udc_wakeup,
-	.udc_start	= imx_udc_start,
-	.udc_stop	= imx_udc_stop,
-};
-
-static struct imx_udc_struct controller = {
-	.gadget = {
-		.ops		= &imx_udc_ops,
-		.ep0		= &controller.imx_ep[0].ep,
-		.name		= driver_name,
-		.dev = {
-			.init_name	= "gadget",
-		},
-	},
-
-	.imx_ep[0] = {
-		.ep = {
-			.name		= ep0name,
-			.ops		= &imx_ep_ops,
-			.maxpacket	= 32,
-		},
-		.imx_usb		= &controller,
-		.fifosize		= 32,
-		.bEndpointAddress	= 0,
-		.bmAttributes		= USB_ENDPOINT_XFER_CONTROL,
-	 },
-	.imx_ep[1] = {
-		.ep = {
-			.name		= "ep1in-bulk",
-			.ops		= &imx_ep_ops,
-			.maxpacket	= 64,
-		},
-		.imx_usb		= &controller,
-		.fifosize		= 64,
-		.bEndpointAddress	= USB_DIR_IN | 1,
-		.bmAttributes		= USB_ENDPOINT_XFER_BULK,
-	 },
-	.imx_ep[2] = {
-		.ep = {
-			.name		= "ep2out-bulk",
-			.ops		= &imx_ep_ops,
-			.maxpacket	= 64,
-		},
-		.imx_usb		= &controller,
-		.fifosize		= 64,
-		.bEndpointAddress	= USB_DIR_OUT | 2,
-		.bmAttributes		= USB_ENDPOINT_XFER_BULK,
-	 },
-	.imx_ep[3] = {
-		.ep = {
-			.name		= "ep3out-bulk",
-			.ops		= &imx_ep_ops,
-			.maxpacket	= 32,
-		},
-		.imx_usb		= &controller,
-		.fifosize		= 32,
-		.bEndpointAddress 	= USB_DIR_OUT | 3,
-		.bmAttributes		= USB_ENDPOINT_XFER_BULK,
-	 },
-	.imx_ep[4] = {
-		.ep = {
-			.name		= "ep4in-int",
-			.ops		= &imx_ep_ops,
-			.maxpacket	= 32,
-		 },
-		.imx_usb		= &controller,
-		.fifosize		= 32,
-		.bEndpointAddress 	= USB_DIR_IN | 4,
-		.bmAttributes		= USB_ENDPOINT_XFER_INT,
-	 },
-	.imx_ep[5] = {
-		.ep = {
-			.name		= "ep5out-int",
-			.ops		= &imx_ep_ops,
-			.maxpacket	= 32,
-		},
-		.imx_usb		= &controller,
-		.fifosize		= 32,
-		.bEndpointAddress 	= USB_DIR_OUT | 5,
-		.bmAttributes		= USB_ENDPOINT_XFER_INT,
-	 },
-};
-
-/*******************************************************************************
- * USB gadget driver functions
- *******************************************************************************
- */
-static int imx_udc_start(struct usb_gadget *gadget,
-		struct usb_gadget_driver *driver)
-{
-	struct imx_udc_struct *imx_usb;
-
-	imx_usb = container_of(gadget, struct imx_udc_struct, gadget);
-	/* first hook up the driver ... */
-	imx_usb->driver = driver;
-
-	D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",
-		__func__, driver->driver.name);
-
-	imx_udc_enable(imx_usb);
-
-	return 0;
-}
-
-static int imx_udc_stop(struct usb_gadget *gadget,
-		struct usb_gadget_driver *driver)
-{
-	struct imx_udc_struct *imx_usb = container_of(gadget,
-			struct imx_udc_struct, gadget);
-
-	udc_stop_activity(imx_usb, driver);
-	imx_udc_disable(imx_usb);
-	del_timer(&imx_usb->timer);
-
-	imx_usb->driver = NULL;
-
-	D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n",
-		__func__, driver->driver.name);
-
-	return 0;
-}
-
-/*******************************************************************************
- * Module functions
- *******************************************************************************
- */
-
-static int __init imx_udc_probe(struct platform_device *pdev)
-{
-	struct imx_udc_struct *imx_usb = &controller;
-	struct resource *res;
-	struct imxusb_platform_data *pdata;
-	struct clk *clk;
-	void __iomem *base;
-	int ret = 0;
-	int i;
-	resource_size_t res_size;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "can't get device resources\n");
-		return -ENODEV;
-	}
-
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_err(&pdev->dev, "driver needs platform data\n");
-		return -ENODEV;
-	}
-
-	res_size = resource_size(res);
-	if (!request_mem_region(res->start, res_size, res->name)) {
-		dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n",
-			res_size, res->start);
-		return -ENOMEM;
-	}
-
-	if (pdata->init) {
-		ret = pdata->init(&pdev->dev);
-		if (ret)
-			goto fail0;
-	}
-
-	base = ioremap(res->start, res_size);
-	if (!base) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		ret = -EIO;
-		goto fail1;
-	}
-
-	clk = clk_get(NULL, "usbd_clk");
-	if (IS_ERR(clk)) {
-		ret = PTR_ERR(clk);
-		dev_err(&pdev->dev, "can't get USB clock\n");
-		goto fail2;
-	}
-	clk_prepare_enable(clk);
-
-	if (clk_get_rate(clk) != 48000000) {
-		D_INI(&pdev->dev,
-			"Bad USB clock (%d Hz), changing to 48000000 Hz\n",
-			(int)clk_get_rate(clk));
-		if (clk_set_rate(clk, 48000000)) {
-			dev_err(&pdev->dev,
-				"Unable to set correct USB clock (48MHz)\n");
-			ret = -EIO;
-			goto fail3;
-		}
-	}
-
-	for (i = 0; i < IMX_USB_NB_EP + 1; i++) {
-		imx_usb->usbd_int[i] = platform_get_irq(pdev, i);
-		if (imx_usb->usbd_int[i] < 0) {
-			dev_err(&pdev->dev, "can't get irq number\n");
-			ret = -ENODEV;
-			goto fail3;
-		}
-	}
-
-	for (i = 0; i < IMX_USB_NB_EP + 1; i++) {
-		ret = request_irq(imx_usb->usbd_int[i], intr_handler(i),
-				     0, driver_name, imx_usb);
-		if (ret) {
-			dev_err(&pdev->dev, "can't get irq %i, err %d\n",
-				imx_usb->usbd_int[i], ret);
-			for (--i; i >= 0; i--)
-				free_irq(imx_usb->usbd_int[i], imx_usb);
-			goto fail3;
-		}
-	}
-
-	imx_usb->res = res;
-	imx_usb->base = base;
-	imx_usb->clk = clk;
-	imx_usb->dev = &pdev->dev;
-
-	platform_set_drvdata(pdev, imx_usb);
-
-	usb_init_data(imx_usb);
-	imx_udc_init(imx_usb);
-
-	init_timer(&imx_usb->timer);
-	imx_usb->timer.function = handle_config;
-	imx_usb->timer.data = (unsigned long)imx_usb;
-
-	ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);
-	if (ret)
-		goto fail4;
-
-	return 0;
-fail4:
-	for (i = 0; i < IMX_USB_NB_EP + 1; i++)
-		free_irq(imx_usb->usbd_int[i], imx_usb);
-fail3:
-	clk_put(clk);
-	clk_disable_unprepare(clk);
-fail2:
-	iounmap(base);
-fail1:
-	if (pdata->exit)
-		pdata->exit(&pdev->dev);
-fail0:
-	release_mem_region(res->start, res_size);
-	return ret;
-}
-
-static int __exit imx_udc_remove(struct platform_device *pdev)
-{
-	struct imx_udc_struct *imx_usb = platform_get_drvdata(pdev);
-	struct imxusb_platform_data *pdata = pdev->dev.platform_data;
-	int i;
-
-	usb_del_gadget_udc(&imx_usb->gadget);
-	imx_udc_disable(imx_usb);
-	del_timer(&imx_usb->timer);
-
-	for (i = 0; i < IMX_USB_NB_EP + 1; i++)
-		free_irq(imx_usb->usbd_int[i], imx_usb);
-
-	clk_put(imx_usb->clk);
-	clk_disable_unprepare(imx_usb->clk);
-	iounmap(imx_usb->base);
-
-	release_mem_region(imx_usb->res->start, resource_size(imx_usb->res));
-
-	if (pdata->exit)
-		pdata->exit(&pdev->dev);
-
-	return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-#ifdef	CONFIG_PM
-#define	imx_udc_suspend	NULL
-#define	imx_udc_resume	NULL
-#else
-#define	imx_udc_suspend	NULL
-#define	imx_udc_resume	NULL
-#endif
-
-/*----------------------------------------------------------------------------*/
-
-static struct platform_driver udc_driver = {
-	.driver		= {
-		.name	= driver_name,
-		.owner	= THIS_MODULE,
-	},
-	.remove		= __exit_p(imx_udc_remove),
-	.suspend	= imx_udc_suspend,
-	.resume		= imx_udc_resume,
-};
-
-module_platform_driver_probe(udc_driver, imx_udc_probe);
-
-MODULE_DESCRIPTION("IMX USB Device Controller driver");
-MODULE_AUTHOR("Darius Augulis <augulis.darius@gmail.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:imx_udc");

+ 0 - 351
drivers/usb/gadget/imx_udc.h

@@ -1,351 +0,0 @@
-/*
- *	Copyright (C) 2005 Mike Lee(eemike@gmail.com)
- *
- *	This udc driver is now under testing and code is based on pxa2xx_udc.h
- *	Please use it with your own risk!
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- */
-
-#ifndef __LINUX_USB_GADGET_IMX_H
-#define __LINUX_USB_GADGET_IMX_H
-
-#include <linux/types.h>
-
-/* Helper macros */
-#define EP_NO(ep)	((ep->bEndpointAddress) & ~USB_DIR_IN) /* IN:1, OUT:0 */
-#define EP_DIR(ep)	((ep->bEndpointAddress) & USB_DIR_IN ? 1 : 0)
-#define IMX_USB_NB_EP	6
-
-/* Driver structures */
-struct imx_request {
-	struct usb_request			req;
-	struct list_head			queue;
-	unsigned int				in_use;
-};
-
-enum ep0_state {
-	EP0_IDLE,
-	EP0_IN_DATA_PHASE,
-	EP0_OUT_DATA_PHASE,
-	EP0_CONFIG,
-	EP0_STALL,
-};
-
-struct imx_ep_struct {
-	struct usb_ep				ep;
-	struct imx_udc_struct			*imx_usb;
-	struct list_head			queue;
-	unsigned char				stopped;
-	unsigned char				fifosize;
-	unsigned char				bEndpointAddress;
-	unsigned char				bmAttributes;
-};
-
-struct imx_udc_struct {
-	struct usb_gadget			gadget;
-	struct usb_gadget_driver		*driver;
-	struct device				*dev;
-	struct imx_ep_struct			imx_ep[IMX_USB_NB_EP];
-	struct clk				*clk;
-	struct timer_list			timer;
-	enum ep0_state				ep0state;
-	struct resource				*res;
-	void __iomem				*base;
-	unsigned char				set_config;
-	int					cfg,
-						intf,
-						alt,
-						usbd_int[7];
-};
-
-/* USB registers */
-#define  USB_FRAME		(0x00)	/* USB frame */
-#define  USB_SPEC		(0x04)	/* USB Spec */
-#define  USB_STAT		(0x08)	/* USB Status */
-#define  USB_CTRL		(0x0C)	/* USB Control */
-#define  USB_DADR		(0x10)	/* USB Desc RAM addr */
-#define  USB_DDAT		(0x14)	/* USB Desc RAM/EP buffer data */
-#define  USB_INTR		(0x18)	/* USB interrupt */
-#define  USB_MASK		(0x1C)	/* USB Mask */
-#define  USB_ENAB		(0x24)	/* USB Enable */
-#define  USB_EP_STAT(x)		(0x30 + (x*0x30)) /* USB status/control */
-#define  USB_EP_INTR(x)		(0x34 + (x*0x30)) /* USB interrupt */
-#define  USB_EP_MASK(x)		(0x38 + (x*0x30)) /* USB mask */
-#define  USB_EP_FDAT(x)		(0x3C + (x*0x30)) /* USB FIFO data */
-#define  USB_EP_FDAT0(x)	(0x3C + (x*0x30)) /* USB FIFO data */
-#define  USB_EP_FDAT1(x)	(0x3D + (x*0x30)) /* USB FIFO data */
-#define  USB_EP_FDAT2(x)	(0x3E + (x*0x30)) /* USB FIFO data */
-#define  USB_EP_FDAT3(x)	(0x3F + (x*0x30)) /* USB FIFO data */
-#define  USB_EP_FSTAT(x)	(0x40 + (x*0x30)) /* USB FIFO status */
-#define  USB_EP_FCTRL(x)	(0x44 + (x*0x30)) /* USB FIFO control */
-#define  USB_EP_LRFP(x)		(0x48 + (x*0x30)) /* USB last rd f. pointer */
-#define  USB_EP_LWFP(x)		(0x4C + (x*0x30)) /* USB last wr f. pointer */
-#define  USB_EP_FALRM(x)	(0x50 + (x*0x30)) /* USB FIFO alarm */
-#define  USB_EP_FRDP(x)		(0x54 + (x*0x30)) /* USB FIFO read pointer */
-#define  USB_EP_FWRP(x)		(0x58 + (x*0x30)) /* USB FIFO write pointer */
-/* USB Control Register Bit Fields.*/
-#define CTRL_CMDOVER		(1<<6)	/* UDC status */
-#define CTRL_CMDERROR		(1<<5)	/* UDC status */
-#define CTRL_FE_ENA		(1<<3)	/* Enable Font End logic */
-#define CTRL_UDC_RST		(1<<2)	/* UDC reset */
-#define CTRL_AFE_ENA		(1<<1)	/* Analog Font end enable */
-#define CTRL_RESUME		(1<<0)	/* UDC resume */
-/* USB Status Register Bit Fields.*/
-#define STAT_RST		(1<<8)
-#define STAT_SUSP		(1<<7)
-#define STAT_CFG		(3<<5)
-#define STAT_INTF		(3<<3)
-#define STAT_ALTSET		(7<<0)
-/* USB Interrupt Status/Mask Registers Bit fields */
-#define INTR_WAKEUP		(1<<31)	/* Wake up Interrupt */
-#define INTR_MSOF		(1<<7)	/* Missed Start of Frame */
-#define INTR_SOF		(1<<6)	/* Start of Frame */
-#define INTR_RESET_STOP		(1<<5)	/* Reset Signaling stop */
-#define INTR_RESET_START	(1<<4)	/* Reset Signaling start */
-#define INTR_RESUME		(1<<3)	/* Suspend to resume */
-#define INTR_SUSPEND		(1<<2)	/* Active to suspend */
-#define INTR_FRAME_MATCH	(1<<1)	/* Frame matched */
-#define INTR_CFG_CHG		(1<<0)	/* Configuration change occurred */
-/* USB Enable Register Bit Fields.*/
-#define ENAB_RST		(1<<31)	/* Reset USB modules */
-#define ENAB_ENAB		(1<<30)	/* Enable USB modules*/
-#define ENAB_SUSPEND		(1<<29)	/* Suspend USB modules */
-#define ENAB_ENDIAN		(1<<28)	/* Endian of USB modules */
-#define ENAB_PWRMD		(1<<0)	/* Power mode of USB modules */
-/* USB Descriptor Ram Address Register bit fields */
-#define DADR_CFG		(1<<31)	/* Configuration */
-#define DADR_BSY		(1<<30)	/* Busy status */
-#define DADR_DADR		(0x1FF)	/* Descriptor Ram Address */
-/* USB Descriptor RAM/Endpoint Buffer Data Register bit fields */
-#define DDAT_DDAT		(0xFF)	/* Descriptor Endpoint Buffer */
-/* USB Endpoint Status Register bit fields */
-#define EPSTAT_BCOUNT		(0x7F<<16)	/* Endpoint FIFO byte count */
-#define EPSTAT_SIP		(1<<8)	/* Endpoint setup in progress */
-#define EPSTAT_DIR		(1<<7)	/* Endpoint transfer direction */
-#define EPSTAT_MAX		(3<<5)	/* Endpoint Max packet size */
-#define EPSTAT_TYP		(3<<3)	/* Endpoint type */
-#define EPSTAT_ZLPS		(1<<2)	/* Send zero length packet */
-#define EPSTAT_FLUSH		(1<<1)	/* Endpoint FIFO Flush */
-#define EPSTAT_STALL		(1<<0)	/* Force stall */
-/* USB Endpoint FIFO Status Register bit fields */
-#define FSTAT_FRAME_STAT	(0xF<<24)	/* Frame status bit [0-3] */
-#define FSTAT_ERR		(1<<22)	/* FIFO error */
-#define FSTAT_UF		(1<<21)	/* FIFO underflow */
-#define FSTAT_OF		(1<<20)	/* FIFO overflow */
-#define FSTAT_FR		(1<<19)	/* FIFO frame ready */
-#define FSTAT_FULL		(1<<18)	/* FIFO full */
-#define FSTAT_ALRM		(1<<17)	/* FIFO alarm */
-#define FSTAT_EMPTY		(1<<16)	/* FIFO empty */
-/* USB Endpoint FIFO Control Register bit fields */
-#define FCTRL_WFR		(1<<29)	/* Write frame end */
-/* USB Endpoint Interrupt Status Regsiter bit fields */
-#define EPINTR_FIFO_FULL	(1<<8)	/* fifo full */
-#define EPINTR_FIFO_EMPTY	(1<<7)	/* fifo empty */
-#define EPINTR_FIFO_ERROR	(1<<6)	/* fifo error */
-#define EPINTR_FIFO_HIGH	(1<<5)	/* fifo high */
-#define EPINTR_FIFO_LOW		(1<<4)	/* fifo low */
-#define EPINTR_MDEVREQ		(1<<3)	/* multi Device request */
-#define EPINTR_EOT		(1<<2)	/* fifo end of transfer */
-#define EPINTR_DEVREQ		(1<<1)	/* Device request */
-#define EPINTR_EOF		(1<<0)	/* fifo end of frame */
-
-/* Debug macros */
-#ifdef DEBUG
-
-/* #define DEBUG_REQ */
-/* #define DEBUG_TRX */
-/* #define DEBUG_INIT */
-/* #define DEBUG_EP0 */
-/* #define DEBUG_EPX */
-/* #define DEBUG_IRQ */
-/* #define DEBUG_EPIRQ */
-/* #define DEBUG_DUMP */
-/* #define DEBUG_ERR */
-
-#ifdef DEBUG_REQ
-	#define D_REQ(dev, args...)	dev_dbg(dev, ## args)
-#else
-	#define D_REQ(dev, args...)	do {} while (0)
-#endif /* DEBUG_REQ */
-
-#ifdef DEBUG_TRX
-	#define D_TRX(dev, args...)	dev_dbg(dev, ## args)
-#else
-	#define D_TRX(dev, args...)	do {} while (0)
-#endif /* DEBUG_TRX */
-
-#ifdef DEBUG_INIT
-	#define D_INI(dev, args...)	dev_dbg(dev, ## args)
-#else
-	#define D_INI(dev, args...)	do {} while (0)
-#endif /* DEBUG_INIT */
-
-#ifdef DEBUG_EP0
-	static const char *state_name[] = {
-		"EP0_IDLE",
-		"EP0_IN_DATA_PHASE",
-		"EP0_OUT_DATA_PHASE",
-		"EP0_CONFIG",
-		"EP0_STALL"
-	};
-	#define D_EP0(dev, args...)	dev_dbg(dev, ## args)
-#else
-	#define D_EP0(dev, args...)	do {} while (0)
-#endif /* DEBUG_EP0 */
-
-#ifdef DEBUG_EPX
-	#define D_EPX(dev, args...)	dev_dbg(dev, ## args)
-#else
-	#define D_EPX(dev, args...)	do {} while (0)
-#endif /* DEBUG_EP0 */
-
-#ifdef DEBUG_IRQ
-	static void dump_intr(const char *label, int irqreg, struct device *dev)
-	{
-		dev_dbg(dev, "<%s> USB_INTR=[%s%s%s%s%s%s%s%s%s]\n", label,
-			(irqreg & INTR_WAKEUP) ? " wake" : "",
-			(irqreg & INTR_MSOF) ? " msof" : "",
-			(irqreg & INTR_SOF) ? " sof" : "",
-			(irqreg & INTR_RESUME) ? " resume" : "",
-			(irqreg & INTR_SUSPEND) ? " suspend" : "",
-			(irqreg & INTR_RESET_STOP) ? " noreset" : "",
-			(irqreg & INTR_RESET_START) ? " reset" : "",
-			(irqreg & INTR_FRAME_MATCH) ? " fmatch" : "",
-			(irqreg & INTR_CFG_CHG) ? " config" : "");
-	}
-#else
-	#define dump_intr(x, y, z)		do {} while (0)
-#endif /* DEBUG_IRQ */
-
-#ifdef DEBUG_EPIRQ
-	static void dump_ep_intr(const char *label, int nr, int irqreg,
-							struct device *dev)
-	{
-		dev_dbg(dev, "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, nr,
-			(irqreg & EPINTR_FIFO_FULL) ? " full" : "",
-			(irqreg & EPINTR_FIFO_EMPTY) ? " fempty" : "",
-			(irqreg & EPINTR_FIFO_ERROR) ? " ferr" : "",
-			(irqreg & EPINTR_FIFO_HIGH) ? " fhigh" : "",
-			(irqreg & EPINTR_FIFO_LOW) ? " flow" : "",
-			(irqreg & EPINTR_MDEVREQ) ? " mreq" : "",
-			(irqreg & EPINTR_EOF) ? " eof" : "",
-			(irqreg & EPINTR_DEVREQ) ? " devreq" : "",
-			(irqreg & EPINTR_EOT) ? " eot" : "");
-	}
-#else
-	#define dump_ep_intr(x, y, z, i)	do {} while (0)
-#endif /* DEBUG_IRQ */
-
-#ifdef DEBUG_DUMP
-	static void dump_usb_stat(const char *label,
-						struct imx_udc_struct *imx_usb)
-	{
-		int temp = __raw_readl(imx_usb->base + USB_STAT);
-
-		dev_dbg(imx_usb->dev,
-			"<%s> USB_STAT=[%s%s CFG=%d, INTF=%d, ALTR=%d]\n", label,
-			(temp & STAT_RST) ? " reset" : "",
-			(temp & STAT_SUSP) ? " suspend" : "",
-			(temp & STAT_CFG) >> 5,
-			(temp & STAT_INTF) >> 3,
-			(temp & STAT_ALTSET));
-	}
-
-	static void dump_ep_stat(const char *label,
-						struct imx_ep_struct *imx_ep)
-	{
-		int temp = __raw_readl(imx_ep->imx_usb->base
-						+ USB_EP_INTR(EP_NO(imx_ep)));
-
-		dev_dbg(imx_ep->imx_usb->dev,
-			"<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n",
-			label, EP_NO(imx_ep),
-			(temp & EPINTR_FIFO_FULL) ? " full" : "",
-			(temp & EPINTR_FIFO_EMPTY) ? " fempty" : "",
-			(temp & EPINTR_FIFO_ERROR) ? " ferr" : "",
-			(temp & EPINTR_FIFO_HIGH) ? " fhigh" : "",
-			(temp & EPINTR_FIFO_LOW) ? " flow" : "",
-			(temp & EPINTR_MDEVREQ) ? " mreq" : "",
-			(temp & EPINTR_EOF) ? " eof" : "",
-			(temp & EPINTR_DEVREQ) ? " devreq" : "",
-			(temp & EPINTR_EOT) ? " eot" : "");
-
-		temp = __raw_readl(imx_ep->imx_usb->base
-						+ USB_EP_STAT(EP_NO(imx_ep)));
-
-		dev_dbg(imx_ep->imx_usb->dev,
-			"<%s> EP%d_STAT=[%s%s bcount=%d]\n",
-			label, EP_NO(imx_ep),
-			(temp & EPSTAT_SIP) ? " sip" : "",
-			(temp & EPSTAT_STALL) ? " stall" : "",
-			(temp & EPSTAT_BCOUNT) >> 16);
-
-		temp = __raw_readl(imx_ep->imx_usb->base
-						+ USB_EP_FSTAT(EP_NO(imx_ep)));
-
-		dev_dbg(imx_ep->imx_usb->dev,
-			"<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n",
-			label, EP_NO(imx_ep),
-			(temp & FSTAT_ERR) ? " ferr" : "",
-			(temp & FSTAT_UF) ? " funder" : "",
-			(temp & FSTAT_OF) ? " fover" : "",
-			(temp & FSTAT_FR) ? " fready" : "",
-			(temp & FSTAT_FULL) ? " ffull" : "",
-			(temp & FSTAT_ALRM) ? " falarm" : "",
-			(temp & FSTAT_EMPTY) ? " fempty" : "");
-	}
-
-	static void dump_req(const char *label, struct imx_ep_struct *imx_ep,
-							struct usb_request *req)
-	{
-		int i;
-
-		if (!req || !req->buf) {
-			dev_dbg(imx_ep->imx_usb->dev,
-					"<%s> req or req buf is free\n", label);
-			return;
-		}
-
-		if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state
-			== EP0_IN_DATA_PHASE)
-			|| (EP_NO(imx_ep) && EP_DIR(imx_ep))) {
-
-			dev_dbg(imx_ep->imx_usb->dev,
-						"<%s> request dump <", label);
-			for (i = 0; i < req->length; i++)
-				printk("%02x-", *((u8 *)req->buf + i));
-			printk(">\n");
-		}
-	}
-
-#else
-	#define dump_ep_stat(x, y)		do {} while (0)
-	#define dump_usb_stat(x, y)		do {} while (0)
-	#define dump_req(x, y, z)		do {} while (0)
-#endif /* DEBUG_DUMP */
-
-#ifdef DEBUG_ERR
-	#define D_ERR(dev, args...)	dev_dbg(dev, ## args)
-#else
-	#define D_ERR(dev, args...)	do {} while (0)
-#endif
-
-#else
-	#define D_REQ(dev, args...)		do {} while (0)
-	#define D_TRX(dev, args...)		do {} while (0)
-	#define D_INI(dev, args...)		do {} while (0)
-	#define D_EP0(dev, args...)		do {} while (0)
-	#define D_EPX(dev, args...)		do {} while (0)
-	#define dump_ep_intr(x, y, z, i)	do {} while (0)
-	#define dump_intr(x, y, z)		do {} while (0)
-	#define dump_ep_stat(x, y)		do {} while (0)
-	#define dump_usb_stat(x, y)		do {} while (0)
-	#define dump_req(x, y, z)		do {} while (0)
-	#define D_ERR(dev, args...)		do {} while (0)
-#endif /* DEBUG */
-
-#endif /* __LINUX_USB_GADGET_IMX_H */

+ 2 - 2
drivers/usb/gadget/m66592-udc.c

@@ -1584,7 +1584,7 @@ static int __init m66592_probe(struct platform_device *pdev)
 		goto clean_up;
 	}
 
-	if (pdev->dev.platform_data == NULL) {
+	if (dev_get_platdata(&pdev->dev) == NULL) {
 		dev_err(&pdev->dev, "no platform data\n");
 		ret = -ENODEV;
 		goto clean_up;
@@ -1598,7 +1598,7 @@ static int __init m66592_probe(struct platform_device *pdev)
 		goto clean_up;
 	}
 
-	m66592->pdata = pdev->dev.platform_data;
+	m66592->pdata = dev_get_platdata(&pdev->dev);
 	m66592->irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
 
 	spin_lock_init(&m66592->lock);

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

@@ -1109,7 +1109,7 @@ static int mv_u3d_controller_reset(struct mv_u3d *u3d)
 
 static int mv_u3d_enable(struct mv_u3d *u3d)
 {
-	struct mv_usb_platform_data *pdata = u3d->dev->platform_data;
+	struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
 	int retval;
 
 	if (u3d->active)
@@ -1138,7 +1138,7 @@ static int mv_u3d_enable(struct mv_u3d *u3d)
 
 static void mv_u3d_disable(struct mv_u3d *u3d)
 {
-	struct mv_usb_platform_data *pdata = u3d->dev->platform_data;
+	struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
 	if (u3d->clock_gating && u3d->active) {
 		dev_dbg(u3d->dev, "disable u3d\n");
 		if (pdata->phy_deinit)
@@ -1246,7 +1246,7 @@ 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;
+	struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
 	unsigned long flags;
 
 	if (u3d->driver)
@@ -1277,7 +1277,7 @@ 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;
+	struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
 	unsigned long flags;
 
 	u3d->vbus_valid_detect = 0;
@@ -1794,12 +1794,12 @@ static int mv_u3d_remove(struct platform_device *dev)
 static int mv_u3d_probe(struct platform_device *dev)
 {
 	struct mv_u3d *u3d = NULL;
-	struct mv_usb_platform_data *pdata = dev->dev.platform_data;
+	struct mv_usb_platform_data *pdata = dev_get_platdata(&dev->dev);
 	int retval = 0;
 	struct resource *r;
 	size_t size;
 
-	if (!dev->dev.platform_data) {
+	if (!dev_get_platdata(&dev->dev)) {
 		dev_err(&dev->dev, "missing platform_data\n");
 		retval = -ENODEV;
 		goto err_pdata;

+ 2 - 2
drivers/usb/gadget/mv_udc_core.c

@@ -2100,7 +2100,7 @@ static int mv_udc_remove(struct platform_device *pdev)
 
 static int mv_udc_probe(struct platform_device *pdev)
 {
-	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
+	struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct mv_udc *udc;
 	int retval = 0;
 	struct resource *r;
@@ -2118,7 +2118,7 @@ static int mv_udc_probe(struct platform_device *pdev)
 	}
 
 	udc->done = &release_done;
-	udc->pdata = pdev->dev.platform_data;
+	udc->pdata = dev_get_platdata(&pdev->dev);
 	spin_lock_init(&udc->lock);
 
 	udc->dev = pdev;

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

@@ -2734,7 +2734,7 @@ static int omap_udc_probe(struct platform_device *pdev)
 	int			hmc;
 	struct usb_phy		*xceiv = NULL;
 	const char		*type = NULL;
-	struct omap_usb_config	*config = pdev->dev.platform_data;
+	struct omap_usb_config	*config = dev_get_platdata(&pdev->dev);
 	struct clk		*dc_clk = NULL;
 	struct clk		*hhc_clk = NULL;
 

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

@@ -2117,7 +2117,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
 
 	/* other non-static parts of init */
 	dev->dev = &pdev->dev;
-	dev->mach = pdev->dev.platform_data;
+	dev->mach = dev_get_platdata(&pdev->dev);
 
 	dev->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 

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

@@ -2422,7 +2422,7 @@ static int pxa_udc_probe(struct platform_device *pdev)
 		return udc->irq;
 
 	udc->dev = &pdev->dev;
-	udc->mach = pdev->dev.platform_data;
+	udc->mach = dev_get_platdata(&pdev->dev);
 	udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 
 	gpio = udc->mach->gpio_pullup;

+ 1 - 1
drivers/usb/gadget/r8a66597-udc.c

@@ -1910,7 +1910,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 
 	spin_lock_init(&r8a66597->lock);
 	platform_set_drvdata(pdev, r8a66597);
-	r8a66597->pdata = pdev->dev.platform_data;
+	r8a66597->pdata = dev_get_platdata(&pdev->dev);
 	r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 
 	r8a66597->gadget.ops = &r8a66597_gadget_ops;

+ 2 - 2
drivers/usb/gadget/rndis.c

@@ -1142,7 +1142,7 @@ static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
 #endif /* CONFIG_USB_GADGET_DEBUG_FILES */
 
 
-int rndis_init(void)
+static int rndis_init(void)
 {
 	u8 i;
 
@@ -1176,7 +1176,7 @@ int rndis_init(void)
 }
 module_init(rndis_init);
 
-void rndis_exit(void)
+static void rndis_exit(void)
 {
 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
 	u8 i;

+ 12 - 2
drivers/usb/gadget/s3c-hsotg.c

@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/regulator/consumer.h>
+#include <linux/of_platform.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
@@ -3450,7 +3451,7 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
 
 static int s3c_hsotg_probe(struct platform_device *pdev)
 {
-	struct s3c_hsotg_plat *plat = pdev->dev.platform_data;
+	struct s3c_hsotg_plat *plat = dev_get_platdata(&pdev->dev);
 	struct usb_phy *phy;
 	struct device *dev = &pdev->dev;
 	struct s3c_hsotg_ep *eps;
@@ -3469,7 +3470,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 	phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 	if (IS_ERR(phy)) {
 		/* Fallback for pdata */
-		plat = pdev->dev.platform_data;
+		plat = dev_get_platdata(&pdev->dev);
 		if (!plat) {
 			dev_err(&pdev->dev, "no platform data or transceiver defined\n");
 			return -EPROBE_DEFER;
@@ -3648,10 +3649,19 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
 #define s3c_hsotg_resume NULL
 #endif
 
+#ifdef CONFIG_OF
+static const struct of_device_id s3c_hsotg_of_ids[] = {
+	{ .compatible = "samsung,s3c6400-hsotg", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, s3c_hsotg_of_ids);
+#endif
+
 static struct platform_driver s3c_hsotg_driver = {
 	.driver		= {
 		.name	= "s3c-hsotg",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(s3c_hsotg_of_ids),
 	},
 	.probe		= s3c_hsotg_probe,
 	.remove		= s3c_hsotg_remove,

+ 2 - 2
drivers/usb/gadget/s3c-hsudc.c

@@ -1262,7 +1262,7 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct resource *res;
 	struct s3c_hsudc *hsudc;
-	struct s3c24xx_hsudc_platdata *pd = pdev->dev.platform_data;
+	struct s3c24xx_hsudc_platdata *pd = dev_get_platdata(&pdev->dev);
 	int ret, i;
 
 	hsudc = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsudc) +
@@ -1275,7 +1275,7 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, dev);
 	hsudc->dev = dev;
-	hsudc->pd = pdev->dev.platform_data;
+	hsudc->pd = dev_get_platdata(&pdev->dev);
 
 	hsudc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 

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

@@ -1809,7 +1809,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
 	}
 
 	spin_lock_init(&udc->lock);
-	udc_info = pdev->dev.platform_data;
+	udc_info = dev_get_platdata(&pdev->dev);
 
 	rsrc_start = S3C2410_PA_USBDEV;
 	rsrc_len   = S3C24XX_SZ_USBDEV;

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

@@ -191,7 +191,7 @@ try_again:
 	frames = bytes_to_frames(runtime, count);
 	old_fs = get_fs();
 	set_fs(KERNEL_DS);
-	result = snd_pcm_lib_write(snd->substream, buf, frames);
+	result = snd_pcm_lib_write(snd->substream, (void __user *)buf, frames);
 	if (result != frames) {
 		ERROR(card, "Playback error: %d\n", (int)result);
 		set_fs(old_fs);

+ 11 - 1
drivers/usb/gadget/udc-core.c

@@ -23,6 +23,7 @@
 #include <linux/list.h>
 #include <linux/err.h>
 #include <linux/dma-mapping.h>
+#include <linux/workqueue.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
@@ -105,11 +106,18 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
 
 /* ------------------------------------------------------------------------- */
 
+static void usb_gadget_state_work(struct work_struct *work)
+{
+	struct usb_gadget	*gadget = work_to_gadget(work);
+
+	sysfs_notify(&gadget->dev.kobj, NULL, "state");
+}
+
 void usb_gadget_set_state(struct usb_gadget *gadget,
 		enum usb_device_state state)
 {
 	gadget->state = state;
-	sysfs_notify(&gadget->dev.kobj, NULL, "state");
+	schedule_work(&gadget->work);
 }
 EXPORT_SYMBOL_GPL(usb_gadget_set_state);
 
@@ -196,6 +204,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
 		goto err1;
 
 	dev_set_name(&gadget->dev, "gadget");
+	INIT_WORK(&gadget->work, usb_gadget_state_work);
 	gadget->dev.parent = parent;
 
 #ifdef	CONFIG_HAS_DMA
@@ -315,6 +324,7 @@ found:
 		usb_gadget_remove_driver(udc);
 
 	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
+	flush_work(&gadget->work);
 	device_unregister(&udc->dev);
 	device_unregister(&gadget->dev);
 }

+ 5 - 1
drivers/usb/gadget/uvc_queue.c

@@ -193,12 +193,16 @@ static int uvc_queue_buffer(struct uvc_video_queue *queue,
 
 	mutex_lock(&queue->mutex);
 	ret = vb2_qbuf(&queue->queue, buf);
+	if (ret < 0)
+		goto done;
+
 	spin_lock_irqsave(&queue->irqlock, flags);
 	ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
 	queue->flags &= ~UVC_QUEUE_PAUSED;
 	spin_unlock_irqrestore(&queue->irqlock, flags);
-	mutex_unlock(&queue->mutex);
 
+done:
+	mutex_unlock(&queue->mutex);
 	return ret;
 }
 

+ 1 - 4
drivers/usb/host/Kconfig

@@ -142,13 +142,11 @@ config USB_EHCI_MXC
 config USB_EHCI_HCD_OMAP
 	tristate "EHCI support for OMAP3 and later chips"
 	depends on ARCH_OMAP
+	select NOP_USB_XCEIV
 	default y
 	---help---
 	  Enables support for the on-chip EHCI controller on
 	  OMAP3 and later chips.
-	  If your system uses a PHY on the USB port, you will need to
-	  enable USB_PHY and the appropriate PHY driver as well. Most
-	  boards need the NOP_USB_XCEIV PHY driver.
 
 config USB_EHCI_HCD_ORION
 	tristate  "Support for Marvell EBU on-chip EHCI USB controller"
@@ -180,7 +178,6 @@ config USB_EHCI_HCD_AT91
 config USB_EHCI_MSM
 	tristate "Support for Qualcomm QSD/MSM on-chip EHCI USB controller"
 	depends on ARCH_MSM
-	depends on USB_PHY
 	select USB_EHCI_ROOT_HUB_TT
 	select USB_MSM_OTG
 	---help---

+ 7 - 7
drivers/usb/host/ehci-hub.c

@@ -183,7 +183,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
 	spin_lock_irq(&ehci->lock);
 
 	/* clear phy low-power mode before changing wakeup flags */
-	if (ehci->has_hostpc) {
+	if (ehci->has_tdi_phy_lpm) {
 		port = HCS_N_PORTS(ehci->hcs_params);
 		while (port--) {
 			u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[port];
@@ -217,7 +217,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
 	}
 
 	/* enter phy low-power mode again */
-	if (ehci->has_hostpc) {
+	if (ehci->has_tdi_phy_lpm) {
 		port = HCS_N_PORTS(ehci->hcs_params);
 		while (port--) {
 			u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[port];
@@ -309,7 +309,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
 		}
 	}
 
-	if (changed && ehci->has_hostpc) {
+	if (changed && ehci->has_tdi_phy_lpm) {
 		spin_unlock_irq(&ehci->lock);
 		msleep(5);	/* 5 ms for HCD to enter low-power mode */
 		spin_lock_irq(&ehci->lock);
@@ -436,7 +436,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 		goto shutdown;
 
 	/* clear phy low-power mode before resume */
-	if (ehci->bus_suspended && ehci->has_hostpc) {
+	if (ehci->bus_suspended && ehci->has_tdi_phy_lpm) {
 		i = HCS_N_PORTS(ehci->hcs_params);
 		while (i--) {
 			if (test_bit(i, &ehci->bus_suspended)) {
@@ -925,7 +925,7 @@ static int ehci_hub_control (
 				goto error;
 
 			/* clear phy low-power mode before resume */
-			if (ehci->has_hostpc) {
+			if (ehci->has_tdi_phy_lpm) {
 				temp1 = ehci_readl(ehci, hostpc_reg);
 				ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
 						hostpc_reg);
@@ -1162,12 +1162,12 @@ static int ehci_hub_control (
 
 			/* After above check the port must be connected.
 			 * Set appropriate bit thus could put phy into low power
-			 * mode if we have hostpc feature
+			 * mode if we have tdi_phy_lpm feature
 			 */
 			temp &= ~PORT_WKCONN_E;
 			temp |= PORT_WKDISC_E | PORT_WKOC_E;
 			ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
-			if (ehci->has_hostpc) {
+			if (ehci->has_tdi_phy_lpm) {
 				spin_unlock_irqrestore(&ehci->lock, flags);
 				msleep(5);/* 5ms for HCD enter low pwr mode */
 				spin_lock_irqsave(&ehci->lock, flags);

+ 31 - 64
drivers/usb/host/ehci-tegra.c

@@ -25,9 +25,9 @@
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/platform_device.h>
-#include <linux/platform_data/tegra_usb.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/usb/ehci_def.h>
@@ -51,6 +51,10 @@
 
 static struct hc_driver __read_mostly tegra_ehci_hc_driver;
 
+struct tegra_ehci_soc_config {
+	bool has_hostpc;
+};
+
 static int (*orig_hub_control)(struct usb_hcd *hcd,
 				u16 typeReq, u16 wValue, u16 wIndex,
 				char *buf, u16 wLength);
@@ -58,7 +62,6 @@ static int (*orig_hub_control)(struct usb_hcd *hcd,
 struct tegra_ehci_hcd {
 	struct tegra_usb_phy *phy;
 	struct clk *clk;
-	struct usb_phy *transceiver;
 	int port_resuming;
 	bool needs_double_reset;
 	enum tegra_usb_phy_port_speed port_speed;
@@ -322,50 +325,38 @@ static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
 	free_dma_aligned_buffer(urb);
 }
 
-static int setup_vbus_gpio(struct platform_device *pdev,
-			   struct tegra_ehci_platform_data *pdata)
-{
-	int err = 0;
-	int gpio;
-
-	gpio = pdata->vbus_gpio;
-	if (!gpio_is_valid(gpio))
-		gpio = of_get_named_gpio(pdev->dev.of_node,
-					 "nvidia,vbus-gpio", 0);
-	if (!gpio_is_valid(gpio))
-		return 0;
+static const struct tegra_ehci_soc_config tegra30_soc_config = {
+	.has_hostpc = true,
+};
 
-	err = gpio_request(gpio, "vbus_gpio");
-	if (err) {
-		dev_err(&pdev->dev, "can't request vbus gpio %d", gpio);
-		return err;
-	}
-	err = gpio_direction_output(gpio, 1);
-	if (err) {
-		dev_err(&pdev->dev, "can't enable vbus\n");
-		return err;
-	}
+static const struct tegra_ehci_soc_config tegra20_soc_config = {
+	.has_hostpc = false,
+};
 
-	return err;
-}
+static struct of_device_id tegra_ehci_of_match[] = {
+	{ .compatible = "nvidia,tegra30-ehci", .data = &tegra30_soc_config },
+	{ .compatible = "nvidia,tegra20-ehci", .data = &tegra20_soc_config },
+	{ },
+};
 
 static int tegra_ehci_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *match;
+	const struct tegra_ehci_soc_config *soc_config;
 	struct resource *res;
 	struct usb_hcd *hcd;
 	struct ehci_hcd *ehci;
 	struct tegra_ehci_hcd *tegra;
-	struct tegra_ehci_platform_data *pdata;
 	int err = 0;
 	int irq;
-	struct device_node *np_phy;
 	struct usb_phy *u_phy;
 
-	pdata = dev_get_platdata(&pdev->dev);
-	if (!pdata) {
-		dev_err(&pdev->dev, "Platform data missing\n");
-		return -EINVAL;
+	match = of_match_device(tegra_ehci_of_match, &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "Error: No device match found\n");
+		return -ENODEV;
 	}
+	soc_config = match->data;
 
 	/* Right now device-tree probed devices don't get dma_mask set.
 	 * Since shared usb code relies on it, set it here for now.
@@ -376,14 +367,11 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 	if (!pdev->dev.coherent_dma_mask)
 		pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
-	setup_vbus_gpio(pdev, pdata);
-
 	hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev,
 					dev_name(&pdev->dev));
 	if (!hcd) {
 		dev_err(&pdev->dev, "Unable to create HCD\n");
-		err = -ENOMEM;
-		goto cleanup_vbus_gpio;
+		return -ENOMEM;
 	}
 	platform_set_drvdata(pdev, hcd);
 	ehci = hcd_to_ehci(hcd);
@@ -406,13 +394,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 	udelay(1);
 	tegra_periph_reset_deassert(tegra->clk);
 
-	np_phy = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0);
-	if (!np_phy) {
-		err = -ENODEV;
-		goto cleanup_clk_en;
-	}
-
-	u_phy = tegra_usb_get_phy(np_phy);
+	u_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0);
 	if (IS_ERR(u_phy)) {
 		err = PTR_ERR(u_phy);
 		goto cleanup_clk_en;
@@ -437,6 +419,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 		goto cleanup_clk_en;
 	}
 	ehci->caps = hcd->regs + 0x100;
+	ehci->has_hostpc = soc_config->has_hostpc;
 
 	err = usb_phy_init(hcd->phy);
 	if (err) {
@@ -466,26 +449,18 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 		goto cleanup_phy;
 	}
 
-	if (pdata->operating_mode == TEGRA_USB_OTG) {
-		tegra->transceiver =
-			devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-		if (!IS_ERR(tegra->transceiver))
-			otg_set_host(tegra->transceiver->otg, &hcd->self);
-	} else {
-		tegra->transceiver = ERR_PTR(-ENODEV);
-	}
+	otg_set_host(u_phy->otg, &hcd->self);
 
 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (err) {
 		dev_err(&pdev->dev, "Failed to add USB HCD\n");
-		goto cleanup_transceiver;
+		goto cleanup_otg_set_host;
 	}
 
 	return err;
 
-cleanup_transceiver:
-	if (!IS_ERR(tegra->transceiver))
-		otg_set_host(tegra->transceiver->otg, NULL);
+cleanup_otg_set_host:
+	otg_set_host(u_phy->otg, NULL);
 cleanup_phy:
 	usb_phy_shutdown(hcd->phy);
 cleanup_clk_en:
@@ -494,8 +469,6 @@ cleanup_clk_get:
 	clk_put(tegra->clk);
 cleanup_hcd_create:
 	usb_put_hcd(hcd);
-cleanup_vbus_gpio:
-	/* FIXME: Undo setup_vbus_gpio() here */
 	return err;
 }
 
@@ -505,8 +478,7 @@ static int tegra_ehci_remove(struct platform_device *pdev)
 	struct tegra_ehci_hcd *tegra =
 		(struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv;
 
-	if (!IS_ERR(tegra->transceiver))
-		otg_set_host(tegra->transceiver->otg, NULL);
+	otg_set_host(hcd->phy->otg, NULL);
 
 	usb_phy_shutdown(hcd->phy);
 	usb_remove_hcd(hcd);
@@ -525,11 +497,6 @@ static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)
 		hcd->driver->shutdown(hcd);
 }
 
-static struct of_device_id tegra_ehci_of_match[] = {
-	{ .compatible = "nvidia,tegra20-ehci", },
-	{ },
-};
-
 static struct platform_driver tegra_ehci_driver = {
 	.probe		= tegra_ehci_probe,
 	.remove		= tegra_ehci_remove,

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

@@ -213,6 +213,7 @@ struct ehci_hcd {			/* one per controller */
 	#define OHCI_HCCTRL_LEN         0x4
 	__hc32			*ohci_hcctrl_reg;
 	unsigned		has_hostpc:1;
+	unsigned		has_tdi_phy_lpm:1;
 	unsigned		has_ppcd:1; /* support per-port change bits */
 	u8			sbrn;		/* packed release number */
 

+ 9 - 0
drivers/usb/musb/Kconfig

@@ -83,6 +83,8 @@ config USB_MUSB_AM35X
 
 config USB_MUSB_DSPS
 	tristate "TI DSPS platforms"
+	select USB_MUSB_AM335X_CHILD
+	depends on OF_IRQ
 
 config USB_MUSB_BLACKFIN
 	tristate "Blackfin"
@@ -93,6 +95,9 @@ config USB_MUSB_UX500
 
 endchoice
 
+config USB_MUSB_AM335X_CHILD
+	tristate
+
 choice
 	prompt 'MUSB DMA mode'
 	default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM
@@ -125,6 +130,10 @@ config USB_TI_CPPI_DMA
 	help
 	  Enable DMA transfers when TI CPPI DMA is available.
 
+config USB_TI_CPPI41_DMA
+	bool 'TI CPPI 4.1 (AM335x)'
+	depends on ARCH_OMAP
+
 config USB_TUSB_OMAP_DMA
 	bool 'TUSB 6010'
 	depends on USB_MUSB_TUSB6010

+ 4 - 0
drivers/usb/musb/Makefile

@@ -20,6 +20,9 @@ obj-$(CONFIG_USB_MUSB_DA8XX)			+= da8xx.o
 obj-$(CONFIG_USB_MUSB_BLACKFIN)			+= blackfin.o
 obj-$(CONFIG_USB_MUSB_UX500)			+= ux500.o
 
+
+obj-$(CONFIG_USB_MUSB_AM335X_CHILD)		+= musb_am335x.o
+
 # the kconfig must guarantee that only one of the
 # possible I/O schemes will be enabled at a time ...
 # PIO only, or DMA (several potential schemes).
@@ -29,3 +32,4 @@ musb_hdrc-$(CONFIG_USB_INVENTRA_DMA)		+= musbhsdma.o
 musb_hdrc-$(CONFIG_USB_TI_CPPI_DMA)		+= cppi_dma.o
 musb_hdrc-$(CONFIG_USB_TUSB_OMAP_DMA)		+= tusb6010_omap.o
 musb_hdrc-$(CONFIG_USB_UX500_DMA)		+= ux500_dma.o
+musb_hdrc-$(CONFIG_USB_TI_CPPI41_DMA)		+= musb_cppi41.o

+ 8 - 8
drivers/usb/musb/am35x.c

@@ -33,7 +33,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
 #include <linux/platform_data/usb-omap.h>
 
 #include "musb_core.h"
@@ -218,7 +218,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
 	struct musb  *musb = hci;
 	void __iomem *reg_base = musb->ctrl_base;
 	struct device *dev = musb->controller;
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = plat->board_data;
 	struct usb_otg *otg = musb->xceiv->otg;
 	unsigned long flags;
@@ -335,7 +335,7 @@ eoi:
 static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode)
 {
 	struct device *dev = musb->controller;
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = plat->board_data;
 	int     retval = 0;
 
@@ -350,7 +350,7 @@ static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode)
 static int am35x_musb_init(struct musb *musb)
 {
 	struct device *dev = musb->controller;
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = plat->board_data;
 	void __iomem *reg_base = musb->ctrl_base;
 	u32 rev;
@@ -394,7 +394,7 @@ static int am35x_musb_init(struct musb *musb)
 static int am35x_musb_exit(struct musb *musb)
 {
 	struct device *dev = musb->controller;
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = plat->board_data;
 
 	del_timer_sync(&otg_workaround);
@@ -456,7 +456,7 @@ static u64 am35x_dmamask = DMA_BIT_MASK(32);
 
 static int am35x_probe(struct platform_device *pdev)
 {
-	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct platform_device		*musb;
 	struct am35x_glue		*glue;
 
@@ -577,7 +577,7 @@ static int am35x_remove(struct platform_device *pdev)
 static int am35x_suspend(struct device *dev)
 {
 	struct am35x_glue	*glue = dev_get_drvdata(dev);
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = plat->board_data;
 
 	/* Shutdown the on-chip PHY and its PLL. */
@@ -593,7 +593,7 @@ static int am35x_suspend(struct device *dev)
 static int am35x_resume(struct device *dev)
 {
 	struct am35x_glue	*glue = dev_get_drvdata(dev);
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = plat->board_data;
 	int			ret;
 

+ 2 - 2
drivers/usb/musb/blackfin.c

@@ -19,7 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/prefetch.h>
-#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
 
 #include <asm/cacheflush.h>
 
@@ -451,7 +451,7 @@ static u64 bfin_dmamask = DMA_BIT_MASK(32);
 static int bfin_probe(struct platform_device *pdev)
 {
 	struct resource musb_resources[2];
-	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct platform_device		*musb;
 	struct bfin_glue		*glue;
 

+ 5 - 13
drivers/usb/musb/cppi_dma.c

@@ -150,14 +150,11 @@ static void cppi_pool_free(struct cppi_channel *c)
 	c->last_processed = NULL;
 }
 
-static int cppi_controller_start(struct dma_controller *c)
+static void cppi_controller_start(struct cppi *controller)
 {
-	struct cppi	*controller;
 	void __iomem	*tibase;
 	int		i;
 
-	controller = container_of(c, struct cppi, controller);
-
 	/* do whatever is necessary to start controller */
 	for (i = 0; i < ARRAY_SIZE(controller->tx); i++) {
 		controller->tx[i].transmit = true;
@@ -212,8 +209,6 @@ static int cppi_controller_start(struct dma_controller *c)
 	/* disable RNDIS mode, also host rx RNDIS autorequest */
 	musb_writel(tibase, DAVINCI_RNDIS_REG, 0);
 	musb_writel(tibase, DAVINCI_AUTOREQ_REG, 0);
-
-	return 0;
 }
 
 /*
@@ -222,14 +217,12 @@ static int cppi_controller_start(struct dma_controller *c)
  *  De-Init the DMA controller as necessary.
  */
 
-static int cppi_controller_stop(struct dma_controller *c)
+static void cppi_controller_stop(struct cppi *controller)
 {
-	struct cppi		*controller;
 	void __iomem		*tibase;
 	int			i;
 	struct musb		*musb;
 
-	controller = container_of(c, struct cppi, controller);
 	musb = controller->musb;
 
 	tibase = controller->tibase;
@@ -255,8 +248,6 @@ static int cppi_controller_stop(struct dma_controller *c)
 	/*disable tx/rx cppi */
 	musb_writel(tibase, DAVINCI_TXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_DISABLE);
 	musb_writel(tibase, DAVINCI_RXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_DISABLE);
-
-	return 0;
 }
 
 /* While dma channel is allocated, we only want the core irqs active
@@ -1321,8 +1312,6 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *mr
 	controller->tibase = mregs - DAVINCI_BASE_OFFSET;
 
 	controller->musb = musb;
-	controller->controller.start = cppi_controller_start;
-	controller->controller.stop = cppi_controller_stop;
 	controller->controller.channel_alloc = cppi_channel_allocate;
 	controller->controller.channel_release = cppi_channel_release;
 	controller->controller.channel_program = cppi_channel_program;
@@ -1351,6 +1340,7 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *mr
 		controller->irq = irq;
 	}
 
+	cppi_controller_start(controller);
 	return &controller->controller;
 }
 
@@ -1363,6 +1353,8 @@ void dma_controller_destroy(struct dma_controller *c)
 
 	cppi = container_of(c, struct cppi, controller);
 
+	cppi_controller_stop(cppi);
+
 	if (cppi->irq)
 		free_irq(cppi->irq, cppi->musb);
 

+ 2 - 2
drivers/usb/musb/da8xx.c

@@ -33,7 +33,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
 
 #include <mach/da8xx.h>
 #include <linux/platform_data/usb-davinci.h>
@@ -477,7 +477,7 @@ static u64 da8xx_dmamask = DMA_BIT_MASK(32);
 static int da8xx_probe(struct platform_device *pdev)
 {
 	struct resource musb_resources[2];
-	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct platform_device		*musb;
 	struct da8xx_glue		*glue;
 

+ 2 - 2
drivers/usb/musb/davinci.c

@@ -33,7 +33,7 @@
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
 
 #include <mach/cputype.h>
 #include <mach/hardware.h>
@@ -510,7 +510,7 @@ static u64 davinci_dmamask = DMA_BIT_MASK(32);
 static int davinci_probe(struct platform_device *pdev)
 {
 	struct resource musb_resources[2];
-	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct platform_device		*musb;
 	struct davinci_glue		*glue;
 	struct clk			*clk;

+ 55 - 0
drivers/usb/musb/musb_am335x.c

@@ -0,0 +1,55 @@
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+
+static int am335x_child_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	pm_runtime_enable(&pdev->dev);
+
+	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	pm_runtime_disable(&pdev->dev);
+	return ret;
+}
+
+static int of_remove_populated_child(struct device *dev, void *d)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	of_device_unregister(pdev);
+	return 0;
+}
+
+static int am335x_child_remove(struct platform_device *pdev)
+{
+	device_for_each_child(&pdev->dev, NULL, of_remove_populated_child);
+	pm_runtime_disable(&pdev->dev);
+	return 0;
+}
+
+static const struct of_device_id am335x_child_of_match[] = {
+	{ .compatible = "ti,am33xx-usb" },
+	{  },
+};
+MODULE_DEVICE_TABLE(of, am335x_child_of_match);
+
+static struct platform_driver am335x_child_driver = {
+	.probe		= am335x_child_probe,
+	.remove         = am335x_child_remove,
+	.driver         = {
+		.name   = "am335x-usb-childs",
+		.of_match_table	= of_match_ptr(am335x_child_of_match),
+	},
+};
+
+module_platform_driver(am335x_child_driver);
+MODULE_DESCRIPTION("AM33xx child devices");
+MODULE_LICENSE("GPL v2");

+ 7 - 23
drivers/usb/musb/musb_core.c

@@ -1763,12 +1763,8 @@ static void musb_free(struct musb *musb)
 			disable_irq_wake(musb->nIrq);
 		free_irq(musb->nIrq, musb);
 	}
-	if (is_dma_capable() && musb->dma_controller) {
-		struct dma_controller	*c = musb->dma_controller;
-
-		(void) c->stop(c);
-		dma_controller_destroy(c);
-	}
+	if (musb->dma_controller)
+		dma_controller_destroy(musb->dma_controller);
 
 	musb_host_free(musb);
 }
@@ -1786,7 +1782,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 {
 	int			status;
 	struct musb		*musb;
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 
 	/* The driver might handle more features than the board; OK.
 	 * Fail when the board needs a feature that's not enabled.
@@ -1843,19 +1839,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 
 	pm_runtime_get_sync(musb->controller);
 
-#ifndef CONFIG_MUSB_PIO_ONLY
-	if (use_dma && dev->dma_mask) {
-		struct dma_controller	*c;
-
-		c = dma_controller_create(musb, musb->mregs);
-		musb->dma_controller = c;
-		if (c)
-			(void) c->start(c);
-	}
-#endif
-	/* ideally this would be abstracted in platform setup */
-	if (!is_dma_capable() || !musb->dma_controller)
-		dev->dma_mask = NULL;
+	if (use_dma && dev->dma_mask)
+		musb->dma_controller = dma_controller_create(musb, musb->mregs);
 
 	/* be sure interrupts are disabled before connecting ISR */
 	musb_platform_disable(musb);
@@ -1943,6 +1928,8 @@ fail4:
 	musb_gadget_cleanup(musb);
 
 fail3:
+	if (musb->dma_controller)
+		dma_controller_destroy(musb->dma_controller);
 	pm_runtime_put_sync(musb->controller);
 
 fail2:
@@ -2001,9 +1988,6 @@ static int musb_remove(struct platform_device *pdev)
 
 	musb_free(musb);
 	device_init_wakeup(dev, 0);
-#ifndef CONFIG_MUSB_PIO_ONLY
-	dma_set_mask(dev, *dev->parent->dma_mask);
-#endif
 	return 0;
 }
 

+ 0 - 8
drivers/usb/musb/musb_core.h

@@ -83,11 +83,6 @@ enum {
 	MUSB_PORT_MODE_DUAL_ROLE,
 };
 
-#ifdef CONFIG_PROC_FS
-#include <linux/fs.h>
-#define MUSB_CONFIG_PROC_FS
-#endif
-
 /****************************** CONSTANTS ********************************/
 
 #ifndef MUSB_C_NUM_EPS
@@ -425,9 +420,6 @@ struct musb {
 
 	struct musb_hdrc_config	*config;
 
-#ifdef MUSB_CONFIG_PROC_FS
-	struct proc_dir_entry *proc_entry;
-#endif
 	int			xceiv_old_state;
 #ifdef CONFIG_DEBUG_FS
 	struct dentry		*debugfs_root;

+ 555 - 0
drivers/usb/musb/musb_cppi41.c

@@ -0,0 +1,555 @@
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/sizes.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+
+#include "musb_core.h"
+
+#define RNDIS_REG(x) (0x80 + ((x - 1) * 4))
+
+#define EP_MODE_AUTOREG_NONE		0
+#define EP_MODE_AUTOREG_ALL_NEOP	1
+#define EP_MODE_AUTOREG_ALWAYS		3
+
+#define EP_MODE_DMA_TRANSPARENT		0
+#define EP_MODE_DMA_RNDIS		1
+#define EP_MODE_DMA_GEN_RNDIS		3
+
+#define USB_CTRL_TX_MODE	0x70
+#define USB_CTRL_RX_MODE	0x74
+#define USB_CTRL_AUTOREQ	0xd0
+#define USB_TDOWN		0xd8
+
+struct cppi41_dma_channel {
+	struct dma_channel channel;
+	struct cppi41_dma_controller *controller;
+	struct musb_hw_ep *hw_ep;
+	struct dma_chan *dc;
+	dma_cookie_t cookie;
+	u8 port_num;
+	u8 is_tx;
+	u8 is_allocated;
+	u8 usb_toggle;
+
+	dma_addr_t buf_addr;
+	u32 total_len;
+	u32 prog_len;
+	u32 transferred;
+	u32 packet_sz;
+};
+
+#define MUSB_DMA_NUM_CHANNELS 15
+
+struct cppi41_dma_controller {
+	struct dma_controller controller;
+	struct cppi41_dma_channel rx_channel[MUSB_DMA_NUM_CHANNELS];
+	struct cppi41_dma_channel tx_channel[MUSB_DMA_NUM_CHANNELS];
+	struct musb *musb;
+	u32 rx_mode;
+	u32 tx_mode;
+	u32 auto_req;
+};
+
+static void save_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
+{
+	u16 csr;
+	u8 toggle;
+
+	if (cppi41_channel->is_tx)
+		return;
+	if (!is_host_active(cppi41_channel->controller->musb))
+		return;
+
+	csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR);
+	toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;
+
+	cppi41_channel->usb_toggle = toggle;
+}
+
+static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
+{
+	u16 csr;
+	u8 toggle;
+
+	if (cppi41_channel->is_tx)
+		return;
+	if (!is_host_active(cppi41_channel->controller->musb))
+		return;
+
+	csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR);
+	toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;
+
+	/*
+	 * AM335x Advisory 1.0.13: Due to internal synchronisation error the
+	 * data toggle may reset from DATA1 to DATA0 during receiving data from
+	 * more than one endpoint.
+	 */
+	if (!toggle && toggle == cppi41_channel->usb_toggle) {
+		csr |= MUSB_RXCSR_H_DATATOGGLE | MUSB_RXCSR_H_WR_DATATOGGLE;
+		musb_writew(cppi41_channel->hw_ep->regs, MUSB_RXCSR, csr);
+		dev_dbg(cppi41_channel->controller->musb->controller,
+				"Restoring DATA1 toggle.\n");
+	}
+
+	cppi41_channel->usb_toggle = toggle;
+}
+
+static void cppi41_dma_callback(void *private_data)
+{
+	struct dma_channel *channel = private_data;
+	struct cppi41_dma_channel *cppi41_channel = channel->private_data;
+	struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+	struct musb *musb = hw_ep->musb;
+	unsigned long flags;
+	struct dma_tx_state txstate;
+	u32 transferred;
+
+	spin_lock_irqsave(&musb->lock, flags);
+
+	dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie,
+			&txstate);
+	transferred = cppi41_channel->prog_len - txstate.residue;
+	cppi41_channel->transferred += transferred;
+
+	dev_dbg(musb->controller, "DMA transfer done on hw_ep=%d bytes=%d/%d\n",
+		hw_ep->epnum, cppi41_channel->transferred,
+		cppi41_channel->total_len);
+
+	update_rx_toggle(cppi41_channel);
+
+	if (cppi41_channel->transferred == cppi41_channel->total_len ||
+			transferred < cppi41_channel->packet_sz) {
+
+		/* done, complete */
+		cppi41_channel->channel.actual_len =
+			cppi41_channel->transferred;
+		cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE;
+		musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx);
+	} else {
+		/* next iteration, reload */
+		struct dma_chan *dc = cppi41_channel->dc;
+		struct dma_async_tx_descriptor *dma_desc;
+		enum dma_transfer_direction direction;
+		u16 csr;
+		u32 remain_bytes;
+		void __iomem *epio = cppi41_channel->hw_ep->regs;
+
+		cppi41_channel->buf_addr += cppi41_channel->packet_sz;
+
+		remain_bytes = cppi41_channel->total_len;
+		remain_bytes -= cppi41_channel->transferred;
+		remain_bytes = min(remain_bytes, cppi41_channel->packet_sz);
+		cppi41_channel->prog_len = remain_bytes;
+
+		direction = cppi41_channel->is_tx ? DMA_MEM_TO_DEV
+			: DMA_DEV_TO_MEM;
+		dma_desc = dmaengine_prep_slave_single(dc,
+				cppi41_channel->buf_addr,
+				remain_bytes,
+				direction,
+				DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+		if (WARN_ON(!dma_desc))
+			return;
+
+		dma_desc->callback = cppi41_dma_callback;
+		dma_desc->callback_param = channel;
+		cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
+		dma_async_issue_pending(dc);
+
+		if (!cppi41_channel->is_tx) {
+			csr = musb_readw(epio, MUSB_RXCSR);
+			csr |= MUSB_RXCSR_H_REQPKT;
+			musb_writew(epio, MUSB_RXCSR, csr);
+		}
+	}
+	spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+static u32 update_ep_mode(unsigned ep, unsigned mode, u32 old)
+{
+	unsigned shift;
+
+	shift = (ep - 1) * 2;
+	old &= ~(3 << shift);
+	old |= mode << shift;
+	return old;
+}
+
+static void cppi41_set_dma_mode(struct cppi41_dma_channel *cppi41_channel,
+		unsigned mode)
+{
+	struct cppi41_dma_controller *controller = cppi41_channel->controller;
+	u32 port;
+	u32 new_mode;
+	u32 old_mode;
+
+	if (cppi41_channel->is_tx)
+		old_mode = controller->tx_mode;
+	else
+		old_mode = controller->rx_mode;
+	port = cppi41_channel->port_num;
+	new_mode = update_ep_mode(port, mode, old_mode);
+
+	if (new_mode == old_mode)
+		return;
+	if (cppi41_channel->is_tx) {
+		controller->tx_mode = new_mode;
+		musb_writel(controller->musb->ctrl_base, USB_CTRL_TX_MODE,
+				new_mode);
+	} else {
+		controller->rx_mode = new_mode;
+		musb_writel(controller->musb->ctrl_base, USB_CTRL_RX_MODE,
+				new_mode);
+	}
+}
+
+static void cppi41_set_autoreq_mode(struct cppi41_dma_channel *cppi41_channel,
+		unsigned mode)
+{
+	struct cppi41_dma_controller *controller = cppi41_channel->controller;
+	u32 port;
+	u32 new_mode;
+	u32 old_mode;
+
+	old_mode = controller->auto_req;
+	port = cppi41_channel->port_num;
+	new_mode = update_ep_mode(port, mode, old_mode);
+
+	if (new_mode == old_mode)
+		return;
+	controller->auto_req = new_mode;
+	musb_writel(controller->musb->ctrl_base, USB_CTRL_AUTOREQ, new_mode);
+}
+
+static bool cppi41_configure_channel(struct dma_channel *channel,
+				u16 packet_sz, u8 mode,
+				dma_addr_t dma_addr, u32 len)
+{
+	struct cppi41_dma_channel *cppi41_channel = channel->private_data;
+	struct dma_chan *dc = cppi41_channel->dc;
+	struct dma_async_tx_descriptor *dma_desc;
+	enum dma_transfer_direction direction;
+	struct musb *musb = cppi41_channel->controller->musb;
+	unsigned use_gen_rndis = 0;
+
+	dev_dbg(musb->controller,
+		"configure ep%d/%x packet_sz=%d, mode=%d, dma_addr=0x%llx, len=%d is_tx=%d\n",
+		cppi41_channel->port_num, RNDIS_REG(cppi41_channel->port_num),
+		packet_sz, mode, (unsigned long long) dma_addr,
+		len, cppi41_channel->is_tx);
+
+	cppi41_channel->buf_addr = dma_addr;
+	cppi41_channel->total_len = len;
+	cppi41_channel->transferred = 0;
+	cppi41_channel->packet_sz = packet_sz;
+
+	/*
+	 * Due to AM335x' Advisory 1.0.13 we are not allowed to transfer more
+	 * than max packet size at a time.
+	 */
+	if (cppi41_channel->is_tx)
+		use_gen_rndis = 1;
+
+	if (use_gen_rndis) {
+		/* RNDIS mode */
+		if (len > packet_sz) {
+			musb_writel(musb->ctrl_base,
+				RNDIS_REG(cppi41_channel->port_num), len);
+			/* gen rndis */
+			cppi41_set_dma_mode(cppi41_channel,
+					EP_MODE_DMA_GEN_RNDIS);
+
+			/* auto req */
+			cppi41_set_autoreq_mode(cppi41_channel,
+					EP_MODE_AUTOREG_ALL_NEOP);
+		} else {
+			musb_writel(musb->ctrl_base,
+					RNDIS_REG(cppi41_channel->port_num), 0);
+			cppi41_set_dma_mode(cppi41_channel,
+					EP_MODE_DMA_TRANSPARENT);
+			cppi41_set_autoreq_mode(cppi41_channel,
+					EP_MODE_AUTOREG_NONE);
+		}
+	} else {
+		/* fallback mode */
+		cppi41_set_dma_mode(cppi41_channel, EP_MODE_DMA_TRANSPARENT);
+		cppi41_set_autoreq_mode(cppi41_channel, EP_MODE_AUTOREG_NONE);
+		len = min_t(u32, packet_sz, len);
+	}
+	cppi41_channel->prog_len = len;
+	direction = cppi41_channel->is_tx ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+	dma_desc = dmaengine_prep_slave_single(dc, dma_addr, len, direction,
+			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!dma_desc)
+		return false;
+
+	dma_desc->callback = cppi41_dma_callback;
+	dma_desc->callback_param = channel;
+	cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
+
+	save_rx_toggle(cppi41_channel);
+	dma_async_issue_pending(dc);
+	return true;
+}
+
+static struct dma_channel *cppi41_dma_channel_allocate(struct dma_controller *c,
+				struct musb_hw_ep *hw_ep, u8 is_tx)
+{
+	struct cppi41_dma_controller *controller = container_of(c,
+			struct cppi41_dma_controller, controller);
+	struct cppi41_dma_channel *cppi41_channel = NULL;
+	u8 ch_num = hw_ep->epnum - 1;
+
+	if (ch_num >= MUSB_DMA_NUM_CHANNELS)
+		return NULL;
+
+	if (is_tx)
+		cppi41_channel = &controller->tx_channel[ch_num];
+	else
+		cppi41_channel = &controller->rx_channel[ch_num];
+
+	if (!cppi41_channel->dc)
+		return NULL;
+
+	if (cppi41_channel->is_allocated)
+		return NULL;
+
+	cppi41_channel->hw_ep = hw_ep;
+	cppi41_channel->is_allocated = 1;
+
+	return &cppi41_channel->channel;
+}
+
+static void cppi41_dma_channel_release(struct dma_channel *channel)
+{
+	struct cppi41_dma_channel *cppi41_channel = channel->private_data;
+
+	if (cppi41_channel->is_allocated) {
+		cppi41_channel->is_allocated = 0;
+		channel->status = MUSB_DMA_STATUS_FREE;
+		channel->actual_len = 0;
+	}
+}
+
+static int cppi41_dma_channel_program(struct dma_channel *channel,
+				u16 packet_sz, u8 mode,
+				dma_addr_t dma_addr, u32 len)
+{
+	int ret;
+
+	BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN ||
+		channel->status == MUSB_DMA_STATUS_BUSY);
+
+	channel->status = MUSB_DMA_STATUS_BUSY;
+	channel->actual_len = 0;
+	ret = cppi41_configure_channel(channel, packet_sz, mode, dma_addr, len);
+	if (!ret)
+		channel->status = MUSB_DMA_STATUS_FREE;
+
+	return ret;
+}
+
+static int cppi41_is_compatible(struct dma_channel *channel, u16 maxpacket,
+		void *buf, u32 length)
+{
+	struct cppi41_dma_channel *cppi41_channel = channel->private_data;
+	struct cppi41_dma_controller *controller = cppi41_channel->controller;
+	struct musb *musb = controller->musb;
+
+	if (is_host_active(musb)) {
+		WARN_ON(1);
+		return 1;
+	}
+	if (cppi41_channel->is_tx)
+		return 1;
+	/* AM335x Advisory 1.0.13. No workaround for device RX mode */
+	return 0;
+}
+
+static int cppi41_dma_channel_abort(struct dma_channel *channel)
+{
+	struct cppi41_dma_channel *cppi41_channel = channel->private_data;
+	struct cppi41_dma_controller *controller = cppi41_channel->controller;
+	struct musb *musb = controller->musb;
+	void __iomem *epio = cppi41_channel->hw_ep->regs;
+	int tdbit;
+	int ret;
+	unsigned is_tx;
+	u16 csr;
+
+	is_tx = cppi41_channel->is_tx;
+	dev_dbg(musb->controller, "abort channel=%d, is_tx=%d\n",
+			cppi41_channel->port_num, is_tx);
+
+	if (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)
+		return 0;
+
+	if (is_tx) {
+		csr = musb_readw(epio, MUSB_TXCSR);
+		csr &= ~MUSB_TXCSR_DMAENAB;
+		musb_writew(epio, MUSB_TXCSR, csr);
+	} else {
+		csr = musb_readw(epio, MUSB_RXCSR);
+		csr &= ~(MUSB_RXCSR_H_REQPKT | MUSB_RXCSR_DMAENAB);
+		musb_writew(epio, MUSB_RXCSR, csr);
+
+		csr = musb_readw(epio, MUSB_RXCSR);
+		if (csr & MUSB_RXCSR_RXPKTRDY) {
+			csr |= MUSB_RXCSR_FLUSHFIFO;
+			musb_writew(epio, MUSB_RXCSR, csr);
+			musb_writew(epio, MUSB_RXCSR, csr);
+		}
+	}
+
+	tdbit = 1 << cppi41_channel->port_num;
+	if (is_tx)
+		tdbit <<= 16;
+
+	do {
+		musb_writel(musb->ctrl_base, USB_TDOWN, tdbit);
+		ret = dmaengine_terminate_all(cppi41_channel->dc);
+	} while (ret == -EAGAIN);
+
+	musb_writel(musb->ctrl_base, USB_TDOWN, tdbit);
+
+	if (is_tx) {
+		csr = musb_readw(epio, MUSB_TXCSR);
+		if (csr & MUSB_TXCSR_TXPKTRDY) {
+			csr |= MUSB_TXCSR_FLUSHFIFO;
+			musb_writew(epio, MUSB_TXCSR, csr);
+		}
+	}
+
+	cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE;
+	return 0;
+}
+
+static void cppi41_release_all_dma_chans(struct cppi41_dma_controller *ctrl)
+{
+	struct dma_chan *dc;
+	int i;
+
+	for (i = 0; i < MUSB_DMA_NUM_CHANNELS; i++) {
+		dc = ctrl->tx_channel[i].dc;
+		if (dc)
+			dma_release_channel(dc);
+		dc = ctrl->rx_channel[i].dc;
+		if (dc)
+			dma_release_channel(dc);
+	}
+}
+
+static void cppi41_dma_controller_stop(struct cppi41_dma_controller *controller)
+{
+	cppi41_release_all_dma_chans(controller);
+}
+
+static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
+{
+	struct musb *musb = controller->musb;
+	struct device *dev = musb->controller;
+	struct device_node *np = dev->of_node;
+	struct cppi41_dma_channel *cppi41_channel;
+	int count;
+	int i;
+	int ret;
+
+	count = of_property_count_strings(np, "dma-names");
+	if (count < 0)
+		return count;
+
+	for (i = 0; i < count; i++) {
+		struct dma_chan *dc;
+		struct dma_channel *musb_dma;
+		const char *str;
+		unsigned is_tx;
+		unsigned int port;
+
+		ret = of_property_read_string_index(np, "dma-names", i, &str);
+		if (ret)
+			goto err;
+		if (!strncmp(str, "tx", 2))
+			is_tx = 1;
+		else if (!strncmp(str, "rx", 2))
+			is_tx = 0;
+		else {
+			dev_err(dev, "Wrong dmatype %s\n", str);
+			goto err;
+		}
+		ret = kstrtouint(str + 2, 0, &port);
+		if (ret)
+			goto err;
+
+		if (port > MUSB_DMA_NUM_CHANNELS || !port)
+			goto err;
+		if (is_tx)
+			cppi41_channel = &controller->tx_channel[port - 1];
+		else
+			cppi41_channel = &controller->rx_channel[port - 1];
+
+		cppi41_channel->controller = controller;
+		cppi41_channel->port_num = port;
+		cppi41_channel->is_tx = is_tx;
+
+		musb_dma = &cppi41_channel->channel;
+		musb_dma->private_data = cppi41_channel;
+		musb_dma->status = MUSB_DMA_STATUS_FREE;
+		musb_dma->max_len = SZ_4M;
+
+		dc = dma_request_slave_channel(dev, str);
+		if (!dc) {
+			dev_err(dev, "Falied to request %s.\n", str);
+			goto err;
+		}
+		cppi41_channel->dc = dc;
+	}
+	return 0;
+err:
+	cppi41_release_all_dma_chans(controller);
+	return -EINVAL;
+}
+
+void dma_controller_destroy(struct dma_controller *c)
+{
+	struct cppi41_dma_controller *controller = container_of(c,
+			struct cppi41_dma_controller, controller);
+
+	cppi41_dma_controller_stop(controller);
+	kfree(controller);
+}
+
+struct dma_controller *dma_controller_create(struct musb *musb,
+					void __iomem *base)
+{
+	struct cppi41_dma_controller *controller;
+	int ret;
+
+	if (!musb->controller->of_node) {
+		dev_err(musb->controller, "Need DT for the DMA engine.\n");
+		return NULL;
+	}
+
+	controller = kzalloc(sizeof(*controller), GFP_KERNEL);
+	if (!controller)
+		goto kzalloc_fail;
+
+	controller->musb = musb;
+
+	controller->controller.channel_alloc = cppi41_dma_channel_allocate;
+	controller->controller.channel_release = cppi41_dma_channel_release;
+	controller->controller.channel_program = cppi41_dma_channel_program;
+	controller->controller.channel_abort = cppi41_dma_channel_abort;
+	controller->controller.is_compatible = cppi41_is_compatible;
+
+	ret = cppi41_dma_controller_start(controller);
+	if (ret)
+		goto plat_get_fail;
+	return &controller->controller;
+
+plat_get_fail:
+	kfree(controller);
+kzalloc_fail:
+	return NULL;
+}

+ 15 - 6
drivers/usb/musb/musb_dma.h

@@ -62,13 +62,13 @@ struct musb_hw_ep;
 
 #define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
 
-#ifndef CONFIG_MUSB_PIO_ONLY
-#define	is_dma_capable()	(1)
-#else
+#ifdef CONFIG_MUSB_PIO_ONLY
 #define	is_dma_capable()	(0)
+#else
+#define	is_dma_capable()	(1)
 #endif
 
-#ifdef CONFIG_USB_TI_CPPI_DMA
+#if defined(CONFIG_USB_TI_CPPI_DMA) || defined(CONFIG_USB_TI_CPPI41_DMA)
 #define	is_cppi_enabled()	1
 #else
 #define	is_cppi_enabled()	0
@@ -159,8 +159,6 @@ dma_channel_status(struct dma_channel *c)
  * Controllers manage dma channels.
  */
 struct dma_controller {
-	int			(*start)(struct dma_controller *);
-	int			(*stop)(struct dma_controller *);
 	struct dma_channel	*(*channel_alloc)(struct dma_controller *,
 					struct musb_hw_ep *, u8 is_tx);
 	void			(*channel_release)(struct dma_channel *);
@@ -177,9 +175,20 @@ struct dma_controller {
 /* called after channel_program(), may indicate a fault */
 extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit);
 
+#ifdef CONFIG_MUSB_PIO_ONLY
+static inline struct dma_controller *dma_controller_create(struct musb *m,
+		void __iomem *io)
+{
+	return NULL;
+}
+
+static inline void dma_controller_destroy(struct dma_controller *d) { }
+
+#else
 
 extern struct dma_controller *dma_controller_create(struct musb *, void __iomem *);
 
 extern void dma_controller_destroy(struct dma_controller *);
+#endif
 
 #endif	/* __MUSB_DMA_H__ */

+ 103 - 279
drivers/usb/musb/musb_dsps.c

@@ -36,19 +36,18 @@
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <linux/module.h>
-#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
 #include <linux/platform_data/usb-omap.h>
 #include <linux/sizes.h>
 
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include "musb_core.h"
 
-#ifdef CONFIG_OF
 static const struct of_device_id musb_dsps_of_match[];
-#endif
 
 /**
  * avoid using musb_readx()/musb_writex() as glue layer should not be
@@ -75,7 +74,6 @@ struct dsps_musb_wrapper {
 	u16	revision;
 	u16	control;
 	u16	status;
-	u16	eoi;
 	u16	epintr_set;
 	u16	epintr_clear;
 	u16	epintr_status;
@@ -108,10 +106,7 @@ struct dsps_musb_wrapper {
 	/* bit positions for mode */
 	unsigned	iddig:5;
 	/* miscellaneous stuff */
-	u32		musb_core_offset;
 	u8		poll_seconds;
-	/* number of musb instances */
-	u8		instances;
 };
 
 /**
@@ -119,53 +114,12 @@ struct dsps_musb_wrapper {
  */
 struct dsps_glue {
 	struct device *dev;
-	struct platform_device *musb[2];	/* child musb pdev */
+	struct platform_device *musb;	/* child musb pdev */
 	const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
-	struct timer_list timer[2];	/* otg_workaround timer */
-	unsigned long last_timer[2];    /* last timer data for each instance */
-	u32 __iomem *usb_ctrl[2];
+	struct timer_list timer;	/* otg_workaround timer */
+	unsigned long last_timer;    /* last timer data for each instance */
 };
 
-#define	DSPS_AM33XX_CONTROL_MODULE_PHYS_0	0x44e10620
-#define	DSPS_AM33XX_CONTROL_MODULE_PHYS_1	0x44e10628
-
-static const resource_size_t dsps_control_module_phys[] = {
-	DSPS_AM33XX_CONTROL_MODULE_PHYS_0,
-	DSPS_AM33XX_CONTROL_MODULE_PHYS_1,
-};
-
-#define USBPHY_CM_PWRDN		(1 << 0)
-#define USBPHY_OTG_PWRDN	(1 << 1)
-#define USBPHY_OTGVDET_EN	(1 << 19)
-#define USBPHY_OTGSESSEND_EN	(1 << 20)
-
-/**
- * musb_dsps_phy_control - phy on/off
- * @glue: struct dsps_glue *
- * @id: musb instance
- * @on: flag for phy to be switched on or off
- *
- * This is to enable the PHY using usb_ctrl register in system control
- * module space.
- *
- * XXX: This function will be removed once we have a seperate driver for
- * control module
- */
-static void musb_dsps_phy_control(struct dsps_glue *glue, u8 id, u8 on)
-{
-	u32 usbphycfg;
-
-	usbphycfg = readl(glue->usb_ctrl[id]);
-
-	if (on) {
-		usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
-		usbphycfg |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN;
-	} else {
-		usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
-	}
-
-	writel(usbphycfg, glue->usb_ctrl[id]);
-}
 /**
  * dsps_musb_enable - enable interrupts
  */
@@ -205,7 +159,6 @@ static void dsps_musb_disable(struct musb *musb)
 	dsps_writel(reg_base, wrp->epintr_clear,
 			 wrp->txep_bitmap | wrp->rxep_bitmap);
 	dsps_writeb(musb->mregs, MUSB_DEVCTL, 0);
-	dsps_writel(reg_base, wrp->eoi, 0);
 }
 
 static void otg_timer(unsigned long _musb)
@@ -213,7 +166,6 @@ static void otg_timer(unsigned long _musb)
 	struct musb *musb = (void *)_musb;
 	void __iomem *mregs = musb->mregs;
 	struct device *dev = musb->controller;
-	struct platform_device *pdev = to_platform_device(dev);
 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
 	const struct dsps_musb_wrapper *wrp = glue->wrp;
 	u8 devctl;
@@ -250,7 +202,7 @@ static void otg_timer(unsigned long _musb)
 	case OTG_STATE_B_IDLE:
 		devctl = dsps_readb(mregs, MUSB_DEVCTL);
 		if (devctl & MUSB_DEVCTL_BDEVICE)
-			mod_timer(&glue->timer[pdev->id],
+			mod_timer(&glue->timer,
 					jiffies + wrp->poll_seconds * HZ);
 		else
 			musb->xceiv->state = OTG_STATE_A_IDLE;
@@ -264,7 +216,6 @@ static void otg_timer(unsigned long _musb)
 static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
 {
 	struct device *dev = musb->controller;
-	struct platform_device *pdev = to_platform_device(dev);
 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
 
 	if (timeout == 0)
@@ -275,23 +226,23 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
 				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 		dev_dbg(musb->controller, "%s active, deleting timer\n",
 				usb_otg_state_string(musb->xceiv->state));
-		del_timer(&glue->timer[pdev->id]);
-		glue->last_timer[pdev->id] = jiffies;
+		del_timer(&glue->timer);
+		glue->last_timer = jiffies;
 		return;
 	}
 
-	if (time_after(glue->last_timer[pdev->id], timeout) &&
-				timer_pending(&glue->timer[pdev->id])) {
+	if (time_after(glue->last_timer, timeout) &&
+				timer_pending(&glue->timer)) {
 		dev_dbg(musb->controller,
 			"Longer idle timer already pending, ignoring...\n");
 		return;
 	}
-	glue->last_timer[pdev->id] = timeout;
+	glue->last_timer = timeout;
 
 	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
 		usb_otg_state_string(musb->xceiv->state),
 			jiffies_to_msecs(timeout - jiffies));
-	mod_timer(&glue->timer[pdev->id], timeout);
+	mod_timer(&glue->timer, timeout);
 }
 
 static irqreturn_t dsps_interrupt(int irq, void *hci)
@@ -299,7 +250,6 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 	struct musb  *musb = hci;
 	void __iomem *reg_base = musb->ctrl_base;
 	struct device *dev = musb->controller;
-	struct platform_device *pdev = to_platform_device(dev);
 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
 	const struct dsps_musb_wrapper *wrp = glue->wrp;
 	unsigned long flags;
@@ -319,7 +269,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 	/* Get usb core interrupts */
 	usbintr = dsps_readl(reg_base, wrp->coreintr_status);
 	if (!usbintr && !epintr)
-		goto eoi;
+		goto out;
 
 	musb->int_usb =	(usbintr & wrp->usb_bitmap) >> wrp->usb_shift;
 	if (usbintr)
@@ -359,7 +309,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 			 */
 			musb->int_usb &= ~MUSB_INTR_VBUSERROR;
 			musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
-			mod_timer(&glue->timer[pdev->id],
+			mod_timer(&glue->timer,
 					jiffies + wrp->poll_seconds * HZ);
 			WARNING("VBUS error workaround (delay coming)\n");
 		} else if (drvvbus) {
@@ -367,7 +317,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 			MUSB_HST_MODE(musb);
 			musb->xceiv->otg->default_a = 1;
 			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
-			del_timer(&glue->timer[pdev->id]);
+			del_timer(&glue->timer);
 		} else {
 			musb->is_active = 0;
 			MUSB_DEV_MODE(musb);
@@ -387,16 +337,10 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 	if (musb->int_tx || musb->int_rx || musb->int_usb)
 		ret |= musb_interrupt(musb);
 
- eoi:
-	/* EOI needs to be written for the IRQ to be re-asserted. */
-	if (ret == IRQ_HANDLED || epintr || usbintr)
-		dsps_writel(reg_base, wrp->eoi, 1);
-
 	/* Poll for ID change */
 	if (musb->xceiv->state == OTG_STATE_B_IDLE)
-		mod_timer(&glue->timer[pdev->id],
-			 jiffies + wrp->poll_seconds * HZ);
-
+		mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
+out:
 	spin_unlock_irqrestore(&musb->lock, flags);
 
 	return ret;
@@ -405,37 +349,38 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 static int dsps_musb_init(struct musb *musb)
 {
 	struct device *dev = musb->controller;
-	struct platform_device *pdev = to_platform_device(dev);
 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
+	struct platform_device *parent = to_platform_device(dev->parent);
 	const struct dsps_musb_wrapper *wrp = glue->wrp;
-	void __iomem *reg_base = musb->ctrl_base;
+	void __iomem *reg_base;
+	struct resource *r;
 	u32 rev, val;
-	int status;
 
-	/* mentor core register starts at offset of 0x400 from musb base */
-	musb->mregs += wrp->musb_core_offset;
+	r = platform_get_resource_byname(parent, IORESOURCE_MEM, "control");
+	if (!r)
+		return -EINVAL;
+
+	reg_base = devm_ioremap_resource(dev, r);
+	if (!musb->ctrl_base)
+		return -EINVAL;
+	musb->ctrl_base = reg_base;
 
 	/* NOP driver needs change if supporting dual instance */
-	usb_nop_xceiv_register();
-	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
-	if (IS_ERR_OR_NULL(musb->xceiv))
-		return -EPROBE_DEFER;
+	musb->xceiv = devm_usb_get_phy_by_phandle(dev, "phys", 0);
+	if (IS_ERR(musb->xceiv))
+		return PTR_ERR(musb->xceiv);
 
 	/* Returns zero if e.g. not clocked */
 	rev = dsps_readl(reg_base, wrp->revision);
-	if (!rev) {
-		status = -ENODEV;
-		goto err0;
-	}
+	if (!rev)
+		return -ENODEV;
 
-	setup_timer(&glue->timer[pdev->id], otg_timer, (unsigned long) musb);
+	usb_phy_init(musb->xceiv);
+	setup_timer(&glue->timer, otg_timer, (unsigned long) musb);
 
 	/* Reset the musb */
 	dsps_writel(reg_base, wrp->control, (1 << wrp->reset));
 
-	/* Start the on-chip PHY and its PLL. */
-	musb_dsps_phy_control(glue, pdev->id, 1);
-
 	musb->isr = dsps_interrupt;
 
 	/* reset the otgdisable bit, needed for host mode to work */
@@ -443,31 +388,17 @@ static int dsps_musb_init(struct musb *musb)
 	val &= ~(1 << wrp->otg_disable);
 	dsps_writel(musb->ctrl_base, wrp->phy_utmi, val);
 
-	/* clear level interrupt */
-	dsps_writel(reg_base, wrp->eoi, 0);
-
 	return 0;
-err0:
-	usb_put_phy(musb->xceiv);
-	usb_nop_xceiv_unregister();
-	return status;
 }
 
 static int dsps_musb_exit(struct musb *musb)
 {
 	struct device *dev = musb->controller;
-	struct platform_device *pdev = to_platform_device(dev);
 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
 
-	del_timer_sync(&glue->timer[pdev->id]);
-
-	/* Shutdown the on-chip PHY and its PLL. */
-	musb_dsps_phy_control(glue, pdev->id, 0);
-
-	/* NOP driver needs change if supporting dual instance */
-	usb_put_phy(musb->xceiv);
-	usb_nop_xceiv_unregister();
+	del_timer_sync(&glue->timer);
 
+	usb_phy_shutdown(musb->xceiv);
 	return 0;
 }
 
@@ -483,116 +414,98 @@ static struct musb_platform_ops dsps_ops = {
 
 static u64 musb_dmamask = DMA_BIT_MASK(32);
 
-static int dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
+static int get_int_prop(struct device_node *dn, const char *s)
 {
-	struct device *dev = glue->dev;
-	struct platform_device *pdev = to_platform_device(dev);
-	struct musb_hdrc_platform_data  *pdata = dev->platform_data;
-	struct device_node *np = pdev->dev.of_node;
-	struct musb_hdrc_config	*config;
-	struct platform_device	*musb;
-	struct resource *res;
+	int ret;
+	u32 val;
+
+	ret = of_property_read_u32(dn, s, &val);
+	if (ret)
+		return 0;
+	return val;
+}
+
+static int dsps_create_musb_pdev(struct dsps_glue *glue,
+		struct platform_device *parent)
+{
+	struct musb_hdrc_platform_data pdata;
 	struct resource	resources[2];
-	char res_name[11];
+	struct device *dev = &parent->dev;
+	struct musb_hdrc_config	*config;
+	struct platform_device *musb;
+	struct device_node *dn = parent->dev.of_node;
+	struct device_node *child_node;
 	int ret;
 
-	resources[0].start = dsps_control_module_phys[id];
-	resources[0].end = resources[0].start + SZ_4 - 1;
-	resources[0].flags = IORESOURCE_MEM;
+	child_node = of_get_child_by_name(dn, "usb");
+	if (!child_node)
+		return -EINVAL;
 
-	glue->usb_ctrl[id] = devm_ioremap_resource(&pdev->dev, resources);
-	if (IS_ERR(glue->usb_ctrl[id])) {
-		ret = PTR_ERR(glue->usb_ctrl[id]);
-		goto err0;
+	memset(resources, 0, sizeof(resources));
+	ret = of_address_to_resource(child_node, 0, &resources[0]);
+	if (ret) {
+		dev_err(dev, "failed to get memory.\n");
+		return ret;
 	}
 
-	/* first resource is for usbss, so start index from 1 */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, id + 1);
-	if (!res) {
-		dev_err(dev, "failed to get memory for instance %d\n", id);
-		ret = -ENODEV;
-		goto err0;
-	}
-	res->parent = NULL;
-	resources[0] = *res;
-
-	/* first resource is for usbss, so start index from 1 */
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, id + 1);
-	if (!res) {
-		dev_err(dev, "failed to get irq for instance %d\n", id);
-		ret = -ENODEV;
-		goto err0;
+	ret = of_irq_to_resource(child_node, 0, &resources[1]);
+	if (ret == 0) {
+		dev_err(dev, "failed to get irq.\n");
+		ret = -EINVAL;
+		return ret;
 	}
-	res->parent = NULL;
-	resources[1] = *res;
-	resources[1].name = "mc";
 
 	/* allocate the child platform device */
 	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 	if (!musb) {
 		dev_err(dev, "failed to allocate musb device\n");
-		ret = -ENOMEM;
-		goto err0;
+		return -ENOMEM;
 	}
 
 	musb->dev.parent		= dev;
 	musb->dev.dma_mask		= &musb_dmamask;
 	musb->dev.coherent_dma_mask	= musb_dmamask;
+	musb->dev.of_node		= of_node_get(child_node);
 
-	glue->musb[id]			= musb;
+	glue->musb = musb;
 
-	ret = platform_device_add_resources(musb, resources, 2);
+	ret = platform_device_add_resources(musb, resources,
+			ARRAY_SIZE(resources));
 	if (ret) {
 		dev_err(dev, "failed to add resources\n");
-		goto err2;
+		goto err;
 	}
 
-	if (np) {
-		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-		if (!pdata) {
-			dev_err(&pdev->dev,
-				"failed to allocate musb platform data\n");
-			ret = -ENOMEM;
-			goto err2;
-		}
-
-		config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
-		if (!config) {
-			dev_err(&pdev->dev,
-				"failed to allocate musb hdrc config\n");
-			ret = -ENOMEM;
-			goto err2;
-		}
-
-		of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
-		of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
-		snprintf(res_name, sizeof(res_name), "port%d-mode", id);
-		of_property_read_u32(np, res_name, (u32 *)&pdata->mode);
-		of_property_read_u32(np, "power", (u32 *)&pdata->power);
-		config->multipoint = of_property_read_bool(np, "multipoint");
-
-		pdata->config		= config;
+	config = devm_kzalloc(&parent->dev, sizeof(*config), GFP_KERNEL);
+	if (!config) {
+		dev_err(dev, "failed to allocate musb hdrc config\n");
+		ret = -ENOMEM;
+		goto err;
 	}
+	pdata.config = config;
+	pdata.platform_ops = &dsps_ops;
 
-	pdata->platform_ops		= &dsps_ops;
+	config->num_eps = get_int_prop(child_node, "num-eps");
+	config->ram_bits = get_int_prop(child_node, "ram-bits");
+	pdata.mode = get_int_prop(child_node, "port-mode");
+	pdata.power = get_int_prop(child_node, "power");
+	config->multipoint = of_property_read_bool(child_node, "multipoint");
 
-	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	ret = platform_device_add_data(musb, &pdata, sizeof(pdata));
 	if (ret) {
 		dev_err(dev, "failed to add platform_data\n");
-		goto err2;
+		goto err;
 	}
 
 	ret = platform_device_add(musb);
 	if (ret) {
 		dev_err(dev, "failed to register musb device\n");
-		goto err2;
+		goto err;
 	}
-
 	return 0;
 
-err2:
+err:
 	platform_device_put(musb);
-err0:
 	return ret;
 }
 
@@ -601,14 +514,12 @@ static int dsps_probe(struct platform_device *pdev)
 	const struct of_device_id *match;
 	const struct dsps_musb_wrapper *wrp;
 	struct dsps_glue *glue;
-	struct resource *iomem;
-	int ret, i;
+	int ret;
 
 	match = of_match_node(musb_dsps_of_match, pdev->dev.of_node);
 	if (!match) {
 		dev_err(&pdev->dev, "fail to get matching of_match struct\n");
-		ret = -EINVAL;
-		goto err0;
+		return -EINVAL;
 	}
 	wrp = match->data;
 
@@ -616,29 +527,13 @@ static int dsps_probe(struct platform_device *pdev)
 	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
 		dev_err(&pdev->dev, "unable to allocate glue memory\n");
-		ret = -ENOMEM;
-		goto err0;
-	}
-
-	/* get memory resource */
-	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!iomem) {
-		dev_err(&pdev->dev, "failed to get usbss mem resourse\n");
-		ret = -ENODEV;
-		goto err1;
+		return -ENOMEM;
 	}
 
 	glue->dev = &pdev->dev;
+	glue->wrp = wrp;
 
-	glue->wrp = kmemdup(wrp, sizeof(*wrp), GFP_KERNEL);
-	if (!glue->wrp) {
-		dev_err(&pdev->dev, "failed to duplicate wrapper struct memory\n");
-		ret = -ENOMEM;
-		goto err1;
-	}
 	platform_set_drvdata(pdev, glue);
-
-	/* enable the usbss clocks */
 	pm_runtime_enable(&pdev->dev);
 
 	ret = pm_runtime_get_sync(&pdev->dev);
@@ -647,17 +542,9 @@ static int dsps_probe(struct platform_device *pdev)
 		goto err2;
 	}
 
-	/* create the child platform device for all instances of musb */
-	for (i = 0; i < wrp->instances ; i++) {
-		ret = dsps_create_musb_pdev(glue, i);
-		if (ret != 0) {
-			dev_err(&pdev->dev, "failed to create child pdev\n");
-			/* release resources of previously created instances */
-			for (i--; i >= 0 ; i--)
-				platform_device_unregister(glue->musb[i]);
-			goto err3;
-		}
-	}
+	ret = dsps_create_musb_pdev(glue, pdev);
+	if (ret)
+		goto err3;
 
 	return 0;
 
@@ -665,65 +552,27 @@ err3:
 	pm_runtime_put(&pdev->dev);
 err2:
 	pm_runtime_disable(&pdev->dev);
-	kfree(glue->wrp);
-err1:
 	kfree(glue);
-err0:
 	return ret;
 }
+
 static int dsps_remove(struct platform_device *pdev)
 {
 	struct dsps_glue *glue = platform_get_drvdata(pdev);
-	const struct dsps_musb_wrapper *wrp = glue->wrp;
-	int i;
 
-	/* delete the child platform device */
-	for (i = 0; i < wrp->instances ; i++)
-		platform_device_unregister(glue->musb[i]);
+	platform_device_unregister(glue->musb);
 
 	/* disable usbss clocks */
 	pm_runtime_put(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
-	kfree(glue->wrp);
 	kfree(glue);
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int dsps_suspend(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev->parent);
-	struct dsps_glue *glue = platform_get_drvdata(pdev);
-	const struct dsps_musb_wrapper *wrp = glue->wrp;
-	int i;
-
-	for (i = 0; i < wrp->instances; i++)
-		musb_dsps_phy_control(glue, i, 0);
-
-	return 0;
-}
-
-static int dsps_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev->parent);
-	struct dsps_glue *glue = platform_get_drvdata(pdev);
-	const struct dsps_musb_wrapper *wrp = glue->wrp;
-	int i;
-
-	for (i = 0; i < wrp->instances; i++)
-		musb_dsps_phy_control(glue, i, 1);
-
-	return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
-
-static const struct dsps_musb_wrapper ti81xx_driver_data = {
+static const struct dsps_musb_wrapper am33xx_driver_data = {
 	.revision		= 0x00,
 	.control		= 0x14,
 	.status			= 0x18,
-	.eoi			= 0x24,
 	.epintr_set		= 0x38,
 	.epintr_clear		= 0x40,
 	.epintr_status		= 0x30,
@@ -745,38 +594,23 @@ static const struct dsps_musb_wrapper ti81xx_driver_data = {
 	.rxep_shift		= 16,
 	.rxep_mask		= 0xfffe,
 	.rxep_bitmap		= (0xfffe << 16),
-	.musb_core_offset	= 0x400,
 	.poll_seconds		= 2,
-	.instances		= 1,
-};
-
-static const struct platform_device_id musb_dsps_id_table[] = {
-	{
-		.name	= "musb-ti81xx",
-		.driver_data	= (kernel_ulong_t) &ti81xx_driver_data,
-	},
-	{  },	/* Terminating Entry */
 };
-MODULE_DEVICE_TABLE(platform, musb_dsps_id_table);
 
-#ifdef CONFIG_OF
 static const struct of_device_id musb_dsps_of_match[] = {
 	{ .compatible = "ti,musb-am33xx",
-		.data = (void *) &ti81xx_driver_data, },
+		.data = (void *) &am33xx_driver_data, },
 	{  },
 };
 MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
-#endif
 
 static struct platform_driver dsps_usbss_driver = {
 	.probe		= dsps_probe,
 	.remove         = dsps_remove,
 	.driver         = {
 		.name   = "musb-dsps",
-		.pm	= &dsps_pm_ops,
 		.of_match_table	= of_match_ptr(musb_dsps_of_match),
 	},
-	.id_table	= musb_dsps_id_table,
 };
 
 MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer");
@@ -784,14 +618,4 @@ MODULE_AUTHOR("Ravi B <ravibabu@ti.com>");
 MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
 MODULE_LICENSE("GPL v2");
 
-static int __init dsps_init(void)
-{
-	return platform_driver_register(&dsps_usbss_driver);
-}
-subsys_initcall(dsps_init);
-
-static void __exit dsps_exit(void)
-{
-	platform_driver_unregister(&dsps_usbss_driver);
-}
-module_exit(dsps_exit);
+module_platform_driver(dsps_usbss_driver);

+ 45 - 42
drivers/usb/musb/musb_gadget.c

@@ -357,47 +357,49 @@ static void txstate(struct musb *musb, struct musb_request *req)
 			}
 		}
 
-#elif defined(CONFIG_USB_TI_CPPI_DMA)
-		/* program endpoint CSR first, then setup DMA */
-		csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
-		csr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE |
-		       MUSB_TXCSR_MODE;
-		musb_writew(epio, MUSB_TXCSR,
-			(MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN)
-				| csr);
-
-		/* ensure writebuffer is empty */
-		csr = musb_readw(epio, MUSB_TXCSR);
-
-		/* NOTE host side sets DMAENAB later than this; both are
-		 * OK since the transfer dma glue (between CPPI and Mentor
-		 * fifos) just tells CPPI it could start.  Data only moves
-		 * to the USB TX fifo when both fifos are ready.
-		 */
-
-		/* "mode" is irrelevant here; handle terminating ZLPs like
-		 * PIO does, since the hardware RNDIS mode seems unreliable
-		 * except for the last-packet-is-already-short case.
-		 */
-		use_dma = use_dma && c->channel_program(
-				musb_ep->dma, musb_ep->packet_sz,
-				0,
-				request->dma + request->actual,
-				request_size);
-		if (!use_dma) {
-			c->channel_release(musb_ep->dma);
-			musb_ep->dma = NULL;
-			csr &= ~MUSB_TXCSR_DMAENAB;
-			musb_writew(epio, MUSB_TXCSR, csr);
-			/* invariant: prequest->buf is non-null */
-		}
-#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
-		use_dma = use_dma && c->channel_program(
-				musb_ep->dma, musb_ep->packet_sz,
-				request->zero,
-				request->dma + request->actual,
-				request_size);
 #endif
+		if (is_cppi_enabled()) {
+			/* program endpoint CSR first, then setup DMA */
+			csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
+			csr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE |
+				MUSB_TXCSR_MODE;
+			musb_writew(epio, MUSB_TXCSR, (MUSB_TXCSR_P_WZC_BITS &
+						~MUSB_TXCSR_P_UNDERRUN) | csr);
+
+			/* ensure writebuffer is empty */
+			csr = musb_readw(epio, MUSB_TXCSR);
+
+			/*
+			 * NOTE host side sets DMAENAB later than this; both are
+			 * OK since the transfer dma glue (between CPPI and
+			 * Mentor fifos) just tells CPPI it could start. Data
+			 * only moves to the USB TX fifo when both fifos are
+			 * ready.
+			 */
+			/*
+			 * "mode" is irrelevant here; handle terminating ZLPs
+			 * like PIO does, since the hardware RNDIS mode seems
+			 * unreliable except for the
+			 * last-packet-is-already-short case.
+			 */
+			use_dma = use_dma && c->channel_program(
+					musb_ep->dma, musb_ep->packet_sz,
+					0,
+					request->dma + request->actual,
+					request_size);
+			if (!use_dma) {
+				c->channel_release(musb_ep->dma);
+				musb_ep->dma = NULL;
+				csr &= ~MUSB_TXCSR_DMAENAB;
+				musb_writew(epio, MUSB_TXCSR, csr);
+				/* invariant: prequest->buf is non-null */
+			}
+		} else if (tusb_dma_omap())
+			use_dma = use_dma && c->channel_program(
+					musb_ep->dma, musb_ep->packet_sz,
+					request->zero,
+					request->dma + request->actual,
+					request_size);
 	}
 #endif
 
@@ -1266,7 +1268,8 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 		dev_dbg(musb->controller, "req %p queued to %s while ep %s\n",
 				req, ep->name, "disabled");
 		status = -ESHUTDOWN;
-		goto cleanup;
+		unmap_dma_buffer(request, musb);
+		goto unlock;
 	}
 
 	/* add request to the list */
@@ -1276,7 +1279,7 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 	if (!musb_ep->busy && &request->list == musb_ep->req_list.next)
 		musb_ep_restart(musb, request);
 
-cleanup:
+unlock:
 	spin_unlock_irqrestore(&musb->lock, lockflags);
 	return status;
 }

+ 2 - 15
drivers/usb/musb/musbhsdma.c

@@ -37,18 +37,10 @@
 #include "musb_core.h"
 #include "musbhsdma.h"
 
-static int dma_controller_start(struct dma_controller *c)
-{
-	/* nothing to do */
-	return 0;
-}
-
 static void dma_channel_release(struct dma_channel *channel);
 
-static int dma_controller_stop(struct dma_controller *c)
+static void dma_controller_stop(struct musb_dma_controller *controller)
 {
-	struct musb_dma_controller *controller = container_of(c,
-			struct musb_dma_controller, controller);
 	struct musb *musb = controller->private_data;
 	struct dma_channel *channel;
 	u8 bit;
@@ -67,8 +59,6 @@ static int dma_controller_stop(struct dma_controller *c)
 			}
 		}
 	}
-
-	return 0;
 }
 
 static struct dma_channel *dma_channel_allocate(struct dma_controller *c,
@@ -371,8 +361,7 @@ void dma_controller_destroy(struct dma_controller *c)
 	struct musb_dma_controller *controller = container_of(c,
 			struct musb_dma_controller, controller);
 
-	if (!controller)
-		return;
+	dma_controller_stop(controller);
 
 	if (controller->irq)
 		free_irq(controller->irq, c);
@@ -400,8 +389,6 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba
 	controller->private_data = musb;
 	controller->base = base;
 
-	controller->controller.start = dma_controller_start;
-	controller->controller.stop = dma_controller_stop;
 	controller->controller.channel_alloc = dma_channel_allocate;
 	controller->controller.channel_release = dma_channel_release;
 	controller->controller.channel_program = dma_channel_program;

+ 4 - 4
drivers/usb/musb/omap2430.c

@@ -255,7 +255,7 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 {
 	struct musb *musb = glue_to_musb(glue);
 	struct device *dev = musb->controller;
-	struct musb_hdrc_platform_data *pdata = dev->platform_data;
+	struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = pdata->board_data;
 	struct usb_otg *otg = musb->xceiv->otg;
 
@@ -341,7 +341,7 @@ static int omap2430_musb_init(struct musb *musb)
 	int status = 0;
 	struct device *dev = musb->controller;
 	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = plat->board_data;
 
 	/* We require some kind of external transceiver, hooked
@@ -412,7 +412,7 @@ static void omap2430_musb_enable(struct musb *musb)
 	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 	struct device *dev = musb->controller;
 	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
-	struct musb_hdrc_platform_data *pdata = dev->platform_data;
+	struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
 	struct omap_musb_board_data *data = pdata->board_data;
 
 	switch (glue->status) {
@@ -482,7 +482,7 @@ static u64 omap2430_dmamask = DMA_BIT_MASK(32);
 static int omap2430_probe(struct platform_device *pdev)
 {
 	struct resource			musb_resources[3];
-	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct omap_musb_board_data	*data;
 	struct platform_device		*musb;
 	struct omap2430_glue		*glue;

+ 2 - 2
drivers/usb/musb/tusb6010.c

@@ -25,7 +25,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
 
 #include "musb_core.h"
 
@@ -1157,7 +1157,7 @@ static u64 tusb_dmamask = DMA_BIT_MASK(32);
 static int tusb_probe(struct platform_device *pdev)
 {
 	struct resource musb_resources[3];
-	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct platform_device		*musb;
 	struct tusb6010_glue		*glue;
 

+ 0 - 24
drivers/usb/musb/tusb6010_omap.c

@@ -66,28 +66,6 @@ struct tusb_omap_dma {
 	unsigned			multichannel:1;
 };
 
-static int tusb_omap_dma_start(struct dma_controller *c)
-{
-	struct tusb_omap_dma	*tusb_dma;
-
-	tusb_dma = container_of(c, struct tusb_omap_dma, controller);
-
-	/* dev_dbg(musb->controller, "ep%i ch: %i\n", chdat->epnum, chdat->ch); */
-
-	return 0;
-}
-
-static int tusb_omap_dma_stop(struct dma_controller *c)
-{
-	struct tusb_omap_dma	*tusb_dma;
-
-	tusb_dma = container_of(c, struct tusb_omap_dma, controller);
-
-	/* dev_dbg(musb->controller, "ep%i ch: %i\n", chdat->epnum, chdat->ch); */
-
-	return 0;
-}
-
 /*
  * Allocate dmareq0 to the current channel unless it's already taken
  */
@@ -695,8 +673,6 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba
 	tusb_dma->dmareq = -1;
 	tusb_dma->sync_dev = -1;
 
-	tusb_dma->controller.start = tusb_omap_dma_start;
-	tusb_dma->controller.stop = tusb_omap_dma_stop;
 	tusb_dma->controller.channel_alloc = tusb_omap_dma_allocate;
 	tusb_dma->controller.channel_release = tusb_omap_dma_release;
 	tusb_dma->controller.channel_program = tusb_omap_dma_program;

+ 1 - 1
drivers/usb/musb/ux500.c

@@ -227,7 +227,7 @@ ux500_of_probe(struct platform_device *pdev, struct device_node *np)
 static int ux500_probe(struct platform_device *pdev)
 {
 	struct resource musb_resources[2];
-	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct device_node		*np = pdev->dev.of_node;
 	struct platform_device		*musb;
 	struct ux500_glue		*glue;

+ 9 - 12
drivers/usb/musb/ux500_dma.c

@@ -254,10 +254,8 @@ static int ux500_dma_channel_abort(struct dma_channel *channel)
 	return 0;
 }
 
-static int ux500_dma_controller_stop(struct dma_controller *c)
+static void ux500_dma_controller_stop(struct ux500_dma_controller *controller)
 {
-	struct ux500_dma_controller *controller = container_of(c,
-			struct ux500_dma_controller, controller);
 	struct ux500_dma_channel *ux500_channel;
 	struct dma_channel *channel;
 	u8 ch_num;
@@ -281,18 +279,14 @@ static int ux500_dma_controller_stop(struct dma_controller *c)
 		if (ux500_channel->dma_chan)
 			dma_release_channel(ux500_channel->dma_chan);
 	}
-
-	return 0;
 }
 
-static int ux500_dma_controller_start(struct dma_controller *c)
+static int ux500_dma_controller_start(struct ux500_dma_controller *controller)
 {
-	struct ux500_dma_controller *controller = container_of(c,
-			struct ux500_dma_controller, controller);
 	struct ux500_dma_channel *ux500_channel = NULL;
 	struct musb *musb = controller->private_data;
 	struct device *dev = musb->controller;
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 	struct ux500_musb_board_data *data;
 	struct dma_channel *dma_channel = NULL;
 	char **chan_names;
@@ -347,7 +341,7 @@ static int ux500_dma_controller_start(struct dma_controller *c)
 					dir, ch_num);
 
 				/* Release already allocated channels */
-				ux500_dma_controller_stop(c);
+				ux500_dma_controller_stop(controller);
 
 				return -EBUSY;
 			}
@@ -369,6 +363,7 @@ void dma_controller_destroy(struct dma_controller *c)
 	struct ux500_dma_controller *controller = container_of(c,
 			struct ux500_dma_controller, controller);
 
+	ux500_dma_controller_stop(controller);
 	kfree(controller);
 }
 
@@ -378,6 +373,7 @@ struct dma_controller *dma_controller_create(struct musb *musb,
 	struct ux500_dma_controller *controller;
 	struct platform_device *pdev = to_platform_device(musb->controller);
 	struct resource	*iomem;
+	int ret;
 
 	controller = kzalloc(sizeof(*controller), GFP_KERNEL);
 	if (!controller)
@@ -394,14 +390,15 @@ struct dma_controller *dma_controller_create(struct musb *musb,
 
 	controller->phy_base = (dma_addr_t) iomem->start;
 
-	controller->controller.start = ux500_dma_controller_start;
-	controller->controller.stop = ux500_dma_controller_stop;
 	controller->controller.channel_alloc = ux500_dma_channel_allocate;
 	controller->controller.channel_release = ux500_dma_channel_release;
 	controller->controller.channel_program = ux500_dma_channel_program;
 	controller->controller.channel_abort = ux500_dma_channel_abort;
 	controller->controller.is_compatible = ux500_dma_is_compatible;
 
+	ret = ux500_dma_controller_start(controller);
+	if (ret)
+		goto plat_get_fail;
 	return &controller->controller;
 
 plat_get_fail:

+ 32 - 16
drivers/usb/phy/Kconfig

@@ -1,22 +1,10 @@
 #
 # Physical Layer USB driver configuration
 #
-menuconfig USB_PHY
-	bool "USB Physical Layer drivers"
-	help
-	  Most USB controllers have the physical layer signalling part
-	  (commonly called a PHY) built in.  However, dual-role devices
-	  (a.k.a. USB on-the-go) which support being USB master or slave
-	  with the same connector often use an external PHY.
-
-	  The drivers in this submenu add support for such PHY devices.
-	  They are not needed for standard master-only (or the vast
-	  majority of slave-only) USB interfaces.
+menu "USB Physical Layer drivers"
 
-	  If you're not sure if this applies to you, it probably doesn't;
-	  say N here.
-
-if USB_PHY
+config USB_PHY
+	def_bool n
 
 #
 # USB Transceiver Drivers
@@ -24,6 +12,7 @@ if USB_PHY
 config AB8500_USB
 	tristate "AB8500 USB Transceiver Driver"
 	depends on AB8500_CORE
+	select USB_PHY
 	help
 	  Enable this to support the USB OTG transceiver in AB8500 chip.
 	  This transceiver supports high and full speed devices plus,
@@ -33,12 +22,14 @@ config FSL_USB2_OTG
 	bool "Freescale USB OTG Transceiver Driver"
 	depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME
 	select USB_OTG
+	select USB_PHY
 	help
 	  Enable this to support Freescale USB OTG transceiver.
 
 config ISP1301_OMAP
 	tristate "Philips ISP1301 with OMAP OTG"
 	depends on I2C && ARCH_OMAP_OTG
+	select USB_PHY
 	help
 	  If you say yes here you get support for the Philips ISP1301
 	  USB-On-The-Go transceiver working with the OMAP OTG controller.
@@ -52,12 +43,14 @@ config ISP1301_OMAP
 config MV_U3D_PHY
 	bool "Marvell USB 3.0 PHY controller Driver"
 	depends on CPU_MMP3
+	select USB_PHY
 	help
 	  Enable this to support Marvell USB 3.0 phy controller for Marvell
 	  SoC.
 
 config NOP_USB_XCEIV
 	tristate "NOP USB Transceiver Driver"
+	select USB_PHY
 	help
 	  This driver is to be used by all the usb transceiver which are either
 	  built-in with usb ip or which are autonomous and doesn't require any
@@ -77,6 +70,7 @@ config OMAP_USB2
 	tristate "OMAP USB2 PHY Driver"
 	depends on ARCH_OMAP2PLUS
 	select OMAP_CONTROL_USB
+	select USB_PHY
 	help
 	  Enable this to support the transceiver that is part of SOC. This
 	  driver takes care of all the PHY functionality apart from comparator.
@@ -87,12 +81,25 @@ config OMAP_USB3
 	tristate "OMAP USB3 PHY Driver"
 	depends on ARCH_OMAP2PLUS || COMPILE_TEST
 	select OMAP_CONTROL_USB
+	select USB_PHY
 	help
 	  Enable this to support the USB3 PHY that is part of SOC. This
 	  driver takes care of all the PHY functionality apart from comparator.
 	  This driver interacts with the "OMAP Control USB Driver" to power
 	  on/off the PHY.
 
+config AM335X_CONTROL_USB
+	tristate
+
+config AM335X_PHY_USB
+	tristate "AM335x USB PHY Driver"
+	select USB_PHY
+	select AM335X_CONTROL_USB
+	select NOP_USB_XCEIV
+	help
+	  This driver provides PHY support for that phy which part for the
+	  AM335x SoC.
+
 config SAMSUNG_USBPHY
 	tristate
 	help
@@ -103,6 +110,7 @@ config SAMSUNG_USBPHY
 config SAMSUNG_USB2PHY
 	tristate "Samsung USB 2.0 PHY controller Driver"
 	select SAMSUNG_USBPHY
+	select USB_PHY
 	help
 	  Enable this to support Samsung USB 2.0 (High Speed) PHY controller
 	  driver for Samsung SoCs.
@@ -110,6 +118,7 @@ config SAMSUNG_USB2PHY
 config SAMSUNG_USB3PHY
 	tristate "Samsung USB 3.0 PHY controller Driver"
 	select SAMSUNG_USBPHY
+	select USB_PHY
 	help
 	  Enable this to support Samsung USB 3.0 (Super Speed) phy controller
 	  for samsung SoCs.
@@ -117,6 +126,7 @@ config SAMSUNG_USB3PHY
 config TWL4030_USB
 	tristate "TWL4030 USB Transceiver Driver"
 	depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
+	select USB_PHY
 	help
 	  Enable this to support the USB OTG transceiver on TWL4030
 	  family chips (including the TWL5030 and TPS659x0 devices).
@@ -137,6 +147,7 @@ config TWL6030_USB
 config USB_GPIO_VBUS
 	tristate "GPIO based peripheral-only VBUS sensing 'transceiver'"
 	depends on GPIOLIB
+	select USB_PHY
 	help
 	  Provides simple GPIO VBUS sensing for controllers with an
 	  internal transceiver via the usb_phy interface, and
@@ -147,6 +158,7 @@ config USB_ISP1301
 	tristate "NXP ISP1301 USB transceiver support"
 	depends on USB || USB_GADGET
 	depends on I2C
+	select USB_PHY
 	help
 	  Say Y here to add support for the NXP ISP1301 USB transceiver driver.
 	  This chip is typically used as USB transceiver for USB host, gadget
@@ -158,6 +170,7 @@ config USB_ISP1301
 config USB_MSM_OTG
 	tristate "OTG support for Qualcomm on-chip USB controller"
 	depends on (USB || USB_GADGET) && ARCH_MSM
+	select USB_PHY
 	help
 	  Enable this to support the USB OTG transceiver on MSM chips. It
 	  handles PHY initialization, clock management, and workarounds
@@ -171,6 +184,7 @@ config USB_MV_OTG
 	tristate "Marvell USB OTG support"
 	depends on USB_EHCI_MV && USB_MV_UDC && PM_RUNTIME
 	select USB_OTG
+	select USB_PHY
 	help
 	  Say Y here if you want to build Marvell USB OTG transciever
 	  driver in kernel (including PXA and MMP series). This driver
@@ -182,6 +196,7 @@ config USB_MXS_PHY
 	tristate "Freescale MXS USB PHY support"
 	depends on ARCH_MXC || ARCH_MXS
 	select STMP_DEVICE
+	select USB_PHY
 	help
 	  Enable this to support the Freescale MXS USB PHY.
 
@@ -190,6 +205,7 @@ config USB_MXS_PHY
 config USB_RCAR_PHY
 	tristate "Renesas R-Car USB PHY support"
 	depends on USB || USB_GADGET
+	select USB_PHY
 	help
 	  Say Y here to add support for the Renesas R-Car USB common PHY driver.
 	  This chip is typically used as USB PHY for USB host, gadget.
@@ -212,4 +228,4 @@ config USB_ULPI_VIEWPORT
 	  Provides read/write operations to the ULPI phy register set for
 	  controllers with a viewport register (e.g. Chipidea/ARC controllers).
 
-endif # USB_PHY
+endmenu

+ 3 - 1
drivers/usb/phy/Makefile

@@ -11,8 +11,10 @@ phy-fsl-usb2-objs			:= phy-fsl-usb.o phy-fsm-usb.o
 obj-$(CONFIG_FSL_USB2_OTG)		+= phy-fsl-usb2.o
 obj-$(CONFIG_ISP1301_OMAP)		+= phy-isp1301-omap.o
 obj-$(CONFIG_MV_U3D_PHY)		+= phy-mv-u3d-usb.o
-obj-$(CONFIG_NOP_USB_XCEIV)		+= phy-nop.o
+obj-$(CONFIG_NOP_USB_XCEIV)		+= phy-generic.o
 obj-$(CONFIG_OMAP_CONTROL_USB)		+= phy-omap-control.o
+obj-$(CONFIG_AM335X_CONTROL_USB)	+= phy-am335x-control.o
+obj-$(CONFIG_AM335X_PHY_USB)		+= phy-am335x.o
 obj-$(CONFIG_OMAP_USB2)			+= phy-omap-usb2.o
 obj-$(CONFIG_OMAP_USB3)			+= phy-omap-usb3.o
 obj-$(CONFIG_SAMSUNG_USBPHY)		+= phy-samsung-usb.o

+ 21 - 0
drivers/usb/phy/am35x-phy-control.h

@@ -0,0 +1,21 @@
+#ifndef _AM335x_PHY_CONTROL_H_
+#define _AM335x_PHY_CONTROL_H_
+
+struct phy_control {
+	void (*phy_power)(struct phy_control *phy_ctrl, u32 id, bool on);
+	void (*phy_wkup)(struct phy_control *phy_ctrl, u32 id, bool on);
+};
+
+static inline void phy_ctrl_power(struct phy_control *phy_ctrl, u32 id, bool on)
+{
+	phy_ctrl->phy_power(phy_ctrl, id, on);
+}
+
+static inline void phy_ctrl_wkup(struct phy_control *phy_ctrl, u32 id, bool on)
+{
+	phy_ctrl->phy_wkup(phy_ctrl, id, on);
+}
+
+struct phy_control *am335x_get_phy_control(struct device *dev);
+
+#endif

+ 137 - 0
drivers/usb/phy/phy-am335x-control.c

@@ -0,0 +1,137 @@
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/io.h>
+
+struct phy_control {
+	void (*phy_power)(struct phy_control *phy_ctrl, u32 id, bool on);
+	void (*phy_wkup)(struct phy_control *phy_ctrl, u32 id, bool on);
+};
+
+struct am335x_control_usb {
+	struct device *dev;
+	void __iomem *phy_reg;
+	void __iomem *wkup;
+	spinlock_t lock;
+	struct phy_control phy_ctrl;
+};
+
+#define AM335X_USB0_CTRL		0x0
+#define AM335X_USB1_CTRL		0x8
+#define AM335x_USB_WKUP			0x0
+
+#define USBPHY_CM_PWRDN		(1 << 0)
+#define USBPHY_OTG_PWRDN	(1 << 1)
+#define USBPHY_OTGVDET_EN	(1 << 19)
+#define USBPHY_OTGSESSEND_EN	(1 << 20)
+
+static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on)
+{
+	struct am335x_control_usb *usb_ctrl;
+	u32 val;
+	u32 reg;
+
+	usb_ctrl = container_of(phy_ctrl, struct am335x_control_usb, phy_ctrl);
+
+	switch (id) {
+	case 0:
+		reg = AM335X_USB0_CTRL;
+		break;
+	case 1:
+		reg = AM335X_USB1_CTRL;
+		break;
+	default:
+		__WARN();
+		 return;
+	}
+
+	val = readl(usb_ctrl->phy_reg + reg);
+	if (on) {
+		val &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
+		val |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN;
+	} else {
+		val |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
+	}
+
+	writel(val, usb_ctrl->phy_reg + reg);
+}
+
+static const struct phy_control ctrl_am335x = {
+	.phy_power = am335x_phy_power,
+};
+
+static const struct of_device_id omap_control_usb_id_table[] = {
+	{ .compatible = "ti,am335x-usb-ctrl-module", .data = &ctrl_am335x },
+	{}
+};
+MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
+
+static struct platform_driver am335x_control_driver;
+static int match(struct device *dev, void *data)
+{
+	struct device_node *node = (struct device_node *)data;
+	return dev->of_node == node &&
+		dev->driver == &am335x_control_driver.driver;
+}
+
+struct phy_control *am335x_get_phy_control(struct device *dev)
+{
+	struct device_node *node;
+	struct am335x_control_usb *ctrl_usb;
+
+	node = of_parse_phandle(dev->of_node, "ti,ctrl_mod", 0);
+	if (!node)
+		return NULL;
+
+	dev = bus_find_device(&platform_bus_type, NULL, node, match);
+	ctrl_usb = dev_get_drvdata(dev);
+	if (!ctrl_usb)
+		return NULL;
+	return &ctrl_usb->phy_ctrl;
+}
+EXPORT_SYMBOL_GPL(am335x_get_phy_control);
+
+static int am335x_control_usb_probe(struct platform_device *pdev)
+{
+	struct resource	*res;
+	struct am335x_control_usb *ctrl_usb;
+	const struct of_device_id *of_id;
+	const struct phy_control *phy_ctrl;
+
+	of_id = of_match_node(omap_control_usb_id_table, pdev->dev.of_node);
+	if (!of_id)
+		return -EINVAL;
+
+	phy_ctrl = of_id->data;
+
+	ctrl_usb = devm_kzalloc(&pdev->dev, sizeof(*ctrl_usb), GFP_KERNEL);
+	if (!ctrl_usb) {
+		dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
+		return -ENOMEM;
+	}
+
+	ctrl_usb->dev = &pdev->dev;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
+	ctrl_usb->phy_reg = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ctrl_usb->phy_reg))
+		return PTR_ERR(ctrl_usb->phy_reg);
+	spin_lock_init(&ctrl_usb->lock);
+	ctrl_usb->phy_ctrl = *phy_ctrl;
+
+	dev_set_drvdata(ctrl_usb->dev, ctrl_usb);
+	return 0;
+}
+
+static struct platform_driver am335x_control_driver = {
+	.probe		= am335x_control_usb_probe,
+	.driver		= {
+		.name	= "am335x-control-usb",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(omap_control_usb_id_table),
+	},
+};
+
+module_platform_driver(am335x_control_driver);
+MODULE_LICENSE("GPL v2");

+ 99 - 0
drivers/usb/phy/phy-am335x.c

@@ -0,0 +1,99 @@
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "am35x-phy-control.h"
+#include "phy-generic.h"
+
+struct am335x_phy {
+	struct usb_phy_gen_xceiv usb_phy_gen;
+	struct phy_control *phy_ctrl;
+	int id;
+};
+
+static int am335x_init(struct usb_phy *phy)
+{
+	struct am335x_phy *am_phy = dev_get_drvdata(phy->dev);
+
+	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, true);
+	return 0;
+}
+
+static void am335x_shutdown(struct usb_phy *phy)
+{
+	struct am335x_phy *am_phy = dev_get_drvdata(phy->dev);
+
+	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, false);
+}
+
+static int am335x_phy_probe(struct platform_device *pdev)
+{
+	struct am335x_phy *am_phy;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	am_phy = devm_kzalloc(dev, sizeof(*am_phy), GFP_KERNEL);
+	if (!am_phy)
+		return -ENOMEM;
+
+	am_phy->phy_ctrl = am335x_get_phy_control(dev);
+	if (!am_phy->phy_ctrl)
+		return -EPROBE_DEFER;
+	am_phy->id = of_alias_get_id(pdev->dev.of_node, "phy");
+	if (am_phy->id < 0) {
+		dev_err(&pdev->dev, "Missing PHY id: %d\n", am_phy->id);
+		return am_phy->id;
+	}
+
+	ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen,
+			USB_PHY_TYPE_USB2, 0, false, false);
+	if (ret)
+		return ret;
+
+	ret = usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
+	if (ret)
+		goto err_add;
+	am_phy->usb_phy_gen.phy.init = am335x_init;
+	am_phy->usb_phy_gen.phy.shutdown = am335x_shutdown;
+
+	platform_set_drvdata(pdev, am_phy);
+	return 0;
+
+err_add:
+	usb_phy_gen_cleanup_phy(&am_phy->usb_phy_gen);
+	return ret;
+}
+
+static int am335x_phy_remove(struct platform_device *pdev)
+{
+	struct am335x_phy *am_phy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&am_phy->usb_phy_gen.phy);
+	return 0;
+}
+
+static const struct of_device_id am335x_phy_ids[] = {
+	{ .compatible = "ti,am335x-usb-phy" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, am335x_phy_ids);
+
+static struct platform_driver am335x_phy_driver = {
+	.probe          = am335x_phy_probe,
+	.remove         = am335x_phy_remove,
+	.driver         = {
+		.name   = "am335x-phy-driver",
+		.owner  = THIS_MODULE,
+		.of_match_table = of_match_ptr(am335x_phy_ids),
+	},
+};
+
+module_platform_driver(am335x_phy_driver);
+MODULE_LICENSE("GPL v2");

+ 3 - 3
drivers/usb/phy/phy-fsl-usb.c

@@ -834,7 +834,7 @@ int usb_otg_start(struct platform_device *pdev)
 	int status;
 	struct resource *res;
 	u32 temp;
-	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 	p_otg = container_of(otg_trans, struct fsl_otg, phy);
 	fsm = &p_otg->fsm;
@@ -1105,7 +1105,7 @@ static int fsl_otg_probe(struct platform_device *pdev)
 {
 	int ret;
 
-	if (!pdev->dev.platform_data)
+	if (!dev_get_platdata(&pdev->dev))
 		return -ENODEV;
 
 	/* configure the OTG */
@@ -1137,7 +1137,7 @@ static int fsl_otg_probe(struct platform_device *pdev)
 
 static int fsl_otg_remove(struct platform_device *pdev)
 {
-	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 	usb_remove_phy(&fsl_otg_dev->phy);
 	free_irq(fsl_otg_dev->irq, fsl_otg_dev);

+ 92 - 75
drivers/usb/phy/phy-nop.c → drivers/usb/phy/phy-generic.c

@@ -30,19 +30,13 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/usb/otg.h>
-#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/regulator/consumer.h>
 #include <linux/of.h>
 
-struct nop_usb_xceiv {
-	struct usb_phy phy;
-	struct device *dev;
-	struct clk *clk;
-	struct regulator *vcc;
-	struct regulator *reset;
-};
+#include "phy-generic.h"
 
 static struct platform_device *pd;
 
@@ -50,9 +44,9 @@ void usb_nop_xceiv_register(void)
 {
 	if (pd)
 		return;
-	pd = platform_device_register_simple("nop_usb_xceiv", -1, NULL, 0);
+	pd = platform_device_register_simple("usb_phy_gen_xceiv", -1, NULL, 0);
 	if (!pd) {
-		printk(KERN_ERR "Unable to register usb nop transceiver\n");
+		pr_err("Unable to register generic usb transceiver\n");
 		return;
 	}
 }
@@ -70,9 +64,9 @@ static int nop_set_suspend(struct usb_phy *x, int suspend)
 	return 0;
 }
 
-static int nop_init(struct usb_phy *phy)
+int usb_gen_phy_init(struct usb_phy *phy)
 {
-	struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev);
+	struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev);
 
 	if (!IS_ERR(nop->vcc)) {
 		if (regulator_enable(nop->vcc))
@@ -90,10 +84,11 @@ static int nop_init(struct usb_phy *phy)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(usb_gen_phy_init);
 
-static void nop_shutdown(struct usb_phy *phy)
+void usb_gen_phy_shutdown(struct usb_phy *phy)
 {
-	struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev);
+	struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev);
 
 	if (!IS_ERR(nop->reset)) {
 		/* Assert RESET */
@@ -109,6 +104,7 @@ static void nop_shutdown(struct usb_phy *phy)
 			dev_err(phy->dev, "Failed to disable power\n");
 	}
 }
+EXPORT_SYMBOL_GPL(usb_gen_phy_shutdown);
 
 static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
 {
@@ -139,52 +135,27 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
 	return 0;
 }
 
-static int nop_usb_xceiv_probe(struct platform_device *pdev)
+int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
+		enum usb_phy_type type, u32 clk_rate, bool needs_vcc,
+		bool needs_reset)
 {
-	struct device *dev = &pdev->dev;
-	struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data;
-	struct nop_usb_xceiv	*nop;
-	enum usb_phy_type	type = USB_PHY_TYPE_USB2;
 	int err;
-	u32 clk_rate = 0;
-	bool needs_vcc = false;
-	bool needs_reset = false;
-
-	nop = devm_kzalloc(&pdev->dev, sizeof(*nop), GFP_KERNEL);
-	if (!nop)
-		return -ENOMEM;
 
-	nop->phy.otg = devm_kzalloc(&pdev->dev, sizeof(*nop->phy.otg),
-							GFP_KERNEL);
+	nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg),
+			GFP_KERNEL);
 	if (!nop->phy.otg)
 		return -ENOMEM;
 
-	if (dev->of_node) {
-		struct device_node *node = dev->of_node;
-
-		if (of_property_read_u32(node, "clock-frequency", &clk_rate))
-			clk_rate = 0;
-
-		needs_vcc = of_property_read_bool(node, "vcc-supply");
-		needs_reset = of_property_read_bool(node, "reset-supply");
-
-	} else if (pdata) {
-		type = pdata->type;
-		clk_rate = pdata->clk_rate;
-		needs_vcc = pdata->needs_vcc;
-		needs_reset = pdata->needs_reset;
-	}
-
-	nop->clk = devm_clk_get(&pdev->dev, "main_clk");
+	nop->clk = devm_clk_get(dev, "main_clk");
 	if (IS_ERR(nop->clk)) {
-		dev_dbg(&pdev->dev, "Can't get phy clock: %ld\n",
+		dev_dbg(dev, "Can't get phy clock: %ld\n",
 					PTR_ERR(nop->clk));
 	}
 
 	if (!IS_ERR(nop->clk) && clk_rate) {
 		err = clk_set_rate(nop->clk, clk_rate);
 		if (err) {
-			dev_err(&pdev->dev, "Error setting clock rate\n");
+			dev_err(dev, "Error setting clock rate\n");
 			return err;
 		}
 	}
@@ -192,33 +163,31 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev)
 	if (!IS_ERR(nop->clk)) {
 		err = clk_prepare(nop->clk);
 		if (err) {
-			dev_err(&pdev->dev, "Error preparing clock\n");
+			dev_err(dev, "Error preparing clock\n");
 			return err;
 		}
 	}
 
-	nop->vcc = devm_regulator_get(&pdev->dev, "vcc");
+	nop->vcc = devm_regulator_get(dev, "vcc");
 	if (IS_ERR(nop->vcc)) {
-		dev_dbg(&pdev->dev, "Error getting vcc regulator: %ld\n",
+		dev_dbg(dev, "Error getting vcc regulator: %ld\n",
 					PTR_ERR(nop->vcc));
 		if (needs_vcc)
 			return -EPROBE_DEFER;
 	}
 
-	nop->reset = devm_regulator_get(&pdev->dev, "reset");
+	nop->reset = devm_regulator_get(dev, "reset");
 	if (IS_ERR(nop->reset)) {
-		dev_dbg(&pdev->dev, "Error getting reset regulator: %ld\n",
+		dev_dbg(dev, "Error getting reset regulator: %ld\n",
 					PTR_ERR(nop->reset));
 		if (needs_reset)
 			return -EPROBE_DEFER;
 	}
 
-	nop->dev		= &pdev->dev;
+	nop->dev		= dev;
 	nop->phy.dev		= nop->dev;
 	nop->phy.label		= "nop-xceiv";
 	nop->phy.set_suspend	= nop_set_suspend;
-	nop->phy.init		= nop_init;
-	nop->phy.shutdown	= nop_shutdown;
 	nop->phy.state		= OTG_STATE_UNDEFINED;
 	nop->phy.type		= type;
 
@@ -226,6 +195,59 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev)
 	nop->phy.otg->set_host		= nop_set_host;
 	nop->phy.otg->set_peripheral	= nop_set_peripheral;
 
+	ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
+
+void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop)
+{
+	if (!IS_ERR(nop->clk))
+		clk_unprepare(nop->clk);
+}
+EXPORT_SYMBOL_GPL(usb_phy_gen_cleanup_phy);
+
+static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct usb_phy_gen_xceiv_platform_data *pdata =
+			dev_get_platdata(&pdev->dev);
+	struct usb_phy_gen_xceiv	*nop;
+	enum usb_phy_type	type = USB_PHY_TYPE_USB2;
+	int err;
+	u32 clk_rate = 0;
+	bool needs_vcc = false;
+	bool needs_reset = false;
+
+	if (dev->of_node) {
+		struct device_node *node = dev->of_node;
+
+		if (of_property_read_u32(node, "clock-frequency", &clk_rate))
+			clk_rate = 0;
+
+		needs_vcc = of_property_read_bool(node, "vcc-supply");
+		needs_reset = of_property_read_bool(node, "reset-supply");
+
+	} else if (pdata) {
+		type = pdata->type;
+		clk_rate = pdata->clk_rate;
+		needs_vcc = pdata->needs_vcc;
+		needs_reset = pdata->needs_reset;
+	}
+
+	nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL);
+	if (!nop)
+		return -ENOMEM;
+
+
+	err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc,
+			needs_reset);
+	if (err)
+		return err;
+
+	nop->phy.init		= usb_gen_phy_init;
+	nop->phy.shutdown	= usb_gen_phy_shutdown;
+
 	err = usb_add_phy_dev(&nop->phy);
 	if (err) {
 		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
@@ -235,23 +257,18 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, nop);
 
-	ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
-
 	return 0;
 
 err_add:
-	if (!IS_ERR(nop->clk))
-		clk_unprepare(nop->clk);
+	usb_phy_gen_cleanup_phy(nop);
 	return err;
 }
 
-static int nop_usb_xceiv_remove(struct platform_device *pdev)
+static int usb_phy_gen_xceiv_remove(struct platform_device *pdev)
 {
-	struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
-
-	if (!IS_ERR(nop->clk))
-		clk_unprepare(nop->clk);
+	struct usb_phy_gen_xceiv *nop = platform_get_drvdata(pdev);
 
+	usb_phy_gen_cleanup_phy(nop);
 	usb_remove_phy(&nop->phy);
 
 	return 0;
@@ -264,29 +281,29 @@ static const struct of_device_id nop_xceiv_dt_ids[] = {
 
 MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids);
 
-static struct platform_driver nop_usb_xceiv_driver = {
-	.probe		= nop_usb_xceiv_probe,
-	.remove		= nop_usb_xceiv_remove,
+static struct platform_driver usb_phy_gen_xceiv_driver = {
+	.probe		= usb_phy_gen_xceiv_probe,
+	.remove		= usb_phy_gen_xceiv_remove,
 	.driver		= {
-		.name	= "nop_usb_xceiv",
+		.name	= "usb_phy_gen_xceiv",
 		.owner	= THIS_MODULE,
 		.of_match_table = nop_xceiv_dt_ids,
 	},
 };
 
-static int __init nop_usb_xceiv_init(void)
+static int __init usb_phy_gen_xceiv_init(void)
 {
-	return platform_driver_register(&nop_usb_xceiv_driver);
+	return platform_driver_register(&usb_phy_gen_xceiv_driver);
 }
-subsys_initcall(nop_usb_xceiv_init);
+subsys_initcall(usb_phy_gen_xceiv_init);
 
-static void __exit nop_usb_xceiv_exit(void)
+static void __exit usb_phy_gen_xceiv_exit(void)
 {
-	platform_driver_unregister(&nop_usb_xceiv_driver);
+	platform_driver_unregister(&usb_phy_gen_xceiv_driver);
 }
-module_exit(nop_usb_xceiv_exit);
+module_exit(usb_phy_gen_xceiv_exit);
 
-MODULE_ALIAS("platform:nop_usb_xceiv");
+MODULE_ALIAS("platform:usb_phy_gen_xceiv");
 MODULE_AUTHOR("Texas Instruments Inc");
 MODULE_DESCRIPTION("NOP USB Transceiver driver");
 MODULE_LICENSE("GPL");

+ 20 - 0
drivers/usb/phy/phy-generic.h

@@ -0,0 +1,20 @@
+#ifndef _PHY_GENERIC_H_
+#define _PHY_GENERIC_H_
+
+struct usb_phy_gen_xceiv {
+	struct usb_phy phy;
+	struct device *dev;
+	struct clk *clk;
+	struct regulator *vcc;
+	struct regulator *reset;
+};
+
+int usb_gen_phy_init(struct usb_phy *phy);
+void usb_gen_phy_shutdown(struct usb_phy *phy);
+
+int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
+		enum usb_phy_type type, u32 clk_rate, bool needs_vcc,
+		bool needs_reset);
+void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop);
+
+#endif

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