usb: patches for v3.10 merge window
Here is the big Gadget & PHY pull request. Many of us have been really busy lately getting multiple drivers to a better position. Since this pull request is so large, I will divide it in sections so it's easier to grasp what's included. - cleanups: . UDC drivers no longer touch gadget->dev, that's now udc-core responsibility . Many more UDC drivers converted to usb_gadget_map/unmap_request() . UDC drivers no longer initialize DMA-related fields from gadget's device structure . UDC drivers don't touch gadget.dev.driver directly . UDC drivers don't assign gadget.dev.release directly . Removal of some unused DMA_ADDR_INVALID . Introduction of CONFIG_USB_PHY . All phy drivers have been moved to drivers/usb/phy and renamed to a common naming scheme . Fix PHY layer so it never returns a NULL pointer, also fix all callers to avoid using IS_ERR_OR_NULL() . Sparse fixes all over the place . drivers/usb/otg/ has been deleted . Marvel drivers (mv_udc, ehci-mv, mv_otg and mv_u3d) improved clock usage - new features: . UDC core now provides a generic way for tracking and reporting UDC's state (not attached, resuming, suspended, addressed, default, etc) . twl4030-usb learned that it shouldn't be enabled during init . Full DT support for DWC3 has been implemented . ab8500-usb learned about pinctrl framework . nop PHY learned about DeviceTree and regulators . DWC3 learned about suspend/resume . DWC3 can now be compiled in host-only and gadget-only (as well as DRD) configurations . UVC now enables streaming endpoint based on negotiated speed . isp1301 now implements the PHY API properly . configfs-based interface for gadget drivers which will lead to the removal of all code which just combines functions together to build functional gadget drivers. . f_serial and f_obex were converted to new configfs interface while maintaining old interface around. - non-critical fixes: . UVC gadget driver got fixes for Endpoint usage and stream calculation . ab8500-usb fixed unbalanced clock and regulator API usage . twl4030-usb got a fix for when OMAP3 is booted with cable connected . fusb300_udc got a fix for DMA usage . UVC got fixes for two assertions of the USB Video Class Compliance specification revision 1.1 . build warning issues caused by recent addition of __must_check to regulator API These are all changes which deserve a mention, all other changes are related to these one or minor spelling fixes and other similar tasks. Signed-of-by: Felipe Balbi <balbi@ti.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJRXG8GAAoJEIaOsuA1yqREJzYQAKMLW3J/TKTWS1DDuf7qMtMz Ug6qChKZXgT1/QrNjsq2tx4jYIkNdSMtRKiUx0BnIptlUx6gM22gcsN8mXX/UJjC FYAiWl+tYe85e9uayqqt+qVCZjTZCc7St4wQalugDHefvA7yCbiZpSaJRGlJMK+x mePJ7MfrulDsYBXr0u+m2LOJ0qxMDi40k3/UN3aUu5yzrmBiRpVq1mySruvLwGFp Pr6vBnprEc6bW5sRdUR4SICKLvLk5sHwHpvpkzDLYBIb/jXQwbfQri/HKeh4VMk8 trbsvHZyB7H8uuFsCHiBc6VtjcbZ4mxPUK+1PCq8hG077avdkm3ox0BERk9aRTeC jg4mdpyWjgovwi882woPEQXNZoaAXpVDyI8tBRx92a+rGJjXSHhLQI+4Ffi4ZvzV d+q1ZzrHxuzwa/BwcPETY76umXQqXWXg+ap1bHDY0RZFoPLdXMpl583NXGSn3gOD dUlD0UlgYwb75333tRIPNQn3qOx0HVd6MlYPMNzl9t9c9qqfX78AYRny6ZucupRg t9VZ6FO3D2yre9W7u3U3q2c9H7uSAKr/8xaNfvdsIWPncgvvYVIyE8MnR7AiHoPv ZYESs/Gs6w9vUsHa9K4J16Ape7D3AMcGpXUoPUxTBHrwBexzt4j27VWtcL4ns/9r 0kcltUJ4Zq+PIjc7xgxe =aF4r -----END PGP SIGNATURE----- Merge tag 'usb-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next Felipe writes: usb: patches for v3.10 merge window Here is the big Gadget & PHY pull request. Many of us have been really busy lately getting multiple drivers to a better position. Since this pull request is so large, I will divide it in sections so it's easier to grasp what's included. - cleanups: . UDC drivers no longer touch gadget->dev, that's now udc-core responsibility . Many more UDC drivers converted to usb_gadget_map/unmap_request() . UDC drivers no longer initialize DMA-related fields from gadget's device structure . UDC drivers don't touch gadget.dev.driver directly . UDC drivers don't assign gadget.dev.release directly . Removal of some unused DMA_ADDR_INVALID . Introduction of CONFIG_USB_PHY . All phy drivers have been moved to drivers/usb/phy and renamed to a common naming scheme . Fix PHY layer so it never returns a NULL pointer, also fix all callers to avoid using IS_ERR_OR_NULL() . Sparse fixes all over the place . drivers/usb/otg/ has been deleted . Marvel drivers (mv_udc, ehci-mv, mv_otg and mv_u3d) improved clock usage - new features: . UDC core now provides a generic way for tracking and reporting UDC's state (not attached, resuming, suspended, addressed, default, etc) . twl4030-usb learned that it shouldn't be enabled during init . Full DT support for DWC3 has been implemented . ab8500-usb learned about pinctrl framework . nop PHY learned about DeviceTree and regulators . DWC3 learned about suspend/resume . DWC3 can now be compiled in host-only and gadget-only (as well as DRD) configurations . UVC now enables streaming endpoint based on negotiated speed . isp1301 now implements the PHY API properly . configfs-based interface for gadget drivers which will lead to the removal of all code which just combines functions together to build functional gadget drivers. . f_serial and f_obex were converted to new configfs interface while maintaining old interface around. - non-critical fixes: . UVC gadget driver got fixes for Endpoint usage and stream calculation . ab8500-usb fixed unbalanced clock and regulator API usage . twl4030-usb got a fix for when OMAP3 is booted with cable connected . fusb300_udc got a fix for DMA usage . UVC got fixes for two assertions of the USB Video Class Compliance specification revision 1.1 . build warning issues caused by recent addition of __must_check to regulator API These are all changes which deserve a mention, all other changes are related to these one or minor spelling fixes and other similar tasks. Signed-of-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
		
				commit
				
					
						64dc9e2e73
					
				
			
		
					 159 changed files with 6868 additions and 4499 deletions
				
			
		| 
						 | 
					@ -8,10 +8,10 @@ OMAP MUSB GLUE
 | 
				
			||||||
   and disconnect.
 | 
					   and disconnect.
 | 
				
			||||||
 - multipoint : Should be "1" indicating the musb controller supports
 | 
					 - multipoint : Should be "1" indicating the musb controller supports
 | 
				
			||||||
   multipoint. This is a MUSB configuration-specific setting.
 | 
					   multipoint. This is a MUSB configuration-specific setting.
 | 
				
			||||||
 - num_eps : Specifies the number of endpoints. This is also a
 | 
					 - num-eps : Specifies the number of endpoints. This is also a
 | 
				
			||||||
   MUSB configuration-specific setting. Should be set to "16"
 | 
					   MUSB configuration-specific setting. Should be set to "16"
 | 
				
			||||||
 - ram_bits : Specifies the ram address size. Should be set to "12"
 | 
					 - ram-bits : Specifies the ram address size. Should be set to "12"
 | 
				
			||||||
 - interface_type : This is a board specific setting to describe the type of
 | 
					 - interface-type : This is a board specific setting to describe the type of
 | 
				
			||||||
   interface between the controller and the phy. It should be "0" or "1"
 | 
					   interface between the controller and the phy. It should be "0" or "1"
 | 
				
			||||||
   specifying ULPI and UTMI respectively.
 | 
					   specifying ULPI and UTMI respectively.
 | 
				
			||||||
 - mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
 | 
					 - mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
 | 
				
			||||||
| 
						 | 
					@ -29,18 +29,46 @@ usb_otg_hs: usb_otg_hs@4a0ab000 {
 | 
				
			||||||
	ti,hwmods = "usb_otg_hs";
 | 
						ti,hwmods = "usb_otg_hs";
 | 
				
			||||||
	ti,has-mailbox;
 | 
						ti,has-mailbox;
 | 
				
			||||||
	multipoint = <1>;
 | 
						multipoint = <1>;
 | 
				
			||||||
	num_eps = <16>;
 | 
						num-eps = <16>;
 | 
				
			||||||
	ram_bits = <12>;
 | 
						ram-bits = <12>;
 | 
				
			||||||
	ctrl-module = <&omap_control_usb>;
 | 
						ctrl-module = <&omap_control_usb>;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Board specific device node entry
 | 
					Board specific device node entry
 | 
				
			||||||
&usb_otg_hs {
 | 
					&usb_otg_hs {
 | 
				
			||||||
	interface_type = <1>;
 | 
						interface-type = <1>;
 | 
				
			||||||
	mode = <3>;
 | 
						mode = <3>;
 | 
				
			||||||
	power = <50>;
 | 
						power = <50>;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OMAP DWC3 GLUE
 | 
				
			||||||
 | 
					 - compatible : Should be "ti,dwc3"
 | 
				
			||||||
 | 
					 - ti,hwmods : Should be "usb_otg_ss"
 | 
				
			||||||
 | 
					 - reg : Address and length of the register set for the device.
 | 
				
			||||||
 | 
					 - interrupts : The irq number of this device that is used to interrupt the
 | 
				
			||||||
 | 
					   MPU
 | 
				
			||||||
 | 
					 - #address-cells, #size-cells : Must be present if the device has sub-nodes
 | 
				
			||||||
 | 
					 - utmi-mode : controls the source of UTMI/PIPE status for VBUS and OTG ID.
 | 
				
			||||||
 | 
					   It should be set to "1" for HW mode and "2" for SW mode.
 | 
				
			||||||
 | 
					 - ranges: the child address space are mapped 1:1 onto the parent address space
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sub-nodes:
 | 
				
			||||||
 | 
					The dwc3 core should be added as subnode to omap dwc3 glue.
 | 
				
			||||||
 | 
					- dwc3 :
 | 
				
			||||||
 | 
					   The binding details of dwc3 can be found in:
 | 
				
			||||||
 | 
					   Documentation/devicetree/bindings/usb/dwc3.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					omap_dwc3 {
 | 
				
			||||||
 | 
						compatible = "ti,dwc3";
 | 
				
			||||||
 | 
						ti,hwmods = "usb_otg_ss";
 | 
				
			||||||
 | 
						reg = <0x4a020000 0x1ff>;
 | 
				
			||||||
 | 
						interrupts = <0 93 4>;
 | 
				
			||||||
 | 
						#address-cells = <1>;
 | 
				
			||||||
 | 
						#size-cells = <1>;
 | 
				
			||||||
 | 
						utmi-mode = <2>;
 | 
				
			||||||
 | 
						ranges;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OMAP CONTROL USB
 | 
					OMAP CONTROL USB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Required properties:
 | 
					Required properties:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,20 +1,25 @@
 | 
				
			||||||
* Samsung's usb phy transceiver
 | 
					SAMSUNG USB-PHY controllers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The Samsung's phy transceiver is used for controlling usb phy for
 | 
					** Samsung's usb 2.0 phy transceiver
 | 
				
			||||||
s3c-hsotg as well as ehci-s5p and ohci-exynos usb controllers
 | 
					
 | 
				
			||||||
across Samsung SOCs.
 | 
					The Samsung's usb 2.0 phy transceiver is used for controlling
 | 
				
			||||||
 | 
					usb 2.0 phy for s3c-hsotg as well as ehci-s5p and ohci-exynos
 | 
				
			||||||
 | 
					usb controllers across Samsung SOCs.
 | 
				
			||||||
TODO: Adding the PHY binding with controller(s) according to the under
 | 
					TODO: Adding the PHY binding with controller(s) according to the under
 | 
				
			||||||
developement generic PHY driver.
 | 
					developement generic PHY driver.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Required properties:
 | 
					Required properties:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Exynos4210:
 | 
					Exynos4210:
 | 
				
			||||||
- compatible : should be "samsung,exynos4210-usbphy"
 | 
					- compatible : should be "samsung,exynos4210-usb2phy"
 | 
				
			||||||
- reg : base physical address of the phy registers and length of memory mapped
 | 
					- reg : base physical address of the phy registers and length of memory mapped
 | 
				
			||||||
	region.
 | 
						region.
 | 
				
			||||||
 | 
					- clocks: Clock IDs array as required by the controller.
 | 
				
			||||||
 | 
					- clock-names: names of clock correseponding IDs clock property as requested
 | 
				
			||||||
 | 
						       by the controller driver.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Exynos5250:
 | 
					Exynos5250:
 | 
				
			||||||
- compatible : should be "samsung,exynos5250-usbphy"
 | 
					- compatible : should be "samsung,exynos5250-usb2phy"
 | 
				
			||||||
- reg : base physical address of the phy registers and length of memory mapped
 | 
					- reg : base physical address of the phy registers and length of memory mapped
 | 
				
			||||||
	region.
 | 
						region.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,12 +49,69 @@ Example:
 | 
				
			||||||
	usbphy@125B0000 {
 | 
						usbphy@125B0000 {
 | 
				
			||||||
		#address-cells = <1>;
 | 
							#address-cells = <1>;
 | 
				
			||||||
		#size-cells = <1>;
 | 
							#size-cells = <1>;
 | 
				
			||||||
		compatible = "samsung,exynos4210-usbphy";
 | 
							compatible = "samsung,exynos4210-usb2phy";
 | 
				
			||||||
		reg = <0x125B0000 0x100>;
 | 
							reg = <0x125B0000 0x100>;
 | 
				
			||||||
		ranges;
 | 
							ranges;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							clocks = <&clock 2>, <&clock 305>;
 | 
				
			||||||
 | 
							clock-names = "xusbxti", "otg";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		usbphy-sys {
 | 
							usbphy-sys {
 | 
				
			||||||
			/* USB device and host PHY_CONTROL registers */
 | 
								/* USB device and host PHY_CONTROL registers */
 | 
				
			||||||
			reg = <0x10020704 0x8>;
 | 
								reg = <0x10020704 0x8>;
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					** Samsung's usb 3.0 phy transceiver
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Starting exynso5250, Samsung's SoC have usb 3.0 phy transceiver
 | 
				
			||||||
 | 
					which is used for controlling usb 3.0 phy for dwc3-exynos usb 3.0
 | 
				
			||||||
 | 
					controllers across Samsung SOCs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Required properties:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Exynos5250:
 | 
				
			||||||
 | 
					- compatible : should be "samsung,exynos5250-usb3phy"
 | 
				
			||||||
 | 
					- reg : base physical address of the phy registers and length of memory mapped
 | 
				
			||||||
 | 
						region.
 | 
				
			||||||
 | 
					- clocks: Clock IDs array as required by the controller.
 | 
				
			||||||
 | 
					- clock-names: names of clocks correseponding to IDs in the clock property
 | 
				
			||||||
 | 
						       as requested by the controller driver.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Optional properties:
 | 
				
			||||||
 | 
					- #address-cells: should be '1' when usbphy node has a child node with 'reg'
 | 
				
			||||||
 | 
							  property.
 | 
				
			||||||
 | 
					- #size-cells: should be '1' when usbphy node has a child node with 'reg'
 | 
				
			||||||
 | 
						       property.
 | 
				
			||||||
 | 
					- ranges: allows valid translation between child's address space and parent's
 | 
				
			||||||
 | 
						  address space.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- The child node 'usbphy-sys' to the node 'usbphy' is for the system controller
 | 
				
			||||||
 | 
					  interface for usb-phy. It should provide the following information required by
 | 
				
			||||||
 | 
					  usb-phy controller to control phy.
 | 
				
			||||||
 | 
					  - reg : base physical address of PHY_CONTROL registers.
 | 
				
			||||||
 | 
						  The size of this register is the total sum of size of all PHY_CONTROL
 | 
				
			||||||
 | 
						  registers that the SoC has. For example, the size will be
 | 
				
			||||||
 | 
						  '0x4' in case we have only one PHY_CONTROL register (e.g.
 | 
				
			||||||
 | 
						  OTHERS register in S3C64XX or USB_PHY_CONTROL register in S5PV210)
 | 
				
			||||||
 | 
						  and, '0x8' in case we have two PHY_CONTROL registers (e.g.
 | 
				
			||||||
 | 
						  USBDEVICE_PHY_CONTROL and USBHOST_PHY_CONTROL registers in exynos4x).
 | 
				
			||||||
 | 
						  and so on.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example:
 | 
				
			||||||
 | 
						usbphy@12100000 {
 | 
				
			||||||
 | 
							compatible = "samsung,exynos5250-usb3phy";
 | 
				
			||||||
 | 
							reg = <0x12100000 0x100>;
 | 
				
			||||||
 | 
							#address-cells = <1>;
 | 
				
			||||||
 | 
							#size-cells = <1>;
 | 
				
			||||||
 | 
							ranges;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							clocks = <&clock 1>, <&clock 286>;
 | 
				
			||||||
 | 
							clock-names = "ext_xtal", "usbdrd30";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							usbphy-sys {
 | 
				
			||||||
 | 
								/* USB device and host PHY_CONTROL registers */
 | 
				
			||||||
 | 
								reg = <0x10040704 0x8>;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										34
									
								
								Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,34 @@
 | 
				
			||||||
 | 
					USB NOP PHY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Required properties:
 | 
				
			||||||
 | 
					- compatible: should be usb-nop-xceiv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Optional properties:
 | 
				
			||||||
 | 
					- clocks: phandle to the PHY clock. Use as per Documentation/devicetree
 | 
				
			||||||
 | 
					  /bindings/clock/clock-bindings.txt
 | 
				
			||||||
 | 
					  This property is required if clock-frequency is specified.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- clock-names: Should be "main_clk"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- clock-frequency: the clock frequency (in Hz) that the PHY clock must
 | 
				
			||||||
 | 
					  be configured to.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- vcc-supply: phandle to the regulator that provides RESET to the PHY.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- reset-supply: phandle to the regulator that provides power to the PHY.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hsusb1_phy {
 | 
				
			||||||
 | 
							compatible = "usb-nop-xceiv";
 | 
				
			||||||
 | 
							clock-frequency = <19200000>;
 | 
				
			||||||
 | 
							clocks = <&osc 0>;
 | 
				
			||||||
 | 
							clock-names = "main_clk";
 | 
				
			||||||
 | 
							vcc-supply = <&hsusb1_vcc_regulator>;
 | 
				
			||||||
 | 
							reset-supply = <&hsusb1_reset_regulator>;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					hsusb1_phy is a NOP USB PHY device that gets its clock from an oscillator
 | 
				
			||||||
 | 
					and expects that clock to be configured to 19.2MHz by the NOP PHY driver.
 | 
				
			||||||
 | 
					hsusb1_vcc_regulator provides power to the PHY and hsusb1_reset_regulator
 | 
				
			||||||
 | 
					controls RESET.
 | 
				
			||||||
| 
						 | 
					@ -223,13 +223,7 @@ static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(CONFIG_USB_EHCI_MV)
 | 
					#if defined(CONFIG_USB_EHCI_MV)
 | 
				
			||||||
static char *pxa168_sph_clock_name[] = {
 | 
					 | 
				
			||||||
	[0] = "PXA168-USBCLK",
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct mv_usb_platform_data pxa168_sph_pdata = {
 | 
					static struct mv_usb_platform_data pxa168_sph_pdata = {
 | 
				
			||||||
	.clknum         = 1,
 | 
					 | 
				
			||||||
	.clkname        = pxa168_sph_clock_name,
 | 
					 | 
				
			||||||
	.mode           = MV_USB_MODE_HOST,
 | 
						.mode           = MV_USB_MODE_HOST,
 | 
				
			||||||
	.phy_init	= pxa_usb_phy_init,
 | 
						.phy_init	= pxa_usb_phy_init,
 | 
				
			||||||
	.phy_deinit	= pxa_usb_phy_deinit,
 | 
						.phy_deinit	= pxa_usb_phy_deinit,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -162,13 +162,7 @@ static struct i2c_board_info ttc_dkb_i2c_info[] = {
 | 
				
			||||||
#ifdef CONFIG_USB_SUPPORT
 | 
					#ifdef CONFIG_USB_SUPPORT
 | 
				
			||||||
#if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV_U2O)
 | 
					#if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV_U2O)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char *pxa910_usb_clock_name[] = {
 | 
					 | 
				
			||||||
	[0] = "U2OCLK",
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct mv_usb_platform_data ttc_usb_pdata = {
 | 
					static struct mv_usb_platform_data ttc_usb_pdata = {
 | 
				
			||||||
	.clknum		= 1,
 | 
					 | 
				
			||||||
	.clkname	= pxa910_usb_clock_name,
 | 
					 | 
				
			||||||
	.vbus		= NULL,
 | 
						.vbus		= NULL,
 | 
				
			||||||
	.mode		= MV_USB_MODE_OTG,
 | 
						.mode		= MV_USB_MODE_OTG,
 | 
				
			||||||
	.otg_force_a_bus_req = 1,
 | 
						.otg_force_a_bus_req = 1,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -169,7 +169,7 @@ static int usbhsf_get_id(struct platform_device *pdev)
 | 
				
			||||||
	return USBHS_GADGET;
 | 
						return USBHS_GADGET;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void usbhsf_power_ctrl(struct platform_device *pdev,
 | 
					static int usbhsf_power_ctrl(struct platform_device *pdev,
 | 
				
			||||||
			      void __iomem *base, int enable)
 | 
								      void __iomem *base, int enable)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usbhsf_private *priv = usbhsf_get_priv(pdev);
 | 
						struct usbhsf_private *priv = usbhsf_get_priv(pdev);
 | 
				
			||||||
| 
						 | 
					@ -223,6 +223,8 @@ static void usbhsf_power_ctrl(struct platform_device *pdev,
 | 
				
			||||||
		clk_disable(priv->pci);		/* usb work around */
 | 
							clk_disable(priv->pci);		/* usb work around */
 | 
				
			||||||
		clk_disable(priv->usb24);	/* usb work around */
 | 
							clk_disable(priv->usb24);	/* usb work around */
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int usbhsf_get_vbus(struct platform_device *pdev)
 | 
					static int usbhsf_get_vbus(struct platform_device *pdev)
 | 
				
			||||||
| 
						 | 
					@ -239,7 +241,7 @@ static irqreturn_t usbhsf_interrupt(int irq, void *data)
 | 
				
			||||||
	return IRQ_HANDLED;
 | 
						return IRQ_HANDLED;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void usbhsf_hardware_exit(struct platform_device *pdev)
 | 
					static int usbhsf_hardware_exit(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usbhsf_private *priv = usbhsf_get_priv(pdev);
 | 
						struct usbhsf_private *priv = usbhsf_get_priv(pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -264,6 +266,8 @@ static void usbhsf_hardware_exit(struct platform_device *pdev)
 | 
				
			||||||
	priv->usbh_base	= NULL;
 | 
						priv->usbh_base	= NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free_irq(IRQ7, pdev);
 | 
						free_irq(IRQ7, pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int usbhsf_hardware_init(struct platform_device *pdev)
 | 
					static int usbhsf_hardware_init(struct platform_device *pdev)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,12 +155,14 @@ static int usbhs_get_vbus(struct platform_device *pdev)
 | 
				
			||||||
	return !((1 << 7) & __raw_readw(priv->cr2));
 | 
						return !((1 << 7) & __raw_readw(priv->cr2));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void usbhs_phy_reset(struct platform_device *pdev)
 | 
					static int usbhs_phy_reset(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usbhs_private *priv = usbhs_get_priv(pdev);
 | 
						struct usbhs_private *priv = usbhs_get_priv(pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* init phy */
 | 
						/* init phy */
 | 
				
			||||||
	__raw_writew(0x8a0a, priv->cr2);
 | 
						__raw_writew(0x8a0a, priv->cr2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int usbhs_get_id(struct platform_device *pdev)
 | 
					static int usbhs_get_id(struct platform_device *pdev)
 | 
				
			||||||
| 
						 | 
					@ -202,7 +204,7 @@ static int usbhs_hardware_init(struct platform_device *pdev)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void usbhs_hardware_exit(struct platform_device *pdev)
 | 
					static int usbhs_hardware_exit(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usbhs_private *priv = usbhs_get_priv(pdev);
 | 
						struct usbhs_private *priv = usbhs_get_priv(pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -210,6 +212,8 @@ static void usbhs_hardware_exit(struct platform_device *pdev)
 | 
				
			||||||
	__raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy);
 | 
						__raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free_irq(IRQ15, pdev);
 | 
						free_irq(IRQ15, pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static u32 usbhs_pipe_cfg[] = {
 | 
					static u32 usbhs_pipe_cfg[] = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -596,12 +596,14 @@ static int usbhs_get_vbus(struct platform_device *pdev)
 | 
				
			||||||
	return usbhs_is_connected(usbhs_get_priv(pdev));
 | 
						return usbhs_is_connected(usbhs_get_priv(pdev));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void usbhs_phy_reset(struct platform_device *pdev)
 | 
					static int usbhs_phy_reset(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usbhs_private *priv = usbhs_get_priv(pdev);
 | 
						struct usbhs_private *priv = usbhs_get_priv(pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* init phy */
 | 
						/* init phy */
 | 
				
			||||||
	__raw_writew(0x8a0a, priv->usbcrcaddr);
 | 
						__raw_writew(0x8a0a, priv->usbcrcaddr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int usbhs0_get_id(struct platform_device *pdev)
 | 
					static int usbhs0_get_id(struct platform_device *pdev)
 | 
				
			||||||
| 
						 | 
					@ -628,11 +630,13 @@ static int usbhs0_hardware_init(struct platform_device *pdev)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void usbhs0_hardware_exit(struct platform_device *pdev)
 | 
					static int usbhs0_hardware_exit(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usbhs_private *priv = usbhs_get_priv(pdev);
 | 
						struct usbhs_private *priv = usbhs_get_priv(pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cancel_delayed_work_sync(&priv->work);
 | 
						cancel_delayed_work_sync(&priv->work);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usbhs_private usbhs0_private = {
 | 
					static struct usbhs_private usbhs0_private = {
 | 
				
			||||||
| 
						 | 
					@ -735,7 +739,7 @@ static int usbhs1_hardware_init(struct platform_device *pdev)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void usbhs1_hardware_exit(struct platform_device *pdev)
 | 
					static int usbhs1_hardware_exit(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usbhs_private *priv = usbhs_get_priv(pdev);
 | 
						struct usbhs_private *priv = usbhs_get_priv(pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -743,6 +747,8 @@ static void usbhs1_hardware_exit(struct platform_device *pdev)
 | 
				
			||||||
	__raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr);
 | 
						__raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free_irq(IRQ8, pdev);
 | 
						free_irq(IRQ8, pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int usbhs1_get_id(struct platform_device *pdev)
 | 
					static int usbhs1_get_id(struct platform_device *pdev)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,8 +18,8 @@ config ARCH_TEGRA_2x_SOC
 | 
				
			||||||
	select PL310_ERRATA_727915 if CACHE_L2X0
 | 
						select PL310_ERRATA_727915 if CACHE_L2X0
 | 
				
			||||||
	select PL310_ERRATA_769419 if CACHE_L2X0
 | 
						select PL310_ERRATA_769419 if CACHE_L2X0
 | 
				
			||||||
	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 | 
						select USB_ARCH_HAS_EHCI if USB_SUPPORT
 | 
				
			||||||
	select USB_ULPI if USB
 | 
						select USB_ULPI if USB_PHY
 | 
				
			||||||
	select USB_ULPI_VIEWPORT if USB_SUPPORT
 | 
						select USB_ULPI_VIEWPORT if USB_PHY
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  Support for NVIDIA Tegra AP20 and T20 processors, based on the
 | 
						  Support for NVIDIA Tegra AP20 and T20 processors, based on the
 | 
				
			||||||
	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
 | 
						  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
 | 
				
			||||||
| 
						 | 
					@ -37,8 +37,8 @@ config ARCH_TEGRA_3x_SOC
 | 
				
			||||||
	select PINCTRL_TEGRA30
 | 
						select PINCTRL_TEGRA30
 | 
				
			||||||
	select PL310_ERRATA_769419 if CACHE_L2X0
 | 
						select PL310_ERRATA_769419 if CACHE_L2X0
 | 
				
			||||||
	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 | 
						select USB_ARCH_HAS_EHCI if USB_SUPPORT
 | 
				
			||||||
	select USB_ULPI if USB
 | 
						select USB_ULPI if USB_PHY
 | 
				
			||||||
	select USB_ULPI_VIEWPORT if USB_SUPPORT
 | 
						select USB_ULPI_VIEWPORT if USB_PHY
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  Support for NVIDIA Tegra T30 processor family, based on the
 | 
						  Support for NVIDIA Tegra T30 processor family, based on the
 | 
				
			||||||
	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
 | 
						  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -254,11 +254,13 @@ static int usbhs_get_id(struct platform_device *pdev)
 | 
				
			||||||
	return gpio_get_value(GPIO_PTB3);
 | 
						return gpio_get_value(GPIO_PTB3);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void usbhs_phy_reset(struct platform_device *pdev)
 | 
					static int usbhs_phy_reset(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* enable vbus if HOST */
 | 
						/* enable vbus if HOST */
 | 
				
			||||||
	if (!gpio_get_value(GPIO_PTB3))
 | 
						if (!gpio_get_value(GPIO_PTB3))
 | 
				
			||||||
		gpio_set_value(GPIO_PTB5, 1);
 | 
							gpio_set_value(GPIO_PTB5, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct renesas_usbhs_platform_info usbhs_info = {
 | 
					static struct renesas_usbhs_platform_info usbhs_info = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,7 @@ obj-$(CONFIG_ATA_OVER_ETH)	+= block/aoe/
 | 
				
			||||||
obj-$(CONFIG_PARIDE) 		+= block/paride/
 | 
					obj-$(CONFIG_PARIDE) 		+= block/paride/
 | 
				
			||||||
obj-$(CONFIG_TC)		+= tc/
 | 
					obj-$(CONFIG_TC)		+= tc/
 | 
				
			||||||
obj-$(CONFIG_UWB)		+= uwb/
 | 
					obj-$(CONFIG_UWB)		+= uwb/
 | 
				
			||||||
obj-$(CONFIG_USB_OTG_UTILS)	+= usb/
 | 
					obj-$(CONFIG_USB_PHY)		+= usb/
 | 
				
			||||||
obj-$(CONFIG_USB)		+= usb/
 | 
					obj-$(CONFIG_USB)		+= usb/
 | 
				
			||||||
obj-$(CONFIG_PCI)		+= usb/
 | 
					obj-$(CONFIG_PCI)		+= usb/
 | 
				
			||||||
obj-$(CONFIG_USB_GADGET)	+= usb/
 | 
					obj-$(CONFIG_USB_GADGET)	+= usb/
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -254,7 +254,7 @@ config BATTERY_RX51
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config CHARGER_ISP1704
 | 
					config CHARGER_ISP1704
 | 
				
			||||||
	tristate "ISP1704 USB Charger Detection"
 | 
						tristate "ISP1704 USB Charger Detection"
 | 
				
			||||||
	depends on USB_OTG_UTILS
 | 
						depends on USB_PHY
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  Say Y to enable support for USB Charger Detection with
 | 
						  Say Y to enable support for USB Charger Detection with
 | 
				
			||||||
	  ISP1707/ISP1704 USB transceivers.
 | 
						  ISP1707/ISP1704 USB transceivers.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,7 @@ static struct timer_list supply_timer;
 | 
				
			||||||
static struct timer_list polling_timer;
 | 
					static struct timer_list polling_timer;
 | 
				
			||||||
static int polling;
 | 
					static int polling;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_USB_OTG_UTILS
 | 
					#if IS_ENABLED(CONFIG_USB_PHY)
 | 
				
			||||||
static struct usb_phy *transceiver;
 | 
					static struct usb_phy *transceiver;
 | 
				
			||||||
static struct notifier_block otg_nb;
 | 
					static struct notifier_block otg_nb;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -218,7 +218,7 @@ static void polling_timer_func(unsigned long unused)
 | 
				
			||||||
		  jiffies + msecs_to_jiffies(pdata->polling_interval));
 | 
							  jiffies + msecs_to_jiffies(pdata->polling_interval));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_USB_OTG_UTILS
 | 
					#if IS_ENABLED(CONFIG_USB_PHY)
 | 
				
			||||||
static int otg_is_usb_online(void)
 | 
					static int otg_is_usb_online(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return (transceiver->last_event == USB_EVENT_VBUS ||
 | 
						return (transceiver->last_event == USB_EVENT_VBUS ||
 | 
				
			||||||
| 
						 | 
					@ -315,7 +315,7 @@ static int pda_power_probe(struct platform_device *pdev)
 | 
				
			||||||
		pda_psy_usb.num_supplicants = pdata->num_supplicants;
 | 
							pda_psy_usb.num_supplicants = pdata->num_supplicants;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_USB_OTG_UTILS
 | 
					#if IS_ENABLED(CONFIG_USB_PHY)
 | 
				
			||||||
	transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 | 
						transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 | 
				
			||||||
	if (!IS_ERR_OR_NULL(transceiver)) {
 | 
						if (!IS_ERR_OR_NULL(transceiver)) {
 | 
				
			||||||
		if (!pdata->is_usb_online)
 | 
							if (!pdata->is_usb_online)
 | 
				
			||||||
| 
						 | 
					@ -367,7 +367,7 @@ static int pda_power_probe(struct platform_device *pdev)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_USB_OTG_UTILS
 | 
					#if IS_ENABLED(CONFIG_USB_PHY)
 | 
				
			||||||
	if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
 | 
						if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
 | 
				
			||||||
		otg_nb.notifier_call = otg_handle_notification;
 | 
							otg_nb.notifier_call = otg_handle_notification;
 | 
				
			||||||
		ret = usb_register_notifier(transceiver, &otg_nb);
 | 
							ret = usb_register_notifier(transceiver, &otg_nb);
 | 
				
			||||||
| 
						 | 
					@ -391,7 +391,7 @@ static int pda_power_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_USB_OTG_UTILS
 | 
					#if IS_ENABLED(CONFIG_USB_PHY)
 | 
				
			||||||
otg_reg_notifier_failed:
 | 
					otg_reg_notifier_failed:
 | 
				
			||||||
	if (pdata->is_usb_online && usb_irq)
 | 
						if (pdata->is_usb_online && usb_irq)
 | 
				
			||||||
		free_irq(usb_irq->start, &pda_psy_usb);
 | 
							free_irq(usb_irq->start, &pda_psy_usb);
 | 
				
			||||||
| 
						 | 
					@ -402,7 +402,7 @@ usb_irq_failed:
 | 
				
			||||||
usb_supply_failed:
 | 
					usb_supply_failed:
 | 
				
			||||||
	if (pdata->is_ac_online && ac_irq)
 | 
						if (pdata->is_ac_online && ac_irq)
 | 
				
			||||||
		free_irq(ac_irq->start, &pda_psy_ac);
 | 
							free_irq(ac_irq->start, &pda_psy_ac);
 | 
				
			||||||
#ifdef CONFIG_USB_OTG_UTILS
 | 
					#if IS_ENABLED(CONFIG_USB_PHY)
 | 
				
			||||||
	if (!IS_ERR_OR_NULL(transceiver))
 | 
						if (!IS_ERR_OR_NULL(transceiver))
 | 
				
			||||||
		usb_put_phy(transceiver);
 | 
							usb_put_phy(transceiver);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -437,7 +437,7 @@ static int pda_power_remove(struct platform_device *pdev)
 | 
				
			||||||
		power_supply_unregister(&pda_psy_usb);
 | 
							power_supply_unregister(&pda_psy_usb);
 | 
				
			||||||
	if (pdata->is_ac_online)
 | 
						if (pdata->is_ac_online)
 | 
				
			||||||
		power_supply_unregister(&pda_psy_ac);
 | 
							power_supply_unregister(&pda_psy_ac);
 | 
				
			||||||
#ifdef CONFIG_USB_OTG_UTILS
 | 
					#if IS_ENABLED(CONFIG_USB_PHY)
 | 
				
			||||||
	if (!IS_ERR_OR_NULL(transceiver))
 | 
						if (!IS_ERR_OR_NULL(transceiver))
 | 
				
			||||||
		usb_put_phy(transceiver);
 | 
							usb_put_phy(transceiver);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -186,6 +186,4 @@ source "drivers/usb/atm/Kconfig"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
source "drivers/usb/gadget/Kconfig"
 | 
					source "drivers/usb/gadget/Kconfig"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
source "drivers/usb/otg/Kconfig"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
endif # USB_SUPPORT
 | 
					endif # USB_SUPPORT
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,8 +6,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_USB)		+= core/
 | 
					obj-$(CONFIG_USB)		+= core/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_USB_OTG_UTILS)	+= otg/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
obj-$(CONFIG_USB_DWC3)		+= dwc3/
 | 
					obj-$(CONFIG_USB_DWC3)		+= dwc3/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_USB_MON)		+= mon/
 | 
					obj-$(CONFIG_USB_MON)		+= mon/
 | 
				
			||||||
| 
						 | 
					@ -46,7 +44,7 @@ obj-$(CONFIG_USB_MICROTEK)	+= image/
 | 
				
			||||||
obj-$(CONFIG_USB_SERIAL)	+= serial/
 | 
					obj-$(CONFIG_USB_SERIAL)	+= serial/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_USB)		+= misc/
 | 
					obj-$(CONFIG_USB)		+= misc/
 | 
				
			||||||
obj-$(CONFIG_USB_OTG_UTILS)	+= phy/
 | 
					obj-$(CONFIG_USB_PHY)		+= phy/
 | 
				
			||||||
obj-$(CONFIG_EARLY_PRINTK_DBGP)	+= early/
 | 
					obj-$(CONFIG_EARLY_PRINTK_DBGP)	+= early/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_USB_ATM)		+= atm/
 | 
					obj-$(CONFIG_USB_ATM)		+= atm/
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1638,16 +1638,6 @@ static irqreturn_t udc_irq(struct ci13xxx *ci)
 | 
				
			||||||
	return retval;
 | 
						return retval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * udc_release: driver release function
 | 
					 | 
				
			||||||
 * @dev: device
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Currently does nothing
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void udc_release(struct device *dev)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * udc_start: initialize gadget role
 | 
					 * udc_start: initialize gadget role
 | 
				
			||||||
 * @ci: chipidea controller
 | 
					 * @ci: chipidea controller
 | 
				
			||||||
| 
						 | 
					@ -1667,12 +1657,6 @@ static int udc_start(struct ci13xxx *ci)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	INIT_LIST_HEAD(&ci->gadget.ep_list);
 | 
						INIT_LIST_HEAD(&ci->gadget.ep_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_set_name(&ci->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
	ci->gadget.dev.dma_mask = dev->dma_mask;
 | 
					 | 
				
			||||||
	ci->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
 | 
					 | 
				
			||||||
	ci->gadget.dev.parent   = dev;
 | 
					 | 
				
			||||||
	ci->gadget.dev.release  = udc_release;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* alloc resources */
 | 
						/* alloc resources */
 | 
				
			||||||
	ci->qh_pool = dma_pool_create("ci13xxx_qh", dev,
 | 
						ci->qh_pool = dma_pool_create("ci13xxx_qh", dev,
 | 
				
			||||||
				       sizeof(struct ci13xxx_qh),
 | 
									       sizeof(struct ci13xxx_qh),
 | 
				
			||||||
| 
						 | 
					@ -1710,17 +1694,11 @@ static int udc_start(struct ci13xxx *ci)
 | 
				
			||||||
			goto put_transceiver;
 | 
								goto put_transceiver;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = device_register(&ci->gadget.dev);
 | 
					 | 
				
			||||||
	if (retval) {
 | 
					 | 
				
			||||||
		put_device(&ci->gadget.dev);
 | 
					 | 
				
			||||||
		goto put_transceiver;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!IS_ERR_OR_NULL(ci->transceiver)) {
 | 
						if (!IS_ERR_OR_NULL(ci->transceiver)) {
 | 
				
			||||||
		retval = otg_set_peripheral(ci->transceiver->otg,
 | 
							retval = otg_set_peripheral(ci->transceiver->otg,
 | 
				
			||||||
						&ci->gadget);
 | 
											&ci->gadget);
 | 
				
			||||||
		if (retval)
 | 
							if (retval)
 | 
				
			||||||
			goto unreg_device;
 | 
								goto put_transceiver;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = usb_add_gadget_udc(dev, &ci->gadget);
 | 
						retval = usb_add_gadget_udc(dev, &ci->gadget);
 | 
				
			||||||
| 
						 | 
					@ -1740,8 +1718,6 @@ remove_trans:
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_err(dev, "error = %i\n", retval);
 | 
						dev_err(dev, "error = %i\n", retval);
 | 
				
			||||||
unreg_device:
 | 
					 | 
				
			||||||
	device_unregister(&ci->gadget.dev);
 | 
					 | 
				
			||||||
put_transceiver:
 | 
					put_transceiver:
 | 
				
			||||||
	if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)
 | 
						if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)
 | 
				
			||||||
		usb_put_phy(ci->transceiver);
 | 
							usb_put_phy(ci->transceiver);
 | 
				
			||||||
| 
						 | 
					@ -1776,7 +1752,6 @@ static void udc_stop(struct ci13xxx *ci)
 | 
				
			||||||
		if (ci->global_phy)
 | 
							if (ci->global_phy)
 | 
				
			||||||
			usb_put_phy(ci->transceiver);
 | 
								usb_put_phy(ci->transceiver);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	device_unregister(&ci->gadget.dev);
 | 
					 | 
				
			||||||
	/* my kobject is dynamic, I swear! */
 | 
						/* my kobject is dynamic, I swear! */
 | 
				
			||||||
	memset(&ci->gadget, 0, sizeof(ci->gadget));
 | 
						memset(&ci->gadget, 0, sizeof(ci->gadget));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,6 @@
 | 
				
			||||||
config USB_DWC3
 | 
					config USB_DWC3
 | 
				
			||||||
	tristate "DesignWare USB3 DRD Core Support"
 | 
						tristate "DesignWare USB3 DRD Core Support"
 | 
				
			||||||
	depends on (USB || USB_GADGET) && GENERIC_HARDIRQS
 | 
						depends on (USB || USB_GADGET) && GENERIC_HARDIRQS
 | 
				
			||||||
	select USB_OTG_UTILS
 | 
					 | 
				
			||||||
	select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
 | 
						select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  Say Y or M here if your system has a Dual Role SuperSpeed
 | 
						  Say Y or M here if your system has a Dual Role SuperSpeed
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,7 +140,8 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
 | 
				
			||||||
 * Returns a pointer to the allocated event buffer structure on success
 | 
					 * Returns a pointer to the allocated event buffer structure on success
 | 
				
			||||||
 * otherwise ERR_PTR(errno).
 | 
					 * otherwise ERR_PTR(errno).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
 | 
					static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
 | 
				
			||||||
 | 
							unsigned length)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dwc3_event_buffer	*evt;
 | 
						struct dwc3_event_buffer	*evt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -259,6 +260,17 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void dwc3_core_num_eps(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dwc3_hwparams	*parms = &dwc->hwparams;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
 | 
				
			||||||
 | 
						dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n",
 | 
				
			||||||
 | 
								dwc->num_in_eps, dwc->num_out_eps);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void dwc3_cache_hwparams(struct dwc3 *dwc)
 | 
					static void dwc3_cache_hwparams(struct dwc3 *dwc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dwc3_hwparams	*parms = &dwc->hwparams;
 | 
						struct dwc3_hwparams	*parms = &dwc->hwparams;
 | 
				
			||||||
| 
						 | 
					@ -335,13 +347,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
 | 
				
			||||||
	if (dwc->revision < DWC3_REVISION_190A)
 | 
						if (dwc->revision < DWC3_REVISION_190A)
 | 
				
			||||||
		reg |= DWC3_GCTL_U2RSTECN;
 | 
							reg |= DWC3_GCTL_U2RSTECN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 | 
						dwc3_core_num_eps(dwc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = dwc3_event_buffers_setup(dwc);
 | 
						dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		dev_err(dwc->dev, "failed to setup event buffers\n");
 | 
					 | 
				
			||||||
		goto err0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -351,8 +359,6 @@ err0:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void dwc3_core_exit(struct dwc3 *dwc)
 | 
					static void dwc3_core_exit(struct dwc3 *dwc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	dwc3_event_buffers_cleanup(dwc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	usb_phy_shutdown(dwc->usb2_phy);
 | 
						usb_phy_shutdown(dwc->usb2_phy);
 | 
				
			||||||
	usb_phy_shutdown(dwc->usb3_phy);
 | 
						usb_phy_shutdown(dwc->usb3_phy);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -428,12 +434,32 @@ static int dwc3_probe(struct platform_device *pdev)
 | 
				
			||||||
		dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
 | 
							dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (IS_ERR_OR_NULL(dwc->usb2_phy)) {
 | 
						if (IS_ERR(dwc->usb2_phy)) {
 | 
				
			||||||
 | 
							ret = PTR_ERR(dwc->usb2_phy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * if -ENXIO is returned, it means PHY layer wasn't
 | 
				
			||||||
 | 
							 * enabled, so it makes no sense to return -EPROBE_DEFER
 | 
				
			||||||
 | 
							 * in that case, since no PHY driver will ever probe.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (ret == -ENXIO)
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dev_err(dev, "no usb2 phy configured\n");
 | 
							dev_err(dev, "no usb2 phy configured\n");
 | 
				
			||||||
		return -EPROBE_DEFER;
 | 
							return -EPROBE_DEFER;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (IS_ERR_OR_NULL(dwc->usb3_phy)) {
 | 
						if (IS_ERR(dwc->usb3_phy)) {
 | 
				
			||||||
 | 
							ret = PTR_ERR(dwc->usb2_phy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * if -ENXIO is returned, it means PHY layer wasn't
 | 
				
			||||||
 | 
							 * enabled, so it makes no sense to return -EPROBE_DEFER
 | 
				
			||||||
 | 
							 * in that case, since no PHY driver will ever probe.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (ret == -ENXIO)
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dev_err(dev, "no usb3 phy configured\n");
 | 
							dev_err(dev, "no usb3 phy configured\n");
 | 
				
			||||||
		return -EPROBE_DEFER;
 | 
							return -EPROBE_DEFER;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -448,6 +474,10 @@ static int dwc3_probe(struct platform_device *pdev)
 | 
				
			||||||
	dwc->regs_size	= resource_size(res);
 | 
						dwc->regs_size	= resource_size(res);
 | 
				
			||||||
	dwc->dev	= dev;
 | 
						dwc->dev	= dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev->dma_mask	= dev->parent->dma_mask;
 | 
				
			||||||
 | 
						dev->dma_parms	= dev->parent->dma_parms;
 | 
				
			||||||
 | 
						dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!strncmp("super", maximum_speed, 5))
 | 
						if (!strncmp("super", maximum_speed, 5))
 | 
				
			||||||
		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
 | 
							dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
 | 
				
			||||||
	else if (!strncmp("high", maximum_speed, 4))
 | 
						else if (!strncmp("high", maximum_speed, 4))
 | 
				
			||||||
| 
						 | 
					@ -480,7 +510,18 @@ static int dwc3_probe(struct platform_device *pdev)
 | 
				
			||||||
		goto err0;
 | 
							goto err0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mode = DWC3_MODE(dwc->hwparams.hwparams0);
 | 
						ret = dwc3_event_buffers_setup(dwc);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dwc->dev, "failed to setup event buffers\n");
 | 
				
			||||||
 | 
							goto err1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
 | 
				
			||||||
 | 
							mode = DWC3_MODE_HOST;
 | 
				
			||||||
 | 
						else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
 | 
				
			||||||
 | 
							mode = DWC3_MODE_DEVICE;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							mode = DWC3_MODE_DRD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (mode) {
 | 
						switch (mode) {
 | 
				
			||||||
	case DWC3_MODE_DEVICE:
 | 
						case DWC3_MODE_DEVICE:
 | 
				
			||||||
| 
						 | 
					@ -488,7 +529,7 @@ static int dwc3_probe(struct platform_device *pdev)
 | 
				
			||||||
		ret = dwc3_gadget_init(dwc);
 | 
							ret = dwc3_gadget_init(dwc);
 | 
				
			||||||
		if (ret) {
 | 
							if (ret) {
 | 
				
			||||||
			dev_err(dev, "failed to initialize gadget\n");
 | 
								dev_err(dev, "failed to initialize gadget\n");
 | 
				
			||||||
			goto err1;
 | 
								goto err2;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case DWC3_MODE_HOST:
 | 
						case DWC3_MODE_HOST:
 | 
				
			||||||
| 
						 | 
					@ -496,7 +537,7 @@ static int dwc3_probe(struct platform_device *pdev)
 | 
				
			||||||
		ret = dwc3_host_init(dwc);
 | 
							ret = dwc3_host_init(dwc);
 | 
				
			||||||
		if (ret) {
 | 
							if (ret) {
 | 
				
			||||||
			dev_err(dev, "failed to initialize host\n");
 | 
								dev_err(dev, "failed to initialize host\n");
 | 
				
			||||||
			goto err1;
 | 
								goto err2;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case DWC3_MODE_DRD:
 | 
						case DWC3_MODE_DRD:
 | 
				
			||||||
| 
						 | 
					@ -504,32 +545,32 @@ static int dwc3_probe(struct platform_device *pdev)
 | 
				
			||||||
		ret = dwc3_host_init(dwc);
 | 
							ret = dwc3_host_init(dwc);
 | 
				
			||||||
		if (ret) {
 | 
							if (ret) {
 | 
				
			||||||
			dev_err(dev, "failed to initialize host\n");
 | 
								dev_err(dev, "failed to initialize host\n");
 | 
				
			||||||
			goto err1;
 | 
								goto err2;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = dwc3_gadget_init(dwc);
 | 
							ret = dwc3_gadget_init(dwc);
 | 
				
			||||||
		if (ret) {
 | 
							if (ret) {
 | 
				
			||||||
			dev_err(dev, "failed to initialize gadget\n");
 | 
								dev_err(dev, "failed to initialize gadget\n");
 | 
				
			||||||
			goto err1;
 | 
								goto err2;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		dev_err(dev, "Unsupported mode of operation %d\n", mode);
 | 
							dev_err(dev, "Unsupported mode of operation %d\n", mode);
 | 
				
			||||||
		goto err1;
 | 
							goto err2;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dwc->mode = mode;
 | 
						dwc->mode = mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = dwc3_debugfs_init(dwc);
 | 
						ret = dwc3_debugfs_init(dwc);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		dev_err(dev, "failed to initialize debugfs\n");
 | 
							dev_err(dev, "failed to initialize debugfs\n");
 | 
				
			||||||
		goto err2;
 | 
							goto err3;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pm_runtime_allow(dev);
 | 
						pm_runtime_allow(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err2:
 | 
					err3:
 | 
				
			||||||
	switch (mode) {
 | 
						switch (mode) {
 | 
				
			||||||
	case DWC3_MODE_DEVICE:
 | 
						case DWC3_MODE_DEVICE:
 | 
				
			||||||
		dwc3_gadget_exit(dwc);
 | 
							dwc3_gadget_exit(dwc);
 | 
				
			||||||
| 
						 | 
					@ -546,6 +587,9 @@ err2:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err2:
 | 
				
			||||||
 | 
						dwc3_event_buffers_cleanup(dwc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err1:
 | 
					err1:
 | 
				
			||||||
	dwc3_core_exit(dwc);
 | 
						dwc3_core_exit(dwc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -583,12 +627,130 @@ static int dwc3_remove(struct platform_device *pdev)
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dwc3_event_buffers_cleanup(dwc);
 | 
				
			||||||
	dwc3_free_event_buffers(dwc);
 | 
						dwc3_free_event_buffers(dwc);
 | 
				
			||||||
	dwc3_core_exit(dwc);
 | 
						dwc3_core_exit(dwc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_PM_SLEEP
 | 
				
			||||||
 | 
					static int dwc3_prepare(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dwc3	*dwc = dev_get_drvdata(dev);
 | 
				
			||||||
 | 
						unsigned long	flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&dwc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (dwc->mode) {
 | 
				
			||||||
 | 
						case DWC3_MODE_DEVICE:
 | 
				
			||||||
 | 
						case DWC3_MODE_DRD:
 | 
				
			||||||
 | 
							dwc3_gadget_prepare(dwc);
 | 
				
			||||||
 | 
							/* FALLTHROUGH */
 | 
				
			||||||
 | 
						case DWC3_MODE_HOST:
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							dwc3_event_buffers_cleanup(dwc);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&dwc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void dwc3_complete(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dwc3	*dwc = dev_get_drvdata(dev);
 | 
				
			||||||
 | 
						unsigned long	flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&dwc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (dwc->mode) {
 | 
				
			||||||
 | 
						case DWC3_MODE_DEVICE:
 | 
				
			||||||
 | 
						case DWC3_MODE_DRD:
 | 
				
			||||||
 | 
							dwc3_gadget_complete(dwc);
 | 
				
			||||||
 | 
							/* FALLTHROUGH */
 | 
				
			||||||
 | 
						case DWC3_MODE_HOST:
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							dwc3_event_buffers_setup(dwc);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&dwc->lock, flags);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dwc3_suspend(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dwc3	*dwc = dev_get_drvdata(dev);
 | 
				
			||||||
 | 
						unsigned long	flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&dwc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (dwc->mode) {
 | 
				
			||||||
 | 
						case DWC3_MODE_DEVICE:
 | 
				
			||||||
 | 
						case DWC3_MODE_DRD:
 | 
				
			||||||
 | 
							dwc3_gadget_suspend(dwc);
 | 
				
			||||||
 | 
							/* FALLTHROUGH */
 | 
				
			||||||
 | 
						case DWC3_MODE_HOST:
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							/* do nothing */
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL);
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&dwc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						usb_phy_shutdown(dwc->usb3_phy);
 | 
				
			||||||
 | 
						usb_phy_shutdown(dwc->usb2_phy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dwc3_resume(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dwc3	*dwc = dev_get_drvdata(dev);
 | 
				
			||||||
 | 
						unsigned long	flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						usb_phy_init(dwc->usb3_phy);
 | 
				
			||||||
 | 
						usb_phy_init(dwc->usb2_phy);
 | 
				
			||||||
 | 
						msleep(100);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&dwc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (dwc->mode) {
 | 
				
			||||||
 | 
						case DWC3_MODE_DEVICE:
 | 
				
			||||||
 | 
						case DWC3_MODE_DRD:
 | 
				
			||||||
 | 
							dwc3_gadget_resume(dwc);
 | 
				
			||||||
 | 
							/* FALLTHROUGH */
 | 
				
			||||||
 | 
						case DWC3_MODE_HOST:
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							/* do nothing */
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&dwc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pm_runtime_disable(dev);
 | 
				
			||||||
 | 
						pm_runtime_set_active(dev);
 | 
				
			||||||
 | 
						pm_runtime_enable(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct dev_pm_ops dwc3_dev_pm_ops = {
 | 
				
			||||||
 | 
						.prepare	= dwc3_prepare,
 | 
				
			||||||
 | 
						.complete	= dwc3_complete,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DWC3_PM_OPS	&(dwc3_dev_pm_ops)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define DWC3_PM_OPS	NULL
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_OF
 | 
					#ifdef CONFIG_OF
 | 
				
			||||||
static const struct of_device_id of_dwc3_match[] = {
 | 
					static const struct of_device_id of_dwc3_match[] = {
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -605,6 +767,7 @@ static struct platform_driver dwc3_driver = {
 | 
				
			||||||
	.driver		= {
 | 
						.driver		= {
 | 
				
			||||||
		.name	= "dwc3",
 | 
							.name	= "dwc3",
 | 
				
			||||||
		.of_match_table	= of_match_ptr(of_dwc3_match),
 | 
							.of_match_table	= of_match_ptr(of_dwc3_match),
 | 
				
			||||||
 | 
							.pm	= DWC3_PM_OPS,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -154,8 +154,9 @@
 | 
				
			||||||
/* OTG Registers */
 | 
					/* OTG Registers */
 | 
				
			||||||
#define DWC3_OCFG		0xcc00
 | 
					#define DWC3_OCFG		0xcc00
 | 
				
			||||||
#define DWC3_OCTL		0xcc04
 | 
					#define DWC3_OCTL		0xcc04
 | 
				
			||||||
#define DWC3_OEVTEN		0xcc08
 | 
					#define DWC3_OEVT		0xcc08
 | 
				
			||||||
#define DWC3_OSTS		0xcc0C
 | 
					#define DWC3_OEVTEN		0xcc0C
 | 
				
			||||||
 | 
					#define DWC3_OSTS		0xcc10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Bit fields */
 | 
					/* Bit fields */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -369,6 +370,9 @@ struct dwc3_trb;
 | 
				
			||||||
 * @list: a list of event buffers
 | 
					 * @list: a list of event buffers
 | 
				
			||||||
 * @buf: _THE_ buffer
 | 
					 * @buf: _THE_ buffer
 | 
				
			||||||
 * @length: size of this buffer
 | 
					 * @length: size of this buffer
 | 
				
			||||||
 | 
					 * @lpos: event offset
 | 
				
			||||||
 | 
					 * @count: cache of last read event count register
 | 
				
			||||||
 | 
					 * @flags: flags related to this event buffer
 | 
				
			||||||
 * @dma: dma_addr_t
 | 
					 * @dma: dma_addr_t
 | 
				
			||||||
 * @dwc: pointer to DWC controller
 | 
					 * @dwc: pointer to DWC controller
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -376,6 +380,10 @@ struct dwc3_event_buffer {
 | 
				
			||||||
	void			*buf;
 | 
						void			*buf;
 | 
				
			||||||
	unsigned		length;
 | 
						unsigned		length;
 | 
				
			||||||
	unsigned int		lpos;
 | 
						unsigned int		lpos;
 | 
				
			||||||
 | 
						unsigned int		count;
 | 
				
			||||||
 | 
						unsigned int		flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DWC3_EVENT_PENDING	BIT(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dma_addr_t		dma;
 | 
						dma_addr_t		dma;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -487,12 +495,6 @@ enum dwc3_link_state {
 | 
				
			||||||
	DWC3_LINK_STATE_MASK		= 0x0f,
 | 
						DWC3_LINK_STATE_MASK		= 0x0f,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum dwc3_device_state {
 | 
					 | 
				
			||||||
	DWC3_DEFAULT_STATE,
 | 
					 | 
				
			||||||
	DWC3_ADDRESS_STATE,
 | 
					 | 
				
			||||||
	DWC3_CONFIGURED_STATE,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* TRB Length, PCM and Status */
 | 
					/* TRB Length, PCM and Status */
 | 
				
			||||||
#define DWC3_TRB_SIZE_MASK	(0x00ffffff)
 | 
					#define DWC3_TRB_SIZE_MASK	(0x00ffffff)
 | 
				
			||||||
#define DWC3_TRB_SIZE_LENGTH(n)	((n) & DWC3_TRB_SIZE_MASK)
 | 
					#define DWC3_TRB_SIZE_LENGTH(n)	((n) & DWC3_TRB_SIZE_MASK)
 | 
				
			||||||
| 
						 | 
					@ -574,6 +576,14 @@ struct dwc3_hwparams {
 | 
				
			||||||
/* HWPARAMS1 */
 | 
					/* HWPARAMS1 */
 | 
				
			||||||
#define DWC3_NUM_INT(n)		(((n) & (0x3f << 15)) >> 15)
 | 
					#define DWC3_NUM_INT(n)		(((n) & (0x3f << 15)) >> 15)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* HWPARAMS3 */
 | 
				
			||||||
 | 
					#define DWC3_NUM_IN_EPS_MASK	(0x1f << 18)
 | 
				
			||||||
 | 
					#define DWC3_NUM_EPS_MASK	(0x3f << 12)
 | 
				
			||||||
 | 
					#define DWC3_NUM_EPS(p)		(((p)->hwparams3 &		\
 | 
				
			||||||
 | 
								(DWC3_NUM_EPS_MASK)) >> 12)
 | 
				
			||||||
 | 
					#define DWC3_NUM_IN_EPS(p)	(((p)->hwparams3 &		\
 | 
				
			||||||
 | 
								(DWC3_NUM_IN_EPS_MASK)) >> 18)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* HWPARAMS7 */
 | 
					/* HWPARAMS7 */
 | 
				
			||||||
#define DWC3_RAM1_DEPTH(n)	((n) & 0xffff)
 | 
					#define DWC3_RAM1_DEPTH(n)	((n) & 0xffff)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -618,7 +628,6 @@ struct dwc3_scratchpad_array {
 | 
				
			||||||
 * @gadget_driver: pointer to the gadget driver
 | 
					 * @gadget_driver: pointer to the gadget driver
 | 
				
			||||||
 * @regs: base address for our registers
 | 
					 * @regs: base address for our registers
 | 
				
			||||||
 * @regs_size: address space size
 | 
					 * @regs_size: address space size
 | 
				
			||||||
 * @irq: IRQ number
 | 
					 | 
				
			||||||
 * @num_event_buffers: calculated number of event buffers
 | 
					 * @num_event_buffers: calculated number of event buffers
 | 
				
			||||||
 * @u1u2: only used on revisions <1.83a for workaround
 | 
					 * @u1u2: only used on revisions <1.83a for workaround
 | 
				
			||||||
 * @maximum_speed: maximum speed requested (mainly for testing purposes)
 | 
					 * @maximum_speed: maximum speed requested (mainly for testing purposes)
 | 
				
			||||||
| 
						 | 
					@ -626,6 +635,8 @@ struct dwc3_scratchpad_array {
 | 
				
			||||||
 * @mode: mode of operation
 | 
					 * @mode: mode of operation
 | 
				
			||||||
 * @usb2_phy: pointer to USB2 PHY
 | 
					 * @usb2_phy: pointer to USB2 PHY
 | 
				
			||||||
 * @usb3_phy: pointer to USB3 PHY
 | 
					 * @usb3_phy: pointer to USB3 PHY
 | 
				
			||||||
 | 
					 * @dcfg: saved contents of DCFG register
 | 
				
			||||||
 | 
					 * @gctl: saved contents of GCTL register
 | 
				
			||||||
 * @is_selfpowered: true when we are selfpowered
 | 
					 * @is_selfpowered: true when we are selfpowered
 | 
				
			||||||
 * @three_stage_setup: set if we perform a three phase setup
 | 
					 * @three_stage_setup: set if we perform a three phase setup
 | 
				
			||||||
 * @ep0_bounced: true when we used bounce buffer
 | 
					 * @ep0_bounced: true when we used bounce buffer
 | 
				
			||||||
| 
						 | 
					@ -639,6 +650,8 @@ struct dwc3_scratchpad_array {
 | 
				
			||||||
 * @u2pel: parameter from Set SEL request.
 | 
					 * @u2pel: parameter from Set SEL request.
 | 
				
			||||||
 * @u1sel: parameter from Set SEL request.
 | 
					 * @u1sel: parameter from Set SEL request.
 | 
				
			||||||
 * @u1pel: parameter from Set SEL request.
 | 
					 * @u1pel: parameter from Set SEL request.
 | 
				
			||||||
 | 
					 * @num_out_eps: number of out endpoints
 | 
				
			||||||
 | 
					 * @num_in_eps: number of in endpoints
 | 
				
			||||||
 * @ep0_next_event: hold the next expected event
 | 
					 * @ep0_next_event: hold the next expected event
 | 
				
			||||||
 * @ep0state: state of endpoint zero
 | 
					 * @ep0state: state of endpoint zero
 | 
				
			||||||
 * @link_state: link state
 | 
					 * @link_state: link state
 | 
				
			||||||
| 
						 | 
					@ -656,8 +669,10 @@ struct dwc3 {
 | 
				
			||||||
	dma_addr_t		ep0_trb_addr;
 | 
						dma_addr_t		ep0_trb_addr;
 | 
				
			||||||
	dma_addr_t		ep0_bounce_addr;
 | 
						dma_addr_t		ep0_bounce_addr;
 | 
				
			||||||
	struct dwc3_request	ep0_usb_req;
 | 
						struct dwc3_request	ep0_usb_req;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* device lock */
 | 
						/* device lock */
 | 
				
			||||||
	spinlock_t		lock;
 | 
						spinlock_t		lock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct device		*dev;
 | 
						struct device		*dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct platform_device	*xhci;
 | 
						struct platform_device	*xhci;
 | 
				
			||||||
| 
						 | 
					@ -675,6 +690,10 @@ struct dwc3 {
 | 
				
			||||||
	void __iomem		*regs;
 | 
						void __iomem		*regs;
 | 
				
			||||||
	size_t			regs_size;
 | 
						size_t			regs_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* used for suspend/resume */
 | 
				
			||||||
 | 
						u32			dcfg;
 | 
				
			||||||
 | 
						u32			gctl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u32			num_event_buffers;
 | 
						u32			num_event_buffers;
 | 
				
			||||||
	u32			u1u2;
 | 
						u32			u1u2;
 | 
				
			||||||
	u32			maximum_speed;
 | 
						u32			maximum_speed;
 | 
				
			||||||
| 
						 | 
					@ -694,6 +713,9 @@ struct dwc3 {
 | 
				
			||||||
#define DWC3_REVISION_202A	0x5533202a
 | 
					#define DWC3_REVISION_202A	0x5533202a
 | 
				
			||||||
#define DWC3_REVISION_210A	0x5533210a
 | 
					#define DWC3_REVISION_210A	0x5533210a
 | 
				
			||||||
#define DWC3_REVISION_220A	0x5533220a
 | 
					#define DWC3_REVISION_220A	0x5533220a
 | 
				
			||||||
 | 
					#define DWC3_REVISION_230A	0x5533230a
 | 
				
			||||||
 | 
					#define DWC3_REVISION_240A	0x5533240a
 | 
				
			||||||
 | 
					#define DWC3_REVISION_250A	0x5533250a
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unsigned		is_selfpowered:1;
 | 
						unsigned		is_selfpowered:1;
 | 
				
			||||||
	unsigned		three_stage_setup:1;
 | 
						unsigned		three_stage_setup:1;
 | 
				
			||||||
| 
						 | 
					@ -704,11 +726,11 @@ struct dwc3 {
 | 
				
			||||||
	unsigned		delayed_status:1;
 | 
						unsigned		delayed_status:1;
 | 
				
			||||||
	unsigned		needs_fifo_resize:1;
 | 
						unsigned		needs_fifo_resize:1;
 | 
				
			||||||
	unsigned		resize_fifos:1;
 | 
						unsigned		resize_fifos:1;
 | 
				
			||||||
 | 
						unsigned		pullups_connected:1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	enum dwc3_ep0_next	ep0_next_event;
 | 
						enum dwc3_ep0_next	ep0_next_event;
 | 
				
			||||||
	enum dwc3_ep0_state	ep0state;
 | 
						enum dwc3_ep0_state	ep0state;
 | 
				
			||||||
	enum dwc3_link_state	link_state;
 | 
						enum dwc3_link_state	link_state;
 | 
				
			||||||
	enum dwc3_device_state	dev_state;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u16			isoch_delay;
 | 
						u16			isoch_delay;
 | 
				
			||||||
	u16			u2sel;
 | 
						u16			u2sel;
 | 
				
			||||||
| 
						 | 
					@ -718,6 +740,9 @@ struct dwc3 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u8			speed;
 | 
						u8			speed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						u8			num_out_eps;
 | 
				
			||||||
 | 
						u8			num_in_eps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void			*mem;
 | 
						void			*mem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct dwc3_hwparams	hwparams;
 | 
						struct dwc3_hwparams	hwparams;
 | 
				
			||||||
| 
						 | 
					@ -884,4 +909,31 @@ static inline void dwc3_gadget_exit(struct dwc3 *dwc)
 | 
				
			||||||
{ }
 | 
					{ }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* power management interface */
 | 
				
			||||||
 | 
					#if !IS_ENABLED(CONFIG_USB_DWC3_HOST)
 | 
				
			||||||
 | 
					int dwc3_gadget_prepare(struct dwc3 *dwc);
 | 
				
			||||||
 | 
					void dwc3_gadget_complete(struct dwc3 *dwc);
 | 
				
			||||||
 | 
					int dwc3_gadget_suspend(struct dwc3 *dwc);
 | 
				
			||||||
 | 
					int dwc3_gadget_resume(struct dwc3 *dwc);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					static inline int dwc3_gadget_prepare(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void dwc3_gadget_complete(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int dwc3_gadget_suspend(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int dwc3_gadget_resume(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* __DRIVERS_USB_DWC3_CORE_H */
 | 
					#endif /* __DRIVERS_USB_DWC3_CORE_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,7 +59,7 @@
 | 
				
			||||||
	.offset	= DWC3_ ##nm - DWC3_GLOBALS_REGS_START,	\
 | 
						.offset	= DWC3_ ##nm - DWC3_GLOBALS_REGS_START,	\
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct debugfs_reg32 dwc3_regs[] = {
 | 
					static const struct debugfs_reg32 dwc3_regs[] = {
 | 
				
			||||||
	dump_register(GSBUSCFG0),
 | 
						dump_register(GSBUSCFG0),
 | 
				
			||||||
	dump_register(GSBUSCFG1),
 | 
						dump_register(GSBUSCFG1),
 | 
				
			||||||
	dump_register(GTXTHRCFG),
 | 
						dump_register(GTXTHRCFG),
 | 
				
			||||||
| 
						 | 
					@ -372,6 +372,7 @@ static struct debugfs_reg32 dwc3_regs[] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dump_register(OCFG),
 | 
						dump_register(OCFG),
 | 
				
			||||||
	dump_register(OCTL),
 | 
						dump_register(OCTL),
 | 
				
			||||||
 | 
						dump_register(OEVT),
 | 
				
			||||||
	dump_register(OEVTEN),
 | 
						dump_register(OEVTEN),
 | 
				
			||||||
	dump_register(OSTS),
 | 
						dump_register(OSTS),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -577,8 +578,14 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused)
 | 
				
			||||||
	case DWC3_LINK_STATE_LPBK:
 | 
						case DWC3_LINK_STATE_LPBK:
 | 
				
			||||||
		seq_printf(s, "Loopback\n");
 | 
							seq_printf(s, "Loopback\n");
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case DWC3_LINK_STATE_RESET:
 | 
				
			||||||
 | 
							seq_printf(s, "Reset\n");
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case DWC3_LINK_STATE_RESUME:
 | 
				
			||||||
 | 
							seq_printf(s, "Resume\n");
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		seq_printf(s, "UNKNOWN %d\n", reg);
 | 
							seq_printf(s, "UNKNOWN %d\n", state);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -661,28 +668,31 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
 | 
				
			||||||
		goto err1;
 | 
							goto err1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if IS_ENABLED(CONFIG_USB_DWC3_GADGET)
 | 
						if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) {
 | 
				
			||||||
	file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
 | 
							file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
 | 
				
			||||||
			dwc, &dwc3_mode_fops);
 | 
									dwc, &dwc3_mode_fops);
 | 
				
			||||||
	if (!file) {
 | 
							if (!file) {
 | 
				
			||||||
		ret = -ENOMEM;
 | 
								ret = -ENOMEM;
 | 
				
			||||||
		goto err1;
 | 
								goto err1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
 | 
						if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) ||
 | 
				
			||||||
			dwc, &dwc3_testmode_fops);
 | 
								IS_ENABLED(CONFIG_USB_DWC3_GADGET)) {
 | 
				
			||||||
	if (!file) {
 | 
							file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
 | 
				
			||||||
		ret = -ENOMEM;
 | 
									dwc, &dwc3_testmode_fops);
 | 
				
			||||||
		goto err1;
 | 
							if (!file) {
 | 
				
			||||||
	}
 | 
								ret = -ENOMEM;
 | 
				
			||||||
 | 
								goto err1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
 | 
							file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
 | 
				
			||||||
			dwc, &dwc3_link_state_fops);
 | 
									dwc, &dwc3_link_state_fops);
 | 
				
			||||||
	if (!file) {
 | 
							if (!file) {
 | 
				
			||||||
		ret = -ENOMEM;
 | 
								ret = -ENOMEM;
 | 
				
			||||||
		goto err1;
 | 
								goto err1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,9 +22,9 @@
 | 
				
			||||||
#include <linux/usb/otg.h>
 | 
					#include <linux/usb/otg.h>
 | 
				
			||||||
#include <linux/usb/nop-usb-xceiv.h>
 | 
					#include <linux/usb/nop-usb-xceiv.h>
 | 
				
			||||||
#include <linux/of.h>
 | 
					#include <linux/of.h>
 | 
				
			||||||
 | 
					#include <linux/of_platform.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct dwc3_exynos {
 | 
					struct dwc3_exynos {
 | 
				
			||||||
	struct platform_device	*dwc3;
 | 
					 | 
				
			||||||
	struct platform_device	*usb2_phy;
 | 
						struct platform_device	*usb2_phy;
 | 
				
			||||||
	struct platform_device	*usb3_phy;
 | 
						struct platform_device	*usb3_phy;
 | 
				
			||||||
	struct device		*dev;
 | 
						struct device		*dev;
 | 
				
			||||||
| 
						 | 
					@ -86,21 +86,30 @@ err1:
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dwc3_exynos_remove_child(struct device *dev, void *unused)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct platform_device *pdev = to_platform_device(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						platform_device_unregister(pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
 | 
					static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dwc3_exynos_probe(struct platform_device *pdev)
 | 
					static int dwc3_exynos_probe(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct platform_device	*dwc3;
 | 
					 | 
				
			||||||
	struct dwc3_exynos	*exynos;
 | 
						struct dwc3_exynos	*exynos;
 | 
				
			||||||
	struct clk		*clk;
 | 
						struct clk		*clk;
 | 
				
			||||||
	struct device		*dev = &pdev->dev;
 | 
						struct device		*dev = &pdev->dev;
 | 
				
			||||||
 | 
						struct device_node	*node = dev->of_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int			ret = -ENOMEM;
 | 
						int			ret = -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
 | 
						exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
 | 
				
			||||||
	if (!exynos) {
 | 
						if (!exynos) {
 | 
				
			||||||
		dev_err(dev, "not enough memory\n");
 | 
							dev_err(dev, "not enough memory\n");
 | 
				
			||||||
		return -ENOMEM;
 | 
							goto err1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -108,21 +117,15 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
 | 
				
			||||||
	 * Since shared usb code relies on it, set it here for now.
 | 
						 * Since shared usb code relies on it, set it here for now.
 | 
				
			||||||
	 * Once we move to full device tree support this will vanish off.
 | 
						 * Once we move to full device tree support this will vanish off.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (!pdev->dev.dma_mask)
 | 
						if (!dev->dma_mask)
 | 
				
			||||||
		pdev->dev.dma_mask = &dwc3_exynos_dma_mask;
 | 
							dev->dma_mask = &dwc3_exynos_dma_mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	platform_set_drvdata(pdev, exynos);
 | 
						platform_set_drvdata(pdev, exynos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = dwc3_exynos_register_phys(exynos);
 | 
						ret = dwc3_exynos_register_phys(exynos);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		dev_err(dev, "couldn't register PHYs\n");
 | 
							dev_err(dev, "couldn't register PHYs\n");
 | 
				
			||||||
		return ret;
 | 
							goto err1;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
 | 
					 | 
				
			||||||
	if (!dwc3) {
 | 
					 | 
				
			||||||
		dev_err(dev, "couldn't allocate dwc3 device\n");
 | 
					 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clk = devm_clk_get(dev, "usbdrd30");
 | 
						clk = devm_clk_get(dev, "usbdrd30");
 | 
				
			||||||
| 
						 | 
					@ -132,37 +135,28 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
 | 
				
			||||||
		goto err1;
 | 
							goto err1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dwc3->dev.parent = dev;
 | 
					 | 
				
			||||||
	dwc3->dev.dma_mask = dev->dma_mask;
 | 
					 | 
				
			||||||
	dwc3->dev.dma_parms = dev->dma_parms;
 | 
					 | 
				
			||||||
	exynos->dwc3	= dwc3;
 | 
					 | 
				
			||||||
	exynos->dev	= dev;
 | 
						exynos->dev	= dev;
 | 
				
			||||||
	exynos->clk	= clk;
 | 
						exynos->clk	= clk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clk_enable(exynos->clk);
 | 
						clk_prepare_enable(exynos->clk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = platform_device_add_resources(dwc3, pdev->resource,
 | 
						if (node) {
 | 
				
			||||||
			pdev->num_resources);
 | 
							ret = of_platform_populate(node, NULL, NULL, dev);
 | 
				
			||||||
	if (ret) {
 | 
							if (ret) {
 | 
				
			||||||
		dev_err(dev, "couldn't add resources to dwc3 device\n");
 | 
								dev_err(dev, "failed to add dwc3 core\n");
 | 
				
			||||||
		goto err2;
 | 
								goto err2;
 | 
				
			||||||
	}
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
	ret = platform_device_add(dwc3);
 | 
							dev_err(dev, "no device node, failed to add dwc3 core\n");
 | 
				
			||||||
	if (ret) {
 | 
							ret = -ENODEV;
 | 
				
			||||||
		dev_err(dev, "failed to register dwc3 device\n");
 | 
					 | 
				
			||||||
		goto err2;
 | 
							goto err2;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err2:
 | 
					err2:
 | 
				
			||||||
	clk_disable(clk);
 | 
						clk_disable_unprepare(clk);
 | 
				
			||||||
err1:
 | 
					err1:
 | 
				
			||||||
	platform_device_put(dwc3);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -170,11 +164,11 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dwc3_exynos	*exynos = platform_get_drvdata(pdev);
 | 
						struct dwc3_exynos	*exynos = platform_get_drvdata(pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	platform_device_unregister(exynos->dwc3);
 | 
					 | 
				
			||||||
	platform_device_unregister(exynos->usb2_phy);
 | 
						platform_device_unregister(exynos->usb2_phy);
 | 
				
			||||||
	platform_device_unregister(exynos->usb3_phy);
 | 
						platform_device_unregister(exynos->usb3_phy);
 | 
				
			||||||
 | 
						device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clk_disable(exynos->clk);
 | 
						clk_disable_unprepare(exynos->clk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -187,12 +181,46 @@ static const struct of_device_id exynos_dwc3_match[] = {
 | 
				
			||||||
MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
 | 
					MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_PM_SLEEP
 | 
				
			||||||
 | 
					static int dwc3_exynos_suspend(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dwc3_exynos *exynos = dev_get_drvdata(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clk_disable(exynos->clk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dwc3_exynos_resume(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dwc3_exynos *exynos = dev_get_drvdata(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clk_enable(exynos->clk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* runtime set active to reflect active state. */
 | 
				
			||||||
 | 
						pm_runtime_disable(dev);
 | 
				
			||||||
 | 
						pm_runtime_set_active(dev);
 | 
				
			||||||
 | 
						pm_runtime_enable(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct dev_pm_ops dwc3_exynos_dev_pm_ops = {
 | 
				
			||||||
 | 
						SET_SYSTEM_SLEEP_PM_OPS(dwc3_exynos_suspend, dwc3_exynos_resume)
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DEV_PM_OPS	(&dwc3_exynos_dev_pm_ops)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define DEV_PM_OPS	NULL
 | 
				
			||||||
 | 
					#endif /* CONFIG_PM_SLEEP */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct platform_driver dwc3_exynos_driver = {
 | 
					static struct platform_driver dwc3_exynos_driver = {
 | 
				
			||||||
	.probe		= dwc3_exynos_probe,
 | 
						.probe		= dwc3_exynos_probe,
 | 
				
			||||||
	.remove		= dwc3_exynos_remove,
 | 
						.remove		= dwc3_exynos_remove,
 | 
				
			||||||
	.driver		= {
 | 
						.driver		= {
 | 
				
			||||||
		.name	= "exynos-dwc3",
 | 
							.name	= "exynos-dwc3",
 | 
				
			||||||
		.of_match_table = of_match_ptr(exynos_dwc3_match),
 | 
							.of_match_table = of_match_ptr(exynos_dwc3_match),
 | 
				
			||||||
 | 
							.pm	= DEV_PM_OPS,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,7 +52,6 @@
 | 
				
			||||||
#include <linux/of_platform.h>
 | 
					#include <linux/of_platform.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/usb/otg.h>
 | 
					#include <linux/usb/otg.h>
 | 
				
			||||||
#include <linux/usb/nop-usb-xceiv.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * All these registers belong to OMAP's Wrapper around the
 | 
					 * All these registers belong to OMAP's Wrapper around the
 | 
				
			||||||
| 
						 | 
					@ -117,20 +116,17 @@ struct dwc3_omap {
 | 
				
			||||||
	/* device lock */
 | 
						/* device lock */
 | 
				
			||||||
	spinlock_t		lock;
 | 
						spinlock_t		lock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct platform_device	*usb2_phy;
 | 
					 | 
				
			||||||
	struct platform_device	*usb3_phy;
 | 
					 | 
				
			||||||
	struct device		*dev;
 | 
						struct device		*dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int			irq;
 | 
						int			irq;
 | 
				
			||||||
	void __iomem		*base;
 | 
						void __iomem		*base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void			*context;
 | 
						u32			utmi_otg_status;
 | 
				
			||||||
	u32			resource_size;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u32			dma_status:1;
 | 
						u32			dma_status:1;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct dwc3_omap		*_omap;
 | 
					static struct dwc3_omap		*_omap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
 | 
					static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -142,11 +138,14 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
 | 
				
			||||||
	writel(value, base + offset);
 | 
						writel(value, base + offset);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
 | 
					int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32			val;
 | 
						u32			val;
 | 
				
			||||||
	struct dwc3_omap	*omap = _omap;
 | 
						struct dwc3_omap	*omap = _omap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!omap)
 | 
				
			||||||
 | 
							return -EPROBE_DEFER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (status) {
 | 
						switch (status) {
 | 
				
			||||||
	case OMAP_DWC3_ID_GROUND:
 | 
						case OMAP_DWC3_ID_GROUND:
 | 
				
			||||||
		dev_dbg(omap->dev, "ID GND\n");
 | 
							dev_dbg(omap->dev, "ID GND\n");
 | 
				
			||||||
| 
						 | 
					@ -189,64 +188,10 @@ void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
 | 
				
			||||||
		dev_dbg(omap->dev, "ID float\n");
 | 
							dev_dbg(omap->dev, "ID float\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
 | 
					EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dwc3_omap_register_phys(struct dwc3_omap *omap)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct nop_usb_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);
 | 
					 | 
				
			||||||
	if (!pdev)
 | 
					 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	omap->usb2_phy = pdev;
 | 
					 | 
				
			||||||
	pdata.type = USB_PHY_TYPE_USB2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = platform_device_add_data(omap->usb2_phy, &pdata, sizeof(pdata));
 | 
					 | 
				
			||||||
	if (ret)
 | 
					 | 
				
			||||||
		goto err1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
 | 
					 | 
				
			||||||
	if (!pdev) {
 | 
					 | 
				
			||||||
		ret = -ENOMEM;
 | 
					 | 
				
			||||||
		goto err1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	omap->usb3_phy = pdev;
 | 
					 | 
				
			||||||
	pdata.type = USB_PHY_TYPE_USB3;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = platform_device_add_data(omap->usb3_phy, &pdata, sizeof(pdata));
 | 
					 | 
				
			||||||
	if (ret)
 | 
					 | 
				
			||||||
		goto err2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = platform_device_add(omap->usb2_phy);
 | 
					 | 
				
			||||||
	if (ret)
 | 
					 | 
				
			||||||
		goto err2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = platform_device_add(omap->usb3_phy);
 | 
					 | 
				
			||||||
	if (ret)
 | 
					 | 
				
			||||||
		goto err3;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
err3:
 | 
					 | 
				
			||||||
	platform_device_del(omap->usb2_phy);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
err2:
 | 
					 | 
				
			||||||
	platform_device_put(omap->usb3_phy);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
err1:
 | 
					 | 
				
			||||||
	platform_device_put(omap->usb2_phy);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
 | 
					static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dwc3_omap	*omap = _omap;
 | 
						struct dwc3_omap	*omap = _omap;
 | 
				
			||||||
| 
						 | 
					@ -307,121 +252,10 @@ static int dwc3_omap_remove_core(struct device *dev, void *c)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dwc3_omap_probe(struct platform_device *pdev)
 | 
					static void dwc3_omap_enable_irqs(struct dwc3_omap *omap)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dwc3_omap_data	*pdata = pdev->dev.platform_data;
 | 
					 | 
				
			||||||
	struct device_node	*node = pdev->dev.of_node;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct dwc3_omap	*omap;
 | 
					 | 
				
			||||||
	struct resource		*res;
 | 
					 | 
				
			||||||
	struct device		*dev = &pdev->dev;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int			size;
 | 
					 | 
				
			||||||
	int			ret = -ENOMEM;
 | 
					 | 
				
			||||||
	int			irq;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const u32		*utmi_mode;
 | 
					 | 
				
			||||||
	u32			reg;
 | 
						u32			reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void __iomem		*base;
 | 
					 | 
				
			||||||
	void			*context;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
 | 
					 | 
				
			||||||
	if (!omap) {
 | 
					 | 
				
			||||||
		dev_err(dev, "not enough memory\n");
 | 
					 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	platform_set_drvdata(pdev, omap);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	irq = platform_get_irq(pdev, 1);
 | 
					 | 
				
			||||||
	if (irq < 0) {
 | 
					 | 
				
			||||||
		dev_err(dev, "missing IRQ resource\n");
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 | 
					 | 
				
			||||||
	if (!res) {
 | 
					 | 
				
			||||||
		dev_err(dev, "missing memory base resource\n");
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	base = devm_ioremap_nocache(dev, res->start, resource_size(res));
 | 
					 | 
				
			||||||
	if (!base) {
 | 
					 | 
				
			||||||
		dev_err(dev, "ioremap failed\n");
 | 
					 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = dwc3_omap_register_phys(omap);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		dev_err(dev, "couldn't register PHYs\n");
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL);
 | 
					 | 
				
			||||||
	if (!context) {
 | 
					 | 
				
			||||||
		dev_err(dev, "couldn't allocate dwc3 context memory\n");
 | 
					 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	spin_lock_init(&omap->lock);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	omap->resource_size = resource_size(res);
 | 
					 | 
				
			||||||
	omap->context	= context;
 | 
					 | 
				
			||||||
	omap->dev	= dev;
 | 
					 | 
				
			||||||
	omap->irq	= irq;
 | 
					 | 
				
			||||||
	omap->base	= base;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * REVISIT if we ever have two instances of the wrapper, we will be
 | 
					 | 
				
			||||||
	 * in big trouble
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	_omap	= omap;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pm_runtime_enable(dev);
 | 
					 | 
				
			||||||
	ret = pm_runtime_get_sync(dev);
 | 
					 | 
				
			||||||
	if (ret < 0) {
 | 
					 | 
				
			||||||
		dev_err(dev, "get_sync failed with err %d\n", ret);
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	utmi_mode = of_get_property(node, "utmi-mode", &size);
 | 
					 | 
				
			||||||
	if (utmi_mode && size == sizeof(*utmi_mode)) {
 | 
					 | 
				
			||||||
		reg |= *utmi_mode;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		if (!pdata) {
 | 
					 | 
				
			||||||
			dev_dbg(dev, "missing platform data\n");
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			switch (pdata->utmi_mode) {
 | 
					 | 
				
			||||||
			case DWC3_OMAP_UTMI_MODE_SW:
 | 
					 | 
				
			||||||
				reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case DWC3_OMAP_UTMI_MODE_HW:
 | 
					 | 
				
			||||||
				reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				dev_dbg(dev, "UNKNOWN utmi mode %d\n",
 | 
					 | 
				
			||||||
						pdata->utmi_mode);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* check the DMA Status */
 | 
					 | 
				
			||||||
	reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
 | 
					 | 
				
			||||||
	omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0,
 | 
					 | 
				
			||||||
			"dwc3-omap", omap);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		dev_err(dev, "failed to request IRQ #%d --> %d\n",
 | 
					 | 
				
			||||||
				omap->irq, ret);
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* enable all IRQs */
 | 
						/* enable all IRQs */
 | 
				
			||||||
	reg = USBOTGSS_IRQO_COREIRQ_ST;
 | 
						reg = USBOTGSS_IRQO_COREIRQ_ST;
 | 
				
			||||||
	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
 | 
						dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
 | 
				
			||||||
| 
						 | 
					@ -437,14 +271,120 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 | 
				
			||||||
			USBOTGSS_IRQ1_IDPULLUP_FALL);
 | 
								USBOTGSS_IRQ1_IDPULLUP_FALL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
 | 
						dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (node) {
 | 
					static void dwc3_omap_disable_irqs(struct dwc3_omap *omap)
 | 
				
			||||||
		ret = of_platform_populate(node, NULL, NULL, dev);
 | 
					{
 | 
				
			||||||
		if (ret) {
 | 
						/* disable all IRQs */
 | 
				
			||||||
			dev_err(&pdev->dev,
 | 
						dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, 0x00);
 | 
				
			||||||
				"failed to add create dwc3 core\n");
 | 
						dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, 0x00);
 | 
				
			||||||
			return ret;
 | 
					}
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
					static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dwc3_omap_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct device_node	*node = pdev->dev.of_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct dwc3_omap	*omap;
 | 
				
			||||||
 | 
						struct resource		*res;
 | 
				
			||||||
 | 
						struct device		*dev = &pdev->dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int			ret = -ENOMEM;
 | 
				
			||||||
 | 
						int			irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int			utmi_mode = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						u32			reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void __iomem		*base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!node) {
 | 
				
			||||||
 | 
							dev_err(dev, "device node not found\n");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!omap) {
 | 
				
			||||||
 | 
							dev_err(dev, "not enough memory\n");
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						platform_set_drvdata(pdev, omap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						irq = platform_get_irq(pdev, 0);
 | 
				
			||||||
 | 
						if (irq < 0) {
 | 
				
			||||||
 | 
							dev_err(dev, "missing IRQ resource\n");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 | 
				
			||||||
 | 
						if (!res) {
 | 
				
			||||||
 | 
							dev_err(dev, "missing memory base resource\n");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						base = devm_ioremap_nocache(dev, res->start, resource_size(res));
 | 
				
			||||||
 | 
						if (!base) {
 | 
				
			||||||
 | 
							dev_err(dev, "ioremap failed\n");
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_init(&omap->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						omap->dev	= dev;
 | 
				
			||||||
 | 
						omap->irq	= irq;
 | 
				
			||||||
 | 
						omap->base	= base;
 | 
				
			||||||
 | 
						dev->dma_mask	= &dwc3_omap_dma_mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * REVISIT if we ever have two instances of the wrapper, we will be
 | 
				
			||||||
 | 
						 * in big trouble
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						_omap	= omap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pm_runtime_enable(dev);
 | 
				
			||||||
 | 
						ret = pm_runtime_get_sync(dev);
 | 
				
			||||||
 | 
						if (ret < 0) {
 | 
				
			||||||
 | 
							dev_err(dev, "get_sync failed with err %d\n", ret);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						of_property_read_u32(node, "utmi-mode", &utmi_mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (utmi_mode) {
 | 
				
			||||||
 | 
						case DWC3_OMAP_UTMI_MODE_SW:
 | 
				
			||||||
 | 
							reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case DWC3_OMAP_UTMI_MODE_HW:
 | 
				
			||||||
 | 
							reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* check the DMA Status */
 | 
				
			||||||
 | 
						reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
 | 
				
			||||||
 | 
						omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0,
 | 
				
			||||||
 | 
								"dwc3-omap", omap);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dev, "failed to request IRQ #%d --> %d\n",
 | 
				
			||||||
 | 
									omap->irq, ret);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dwc3_omap_enable_irqs(omap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = of_platform_populate(node, NULL, NULL, dev);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(&pdev->dev, "failed to create dwc3 core\n");
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -454,8 +394,7 @@ static int dwc3_omap_remove(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dwc3_omap	*omap = platform_get_drvdata(pdev);
 | 
						struct dwc3_omap	*omap = platform_get_drvdata(pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	platform_device_unregister(omap->usb2_phy);
 | 
						dwc3_omap_disable_irqs(omap);
 | 
				
			||||||
	platform_device_unregister(omap->usb3_phy);
 | 
					 | 
				
			||||||
	pm_runtime_put_sync(&pdev->dev);
 | 
						pm_runtime_put_sync(&pdev->dev);
 | 
				
			||||||
	pm_runtime_disable(&pdev->dev);
 | 
						pm_runtime_disable(&pdev->dev);
 | 
				
			||||||
	device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
 | 
						device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
 | 
				
			||||||
| 
						 | 
					@ -465,18 +404,72 @@ static int dwc3_omap_remove(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct of_device_id of_dwc3_match[] = {
 | 
					static const struct of_device_id of_dwc3_match[] = {
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		"ti,dwc3",
 | 
							.compatible =	"ti,dwc3"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	{ },
 | 
						{ },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
MODULE_DEVICE_TABLE(of, of_dwc3_match);
 | 
					MODULE_DEVICE_TABLE(of, of_dwc3_match);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_PM_SLEEP
 | 
				
			||||||
 | 
					static int dwc3_omap_prepare(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dwc3_omap	*omap = dev_get_drvdata(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dwc3_omap_disable_irqs(omap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void dwc3_omap_complete(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dwc3_omap	*omap = dev_get_drvdata(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dwc3_omap_enable_irqs(omap);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dwc3_omap_suspend(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dwc3_omap	*omap = dev_get_drvdata(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						omap->utmi_otg_status = dwc3_omap_readl(omap->base,
 | 
				
			||||||
 | 
								USBOTGSS_UTMI_OTG_STATUS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dwc3_omap_resume(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dwc3_omap	*omap = dev_get_drvdata(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS,
 | 
				
			||||||
 | 
								omap->utmi_otg_status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pm_runtime_disable(dev);
 | 
				
			||||||
 | 
						pm_runtime_set_active(dev);
 | 
				
			||||||
 | 
						pm_runtime_enable(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {
 | 
				
			||||||
 | 
						.prepare	= dwc3_omap_prepare,
 | 
				
			||||||
 | 
						.complete	= dwc3_omap_complete,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume)
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DEV_PM_OPS	(&dwc3_omap_dev_pm_ops)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define DEV_PM_OPS	NULL
 | 
				
			||||||
 | 
					#endif /* CONFIG_PM_SLEEP */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct platform_driver dwc3_omap_driver = {
 | 
					static struct platform_driver dwc3_omap_driver = {
 | 
				
			||||||
	.probe		= dwc3_omap_probe,
 | 
						.probe		= dwc3_omap_probe,
 | 
				
			||||||
	.remove		= dwc3_omap_remove,
 | 
						.remove		= dwc3_omap_remove,
 | 
				
			||||||
	.driver		= {
 | 
						.driver		= {
 | 
				
			||||||
		.name	= "omap-dwc3",
 | 
							.name	= "omap-dwc3",
 | 
				
			||||||
		.of_match_table	= of_dwc3_match,
 | 
							.of_match_table	= of_dwc3_match,
 | 
				
			||||||
 | 
							.pm	= DEV_PM_OPS,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,11 +212,49 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
 | 
					MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_PM
 | 
				
			||||||
 | 
					static int dwc3_pci_suspend(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct pci_dev	*pci = to_pci_dev(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pci_disable_device(pci);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dwc3_pci_resume(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct pci_dev	*pci = to_pci_dev(dev);
 | 
				
			||||||
 | 
						int		ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = pci_enable_device(pci);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dev, "can't re-enable device --> %d\n", ret);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pci_set_master(pci);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 = {
 | 
					static struct pci_driver dwc3_pci_driver = {
 | 
				
			||||||
	.name		= "dwc3-pci",
 | 
						.name		= "dwc3-pci",
 | 
				
			||||||
	.id_table	= dwc3_pci_id_table,
 | 
						.id_table	= dwc3_pci_id_table,
 | 
				
			||||||
	.probe		= dwc3_pci_probe,
 | 
						.probe		= dwc3_pci_probe,
 | 
				
			||||||
	.remove		= dwc3_pci_remove,
 | 
						.remove		= dwc3_pci_remove,
 | 
				
			||||||
 | 
						.driver		= {
 | 
				
			||||||
 | 
							.pm	= DEV_PM_OPS,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 | 
					MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -394,10 +394,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 | 
				
			||||||
	u32			wIndex;
 | 
						u32			wIndex;
 | 
				
			||||||
	u32			reg;
 | 
						u32			reg;
 | 
				
			||||||
	int			ret;
 | 
						int			ret;
 | 
				
			||||||
 | 
						enum usb_device_state	state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wValue = le16_to_cpu(ctrl->wValue);
 | 
						wValue = le16_to_cpu(ctrl->wValue);
 | 
				
			||||||
	wIndex = le16_to_cpu(ctrl->wIndex);
 | 
						wIndex = le16_to_cpu(ctrl->wIndex);
 | 
				
			||||||
	recip = ctrl->bRequestType & USB_RECIP_MASK;
 | 
						recip = ctrl->bRequestType & USB_RECIP_MASK;
 | 
				
			||||||
 | 
						state = dwc->gadget.state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (recip) {
 | 
						switch (recip) {
 | 
				
			||||||
	case USB_RECIP_DEVICE:
 | 
						case USB_RECIP_DEVICE:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -409,7 +412,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 | 
				
			||||||
		 * default control pipe
 | 
							 * default control pipe
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		case USB_DEVICE_U1_ENABLE:
 | 
							case USB_DEVICE_U1_ENABLE:
 | 
				
			||||||
			if (dwc->dev_state != DWC3_CONFIGURED_STATE)
 | 
								if (state != USB_STATE_CONFIGURED)
 | 
				
			||||||
				return -EINVAL;
 | 
									return -EINVAL;
 | 
				
			||||||
			if (dwc->speed != DWC3_DSTS_SUPERSPEED)
 | 
								if (dwc->speed != DWC3_DSTS_SUPERSPEED)
 | 
				
			||||||
				return -EINVAL;
 | 
									return -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -423,7 +426,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case USB_DEVICE_U2_ENABLE:
 | 
							case USB_DEVICE_U2_ENABLE:
 | 
				
			||||||
			if (dwc->dev_state != DWC3_CONFIGURED_STATE)
 | 
								if (state != USB_STATE_CONFIGURED)
 | 
				
			||||||
				return -EINVAL;
 | 
									return -EINVAL;
 | 
				
			||||||
			if (dwc->speed != DWC3_DSTS_SUPERSPEED)
 | 
								if (dwc->speed != DWC3_DSTS_SUPERSPEED)
 | 
				
			||||||
				return -EINVAL;
 | 
									return -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -493,6 +496,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 | 
					static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						enum usb_device_state state = dwc->gadget.state;
 | 
				
			||||||
	u32 addr;
 | 
						u32 addr;
 | 
				
			||||||
	u32 reg;
 | 
						u32 reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -502,7 +506,7 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dwc->dev_state == DWC3_CONFIGURED_STATE) {
 | 
						if (state == USB_STATE_CONFIGURED) {
 | 
				
			||||||
		dev_dbg(dwc->dev, "trying to set address when configured\n");
 | 
							dev_dbg(dwc->dev, "trying to set address when configured\n");
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -513,9 +517,9 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 | 
				
			||||||
	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 | 
						dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (addr)
 | 
						if (addr)
 | 
				
			||||||
		dwc->dev_state = DWC3_ADDRESS_STATE;
 | 
							usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		dwc->dev_state = DWC3_DEFAULT_STATE;
 | 
							usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -532,6 +536,7 @@ static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 | 
					static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						enum usb_device_state state = dwc->gadget.state;
 | 
				
			||||||
	u32 cfg;
 | 
						u32 cfg;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	u32 reg;
 | 
						u32 reg;
 | 
				
			||||||
| 
						 | 
					@ -539,16 +544,18 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 | 
				
			||||||
	dwc->start_config_issued = false;
 | 
						dwc->start_config_issued = false;
 | 
				
			||||||
	cfg = le16_to_cpu(ctrl->wValue);
 | 
						cfg = le16_to_cpu(ctrl->wValue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (dwc->dev_state) {
 | 
						switch (state) {
 | 
				
			||||||
	case DWC3_DEFAULT_STATE:
 | 
						case USB_STATE_DEFAULT:
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case DWC3_ADDRESS_STATE:
 | 
						case USB_STATE_ADDRESS:
 | 
				
			||||||
		ret = dwc3_ep0_delegate_req(dwc, ctrl);
 | 
							ret = dwc3_ep0_delegate_req(dwc, ctrl);
 | 
				
			||||||
		/* if the cfg matches and the cfg is non zero */
 | 
							/* if the cfg matches and the cfg is non zero */
 | 
				
			||||||
		if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
 | 
							if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
 | 
				
			||||||
			dwc->dev_state = DWC3_CONFIGURED_STATE;
 | 
								usb_gadget_set_state(&dwc->gadget,
 | 
				
			||||||
 | 
										USB_STATE_CONFIGURED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
			 * Enable transition to U1/U2 state when
 | 
								 * Enable transition to U1/U2 state when
 | 
				
			||||||
			 * nothing is pending from application.
 | 
								 * nothing is pending from application.
 | 
				
			||||||
| 
						 | 
					@ -562,10 +569,11 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case DWC3_CONFIGURED_STATE:
 | 
						case USB_STATE_CONFIGURED:
 | 
				
			||||||
		ret = dwc3_ep0_delegate_req(dwc, ctrl);
 | 
							ret = dwc3_ep0_delegate_req(dwc, ctrl);
 | 
				
			||||||
		if (!cfg)
 | 
							if (!cfg)
 | 
				
			||||||
			dwc->dev_state = DWC3_ADDRESS_STATE;
 | 
								usb_gadget_set_state(&dwc->gadget,
 | 
				
			||||||
 | 
										USB_STATE_ADDRESS);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		ret = -EINVAL;
 | 
							ret = -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -620,10 +628,11 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req)
 | 
				
			||||||
static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 | 
					static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dwc3_ep	*dep;
 | 
						struct dwc3_ep	*dep;
 | 
				
			||||||
 | 
						enum usb_device_state state = dwc->gadget.state;
 | 
				
			||||||
	u16		wLength;
 | 
						u16		wLength;
 | 
				
			||||||
	u16		wValue;
 | 
						u16		wValue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dwc->dev_state == DWC3_DEFAULT_STATE)
 | 
						if (state == USB_STATE_DEFAULT)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wValue = le16_to_cpu(ctrl->wValue);
 | 
						wValue = le16_to_cpu(ctrl->wValue);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1425,8 +1425,10 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
 | 
				
			||||||
		if (dwc->revision >= DWC3_REVISION_194A)
 | 
							if (dwc->revision >= DWC3_REVISION_194A)
 | 
				
			||||||
			reg &= ~DWC3_DCTL_KEEP_CONNECT;
 | 
								reg &= ~DWC3_DCTL_KEEP_CONNECT;
 | 
				
			||||||
		reg |= DWC3_DCTL_RUN_STOP;
 | 
							reg |= DWC3_DCTL_RUN_STOP;
 | 
				
			||||||
 | 
							dwc->pullups_connected = true;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		reg &= ~DWC3_DCTL_RUN_STOP;
 | 
							reg &= ~DWC3_DCTL_RUN_STOP;
 | 
				
			||||||
 | 
							dwc->pullups_connected = false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 | 
						dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 | 
				
			||||||
| 
						 | 
					@ -1469,6 +1471,33 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void dwc3_gadget_enable_irq(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32			reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Enable all but Start and End of Frame IRQs */
 | 
				
			||||||
 | 
						reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
 | 
				
			||||||
 | 
								DWC3_DEVTEN_EVNTOVERFLOWEN |
 | 
				
			||||||
 | 
								DWC3_DEVTEN_CMDCMPLTEN |
 | 
				
			||||||
 | 
								DWC3_DEVTEN_ERRTICERREN |
 | 
				
			||||||
 | 
								DWC3_DEVTEN_WKUPEVTEN |
 | 
				
			||||||
 | 
								DWC3_DEVTEN_ULSTCNGEN |
 | 
				
			||||||
 | 
								DWC3_DEVTEN_CONNECTDONEEN |
 | 
				
			||||||
 | 
								DWC3_DEVTEN_USBRSTEN |
 | 
				
			||||||
 | 
								DWC3_DEVTEN_DISCONNEVTEN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void dwc3_gadget_disable_irq(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* mask all interrupts */
 | 
				
			||||||
 | 
						dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static irqreturn_t dwc3_interrupt(int irq, void *_dwc);
 | 
				
			||||||
 | 
					static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dwc3_gadget_start(struct usb_gadget *g,
 | 
					static int dwc3_gadget_start(struct usb_gadget *g,
 | 
				
			||||||
		struct usb_gadget_driver *driver)
 | 
							struct usb_gadget_driver *driver)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1476,6 +1505,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 | 
				
			||||||
	struct dwc3_ep		*dep;
 | 
						struct dwc3_ep		*dep;
 | 
				
			||||||
	unsigned long		flags;
 | 
						unsigned long		flags;
 | 
				
			||||||
	int			ret = 0;
 | 
						int			ret = 0;
 | 
				
			||||||
 | 
						int			irq;
 | 
				
			||||||
	u32			reg;
 | 
						u32			reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&dwc->lock, flags);
 | 
						spin_lock_irqsave(&dwc->lock, flags);
 | 
				
			||||||
| 
						 | 
					@ -1489,7 +1519,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dwc->gadget_driver	= driver;
 | 
						dwc->gadget_driver	= driver;
 | 
				
			||||||
	dwc->gadget.dev.driver	= &driver->driver;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
 | 
						reg = dwc3_readl(dwc->regs, DWC3_DCFG);
 | 
				
			||||||
	reg &= ~(DWC3_DCFG_SPEED_MASK);
 | 
						reg &= ~(DWC3_DCFG_SPEED_MASK);
 | 
				
			||||||
| 
						 | 
					@ -1536,6 +1565,17 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 | 
				
			||||||
	dwc->ep0state = EP0_SETUP_PHASE;
 | 
						dwc->ep0state = EP0_SETUP_PHASE;
 | 
				
			||||||
	dwc3_ep0_out_start(dwc);
 | 
						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);
 | 
						spin_unlock_irqrestore(&dwc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -1554,14 +1594,18 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dwc3		*dwc = gadget_to_dwc(g);
 | 
						struct dwc3		*dwc = gadget_to_dwc(g);
 | 
				
			||||||
	unsigned long		flags;
 | 
						unsigned long		flags;
 | 
				
			||||||
 | 
						int			irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&dwc->lock, flags);
 | 
						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[0]);
 | 
				
			||||||
	__dwc3_gadget_ep_disable(dwc->eps[1]);
 | 
						__dwc3_gadget_ep_disable(dwc->eps[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dwc->gadget_driver	= NULL;
 | 
						dwc->gadget_driver	= NULL;
 | 
				
			||||||
	dwc->gadget.dev.driver	= NULL;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_irqrestore(&dwc->lock, flags);
 | 
						spin_unlock_irqrestore(&dwc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1579,14 +1623,15 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* -------------------------------------------------------------------------- */
 | 
					/* -------------------------------------------------------------------------- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
 | 
					static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
 | 
				
			||||||
 | 
							u8 num, u32 direction)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dwc3_ep			*dep;
 | 
						struct dwc3_ep			*dep;
 | 
				
			||||||
	u8				epnum;
 | 
						u8				i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	INIT_LIST_HEAD(&dwc->gadget.ep_list);
 | 
						for (i = 0; i < num; i++) {
 | 
				
			||||||
 | 
							u8 epnum = (i << 1) | (!!direction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
 | 
					 | 
				
			||||||
		dep = kzalloc(sizeof(*dep), GFP_KERNEL);
 | 
							dep = kzalloc(sizeof(*dep), GFP_KERNEL);
 | 
				
			||||||
		if (!dep) {
 | 
							if (!dep) {
 | 
				
			||||||
			dev_err(dwc->dev, "can't allocate endpoint %d\n",
 | 
								dev_err(dwc->dev, "can't allocate endpoint %d\n",
 | 
				
			||||||
| 
						 | 
					@ -1600,6 +1645,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
 | 
							snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
 | 
				
			||||||
				(epnum & 1) ? "in" : "out");
 | 
									(epnum & 1) ? "in" : "out");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dep->endpoint.name = dep->name;
 | 
							dep->endpoint.name = dep->name;
 | 
				
			||||||
		dep->direction = (epnum & 1);
 | 
							dep->direction = (epnum & 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1630,6 +1676,27 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int				ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&dwc->gadget.ep_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_out_eps, 0);
 | 
				
			||||||
 | 
						if (ret < 0) {
 | 
				
			||||||
 | 
							dev_vdbg(dwc->dev, "failed to allocate OUT endpoints\n");
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_in_eps, 1);
 | 
				
			||||||
 | 
						if (ret < 0) {
 | 
				
			||||||
 | 
							dev_vdbg(dwc->dev, "failed to allocate IN endpoints\n");
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
 | 
					static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dwc3_ep			*dep;
 | 
						struct dwc3_ep			*dep;
 | 
				
			||||||
| 
						 | 
					@ -1637,6 +1704,9 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
 | 
						for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
 | 
				
			||||||
		dep = dwc->eps[epnum];
 | 
							dep = dwc->eps[epnum];
 | 
				
			||||||
 | 
							if (!dep)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dwc3_free_trb_pool(dep);
 | 
							dwc3_free_trb_pool(dep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (epnum != 0 && epnum != 1)
 | 
							if (epnum != 0 && epnum != 1)
 | 
				
			||||||
| 
						 | 
					@ -1646,12 +1716,8 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void dwc3_gadget_release(struct device *dev)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	dev_dbg(dev, "%s\n", __func__);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* -------------------------------------------------------------------------- */
 | 
					/* -------------------------------------------------------------------------- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
 | 
					static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
 | 
				
			||||||
		struct dwc3_request *req, struct dwc3_trb *trb,
 | 
							struct dwc3_request *req, struct dwc3_trb *trb,
 | 
				
			||||||
		const struct dwc3_event_depevt *event, int status)
 | 
							const struct dwc3_event_depevt *event, int status)
 | 
				
			||||||
| 
						 | 
					@ -1975,6 +2041,9 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
 | 
				
			||||||
		struct dwc3_ep *dep;
 | 
							struct dwc3_ep *dep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dep = dwc->eps[epnum];
 | 
							dep = dwc->eps[epnum];
 | 
				
			||||||
 | 
							if (!dep)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!(dep->flags & DWC3_EP_ENABLED))
 | 
							if (!(dep->flags & DWC3_EP_ENABLED))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1992,6 +2061,8 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
 | 
				
			||||||
		int ret;
 | 
							int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dep = dwc->eps[epnum];
 | 
							dep = dwc->eps[epnum];
 | 
				
			||||||
 | 
							if (!dep)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!(dep->flags & DWC3_EP_STALL))
 | 
							if (!(dep->flags & DWC3_EP_STALL))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
| 
						 | 
					@ -2091,7 +2162,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* after reset -> Default State */
 | 
						/* after reset -> Default State */
 | 
				
			||||||
	dwc->dev_state = DWC3_DEFAULT_STATE;
 | 
						usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Recent versions support automatic phy suspend and don't need this */
 | 
						/* Recent versions support automatic phy suspend and don't need this */
 | 
				
			||||||
	if (dwc->revision < DWC3_REVISION_194A) {
 | 
						if (dwc->revision < DWC3_REVISION_194A) {
 | 
				
			||||||
| 
						 | 
					@ -2277,6 +2348,34 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
 | 
				
			||||||
		unsigned int evtinfo)
 | 
							unsigned int evtinfo)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	enum dwc3_link_state	next = evtinfo & DWC3_LINK_STATE_MASK;
 | 
						enum dwc3_link_state	next = evtinfo & DWC3_LINK_STATE_MASK;
 | 
				
			||||||
 | 
						unsigned int		pwropt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * WORKAROUND: DWC3 < 2.50a have an issue when configured without
 | 
				
			||||||
 | 
						 * Hibernation mode enabled which would show up when device detects
 | 
				
			||||||
 | 
						 * host-initiated U3 exit.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * In that case, device will generate a Link State Change Interrupt
 | 
				
			||||||
 | 
						 * from U3 to RESUME which is only necessary if Hibernation is
 | 
				
			||||||
 | 
						 * configured in.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * There are no functional changes due to such spurious event and we
 | 
				
			||||||
 | 
						 * just need to ignore it.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Refers to:
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * STAR#9000570034 RTL: SS Resume event generated in non-Hibernation
 | 
				
			||||||
 | 
						 * operational mode
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						pwropt = DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1);
 | 
				
			||||||
 | 
						if ((dwc->revision < DWC3_REVISION_250A) &&
 | 
				
			||||||
 | 
								(pwropt != DWC3_GHWPARAMS1_EN_PWROPT_HIB)) {
 | 
				
			||||||
 | 
							if ((dwc->link_state == DWC3_LINK_STATE_U3) &&
 | 
				
			||||||
 | 
									(next == DWC3_LINK_STATE_RESUME)) {
 | 
				
			||||||
 | 
								dev_vdbg(dwc->dev, "ignoring transition U3 -> Resume\n");
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * WORKAROUND: DWC3 Revisions <1.83a have an issue which, depending
 | 
						 * WORKAROUND: DWC3 Revisions <1.83a have an issue which, depending
 | 
				
			||||||
| 
						 | 
					@ -2387,40 +2486,73 @@ static void dwc3_process_event_entry(struct dwc3 *dwc,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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++) {
 | 
				
			||||||
 | 
							struct dwc3_event_buffer *evt;
 | 
				
			||||||
 | 
							int			left;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							evt = dwc->ev_buffs[i];
 | 
				
			||||||
 | 
							left = evt->count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!(evt->flags & DWC3_EVENT_PENDING))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							while (left > 0) {
 | 
				
			||||||
 | 
								union dwc3_event event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								event.raw = *(u32 *) (evt->buf + evt->lpos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								dwc3_process_event_entry(dwc, &event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * 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_writel(dwc->regs, DWC3_GEVNTCOUNT(i), 4);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							evt->count = 0;
 | 
				
			||||||
 | 
							evt->flags &= ~DWC3_EVENT_PENDING;
 | 
				
			||||||
 | 
							ret = IRQ_HANDLED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&dwc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
 | 
					static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dwc3_event_buffer *evt;
 | 
						struct dwc3_event_buffer *evt;
 | 
				
			||||||
	int left;
 | 
					 | 
				
			||||||
	u32 count;
 | 
						u32 count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						evt = dwc->ev_buffs[buf];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf));
 | 
						count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf));
 | 
				
			||||||
	count &= DWC3_GEVNTCOUNT_MASK;
 | 
						count &= DWC3_GEVNTCOUNT_MASK;
 | 
				
			||||||
	if (!count)
 | 
						if (!count)
 | 
				
			||||||
		return IRQ_NONE;
 | 
							return IRQ_NONE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	evt = dwc->ev_buffs[buf];
 | 
						evt->count = count;
 | 
				
			||||||
	left = count;
 | 
						evt->flags |= DWC3_EVENT_PENDING;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (left > 0) {
 | 
						return IRQ_WAKE_THREAD;
 | 
				
			||||||
		union dwc3_event event;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		event.raw = *(u32 *) (evt->buf + evt->lpos);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		dwc3_process_event_entry(dwc, &event);
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * XXX 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 were 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_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return IRQ_HANDLED;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
 | 
					static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
 | 
				
			||||||
| 
						 | 
					@ -2435,7 +2567,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
 | 
				
			||||||
		irqreturn_t status;
 | 
							irqreturn_t status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		status = dwc3_process_event_buf(dwc, i);
 | 
							status = dwc3_process_event_buf(dwc, i);
 | 
				
			||||||
		if (status == IRQ_HANDLED)
 | 
							if (status == IRQ_WAKE_THREAD)
 | 
				
			||||||
			ret = status;
 | 
								ret = status;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2454,7 +2586,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32					reg;
 | 
						u32					reg;
 | 
				
			||||||
	int					ret;
 | 
						int					ret;
 | 
				
			||||||
	int					irq;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
 | 
						dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
 | 
				
			||||||
			&dwc->ctrl_req_addr, GFP_KERNEL);
 | 
								&dwc->ctrl_req_addr, GFP_KERNEL);
 | 
				
			||||||
| 
						 | 
					@ -2488,19 +2619,10 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 | 
				
			||||||
		goto err3;
 | 
							goto err3;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_set_name(&dwc->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dwc->gadget.ops			= &dwc3_gadget_ops;
 | 
						dwc->gadget.ops			= &dwc3_gadget_ops;
 | 
				
			||||||
	dwc->gadget.max_speed		= USB_SPEED_SUPER;
 | 
						dwc->gadget.max_speed		= USB_SPEED_SUPER;
 | 
				
			||||||
	dwc->gadget.speed		= USB_SPEED_UNKNOWN;
 | 
						dwc->gadget.speed		= USB_SPEED_UNKNOWN;
 | 
				
			||||||
	dwc->gadget.dev.parent		= dwc->dev;
 | 
					 | 
				
			||||||
	dwc->gadget.sg_supported	= true;
 | 
						dwc->gadget.sg_supported	= true;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dwc->gadget.dev.dma_parms	= dwc->dev->dma_parms;
 | 
					 | 
				
			||||||
	dwc->gadget.dev.dma_mask	= dwc->dev->dma_mask;
 | 
					 | 
				
			||||||
	dwc->gadget.dev.release		= dwc3_gadget_release;
 | 
					 | 
				
			||||||
	dwc->gadget.name		= "dwc3-gadget";
 | 
						dwc->gadget.name		= "dwc3-gadget";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -2512,60 +2634,24 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto err4;
 | 
							goto err4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED,
 | 
					 | 
				
			||||||
			"dwc3", dwc);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
 | 
					 | 
				
			||||||
				irq, ret);
 | 
					 | 
				
			||||||
		goto err5;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
 | 
						reg = dwc3_readl(dwc->regs, DWC3_DCFG);
 | 
				
			||||||
	reg |= DWC3_DCFG_LPM_CAP;
 | 
						reg |= DWC3_DCFG_LPM_CAP;
 | 
				
			||||||
	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 | 
						dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Enable all but Start and End of Frame IRQs */
 | 
						/* Enable USB2 LPM and automatic phy suspend only on recent versions */
 | 
				
			||||||
	reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
 | 
					 | 
				
			||||||
			DWC3_DEVTEN_EVNTOVERFLOWEN |
 | 
					 | 
				
			||||||
			DWC3_DEVTEN_CMDCMPLTEN |
 | 
					 | 
				
			||||||
			DWC3_DEVTEN_ERRTICERREN |
 | 
					 | 
				
			||||||
			DWC3_DEVTEN_WKUPEVTEN |
 | 
					 | 
				
			||||||
			DWC3_DEVTEN_ULSTCNGEN |
 | 
					 | 
				
			||||||
			DWC3_DEVTEN_CONNECTDONEEN |
 | 
					 | 
				
			||||||
			DWC3_DEVTEN_USBRSTEN |
 | 
					 | 
				
			||||||
			DWC3_DEVTEN_DISCONNEVTEN);
 | 
					 | 
				
			||||||
	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* automatic phy suspend only on recent versions */
 | 
					 | 
				
			||||||
	if (dwc->revision >= DWC3_REVISION_194A) {
 | 
						if (dwc->revision >= DWC3_REVISION_194A) {
 | 
				
			||||||
		dwc3_gadget_usb2_phy_suspend(dwc, false);
 | 
							dwc3_gadget_usb2_phy_suspend(dwc, false);
 | 
				
			||||||
		dwc3_gadget_usb3_phy_suspend(dwc, false);
 | 
							dwc3_gadget_usb3_phy_suspend(dwc, false);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = device_register(&dwc->gadget.dev);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		dev_err(dwc->dev, "failed to register gadget device\n");
 | 
					 | 
				
			||||||
		put_device(&dwc->gadget.dev);
 | 
					 | 
				
			||||||
		goto err6;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
 | 
						ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		dev_err(dwc->dev, "failed to register udc\n");
 | 
							dev_err(dwc->dev, "failed to register udc\n");
 | 
				
			||||||
		goto err7;
 | 
							goto err5;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err7:
 | 
					 | 
				
			||||||
	device_unregister(&dwc->gadget.dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
err6:
 | 
					 | 
				
			||||||
	dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
 | 
					 | 
				
			||||||
	free_irq(irq, dwc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
err5:
 | 
					err5:
 | 
				
			||||||
	dwc3_gadget_free_endpoints(dwc);
 | 
						dwc3_gadget_free_endpoints(dwc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2588,15 +2674,11 @@ err0:
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* -------------------------------------------------------------------------- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void dwc3_gadget_exit(struct dwc3 *dwc)
 | 
					void dwc3_gadget_exit(struct dwc3 *dwc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int			irq;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	usb_del_gadget_udc(&dwc->gadget);
 | 
						usb_del_gadget_udc(&dwc->gadget);
 | 
				
			||||||
	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
 | 
					 | 
				
			||||||
	free_irq(irq, dwc);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dwc3_gadget_free_endpoints(dwc);
 | 
						dwc3_gadget_free_endpoints(dwc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2610,6 +2692,63 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
 | 
						dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
 | 
				
			||||||
			dwc->ctrl_req, dwc->ctrl_req_addr);
 | 
								dwc->ctrl_req, dwc->ctrl_req_addr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
	device_unregister(&dwc->gadget.dev);
 | 
					
 | 
				
			||||||
 | 
					int dwc3_gadget_prepare(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (dwc->pullups_connected)
 | 
				
			||||||
 | 
							dwc3_gadget_disable_irq(dwc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void dwc3_gadget_complete(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (dwc->pullups_connected) {
 | 
				
			||||||
 | 
							dwc3_gadget_enable_irq(dwc);
 | 
				
			||||||
 | 
							dwc3_gadget_run_stop(dwc, true);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int dwc3_gadget_suspend(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__dwc3_gadget_ep_disable(dwc->eps[0]);
 | 
				
			||||||
 | 
						__dwc3_gadget_ep_disable(dwc->eps[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dwc->dcfg = dwc3_readl(dwc->regs, DWC3_DCFG);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int dwc3_gadget_resume(struct dwc3 *dwc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dwc3_ep		*dep;
 | 
				
			||||||
 | 
						int			ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Start with SuperSpeed Default */
 | 
				
			||||||
 | 
						dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dep = dwc->eps[0];
 | 
				
			||||||
 | 
						ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							goto err0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dep = dwc->eps[1];
 | 
				
			||||||
 | 
						ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							goto err1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* begin to receive SETUP packets */
 | 
				
			||||||
 | 
						dwc->ep0state = EP0_SETUP_PHASE;
 | 
				
			||||||
 | 
						dwc3_ep0_out_start(dwc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dwc3_writel(dwc->regs, DWC3_DCFG, dwc->dcfg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err1:
 | 
				
			||||||
 | 
						__dwc3_gadget_ep_disable(dwc->eps[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err0:
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -196,7 +196,6 @@ config USB_OMAP
 | 
				
			||||||
	tristate "OMAP USB Device Controller"
 | 
						tristate "OMAP USB Device Controller"
 | 
				
			||||||
	depends on ARCH_OMAP1
 | 
						depends on ARCH_OMAP1
 | 
				
			||||||
	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
 | 
						select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
 | 
				
			||||||
	select USB_OTG_UTILS if ARCH_OMAP
 | 
					 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	   Many Texas Instruments OMAP processors have flexible full
 | 
						   Many Texas Instruments OMAP processors have flexible full
 | 
				
			||||||
	   speed USB device controllers, with support for up to 30
 | 
						   speed USB device controllers, with support for up to 30
 | 
				
			||||||
| 
						 | 
					@ -211,7 +210,6 @@ config USB_OMAP
 | 
				
			||||||
config USB_PXA25X
 | 
					config USB_PXA25X
 | 
				
			||||||
	tristate "PXA 25x or IXP 4xx"
 | 
						tristate "PXA 25x or IXP 4xx"
 | 
				
			||||||
	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
 | 
						depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
 | 
				
			||||||
	select USB_OTG_UTILS
 | 
					 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	   Intel's PXA 25x series XScale ARM-5TE processors include
 | 
						   Intel's PXA 25x series XScale ARM-5TE processors include
 | 
				
			||||||
	   an integrated full speed USB 1.1 device controller.  The
 | 
						   an integrated full speed USB 1.1 device controller.  The
 | 
				
			||||||
| 
						 | 
					@ -259,8 +257,6 @@ config USB_RENESAS_USBHS_UDC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config USB_PXA27X
 | 
					config USB_PXA27X
 | 
				
			||||||
	tristate "PXA 27x"
 | 
						tristate "PXA 27x"
 | 
				
			||||||
	depends on ARCH_PXA && (PXA27x || PXA3xx)
 | 
					 | 
				
			||||||
	select USB_OTG_UTILS
 | 
					 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	   Intel's PXA 27x series XScale ARM v5TE processors include
 | 
						   Intel's PXA 27x series XScale ARM v5TE processors include
 | 
				
			||||||
	   an integrated full speed USB 1.1 device controller.
 | 
						   an integrated full speed USB 1.1 device controller.
 | 
				
			||||||
| 
						 | 
					@ -329,9 +325,6 @@ config USB_MV_UDC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config USB_MV_U3D
 | 
					config USB_MV_U3D
 | 
				
			||||||
	tristate "MARVELL PXA2128 USB 3.0 controller"
 | 
						tristate "MARVELL PXA2128 USB 3.0 controller"
 | 
				
			||||||
	depends on CPU_MMP3
 | 
					 | 
				
			||||||
	select USB_GADGET_DUALSPEED
 | 
					 | 
				
			||||||
	select USB_GADGET_SUPERSPEED
 | 
					 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  MARVELL PXA2128 Processor series include a super speed USB3.0 device
 | 
						  MARVELL PXA2128 Processor series include a super speed USB3.0 device
 | 
				
			||||||
	  controller, which support super speed USB peripheral.
 | 
						  controller, which support super speed USB peripheral.
 | 
				
			||||||
| 
						 | 
					@ -501,6 +494,7 @@ endmenu
 | 
				
			||||||
# composite based drivers
 | 
					# composite based drivers
 | 
				
			||||||
config USB_LIBCOMPOSITE
 | 
					config USB_LIBCOMPOSITE
 | 
				
			||||||
	tristate
 | 
						tristate
 | 
				
			||||||
 | 
						select CONFIGFS_FS
 | 
				
			||||||
	depends on USB_GADGET
 | 
						depends on USB_GADGET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config USB_F_ACM
 | 
					config USB_F_ACM
 | 
				
			||||||
| 
						 | 
					@ -512,6 +506,12 @@ config USB_F_SS_LB
 | 
				
			||||||
config USB_U_SERIAL
 | 
					config USB_U_SERIAL
 | 
				
			||||||
	tristate
 | 
						tristate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config USB_F_SERIAL
 | 
				
			||||||
 | 
						tristate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config USB_F_OBEX
 | 
				
			||||||
 | 
						tristate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
choice
 | 
					choice
 | 
				
			||||||
	tristate "USB Gadget Drivers"
 | 
						tristate "USB Gadget Drivers"
 | 
				
			||||||
	default USB_ETH
 | 
						default USB_ETH
 | 
				
			||||||
| 
						 | 
					@ -766,6 +766,8 @@ config USB_G_SERIAL
 | 
				
			||||||
	depends on TTY
 | 
						depends on TTY
 | 
				
			||||||
	select USB_U_SERIAL
 | 
						select USB_U_SERIAL
 | 
				
			||||||
	select USB_F_ACM
 | 
						select USB_F_ACM
 | 
				
			||||||
 | 
						select USB_F_SERIAL
 | 
				
			||||||
 | 
						select USB_F_OBEX
 | 
				
			||||||
	select USB_LIBCOMPOSITE
 | 
						select USB_LIBCOMPOSITE
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  The Serial Gadget talks to the Linux-USB generic serial driver.
 | 
						  The Serial Gadget talks to the Linux-USB generic serial driver.
 | 
				
			||||||
| 
						 | 
					@ -839,6 +841,7 @@ config USB_G_NOKIA
 | 
				
			||||||
	depends on PHONET
 | 
						depends on PHONET
 | 
				
			||||||
	select USB_LIBCOMPOSITE
 | 
						select USB_LIBCOMPOSITE
 | 
				
			||||||
	select USB_U_SERIAL
 | 
						select USB_U_SERIAL
 | 
				
			||||||
 | 
						select USB_F_ACM
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  The Nokia composite gadget provides support for acm, obex
 | 
						  The Nokia composite gadget provides support for acm, obex
 | 
				
			||||||
	  and phonet in only one composite gadget driver.
 | 
						  and phonet in only one composite gadget driver.
 | 
				
			||||||
| 
						 | 
					@ -957,6 +960,7 @@ config USB_G_WEBCAM
 | 
				
			||||||
	tristate "USB Webcam Gadget"
 | 
						tristate "USB Webcam Gadget"
 | 
				
			||||||
	depends on VIDEO_DEV
 | 
						depends on VIDEO_DEV
 | 
				
			||||||
	select USB_LIBCOMPOSITE
 | 
						select USB_LIBCOMPOSITE
 | 
				
			||||||
 | 
						select VIDEOBUF2_VMALLOC
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  The Webcam Gadget acts as a composite USB Audio and Video Class
 | 
						  The Webcam Gadget acts as a composite USB Audio and Video Class
 | 
				
			||||||
	  device. It provides a userspace API to process UVC control requests
 | 
						  device. It provides a userspace API to process UVC control requests
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
 | 
				
			||||||
obj-$(CONFIG_USB_GADGET)	+= udc-core.o
 | 
					obj-$(CONFIG_USB_GADGET)	+= udc-core.o
 | 
				
			||||||
obj-$(CONFIG_USB_LIBCOMPOSITE)	+= libcomposite.o
 | 
					obj-$(CONFIG_USB_LIBCOMPOSITE)	+= libcomposite.o
 | 
				
			||||||
libcomposite-y			:= usbstring.o config.o epautoconf.o
 | 
					libcomposite-y			:= usbstring.o config.o epautoconf.o
 | 
				
			||||||
libcomposite-y			+= composite.o functions.o
 | 
					libcomposite-y			+= composite.o functions.o configfs.o
 | 
				
			||||||
obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
 | 
					obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
 | 
				
			||||||
obj-$(CONFIG_USB_NET2272)	+= net2272.o
 | 
					obj-$(CONFIG_USB_NET2272)	+= net2272.o
 | 
				
			||||||
obj-$(CONFIG_USB_NET2280)	+= net2280.o
 | 
					obj-$(CONFIG_USB_NET2280)	+= net2280.o
 | 
				
			||||||
| 
						 | 
					@ -36,10 +36,15 @@ obj-$(CONFIG_USB_FUSB300)	+= fusb300_udc.o
 | 
				
			||||||
obj-$(CONFIG_USB_MV_U3D)	+= mv_u3d_core.o
 | 
					obj-$(CONFIG_USB_MV_U3D)	+= mv_u3d_core.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# USB Functions
 | 
					# USB Functions
 | 
				
			||||||
obj-$(CONFIG_USB_F_ACM)		+= f_acm.o
 | 
					usb_f_acm-y			:= f_acm.o
 | 
				
			||||||
f_ss_lb-y			:= f_loopback.o f_sourcesink.o
 | 
					obj-$(CONFIG_USB_F_ACM)		+= usb_f_acm.o
 | 
				
			||||||
obj-$(CONFIG_USB_F_SS_LB)	+= f_ss_lb.o
 | 
					usb_f_ss_lb-y			:= f_loopback.o f_sourcesink.o
 | 
				
			||||||
 | 
					obj-$(CONFIG_USB_F_SS_LB)	+= usb_f_ss_lb.o
 | 
				
			||||||
obj-$(CONFIG_USB_U_SERIAL)	+= u_serial.o
 | 
					obj-$(CONFIG_USB_U_SERIAL)	+= u_serial.o
 | 
				
			||||||
 | 
					usb_f_serial-y			:= f_serial.o
 | 
				
			||||||
 | 
					obj-$(CONFIG_USB_F_SERIAL)	+= usb_f_serial.o
 | 
				
			||||||
 | 
					usb_f_obex-y			:= f_obex.o
 | 
				
			||||||
 | 
					obj-$(CONFIG_USB_F_OBEX)	+= usb_f_obex.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# USB gadget drivers
 | 
					# USB gadget drivers
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,7 +109,6 @@ FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
 | 
				
			||||||
static struct fsg_common fsg_common;
 | 
					static struct fsg_common fsg_common;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*-------------------------------------------------------------------------*/
 | 
					/*-------------------------------------------------------------------------*/
 | 
				
			||||||
static unsigned char tty_line;
 | 
					 | 
				
			||||||
static struct usb_function *f_acm;
 | 
					static struct usb_function *f_acm;
 | 
				
			||||||
static struct usb_function_instance *f_acm_inst;
 | 
					static struct usb_function_instance *f_acm_inst;
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -117,7 +116,6 @@ static struct usb_function_instance *f_acm_inst;
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int __init acm_ms_do_config(struct usb_configuration *c)
 | 
					static int __init acm_ms_do_config(struct usb_configuration *c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct f_serial_opts *opts;
 | 
					 | 
				
			||||||
	int	status;
 | 
						int	status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (gadget_is_otg(c->cdev->gadget)) {
 | 
						if (gadget_is_otg(c->cdev->gadget)) {
 | 
				
			||||||
| 
						 | 
					@ -129,9 +127,6 @@ static int __init acm_ms_do_config(struct usb_configuration *c)
 | 
				
			||||||
	if (IS_ERR(f_acm_inst))
 | 
						if (IS_ERR(f_acm_inst))
 | 
				
			||||||
		return PTR_ERR(f_acm_inst);
 | 
							return PTR_ERR(f_acm_inst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts = container_of(f_acm_inst, struct f_serial_opts, func_inst);
 | 
					 | 
				
			||||||
	opts->port_num = tty_line;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	f_acm = usb_get_function(f_acm_inst);
 | 
						f_acm = usb_get_function(f_acm_inst);
 | 
				
			||||||
	if (IS_ERR(f_acm)) {
 | 
						if (IS_ERR(f_acm)) {
 | 
				
			||||||
		status = PTR_ERR(f_acm);
 | 
							status = PTR_ERR(f_acm);
 | 
				
			||||||
| 
						 | 
					@ -171,16 +166,11 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
	int			status;
 | 
						int			status;
 | 
				
			||||||
	void			*retp;
 | 
						void			*retp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* set up serial link layer */
 | 
					 | 
				
			||||||
	status = gserial_alloc_line(&tty_line);
 | 
					 | 
				
			||||||
	if (status < 0)
 | 
					 | 
				
			||||||
		return status;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* set up mass storage function */
 | 
						/* set up mass storage function */
 | 
				
			||||||
	retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
 | 
						retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
 | 
				
			||||||
	if (IS_ERR(retp)) {
 | 
						if (IS_ERR(retp)) {
 | 
				
			||||||
		status = PTR_ERR(retp);
 | 
							status = PTR_ERR(retp);
 | 
				
			||||||
		goto fail0;
 | 
							return PTR_ERR(retp);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -207,8 +197,6 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
	/* error recovery */
 | 
						/* error recovery */
 | 
				
			||||||
fail1:
 | 
					fail1:
 | 
				
			||||||
	fsg_common_put(&fsg_common);
 | 
						fsg_common_put(&fsg_common);
 | 
				
			||||||
fail0:
 | 
					 | 
				
			||||||
	gserial_free_line(tty_line);
 | 
					 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -216,7 +204,6 @@ static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	usb_put_function(f_acm);
 | 
						usb_put_function(f_acm);
 | 
				
			||||||
	usb_put_function_instance(f_acm_inst);
 | 
						usb_put_function_instance(f_acm_inst);
 | 
				
			||||||
	gserial_free_line(tty_line);
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1922,7 +1922,6 @@ static int amd5536_udc_start(struct usb_gadget *g,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	driver->driver.bus = NULL;
 | 
						driver->driver.bus = NULL;
 | 
				
			||||||
	dev->driver = driver;
 | 
						dev->driver = driver;
 | 
				
			||||||
	dev->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Some gadget drivers use both ep0 directions.
 | 
						/* Some gadget drivers use both ep0 directions.
 | 
				
			||||||
	 * NOTE: to gadget driver, ep0 is just one endpoint...
 | 
						 * NOTE: to gadget driver, ep0 is just one endpoint...
 | 
				
			||||||
| 
						 | 
					@ -1973,7 +1972,6 @@ static int amd5536_udc_stop(struct usb_gadget *g,
 | 
				
			||||||
	shutdown(dev, driver);
 | 
						shutdown(dev, driver);
 | 
				
			||||||
	spin_unlock_irqrestore(&dev->lock, flags);
 | 
						spin_unlock_irqrestore(&dev->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	dev->driver = NULL;
 | 
						dev->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* set SD */
 | 
						/* set SD */
 | 
				
			||||||
| 
						 | 
					@ -3080,7 +3078,6 @@ static void udc_pci_remove(struct pci_dev *pdev)
 | 
				
			||||||
	if (dev->active)
 | 
						if (dev->active)
 | 
				
			||||||
		pci_disable_device(pdev);
 | 
							pci_disable_device(pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_unregister(&dev->gadget.dev);
 | 
					 | 
				
			||||||
	pci_set_drvdata(pdev, NULL);
 | 
						pci_set_drvdata(pdev, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc_remove(dev);
 | 
						udc_remove(dev);
 | 
				
			||||||
| 
						 | 
					@ -3245,8 +3242,6 @@ static int udc_pci_probe(
 | 
				
			||||||
	dev->phys_addr = resource;
 | 
						dev->phys_addr = resource;
 | 
				
			||||||
	dev->irq = pdev->irq;
 | 
						dev->irq = pdev->irq;
 | 
				
			||||||
	dev->pdev = pdev;
 | 
						dev->pdev = pdev;
 | 
				
			||||||
	dev->gadget.dev.parent = &pdev->dev;
 | 
					 | 
				
			||||||
	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* general probing */
 | 
						/* general probing */
 | 
				
			||||||
	if (udc_probe(dev) == 0)
 | 
						if (udc_probe(dev) == 0)
 | 
				
			||||||
| 
						 | 
					@ -3273,7 +3268,6 @@ static int udc_probe(struct udc *dev)
 | 
				
			||||||
	dev->gadget.ops = &udc_ops;
 | 
						dev->gadget.ops = &udc_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_set_name(&dev->gadget.dev, "gadget");
 | 
						dev_set_name(&dev->gadget.dev, "gadget");
 | 
				
			||||||
	dev->gadget.dev.release = gadget_release;
 | 
					 | 
				
			||||||
	dev->gadget.name = name;
 | 
						dev->gadget.name = name;
 | 
				
			||||||
	dev->gadget.max_speed = USB_SPEED_HIGH;
 | 
						dev->gadget.max_speed = USB_SPEED_HIGH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3297,17 +3291,11 @@ static int udc_probe(struct udc *dev)
 | 
				
			||||||
		"driver version: %s(for Geode5536 B1)\n", tmp);
 | 
							"driver version: %s(for Geode5536 B1)\n", tmp);
 | 
				
			||||||
	udc = dev;
 | 
						udc = dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = usb_add_gadget_udc(&udc->pdev->dev, &dev->gadget);
 | 
						retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
 | 
				
			||||||
 | 
								gadget_release);
 | 
				
			||||||
	if (retval)
 | 
						if (retval)
 | 
				
			||||||
		goto finished;
 | 
							goto finished;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = device_register(&dev->gadget.dev);
 | 
					 | 
				
			||||||
	if (retval) {
 | 
					 | 
				
			||||||
		usb_del_gadget_udc(&dev->gadget);
 | 
					 | 
				
			||||||
		put_device(&dev->gadget.dev);
 | 
					 | 
				
			||||||
		goto finished;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* timer init */
 | 
						/* timer init */
 | 
				
			||||||
	init_timer(&udc_timer);
 | 
						init_timer(&udc_timer);
 | 
				
			||||||
	udc_timer.function = udc_timer_function;
 | 
						udc_timer.function = udc_timer_function;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -472,7 +472,6 @@ struct udc_request {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* flags */
 | 
						/* flags */
 | 
				
			||||||
	unsigned			dma_going : 1,
 | 
						unsigned			dma_going : 1,
 | 
				
			||||||
					dma_mapping : 1,
 | 
					 | 
				
			||||||
					dma_done : 1;
 | 
										dma_done : 1;
 | 
				
			||||||
	/* phys. address */
 | 
						/* phys. address */
 | 
				
			||||||
	dma_addr_t			td_phys;
 | 
						dma_addr_t			td_phys;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1631,7 +1631,6 @@ static int at91_start(struct usb_gadget *gadget,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc = container_of(gadget, struct at91_udc, gadget);
 | 
						udc = container_of(gadget, struct at91_udc, gadget);
 | 
				
			||||||
	udc->driver = driver;
 | 
						udc->driver = driver;
 | 
				
			||||||
	udc->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
	udc->gadget.dev.of_node = udc->pdev->dev.of_node;
 | 
						udc->gadget.dev.of_node = udc->pdev->dev.of_node;
 | 
				
			||||||
	udc->enabled = 1;
 | 
						udc->enabled = 1;
 | 
				
			||||||
	udc->selfpowered = 1;
 | 
						udc->selfpowered = 1;
 | 
				
			||||||
| 
						 | 
					@ -1652,7 +1651,6 @@ static int at91_stop(struct usb_gadget *gadget,
 | 
				
			||||||
	at91_udp_write(udc, AT91_UDP_IDR, ~0);
 | 
						at91_udp_write(udc, AT91_UDP_IDR, ~0);
 | 
				
			||||||
	spin_unlock_irqrestore(&udc->lock, flags);
 | 
						spin_unlock_irqrestore(&udc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	udc->driver = NULL;
 | 
						udc->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DBG("unbound from %s\n", driver->driver.name);
 | 
						DBG("unbound from %s\n", driver->driver.name);
 | 
				
			||||||
| 
						 | 
					@ -1780,13 +1778,7 @@ static int at91udc_probe(struct platform_device *pdev)
 | 
				
			||||||
		DBG("clocks missing\n");
 | 
							DBG("clocks missing\n");
 | 
				
			||||||
		retval = -ENODEV;
 | 
							retval = -ENODEV;
 | 
				
			||||||
		/* NOTE: we "know" here that refcounts on these are NOPs */
 | 
							/* NOTE: we "know" here that refcounts on these are NOPs */
 | 
				
			||||||
		goto fail0b;
 | 
							goto fail1;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	retval = device_register(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	if (retval < 0) {
 | 
					 | 
				
			||||||
		put_device(&udc->gadget.dev);
 | 
					 | 
				
			||||||
		goto fail0b;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* don't do anything until we have both gadget driver and VBUS */
 | 
						/* don't do anything until we have both gadget driver and VBUS */
 | 
				
			||||||
| 
						 | 
					@ -1857,8 +1849,6 @@ fail3:
 | 
				
			||||||
fail2:
 | 
					fail2:
 | 
				
			||||||
	free_irq(udc->udp_irq, udc);
 | 
						free_irq(udc->udp_irq, udc);
 | 
				
			||||||
fail1:
 | 
					fail1:
 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
fail0b:
 | 
					 | 
				
			||||||
	iounmap(udc->udp_baseaddr);
 | 
						iounmap(udc->udp_baseaddr);
 | 
				
			||||||
fail0a:
 | 
					fail0a:
 | 
				
			||||||
	if (cpu_is_at91rm9200())
 | 
						if (cpu_is_at91rm9200())
 | 
				
			||||||
| 
						 | 
					@ -1892,8 +1882,6 @@ static int __exit at91udc_remove(struct platform_device *pdev)
 | 
				
			||||||
		gpio_free(udc->board.vbus_pin);
 | 
							gpio_free(udc->board.vbus_pin);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	free_irq(udc->udp_irq, udc);
 | 
						free_irq(udc->udp_irq, udc);
 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	iounmap(udc->udp_baseaddr);
 | 
						iounmap(udc->udp_baseaddr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cpu_is_at91rm9200())
 | 
						if (cpu_is_at91rm9200())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -489,13 +489,8 @@ request_complete(struct usba_ep *ep, struct usba_request *req, int status)
 | 
				
			||||||
	if (req->req.status == -EINPROGRESS)
 | 
						if (req->req.status == -EINPROGRESS)
 | 
				
			||||||
		req->req.status = status;
 | 
							req->req.status = status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (req->mapped) {
 | 
						if (req->using_dma)
 | 
				
			||||||
		dma_unmap_single(
 | 
							usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
 | 
				
			||||||
			&udc->pdev->dev, req->req.dma, req->req.length,
 | 
					 | 
				
			||||||
			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 | 
					 | 
				
			||||||
		req->req.dma = DMA_ADDR_INVALID;
 | 
					 | 
				
			||||||
		req->mapped = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DBG(DBG_GADGET | DBG_REQ,
 | 
						DBG(DBG_GADGET | DBG_REQ,
 | 
				
			||||||
		"%s: req %p complete: status %d, actual %u\n",
 | 
							"%s: req %p complete: status %d, actual %u\n",
 | 
				
			||||||
| 
						 | 
					@ -684,7 +679,6 @@ usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	INIT_LIST_HEAD(&req->queue);
 | 
						INIT_LIST_HEAD(&req->queue);
 | 
				
			||||||
	req->req.dma = DMA_ADDR_INVALID;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &req->req;
 | 
						return &req->req;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -717,20 +711,11 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = usb_gadget_map_request(&udc->gadget, &req->req, ep->is_in);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req->using_dma = 1;
 | 
						req->using_dma = 1;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (req->req.dma == DMA_ADDR_INVALID) {
 | 
					 | 
				
			||||||
		req->req.dma = dma_map_single(
 | 
					 | 
				
			||||||
			&udc->pdev->dev, req->req.buf, req->req.length,
 | 
					 | 
				
			||||||
			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 | 
					 | 
				
			||||||
		req->mapped = 1;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		dma_sync_single_for_device(
 | 
					 | 
				
			||||||
			&udc->pdev->dev, req->req.dma, req->req.length,
 | 
					 | 
				
			||||||
			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 | 
					 | 
				
			||||||
		req->mapped = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length)
 | 
						req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length)
 | 
				
			||||||
			| USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE
 | 
								| USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE
 | 
				
			||||||
			| USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE;
 | 
								| USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE;
 | 
				
			||||||
| 
						 | 
					@ -1799,7 +1784,6 @@ static int atmel_usba_start(struct usb_gadget *gadget,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
 | 
						udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
 | 
				
			||||||
	udc->driver = driver;
 | 
						udc->driver = driver;
 | 
				
			||||||
	udc->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
	spin_unlock_irqrestore(&udc->lock, flags);
 | 
						spin_unlock_irqrestore(&udc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clk_enable(udc->pclk);
 | 
						clk_enable(udc->pclk);
 | 
				
			||||||
| 
						 | 
					@ -1841,7 +1825,6 @@ static int atmel_usba_stop(struct usb_gadget *gadget,
 | 
				
			||||||
	toggle_bias(0);
 | 
						toggle_bias(0);
 | 
				
			||||||
	usba_writel(udc, CTRL, USBA_DISABLE_MASK);
 | 
						usba_writel(udc, CTRL, USBA_DISABLE_MASK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	udc->driver = NULL;
 | 
						udc->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clk_disable(udc->hclk);
 | 
						clk_disable(udc->hclk);
 | 
				
			||||||
| 
						 | 
					@ -1900,10 +1883,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
	dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
 | 
						dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
 | 
				
			||||||
		 (unsigned long)fifo->start, udc->fifo);
 | 
							 (unsigned long)fifo->start, udc->fifo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_initialize(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	udc->gadget.dev.parent = &pdev->dev;
 | 
					 | 
				
			||||||
	udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	platform_set_drvdata(pdev, udc);
 | 
						platform_set_drvdata(pdev, udc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Make sure we start from a clean slate */
 | 
						/* Make sure we start from a clean slate */
 | 
				
			||||||
| 
						 | 
					@ -1962,12 +1941,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	udc->irq = irq;
 | 
						udc->irq = irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = device_add(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		dev_dbg(&pdev->dev, "Could not add gadget: %d\n", ret);
 | 
					 | 
				
			||||||
		goto err_device_add;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (gpio_is_valid(pdata->vbus_pin)) {
 | 
						if (gpio_is_valid(pdata->vbus_pin)) {
 | 
				
			||||||
		if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {
 | 
							if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {
 | 
				
			||||||
			udc->vbus_pin = pdata->vbus_pin;
 | 
								udc->vbus_pin = pdata->vbus_pin;
 | 
				
			||||||
| 
						 | 
					@ -2007,9 +1980,6 @@ err_add_udc:
 | 
				
			||||||
		gpio_free(udc->vbus_pin);
 | 
							gpio_free(udc->vbus_pin);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
err_device_add:
 | 
					 | 
				
			||||||
	free_irq(irq, udc);
 | 
						free_irq(irq, udc);
 | 
				
			||||||
err_request_irq:
 | 
					err_request_irq:
 | 
				
			||||||
	kfree(usba_ep);
 | 
						kfree(usba_ep);
 | 
				
			||||||
| 
						 | 
					@ -2053,8 +2023,6 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
 | 
				
			||||||
	clk_put(udc->hclk);
 | 
						clk_put(udc->hclk);
 | 
				
			||||||
	clk_put(udc->pclk);
 | 
						clk_put(udc->pclk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -216,12 +216,6 @@
 | 
				
			||||||
#define EP0_EPT_SIZE		USBA_EPT_SIZE_64
 | 
					#define EP0_EPT_SIZE		USBA_EPT_SIZE_64
 | 
				
			||||||
#define EP0_NR_BANKS		1
 | 
					#define EP0_NR_BANKS		1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * REVISIT: Try to eliminate this value. Can we rely on req->mapped to
 | 
					 | 
				
			||||||
 * provide this information?
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define FIFO_IOMEM_ID	0
 | 
					#define FIFO_IOMEM_ID	0
 | 
				
			||||||
#define CTRL_IOMEM_ID	1
 | 
					#define CTRL_IOMEM_ID	1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1819,7 +1819,6 @@ static int bcm63xx_udc_start(struct usb_gadget *gadget,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->driver = driver;
 | 
						udc->driver = driver;
 | 
				
			||||||
	driver->driver.bus = NULL;
 | 
						driver->driver.bus = NULL;
 | 
				
			||||||
	udc->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
	udc->gadget.dev.of_node = udc->dev->of_node;
 | 
						udc->gadget.dev.of_node = udc->dev->of_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_irqrestore(&udc->lock, flags);
 | 
						spin_unlock_irqrestore(&udc->lock, flags);
 | 
				
			||||||
| 
						 | 
					@ -1841,7 +1840,6 @@ static int bcm63xx_udc_stop(struct usb_gadget *gadget,
 | 
				
			||||||
	spin_lock_irqsave(&udc->lock, flags);
 | 
						spin_lock_irqsave(&udc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->driver = NULL;
 | 
						udc->driver = NULL;
 | 
				
			||||||
	udc->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If we switch the PHY too abruptly after dropping D+, the host
 | 
						 * If we switch the PHY too abruptly after dropping D+, the host
 | 
				
			||||||
| 
						 | 
					@ -2305,17 +2303,6 @@ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc)
 | 
				
			||||||
 * Driver init/exit
 | 
					 * Driver init/exit
 | 
				
			||||||
 ***********************************************************************/
 | 
					 ***********************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * bcm63xx_udc_gadget_release - Called from device_release().
 | 
					 | 
				
			||||||
 * @dev: Unused.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * We get a warning if this function doesn't exist, but it's empty because
 | 
					 | 
				
			||||||
 * we don't have to free any of the memory allocated with the devm_* APIs.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void bcm63xx_udc_gadget_release(struct device *dev)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * bcm63xx_udc_probe - Initialize a new instance of the UDC.
 | 
					 * bcm63xx_udc_probe - Initialize a new instance of the UDC.
 | 
				
			||||||
 * @pdev: Platform device struct from the bcm63xx BSP code.
 | 
					 * @pdev: Platform device struct from the bcm63xx BSP code.
 | 
				
			||||||
| 
						 | 
					@ -2368,13 +2355,9 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_init(&udc->lock);
 | 
						spin_lock_init(&udc->lock);
 | 
				
			||||||
	INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process);
 | 
						INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process);
 | 
				
			||||||
	dev_set_name(&udc->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->gadget.ops = &bcm63xx_udc_ops;
 | 
						udc->gadget.ops = &bcm63xx_udc_ops;
 | 
				
			||||||
	udc->gadget.name = dev_name(dev);
 | 
						udc->gadget.name = dev_name(dev);
 | 
				
			||||||
	udc->gadget.dev.parent = dev;
 | 
					 | 
				
			||||||
	udc->gadget.dev.release = bcm63xx_udc_gadget_release;
 | 
					 | 
				
			||||||
	udc->gadget.dev.dma_mask = dev->dma_mask;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!pd->use_fullspeed && !use_fullspeed)
 | 
						if (!pd->use_fullspeed && !use_fullspeed)
 | 
				
			||||||
		udc->gadget.max_speed = USB_SPEED_HIGH;
 | 
							udc->gadget.max_speed = USB_SPEED_HIGH;
 | 
				
			||||||
| 
						 | 
					@ -2414,17 +2397,12 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = device_register(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	if (rc)
 | 
					 | 
				
			||||||
		goto out_uninit;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bcm63xx_udc_init_debugfs(udc);
 | 
						bcm63xx_udc_init_debugfs(udc);
 | 
				
			||||||
	rc = usb_add_gadget_udc(dev, &udc->gadget);
 | 
						rc = usb_add_gadget_udc(dev, &udc->gadget);
 | 
				
			||||||
	if (!rc)
 | 
						if (!rc)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bcm63xx_udc_cleanup_debugfs(udc);
 | 
						bcm63xx_udc_cleanup_debugfs(udc);
 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
out_uninit:
 | 
					out_uninit:
 | 
				
			||||||
	bcm63xx_uninit_udc_hw(udc);
 | 
						bcm63xx_uninit_udc_hw(udc);
 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
| 
						 | 
					@ -2440,7 +2418,6 @@ static int bcm63xx_udc_remove(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bcm63xx_udc_cleanup_debugfs(udc);
 | 
						bcm63xx_udc_cleanup_debugfs(udc);
 | 
				
			||||||
	usb_del_gadget_udc(&udc->gadget);
 | 
						usb_del_gadget_udc(&udc->gadget);
 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	BUG_ON(udc->driver);
 | 
						BUG_ON(udc->driver);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	platform_set_drvdata(pdev, NULL);
 | 
						platform_set_drvdata(pdev, NULL);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -103,18 +103,16 @@ static struct usb_gadget_strings *dev_strings[] = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static u8 hostaddr[ETH_ALEN];
 | 
					static u8 hostaddr[ETH_ALEN];
 | 
				
			||||||
 | 
					static struct eth_dev *the_dev;
 | 
				
			||||||
/*-------------------------------------------------------------------------*/
 | 
					/*-------------------------------------------------------------------------*/
 | 
				
			||||||
static struct usb_function *f_acm;
 | 
					static struct usb_function *f_acm;
 | 
				
			||||||
static struct usb_function_instance *fi_serial;
 | 
					static struct usb_function_instance *fi_serial;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static unsigned char tty_line;
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * We _always_ have both CDC ECM and CDC ACM functions.
 | 
					 * We _always_ have both CDC ECM and CDC ACM functions.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int __init cdc_do_config(struct usb_configuration *c)
 | 
					static int __init cdc_do_config(struct usb_configuration *c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct f_serial_opts *opts;
 | 
					 | 
				
			||||||
	int	status;
 | 
						int	status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (gadget_is_otg(c->cdev->gadget)) {
 | 
						if (gadget_is_otg(c->cdev->gadget)) {
 | 
				
			||||||
| 
						 | 
					@ -122,7 +120,7 @@ static int __init cdc_do_config(struct usb_configuration *c)
 | 
				
			||||||
		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 | 
							c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = ecm_bind_config(c, hostaddr);
 | 
						status = ecm_bind_config(c, hostaddr, the_dev);
 | 
				
			||||||
	if (status < 0)
 | 
						if (status < 0)
 | 
				
			||||||
		return status;
 | 
							return status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -130,9 +128,6 @@ static int __init cdc_do_config(struct usb_configuration *c)
 | 
				
			||||||
	if (IS_ERR(fi_serial))
 | 
						if (IS_ERR(fi_serial))
 | 
				
			||||||
		return PTR_ERR(fi_serial);
 | 
							return PTR_ERR(fi_serial);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts = container_of(fi_serial, struct f_serial_opts, func_inst);
 | 
					 | 
				
			||||||
	opts->port_num = tty_line;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	f_acm = usb_get_function(fi_serial);
 | 
						f_acm = usb_get_function(fi_serial);
 | 
				
			||||||
	if (IS_ERR(f_acm))
 | 
						if (IS_ERR(f_acm))
 | 
				
			||||||
		goto err_func_acm;
 | 
							goto err_func_acm;
 | 
				
			||||||
| 
						 | 
					@ -169,14 +164,9 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* set up network link layer */
 | 
						/* set up network link layer */
 | 
				
			||||||
	status = gether_setup(cdev->gadget, hostaddr);
 | 
						the_dev = gether_setup(cdev->gadget, hostaddr);
 | 
				
			||||||
	if (status < 0)
 | 
						if (IS_ERR(the_dev))
 | 
				
			||||||
		return status;
 | 
							return PTR_ERR(the_dev);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* set up serial link layer */
 | 
					 | 
				
			||||||
	status = gserial_alloc_line(&tty_line);
 | 
					 | 
				
			||||||
	if (status < 0)
 | 
					 | 
				
			||||||
		goto fail0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Allocate string descriptor numbers ... note that string
 | 
						/* Allocate string descriptor numbers ... note that string
 | 
				
			||||||
	 * contents can be overridden by the composite_dev glue.
 | 
						 * contents can be overridden by the composite_dev glue.
 | 
				
			||||||
| 
						 | 
					@ -200,9 +190,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fail1:
 | 
					fail1:
 | 
				
			||||||
	gserial_free_line(tty_line);
 | 
						gether_cleanup(the_dev);
 | 
				
			||||||
fail0:
 | 
					 | 
				
			||||||
	gether_cleanup();
 | 
					 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -210,8 +198,7 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	usb_put_function(f_acm);
 | 
						usb_put_function(f_acm);
 | 
				
			||||||
	usb_put_function_instance(fi_serial);
 | 
						usb_put_function_instance(fi_serial);
 | 
				
			||||||
	gserial_free_line(tty_line);
 | 
						gether_cleanup(the_dev);
 | 
				
			||||||
	gether_cleanup();
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1637,6 +1637,7 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
 | 
				
			||||||
		kfree(cdev->req->buf);
 | 
							kfree(cdev->req->buf);
 | 
				
			||||||
		usb_ep_free_request(cdev->gadget->ep0, cdev->req);
 | 
							usb_ep_free_request(cdev->gadget->ep0, cdev->req);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						cdev->next_string_id = 0;
 | 
				
			||||||
	device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
 | 
						device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1003
									
								
								drivers/usb/gadget/configfs.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1003
									
								
								drivers/usb/gadget/configfs.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -912,7 +912,6 @@ static int dummy_udc_start(struct usb_gadget *g,
 | 
				
			||||||
	dum->devstatus = 0;
 | 
						dum->devstatus = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dum->driver = driver;
 | 
						dum->driver = driver;
 | 
				
			||||||
	dum->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
	dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
 | 
						dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
 | 
				
			||||||
			driver->driver.name);
 | 
								driver->driver.name);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -927,7 +926,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
 | 
				
			||||||
	dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
 | 
						dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
 | 
				
			||||||
			driver->driver.name);
 | 
								driver->driver.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dum->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	dum->driver = NULL;
 | 
						dum->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -937,11 +935,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* The gadget structure is stored inside the hcd structure and will be
 | 
					/* The gadget structure is stored inside the hcd structure and will be
 | 
				
			||||||
 * released along with it. */
 | 
					 * released along with it. */
 | 
				
			||||||
static void dummy_gadget_release(struct device *dev)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void init_dummy_udc_hw(struct dummy *dum)
 | 
					static void init_dummy_udc_hw(struct dummy *dum)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
| 
						 | 
					@ -984,15 +977,7 @@ static int dummy_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
	dum->gadget.ops = &dummy_ops;
 | 
						dum->gadget.ops = &dummy_ops;
 | 
				
			||||||
	dum->gadget.max_speed = USB_SPEED_SUPER;
 | 
						dum->gadget.max_speed = USB_SPEED_SUPER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_set_name(&dum->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
	dum->gadget.dev.parent = &pdev->dev;
 | 
						dum->gadget.dev.parent = &pdev->dev;
 | 
				
			||||||
	dum->gadget.dev.release = dummy_gadget_release;
 | 
					 | 
				
			||||||
	rc = device_register(&dum->gadget.dev);
 | 
					 | 
				
			||||||
	if (rc < 0) {
 | 
					 | 
				
			||||||
		put_device(&dum->gadget.dev);
 | 
					 | 
				
			||||||
		return rc;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	init_dummy_udc_hw(dum);
 | 
						init_dummy_udc_hw(dum);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget);
 | 
						rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget);
 | 
				
			||||||
| 
						 | 
					@ -1008,7 +993,6 @@ static int dummy_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
err_dev:
 | 
					err_dev:
 | 
				
			||||||
	usb_del_gadget_udc(&dum->gadget);
 | 
						usb_del_gadget_udc(&dum->gadget);
 | 
				
			||||||
err_udc:
 | 
					err_udc:
 | 
				
			||||||
	device_unregister(&dum->gadget.dev);
 | 
					 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1019,7 +1003,6 @@ static int dummy_udc_remove(struct platform_device *pdev)
 | 
				
			||||||
	usb_del_gadget_udc(&dum->gadget);
 | 
						usb_del_gadget_udc(&dum->gadget);
 | 
				
			||||||
	platform_set_drvdata(pdev, NULL);
 | 
						platform_set_drvdata(pdev, NULL);
 | 
				
			||||||
	device_remove_file(&dum->gadget.dev, &dev_attr_function);
 | 
						device_remove_file(&dum->gadget.dev, &dev_attr_function);
 | 
				
			||||||
	device_unregister(&dum->gadget.dev);
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1923,7 +1906,7 @@ done:
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* usb 3.0 root hub device descriptor */
 | 
					/* usb 3.0 root hub device descriptor */
 | 
				
			||||||
struct {
 | 
					static struct {
 | 
				
			||||||
	struct usb_bos_descriptor bos;
 | 
						struct usb_bos_descriptor bos;
 | 
				
			||||||
	struct usb_ss_cap_descriptor ss_cap;
 | 
						struct usb_ss_cap_descriptor ss_cap;
 | 
				
			||||||
} __packed usb3_bos_desc = {
 | 
					} __packed usb3_bos_desc = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -207,7 +207,7 @@ static struct usb_gadget_strings *dev_strings[] = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static u8 hostaddr[ETH_ALEN];
 | 
					static u8 hostaddr[ETH_ALEN];
 | 
				
			||||||
 | 
					static struct eth_dev *the_dev;
 | 
				
			||||||
/*-------------------------------------------------------------------------*/
 | 
					/*-------------------------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -224,7 +224,7 @@ static int __init rndis_do_config(struct usb_configuration *c)
 | 
				
			||||||
		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 | 
							c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return rndis_bind_config(c, hostaddr);
 | 
						return rndis_bind_config(c, hostaddr, the_dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_configuration rndis_config_driver = {
 | 
					static struct usb_configuration rndis_config_driver = {
 | 
				
			||||||
| 
						 | 
					@ -257,11 +257,11 @@ static int __init eth_do_config(struct usb_configuration *c)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (use_eem)
 | 
						if (use_eem)
 | 
				
			||||||
		return eem_bind_config(c);
 | 
							return eem_bind_config(c, the_dev);
 | 
				
			||||||
	else if (can_support_ecm(c->cdev->gadget))
 | 
						else if (can_support_ecm(c->cdev->gadget))
 | 
				
			||||||
		return ecm_bind_config(c, hostaddr);
 | 
							return ecm_bind_config(c, hostaddr, the_dev);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return geth_bind_config(c, hostaddr);
 | 
							return geth_bind_config(c, hostaddr, the_dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_configuration eth_config_driver = {
 | 
					static struct usb_configuration eth_config_driver = {
 | 
				
			||||||
| 
						 | 
					@ -279,9 +279,9 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
	int			status;
 | 
						int			status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* set up network link layer */
 | 
						/* set up network link layer */
 | 
				
			||||||
	status = gether_setup(cdev->gadget, hostaddr);
 | 
						the_dev = gether_setup(cdev->gadget, hostaddr);
 | 
				
			||||||
	if (status < 0)
 | 
						if (IS_ERR(the_dev))
 | 
				
			||||||
		return status;
 | 
							return PTR_ERR(the_dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* set up main config label and device descriptor */
 | 
						/* set up main config label and device descriptor */
 | 
				
			||||||
	if (use_eem) {
 | 
						if (use_eem) {
 | 
				
			||||||
| 
						 | 
					@ -338,13 +338,13 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fail:
 | 
					fail:
 | 
				
			||||||
	gether_cleanup();
 | 
						gether_cleanup(the_dev);
 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __exit eth_unbind(struct usb_composite_dev *cdev)
 | 
					static int __exit eth_unbind(struct usb_composite_dev *cdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	gether_cleanup();
 | 
						gether_cleanup(the_dev);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -715,72 +715,6 @@ fail:
 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct f_acm *acm_alloc_basic_func(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct f_acm	*acm;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	acm = kzalloc(sizeof(*acm), GFP_KERNEL);
 | 
					 | 
				
			||||||
	if (!acm)
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	spin_lock_init(&acm->lock);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	acm->port.connect = acm_connect;
 | 
					 | 
				
			||||||
	acm->port.disconnect = acm_disconnect;
 | 
					 | 
				
			||||||
	acm->port.send_break = acm_send_break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	acm->port.func.name = "acm";
 | 
					 | 
				
			||||||
	/* descriptors are per-instance copies */
 | 
					 | 
				
			||||||
	acm->port.func.bind = acm_bind;
 | 
					 | 
				
			||||||
	acm->port.func.set_alt = acm_set_alt;
 | 
					 | 
				
			||||||
	acm->port.func.setup = acm_setup;
 | 
					 | 
				
			||||||
	acm->port.func.disable = acm_disable;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return acm;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef USB_FACM_INCLUDED
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
acm_old_unbind(struct usb_configuration *c, struct usb_function *f)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct f_acm		*acm = func_to_acm(f);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	usb_free_all_descriptors(f);
 | 
					 | 
				
			||||||
	if (acm->notify_req)
 | 
					 | 
				
			||||||
		gs_free_req(acm->notify, acm->notify_req);
 | 
					 | 
				
			||||||
	kfree(acm);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * acm_bind_config - add a CDC ACM function to a configuration
 | 
					 | 
				
			||||||
 * @c: the configuration to support the CDC ACM instance
 | 
					 | 
				
			||||||
 * @port_num: /dev/ttyGS* port this interface will use
 | 
					 | 
				
			||||||
 * Context: single threaded during gadget setup
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Returns zero on success, else negative errno.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int acm_bind_config(struct usb_configuration *c, u8 port_num)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct f_acm	*acm;
 | 
					 | 
				
			||||||
	int		status;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* allocate and initialize one new instance */
 | 
					 | 
				
			||||||
	acm = acm_alloc_basic_func();
 | 
					 | 
				
			||||||
	if (!acm)
 | 
					 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	acm->port_num = port_num;
 | 
					 | 
				
			||||||
	acm->port.func.unbind = acm_old_unbind;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	status = usb_add_function(c, &acm->port.func);
 | 
					 | 
				
			||||||
	if (status)
 | 
					 | 
				
			||||||
		kfree(acm);
 | 
					 | 
				
			||||||
	return status;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
 | 
					static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct f_acm		*acm = func_to_acm(f);
 | 
						struct f_acm		*acm = func_to_acm(f);
 | 
				
			||||||
| 
						 | 
					@ -803,10 +737,24 @@ static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
 | 
				
			||||||
	struct f_serial_opts *opts;
 | 
						struct f_serial_opts *opts;
 | 
				
			||||||
	struct f_acm *acm;
 | 
						struct f_acm *acm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	acm = acm_alloc_basic_func();
 | 
						acm = kzalloc(sizeof(*acm), GFP_KERNEL);
 | 
				
			||||||
	if (!acm)
 | 
						if (!acm)
 | 
				
			||||||
		return ERR_PTR(-ENOMEM);
 | 
							return ERR_PTR(-ENOMEM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_init(&acm->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						acm->port.connect = acm_connect;
 | 
				
			||||||
 | 
						acm->port.disconnect = acm_disconnect;
 | 
				
			||||||
 | 
						acm->port.send_break = acm_send_break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						acm->port.func.name = "acm";
 | 
				
			||||||
 | 
						acm->port.func.strings = acm_strings;
 | 
				
			||||||
 | 
						/* descriptors are per-instance copies */
 | 
				
			||||||
 | 
						acm->port.func.bind = acm_bind;
 | 
				
			||||||
 | 
						acm->port.func.set_alt = acm_set_alt;
 | 
				
			||||||
 | 
						acm->port.func.setup = acm_setup;
 | 
				
			||||||
 | 
						acm->port.func.disable = acm_disable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts = container_of(fi, struct f_serial_opts, func_inst);
 | 
						opts = container_of(fi, struct f_serial_opts, func_inst);
 | 
				
			||||||
	acm->port_num = opts->port_num;
 | 
						acm->port_num = opts->port_num;
 | 
				
			||||||
	acm->port.func.unbind = acm_unbind;
 | 
						acm->port.func.unbind = acm_unbind;
 | 
				
			||||||
| 
						 | 
					@ -815,24 +763,85 @@ static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
 | 
				
			||||||
	return &acm->port.func;
 | 
						return &acm->port.func;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return container_of(to_config_group(item), struct f_serial_opts,
 | 
				
			||||||
 | 
								func_inst.group);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CONFIGFS_ATTR_STRUCT(f_serial_opts);
 | 
				
			||||||
 | 
					static ssize_t f_acm_attr_show(struct config_item *item,
 | 
				
			||||||
 | 
									 struct configfs_attribute *attr,
 | 
				
			||||||
 | 
									 char *page)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct f_serial_opts *opts = to_f_serial_opts(item);
 | 
				
			||||||
 | 
						struct f_serial_opts_attribute *f_serial_opts_attr =
 | 
				
			||||||
 | 
							container_of(attr, struct f_serial_opts_attribute, attr);
 | 
				
			||||||
 | 
						ssize_t ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (f_serial_opts_attr->show)
 | 
				
			||||||
 | 
							ret = f_serial_opts_attr->show(opts, page);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void acm_attr_release(struct config_item *item)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct f_serial_opts *opts = to_f_serial_opts(item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						usb_put_function_instance(&opts->func_inst);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct configfs_item_operations acm_item_ops = {
 | 
				
			||||||
 | 
						.release                = acm_attr_release,
 | 
				
			||||||
 | 
						.show_attribute		= f_acm_attr_show,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ssize_t f_acm_port_num_show(struct f_serial_opts *opts, char *page)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return sprintf(page, "%u\n", opts->port_num);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct f_serial_opts_attribute f_acm_port_num =
 | 
				
			||||||
 | 
						__CONFIGFS_ATTR_RO(port_num, f_acm_port_num_show);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct configfs_attribute *acm_attrs[] = {
 | 
				
			||||||
 | 
						&f_acm_port_num.attr,
 | 
				
			||||||
 | 
						NULL,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct config_item_type acm_func_type = {
 | 
				
			||||||
 | 
						.ct_item_ops    = &acm_item_ops,
 | 
				
			||||||
 | 
						.ct_attrs	= acm_attrs,
 | 
				
			||||||
 | 
						.ct_owner       = THIS_MODULE,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void acm_free_instance(struct usb_function_instance *fi)
 | 
					static void acm_free_instance(struct usb_function_instance *fi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct f_serial_opts *opts;
 | 
						struct f_serial_opts *opts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts = container_of(fi, struct f_serial_opts, func_inst);
 | 
						opts = container_of(fi, struct f_serial_opts, func_inst);
 | 
				
			||||||
 | 
						gserial_free_line(opts->port_num);
 | 
				
			||||||
	kfree(opts);
 | 
						kfree(opts);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_function_instance *acm_alloc_instance(void)
 | 
					static struct usb_function_instance *acm_alloc_instance(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct f_serial_opts *opts;
 | 
						struct f_serial_opts *opts;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
 | 
						opts = kzalloc(sizeof(*opts), GFP_KERNEL);
 | 
				
			||||||
	if (!opts)
 | 
						if (!opts)
 | 
				
			||||||
		return ERR_PTR(-ENOMEM);
 | 
							return ERR_PTR(-ENOMEM);
 | 
				
			||||||
	opts->func_inst.free_func_inst = acm_free_instance;
 | 
						opts->func_inst.free_func_inst = acm_free_instance;
 | 
				
			||||||
 | 
						ret = gserial_alloc_line(&opts->port_num);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							kfree(opts);
 | 
				
			||||||
 | 
							return ERR_PTR(ret);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						config_group_init_type_name(&opts->func_inst.group, "",
 | 
				
			||||||
 | 
								&acm_func_type);
 | 
				
			||||||
	return &opts->func_inst;
 | 
						return &opts->func_inst;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
 | 
					DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
 | 
				
			||||||
MODULE_LICENSE("GPL");
 | 
					MODULE_LICENSE("GPL");
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -824,7 +824,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
 | 
				
			||||||
 * for calling @gether_cleanup() before module unload.
 | 
					 * for calling @gether_cleanup() before module unload.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 | 
					ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
 | 
							struct eth_dev *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct f_ecm	*ecm;
 | 
						struct f_ecm	*ecm;
 | 
				
			||||||
	int		status;
 | 
						int		status;
 | 
				
			||||||
| 
						 | 
					@ -852,6 +853,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 | 
				
			||||||
	snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr);
 | 
						snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr);
 | 
				
			||||||
	ecm_string_defs[1].s = ecm->ethaddr;
 | 
						ecm_string_defs[1].s = ecm->ethaddr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ecm->port.ioport = dev;
 | 
				
			||||||
	ecm->port.cdc_filter = DEFAULT_FILTER;
 | 
						ecm->port.cdc_filter = DEFAULT_FILTER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ecm->port.func.name = "cdc_ethernet";
 | 
						ecm->port.func.name = "cdc_ethernet";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -528,7 +528,7 @@ error:
 | 
				
			||||||
 * Caller must have called @gether_setup().  Caller is also responsible
 | 
					 * Caller must have called @gether_setup().  Caller is also responsible
 | 
				
			||||||
 * for calling @gether_cleanup() before module unload.
 | 
					 * for calling @gether_cleanup() before module unload.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int __init eem_bind_config(struct usb_configuration *c)
 | 
					int __init eem_bind_config(struct usb_configuration *c, struct eth_dev *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct f_eem	*eem;
 | 
						struct f_eem	*eem;
 | 
				
			||||||
	int		status;
 | 
						int		status;
 | 
				
			||||||
| 
						 | 
					@ -549,6 +549,7 @@ int __init eem_bind_config(struct usb_configuration *c)
 | 
				
			||||||
	if (!eem)
 | 
						if (!eem)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						eem->port.ioport = dev;
 | 
				
			||||||
	eem->port.cdc_filter = DEFAULT_FILTER;
 | 
						eem->port.cdc_filter = DEFAULT_FILTER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	eem->port.func.name = "cdc_eem";
 | 
						eem->port.func.name = "cdc_eem";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1287,7 +1287,8 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f)
 | 
				
			||||||
 * Caller must have called @gether_setup().  Caller is also responsible
 | 
					 * Caller must have called @gether_setup().  Caller is also responsible
 | 
				
			||||||
 * for calling @gether_cleanup() before module unload.
 | 
					 * for calling @gether_cleanup() before module unload.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 | 
					int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
 | 
							struct eth_dev *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct f_ncm	*ncm;
 | 
						struct f_ncm	*ncm;
 | 
				
			||||||
	int		status;
 | 
						int		status;
 | 
				
			||||||
| 
						 | 
					@ -1321,6 +1322,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_init(&ncm->lock);
 | 
						spin_lock_init(&ncm->lock);
 | 
				
			||||||
	ncm_reset_values(ncm);
 | 
						ncm_reset_values(ncm);
 | 
				
			||||||
 | 
						ncm->port.ioport = dev;
 | 
				
			||||||
	ncm->port.is_fixed = true;
 | 
						ncm->port.is_fixed = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ncm->port.func.name = "cdc_network";
 | 
						ncm->port.func.name = "cdc_network";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,7 +72,7 @@ static struct usb_gadget_strings *obex_strings[] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*-------------------------------------------------------------------------*/
 | 
					/*-------------------------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_interface_descriptor obex_control_intf __initdata = {
 | 
					static struct usb_interface_descriptor obex_control_intf = {
 | 
				
			||||||
	.bLength		= sizeof(obex_control_intf),
 | 
						.bLength		= sizeof(obex_control_intf),
 | 
				
			||||||
	.bDescriptorType	= USB_DT_INTERFACE,
 | 
						.bDescriptorType	= USB_DT_INTERFACE,
 | 
				
			||||||
	.bInterfaceNumber	= 0,
 | 
						.bInterfaceNumber	= 0,
 | 
				
			||||||
| 
						 | 
					@ -83,7 +83,7 @@ static struct usb_interface_descriptor obex_control_intf __initdata = {
 | 
				
			||||||
	.bInterfaceSubClass	= USB_CDC_SUBCLASS_OBEX,
 | 
						.bInterfaceSubClass	= USB_CDC_SUBCLASS_OBEX,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
 | 
					static struct usb_interface_descriptor obex_data_nop_intf = {
 | 
				
			||||||
	.bLength		= sizeof(obex_data_nop_intf),
 | 
						.bLength		= sizeof(obex_data_nop_intf),
 | 
				
			||||||
	.bDescriptorType	= USB_DT_INTERFACE,
 | 
						.bDescriptorType	= USB_DT_INTERFACE,
 | 
				
			||||||
	.bInterfaceNumber	= 1,
 | 
						.bInterfaceNumber	= 1,
 | 
				
			||||||
| 
						 | 
					@ -93,7 +93,7 @@ static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
 | 
				
			||||||
	.bInterfaceClass	= USB_CLASS_CDC_DATA,
 | 
						.bInterfaceClass	= USB_CLASS_CDC_DATA,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_interface_descriptor obex_data_intf __initdata = {
 | 
					static struct usb_interface_descriptor obex_data_intf = {
 | 
				
			||||||
	.bLength		= sizeof(obex_data_intf),
 | 
						.bLength		= sizeof(obex_data_intf),
 | 
				
			||||||
	.bDescriptorType	= USB_DT_INTERFACE,
 | 
						.bDescriptorType	= USB_DT_INTERFACE,
 | 
				
			||||||
	.bInterfaceNumber	= 2,
 | 
						.bInterfaceNumber	= 2,
 | 
				
			||||||
| 
						 | 
					@ -103,14 +103,14 @@ static struct usb_interface_descriptor obex_data_intf __initdata = {
 | 
				
			||||||
	.bInterfaceClass	= USB_CLASS_CDC_DATA,
 | 
						.bInterfaceClass	= USB_CLASS_CDC_DATA,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = {
 | 
					static struct usb_cdc_header_desc obex_cdc_header_desc = {
 | 
				
			||||||
	.bLength		= sizeof(obex_cdc_header_desc),
 | 
						.bLength		= sizeof(obex_cdc_header_desc),
 | 
				
			||||||
	.bDescriptorType	= USB_DT_CS_INTERFACE,
 | 
						.bDescriptorType	= USB_DT_CS_INTERFACE,
 | 
				
			||||||
	.bDescriptorSubType	= USB_CDC_HEADER_TYPE,
 | 
						.bDescriptorSubType	= USB_CDC_HEADER_TYPE,
 | 
				
			||||||
	.bcdCDC			= cpu_to_le16(0x0120),
 | 
						.bcdCDC			= cpu_to_le16(0x0120),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
 | 
					static struct usb_cdc_union_desc obex_cdc_union_desc = {
 | 
				
			||||||
	.bLength		= sizeof(obex_cdc_union_desc),
 | 
						.bLength		= sizeof(obex_cdc_union_desc),
 | 
				
			||||||
	.bDescriptorType	= USB_DT_CS_INTERFACE,
 | 
						.bDescriptorType	= USB_DT_CS_INTERFACE,
 | 
				
			||||||
	.bDescriptorSubType	= USB_CDC_UNION_TYPE,
 | 
						.bDescriptorSubType	= USB_CDC_UNION_TYPE,
 | 
				
			||||||
| 
						 | 
					@ -118,7 +118,7 @@ static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
 | 
				
			||||||
	.bSlaveInterface0	= 2,
 | 
						.bSlaveInterface0	= 2,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_cdc_obex_desc obex_desc __initdata = {
 | 
					static struct usb_cdc_obex_desc obex_desc = {
 | 
				
			||||||
	.bLength		= sizeof(obex_desc),
 | 
						.bLength		= sizeof(obex_desc),
 | 
				
			||||||
	.bDescriptorType	= USB_DT_CS_INTERFACE,
 | 
						.bDescriptorType	= USB_DT_CS_INTERFACE,
 | 
				
			||||||
	.bDescriptorSubType	= USB_CDC_OBEX_TYPE,
 | 
						.bDescriptorSubType	= USB_CDC_OBEX_TYPE,
 | 
				
			||||||
| 
						 | 
					@ -127,7 +127,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* High-Speed Support */
 | 
					/* High-Speed Support */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
 | 
					static struct usb_endpoint_descriptor obex_hs_ep_out_desc = {
 | 
				
			||||||
	.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
						.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType	= USB_DT_ENDPOINT,
 | 
						.bDescriptorType	= USB_DT_ENDPOINT,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -136,7 +136,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
 | 
				
			||||||
	.wMaxPacketSize		= cpu_to_le16(512),
 | 
						.wMaxPacketSize		= cpu_to_le16(512),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
 | 
					static struct usb_endpoint_descriptor obex_hs_ep_in_desc = {
 | 
				
			||||||
	.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
						.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType	= USB_DT_ENDPOINT,
 | 
						.bDescriptorType	= USB_DT_ENDPOINT,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -145,7 +145,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
 | 
				
			||||||
	.wMaxPacketSize		= cpu_to_le16(512),
 | 
						.wMaxPacketSize		= cpu_to_le16(512),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_descriptor_header *hs_function[] __initdata = {
 | 
					static struct usb_descriptor_header *hs_function[] = {
 | 
				
			||||||
	(struct usb_descriptor_header *) &obex_control_intf,
 | 
						(struct usb_descriptor_header *) &obex_control_intf,
 | 
				
			||||||
	(struct usb_descriptor_header *) &obex_cdc_header_desc,
 | 
						(struct usb_descriptor_header *) &obex_cdc_header_desc,
 | 
				
			||||||
	(struct usb_descriptor_header *) &obex_desc,
 | 
						(struct usb_descriptor_header *) &obex_desc,
 | 
				
			||||||
| 
						 | 
					@ -160,7 +160,7 @@ static struct usb_descriptor_header *hs_function[] __initdata = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Full-Speed Support */
 | 
					/* Full-Speed Support */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
 | 
					static struct usb_endpoint_descriptor obex_fs_ep_in_desc = {
 | 
				
			||||||
	.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
						.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType	= USB_DT_ENDPOINT,
 | 
						.bDescriptorType	= USB_DT_ENDPOINT,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -168,7 +168,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
 | 
				
			||||||
	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
 | 
						.bmAttributes		= USB_ENDPOINT_XFER_BULK,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
 | 
					static struct usb_endpoint_descriptor obex_fs_ep_out_desc = {
 | 
				
			||||||
	.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
						.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType	= USB_DT_ENDPOINT,
 | 
						.bDescriptorType	= USB_DT_ENDPOINT,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -176,7 +176,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
 | 
				
			||||||
	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
 | 
						.bmAttributes		= USB_ENDPOINT_XFER_BULK,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_descriptor_header *fs_function[] __initdata = {
 | 
					static struct usb_descriptor_header *fs_function[] = {
 | 
				
			||||||
	(struct usb_descriptor_header *) &obex_control_intf,
 | 
						(struct usb_descriptor_header *) &obex_control_intf,
 | 
				
			||||||
	(struct usb_descriptor_header *) &obex_cdc_header_desc,
 | 
						(struct usb_descriptor_header *) &obex_cdc_header_desc,
 | 
				
			||||||
	(struct usb_descriptor_header *) &obex_desc,
 | 
						(struct usb_descriptor_header *) &obex_desc,
 | 
				
			||||||
| 
						 | 
					@ -290,14 +290,43 @@ static void obex_disconnect(struct gserial *g)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*-------------------------------------------------------------------------*/
 | 
					/*-------------------------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init
 | 
					/* Some controllers can't support CDC OBEX ... */
 | 
				
			||||||
obex_bind(struct usb_configuration *c, struct usb_function *f)
 | 
					static inline bool can_support_obex(struct usb_configuration *c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* Since the first interface is a NOP, we can ignore the
 | 
				
			||||||
 | 
						 * issue of multi-interface support on most controllers.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Altsettings are mandatory, however...
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (!gadget_supports_altsettings(c->cdev->gadget))
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* everything else is *probably* fine ... */
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int obex_bind(struct usb_configuration *c, struct usb_function *f)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usb_composite_dev *cdev = c->cdev;
 | 
						struct usb_composite_dev *cdev = c->cdev;
 | 
				
			||||||
	struct f_obex		*obex = func_to_obex(f);
 | 
						struct f_obex		*obex = func_to_obex(f);
 | 
				
			||||||
	int			status;
 | 
						int			status;
 | 
				
			||||||
	struct usb_ep		*ep;
 | 
						struct usb_ep		*ep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!can_support_obex(c))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
 | 
				
			||||||
 | 
							status = usb_string_ids_tab(c->cdev, obex_string_defs);
 | 
				
			||||||
 | 
							if (status < 0)
 | 
				
			||||||
 | 
								return status;
 | 
				
			||||||
 | 
							obex_control_intf.iInterface =
 | 
				
			||||||
 | 
								obex_string_defs[OBEX_CTRL_IDX].id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							status = obex_string_defs[OBEX_DATA_IDX].id;
 | 
				
			||||||
 | 
							obex_data_nop_intf.iInterface = status;
 | 
				
			||||||
 | 
							obex_data_intf.iInterface = status;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* allocate instance-specific interface IDs, and patch descriptors */
 | 
						/* allocate instance-specific interface IDs, and patch descriptors */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = usb_interface_id(c, f);
 | 
						status = usb_interface_id(c, f);
 | 
				
			||||||
| 
						 | 
					@ -376,29 +405,16 @@ fail:
 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USBF_OBEX_INCLUDED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
obex_unbind(struct usb_configuration *c, struct usb_function *f)
 | 
					obex_old_unbind(struct usb_configuration *c, struct usb_function *f)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	obex_string_defs[OBEX_CTRL_IDX].id = 0;
 | 
						obex_string_defs[OBEX_CTRL_IDX].id = 0;
 | 
				
			||||||
	usb_free_all_descriptors(f);
 | 
						usb_free_all_descriptors(f);
 | 
				
			||||||
	kfree(func_to_obex(f));
 | 
						kfree(func_to_obex(f));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Some controllers can't support CDC OBEX ... */
 | 
					 | 
				
			||||||
static inline bool can_support_obex(struct usb_configuration *c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	/* Since the first interface is a NOP, we can ignore the
 | 
					 | 
				
			||||||
	 * issue of multi-interface support on most controllers.
 | 
					 | 
				
			||||||
	 *
 | 
					 | 
				
			||||||
	 * Altsettings are mandatory, however...
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (!gadget_supports_altsettings(c->cdev->gadget))
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* everything else is *probably* fine ... */
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * obex_bind_config - add a CDC OBEX function to a configuration
 | 
					 * obex_bind_config - add a CDC OBEX function to a configuration
 | 
				
			||||||
 * @c: the configuration to support the CDC OBEX instance
 | 
					 * @c: the configuration to support the CDC OBEX instance
 | 
				
			||||||
| 
						 | 
					@ -412,21 +428,6 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
 | 
				
			||||||
	struct f_obex	*obex;
 | 
						struct f_obex	*obex;
 | 
				
			||||||
	int		status;
 | 
						int		status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!can_support_obex(c))
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
 | 
					 | 
				
			||||||
		status = usb_string_ids_tab(c->cdev, obex_string_defs);
 | 
					 | 
				
			||||||
		if (status < 0)
 | 
					 | 
				
			||||||
			return status;
 | 
					 | 
				
			||||||
		obex_control_intf.iInterface =
 | 
					 | 
				
			||||||
			obex_string_defs[OBEX_CTRL_IDX].id;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		status = obex_string_defs[OBEX_DATA_IDX].id;
 | 
					 | 
				
			||||||
		obex_data_nop_intf.iInterface = status;
 | 
					 | 
				
			||||||
		obex_data_intf.iInterface = status;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* allocate and initialize one new instance */
 | 
						/* allocate and initialize one new instance */
 | 
				
			||||||
	obex = kzalloc(sizeof *obex, GFP_KERNEL);
 | 
						obex = kzalloc(sizeof *obex, GFP_KERNEL);
 | 
				
			||||||
	if (!obex)
 | 
						if (!obex)
 | 
				
			||||||
| 
						 | 
					@ -441,7 +442,7 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
 | 
				
			||||||
	obex->port.func.strings = obex_strings;
 | 
						obex->port.func.strings = obex_strings;
 | 
				
			||||||
	/* descriptors are per-instance copies */
 | 
						/* descriptors are per-instance copies */
 | 
				
			||||||
	obex->port.func.bind = obex_bind;
 | 
						obex->port.func.bind = obex_bind;
 | 
				
			||||||
	obex->port.func.unbind = obex_unbind;
 | 
						obex->port.func.unbind = obex_old_unbind;
 | 
				
			||||||
	obex->port.func.set_alt = obex_set_alt;
 | 
						obex->port.func.set_alt = obex_set_alt;
 | 
				
			||||||
	obex->port.func.get_alt = obex_get_alt;
 | 
						obex->port.func.get_alt = obex_get_alt;
 | 
				
			||||||
	obex->port.func.disable = obex_disable;
 | 
						obex->port.func.disable = obex_disable;
 | 
				
			||||||
| 
						 | 
					@ -453,5 +454,138 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return container_of(to_config_group(item), struct f_serial_opts,
 | 
				
			||||||
 | 
								    func_inst.group);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CONFIGFS_ATTR_STRUCT(f_serial_opts);
 | 
				
			||||||
 | 
					static ssize_t f_obex_attr_show(struct config_item *item,
 | 
				
			||||||
 | 
									struct configfs_attribute *attr,
 | 
				
			||||||
 | 
									char *page)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct f_serial_opts *opts = to_f_serial_opts(item);
 | 
				
			||||||
 | 
						struct f_serial_opts_attribute *f_serial_opts_attr =
 | 
				
			||||||
 | 
							container_of(attr, struct f_serial_opts_attribute, attr);
 | 
				
			||||||
 | 
						ssize_t ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (f_serial_opts_attr->show)
 | 
				
			||||||
 | 
							ret = f_serial_opts_attr->show(opts, page);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void obex_attr_release(struct config_item *item)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct f_serial_opts *opts = to_f_serial_opts(item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						usb_put_function_instance(&opts->func_inst);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct configfs_item_operations obex_item_ops = {
 | 
				
			||||||
 | 
						.release	= obex_attr_release,
 | 
				
			||||||
 | 
						.show_attribute = f_obex_attr_show,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ssize_t f_obex_port_num_show(struct f_serial_opts *opts, char *page)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return sprintf(page, "%u\n", opts->port_num);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct f_serial_opts_attribute f_obex_port_num =
 | 
				
			||||||
 | 
						__CONFIGFS_ATTR_RO(port_num, f_obex_port_num_show);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct configfs_attribute *acm_attrs[] = {
 | 
				
			||||||
 | 
						&f_obex_port_num.attr,
 | 
				
			||||||
 | 
						NULL,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct config_item_type obex_func_type = {
 | 
				
			||||||
 | 
						.ct_item_ops	= &obex_item_ops,
 | 
				
			||||||
 | 
						.ct_attrs	= acm_attrs,
 | 
				
			||||||
 | 
						.ct_owner	= THIS_MODULE,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void obex_free_inst(struct usb_function_instance *f)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct f_serial_opts *opts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						opts = container_of(f, struct f_serial_opts, func_inst);
 | 
				
			||||||
 | 
						gserial_free_line(opts->port_num);
 | 
				
			||||||
 | 
						kfree(opts);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct usb_function_instance *obex_alloc_inst(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct f_serial_opts *opts;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						opts = kzalloc(sizeof(*opts), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!opts)
 | 
				
			||||||
 | 
							return ERR_PTR(-ENOMEM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						opts->func_inst.free_func_inst = obex_free_inst;
 | 
				
			||||||
 | 
						ret = gserial_alloc_line(&opts->port_num);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							kfree(opts);
 | 
				
			||||||
 | 
							return ERR_PTR(ret);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						config_group_init_type_name(&opts->func_inst.group, "",
 | 
				
			||||||
 | 
									    &obex_func_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &opts->func_inst;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void obex_free(struct usb_function *f)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct f_obex *obex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						obex = func_to_obex(f);
 | 
				
			||||||
 | 
						kfree(obex);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void obex_unbind(struct usb_configuration *c, struct usb_function *f)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						obex_string_defs[OBEX_CTRL_IDX].id = 0;
 | 
				
			||||||
 | 
						usb_free_all_descriptors(f);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_function *obex_alloc(struct usb_function_instance *fi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct f_obex	*obex;
 | 
				
			||||||
 | 
						struct f_serial_opts *opts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* allocate and initialize one new instance */
 | 
				
			||||||
 | 
						obex = kzalloc(sizeof(*obex), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!obex)
 | 
				
			||||||
 | 
							return ERR_PTR(-ENOMEM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						opts = container_of(fi, struct f_serial_opts, func_inst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						obex->port_num = opts->port_num;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						obex->port.connect = obex_connect;
 | 
				
			||||||
 | 
						obex->port.disconnect = obex_disconnect;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						obex->port.func.name = "obex";
 | 
				
			||||||
 | 
						obex->port.func.strings = obex_strings;
 | 
				
			||||||
 | 
						/* descriptors are per-instance copies */
 | 
				
			||||||
 | 
						obex->port.func.bind = obex_bind;
 | 
				
			||||||
 | 
						obex->port.func.unbind = obex_unbind;
 | 
				
			||||||
 | 
						obex->port.func.set_alt = obex_set_alt;
 | 
				
			||||||
 | 
						obex->port.func.get_alt = obex_get_alt;
 | 
				
			||||||
 | 
						obex->port.func.disable = obex_disable;
 | 
				
			||||||
 | 
						obex->port.func.free_func = obex_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &obex->port.func;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DECLARE_USB_FUNCTION_INIT(obex, obex_alloc_inst, obex_alloc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MODULE_AUTHOR("Felipe Balbi");
 | 
					MODULE_AUTHOR("Felipe Balbi");
 | 
				
			||||||
MODULE_LICENSE("GPL");
 | 
					MODULE_LICENSE("GPL");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -813,7 +813,7 @@ static inline bool can_support_rndis(struct usb_configuration *c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
					rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
				u32 vendorID, const char *manufacturer)
 | 
							u32 vendorID, const char *manufacturer, struct eth_dev *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct f_rndis	*rndis;
 | 
						struct f_rndis	*rndis;
 | 
				
			||||||
	int		status;
 | 
						int		status;
 | 
				
			||||||
| 
						 | 
					@ -846,6 +846,7 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
	rndis->vendorID = vendorID;
 | 
						rndis->vendorID = vendorID;
 | 
				
			||||||
	rndis->manufacturer = manufacturer;
 | 
						rndis->manufacturer = manufacturer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rndis->port.ioport = dev;
 | 
				
			||||||
	/* RNDIS activates when the host changes this filter */
 | 
						/* RNDIS activates when the host changes this filter */
 | 
				
			||||||
	rndis->port.cdc_filter = 0;
 | 
						rndis->port.cdc_filter = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/slab.h>
 | 
					#include <linux/slab.h>
 | 
				
			||||||
#include <linux/kernel.h>
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
 | 
					#include <linux/module.h>
 | 
				
			||||||
#include <linux/device.h>
 | 
					#include <linux/device.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "u_serial.h"
 | 
					#include "u_serial.h"
 | 
				
			||||||
| 
						 | 
					@ -42,7 +43,7 @@ static inline struct f_gser *func_to_gser(struct usb_function *f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* interface descriptor: */
 | 
					/* interface descriptor: */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_interface_descriptor gser_interface_desc __initdata = {
 | 
					static struct usb_interface_descriptor gser_interface_desc = {
 | 
				
			||||||
	.bLength =		USB_DT_INTERFACE_SIZE,
 | 
						.bLength =		USB_DT_INTERFACE_SIZE,
 | 
				
			||||||
	.bDescriptorType =	USB_DT_INTERFACE,
 | 
						.bDescriptorType =	USB_DT_INTERFACE,
 | 
				
			||||||
	/* .bInterfaceNumber = DYNAMIC */
 | 
						/* .bInterfaceNumber = DYNAMIC */
 | 
				
			||||||
| 
						 | 
					@ -55,21 +56,21 @@ static struct usb_interface_descriptor gser_interface_desc __initdata = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* full speed support: */
 | 
					/* full speed support: */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_endpoint_descriptor gser_fs_in_desc __initdata = {
 | 
					static struct usb_endpoint_descriptor gser_fs_in_desc = {
 | 
				
			||||||
	.bLength =		USB_DT_ENDPOINT_SIZE,
 | 
						.bLength =		USB_DT_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType =	USB_DT_ENDPOINT,
 | 
						.bDescriptorType =	USB_DT_ENDPOINT,
 | 
				
			||||||
	.bEndpointAddress =	USB_DIR_IN,
 | 
						.bEndpointAddress =	USB_DIR_IN,
 | 
				
			||||||
	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 | 
						.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_endpoint_descriptor gser_fs_out_desc __initdata = {
 | 
					static struct usb_endpoint_descriptor gser_fs_out_desc = {
 | 
				
			||||||
	.bLength =		USB_DT_ENDPOINT_SIZE,
 | 
						.bLength =		USB_DT_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType =	USB_DT_ENDPOINT,
 | 
						.bDescriptorType =	USB_DT_ENDPOINT,
 | 
				
			||||||
	.bEndpointAddress =	USB_DIR_OUT,
 | 
						.bEndpointAddress =	USB_DIR_OUT,
 | 
				
			||||||
	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 | 
						.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_descriptor_header *gser_fs_function[] __initdata = {
 | 
					static struct usb_descriptor_header *gser_fs_function[] = {
 | 
				
			||||||
	(struct usb_descriptor_header *) &gser_interface_desc,
 | 
						(struct usb_descriptor_header *) &gser_interface_desc,
 | 
				
			||||||
	(struct usb_descriptor_header *) &gser_fs_in_desc,
 | 
						(struct usb_descriptor_header *) &gser_fs_in_desc,
 | 
				
			||||||
	(struct usb_descriptor_header *) &gser_fs_out_desc,
 | 
						(struct usb_descriptor_header *) &gser_fs_out_desc,
 | 
				
			||||||
| 
						 | 
					@ -78,47 +79,47 @@ static struct usb_descriptor_header *gser_fs_function[] __initdata = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* high speed support: */
 | 
					/* high speed support: */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = {
 | 
					static struct usb_endpoint_descriptor gser_hs_in_desc = {
 | 
				
			||||||
	.bLength =		USB_DT_ENDPOINT_SIZE,
 | 
						.bLength =		USB_DT_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType =	USB_DT_ENDPOINT,
 | 
						.bDescriptorType =	USB_DT_ENDPOINT,
 | 
				
			||||||
	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 | 
						.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 | 
				
			||||||
	.wMaxPacketSize =	cpu_to_le16(512),
 | 
						.wMaxPacketSize =	cpu_to_le16(512),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = {
 | 
					static struct usb_endpoint_descriptor gser_hs_out_desc = {
 | 
				
			||||||
	.bLength =		USB_DT_ENDPOINT_SIZE,
 | 
						.bLength =		USB_DT_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType =	USB_DT_ENDPOINT,
 | 
						.bDescriptorType =	USB_DT_ENDPOINT,
 | 
				
			||||||
	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 | 
						.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 | 
				
			||||||
	.wMaxPacketSize =	cpu_to_le16(512),
 | 
						.wMaxPacketSize =	cpu_to_le16(512),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_descriptor_header *gser_hs_function[] __initdata = {
 | 
					static struct usb_descriptor_header *gser_hs_function[] = {
 | 
				
			||||||
	(struct usb_descriptor_header *) &gser_interface_desc,
 | 
						(struct usb_descriptor_header *) &gser_interface_desc,
 | 
				
			||||||
	(struct usb_descriptor_header *) &gser_hs_in_desc,
 | 
						(struct usb_descriptor_header *) &gser_hs_in_desc,
 | 
				
			||||||
	(struct usb_descriptor_header *) &gser_hs_out_desc,
 | 
						(struct usb_descriptor_header *) &gser_hs_out_desc,
 | 
				
			||||||
	NULL,
 | 
						NULL,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_endpoint_descriptor gser_ss_in_desc __initdata = {
 | 
					static struct usb_endpoint_descriptor gser_ss_in_desc = {
 | 
				
			||||||
	.bLength =		USB_DT_ENDPOINT_SIZE,
 | 
						.bLength =		USB_DT_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType =	USB_DT_ENDPOINT,
 | 
						.bDescriptorType =	USB_DT_ENDPOINT,
 | 
				
			||||||
	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 | 
						.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 | 
				
			||||||
	.wMaxPacketSize =	cpu_to_le16(1024),
 | 
						.wMaxPacketSize =	cpu_to_le16(1024),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_endpoint_descriptor gser_ss_out_desc __initdata = {
 | 
					static struct usb_endpoint_descriptor gser_ss_out_desc = {
 | 
				
			||||||
	.bLength =		USB_DT_ENDPOINT_SIZE,
 | 
						.bLength =		USB_DT_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType =	USB_DT_ENDPOINT,
 | 
						.bDescriptorType =	USB_DT_ENDPOINT,
 | 
				
			||||||
	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 | 
						.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 | 
				
			||||||
	.wMaxPacketSize =	cpu_to_le16(1024),
 | 
						.wMaxPacketSize =	cpu_to_le16(1024),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc __initdata = {
 | 
					static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc = {
 | 
				
			||||||
	.bLength =              sizeof gser_ss_bulk_comp_desc,
 | 
						.bLength =              sizeof gser_ss_bulk_comp_desc,
 | 
				
			||||||
	.bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
 | 
						.bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_descriptor_header *gser_ss_function[] __initdata = {
 | 
					static struct usb_descriptor_header *gser_ss_function[] = {
 | 
				
			||||||
	(struct usb_descriptor_header *) &gser_interface_desc,
 | 
						(struct usb_descriptor_header *) &gser_interface_desc,
 | 
				
			||||||
	(struct usb_descriptor_header *) &gser_ss_in_desc,
 | 
						(struct usb_descriptor_header *) &gser_ss_in_desc,
 | 
				
			||||||
	(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
 | 
						(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
 | 
				
			||||||
| 
						 | 
					@ -183,14 +184,25 @@ static void gser_disable(struct usb_function *f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* serial function driver setup/binding */
 | 
					/* serial function driver setup/binding */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init
 | 
					static int gser_bind(struct usb_configuration *c, struct usb_function *f)
 | 
				
			||||||
gser_bind(struct usb_configuration *c, struct usb_function *f)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usb_composite_dev *cdev = c->cdev;
 | 
						struct usb_composite_dev *cdev = c->cdev;
 | 
				
			||||||
	struct f_gser		*gser = func_to_gser(f);
 | 
						struct f_gser		*gser = func_to_gser(f);
 | 
				
			||||||
	int			status;
 | 
						int			status;
 | 
				
			||||||
	struct usb_ep		*ep;
 | 
						struct usb_ep		*ep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* REVISIT might want instance-specific strings to help
 | 
				
			||||||
 | 
						 * distinguish instances ...
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* maybe allocate device-global string ID */
 | 
				
			||||||
 | 
						if (gser_string_defs[0].id == 0) {
 | 
				
			||||||
 | 
							status = usb_string_id(c->cdev);
 | 
				
			||||||
 | 
							if (status < 0)
 | 
				
			||||||
 | 
								return status;
 | 
				
			||||||
 | 
							gser_string_defs[0].id = status;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* allocate instance-specific interface IDs */
 | 
						/* allocate instance-specific interface IDs */
 | 
				
			||||||
	status = usb_interface_id(c, f);
 | 
						status = usb_interface_id(c, f);
 | 
				
			||||||
	if (status < 0)
 | 
						if (status < 0)
 | 
				
			||||||
| 
						 | 
					@ -246,44 +258,115 @@ fail:
 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
 | 
				
			||||||
gser_unbind(struct usb_configuration *c, struct usb_function *f)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	usb_free_all_descriptors(f);
 | 
						return container_of(to_config_group(item), struct f_serial_opts,
 | 
				
			||||||
	kfree(func_to_gser(f));
 | 
								    func_inst.group);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					CONFIGFS_ATTR_STRUCT(f_serial_opts);
 | 
				
			||||||
 * gser_bind_config - add a generic serial function to a configuration
 | 
					static ssize_t f_serial_attr_show(struct config_item *item,
 | 
				
			||||||
 * @c: the configuration to support the serial instance
 | 
									  struct configfs_attribute *attr,
 | 
				
			||||||
 * @port_num: /dev/ttyGS* port this interface will use
 | 
									  char *page)
 | 
				
			||||||
 * Context: single threaded during gadget setup
 | 
					{
 | 
				
			||||||
 *
 | 
						struct f_serial_opts *opts = to_f_serial_opts(item);
 | 
				
			||||||
 * Returns zero on success, else negative errno.
 | 
						struct f_serial_opts_attribute *f_serial_opts_attr =
 | 
				
			||||||
 */
 | 
							container_of(attr, struct f_serial_opts_attribute, attr);
 | 
				
			||||||
int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
 | 
						ssize_t ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (f_serial_opts_attr->show)
 | 
				
			||||||
 | 
							ret = f_serial_opts_attr->show(opts, page);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void serial_attr_release(struct config_item *item)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct f_serial_opts *opts = to_f_serial_opts(item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						usb_put_function_instance(&opts->func_inst);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct configfs_item_operations serial_item_ops = {
 | 
				
			||||||
 | 
						.release	= serial_attr_release,
 | 
				
			||||||
 | 
						.show_attribute = f_serial_attr_show,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ssize_t f_serial_port_num_show(struct f_serial_opts *opts, char *page)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return sprintf(page, "%u\n", opts->port_num);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct f_serial_opts_attribute f_serial_port_num =
 | 
				
			||||||
 | 
						__CONFIGFS_ATTR_RO(port_num, f_serial_port_num_show);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct configfs_attribute *acm_attrs[] = {
 | 
				
			||||||
 | 
						&f_serial_port_num.attr,
 | 
				
			||||||
 | 
						NULL,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct config_item_type serial_func_type = {
 | 
				
			||||||
 | 
						.ct_item_ops	= &serial_item_ops,
 | 
				
			||||||
 | 
						.ct_attrs	= acm_attrs,
 | 
				
			||||||
 | 
						.ct_owner	= THIS_MODULE,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gser_free_inst(struct usb_function_instance *f)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct f_serial_opts *opts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						opts = container_of(f, struct f_serial_opts, func_inst);
 | 
				
			||||||
 | 
						gserial_free_line(opts->port_num);
 | 
				
			||||||
 | 
						kfree(opts);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct usb_function_instance *gser_alloc_inst(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct f_serial_opts *opts;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						opts = kzalloc(sizeof(*opts), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!opts)
 | 
				
			||||||
 | 
							return ERR_PTR(-ENOMEM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						opts->func_inst.free_func_inst = gser_free_inst;
 | 
				
			||||||
 | 
						ret = gserial_alloc_line(&opts->port_num);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							kfree(opts);
 | 
				
			||||||
 | 
							return ERR_PTR(ret);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						config_group_init_type_name(&opts->func_inst.group, "",
 | 
				
			||||||
 | 
									    &serial_func_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &opts->func_inst;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gser_free(struct usb_function *f)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct f_gser *serial;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						serial = func_to_gser(f);
 | 
				
			||||||
 | 
						kfree(serial);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gser_unbind(struct usb_configuration *c, struct usb_function *f)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						usb_free_all_descriptors(f);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_function *gser_alloc(struct usb_function_instance *fi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct f_gser	*gser;
 | 
						struct f_gser	*gser;
 | 
				
			||||||
	int		status;
 | 
						struct f_serial_opts *opts;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* REVISIT might want instance-specific strings to help
 | 
					 | 
				
			||||||
	 * distinguish instances ...
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* maybe allocate device-global string ID */
 | 
					 | 
				
			||||||
	if (gser_string_defs[0].id == 0) {
 | 
					 | 
				
			||||||
		status = usb_string_id(c->cdev);
 | 
					 | 
				
			||||||
		if (status < 0)
 | 
					 | 
				
			||||||
			return status;
 | 
					 | 
				
			||||||
		gser_string_defs[0].id = status;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* allocate and initialize one new instance */
 | 
						/* allocate and initialize one new instance */
 | 
				
			||||||
	gser = kzalloc(sizeof *gser, GFP_KERNEL);
 | 
						gser = kzalloc(sizeof(*gser), GFP_KERNEL);
 | 
				
			||||||
	if (!gser)
 | 
						if (!gser)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return ERR_PTR(-ENOMEM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gser->port_num = port_num;
 | 
						opts = container_of(fi, struct f_serial_opts, func_inst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gser->port_num = opts->port_num;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gser->port.func.name = "gser";
 | 
						gser->port.func.name = "gser";
 | 
				
			||||||
	gser->port.func.strings = gser_strings;
 | 
						gser->port.func.strings = gser_strings;
 | 
				
			||||||
| 
						 | 
					@ -291,9 +374,12 @@ int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
 | 
				
			||||||
	gser->port.func.unbind = gser_unbind;
 | 
						gser->port.func.unbind = gser_unbind;
 | 
				
			||||||
	gser->port.func.set_alt = gser_set_alt;
 | 
						gser->port.func.set_alt = gser_set_alt;
 | 
				
			||||||
	gser->port.func.disable = gser_disable;
 | 
						gser->port.func.disable = gser_disable;
 | 
				
			||||||
 | 
						gser->port.func.free_func = gser_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = usb_add_function(c, &gser->port.func);
 | 
						return &gser->port.func;
 | 
				
			||||||
	if (status)
 | 
					 | 
				
			||||||
		kfree(gser);
 | 
					 | 
				
			||||||
	return status;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DECLARE_USB_FUNCTION_INIT(gser, gser_alloc_inst, gser_alloc);
 | 
				
			||||||
 | 
					MODULE_LICENSE("GPL");
 | 
				
			||||||
 | 
					MODULE_AUTHOR("Al Borchers");
 | 
				
			||||||
 | 
					MODULE_AUTHOR("David Brownell");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -380,7 +380,8 @@ geth_unbind(struct usb_configuration *c, struct usb_function *f)
 | 
				
			||||||
 * Caller must have called @gether_setup().  Caller is also responsible
 | 
					 * Caller must have called @gether_setup().  Caller is also responsible
 | 
				
			||||||
 * for calling @gether_cleanup() before module unload.
 | 
					 * for calling @gether_cleanup() before module unload.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 | 
					int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
 | 
							struct eth_dev *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct f_gether	*geth;
 | 
						struct f_gether	*geth;
 | 
				
			||||||
	int		status;
 | 
						int		status;
 | 
				
			||||||
| 
						 | 
					@ -406,6 +407,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 | 
				
			||||||
	snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr);
 | 
						snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr);
 | 
				
			||||||
	geth_string_defs[1].s = geth->ethaddr;
 | 
						geth_string_defs[1].s = geth->ethaddr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						geth->port.ioport = dev;
 | 
				
			||||||
	geth->port.cdc_filter = DEFAULT_FILTER;
 | 
						geth->port.cdc_filter = DEFAULT_FILTER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	geth->port.func.name = "cdc_subset";
 | 
						geth->port.func.name = "cdc_subset";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,19 +33,15 @@ unsigned int uvc_gadget_trace_param;
 | 
				
			||||||
/*-------------------------------------------------------------------------*/
 | 
					/*-------------------------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* module parameters specific to the Video streaming endpoint */
 | 
					/* module parameters specific to the Video streaming endpoint */
 | 
				
			||||||
static unsigned streaming_interval = 1;
 | 
					static unsigned int streaming_interval = 1;
 | 
				
			||||||
module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
 | 
					module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
 | 
				
			||||||
MODULE_PARM_DESC(streaming_interval, "1 - 16");
 | 
					MODULE_PARM_DESC(streaming_interval, "1 - 16");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static unsigned streaming_maxpacket = 1024;
 | 
					static unsigned int streaming_maxpacket = 1024;
 | 
				
			||||||
module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
 | 
					module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
 | 
				
			||||||
MODULE_PARM_DESC(streaming_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
 | 
					MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static unsigned streaming_mult;
 | 
					static unsigned int streaming_maxburst;
 | 
				
			||||||
module_param(streaming_mult, uint, S_IRUGO|S_IWUSR);
 | 
					 | 
				
			||||||
MODULE_PARM_DESC(streaming_mult, "0 - 2 (hs/ss only)");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static unsigned streaming_maxburst;
 | 
					 | 
				
			||||||
module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
 | 
					module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
 | 
				
			||||||
MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
 | 
					MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,13 +51,11 @@ MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* string IDs are assigned dynamically */
 | 
					/* string IDs are assigned dynamically */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define UVC_STRING_ASSOCIATION_IDX		0
 | 
					#define UVC_STRING_CONTROL_IDX			0
 | 
				
			||||||
#define UVC_STRING_CONTROL_IDX			1
 | 
					#define UVC_STRING_STREAMING_IDX		1
 | 
				
			||||||
#define UVC_STRING_STREAMING_IDX		2
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_string uvc_en_us_strings[] = {
 | 
					static struct usb_string uvc_en_us_strings[] = {
 | 
				
			||||||
	[UVC_STRING_ASSOCIATION_IDX].s = "UVC Camera",
 | 
						[UVC_STRING_CONTROL_IDX].s = "UVC Camera",
 | 
				
			||||||
	[UVC_STRING_CONTROL_IDX].s = "Video Control",
 | 
					 | 
				
			||||||
	[UVC_STRING_STREAMING_IDX].s = "Video Streaming",
 | 
						[UVC_STRING_STREAMING_IDX].s = "Video Streaming",
 | 
				
			||||||
	{  }
 | 
						{  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -79,7 +73,7 @@ static struct usb_gadget_strings *uvc_function_strings[] = {
 | 
				
			||||||
#define UVC_INTF_VIDEO_CONTROL			0
 | 
					#define UVC_INTF_VIDEO_CONTROL			0
 | 
				
			||||||
#define UVC_INTF_VIDEO_STREAMING		1
 | 
					#define UVC_INTF_VIDEO_STREAMING		1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define STATUS_BYTECOUNT			16	/* 16 bytes status */
 | 
					#define UVC_STATUS_MAX_PACKET_SIZE		16	/* 16 bytes status */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_interface_assoc_descriptor uvc_iad __initdata = {
 | 
					static struct usb_interface_assoc_descriptor uvc_iad __initdata = {
 | 
				
			||||||
	.bLength		= sizeof(uvc_iad),
 | 
						.bLength		= sizeof(uvc_iad),
 | 
				
			||||||
| 
						 | 
					@ -104,20 +98,29 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = {
 | 
				
			||||||
	.iInterface		= 0,
 | 
						.iInterface		= 0,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = {
 | 
					static struct usb_endpoint_descriptor uvc_control_ep __initdata = {
 | 
				
			||||||
	.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
						.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType	= USB_DT_ENDPOINT,
 | 
						.bDescriptorType	= USB_DT_ENDPOINT,
 | 
				
			||||||
	.bEndpointAddress	= USB_DIR_IN,
 | 
						.bEndpointAddress	= USB_DIR_IN,
 | 
				
			||||||
	.bmAttributes		= USB_ENDPOINT_XFER_INT,
 | 
						.bmAttributes		= USB_ENDPOINT_XFER_INT,
 | 
				
			||||||
	.wMaxPacketSize		= cpu_to_le16(STATUS_BYTECOUNT),
 | 
						.wMaxPacketSize		= cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
 | 
				
			||||||
	.bInterval		= 8,
 | 
						.bInterval		= 8,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = {
 | 
				
			||||||
 | 
						.bLength		= sizeof(uvc_ss_control_comp),
 | 
				
			||||||
 | 
						.bDescriptorType	= USB_DT_SS_ENDPOINT_COMP,
 | 
				
			||||||
 | 
						/* The following 3 values can be tweaked if necessary. */
 | 
				
			||||||
 | 
						.bMaxBurst		= 0,
 | 
				
			||||||
 | 
						.bmAttributes		= 0,
 | 
				
			||||||
 | 
						.wBytesPerInterval	= cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = {
 | 
					static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = {
 | 
				
			||||||
	.bLength		= UVC_DT_CONTROL_ENDPOINT_SIZE,
 | 
						.bLength		= UVC_DT_CONTROL_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType	= USB_DT_CS_ENDPOINT,
 | 
						.bDescriptorType	= USB_DT_CS_ENDPOINT,
 | 
				
			||||||
	.bDescriptorSubType	= UVC_EP_INTERRUPT,
 | 
						.bDescriptorSubType	= UVC_EP_INTERRUPT,
 | 
				
			||||||
	.wMaxTransferSize	= cpu_to_le16(STATUS_BYTECOUNT),
 | 
						.wMaxTransferSize	= cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = {
 | 
					static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = {
 | 
				
			||||||
| 
						 | 
					@ -144,63 +147,53 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = {
 | 
				
			||||||
	.iInterface		= 0,
 | 
						.iInterface		= 0,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_endpoint_descriptor uvc_fs_streaming_ep = {
 | 
					static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = {
 | 
				
			||||||
	.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
						.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType	= USB_DT_ENDPOINT,
 | 
						.bDescriptorType	= USB_DT_ENDPOINT,
 | 
				
			||||||
	.bEndpointAddress	= USB_DIR_IN,
 | 
						.bEndpointAddress	= USB_DIR_IN,
 | 
				
			||||||
	.bmAttributes		= USB_ENDPOINT_XFER_ISOC,
 | 
						.bmAttributes		= USB_ENDPOINT_SYNC_ASYNC
 | 
				
			||||||
	.wMaxPacketSize		= cpu_to_le16(512),
 | 
									| USB_ENDPOINT_XFER_ISOC,
 | 
				
			||||||
	.bInterval		= 1,
 | 
						/* The wMaxPacketSize and bInterval values will be initialized from
 | 
				
			||||||
 | 
						 * module parameters.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						.wMaxPacketSize		= 0,
 | 
				
			||||||
 | 
						.bInterval		= 0,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_endpoint_descriptor uvc_hs_streaming_ep = {
 | 
					static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = {
 | 
				
			||||||
	.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
						.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType	= USB_DT_ENDPOINT,
 | 
						.bDescriptorType	= USB_DT_ENDPOINT,
 | 
				
			||||||
	.bEndpointAddress	= USB_DIR_IN,
 | 
						.bEndpointAddress	= USB_DIR_IN,
 | 
				
			||||||
	.bmAttributes		= USB_ENDPOINT_XFER_ISOC,
 | 
						.bmAttributes		= USB_ENDPOINT_SYNC_ASYNC
 | 
				
			||||||
	.wMaxPacketSize		= cpu_to_le16(1024),
 | 
									| USB_ENDPOINT_XFER_ISOC,
 | 
				
			||||||
	.bInterval		= 1,
 | 
						/* The wMaxPacketSize and bInterval values will be initialized from
 | 
				
			||||||
};
 | 
						 * module parameters.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
/* super speed support */
 | 
						.wMaxPacketSize		= 0,
 | 
				
			||||||
static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = {
 | 
						.bInterval		= 0,
 | 
				
			||||||
	.bLength =		USB_DT_ENDPOINT_SIZE,
 | 
					 | 
				
			||||||
	.bDescriptorType =	USB_DT_ENDPOINT,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	.bEndpointAddress =	USB_DIR_IN,
 | 
					 | 
				
			||||||
	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 | 
					 | 
				
			||||||
	.wMaxPacketSize =	cpu_to_le16(STATUS_BYTECOUNT),
 | 
					 | 
				
			||||||
	.bInterval =		8,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = {
 | 
					 | 
				
			||||||
	.bLength =		sizeof uvc_ss_control_comp,
 | 
					 | 
				
			||||||
	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* the following 3 values can be tweaked if necessary */
 | 
					 | 
				
			||||||
	/* .bMaxBurst =		0, */
 | 
					 | 
				
			||||||
	/* .bmAttributes =	0, */
 | 
					 | 
				
			||||||
	.wBytesPerInterval =	cpu_to_le16(STATUS_BYTECOUNT),
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = {
 | 
					static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = {
 | 
				
			||||||
	.bLength =		USB_DT_ENDPOINT_SIZE,
 | 
						.bLength		= USB_DT_ENDPOINT_SIZE,
 | 
				
			||||||
	.bDescriptorType =	USB_DT_ENDPOINT,
 | 
						.bDescriptorType	= USB_DT_ENDPOINT,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.bEndpointAddress =	USB_DIR_IN,
 | 
						.bEndpointAddress	= USB_DIR_IN,
 | 
				
			||||||
	.bmAttributes =		USB_ENDPOINT_XFER_ISOC,
 | 
						.bmAttributes		= USB_ENDPOINT_SYNC_ASYNC
 | 
				
			||||||
	.wMaxPacketSize =	cpu_to_le16(1024),
 | 
									| USB_ENDPOINT_XFER_ISOC,
 | 
				
			||||||
	.bInterval =		4,
 | 
						/* The wMaxPacketSize and bInterval values will be initialized from
 | 
				
			||||||
 | 
						 * module parameters.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						.wMaxPacketSize		= 0,
 | 
				
			||||||
 | 
						.bInterval		= 0,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = {
 | 
					static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp __initdata = {
 | 
				
			||||||
	.bLength =		sizeof uvc_ss_streaming_comp,
 | 
						.bLength		= sizeof(uvc_ss_streaming_comp),
 | 
				
			||||||
	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 | 
						.bDescriptorType	= USB_DT_SS_ENDPOINT_COMP,
 | 
				
			||||||
 | 
						/* The following 3 values can be tweaked if necessary. */
 | 
				
			||||||
	/* the following 3 values can be tweaked if necessary */
 | 
						.bMaxBurst		= 0,
 | 
				
			||||||
	.bMaxBurst =		0,
 | 
						.bmAttributes		= 0,
 | 
				
			||||||
	.bmAttributes =	0,
 | 
						.wBytesPerInterval	= cpu_to_le16(1024),
 | 
				
			||||||
	.wBytesPerInterval =	cpu_to_le16(1024),
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
 | 
					static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
 | 
				
			||||||
| 
						 | 
					@ -273,6 +266,13 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void uvc_function_setup_continue(struct uvc_device *uvc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct usb_composite_dev *cdev = uvc->func.config->cdev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						usb_composite_setup_continue(cdev);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
uvc_function_get_alt(struct usb_function *f, unsigned interface)
 | 
					uvc_function_get_alt(struct usb_function *f, unsigned interface)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -335,7 +335,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
 | 
				
			||||||
		v4l2_event_queue(uvc->vdev, &v4l2_event);
 | 
							v4l2_event_queue(uvc->vdev, &v4l2_event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		uvc->state = UVC_STATE_CONNECTED;
 | 
							uvc->state = UVC_STATE_CONNECTED;
 | 
				
			||||||
		break;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case 1:
 | 
						case 1:
 | 
				
			||||||
		if (uvc->state != UVC_STATE_CONNECTED)
 | 
							if (uvc->state != UVC_STATE_CONNECTED)
 | 
				
			||||||
| 
						 | 
					@ -352,15 +352,11 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
 | 
				
			||||||
		memset(&v4l2_event, 0, sizeof(v4l2_event));
 | 
							memset(&v4l2_event, 0, sizeof(v4l2_event));
 | 
				
			||||||
		v4l2_event.type = UVC_EVENT_STREAMON;
 | 
							v4l2_event.type = UVC_EVENT_STREAMON;
 | 
				
			||||||
		v4l2_event_queue(uvc->vdev, &v4l2_event);
 | 
							v4l2_event_queue(uvc->vdev, &v4l2_event);
 | 
				
			||||||
 | 
							return USB_GADGET_DELAYED_STATUS;
 | 
				
			||||||
		uvc->state = UVC_STATE_STREAMING;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
| 
						 | 
					@ -454,7 +450,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 | 
				
			||||||
	const struct uvc_descriptor_header * const *uvc_streaming_cls;
 | 
						const struct uvc_descriptor_header * const *uvc_streaming_cls;
 | 
				
			||||||
	const struct usb_descriptor_header * const *uvc_streaming_std;
 | 
						const struct usb_descriptor_header * const *uvc_streaming_std;
 | 
				
			||||||
	const struct usb_descriptor_header * const *src;
 | 
						const struct usb_descriptor_header * const *src;
 | 
				
			||||||
	static struct usb_endpoint_descriptor *uvc_control_ep;
 | 
					 | 
				
			||||||
	struct usb_descriptor_header **dst;
 | 
						struct usb_descriptor_header **dst;
 | 
				
			||||||
	struct usb_descriptor_header **hdr;
 | 
						struct usb_descriptor_header **hdr;
 | 
				
			||||||
	unsigned int control_size;
 | 
						unsigned int control_size;
 | 
				
			||||||
| 
						 | 
					@ -468,14 +463,12 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 | 
				
			||||||
		uvc_control_desc = uvc->desc.ss_control;
 | 
							uvc_control_desc = uvc->desc.ss_control;
 | 
				
			||||||
		uvc_streaming_cls = uvc->desc.ss_streaming;
 | 
							uvc_streaming_cls = uvc->desc.ss_streaming;
 | 
				
			||||||
		uvc_streaming_std = uvc_ss_streaming;
 | 
							uvc_streaming_std = uvc_ss_streaming;
 | 
				
			||||||
		uvc_control_ep = &uvc_ss_control_ep;
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case USB_SPEED_HIGH:
 | 
						case USB_SPEED_HIGH:
 | 
				
			||||||
		uvc_control_desc = uvc->desc.fs_control;
 | 
							uvc_control_desc = uvc->desc.fs_control;
 | 
				
			||||||
		uvc_streaming_cls = uvc->desc.hs_streaming;
 | 
							uvc_streaming_cls = uvc->desc.hs_streaming;
 | 
				
			||||||
		uvc_streaming_std = uvc_hs_streaming;
 | 
							uvc_streaming_std = uvc_hs_streaming;
 | 
				
			||||||
		uvc_control_ep = &uvc_fs_control_ep;
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case USB_SPEED_FULL:
 | 
						case USB_SPEED_FULL:
 | 
				
			||||||
| 
						 | 
					@ -483,7 +476,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 | 
				
			||||||
		uvc_control_desc = uvc->desc.fs_control;
 | 
							uvc_control_desc = uvc->desc.fs_control;
 | 
				
			||||||
		uvc_streaming_cls = uvc->desc.fs_streaming;
 | 
							uvc_streaming_cls = uvc->desc.fs_streaming;
 | 
				
			||||||
		uvc_streaming_std = uvc_fs_streaming;
 | 
							uvc_streaming_std = uvc_fs_streaming;
 | 
				
			||||||
		uvc_control_ep = &uvc_fs_control_ep;
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -494,6 +486,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 | 
				
			||||||
	 * Class-specific UVC control descriptors
 | 
						 * Class-specific UVC control descriptors
 | 
				
			||||||
	 * uvc_control_ep
 | 
						 * uvc_control_ep
 | 
				
			||||||
	 * uvc_control_cs_ep
 | 
						 * uvc_control_cs_ep
 | 
				
			||||||
 | 
						 * uvc_ss_control_comp (for SS only)
 | 
				
			||||||
	 * uvc_streaming_intf_alt0
 | 
						 * uvc_streaming_intf_alt0
 | 
				
			||||||
	 * Class-specific UVC streaming descriptors
 | 
						 * Class-specific UVC streaming descriptors
 | 
				
			||||||
	 * uvc_{fs|hs}_streaming
 | 
						 * uvc_{fs|hs}_streaming
 | 
				
			||||||
| 
						 | 
					@ -503,7 +496,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 | 
				
			||||||
	control_size = 0;
 | 
						control_size = 0;
 | 
				
			||||||
	streaming_size = 0;
 | 
						streaming_size = 0;
 | 
				
			||||||
	bytes = uvc_iad.bLength + uvc_control_intf.bLength
 | 
						bytes = uvc_iad.bLength + uvc_control_intf.bLength
 | 
				
			||||||
	      + uvc_control_ep->bLength + uvc_control_cs_ep.bLength
 | 
						      + uvc_control_ep.bLength + uvc_control_cs_ep.bLength
 | 
				
			||||||
	      + uvc_streaming_intf_alt0.bLength;
 | 
						      + uvc_streaming_intf_alt0.bLength;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (speed == USB_SPEED_SUPER) {
 | 
						if (speed == USB_SPEED_SUPER) {
 | 
				
			||||||
| 
						 | 
					@ -514,13 +507,13 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (src = (const struct usb_descriptor_header **)uvc_control_desc;
 | 
						for (src = (const struct usb_descriptor_header **)uvc_control_desc;
 | 
				
			||||||
			*src; ++src) {
 | 
						     *src; ++src) {
 | 
				
			||||||
		control_size += (*src)->bLength;
 | 
							control_size += (*src)->bLength;
 | 
				
			||||||
		bytes += (*src)->bLength;
 | 
							bytes += (*src)->bLength;
 | 
				
			||||||
		n_desc++;
 | 
							n_desc++;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for (src = (const struct usb_descriptor_header **)uvc_streaming_cls;
 | 
						for (src = (const struct usb_descriptor_header **)uvc_streaming_cls;
 | 
				
			||||||
			*src; ++src) {
 | 
						     *src; ++src) {
 | 
				
			||||||
		streaming_size += (*src)->bLength;
 | 
							streaming_size += (*src)->bLength;
 | 
				
			||||||
		bytes += (*src)->bLength;
 | 
							bytes += (*src)->bLength;
 | 
				
			||||||
		n_desc++;
 | 
							n_desc++;
 | 
				
			||||||
| 
						 | 
					@ -549,7 +542,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 | 
				
			||||||
	uvc_control_header->bInCollection = 1;
 | 
						uvc_control_header->bInCollection = 1;
 | 
				
			||||||
	uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
 | 
						uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	UVC_COPY_DESCRIPTOR(mem, dst, uvc_control_ep);
 | 
						UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep);
 | 
				
			||||||
	if (speed == USB_SPEED_SUPER)
 | 
						if (speed == USB_SPEED_SUPER)
 | 
				
			||||||
		UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp);
 | 
							UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -560,8 +553,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 | 
				
			||||||
	UVC_COPY_DESCRIPTORS(mem, dst,
 | 
						UVC_COPY_DESCRIPTORS(mem, dst,
 | 
				
			||||||
		(const struct usb_descriptor_header**)uvc_streaming_cls);
 | 
							(const struct usb_descriptor_header**)uvc_streaming_cls);
 | 
				
			||||||
	uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size);
 | 
						uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size);
 | 
				
			||||||
	uvc_streaming_header->bEndpointAddress =
 | 
						uvc_streaming_header->bEndpointAddress = uvc->video.ep->address;
 | 
				
			||||||
		uvc_fs_streaming_ep.bEndpointAddress;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std);
 | 
						UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -581,7 +573,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
 | 
				
			||||||
	uvc->control_ep->driver_data = NULL;
 | 
						uvc->control_ep->driver_data = NULL;
 | 
				
			||||||
	uvc->video.ep->driver_data = NULL;
 | 
						uvc->video.ep->driver_data = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0;
 | 
						uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = 0;
 | 
				
			||||||
	usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
 | 
						usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
 | 
				
			||||||
	kfree(uvc->control_buf);
 | 
						kfree(uvc->control_buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -595,31 +587,52 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usb_composite_dev *cdev = c->cdev;
 | 
						struct usb_composite_dev *cdev = c->cdev;
 | 
				
			||||||
	struct uvc_device *uvc = to_uvc(f);
 | 
						struct uvc_device *uvc = to_uvc(f);
 | 
				
			||||||
 | 
						unsigned int max_packet_mult;
 | 
				
			||||||
 | 
						unsigned int max_packet_size;
 | 
				
			||||||
	struct usb_ep *ep;
 | 
						struct usb_ep *ep;
 | 
				
			||||||
	int ret = -EINVAL;
 | 
						int ret = -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	INFO(cdev, "uvc_function_bind\n");
 | 
						INFO(cdev, "uvc_function_bind\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* sanity check the streaming endpoint module parameters */
 | 
						/* Sanity check the streaming endpoint module parameters.
 | 
				
			||||||
	if (streaming_interval < 1)
 | 
					 | 
				
			||||||
		streaming_interval = 1;
 | 
					 | 
				
			||||||
	if (streaming_interval > 16)
 | 
					 | 
				
			||||||
		streaming_interval = 16;
 | 
					 | 
				
			||||||
	if (streaming_mult > 2)
 | 
					 | 
				
			||||||
		streaming_mult = 2;
 | 
					 | 
				
			||||||
	if (streaming_maxburst > 15)
 | 
					 | 
				
			||||||
		streaming_maxburst = 15;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * fill in the FS video streaming specific descriptors from the
 | 
					 | 
				
			||||||
	 * module parameters
 | 
					 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	uvc_fs_streaming_ep.wMaxPacketSize = streaming_maxpacket > 1023 ?
 | 
						streaming_interval = clamp(streaming_interval, 1U, 16U);
 | 
				
			||||||
						1023 : streaming_maxpacket;
 | 
						streaming_maxpacket = clamp(streaming_maxpacket, 1U, 3072U);
 | 
				
			||||||
 | 
						streaming_maxburst = min(streaming_maxburst, 15U);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Fill in the FS/HS/SS Video Streaming specific descriptors from the
 | 
				
			||||||
 | 
						 * module parameters.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * NOTE: We assume that the user knows what they are doing and won't
 | 
				
			||||||
 | 
						 * give parameters that their UDC doesn't support.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (streaming_maxpacket <= 1024) {
 | 
				
			||||||
 | 
							max_packet_mult = 1;
 | 
				
			||||||
 | 
							max_packet_size = streaming_maxpacket;
 | 
				
			||||||
 | 
						} else if (streaming_maxpacket <= 2048) {
 | 
				
			||||||
 | 
							max_packet_mult = 2;
 | 
				
			||||||
 | 
							max_packet_size = streaming_maxpacket / 2;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							max_packet_mult = 3;
 | 
				
			||||||
 | 
							max_packet_size = streaming_maxpacket / 3;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uvc_fs_streaming_ep.wMaxPacketSize = min(streaming_maxpacket, 1023U);
 | 
				
			||||||
	uvc_fs_streaming_ep.bInterval = streaming_interval;
 | 
						uvc_fs_streaming_ep.bInterval = streaming_interval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uvc_hs_streaming_ep.wMaxPacketSize = max_packet_size;
 | 
				
			||||||
 | 
						uvc_hs_streaming_ep.wMaxPacketSize |= ((max_packet_mult - 1) << 11);
 | 
				
			||||||
 | 
						uvc_hs_streaming_ep.bInterval = streaming_interval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uvc_ss_streaming_ep.wMaxPacketSize = max_packet_size;
 | 
				
			||||||
 | 
						uvc_ss_streaming_ep.bInterval = streaming_interval;
 | 
				
			||||||
 | 
						uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1;
 | 
				
			||||||
 | 
						uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
 | 
				
			||||||
 | 
						uvc_ss_streaming_comp.wBytesPerInterval =
 | 
				
			||||||
 | 
							max_packet_size * max_packet_mult * streaming_maxburst;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Allocate endpoints. */
 | 
						/* Allocate endpoints. */
 | 
				
			||||||
	ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_control_ep);
 | 
						ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);
 | 
				
			||||||
	if (!ep) {
 | 
						if (!ep) {
 | 
				
			||||||
		INFO(cdev, "Unable to allocate control EP\n");
 | 
							INFO(cdev, "Unable to allocate control EP\n");
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
| 
						 | 
					@ -627,7 +640,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 | 
				
			||||||
	uvc->control_ep = ep;
 | 
						uvc->control_ep = ep;
 | 
				
			||||||
	ep->driver_data = uvc;
 | 
						ep->driver_data = uvc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
 | 
						if (gadget_is_superspeed(c->cdev->gadget))
 | 
				
			||||||
 | 
							ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep,
 | 
				
			||||||
 | 
										  &uvc_ss_streaming_comp);
 | 
				
			||||||
 | 
						else if (gadget_is_dualspeed(cdev->gadget))
 | 
				
			||||||
 | 
							ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!ep) {
 | 
						if (!ep) {
 | 
				
			||||||
		INFO(cdev, "Unable to allocate streaming EP\n");
 | 
							INFO(cdev, "Unable to allocate streaming EP\n");
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
| 
						 | 
					@ -635,6 +655,10 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 | 
				
			||||||
	uvc->video.ep = ep;
 | 
						uvc->video.ep = ep;
 | 
				
			||||||
	ep->driver_data = uvc;
 | 
						ep->driver_data = uvc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
 | 
				
			||||||
 | 
						uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
 | 
				
			||||||
 | 
						uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Allocate interface IDs. */
 | 
						/* Allocate interface IDs. */
 | 
				
			||||||
	if ((ret = usb_interface_id(c, f)) < 0)
 | 
						if ((ret = usb_interface_id(c, f)) < 0)
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
| 
						 | 
					@ -648,37 +672,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 | 
				
			||||||
	uvc_streaming_intf_alt1.bInterfaceNumber = ret;
 | 
						uvc_streaming_intf_alt1.bInterfaceNumber = ret;
 | 
				
			||||||
	uvc->streaming_intf = ret;
 | 
						uvc->streaming_intf = ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* sanity check the streaming endpoint module parameters */
 | 
					 | 
				
			||||||
	if (streaming_maxpacket > 1024)
 | 
					 | 
				
			||||||
		streaming_maxpacket = 1024;
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Fill in the HS descriptors from the module parameters for the Video
 | 
					 | 
				
			||||||
	 * Streaming endpoint.
 | 
					 | 
				
			||||||
	 * NOTE: We assume that the user knows what they are doing and won't
 | 
					 | 
				
			||||||
	 * give parameters that their UDC doesn't support.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
 | 
					 | 
				
			||||||
	uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
 | 
					 | 
				
			||||||
	uvc_hs_streaming_ep.bInterval = streaming_interval;
 | 
					 | 
				
			||||||
	uvc_hs_streaming_ep.bEndpointAddress =
 | 
					 | 
				
			||||||
		uvc_fs_streaming_ep.bEndpointAddress;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Fill in the SS descriptors from the module parameters for the Video
 | 
					 | 
				
			||||||
	 * Streaming endpoint.
 | 
					 | 
				
			||||||
	 * NOTE: We assume that the user knows what they are doing and won't
 | 
					 | 
				
			||||||
	 * give parameters that their UDC doesn't support.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
 | 
					 | 
				
			||||||
	uvc_ss_streaming_ep.bInterval = streaming_interval;
 | 
					 | 
				
			||||||
	uvc_ss_streaming_comp.bmAttributes = streaming_mult;
 | 
					 | 
				
			||||||
	uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
 | 
					 | 
				
			||||||
	uvc_ss_streaming_comp.wBytesPerInterval =
 | 
					 | 
				
			||||||
		streaming_maxpacket * (streaming_mult + 1) *
 | 
					 | 
				
			||||||
		(streaming_maxburst + 1);
 | 
					 | 
				
			||||||
	uvc_ss_streaming_ep.bEndpointAddress =
 | 
					 | 
				
			||||||
		uvc_fs_streaming_ep.bEndpointAddress;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Copy descriptors */
 | 
						/* Copy descriptors */
 | 
				
			||||||
	f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
 | 
						f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
 | 
				
			||||||
	if (gadget_is_dualspeed(cdev->gadget))
 | 
						if (gadget_is_dualspeed(cdev->gadget))
 | 
				
			||||||
| 
						 | 
					@ -775,23 +768,23 @@ uvc_bind_config(struct usb_configuration *c,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Validate the descriptors. */
 | 
						/* Validate the descriptors. */
 | 
				
			||||||
	if (fs_control == NULL || fs_control[0] == NULL ||
 | 
						if (fs_control == NULL || fs_control[0] == NULL ||
 | 
				
			||||||
		fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
 | 
						    fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ss_control == NULL || ss_control[0] == NULL ||
 | 
						if (ss_control == NULL || ss_control[0] == NULL ||
 | 
				
			||||||
		ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
 | 
						    ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fs_streaming == NULL || fs_streaming[0] == NULL ||
 | 
						if (fs_streaming == NULL || fs_streaming[0] == NULL ||
 | 
				
			||||||
		fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 | 
						    fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (hs_streaming == NULL || hs_streaming[0] == NULL ||
 | 
						if (hs_streaming == NULL || hs_streaming[0] == NULL ||
 | 
				
			||||||
		hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 | 
						    hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ss_streaming == NULL || ss_streaming[0] == NULL ||
 | 
						if (ss_streaming == NULL || ss_streaming[0] == NULL ||
 | 
				
			||||||
		ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 | 
						    ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uvc->desc.fs_control = fs_control;
 | 
						uvc->desc.fs_control = fs_control;
 | 
				
			||||||
| 
						 | 
					@ -800,13 +793,16 @@ uvc_bind_config(struct usb_configuration *c,
 | 
				
			||||||
	uvc->desc.hs_streaming = hs_streaming;
 | 
						uvc->desc.hs_streaming = hs_streaming;
 | 
				
			||||||
	uvc->desc.ss_streaming = ss_streaming;
 | 
						uvc->desc.ss_streaming = ss_streaming;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Allocate string descriptor numbers. */
 | 
						/* String descriptors are global, we only need to allocate string IDs
 | 
				
			||||||
	if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) {
 | 
						 * for the first UVC function. UVC functions beyond the first (if any)
 | 
				
			||||||
 | 
						 * will reuse the same IDs.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id == 0) {
 | 
				
			||||||
		ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
 | 
							ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
		uvc_iad.iFunction =
 | 
							uvc_iad.iFunction =
 | 
				
			||||||
			uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id;
 | 
								uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
 | 
				
			||||||
		uvc_control_intf.iInterface =
 | 
							uvc_control_intf.iInterface =
 | 
				
			||||||
			uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
 | 
								uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
 | 
				
			||||||
		ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;
 | 
							ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,12 +16,12 @@
 | 
				
			||||||
#include <linux/usb/composite.h>
 | 
					#include <linux/usb/composite.h>
 | 
				
			||||||
#include <linux/usb/video.h>
 | 
					#include <linux/usb/video.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int uvc_bind_config(struct usb_configuration *c,
 | 
					int uvc_bind_config(struct usb_configuration *c,
 | 
				
			||||||
		   const struct uvc_descriptor_header * const *fs_control,
 | 
							    const struct uvc_descriptor_header * const *fs_control,
 | 
				
			||||||
		   const struct uvc_descriptor_header * const *hs_control,
 | 
							    const struct uvc_descriptor_header * const *hs_control,
 | 
				
			||||||
		   const struct uvc_descriptor_header * const *fs_streaming,
 | 
							    const struct uvc_descriptor_header * const *fs_streaming,
 | 
				
			||||||
		   const struct uvc_descriptor_header * const *hs_streaming,
 | 
							    const struct uvc_descriptor_header * const *hs_streaming,
 | 
				
			||||||
		   const struct uvc_descriptor_header * const *ss_streaming);
 | 
							    const struct uvc_descriptor_header * const *ss_streaming);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* _F_UVC_H_ */
 | 
					#endif /* _F_UVC_H_ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2296,7 +2296,6 @@ static int fsl_qe_start(struct usb_gadget *gadget,
 | 
				
			||||||
	driver->driver.bus = NULL;
 | 
						driver->driver.bus = NULL;
 | 
				
			||||||
	/* hook up the driver */
 | 
						/* hook up the driver */
 | 
				
			||||||
	udc->driver = driver;
 | 
						udc->driver = driver;
 | 
				
			||||||
	udc->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
	udc->gadget.speed = driver->max_speed;
 | 
						udc->gadget.speed = driver->max_speed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Enable IRQ reg and Set usbcmd reg EN bit */
 | 
						/* Enable IRQ reg and Set usbcmd reg EN bit */
 | 
				
			||||||
| 
						 | 
					@ -2338,7 +2337,6 @@ static int fsl_qe_stop(struct usb_gadget *gadget,
 | 
				
			||||||
		nuke(loop_ep, -ESHUTDOWN);
 | 
							nuke(loop_ep, -ESHUTDOWN);
 | 
				
			||||||
	spin_unlock_irqrestore(&udc->lock, flags);
 | 
						spin_unlock_irqrestore(&udc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	udc->driver = NULL;
 | 
						udc->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_info(udc->dev, "unregistered gadget driver '%s'\r\n",
 | 
						dev_info(udc->dev, "unregistered gadget driver '%s'\r\n",
 | 
				
			||||||
| 
						 | 
					@ -2523,12 +2521,6 @@ static int qe_udc_probe(struct platform_device *ofdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* name: Identifies the controller hardware type. */
 | 
						/* name: Identifies the controller hardware type. */
 | 
				
			||||||
	udc->gadget.name = driver_name;
 | 
						udc->gadget.name = driver_name;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	device_initialize(&udc->gadget.dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dev_set_name(&udc->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	udc->gadget.dev.release = qe_udc_release;
 | 
					 | 
				
			||||||
	udc->gadget.dev.parent = &ofdev->dev;
 | 
						udc->gadget.dev.parent = &ofdev->dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* initialize qe_ep struct */
 | 
						/* initialize qe_ep struct */
 | 
				
			||||||
| 
						 | 
					@ -2592,22 +2584,17 @@ static int qe_udc_probe(struct platform_device *ofdev)
 | 
				
			||||||
		goto err5;
 | 
							goto err5;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = device_add(&udc->gadget.dev);
 | 
						ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
 | 
				
			||||||
 | 
								qe_udc_release);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto err6;
 | 
							goto err6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = usb_add_gadget_udc(&ofdev->dev, &udc->gadget);
 | 
					 | 
				
			||||||
	if (ret)
 | 
					 | 
				
			||||||
		goto err7;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dev_set_drvdata(&ofdev->dev, udc);
 | 
						dev_set_drvdata(&ofdev->dev, udc);
 | 
				
			||||||
	dev_info(udc->dev,
 | 
						dev_info(udc->dev,
 | 
				
			||||||
			"%s USB controller initialized as device\n",
 | 
								"%s USB controller initialized as device\n",
 | 
				
			||||||
			(udc->soc_type == PORT_QE) ? "QE" : "CPM");
 | 
								(udc->soc_type == PORT_QE) ? "QE" : "CPM");
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err7:
 | 
					 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
err6:
 | 
					err6:
 | 
				
			||||||
	free_irq(udc->usb_irq, udc);
 | 
						free_irq(udc->usb_irq, udc);
 | 
				
			||||||
err5:
 | 
					err5:
 | 
				
			||||||
| 
						 | 
					@ -2702,7 +2689,6 @@ static int qe_udc_remove(struct platform_device *ofdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	iounmap(udc->usb_regs);
 | 
						iounmap(udc->usb_regs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	/* wait for release() of gadget.dev to free udc */
 | 
						/* wait for release() of gadget.dev to free udc */
 | 
				
			||||||
	wait_for_completion(&done);
 | 
						wait_for_completion(&done);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -185,20 +185,7 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
 | 
				
			||||||
		dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
 | 
							dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (req->mapped) {
 | 
						usb_gadget_unmap_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
 | 
				
			||||||
		dma_unmap_single(ep->udc->gadget.dev.parent,
 | 
					 | 
				
			||||||
			req->req.dma, req->req.length,
 | 
					 | 
				
			||||||
			ep_is_in(ep)
 | 
					 | 
				
			||||||
				? DMA_TO_DEVICE
 | 
					 | 
				
			||||||
				: DMA_FROM_DEVICE);
 | 
					 | 
				
			||||||
		req->req.dma = DMA_ADDR_INVALID;
 | 
					 | 
				
			||||||
		req->mapped = 0;
 | 
					 | 
				
			||||||
	} else
 | 
					 | 
				
			||||||
		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
 | 
					 | 
				
			||||||
			req->req.dma, req->req.length,
 | 
					 | 
				
			||||||
			ep_is_in(ep)
 | 
					 | 
				
			||||||
				? DMA_TO_DEVICE
 | 
					 | 
				
			||||||
				: DMA_FROM_DEVICE);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (status && (status != -ESHUTDOWN))
 | 
						if (status && (status != -ESHUTDOWN))
 | 
				
			||||||
		VDBG("complete %s req %p stat %d len %u/%u",
 | 
							VDBG("complete %s req %p stat %d len %u/%u",
 | 
				
			||||||
| 
						 | 
					@ -888,6 +875,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 | 
				
			||||||
	struct fsl_req *req = container_of(_req, struct fsl_req, req);
 | 
						struct fsl_req *req = container_of(_req, struct fsl_req, req);
 | 
				
			||||||
	struct fsl_udc *udc;
 | 
						struct fsl_udc *udc;
 | 
				
			||||||
	unsigned long flags;
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* catch various bogus parameters */
 | 
						/* catch various bogus parameters */
 | 
				
			||||||
	if (!_req || !req->req.complete || !req->req.buf
 | 
						if (!_req || !req->req.complete || !req->req.buf
 | 
				
			||||||
| 
						 | 
					@ -910,22 +898,9 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req->ep = ep;
 | 
						req->ep = ep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* map virtual address to hardware */
 | 
						ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
 | 
				
			||||||
	if (req->req.dma == DMA_ADDR_INVALID) {
 | 
						if (ret)
 | 
				
			||||||
		req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
 | 
							return ret;
 | 
				
			||||||
					req->req.buf,
 | 
					 | 
				
			||||||
					req->req.length, ep_is_in(ep)
 | 
					 | 
				
			||||||
						? DMA_TO_DEVICE
 | 
					 | 
				
			||||||
						: DMA_FROM_DEVICE);
 | 
					 | 
				
			||||||
		req->mapped = 1;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		dma_sync_single_for_device(ep->udc->gadget.dev.parent,
 | 
					 | 
				
			||||||
					req->req.dma, req->req.length,
 | 
					 | 
				
			||||||
					ep_is_in(ep)
 | 
					 | 
				
			||||||
						? DMA_TO_DEVICE
 | 
					 | 
				
			||||||
						: DMA_FROM_DEVICE);
 | 
					 | 
				
			||||||
		req->mapped = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req->req.status = -EINPROGRESS;
 | 
						req->req.status = -EINPROGRESS;
 | 
				
			||||||
	req->req.actual = 0;
 | 
						req->req.actual = 0;
 | 
				
			||||||
| 
						 | 
					@ -1290,6 +1265,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct fsl_req *req = udc->status_req;
 | 
						struct fsl_req *req = udc->status_req;
 | 
				
			||||||
	struct fsl_ep *ep;
 | 
						struct fsl_ep *ep;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (direction == EP_DIR_IN)
 | 
						if (direction == EP_DIR_IN)
 | 
				
			||||||
		udc->ep0_dir = USB_DIR_IN;
 | 
							udc->ep0_dir = USB_DIR_IN;
 | 
				
			||||||
| 
						 | 
					@ -1307,10 +1283,9 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
 | 
				
			||||||
	req->req.complete = NULL;
 | 
						req->req.complete = NULL;
 | 
				
			||||||
	req->dtd_count = 0;
 | 
						req->dtd_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
 | 
						ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
 | 
				
			||||||
			req->req.buf, req->req.length,
 | 
						if (ret)
 | 
				
			||||||
			ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 | 
							return ret;
 | 
				
			||||||
	req->mapped = 1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
 | 
						if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
 | 
				
			||||||
		fsl_queue_td(ep, req);
 | 
							fsl_queue_td(ep, req);
 | 
				
			||||||
| 
						 | 
					@ -1353,6 +1328,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
 | 
				
			||||||
	u16 tmp = 0;		/* Status, cpu endian */
 | 
						u16 tmp = 0;		/* Status, cpu endian */
 | 
				
			||||||
	struct fsl_req *req;
 | 
						struct fsl_req *req;
 | 
				
			||||||
	struct fsl_ep *ep;
 | 
						struct fsl_ep *ep;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ep = &udc->eps[0];
 | 
						ep = &udc->eps[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1390,10 +1366,9 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
 | 
				
			||||||
	req->req.complete = NULL;
 | 
						req->req.complete = NULL;
 | 
				
			||||||
	req->dtd_count = 0;
 | 
						req->dtd_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
 | 
						ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
 | 
				
			||||||
				req->req.buf, req->req.length,
 | 
						if (ret)
 | 
				
			||||||
				ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 | 
							goto stall;
 | 
				
			||||||
	req->mapped = 1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* prime the data phase */
 | 
						/* prime the data phase */
 | 
				
			||||||
	if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
 | 
						if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
 | 
				
			||||||
| 
						 | 
					@ -1964,7 +1939,6 @@ static int fsl_udc_start(struct usb_gadget *g,
 | 
				
			||||||
	driver->driver.bus = NULL;
 | 
						driver->driver.bus = NULL;
 | 
				
			||||||
	/* hook up the driver */
 | 
						/* hook up the driver */
 | 
				
			||||||
	udc_controller->driver = driver;
 | 
						udc_controller->driver = driver;
 | 
				
			||||||
	udc_controller->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
	spin_unlock_irqrestore(&udc_controller->lock, flags);
 | 
						spin_unlock_irqrestore(&udc_controller->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
 | 
						if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
 | 
				
			||||||
| 
						 | 
					@ -1980,7 +1954,6 @@ static int fsl_udc_start(struct usb_gadget *g,
 | 
				
			||||||
			if (retval < 0) {
 | 
								if (retval < 0) {
 | 
				
			||||||
				ERR("can't bind to transceiver\n");
 | 
									ERR("can't bind to transceiver\n");
 | 
				
			||||||
				driver->unbind(&udc_controller->gadget);
 | 
									driver->unbind(&udc_controller->gadget);
 | 
				
			||||||
				udc_controller->gadget.dev.driver = 0;
 | 
					 | 
				
			||||||
				udc_controller->driver = 0;
 | 
									udc_controller->driver = 0;
 | 
				
			||||||
				return retval;
 | 
									return retval;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -2023,7 +1996,6 @@ static int fsl_udc_stop(struct usb_gadget *g,
 | 
				
			||||||
		nuke(loop_ep, -ESHUTDOWN);
 | 
							nuke(loop_ep, -ESHUTDOWN);
 | 
				
			||||||
	spin_unlock_irqrestore(&udc_controller->lock, flags);
 | 
						spin_unlock_irqrestore(&udc_controller->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc_controller->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	udc_controller->driver = NULL;
 | 
						udc_controller->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -2521,12 +2493,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Setup gadget.dev and register with kernel */
 | 
						/* Setup gadget.dev and register with kernel */
 | 
				
			||||||
	dev_set_name(&udc_controller->gadget.dev, "gadget");
 | 
						dev_set_name(&udc_controller->gadget.dev, "gadget");
 | 
				
			||||||
	udc_controller->gadget.dev.release = fsl_udc_release;
 | 
					 | 
				
			||||||
	udc_controller->gadget.dev.parent = &pdev->dev;
 | 
					 | 
				
			||||||
	udc_controller->gadget.dev.of_node = pdev->dev.of_node;
 | 
						udc_controller->gadget.dev.of_node = pdev->dev.of_node;
 | 
				
			||||||
	ret = device_register(&udc_controller->gadget.dev);
 | 
					 | 
				
			||||||
	if (ret < 0)
 | 
					 | 
				
			||||||
		goto err_free_irq;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!IS_ERR_OR_NULL(udc_controller->transceiver))
 | 
						if (!IS_ERR_OR_NULL(udc_controller->transceiver))
 | 
				
			||||||
		udc_controller->gadget.is_otg = 1;
 | 
							udc_controller->gadget.is_otg = 1;
 | 
				
			||||||
| 
						 | 
					@ -2559,10 +2526,11 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
			DTD_ALIGNMENT, UDC_DMA_BOUNDARY);
 | 
								DTD_ALIGNMENT, UDC_DMA_BOUNDARY);
 | 
				
			||||||
	if (udc_controller->td_pool == NULL) {
 | 
						if (udc_controller->td_pool == NULL) {
 | 
				
			||||||
		ret = -ENOMEM;
 | 
							ret = -ENOMEM;
 | 
				
			||||||
		goto err_unregister;
 | 
							goto err_free_irq;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = usb_add_gadget_udc(&pdev->dev, &udc_controller->gadget);
 | 
						ret = usb_add_gadget_udc_release(&pdev->dev, &udc_controller->gadget,
 | 
				
			||||||
 | 
								fsl_udc_release);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto err_del_udc;
 | 
							goto err_del_udc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2571,8 +2539,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_del_udc:
 | 
					err_del_udc:
 | 
				
			||||||
	dma_pool_destroy(udc_controller->td_pool);
 | 
						dma_pool_destroy(udc_controller->td_pool);
 | 
				
			||||||
err_unregister:
 | 
					 | 
				
			||||||
	device_unregister(&udc_controller->gadget.dev);
 | 
					 | 
				
			||||||
err_free_irq:
 | 
					err_free_irq:
 | 
				
			||||||
	free_irq(udc_controller->irq, udc_controller);
 | 
						free_irq(udc_controller->irq, udc_controller);
 | 
				
			||||||
err_iounmap:
 | 
					err_iounmap:
 | 
				
			||||||
| 
						 | 
					@ -2622,7 +2588,6 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
 | 
				
			||||||
	if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
 | 
						if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
 | 
				
			||||||
		release_mem_region(res->start, resource_size(res));
 | 
							release_mem_region(res->start, resource_size(res));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_unregister(&udc_controller->gadget.dev);
 | 
					 | 
				
			||||||
	/* free udc --wait for the release() finished */
 | 
						/* free udc --wait for the release() finished */
 | 
				
			||||||
	wait_for_completion(&done);
 | 
						wait_for_completion(&done);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2747,21 +2712,7 @@ static struct platform_driver udc_driver = {
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init udc_init(void)
 | 
					module_platform_driver_probe(udc_driver, fsl_udc_probe);
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	printk(KERN_INFO "%s (%s)\n", driver_desc, DRIVER_VERSION);
 | 
					 | 
				
			||||||
	return platform_driver_probe(&udc_driver, fsl_udc_probe);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module_init(udc_init);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void __exit udc_exit(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	platform_driver_unregister(&udc_driver);
 | 
					 | 
				
			||||||
	printk(KERN_WARNING "%s unregistered\n", driver_desc);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module_exit(udc_exit);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
MODULE_DESCRIPTION(DRIVER_DESC);
 | 
					MODULE_DESCRIPTION(DRIVER_DESC);
 | 
				
			||||||
MODULE_AUTHOR(DRIVER_AUTHOR);
 | 
					MODULE_AUTHOR(DRIVER_AUTHOR);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -394,7 +394,7 @@ static void fusb300_clear_epnstall(struct fusb300 *fusb300, u8 ep)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (reg & FUSB300_EPSET0_STL) {
 | 
						if (reg & FUSB300_EPSET0_STL) {
 | 
				
			||||||
		printk(KERN_DEBUG "EP%d stall... Clear!!\n", ep);
 | 
							printk(KERN_DEBUG "EP%d stall... Clear!!\n", ep);
 | 
				
			||||||
		reg &= ~FUSB300_EPSET0_STL;
 | 
							reg |= FUSB300_EPSET0_STL_CLR;
 | 
				
			||||||
		iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
 | 
							iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -930,33 +930,33 @@ static void fusb300_wait_idma_finished(struct fusb300_ep *ep)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0,
 | 
						fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0,
 | 
				
			||||||
		FUSB300_IGR0_EPn_PRD_INT(ep->epnum));
 | 
							FUSB300_IGR0_EPn_PRD_INT(ep->epnum));
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
IDMA_RESET:
 | 
					IDMA_RESET:
 | 
				
			||||||
	fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGER0,
 | 
						reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGER0);
 | 
				
			||||||
		FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
 | 
						reg &= ~FUSB300_IGER0_EEPn_PRD_INT(ep->epnum);
 | 
				
			||||||
 | 
						iowrite32(reg, ep->fusb300->reg + FUSB300_OFFSET_IGER0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void  fusb300_set_idma(struct fusb300_ep *ep,
 | 
					static void fusb300_set_idma(struct fusb300_ep *ep,
 | 
				
			||||||
			struct fusb300_request *req)
 | 
								struct fusb300_request *req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	dma_addr_t d;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	d = dma_map_single(NULL, req->req.buf, req->req.length, DMA_TO_DEVICE);
 | 
						ret = usb_gadget_map_request(&ep->fusb300->gadget,
 | 
				
			||||||
 | 
								&req->req, DMA_TO_DEVICE);
 | 
				
			||||||
	if (dma_mapping_error(NULL, d)) {
 | 
						if (ret)
 | 
				
			||||||
		printk(KERN_DEBUG "dma_mapping_error\n");
 | 
					 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dma_sync_single_for_device(NULL, d, req->req.length, DMA_TO_DEVICE);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,
 | 
						fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,
 | 
				
			||||||
		FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
 | 
							FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fusb300_fill_idma_prdtbl(ep, d, req->req.length);
 | 
						fusb300_fill_idma_prdtbl(ep, req->req.dma, req->req.length);
 | 
				
			||||||
	/* check idma is done */
 | 
						/* check idma is done */
 | 
				
			||||||
	fusb300_wait_idma_finished(ep);
 | 
						fusb300_wait_idma_finished(ep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE);
 | 
						usb_gadget_unmap_request(&ep->fusb300->gadget,
 | 
				
			||||||
 | 
								&req->req, DMA_TO_DEVICE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void in_ep_fifo_handler(struct fusb300_ep *ep)
 | 
					static void in_ep_fifo_handler(struct fusb300_ep *ep)
 | 
				
			||||||
| 
						 | 
					@ -1316,7 +1316,6 @@ static int fusb300_udc_start(struct usb_gadget *g,
 | 
				
			||||||
	/* hook up the driver */
 | 
						/* hook up the driver */
 | 
				
			||||||
	driver->driver.bus = NULL;
 | 
						driver->driver.bus = NULL;
 | 
				
			||||||
	fusb300->driver = driver;
 | 
						fusb300->driver = driver;
 | 
				
			||||||
	fusb300->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1327,7 +1326,6 @@ static int fusb300_udc_stop(struct usb_gadget *g,
 | 
				
			||||||
	struct fusb300 *fusb300 = to_fusb300(g);
 | 
						struct fusb300 *fusb300 = to_fusb300(g);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	driver->unbind(&fusb300->gadget);
 | 
						driver->unbind(&fusb300->gadget);
 | 
				
			||||||
	fusb300->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_controller(fusb300);
 | 
						init_controller(fusb300);
 | 
				
			||||||
	fusb300->driver = NULL;
 | 
						fusb300->driver = NULL;
 | 
				
			||||||
| 
						 | 
					@ -1422,14 +1420,7 @@ static int __init fusb300_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fusb300->gadget.ops = &fusb300_gadget_ops;
 | 
						fusb300->gadget.ops = &fusb300_gadget_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_initialize(&fusb300->gadget.dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dev_set_name(&fusb300->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fusb300->gadget.max_speed = USB_SPEED_HIGH;
 | 
						fusb300->gadget.max_speed = USB_SPEED_HIGH;
 | 
				
			||||||
	fusb300->gadget.dev.parent = &pdev->dev;
 | 
					 | 
				
			||||||
	fusb300->gadget.dev.dma_mask = pdev->dev.dma_mask;
 | 
					 | 
				
			||||||
	fusb300->gadget.dev.release = pdev->dev.release;
 | 
					 | 
				
			||||||
	fusb300->gadget.name = udc_name;
 | 
						fusb300->gadget.name = udc_name;
 | 
				
			||||||
	fusb300->reg = reg;
 | 
						fusb300->reg = reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1478,19 +1469,10 @@ static int __init fusb300_probe(struct platform_device *pdev)
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto err_add_udc;
 | 
							goto err_add_udc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = device_add(&fusb300->gadget.dev);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		pr_err("device_add error (%d)\n", ret);
 | 
					 | 
				
			||||||
		goto err_add_device;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
 | 
						dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_add_device:
 | 
					 | 
				
			||||||
	usb_del_gadget_udc(&fusb300->gadget);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
err_add_udc:
 | 
					err_add_udc:
 | 
				
			||||||
	fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
 | 
						fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -111,8 +111,8 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * * EPn Setting 0 (EPn_SET0, offset = 020H+(n-1)*30H, n=1~15 )
 | 
					 * * EPn Setting 0 (EPn_SET0, offset = 020H+(n-1)*30H, n=1~15 )
 | 
				
			||||||
 * */
 | 
					 * */
 | 
				
			||||||
 | 
					#define FUSB300_EPSET0_STL_CLR		(1 << 3)
 | 
				
			||||||
#define FUSB300_EPSET0_CLRSEQNUM	(1 << 2)
 | 
					#define FUSB300_EPSET0_CLRSEQNUM	(1 << 2)
 | 
				
			||||||
#define FUSB300_EPSET0_EPn_TX0BYTE	(1 << 1)
 | 
					 | 
				
			||||||
#define FUSB300_EPSET0_STL		(1 << 0)
 | 
					#define FUSB300_EPSET0_STL		(1 << 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,6 @@
 | 
				
			||||||
#define pr_fmt(fmt) "g_ffs: " fmt
 | 
					#define pr_fmt(fmt) "g_ffs: " fmt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/module.h>
 | 
					#include <linux/module.h>
 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * kbuild is not very cooperative with respect to linking separately
 | 
					 * kbuild is not very cooperative with respect to linking separately
 | 
				
			||||||
 * compiled library objects into one module.  So for now we won't use
 | 
					 * compiled library objects into one module.  So for now we won't use
 | 
				
			||||||
| 
						 | 
					@ -38,13 +37,16 @@
 | 
				
			||||||
#  include "u_ether.c"
 | 
					#  include "u_ether.c"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static u8 gfs_hostaddr[ETH_ALEN];
 | 
					static u8 gfs_hostaddr[ETH_ALEN];
 | 
				
			||||||
 | 
					static struct eth_dev *the_dev;
 | 
				
			||||||
#  ifdef CONFIG_USB_FUNCTIONFS_ETH
 | 
					#  ifdef CONFIG_USB_FUNCTIONFS_ETH
 | 
				
			||||||
static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
 | 
					static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
 | 
							struct eth_dev *dev);
 | 
				
			||||||
#  endif
 | 
					#  endif
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
#  define gether_cleanup() do { } while (0)
 | 
					#  define the_dev	NULL
 | 
				
			||||||
#  define gether_setup(gadget, hostaddr)   ((int)0)
 | 
					#  define gether_cleanup(dev) do { } while (0)
 | 
				
			||||||
#  define gfs_hostaddr NULL
 | 
					#  define gfs_hostaddr NULL
 | 
				
			||||||
 | 
					struct eth_dev;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "f_fs.c"
 | 
					#include "f_fs.c"
 | 
				
			||||||
| 
						 | 
					@ -137,7 +139,8 @@ static struct usb_gadget_strings *gfs_dev_strings[] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct gfs_configuration {
 | 
					struct gfs_configuration {
 | 
				
			||||||
	struct usb_configuration c;
 | 
						struct usb_configuration c;
 | 
				
			||||||
	int (*eth)(struct usb_configuration *c, u8 *ethaddr);
 | 
						int (*eth)(struct usb_configuration *c, u8 *ethaddr,
 | 
				
			||||||
 | 
								struct eth_dev *dev);
 | 
				
			||||||
} gfs_configurations[] = {
 | 
					} gfs_configurations[] = {
 | 
				
			||||||
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 | 
					#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -346,10 +349,13 @@ static int gfs_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (missing_funcs)
 | 
						if (missing_funcs)
 | 
				
			||||||
		return -ENODEV;
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
					#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
 | 
				
			||||||
	ret = gether_setup(cdev->gadget, gfs_hostaddr);
 | 
						the_dev = gether_setup(cdev->gadget, gfs_hostaddr);
 | 
				
			||||||
	if (unlikely(ret < 0))
 | 
					#endif
 | 
				
			||||||
 | 
						if (IS_ERR(the_dev)) {
 | 
				
			||||||
 | 
							ret = PTR_ERR(the_dev);
 | 
				
			||||||
		goto error_quick;
 | 
							goto error_quick;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	gfs_ether_setup = true;
 | 
						gfs_ether_setup = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = usb_string_ids_tab(cdev, gfs_strings);
 | 
						ret = usb_string_ids_tab(cdev, gfs_strings);
 | 
				
			||||||
| 
						 | 
					@ -386,7 +392,7 @@ error_unbind:
 | 
				
			||||||
	for (i = 0; i < func_num; i++)
 | 
						for (i = 0; i < func_num; i++)
 | 
				
			||||||
		functionfs_unbind(ffs_tab[i].ffs_data);
 | 
							functionfs_unbind(ffs_tab[i].ffs_data);
 | 
				
			||||||
error:
 | 
					error:
 | 
				
			||||||
	gether_cleanup();
 | 
						gether_cleanup(the_dev);
 | 
				
			||||||
error_quick:
 | 
					error_quick:
 | 
				
			||||||
	gfs_ether_setup = false;
 | 
						gfs_ether_setup = false;
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
| 
						 | 
					@ -410,7 +416,7 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
 | 
				
			||||||
	 * do...?
 | 
						 * do...?
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (gfs_ether_setup)
 | 
						if (gfs_ether_setup)
 | 
				
			||||||
		gether_cleanup();
 | 
							gether_cleanup(the_dev);
 | 
				
			||||||
	gfs_ether_setup = false;
 | 
						gfs_ether_setup = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = func_num; i--; )
 | 
						for (i = func_num; i--; )
 | 
				
			||||||
| 
						 | 
					@ -440,7 +446,7 @@ static int gfs_do_config(struct usb_configuration *c)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (gc->eth) {
 | 
						if (gc->eth) {
 | 
				
			||||||
		ret = gc->eth(c, gfs_hostaddr);
 | 
							ret = gc->eth(c, gfs_hostaddr, the_dev);
 | 
				
			||||||
		if (unlikely(ret < 0))
 | 
							if (unlikely(ret < 0))
 | 
				
			||||||
			return ret;
 | 
								return ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -469,11 +475,12 @@ static int gfs_do_config(struct usb_configuration *c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_USB_FUNCTIONFS_ETH
 | 
					#ifdef CONFIG_USB_FUNCTIONFS_ETH
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 | 
					static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
 | 
							struct eth_dev *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return can_support_ecm(c->cdev->gadget)
 | 
						return can_support_ecm(c->cdev->gadget)
 | 
				
			||||||
		? ecm_bind_config(c, ethaddr)
 | 
							? ecm_bind_config(c, ethaddr, dev)
 | 
				
			||||||
		: geth_bind_config(c, ethaddr);
 | 
							: geth_bind_config(c, ethaddr, dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,8 +51,6 @@
 | 
				
			||||||
#define	DRIVER_DESC		"TC86C001 USB Device Controller"
 | 
					#define	DRIVER_DESC		"TC86C001 USB Device Controller"
 | 
				
			||||||
#define	DRIVER_VERSION		"30-Oct 2003"
 | 
					#define	DRIVER_VERSION		"30-Oct 2003"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char driver_name [] = "goku_udc";
 | 
					static const char driver_name [] = "goku_udc";
 | 
				
			||||||
static const char driver_desc [] = DRIVER_DESC;
 | 
					static const char driver_desc [] = DRIVER_DESC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -275,7 +273,6 @@ goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
 | 
				
			||||||
	if (!req)
 | 
						if (!req)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req->req.dma = DMA_ADDR_INVALID;
 | 
					 | 
				
			||||||
	INIT_LIST_HEAD(&req->queue);
 | 
						INIT_LIST_HEAD(&req->queue);
 | 
				
			||||||
	return &req->req;
 | 
						return &req->req;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1354,7 +1351,6 @@ static int goku_udc_start(struct usb_gadget *g,
 | 
				
			||||||
	/* hook up the driver */
 | 
						/* hook up the driver */
 | 
				
			||||||
	driver->driver.bus = NULL;
 | 
						driver->driver.bus = NULL;
 | 
				
			||||||
	dev->driver = driver;
 | 
						dev->driver = driver;
 | 
				
			||||||
	dev->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * then enable host detection and ep0; and we're ready
 | 
						 * then enable host detection and ep0; and we're ready
 | 
				
			||||||
| 
						 | 
					@ -1394,7 +1390,6 @@ static int goku_udc_stop(struct usb_gadget *g,
 | 
				
			||||||
	dev->driver = NULL;
 | 
						dev->driver = NULL;
 | 
				
			||||||
	stop_activity(dev, driver);
 | 
						stop_activity(dev, driver);
 | 
				
			||||||
	spin_unlock_irqrestore(&dev->lock, flags);
 | 
						spin_unlock_irqrestore(&dev->lock, flags);
 | 
				
			||||||
	dev->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1716,8 +1711,6 @@ static void goku_remove(struct pci_dev *pdev)
 | 
				
			||||||
				pci_resource_len (pdev, 0));
 | 
									pci_resource_len (pdev, 0));
 | 
				
			||||||
	if (dev->enabled)
 | 
						if (dev->enabled)
 | 
				
			||||||
		pci_disable_device(pdev);
 | 
							pci_disable_device(pdev);
 | 
				
			||||||
	if (dev->registered)
 | 
					 | 
				
			||||||
		device_unregister(&dev->gadget.dev);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pci_set_drvdata(pdev, NULL);
 | 
						pci_set_drvdata(pdev, NULL);
 | 
				
			||||||
	dev->regs = NULL;
 | 
						dev->regs = NULL;
 | 
				
			||||||
| 
						 | 
					@ -1756,10 +1749,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 | 
				
			||||||
	dev->gadget.max_speed = USB_SPEED_FULL;
 | 
						dev->gadget.max_speed = USB_SPEED_FULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* the "gadget" abstracts/virtualizes the controller */
 | 
						/* the "gadget" abstracts/virtualizes the controller */
 | 
				
			||||||
	dev_set_name(&dev->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
	dev->gadget.dev.parent = &pdev->dev;
 | 
					 | 
				
			||||||
	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 | 
					 | 
				
			||||||
	dev->gadget.dev.release = gadget_release;
 | 
					 | 
				
			||||||
	dev->gadget.name = driver_name;
 | 
						dev->gadget.name = driver_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* now all the pci goodies ... */
 | 
						/* now all the pci goodies ... */
 | 
				
			||||||
| 
						 | 
					@ -1810,13 +1799,8 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 | 
				
			||||||
	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
 | 
						create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = device_register(&dev->gadget.dev);
 | 
						retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
 | 
				
			||||||
	if (retval) {
 | 
								gadget_release);
 | 
				
			||||||
		put_device(&dev->gadget.dev);
 | 
					 | 
				
			||||||
		goto err;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	dev->registered = 1;
 | 
					 | 
				
			||||||
	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
 | 
					 | 
				
			||||||
	if (retval)
 | 
						if (retval)
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -250,8 +250,7 @@ struct goku_udc {
 | 
				
			||||||
					got_region:1,
 | 
										got_region:1,
 | 
				
			||||||
					req_config:1,
 | 
										req_config:1,
 | 
				
			||||||
					configured:1,
 | 
										configured:1,
 | 
				
			||||||
					enabled:1,
 | 
										enabled:1;
 | 
				
			||||||
					registered:1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* pci state used to access those endpoints */
 | 
						/* pci state used to access those endpoints */
 | 
				
			||||||
	struct pci_dev			*pdev;
 | 
						struct pci_dev			*pdev;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1338,7 +1338,6 @@ static int imx_udc_start(struct usb_gadget *gadget,
 | 
				
			||||||
	imx_usb = container_of(gadget, struct imx_udc_struct, gadget);
 | 
						imx_usb = container_of(gadget, struct imx_udc_struct, gadget);
 | 
				
			||||||
	/* first hook up the driver ... */
 | 
						/* first hook up the driver ... */
 | 
				
			||||||
	imx_usb->driver = driver;
 | 
						imx_usb->driver = driver;
 | 
				
			||||||
	imx_usb->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",
 | 
						D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",
 | 
				
			||||||
		__func__, driver->driver.name);
 | 
							__func__, driver->driver.name);
 | 
				
			||||||
| 
						 | 
					@ -1358,7 +1357,6 @@ static int imx_udc_stop(struct usb_gadget *gadget,
 | 
				
			||||||
	imx_udc_disable(imx_usb);
 | 
						imx_udc_disable(imx_usb);
 | 
				
			||||||
	del_timer(&imx_usb->timer);
 | 
						del_timer(&imx_usb->timer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	imx_usb->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	imx_usb->driver = NULL;
 | 
						imx_usb->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n",
 | 
						D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n",
 | 
				
			||||||
| 
						 | 
					@ -1461,15 +1459,6 @@ static int __init imx_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
	imx_usb->clk = clk;
 | 
						imx_usb->clk = clk;
 | 
				
			||||||
	imx_usb->dev = &pdev->dev;
 | 
						imx_usb->dev = &pdev->dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_initialize(&imx_usb->gadget.dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	imx_usb->gadget.dev.parent = &pdev->dev;
 | 
					 | 
				
			||||||
	imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = device_add(&imx_usb->gadget.dev);
 | 
					 | 
				
			||||||
	if (retval)
 | 
					 | 
				
			||||||
		goto fail4;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	platform_set_drvdata(pdev, imx_usb);
 | 
						platform_set_drvdata(pdev, imx_usb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	usb_init_data(imx_usb);
 | 
						usb_init_data(imx_usb);
 | 
				
			||||||
| 
						 | 
					@ -1481,11 +1470,9 @@ static int __init imx_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);
 | 
						ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto fail5;
 | 
							goto fail4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
fail5:
 | 
					 | 
				
			||||||
	device_unregister(&imx_usb->gadget.dev);
 | 
					 | 
				
			||||||
fail4:
 | 
					fail4:
 | 
				
			||||||
	for (i = 0; i < IMX_USB_NB_EP + 1; i++)
 | 
						for (i = 0; i < IMX_USB_NB_EP + 1; i++)
 | 
				
			||||||
		free_irq(imx_usb->usbd_int[i], imx_usb);
 | 
							free_irq(imx_usb->usbd_int[i], imx_usb);
 | 
				
			||||||
| 
						 | 
					@ -1509,7 +1496,6 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	usb_del_gadget_udc(&imx_usb->gadget);
 | 
						usb_del_gadget_udc(&imx_usb->gadget);
 | 
				
			||||||
	device_unregister(&imx_usb->gadget.dev);
 | 
					 | 
				
			||||||
	imx_udc_disable(imx_usb);
 | 
						imx_udc_disable(imx_usb);
 | 
				
			||||||
	del_timer(&imx_usb->timer);
 | 
						del_timer(&imx_usb->timer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1469,23 +1469,7 @@ static void done(struct lpc32xx_ep *ep, struct lpc32xx_request *req, int status)
 | 
				
			||||||
		status = req->req.status;
 | 
							status = req->req.status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ep->lep) {
 | 
						if (ep->lep) {
 | 
				
			||||||
		enum dma_data_direction direction;
 | 
							usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (ep->is_in)
 | 
					 | 
				
			||||||
			direction = DMA_TO_DEVICE;
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			direction = DMA_FROM_DEVICE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (req->mapped) {
 | 
					 | 
				
			||||||
			dma_unmap_single(ep->udc->gadget.dev.parent,
 | 
					 | 
				
			||||||
					req->req.dma, req->req.length,
 | 
					 | 
				
			||||||
					direction);
 | 
					 | 
				
			||||||
			req->req.dma = 0;
 | 
					 | 
				
			||||||
			req->mapped = 0;
 | 
					 | 
				
			||||||
		} else
 | 
					 | 
				
			||||||
			dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
 | 
					 | 
				
			||||||
						req->req.dma, req->req.length,
 | 
					 | 
				
			||||||
						direction);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Free DDs */
 | 
							/* Free DDs */
 | 
				
			||||||
		udc_dd_free(udc, req->dd_desc_ptr);
 | 
							udc_dd_free(udc, req->dd_desc_ptr);
 | 
				
			||||||
| 
						 | 
					@ -1841,26 +1825,11 @@ static int lpc32xx_ep_queue(struct usb_ep *_ep,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ep->lep) {
 | 
						if (ep->lep) {
 | 
				
			||||||
		enum dma_data_direction direction;
 | 
					 | 
				
			||||||
		struct lpc32xx_usbd_dd_gad *dd;
 | 
							struct lpc32xx_usbd_dd_gad *dd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Map DMA pointer */
 | 
							status = usb_gadget_map_request(&udc->gadget, _req, ep->is_in);
 | 
				
			||||||
		if (ep->is_in)
 | 
							if (status)
 | 
				
			||||||
			direction = DMA_TO_DEVICE;
 | 
								return status;
 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			direction = DMA_FROM_DEVICE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (req->req.dma == 0) {
 | 
					 | 
				
			||||||
			req->req.dma = dma_map_single(
 | 
					 | 
				
			||||||
				ep->udc->gadget.dev.parent,
 | 
					 | 
				
			||||||
				req->req.buf, req->req.length, direction);
 | 
					 | 
				
			||||||
			req->mapped = 1;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			dma_sync_single_for_device(
 | 
					 | 
				
			||||||
				ep->udc->gadget.dev.parent, req->req.dma,
 | 
					 | 
				
			||||||
				req->req.length, direction);
 | 
					 | 
				
			||||||
			req->mapped = 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* For the request, build a list of DDs */
 | 
							/* For the request, build a list of DDs */
 | 
				
			||||||
		dd = udc_dd_alloc(udc);
 | 
							dd = udc_dd_alloc(udc);
 | 
				
			||||||
| 
						 | 
					@ -2977,7 +2946,6 @@ static int lpc32xx_start(struct usb_gadget *gadget,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->driver = driver;
 | 
						udc->driver = driver;
 | 
				
			||||||
	udc->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
	udc->gadget.dev.of_node = udc->dev->of_node;
 | 
						udc->gadget.dev.of_node = udc->dev->of_node;
 | 
				
			||||||
	udc->enabled = 1;
 | 
						udc->enabled = 1;
 | 
				
			||||||
	udc->selfpowered = 1;
 | 
						udc->selfpowered = 1;
 | 
				
			||||||
| 
						 | 
					@ -3026,7 +2994,6 @@ static int lpc32xx_stop(struct usb_gadget *gadget,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->enabled = 0;
 | 
						udc->enabled = 0;
 | 
				
			||||||
	udc->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	udc->driver = NULL;
 | 
						udc->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -3248,12 +3215,6 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
	udc_disable(udc);
 | 
						udc_disable(udc);
 | 
				
			||||||
	udc_reinit(udc);
 | 
						udc_reinit(udc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = device_register(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	if (retval < 0) {
 | 
					 | 
				
			||||||
		dev_err(udc->dev, "Device registration failure\n");
 | 
					 | 
				
			||||||
		goto dev_register_fail;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Request IRQs - low and high priority USB device IRQs are routed to
 | 
						/* Request IRQs - low and high priority USB device IRQs are routed to
 | 
				
			||||||
	 * the same handler, while the DMA interrupt is routed elsewhere */
 | 
						 * the same handler, while the DMA interrupt is routed elsewhere */
 | 
				
			||||||
	retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq,
 | 
						retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq,
 | 
				
			||||||
| 
						 | 
					@ -3320,8 +3281,6 @@ irq_dev_fail:
 | 
				
			||||||
irq_hp_fail:
 | 
					irq_hp_fail:
 | 
				
			||||||
	free_irq(udc->udp_irq[IRQ_USB_LP], udc);
 | 
						free_irq(udc->udp_irq[IRQ_USB_LP], udc);
 | 
				
			||||||
irq_lp_fail:
 | 
					irq_lp_fail:
 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
dev_register_fail:
 | 
					 | 
				
			||||||
	dma_pool_destroy(udc->dd_cache);
 | 
						dma_pool_destroy(udc->dd_cache);
 | 
				
			||||||
dma_alloc_fail:
 | 
					dma_alloc_fail:
 | 
				
			||||||
	dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
 | 
						dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
 | 
				
			||||||
| 
						 | 
					@ -3376,8 +3335,6 @@ static int lpc32xx_udc_remove(struct platform_device *pdev)
 | 
				
			||||||
	free_irq(udc->udp_irq[IRQ_USB_HP], udc);
 | 
						free_irq(udc->udp_irq[IRQ_USB_HP], udc);
 | 
				
			||||||
	free_irq(udc->udp_irq[IRQ_USB_LP], udc);
 | 
						free_irq(udc->udp_irq[IRQ_USB_LP], udc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	clk_disable(udc->usb_otg_clk);
 | 
						clk_disable(udc->usb_otg_clk);
 | 
				
			||||||
	clk_put(udc->usb_otg_clk);
 | 
						clk_put(udc->usb_otg_clk);
 | 
				
			||||||
	clk_disable(udc->usb_slv_clk);
 | 
						clk_disable(udc->usb_slv_clk);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1471,7 +1471,6 @@ static int m66592_udc_start(struct usb_gadget *g,
 | 
				
			||||||
	/* hook up the driver */
 | 
						/* hook up the driver */
 | 
				
			||||||
	driver->driver.bus = NULL;
 | 
						driver->driver.bus = NULL;
 | 
				
			||||||
	m66592->driver = driver;
 | 
						m66592->driver = driver;
 | 
				
			||||||
	m66592->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 | 
						m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 | 
				
			||||||
	if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
 | 
						if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
 | 
				
			||||||
| 
						 | 
					@ -1494,7 +1493,6 @@ static int m66592_udc_stop(struct usb_gadget *g,
 | 
				
			||||||
	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 | 
						m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	driver->unbind(&m66592->gadget);
 | 
						driver->unbind(&m66592->gadget);
 | 
				
			||||||
	m66592->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_controller(m66592);
 | 
						init_controller(m66592);
 | 
				
			||||||
	disable_controller(m66592);
 | 
						disable_controller(m66592);
 | 
				
			||||||
| 
						 | 
					@ -1538,7 +1536,6 @@ static int __exit m66592_remove(struct platform_device *pdev)
 | 
				
			||||||
	struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);
 | 
						struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	usb_del_gadget_udc(&m66592->gadget);
 | 
						usb_del_gadget_udc(&m66592->gadget);
 | 
				
			||||||
	device_del(&m66592->gadget.dev);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	del_timer_sync(&m66592->timer);
 | 
						del_timer_sync(&m66592->timer);
 | 
				
			||||||
	iounmap(m66592->reg);
 | 
						iounmap(m66592->reg);
 | 
				
			||||||
| 
						 | 
					@ -1608,12 +1605,7 @@ static int __init m66592_probe(struct platform_device *pdev)
 | 
				
			||||||
	dev_set_drvdata(&pdev->dev, m66592);
 | 
						dev_set_drvdata(&pdev->dev, m66592);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m66592->gadget.ops = &m66592_gadget_ops;
 | 
						m66592->gadget.ops = &m66592_gadget_ops;
 | 
				
			||||||
	device_initialize(&m66592->gadget.dev);
 | 
					 | 
				
			||||||
	dev_set_name(&m66592->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
	m66592->gadget.max_speed = USB_SPEED_HIGH;
 | 
						m66592->gadget.max_speed = USB_SPEED_HIGH;
 | 
				
			||||||
	m66592->gadget.dev.parent = &pdev->dev;
 | 
					 | 
				
			||||||
	m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
 | 
					 | 
				
			||||||
	m66592->gadget.dev.release = pdev->dev.release;
 | 
					 | 
				
			||||||
	m66592->gadget.name = udc_name;
 | 
						m66592->gadget.name = udc_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_timer(&m66592->timer);
 | 
						init_timer(&m66592->timer);
 | 
				
			||||||
| 
						 | 
					@ -1674,12 +1666,6 @@ static int __init m66592_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_controller(m66592);
 | 
						init_controller(m66592);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = device_add(&m66592->gadget.dev);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		pr_err("device_add error (%d)\n", ret);
 | 
					 | 
				
			||||||
		goto err_device_add;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
 | 
						ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto err_add_udc;
 | 
							goto err_add_udc;
 | 
				
			||||||
| 
						 | 
					@ -1688,9 +1674,6 @@ static int __init m66592_probe(struct platform_device *pdev)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_add_udc:
 | 
					err_add_udc:
 | 
				
			||||||
	device_del(&m66592->gadget.dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
err_device_add:
 | 
					 | 
				
			||||||
	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
 | 
						m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
clean_up3:
 | 
					clean_up3:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,8 +135,8 @@ static struct fsg_common fsg_common;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static u8 hostaddr[ETH_ALEN];
 | 
					static u8 hostaddr[ETH_ALEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static unsigned char tty_line;
 | 
					 | 
				
			||||||
static struct usb_function_instance *fi_acm;
 | 
					static struct usb_function_instance *fi_acm;
 | 
				
			||||||
 | 
					static struct eth_dev *the_dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/********** RNDIS **********/
 | 
					/********** RNDIS **********/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -152,7 +152,7 @@ static __init int rndis_do_config(struct usb_configuration *c)
 | 
				
			||||||
		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 | 
							c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = rndis_bind_config(c, hostaddr);
 | 
						ret = rndis_bind_config(c, hostaddr, the_dev);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -214,7 +214,7 @@ static __init int cdc_do_config(struct usb_configuration *c)
 | 
				
			||||||
		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 | 
							c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = ecm_bind_config(c, hostaddr);
 | 
						ret = ecm_bind_config(c, hostaddr, the_dev);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -269,7 +269,6 @@ static int cdc_config_register(struct usb_composite_dev *cdev)
 | 
				
			||||||
static int __ref multi_bind(struct usb_composite_dev *cdev)
 | 
					static int __ref multi_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usb_gadget *gadget = cdev->gadget;
 | 
						struct usb_gadget *gadget = cdev->gadget;
 | 
				
			||||||
	struct f_serial_opts *opts;
 | 
					 | 
				
			||||||
	int status;
 | 
						int status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!can_support_ecm(cdev->gadget)) {
 | 
						if (!can_support_ecm(cdev->gadget)) {
 | 
				
			||||||
| 
						 | 
					@ -279,24 +278,17 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* set up network link layer */
 | 
						/* set up network link layer */
 | 
				
			||||||
	status = gether_setup(cdev->gadget, hostaddr);
 | 
						the_dev = gether_setup(cdev->gadget, hostaddr);
 | 
				
			||||||
	if (status < 0)
 | 
						if (IS_ERR(the_dev))
 | 
				
			||||||
		return status;
 | 
							return PTR_ERR(the_dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* set up serial link layer */
 | 
						/* set up serial link layer */
 | 
				
			||||||
	status = gserial_alloc_line(&tty_line);
 | 
					 | 
				
			||||||
	if (status < 0)
 | 
					 | 
				
			||||||
		goto fail0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fi_acm = usb_get_function_instance("acm");
 | 
						fi_acm = usb_get_function_instance("acm");
 | 
				
			||||||
	if (IS_ERR(fi_acm)) {
 | 
						if (IS_ERR(fi_acm)) {
 | 
				
			||||||
		status = PTR_ERR(fi_acm);
 | 
							status = PTR_ERR(fi_acm);
 | 
				
			||||||
		goto fail0dot5;
 | 
							goto fail0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts = container_of(fi_acm, struct f_serial_opts, func_inst);
 | 
					 | 
				
			||||||
	opts->port_num = tty_line;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* set up mass storage function */
 | 
						/* set up mass storage function */
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		void *retp;
 | 
							void *retp;
 | 
				
			||||||
| 
						 | 
					@ -334,10 +326,8 @@ fail2:
 | 
				
			||||||
	fsg_common_put(&fsg_common);
 | 
						fsg_common_put(&fsg_common);
 | 
				
			||||||
fail1:
 | 
					fail1:
 | 
				
			||||||
	usb_put_function_instance(fi_acm);
 | 
						usb_put_function_instance(fi_acm);
 | 
				
			||||||
fail0dot5:
 | 
					 | 
				
			||||||
	gserial_free_line(tty_line);
 | 
					 | 
				
			||||||
fail0:
 | 
					fail0:
 | 
				
			||||||
	gether_cleanup();
 | 
						gether_cleanup(the_dev);
 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -350,8 +340,7 @@ static int __exit multi_unbind(struct usb_composite_dev *cdev)
 | 
				
			||||||
	usb_put_function(f_acm_rndis);
 | 
						usb_put_function(f_acm_rndis);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	usb_put_function_instance(fi_acm);
 | 
						usb_put_function_instance(fi_acm);
 | 
				
			||||||
	gserial_free_line(tty_line);
 | 
						gether_cleanup(the_dev);
 | 
				
			||||||
	gether_cleanup();
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,9 +30,6 @@
 | 
				
			||||||
#include <linux/platform_device.h>
 | 
					#include <linux/platform_device.h>
 | 
				
			||||||
#include <linux/platform_data/mv_usb.h>
 | 
					#include <linux/platform_data/mv_usb.h>
 | 
				
			||||||
#include <linux/clk.h>
 | 
					#include <linux/clk.h>
 | 
				
			||||||
#include <asm/system.h>
 | 
					 | 
				
			||||||
#include <asm/unaligned.h>
 | 
					 | 
				
			||||||
#include <asm/byteorder.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "mv_u3d.h"
 | 
					#include "mv_u3d.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -125,7 +122,7 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
 | 
				
			||||||
	struct mv_u3d_trb	*curr_trb;
 | 
						struct mv_u3d_trb	*curr_trb;
 | 
				
			||||||
	dma_addr_t cur_deq_lo;
 | 
						dma_addr_t cur_deq_lo;
 | 
				
			||||||
	struct mv_u3d_ep_context	*curr_ep_context;
 | 
						struct mv_u3d_ep_context	*curr_ep_context;
 | 
				
			||||||
	int trb_complete, actual, remaining_length;
 | 
						int trb_complete, actual, remaining_length = 0;
 | 
				
			||||||
	int direction, ep_num;
 | 
						int direction, ep_num;
 | 
				
			||||||
	int retval = 0;
 | 
						int retval = 0;
 | 
				
			||||||
	u32 tmp, status, length;
 | 
						u32 tmp, status, length;
 | 
				
			||||||
| 
						 | 
					@ -189,6 +186,8 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void mv_u3d_done(struct mv_u3d_ep *ep, struct mv_u3d_req *req, int status)
 | 
					void mv_u3d_done(struct mv_u3d_ep *ep, struct mv_u3d_req *req, int status)
 | 
				
			||||||
 | 
						__releases(&ep->udc->lock)
 | 
				
			||||||
 | 
						__acquires(&ep->udc->lock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mv_u3d *u3d = (struct mv_u3d *)ep->u3d;
 | 
						struct mv_u3d *u3d = (struct mv_u3d *)ep->u3d;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -812,19 +811,19 @@ mv_u3d_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_dbg(u3d->dev, "%s: %s, req: 0x%x\n",
 | 
						dev_dbg(u3d->dev, "%s: %s, req: 0x%p\n",
 | 
				
			||||||
			__func__, _ep->name, (u32)req);
 | 
								__func__, _ep->name, req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* catch various bogus parameters */
 | 
						/* catch various bogus parameters */
 | 
				
			||||||
	if (!req->req.complete || !req->req.buf
 | 
						if (!req->req.complete || !req->req.buf
 | 
				
			||||||
			|| !list_empty(&req->queue)) {
 | 
								|| !list_empty(&req->queue)) {
 | 
				
			||||||
		dev_err(u3d->dev,
 | 
							dev_err(u3d->dev,
 | 
				
			||||||
			"%s, bad params, _req: 0x%x,"
 | 
								"%s, bad params, _req: 0x%p,"
 | 
				
			||||||
			"req->req.complete: 0x%x, req->req.buf: 0x%x,"
 | 
								"req->req.complete: 0x%p, req->req.buf: 0x%p,"
 | 
				
			||||||
			"list_empty: 0x%x\n",
 | 
								"list_empty: 0x%x\n",
 | 
				
			||||||
			__func__, (u32)_req,
 | 
								__func__, _req,
 | 
				
			||||||
			(u32)req->req.complete, (u32)req->req.buf,
 | 
								req->req.complete, req->req.buf,
 | 
				
			||||||
			(u32)list_empty(&req->queue));
 | 
								list_empty(&req->queue));
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (unlikely(!ep->ep.desc)) {
 | 
						if (unlikely(!ep->ep.desc)) {
 | 
				
			||||||
| 
						 | 
					@ -905,7 +904,7 @@ static int mv_u3d_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
 | 
				
			||||||
					struct mv_u3d_req, queue);
 | 
										struct mv_u3d_req, queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* Point first TRB of next request to the EP context. */
 | 
								/* Point first TRB of next request to the EP context. */
 | 
				
			||||||
			iowrite32((u32) next_req->trb_head,
 | 
								iowrite32((unsigned long) next_req->trb_head,
 | 
				
			||||||
					&ep_context->trb_addr_lo);
 | 
										&ep_context->trb_addr_lo);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			struct mv_u3d_ep_context *ep_context;
 | 
								struct mv_u3d_ep_context *ep_context;
 | 
				
			||||||
| 
						 | 
					@ -1264,7 +1263,6 @@ static int mv_u3d_start(struct usb_gadget *g,
 | 
				
			||||||
	/* hook up the driver ... */
 | 
						/* hook up the driver ... */
 | 
				
			||||||
	driver->driver.bus = NULL;
 | 
						driver->driver.bus = NULL;
 | 
				
			||||||
	u3d->driver = driver;
 | 
						u3d->driver = driver;
 | 
				
			||||||
	u3d->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u3d->ep0_dir = USB_DIR_OUT;
 | 
						u3d->ep0_dir = USB_DIR_OUT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1302,7 +1300,6 @@ static int mv_u3d_stop(struct usb_gadget *g,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_irqrestore(&u3d->lock, flags);
 | 
						spin_unlock_irqrestore(&u3d->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u3d->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	u3d->driver = NULL;
 | 
						u3d->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -1525,6 +1522,8 @@ static int mv_u3d_is_set_configuration(struct usb_ctrlrequest *setup)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void mv_u3d_handle_setup_packet(struct mv_u3d *u3d, u8 ep_num,
 | 
					static void mv_u3d_handle_setup_packet(struct mv_u3d *u3d, u8 ep_num,
 | 
				
			||||||
	struct usb_ctrlrequest *setup)
 | 
						struct usb_ctrlrequest *setup)
 | 
				
			||||||
 | 
						__releases(&u3c->lock)
 | 
				
			||||||
 | 
						__acquires(&u3c->lock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	bool delegate = false;
 | 
						bool delegate = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1758,11 +1757,6 @@ static irqreturn_t mv_u3d_irq(int irq, void *dev)
 | 
				
			||||||
	return IRQ_HANDLED;
 | 
						return IRQ_HANDLED;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void mv_u3d_gadget_release(struct device *dev)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	dev_dbg(dev, "%s\n", __func__);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int mv_u3d_remove(struct platform_device *dev)
 | 
					static int mv_u3d_remove(struct platform_device *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mv_u3d *u3d = platform_get_drvdata(dev);
 | 
						struct mv_u3d *u3d = platform_get_drvdata(dev);
 | 
				
			||||||
| 
						 | 
					@ -1792,8 +1786,6 @@ static int mv_u3d_remove(struct platform_device *dev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clk_put(u3d->clk);
 | 
						clk_put(u3d->clk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_unregister(&u3d->gadget.dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	platform_set_drvdata(dev, NULL);
 | 
						platform_set_drvdata(dev, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kfree(u3d);
 | 
						kfree(u3d);
 | 
				
			||||||
| 
						 | 
					@ -1829,7 +1821,7 @@ static int mv_u3d_probe(struct platform_device *dev)
 | 
				
			||||||
	u3d->dev = &dev->dev;
 | 
						u3d->dev = &dev->dev;
 | 
				
			||||||
	u3d->vbus = pdata->vbus;
 | 
						u3d->vbus = pdata->vbus;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u3d->clk = clk_get(&dev->dev, pdata->clkname[0]);
 | 
						u3d->clk = clk_get(&dev->dev, NULL);
 | 
				
			||||||
	if (IS_ERR(u3d->clk)) {
 | 
						if (IS_ERR(u3d->clk)) {
 | 
				
			||||||
		retval = PTR_ERR(u3d->clk);
 | 
							retval = PTR_ERR(u3d->clk);
 | 
				
			||||||
		goto err_get_clk;
 | 
							goto err_get_clk;
 | 
				
			||||||
| 
						 | 
					@ -1849,8 +1841,9 @@ static int mv_u3d_probe(struct platform_device *dev)
 | 
				
			||||||
		retval = -EBUSY;
 | 
							retval = -EBUSY;
 | 
				
			||||||
		goto err_map_cap_regs;
 | 
							goto err_map_cap_regs;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		dev_dbg(&dev->dev, "cap_regs address: 0x%x/0x%x\n",
 | 
							dev_dbg(&dev->dev, "cap_regs address: 0x%lx/0x%lx\n",
 | 
				
			||||||
			(unsigned int)r->start, (unsigned int)u3d->cap_regs);
 | 
								(unsigned long) r->start,
 | 
				
			||||||
 | 
								(unsigned long) u3d->cap_regs);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* we will access controller register, so enable the u3d controller */
 | 
						/* we will access controller register, so enable the u3d controller */
 | 
				
			||||||
| 
						 | 
					@ -1864,10 +1857,10 @@ static int mv_u3d_probe(struct platform_device *dev)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u3d->op_regs = (struct mv_u3d_op_regs __iomem *)((u32)u3d->cap_regs
 | 
						u3d->op_regs = (struct mv_u3d_op_regs __iomem *)(u3d->cap_regs
 | 
				
			||||||
		+ MV_U3D_USB3_OP_REGS_OFFSET);
 | 
							+ MV_U3D_USB3_OP_REGS_OFFSET);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)((u32)u3d->cap_regs
 | 
						u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)(u3d->cap_regs
 | 
				
			||||||
		+ ioread32(&u3d->cap_regs->vuoff));
 | 
							+ ioread32(&u3d->cap_regs->vuoff));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u3d->max_eps = 16;
 | 
						u3d->max_eps = 16;
 | 
				
			||||||
| 
						 | 
					@ -1957,16 +1950,8 @@ static int mv_u3d_probe(struct platform_device *dev)
 | 
				
			||||||
	u3d->gadget.speed = USB_SPEED_UNKNOWN;	/* speed */
 | 
						u3d->gadget.speed = USB_SPEED_UNKNOWN;	/* speed */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* the "gadget" abstracts/virtualizes the controller */
 | 
						/* the "gadget" abstracts/virtualizes the controller */
 | 
				
			||||||
	dev_set_name(&u3d->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
	u3d->gadget.dev.parent = &dev->dev;
 | 
					 | 
				
			||||||
	u3d->gadget.dev.dma_mask = dev->dev.dma_mask;
 | 
					 | 
				
			||||||
	u3d->gadget.dev.release = mv_u3d_gadget_release;
 | 
					 | 
				
			||||||
	u3d->gadget.name = driver_name;		/* gadget name */
 | 
						u3d->gadget.name = driver_name;		/* gadget name */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = device_register(&u3d->gadget.dev);
 | 
					 | 
				
			||||||
	if (retval)
 | 
					 | 
				
			||||||
		goto err_register_gadget_device;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mv_u3d_eps_init(u3d);
 | 
						mv_u3d_eps_init(u3d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* external vbus detection */
 | 
						/* external vbus detection */
 | 
				
			||||||
| 
						 | 
					@ -1991,8 +1976,6 @@ static int mv_u3d_probe(struct platform_device *dev)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_unregister:
 | 
					err_unregister:
 | 
				
			||||||
	device_unregister(&u3d->gadget.dev);
 | 
					 | 
				
			||||||
err_register_gadget_device:
 | 
					 | 
				
			||||||
	free_irq(u3d->irq, &dev->dev);
 | 
						free_irq(u3d->irq, &dev->dev);
 | 
				
			||||||
err_request_irq:
 | 
					err_request_irq:
 | 
				
			||||||
err_get_irq:
 | 
					err_get_irq:
 | 
				
			||||||
| 
						 | 
					@ -2021,7 +2004,7 @@ err_pdata:
 | 
				
			||||||
	return retval;
 | 
						return retval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_PM
 | 
					#ifdef CONFIG_PM_SLEEP
 | 
				
			||||||
static int mv_u3d_suspend(struct device *dev)
 | 
					static int mv_u3d_suspend(struct device *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mv_u3d *u3d = dev_get_drvdata(dev);
 | 
						struct mv_u3d *u3d = dev_get_drvdata(dev);
 | 
				
			||||||
| 
						 | 
					@ -2064,10 +2047,10 @@ static int mv_u3d_resume(struct device *dev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void mv_u3d_shutdown(struct platform_device *dev)
 | 
					static void mv_u3d_shutdown(struct platform_device *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mv_u3d *u3d = dev_get_drvdata(&dev->dev);
 | 
						struct mv_u3d *u3d = dev_get_drvdata(&dev->dev);
 | 
				
			||||||
| 
						 | 
					@ -2080,14 +2063,12 @@ static void mv_u3d_shutdown(struct platform_device *dev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct platform_driver mv_u3d_driver = {
 | 
					static struct platform_driver mv_u3d_driver = {
 | 
				
			||||||
	.probe		= mv_u3d_probe,
 | 
						.probe		= mv_u3d_probe,
 | 
				
			||||||
	.remove		= __exit_p(mv_u3d_remove),
 | 
						.remove		= mv_u3d_remove,
 | 
				
			||||||
	.shutdown	= mv_u3d_shutdown,
 | 
						.shutdown	= mv_u3d_shutdown,
 | 
				
			||||||
	.driver		= {
 | 
						.driver		= {
 | 
				
			||||||
		.owner	= THIS_MODULE,
 | 
							.owner	= THIS_MODULE,
 | 
				
			||||||
		.name	= "mv-u3d",
 | 
							.name	= "mv-u3d",
 | 
				
			||||||
#ifdef CONFIG_PM
 | 
					 | 
				
			||||||
		.pm	= &mv_u3d_pm_ops,
 | 
							.pm	= &mv_u3d_pm_ops,
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -222,8 +222,7 @@ struct mv_udc {
 | 
				
			||||||
	struct mv_usb_platform_data     *pdata;
 | 
						struct mv_usb_platform_data     *pdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* some SOC has mutiple clock sources for USB*/
 | 
						/* some SOC has mutiple clock sources for USB*/
 | 
				
			||||||
	unsigned int    clknum;
 | 
						struct clk      *clk;
 | 
				
			||||||
	struct clk      *clk[0];
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* endpoint data structure */
 | 
					/* endpoint data structure */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,6 +212,8 @@ static int process_ep_req(struct mv_udc *udc, int index,
 | 
				
			||||||
 * request is still in progress.
 | 
					 * request is still in progress.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void done(struct mv_ep *ep, struct mv_req *req, int status)
 | 
					static void done(struct mv_ep *ep, struct mv_req *req, int status)
 | 
				
			||||||
 | 
						__releases(&ep->udc->lock)
 | 
				
			||||||
 | 
						__acquires(&ep->udc->lock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mv_udc *udc = NULL;
 | 
						struct mv_udc *udc = NULL;
 | 
				
			||||||
	unsigned char stopped = ep->stopped;
 | 
						unsigned char stopped = ep->stopped;
 | 
				
			||||||
| 
						 | 
					@ -237,18 +239,7 @@ static void done(struct mv_ep *ep, struct mv_req *req, int status)
 | 
				
			||||||
		dma_pool_free(udc->dtd_pool, curr_td, curr_td->td_dma);
 | 
							dma_pool_free(udc->dtd_pool, curr_td, curr_td->td_dma);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (req->mapped) {
 | 
						usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
 | 
				
			||||||
		dma_unmap_single(ep->udc->gadget.dev.parent,
 | 
					 | 
				
			||||||
			req->req.dma, req->req.length,
 | 
					 | 
				
			||||||
			((ep_dir(ep) == EP_DIR_IN) ?
 | 
					 | 
				
			||||||
				DMA_TO_DEVICE : DMA_FROM_DEVICE));
 | 
					 | 
				
			||||||
		req->req.dma = DMA_ADDR_INVALID;
 | 
					 | 
				
			||||||
		req->mapped = 0;
 | 
					 | 
				
			||||||
	} else
 | 
					 | 
				
			||||||
		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
 | 
					 | 
				
			||||||
			req->req.dma, req->req.length,
 | 
					 | 
				
			||||||
			((ep_dir(ep) == EP_DIR_IN) ?
 | 
					 | 
				
			||||||
				DMA_TO_DEVICE : DMA_FROM_DEVICE));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (status && (status != -ESHUTDOWN))
 | 
						if (status && (status != -ESHUTDOWN))
 | 
				
			||||||
		dev_info(&udc->dev->dev, "complete %s req %p stat %d len %u/%u",
 | 
							dev_info(&udc->dev->dev, "complete %s req %p stat %d len %u/%u",
 | 
				
			||||||
| 
						 | 
					@ -732,21 +723,9 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 | 
				
			||||||
	req->ep = ep;
 | 
						req->ep = ep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* map virtual address to hardware */
 | 
						/* map virtual address to hardware */
 | 
				
			||||||
	if (req->req.dma == DMA_ADDR_INVALID) {
 | 
						retval = usb_gadget_map_request(&udc->gadget, _req, ep_dir(ep));
 | 
				
			||||||
		req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
 | 
						if (retval)
 | 
				
			||||||
					req->req.buf,
 | 
							return retval;
 | 
				
			||||||
					req->req.length, ep_dir(ep)
 | 
					 | 
				
			||||||
						? DMA_TO_DEVICE
 | 
					 | 
				
			||||||
						: DMA_FROM_DEVICE);
 | 
					 | 
				
			||||||
		req->mapped = 1;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		dma_sync_single_for_device(ep->udc->gadget.dev.parent,
 | 
					 | 
				
			||||||
					req->req.dma, req->req.length,
 | 
					 | 
				
			||||||
					ep_dir(ep)
 | 
					 | 
				
			||||||
						? DMA_TO_DEVICE
 | 
					 | 
				
			||||||
						: DMA_FROM_DEVICE);
 | 
					 | 
				
			||||||
		req->mapped = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req->req.status = -EINPROGRESS;
 | 
						req->req.status = -EINPROGRESS;
 | 
				
			||||||
	req->req.actual = 0;
 | 
						req->req.actual = 0;
 | 
				
			||||||
| 
						 | 
					@ -780,18 +759,7 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_unmap_dma:
 | 
					err_unmap_dma:
 | 
				
			||||||
	if (req->mapped) {
 | 
						usb_gadget_unmap_request(&udc->gadget, _req, ep_dir(ep));
 | 
				
			||||||
		dma_unmap_single(ep->udc->gadget.dev.parent,
 | 
					 | 
				
			||||||
				req->req.dma, req->req.length,
 | 
					 | 
				
			||||||
				((ep_dir(ep) == EP_DIR_IN) ?
 | 
					 | 
				
			||||||
				DMA_TO_DEVICE : DMA_FROM_DEVICE));
 | 
					 | 
				
			||||||
		req->req.dma = DMA_ADDR_INVALID;
 | 
					 | 
				
			||||||
		req->mapped = 0;
 | 
					 | 
				
			||||||
	} else
 | 
					 | 
				
			||||||
		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
 | 
					 | 
				
			||||||
				req->req.dma, req->req.length,
 | 
					 | 
				
			||||||
				((ep_dir(ep) == EP_DIR_IN) ?
 | 
					 | 
				
			||||||
				DMA_TO_DEVICE : DMA_FROM_DEVICE));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return retval;
 | 
						return retval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1006,18 +974,12 @@ static struct usb_ep_ops mv_ep_ops = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void udc_clock_enable(struct mv_udc *udc)
 | 
					static void udc_clock_enable(struct mv_udc *udc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int i;
 | 
						clk_prepare_enable(udc->clk);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < udc->clknum; i++)
 | 
					 | 
				
			||||||
		clk_prepare_enable(udc->clk[i]);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void udc_clock_disable(struct mv_udc *udc)
 | 
					static void udc_clock_disable(struct mv_udc *udc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int i;
 | 
						clk_disable_unprepare(udc->clk);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < udc->clknum; i++)
 | 
					 | 
				
			||||||
		clk_disable_unprepare(udc->clk[i]);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void udc_stop(struct mv_udc *udc)
 | 
					static void udc_stop(struct mv_udc *udc)
 | 
				
			||||||
| 
						 | 
					@ -1386,7 +1348,6 @@ static int mv_udc_start(struct usb_gadget *gadget,
 | 
				
			||||||
	/* hook up the driver ... */
 | 
						/* hook up the driver ... */
 | 
				
			||||||
	driver->driver.bus = NULL;
 | 
						driver->driver.bus = NULL;
 | 
				
			||||||
	udc->driver = driver;
 | 
						udc->driver = driver;
 | 
				
			||||||
	udc->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->usb_state = USB_STATE_ATTACHED;
 | 
						udc->usb_state = USB_STATE_ATTACHED;
 | 
				
			||||||
	udc->ep0_state = WAIT_FOR_SETUP;
 | 
						udc->ep0_state = WAIT_FOR_SETUP;
 | 
				
			||||||
| 
						 | 
					@ -1401,7 +1362,6 @@ static int mv_udc_start(struct usb_gadget *gadget,
 | 
				
			||||||
			dev_err(&udc->dev->dev,
 | 
								dev_err(&udc->dev->dev,
 | 
				
			||||||
				"unable to register peripheral to otg\n");
 | 
									"unable to register peripheral to otg\n");
 | 
				
			||||||
			udc->driver = NULL;
 | 
								udc->driver = NULL;
 | 
				
			||||||
			udc->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
			return retval;
 | 
								return retval;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1437,7 +1397,6 @@ static int mv_udc_stop(struct usb_gadget *gadget,
 | 
				
			||||||
	spin_unlock_irqrestore(&udc->lock, flags);
 | 
						spin_unlock_irqrestore(&udc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* unbind gadget driver */
 | 
						/* unbind gadget driver */
 | 
				
			||||||
	udc->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	udc->driver = NULL;
 | 
						udc->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -1528,14 +1487,7 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	if (req->mapped) {
 | 
						usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
 | 
				
			||||||
		dma_unmap_single(ep->udc->gadget.dev.parent,
 | 
					 | 
				
			||||||
				req->req.dma, req->req.length,
 | 
					 | 
				
			||||||
				((ep_dir(ep) == EP_DIR_IN) ?
 | 
					 | 
				
			||||||
				DMA_TO_DEVICE : DMA_FROM_DEVICE));
 | 
					 | 
				
			||||||
		req->req.dma = DMA_ADDR_INVALID;
 | 
					 | 
				
			||||||
		req->mapped = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return retval;
 | 
						return retval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1695,6 +1647,8 @@ out:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_setup_packet(struct mv_udc *udc, u8 ep_num,
 | 
					static void handle_setup_packet(struct mv_udc *udc, u8 ep_num,
 | 
				
			||||||
	struct usb_ctrlrequest *setup)
 | 
						struct usb_ctrlrequest *setup)
 | 
				
			||||||
 | 
						__releases(&ep->udc->lock)
 | 
				
			||||||
 | 
						__acquires(&ep->udc->lock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	bool delegate = false;
 | 
						bool delegate = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1891,7 +1845,7 @@ static void irq_process_tr_complete(struct mv_udc *udc)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void irq_process_reset(struct mv_udc *udc)
 | 
					static void irq_process_reset(struct mv_udc *udc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32 tmp;
 | 
						u32 tmp;
 | 
				
			||||||
	unsigned int loops;
 | 
						unsigned int loops;
 | 
				
			||||||
| 
						 | 
					@ -2138,8 +2092,6 @@ static int mv_udc_remove(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mv_udc_disable(udc);
 | 
						mv_udc_disable(udc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* free dev, wait for the release() finished */
 | 
						/* free dev, wait for the release() finished */
 | 
				
			||||||
	wait_for_completion(udc->done);
 | 
						wait_for_completion(udc->done);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2151,7 +2103,6 @@ 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 = pdev->dev.platform_data;
 | 
				
			||||||
	struct mv_udc *udc;
 | 
						struct mv_udc *udc;
 | 
				
			||||||
	int retval = 0;
 | 
						int retval = 0;
 | 
				
			||||||
	int clk_i = 0;
 | 
					 | 
				
			||||||
	struct resource *r;
 | 
						struct resource *r;
 | 
				
			||||||
	size_t size;
 | 
						size_t size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2160,8 +2111,7 @@ static int mv_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
		return -ENODEV;
 | 
							return -ENODEV;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum;
 | 
						udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL);
 | 
				
			||||||
	udc = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 | 
					 | 
				
			||||||
	if (udc == NULL) {
 | 
						if (udc == NULL) {
 | 
				
			||||||
		dev_err(&pdev->dev, "failed to allocate memory for udc\n");
 | 
							dev_err(&pdev->dev, "failed to allocate memory for udc\n");
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
| 
						 | 
					@ -2173,27 +2123,25 @@ static int mv_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->dev = pdev;
 | 
						udc->dev = pdev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_USB_OTG_UTILS
 | 
					 | 
				
			||||||
	if (pdata->mode == MV_USB_MODE_OTG) {
 | 
						if (pdata->mode == MV_USB_MODE_OTG) {
 | 
				
			||||||
		udc->transceiver = devm_usb_get_phy(&pdev->dev,
 | 
							udc->transceiver = devm_usb_get_phy(&pdev->dev,
 | 
				
			||||||
					USB_PHY_TYPE_USB2);
 | 
										USB_PHY_TYPE_USB2);
 | 
				
			||||||
		if (IS_ERR_OR_NULL(udc->transceiver)) {
 | 
							if (IS_ERR(udc->transceiver)) {
 | 
				
			||||||
			udc->transceiver = NULL;
 | 
								retval = PTR_ERR(udc->transceiver);
 | 
				
			||||||
			return -ENODEV;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->clknum = pdata->clknum;
 | 
								if (retval == -ENXIO)
 | 
				
			||||||
	for (clk_i = 0; clk_i < udc->clknum; clk_i++) {
 | 
									return retval;
 | 
				
			||||||
		udc->clk[clk_i] = devm_clk_get(&pdev->dev,
 | 
					
 | 
				
			||||||
					pdata->clkname[clk_i]);
 | 
								udc->transceiver = NULL;
 | 
				
			||||||
		if (IS_ERR(udc->clk[clk_i])) {
 | 
								return -EPROBE_DEFER;
 | 
				
			||||||
			retval = PTR_ERR(udc->clk[clk_i]);
 | 
					 | 
				
			||||||
			return retval;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* udc only have one sysclk. */
 | 
				
			||||||
 | 
						udc->clk = devm_clk_get(&pdev->dev, NULL);
 | 
				
			||||||
 | 
						if (IS_ERR(udc->clk))
 | 
				
			||||||
 | 
							return PTR_ERR(udc->clk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
 | 
						r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
 | 
				
			||||||
	if (r == NULL) {
 | 
						if (r == NULL) {
 | 
				
			||||||
		dev_err(&pdev->dev, "no I/O memory resource defined\n");
 | 
							dev_err(&pdev->dev, "no I/O memory resource defined\n");
 | 
				
			||||||
| 
						 | 
					@ -2311,16 +2259,8 @@ static int mv_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
	udc->gadget.max_speed = USB_SPEED_HIGH;	/* support dual speed */
 | 
						udc->gadget.max_speed = USB_SPEED_HIGH;	/* support dual speed */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* the "gadget" abstracts/virtualizes the controller */
 | 
						/* the "gadget" abstracts/virtualizes the controller */
 | 
				
			||||||
	dev_set_name(&udc->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
	udc->gadget.dev.parent = &pdev->dev;
 | 
					 | 
				
			||||||
	udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
 | 
					 | 
				
			||||||
	udc->gadget.dev.release = gadget_release;
 | 
					 | 
				
			||||||
	udc->gadget.name = driver_name;		/* gadget name */
 | 
						udc->gadget.name = driver_name;		/* gadget name */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = device_register(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	if (retval)
 | 
					 | 
				
			||||||
		goto err_destroy_dma;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	eps_init(udc);
 | 
						eps_init(udc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* VBUS detect: we can disable/enable clock on demand.*/
 | 
						/* VBUS detect: we can disable/enable clock on demand.*/
 | 
				
			||||||
| 
						 | 
					@ -2342,7 +2282,7 @@ static int mv_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
		if (!udc->qwork) {
 | 
							if (!udc->qwork) {
 | 
				
			||||||
			dev_err(&pdev->dev, "cannot create workqueue\n");
 | 
								dev_err(&pdev->dev, "cannot create workqueue\n");
 | 
				
			||||||
			retval = -ENOMEM;
 | 
								retval = -ENOMEM;
 | 
				
			||||||
			goto err_unregister;
 | 
								goto err_destroy_dma;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		INIT_WORK(&udc->vbus_work, mv_udc_vbus_work);
 | 
							INIT_WORK(&udc->vbus_work, mv_udc_vbus_work);
 | 
				
			||||||
| 
						 | 
					@ -2358,7 +2298,8 @@ static int mv_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		udc->vbus_active = 1;
 | 
							udc->vbus_active = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
 | 
						retval = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
 | 
				
			||||||
 | 
								gadget_release);
 | 
				
			||||||
	if (retval)
 | 
						if (retval)
 | 
				
			||||||
		goto err_create_workqueue;
 | 
							goto err_create_workqueue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2370,8 +2311,6 @@ static int mv_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_create_workqueue:
 | 
					err_create_workqueue:
 | 
				
			||||||
	destroy_workqueue(udc->qwork);
 | 
						destroy_workqueue(udc->qwork);
 | 
				
			||||||
err_unregister:
 | 
					 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
err_destroy_dma:
 | 
					err_destroy_dma:
 | 
				
			||||||
	dma_pool_destroy(udc->dtd_pool);
 | 
						dma_pool_destroy(udc->dtd_pool);
 | 
				
			||||||
err_free_dma:
 | 
					err_free_dma:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -111,6 +111,7 @@ static struct usb_gadget_strings *dev_strings[] = {
 | 
				
			||||||
	NULL,
 | 
						NULL,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct eth_dev *the_dev;
 | 
				
			||||||
static u8 hostaddr[ETH_ALEN];
 | 
					static u8 hostaddr[ETH_ALEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*-------------------------------------------------------------------------*/
 | 
					/*-------------------------------------------------------------------------*/
 | 
				
			||||||
| 
						 | 
					@ -124,7 +125,7 @@ static int __init ncm_do_config(struct usb_configuration *c)
 | 
				
			||||||
		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 | 
							c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ncm_bind_config(c, hostaddr);
 | 
						return ncm_bind_config(c, hostaddr, the_dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_configuration ncm_config_driver = {
 | 
					static struct usb_configuration ncm_config_driver = {
 | 
				
			||||||
| 
						 | 
					@ -143,9 +144,9 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
	int			status;
 | 
						int			status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* set up network link layer */
 | 
						/* set up network link layer */
 | 
				
			||||||
	status = gether_setup(cdev->gadget, hostaddr);
 | 
						the_dev = gether_setup(cdev->gadget, hostaddr);
 | 
				
			||||||
	if (status < 0)
 | 
						if (IS_ERR(the_dev))
 | 
				
			||||||
		return status;
 | 
							return PTR_ERR(the_dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Allocate string descriptor numbers ... note that string
 | 
						/* Allocate string descriptor numbers ... note that string
 | 
				
			||||||
	 * contents can be overridden by the composite_dev glue.
 | 
						 * contents can be overridden by the composite_dev glue.
 | 
				
			||||||
| 
						 | 
					@ -168,13 +169,13 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fail:
 | 
					fail:
 | 
				
			||||||
	gether_cleanup();
 | 
						gether_cleanup(the_dev);
 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __exit gncm_unbind(struct usb_composite_dev *cdev)
 | 
					static int __exit gncm_unbind(struct usb_composite_dev *cdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	gether_cleanup();
 | 
						gether_cleanup(the_dev);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,6 @@ static const char * const ep_name[] = {
 | 
				
			||||||
	"ep-a", "ep-b", "ep-c",
 | 
						"ep-a", "ep-b", "ep-c",
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DMA_ADDR_INVALID	(~(dma_addr_t)0)
 | 
					 | 
				
			||||||
#ifdef CONFIG_USB_NET2272_DMA
 | 
					#ifdef CONFIG_USB_NET2272_DMA
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * use_dma: the NET2272 can use an external DMA controller.
 | 
					 * use_dma: the NET2272 can use an external DMA controller.
 | 
				
			||||||
| 
						 | 
					@ -341,7 +340,6 @@ net2272_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
 | 
				
			||||||
	if (!req)
 | 
						if (!req)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req->req.dma = DMA_ADDR_INVALID;
 | 
					 | 
				
			||||||
	INIT_LIST_HEAD(&req->queue);
 | 
						INIT_LIST_HEAD(&req->queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &req->req;
 | 
						return &req->req;
 | 
				
			||||||
| 
						 | 
					@ -913,7 +911,7 @@ net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (likely(req != 0))
 | 
						if (likely(req))
 | 
				
			||||||
		list_add_tail(&req->queue, &ep->queue);
 | 
							list_add_tail(&req->queue, &ep->queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (likely(!list_empty(&ep->queue)))
 | 
						if (likely(!list_empty(&ep->queue)))
 | 
				
			||||||
| 
						 | 
					@ -1467,7 +1465,6 @@ static int net2272_start(struct usb_gadget *_gadget,
 | 
				
			||||||
	dev->softconnect = 1;
 | 
						dev->softconnect = 1;
 | 
				
			||||||
	driver->driver.bus = NULL;
 | 
						driver->driver.bus = NULL;
 | 
				
			||||||
	dev->driver = driver;
 | 
						dev->driver = driver;
 | 
				
			||||||
	dev->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* ... then enable host detection and ep0; and we're ready
 | 
						/* ... then enable host detection and ep0; and we're ready
 | 
				
			||||||
	 * for set_configuration as well as eventual disconnect.
 | 
						 * for set_configuration as well as eventual disconnect.
 | 
				
			||||||
| 
						 | 
					@ -1517,7 +1514,6 @@ static int net2272_stop(struct usb_gadget *_gadget,
 | 
				
			||||||
	stop_activity(dev, driver);
 | 
						stop_activity(dev, driver);
 | 
				
			||||||
	spin_unlock_irqrestore(&dev->lock, flags);
 | 
						spin_unlock_irqrestore(&dev->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	dev->driver = NULL;
 | 
						dev->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_dbg(dev->dev, "unregistered driver '%s'\n", driver->driver.name);
 | 
						dev_dbg(dev->dev, "unregistered driver '%s'\n", driver->driver.name);
 | 
				
			||||||
| 
						 | 
					@ -1549,7 +1545,7 @@ net2272_handle_dma(struct net2272_ep *ep)
 | 
				
			||||||
	      | (ep->dev->dma_eot_polarity << EOT_POLARITY)
 | 
						      | (ep->dev->dma_eot_polarity << EOT_POLARITY)
 | 
				
			||||||
	      | (ep->dev->dma_dack_polarity << DACK_POLARITY)
 | 
						      | (ep->dev->dma_dack_polarity << DACK_POLARITY)
 | 
				
			||||||
	      | (ep->dev->dma_dreq_polarity << DREQ_POLARITY)
 | 
						      | (ep->dev->dma_dreq_polarity << DREQ_POLARITY)
 | 
				
			||||||
	      | ((ep->dma >> 1) << DMA_ENDPOINT_SELECT));
 | 
						      | (ep->dma << DMA_ENDPOINT_SELECT));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ep->dev->dma_busy = 0;
 | 
						ep->dev->dma_busy = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1622,7 +1618,7 @@ net2272_handle_ep(struct net2272_ep *ep)
 | 
				
			||||||
	ep->irqs++;
 | 
						ep->irqs++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_vdbg(ep->dev->dev, "%s ack ep_stat0 %02x, ep_stat1 %02x, req %p\n",
 | 
						dev_vdbg(ep->dev->dev, "%s ack ep_stat0 %02x, ep_stat1 %02x, req %p\n",
 | 
				
			||||||
		ep->ep.name, stat0, stat1, req ? &req->req : 0);
 | 
							ep->ep.name, stat0, stat1, req ? &req->req : NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	net2272_ep_write(ep, EP_STAT0, stat0 &
 | 
						net2272_ep_write(ep, EP_STAT0, stat0 &
 | 
				
			||||||
		~((1 << NAK_OUT_PACKETS)
 | 
							~((1 << NAK_OUT_PACKETS)
 | 
				
			||||||
| 
						 | 
					@ -2216,7 +2212,6 @@ net2272_remove(struct net2272 *dev)
 | 
				
			||||||
	free_irq(dev->irq, dev);
 | 
						free_irq(dev->irq, dev);
 | 
				
			||||||
	iounmap(dev->base_addr);
 | 
						iounmap(dev->base_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_unregister(&dev->gadget.dev);
 | 
					 | 
				
			||||||
	device_remove_file(dev->dev, &dev_attr_registers);
 | 
						device_remove_file(dev->dev, &dev_attr_registers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_info(dev->dev, "unbind\n");
 | 
						dev_info(dev->dev, "unbind\n");
 | 
				
			||||||
| 
						 | 
					@ -2243,10 +2238,6 @@ static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq)
 | 
				
			||||||
	ret->gadget.max_speed = USB_SPEED_HIGH;
 | 
						ret->gadget.max_speed = USB_SPEED_HIGH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* the "gadget" abstracts/virtualizes the controller */
 | 
						/* the "gadget" abstracts/virtualizes the controller */
 | 
				
			||||||
	dev_set_name(&ret->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
	ret->gadget.dev.parent = dev;
 | 
					 | 
				
			||||||
	ret->gadget.dev.dma_mask = dev->dma_mask;
 | 
					 | 
				
			||||||
	ret->gadget.dev.release = net2272_gadget_release;
 | 
					 | 
				
			||||||
	ret->gadget.name = driver_name;
 | 
						ret->gadget.name = driver_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
| 
						 | 
					@ -2282,14 +2273,12 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
 | 
				
			||||||
		dma_mode_string());
 | 
							dma_mode_string());
 | 
				
			||||||
	dev_info(dev->dev, "version: %s\n", driver_vers);
 | 
						dev_info(dev->dev, "version: %s\n", driver_vers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = device_register(&dev->gadget.dev);
 | 
					 | 
				
			||||||
	if (ret)
 | 
					 | 
				
			||||||
		goto err_irq;
 | 
					 | 
				
			||||||
	ret = device_create_file(dev->dev, &dev_attr_registers);
 | 
						ret = device_create_file(dev->dev, &dev_attr_registers);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto err_dev_reg;
 | 
							goto err_irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = usb_add_gadget_udc(dev->dev, &dev->gadget);
 | 
						ret = usb_add_gadget_udc_release(dev->dev, &dev->gadget,
 | 
				
			||||||
 | 
								net2272_gadget_release);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto err_add_udc;
 | 
							goto err_add_udc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2297,8 +2286,6 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_add_udc:
 | 
					err_add_udc:
 | 
				
			||||||
	device_remove_file(dev->dev, &dev_attr_registers);
 | 
						device_remove_file(dev->dev, &dev_attr_registers);
 | 
				
			||||||
 err_dev_reg:
 | 
					 | 
				
			||||||
	device_unregister(&dev->gadget.dev);
 | 
					 | 
				
			||||||
 err_irq:
 | 
					 err_irq:
 | 
				
			||||||
	free_irq(dev->irq, dev);
 | 
						free_irq(dev->irq, dev);
 | 
				
			||||||
 err:
 | 
					 err:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,7 +65,6 @@
 | 
				
			||||||
#define	DRIVER_DESC		"PLX NET228x USB Peripheral Controller"
 | 
					#define	DRIVER_DESC		"PLX NET228x USB Peripheral Controller"
 | 
				
			||||||
#define	DRIVER_VERSION		"2005 Sept 27"
 | 
					#define	DRIVER_VERSION		"2005 Sept 27"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
 | 
					 | 
				
			||||||
#define	EP_DONTUSE		13	/* nonzero */
 | 
					#define	EP_DONTUSE		13	/* nonzero */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define USE_RDK_LEDS		/* GPIO pins control three LEDs */
 | 
					#define USE_RDK_LEDS		/* GPIO pins control three LEDs */
 | 
				
			||||||
| 
						 | 
					@ -406,7 +405,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
 | 
				
			||||||
	if (!req)
 | 
						if (!req)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req->req.dma = DMA_ADDR_INVALID;
 | 
					 | 
				
			||||||
	INIT_LIST_HEAD (&req->queue);
 | 
						INIT_LIST_HEAD (&req->queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* this dma descriptor may be swapped with the previous dummy */
 | 
						/* this dma descriptor may be swapped with the previous dummy */
 | 
				
			||||||
| 
						 | 
					@ -420,7 +418,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
 | 
				
			||||||
			return NULL;
 | 
								return NULL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		td->dmacount = 0;	/* not VALID */
 | 
							td->dmacount = 0;	/* not VALID */
 | 
				
			||||||
		td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
 | 
					 | 
				
			||||||
		td->dmadesc = td->dmaaddr;
 | 
							td->dmadesc = td->dmaaddr;
 | 
				
			||||||
		req->td = td;
 | 
							req->td = td;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1896,7 +1893,6 @@ static int net2280_start(struct usb_gadget *_gadget,
 | 
				
			||||||
	dev->softconnect = 1;
 | 
						dev->softconnect = 1;
 | 
				
			||||||
	driver->driver.bus = NULL;
 | 
						driver->driver.bus = NULL;
 | 
				
			||||||
	dev->driver = driver;
 | 
						dev->driver = driver;
 | 
				
			||||||
	dev->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = device_create_file (&dev->pdev->dev, &dev_attr_function);
 | 
						retval = device_create_file (&dev->pdev->dev, &dev_attr_function);
 | 
				
			||||||
	if (retval) goto err_unbind;
 | 
						if (retval) goto err_unbind;
 | 
				
			||||||
| 
						 | 
					@ -1924,7 +1920,6 @@ static int net2280_start(struct usb_gadget *_gadget,
 | 
				
			||||||
err_func:
 | 
					err_func:
 | 
				
			||||||
	device_remove_file (&dev->pdev->dev, &dev_attr_function);
 | 
						device_remove_file (&dev->pdev->dev, &dev_attr_function);
 | 
				
			||||||
err_unbind:
 | 
					err_unbind:
 | 
				
			||||||
	dev->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	dev->driver = NULL;
 | 
						dev->driver = NULL;
 | 
				
			||||||
	return retval;
 | 
						return retval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1967,7 +1962,6 @@ static int net2280_stop(struct usb_gadget *_gadget,
 | 
				
			||||||
	stop_activity (dev, driver);
 | 
						stop_activity (dev, driver);
 | 
				
			||||||
	spin_unlock_irqrestore (&dev->lock, flags);
 | 
						spin_unlock_irqrestore (&dev->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	dev->driver = NULL;
 | 
						dev->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	net2280_led_active (dev, 0);
 | 
						net2280_led_active (dev, 0);
 | 
				
			||||||
| 
						 | 
					@ -2072,7 +2066,7 @@ static void handle_ep_small (struct net2280_ep *ep)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* manual DMA queue advance after short OUT */
 | 
						/* manual DMA queue advance after short OUT */
 | 
				
			||||||
	if (likely (ep->dma != 0)) {
 | 
						if (likely (ep->dma)) {
 | 
				
			||||||
		if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
 | 
							if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
 | 
				
			||||||
			u32	count;
 | 
								u32	count;
 | 
				
			||||||
			int	stopped = ep->stopped;
 | 
								int	stopped = ep->stopped;
 | 
				
			||||||
| 
						 | 
					@ -2330,7 +2324,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
 | 
				
			||||||
			/* hw handles device and interface status */
 | 
								/* hw handles device and interface status */
 | 
				
			||||||
			if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
 | 
								if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
 | 
				
			||||||
				goto delegate;
 | 
									goto delegate;
 | 
				
			||||||
			if ((e = get_ep_by_addr (dev, w_index)) == 0
 | 
								if ((e = get_ep_by_addr (dev, w_index)) == NULL
 | 
				
			||||||
					|| w_length > 2)
 | 
										|| w_length > 2)
 | 
				
			||||||
				goto do_stall;
 | 
									goto do_stall;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2358,7 +2352,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
 | 
				
			||||||
			if (w_value != USB_ENDPOINT_HALT
 | 
								if (w_value != USB_ENDPOINT_HALT
 | 
				
			||||||
					|| w_length != 0)
 | 
										|| w_length != 0)
 | 
				
			||||||
				goto do_stall;
 | 
									goto do_stall;
 | 
				
			||||||
			if ((e = get_ep_by_addr (dev, w_index)) == 0)
 | 
								if ((e = get_ep_by_addr (dev, w_index)) == NULL)
 | 
				
			||||||
				goto do_stall;
 | 
									goto do_stall;
 | 
				
			||||||
			if (e->wedged) {
 | 
								if (e->wedged) {
 | 
				
			||||||
				VDEBUG(dev, "%s wedged, halt not cleared\n",
 | 
									VDEBUG(dev, "%s wedged, halt not cleared\n",
 | 
				
			||||||
| 
						 | 
					@ -2380,7 +2374,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
 | 
				
			||||||
			if (w_value != USB_ENDPOINT_HALT
 | 
								if (w_value != USB_ENDPOINT_HALT
 | 
				
			||||||
					|| w_length != 0)
 | 
										|| w_length != 0)
 | 
				
			||||||
				goto do_stall;
 | 
									goto do_stall;
 | 
				
			||||||
			if ((e = get_ep_by_addr (dev, w_index)) == 0)
 | 
								if ((e = get_ep_by_addr (dev, w_index)) == NULL)
 | 
				
			||||||
				goto do_stall;
 | 
									goto do_stall;
 | 
				
			||||||
			if (e->ep.name == ep0name)
 | 
								if (e->ep.name == ep0name)
 | 
				
			||||||
				goto do_stall;
 | 
									goto do_stall;
 | 
				
			||||||
| 
						 | 
					@ -2685,7 +2679,6 @@ static void net2280_remove (struct pci_dev *pdev)
 | 
				
			||||||
				pci_resource_len (pdev, 0));
 | 
									pci_resource_len (pdev, 0));
 | 
				
			||||||
	if (dev->enabled)
 | 
						if (dev->enabled)
 | 
				
			||||||
		pci_disable_device (pdev);
 | 
							pci_disable_device (pdev);
 | 
				
			||||||
	device_unregister (&dev->gadget.dev);
 | 
					 | 
				
			||||||
	device_remove_file (&pdev->dev, &dev_attr_registers);
 | 
						device_remove_file (&pdev->dev, &dev_attr_registers);
 | 
				
			||||||
	pci_set_drvdata (pdev, NULL);
 | 
						pci_set_drvdata (pdev, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2717,10 +2710,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 | 
				
			||||||
	dev->gadget.max_speed = USB_SPEED_HIGH;
 | 
						dev->gadget.max_speed = USB_SPEED_HIGH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* the "gadget" abstracts/virtualizes the controller */
 | 
						/* the "gadget" abstracts/virtualizes the controller */
 | 
				
			||||||
	dev_set_name(&dev->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
	dev->gadget.dev.parent = &pdev->dev;
 | 
					 | 
				
			||||||
	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 | 
					 | 
				
			||||||
	dev->gadget.dev.release = gadget_release;
 | 
					 | 
				
			||||||
	dev->gadget.name = driver_name;
 | 
						dev->gadget.name = driver_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* now all the pci goodies ... */
 | 
						/* now all the pci goodies ... */
 | 
				
			||||||
| 
						 | 
					@ -2802,7 +2791,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 | 
				
			||||||
			goto done;
 | 
								goto done;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		td->dmacount = 0;	/* not VALID */
 | 
							td->dmacount = 0;	/* not VALID */
 | 
				
			||||||
		td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
 | 
					 | 
				
			||||||
		td->dmadesc = td->dmaaddr;
 | 
							td->dmadesc = td->dmaaddr;
 | 
				
			||||||
		dev->ep [i].dummy = td;
 | 
							dev->ep [i].dummy = td;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -2829,12 +2817,11 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 | 
				
			||||||
			use_dma
 | 
								use_dma
 | 
				
			||||||
				? (use_dma_chaining ? "chaining" : "enabled")
 | 
									? (use_dma_chaining ? "chaining" : "enabled")
 | 
				
			||||||
				: "disabled");
 | 
									: "disabled");
 | 
				
			||||||
	retval = device_register (&dev->gadget.dev);
 | 
					 | 
				
			||||||
	if (retval) goto done;
 | 
					 | 
				
			||||||
	retval = device_create_file (&pdev->dev, &dev_attr_registers);
 | 
						retval = device_create_file (&pdev->dev, &dev_attr_registers);
 | 
				
			||||||
	if (retval) goto done;
 | 
						if (retval) goto done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
 | 
						retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
 | 
				
			||||||
 | 
								gadget_release);
 | 
				
			||||||
	if (retval)
 | 
						if (retval)
 | 
				
			||||||
		goto done;
 | 
							goto done;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,11 +37,9 @@
 | 
				
			||||||
 * the runtime footprint, and giving us at least some parts of what
 | 
					 * the runtime footprint, and giving us at least some parts of what
 | 
				
			||||||
 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
 | 
					 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define USB_FACM_INCLUDED
 | 
					#define USBF_OBEX_INCLUDED
 | 
				
			||||||
#include "f_acm.c"
 | 
					 | 
				
			||||||
#include "f_ecm.c"
 | 
					#include "f_ecm.c"
 | 
				
			||||||
#include "f_obex.c"
 | 
					#include "f_obex.c"
 | 
				
			||||||
#include "f_serial.c"
 | 
					 | 
				
			||||||
#include "f_phonet.c"
 | 
					#include "f_phonet.c"
 | 
				
			||||||
#include "u_ether.c"
 | 
					#include "u_ether.c"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,45 +96,19 @@ MODULE_AUTHOR("Felipe Balbi");
 | 
				
			||||||
MODULE_LICENSE("GPL");
 | 
					MODULE_LICENSE("GPL");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*-------------------------------------------------------------------------*/
 | 
					/*-------------------------------------------------------------------------*/
 | 
				
			||||||
 | 
					static struct usb_function *f_acm_cfg1;
 | 
				
			||||||
 | 
					static struct usb_function *f_acm_cfg2;
 | 
				
			||||||
static u8 hostaddr[ETH_ALEN];
 | 
					static u8 hostaddr[ETH_ALEN];
 | 
				
			||||||
 | 
					static struct eth_dev *the_dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
	TTY_PORT_OBEX0,
 | 
						TTY_PORT_OBEX0,
 | 
				
			||||||
	TTY_PORT_OBEX1,
 | 
						TTY_PORT_OBEX1,
 | 
				
			||||||
	TTY_PORT_ACM,
 | 
					 | 
				
			||||||
	TTY_PORTS_MAX,
 | 
						TTY_PORTS_MAX,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static unsigned char tty_lines[TTY_PORTS_MAX];
 | 
					static unsigned char tty_lines[TTY_PORTS_MAX];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init nokia_bind_config(struct usb_configuration *c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int status = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	status = phonet_bind_config(c);
 | 
					 | 
				
			||||||
	if (status)
 | 
					 | 
				
			||||||
		printk(KERN_DEBUG "could not bind phonet config\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX0]);
 | 
					 | 
				
			||||||
	if (status)
 | 
					 | 
				
			||||||
		printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX1]);
 | 
					 | 
				
			||||||
	if (status)
 | 
					 | 
				
			||||||
		printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	status = acm_bind_config(c, tty_lines[TTY_PORT_ACM]);
 | 
					 | 
				
			||||||
	if (status)
 | 
					 | 
				
			||||||
		printk(KERN_DEBUG "could not bind acm config\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	status = ecm_bind_config(c, hostaddr);
 | 
					 | 
				
			||||||
	if (status)
 | 
					 | 
				
			||||||
		printk(KERN_DEBUG "could not bind ecm config\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return status;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct usb_configuration nokia_config_500ma_driver = {
 | 
					static struct usb_configuration nokia_config_500ma_driver = {
 | 
				
			||||||
	.label		= "Bus Powered",
 | 
						.label		= "Bus Powered",
 | 
				
			||||||
	.bConfigurationValue = 1,
 | 
						.bConfigurationValue = 1,
 | 
				
			||||||
| 
						 | 
					@ -153,6 +125,51 @@ static struct usb_configuration nokia_config_100ma_driver = {
 | 
				
			||||||
	.MaxPower	= 100,
 | 
						.MaxPower	= 100,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct usb_function_instance *fi_acm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __init nokia_bind_config(struct usb_configuration *c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct usb_function *f_acm;
 | 
				
			||||||
 | 
						int status = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status = phonet_bind_config(c);
 | 
				
			||||||
 | 
						if (status)
 | 
				
			||||||
 | 
							printk(KERN_DEBUG "could not bind phonet config\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX0]);
 | 
				
			||||||
 | 
						if (status)
 | 
				
			||||||
 | 
							printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX1]);
 | 
				
			||||||
 | 
						if (status)
 | 
				
			||||||
 | 
							printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f_acm = usb_get_function(fi_acm);
 | 
				
			||||||
 | 
						if (IS_ERR(f_acm))
 | 
				
			||||||
 | 
							return PTR_ERR(f_acm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status = usb_add_function(c, f_acm);
 | 
				
			||||||
 | 
						if (status)
 | 
				
			||||||
 | 
							goto err_conf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status = ecm_bind_config(c, hostaddr, the_dev);
 | 
				
			||||||
 | 
						if (status) {
 | 
				
			||||||
 | 
							pr_debug("could not bind ecm config %d\n", status);
 | 
				
			||||||
 | 
							goto err_ecm;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (c == &nokia_config_500ma_driver)
 | 
				
			||||||
 | 
							f_acm_cfg1 = f_acm;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							f_acm_cfg2 = f_acm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return status;
 | 
				
			||||||
 | 
					err_ecm:
 | 
				
			||||||
 | 
						usb_remove_function(c, f_acm);
 | 
				
			||||||
 | 
					err_conf:
 | 
				
			||||||
 | 
						usb_put_function(f_acm);
 | 
				
			||||||
 | 
						return status;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init nokia_bind(struct usb_composite_dev *cdev)
 | 
					static int __init nokia_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usb_gadget	*gadget = cdev->gadget;
 | 
						struct usb_gadget	*gadget = cdev->gadget;
 | 
				
			||||||
| 
						 | 
					@ -169,9 +186,11 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
			goto err_ether;
 | 
								goto err_ether;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = gether_setup(cdev->gadget, hostaddr);
 | 
						the_dev = gether_setup(cdev->gadget, hostaddr);
 | 
				
			||||||
	if (status < 0)
 | 
						if (IS_ERR(the_dev)) {
 | 
				
			||||||
 | 
							status = PTR_ERR(the_dev);
 | 
				
			||||||
		goto err_ether;
 | 
							goto err_ether;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = usb_string_ids_tab(cdev, strings_dev);
 | 
						status = usb_string_ids_tab(cdev, strings_dev);
 | 
				
			||||||
	if (status < 0)
 | 
						if (status < 0)
 | 
				
			||||||
| 
						 | 
					@ -185,24 +204,32 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
	if (!gadget_supports_altsettings(gadget))
 | 
						if (!gadget_supports_altsettings(gadget))
 | 
				
			||||||
		goto err_usb;
 | 
							goto err_usb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fi_acm = usb_get_function_instance("acm");
 | 
				
			||||||
 | 
						if (IS_ERR(fi_acm))
 | 
				
			||||||
 | 
							goto err_usb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* finally register the configuration */
 | 
						/* finally register the configuration */
 | 
				
			||||||
	status = usb_add_config(cdev, &nokia_config_500ma_driver,
 | 
						status = usb_add_config(cdev, &nokia_config_500ma_driver,
 | 
				
			||||||
			nokia_bind_config);
 | 
								nokia_bind_config);
 | 
				
			||||||
	if (status < 0)
 | 
						if (status < 0)
 | 
				
			||||||
		goto err_usb;
 | 
							goto err_acm_inst;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = usb_add_config(cdev, &nokia_config_100ma_driver,
 | 
						status = usb_add_config(cdev, &nokia_config_100ma_driver,
 | 
				
			||||||
			nokia_bind_config);
 | 
								nokia_bind_config);
 | 
				
			||||||
	if (status < 0)
 | 
						if (status < 0)
 | 
				
			||||||
		goto err_usb;
 | 
							goto err_put_cfg1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	usb_composite_overwrite_options(cdev, &coverwrite);
 | 
						usb_composite_overwrite_options(cdev, &coverwrite);
 | 
				
			||||||
	dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME);
 | 
						dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_put_cfg1:
 | 
				
			||||||
 | 
						usb_put_function(f_acm_cfg1);
 | 
				
			||||||
 | 
					err_acm_inst:
 | 
				
			||||||
 | 
						usb_put_function_instance(fi_acm);
 | 
				
			||||||
err_usb:
 | 
					err_usb:
 | 
				
			||||||
	gether_cleanup();
 | 
						gether_cleanup(the_dev);
 | 
				
			||||||
err_ether:
 | 
					err_ether:
 | 
				
			||||||
	cur_line--;
 | 
						cur_line--;
 | 
				
			||||||
	while (cur_line >= 0)
 | 
						while (cur_line >= 0)
 | 
				
			||||||
| 
						 | 
					@ -217,12 +244,15 @@ static int __exit nokia_unbind(struct usb_composite_dev *cdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						usb_put_function(f_acm_cfg1);
 | 
				
			||||||
 | 
						usb_put_function(f_acm_cfg2);
 | 
				
			||||||
 | 
						usb_put_function_instance(fi_acm);
 | 
				
			||||||
	gphonet_cleanup();
 | 
						gphonet_cleanup();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < TTY_PORTS_MAX; i++)
 | 
						for (i = 0; i < TTY_PORTS_MAX; i++)
 | 
				
			||||||
		gserial_free_line(tty_lines[i]);
 | 
							gserial_free_line(tty_lines[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gether_cleanup();
 | 
						gether_cleanup(the_dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -247,4 +277,3 @@ static void __exit nokia_cleanup(void)
 | 
				
			||||||
	usb_composite_unregister(&nokia_driver);
 | 
						usb_composite_unregister(&nokia_driver);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
module_exit(nokia_cleanup);
 | 
					module_exit(nokia_cleanup);
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2067,7 +2067,6 @@ static int omap_udc_start(struct usb_gadget *g,
 | 
				
			||||||
	/* hook up the driver */
 | 
						/* hook up the driver */
 | 
				
			||||||
	driver->driver.bus = NULL;
 | 
						driver->driver.bus = NULL;
 | 
				
			||||||
	udc->driver = driver;
 | 
						udc->driver = driver;
 | 
				
			||||||
	udc->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
	spin_unlock_irqrestore(&udc->lock, flags);
 | 
						spin_unlock_irqrestore(&udc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (udc->dc_clk != NULL)
 | 
						if (udc->dc_clk != NULL)
 | 
				
			||||||
| 
						 | 
					@ -2083,7 +2082,6 @@ static int omap_udc_start(struct usb_gadget *g,
 | 
				
			||||||
			ERR("can't bind to transceiver\n");
 | 
								ERR("can't bind to transceiver\n");
 | 
				
			||||||
			if (driver->unbind) {
 | 
								if (driver->unbind) {
 | 
				
			||||||
				driver->unbind(&udc->gadget);
 | 
									driver->unbind(&udc->gadget);
 | 
				
			||||||
				udc->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
				udc->driver = NULL;
 | 
									udc->driver = NULL;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			goto done;
 | 
								goto done;
 | 
				
			||||||
| 
						 | 
					@ -2129,7 +2127,6 @@ static int omap_udc_stop(struct usb_gadget *g,
 | 
				
			||||||
	udc_quiesce(udc);
 | 
						udc_quiesce(udc);
 | 
				
			||||||
	spin_unlock_irqrestore(&udc->lock, flags);
 | 
						spin_unlock_irqrestore(&udc->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	udc->driver = NULL;
 | 
						udc->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (udc->dc_clk != NULL)
 | 
						if (udc->dc_clk != NULL)
 | 
				
			||||||
| 
						 | 
					@ -2631,14 +2628,6 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
 | 
				
			||||||
	udc->gadget.speed = USB_SPEED_UNKNOWN;
 | 
						udc->gadget.speed = USB_SPEED_UNKNOWN;
 | 
				
			||||||
	udc->gadget.max_speed = USB_SPEED_FULL;
 | 
						udc->gadget.max_speed = USB_SPEED_FULL;
 | 
				
			||||||
	udc->gadget.name = driver_name;
 | 
						udc->gadget.name = driver_name;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	device_initialize(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	dev_set_name(&udc->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
	udc->gadget.dev.release = omap_udc_release;
 | 
					 | 
				
			||||||
	udc->gadget.dev.parent = &odev->dev;
 | 
					 | 
				
			||||||
	if (use_dma)
 | 
					 | 
				
			||||||
		udc->gadget.dev.dma_mask = odev->dev.dma_mask;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	udc->transceiver = xceiv;
 | 
						udc->transceiver = xceiv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* ep0 is special; put it right after the SETUP buffer */
 | 
						/* ep0 is special; put it right after the SETUP buffer */
 | 
				
			||||||
| 
						 | 
					@ -2912,14 +2901,13 @@ bad_on_1710:
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	create_proc_file();
 | 
						create_proc_file();
 | 
				
			||||||
	status = device_add(&udc->gadget.dev);
 | 
						status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
 | 
				
			||||||
 | 
								omap_udc_release);
 | 
				
			||||||
	if (status)
 | 
						if (status)
 | 
				
			||||||
		goto cleanup4;
 | 
							goto cleanup4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
 | 
						return 0;
 | 
				
			||||||
	if (!status)
 | 
					
 | 
				
			||||||
		return status;
 | 
					 | 
				
			||||||
	/* If fail, fall through */
 | 
					 | 
				
			||||||
cleanup4:
 | 
					cleanup4:
 | 
				
			||||||
	remove_proc_file();
 | 
						remove_proc_file();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2990,7 +2978,6 @@ static int omap_udc_remove(struct platform_device *pdev)
 | 
				
			||||||
	release_mem_region(pdev->resource[0].start,
 | 
						release_mem_region(pdev->resource[0].start,
 | 
				
			||||||
			pdev->resource[0].end - pdev->resource[0].start + 1);
 | 
								pdev->resource[0].end - pdev->resource[0].start + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	wait_for_completion(&done);
 | 
						wait_for_completion(&done);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -358,7 +358,6 @@ struct pch_udc_dev {
 | 
				
			||||||
			prot_stall:1,
 | 
								prot_stall:1,
 | 
				
			||||||
			irq_registered:1,
 | 
								irq_registered:1,
 | 
				
			||||||
			mem_region:1,
 | 
								mem_region:1,
 | 
				
			||||||
			registered:1,
 | 
					 | 
				
			||||||
			suspended:1,
 | 
								suspended:1,
 | 
				
			||||||
			connected:1,
 | 
								connected:1,
 | 
				
			||||||
			vbus_session:1,
 | 
								vbus_session:1,
 | 
				
			||||||
| 
						 | 
					@ -1441,6 +1440,8 @@ static void pch_vbus_gpio_free(struct pch_udc_dev *dev)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
 | 
					static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
 | 
				
			||||||
								 int status)
 | 
													 int status)
 | 
				
			||||||
 | 
						__releases(&dev->lock)
 | 
				
			||||||
 | 
						__acquires(&dev->lock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pch_udc_dev	*dev;
 | 
						struct pch_udc_dev	*dev;
 | 
				
			||||||
	unsigned halted = ep->halted;
 | 
						unsigned halted = ep->halted;
 | 
				
			||||||
| 
						 | 
					@ -2382,6 +2383,8 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev)
 | 
				
			||||||
 * @dev:	Reference to the device structure
 | 
					 * @dev:	Reference to the device structure
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
 | 
					static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
 | 
				
			||||||
 | 
						__releases(&dev->lock)
 | 
				
			||||||
 | 
						__acquires(&dev->lock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32	stat;
 | 
						u32	stat;
 | 
				
			||||||
	int setup_supported;
 | 
						int setup_supported;
 | 
				
			||||||
| 
						 | 
					@ -2989,7 +2992,6 @@ static int pch_udc_start(struct usb_gadget *g,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	driver->driver.bus = NULL;
 | 
						driver->driver.bus = NULL;
 | 
				
			||||||
	dev->driver = driver;
 | 
						dev->driver = driver;
 | 
				
			||||||
	dev->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* get ready for ep0 traffic */
 | 
						/* get ready for ep0 traffic */
 | 
				
			||||||
	pch_udc_setup_ep0(dev);
 | 
						pch_udc_setup_ep0(dev);
 | 
				
			||||||
| 
						 | 
					@ -3010,7 +3012,6 @@ static int pch_udc_stop(struct usb_gadget *g,
 | 
				
			||||||
	pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
 | 
						pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Assures that there are no pending requests with this driver */
 | 
						/* Assures that there are no pending requests with this driver */
 | 
				
			||||||
	dev->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	dev->driver = NULL;
 | 
						dev->driver = NULL;
 | 
				
			||||||
	dev->connected = 0;
 | 
						dev->connected = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3078,8 +3079,6 @@ static void pch_udc_remove(struct pci_dev *pdev)
 | 
				
			||||||
				   pci_resource_len(pdev, PCH_UDC_PCI_BAR));
 | 
									   pci_resource_len(pdev, PCH_UDC_PCI_BAR));
 | 
				
			||||||
	if (dev->active)
 | 
						if (dev->active)
 | 
				
			||||||
		pci_disable_device(pdev);
 | 
							pci_disable_device(pdev);
 | 
				
			||||||
	if (dev->registered)
 | 
					 | 
				
			||||||
		device_unregister(&dev->gadget.dev);
 | 
					 | 
				
			||||||
	kfree(dev);
 | 
						kfree(dev);
 | 
				
			||||||
	pci_set_drvdata(pdev, NULL);
 | 
						pci_set_drvdata(pdev, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -3196,21 +3195,13 @@ static int pch_udc_probe(struct pci_dev *pdev,
 | 
				
			||||||
	if (retval)
 | 
						if (retval)
 | 
				
			||||||
		goto finished;
 | 
							goto finished;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_set_name(&dev->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
	dev->gadget.dev.parent = &pdev->dev;
 | 
					 | 
				
			||||||
	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 | 
					 | 
				
			||||||
	dev->gadget.dev.release = gadget_release;
 | 
					 | 
				
			||||||
	dev->gadget.name = KBUILD_MODNAME;
 | 
						dev->gadget.name = KBUILD_MODNAME;
 | 
				
			||||||
	dev->gadget.max_speed = USB_SPEED_HIGH;
 | 
						dev->gadget.max_speed = USB_SPEED_HIGH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = device_register(&dev->gadget.dev);
 | 
					 | 
				
			||||||
	if (retval)
 | 
					 | 
				
			||||||
		goto finished;
 | 
					 | 
				
			||||||
	dev->registered = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Put the device in disconnected state till a driver is bound */
 | 
						/* Put the device in disconnected state till a driver is bound */
 | 
				
			||||||
	pch_udc_set_disconnect(dev);
 | 
						pch_udc_set_disconnect(dev);
 | 
				
			||||||
	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
 | 
						retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
 | 
				
			||||||
 | 
								gadget_release);
 | 
				
			||||||
	if (retval)
 | 
						if (retval)
 | 
				
			||||||
		goto finished;
 | 
							goto finished;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1263,7 +1263,6 @@ static int pxa25x_udc_start(struct usb_gadget *g,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* first hook up the driver ... */
 | 
						/* first hook up the driver ... */
 | 
				
			||||||
	dev->driver = driver;
 | 
						dev->driver = driver;
 | 
				
			||||||
	dev->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
	dev->pullup = 1;
 | 
						dev->pullup = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* ... then enable host detection and ep0; and we're ready
 | 
						/* ... then enable host detection and ep0; and we're ready
 | 
				
			||||||
| 
						 | 
					@ -1325,7 +1324,6 @@ static int pxa25x_udc_stop(struct usb_gadget*g,
 | 
				
			||||||
	if (!IS_ERR_OR_NULL(dev->transceiver))
 | 
						if (!IS_ERR_OR_NULL(dev->transceiver))
 | 
				
			||||||
		(void) otg_set_peripheral(dev->transceiver->otg, NULL);
 | 
							(void) otg_set_peripheral(dev->transceiver->otg, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	dev->driver = NULL;
 | 
						dev->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dump_state(dev);
 | 
						dump_state(dev);
 | 
				
			||||||
| 
						 | 
					@ -2138,17 +2136,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
	dev->timer.function = udc_watchdog;
 | 
						dev->timer.function = udc_watchdog;
 | 
				
			||||||
	dev->timer.data = (unsigned long) dev;
 | 
						dev->timer.data = (unsigned long) dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_initialize(&dev->gadget.dev);
 | 
					 | 
				
			||||||
	dev->gadget.dev.parent = &pdev->dev;
 | 
					 | 
				
			||||||
	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	retval = device_add(&dev->gadget.dev);
 | 
					 | 
				
			||||||
	if (retval) {
 | 
					 | 
				
			||||||
		dev->driver = NULL;
 | 
					 | 
				
			||||||
		dev->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
		goto err_device_add;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	the_controller = dev;
 | 
						the_controller = dev;
 | 
				
			||||||
	platform_set_drvdata(pdev, dev);
 | 
						platform_set_drvdata(pdev, dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2199,8 +2186,6 @@ lubbock_fail0:
 | 
				
			||||||
	free_irq(irq, dev);
 | 
						free_irq(irq, dev);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 err_irq1:
 | 
					 err_irq1:
 | 
				
			||||||
	device_unregister(&dev->gadget.dev);
 | 
					 | 
				
			||||||
 err_device_add:
 | 
					 | 
				
			||||||
	if (gpio_is_valid(dev->mach->gpio_pullup))
 | 
						if (gpio_is_valid(dev->mach->gpio_pullup))
 | 
				
			||||||
		gpio_free(dev->mach->gpio_pullup);
 | 
							gpio_free(dev->mach->gpio_pullup);
 | 
				
			||||||
 err_gpio_pullup:
 | 
					 err_gpio_pullup:
 | 
				
			||||||
| 
						 | 
					@ -2226,7 +2211,6 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
 | 
				
			||||||
		return -EBUSY;
 | 
							return -EBUSY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	usb_del_gadget_udc(&dev->gadget);
 | 
						usb_del_gadget_udc(&dev->gadget);
 | 
				
			||||||
	device_unregister(&dev->gadget.dev);
 | 
					 | 
				
			||||||
	dev->pullup = 0;
 | 
						dev->pullup = 0;
 | 
				
			||||||
	pullup(dev);
 | 
						pullup(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,14 +24,12 @@
 | 
				
			||||||
#include <linux/gpio.h>
 | 
					#include <linux/gpio.h>
 | 
				
			||||||
#include <linux/slab.h>
 | 
					#include <linux/slab.h>
 | 
				
			||||||
#include <linux/prefetch.h>
 | 
					#include <linux/prefetch.h>
 | 
				
			||||||
 | 
					#include <linux/byteorder/generic.h>
 | 
				
			||||||
#include <asm/byteorder.h>
 | 
					#include <linux/platform_data/pxa2xx_udc.h>
 | 
				
			||||||
#include <mach/hardware.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/usb.h>
 | 
					#include <linux/usb.h>
 | 
				
			||||||
#include <linux/usb/ch9.h>
 | 
					#include <linux/usb/ch9.h>
 | 
				
			||||||
#include <linux/usb/gadget.h>
 | 
					#include <linux/usb/gadget.h>
 | 
				
			||||||
#include <mach/udc.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "pxa27x_udc.h"
 | 
					#include "pxa27x_udc.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -611,7 +609,7 @@ static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Find the physical pxa27x ep, and setup its UDCCR
 | 
					 * Find the physical pxa27x ep, and setup its UDCCR
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static __init void pxa_ep_setup(struct pxa_ep *ep)
 | 
					static void pxa_ep_setup(struct pxa_ep *ep)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32 new_udccr;
 | 
						u32 new_udccr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -633,7 +631,7 @@ static __init void pxa_ep_setup(struct pxa_ep *ep)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Setup all pxa physical endpoints, except ep0
 | 
					 * Setup all pxa physical endpoints, except ep0
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static __init void pxa_eps_setup(struct pxa_udc *dev)
 | 
					static void pxa_eps_setup(struct pxa_udc *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1718,7 +1716,7 @@ static void udc_disable(struct pxa_udc *udc)
 | 
				
			||||||
 * Initializes gadget endpoint list, endpoints locks. No action is taken
 | 
					 * Initializes gadget endpoint list, endpoints locks. No action is taken
 | 
				
			||||||
 * on the hardware.
 | 
					 * on the hardware.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static __init void udc_init_data(struct pxa_udc *dev)
 | 
					static void udc_init_data(struct pxa_udc *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
	struct pxa_ep *ep;
 | 
						struct pxa_ep *ep;
 | 
				
			||||||
| 
						 | 
					@ -1811,7 +1809,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* first hook up the driver ... */
 | 
						/* first hook up the driver ... */
 | 
				
			||||||
	udc->driver = driver;
 | 
						udc->driver = driver;
 | 
				
			||||||
	udc->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
	dplus_pullup(udc, 1);
 | 
						dplus_pullup(udc, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!IS_ERR_OR_NULL(udc->transceiver)) {
 | 
						if (!IS_ERR_OR_NULL(udc->transceiver)) {
 | 
				
			||||||
| 
						 | 
					@ -1829,7 +1826,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fail:
 | 
					fail:
 | 
				
			||||||
	udc->driver = NULL;
 | 
						udc->driver = NULL;
 | 
				
			||||||
	udc->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	return retval;
 | 
						return retval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1871,7 +1867,6 @@ static int pxa27x_udc_stop(struct usb_gadget *g,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->driver = NULL;
 | 
						udc->driver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!IS_ERR_OR_NULL(udc->transceiver))
 | 
						if (!IS_ERR_OR_NULL(udc->transceiver))
 | 
				
			||||||
		return otg_set_peripheral(udc->transceiver->otg, NULL);
 | 
							return otg_set_peripheral(udc->transceiver->otg, NULL);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -2413,7 +2408,7 @@ static struct pxa_udc memory = {
 | 
				
			||||||
 * Perform basic init : allocates udc clock, creates sysfs files, requests
 | 
					 * Perform basic init : allocates udc clock, creates sysfs files, requests
 | 
				
			||||||
 * irq.
 | 
					 * irq.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int __init pxa_udc_probe(struct platform_device *pdev)
 | 
					static int pxa_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct resource *regs;
 | 
						struct resource *regs;
 | 
				
			||||||
	struct pxa_udc *udc = &memory;
 | 
						struct pxa_udc *udc = &memory;
 | 
				
			||||||
| 
						 | 
					@ -2456,9 +2451,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
		goto err_map;
 | 
							goto err_map;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_initialize(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	udc->gadget.dev.parent = &pdev->dev;
 | 
					 | 
				
			||||||
	udc->gadget.dev.dma_mask = NULL;
 | 
					 | 
				
			||||||
	udc->vbus_sensed = 0;
 | 
						udc->vbus_sensed = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	the_controller = udc;
 | 
						the_controller = udc;
 | 
				
			||||||
| 
						 | 
					@ -2475,12 +2467,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
		goto err_irq;
 | 
							goto err_irq;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = device_add(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	if (retval) {
 | 
					 | 
				
			||||||
		dev_err(udc->dev, "device_add error %d\n", retval);
 | 
					 | 
				
			||||||
		goto err_dev_add;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
 | 
						retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
 | 
				
			||||||
	if (retval)
 | 
						if (retval)
 | 
				
			||||||
		goto err_add_udc;
 | 
							goto err_add_udc;
 | 
				
			||||||
| 
						 | 
					@ -2490,8 +2476,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_add_udc:
 | 
					err_add_udc:
 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
err_dev_add:
 | 
					 | 
				
			||||||
	free_irq(udc->irq, udc);
 | 
						free_irq(udc->irq, udc);
 | 
				
			||||||
err_irq:
 | 
					err_irq:
 | 
				
			||||||
	iounmap(udc->regs);
 | 
						iounmap(udc->regs);
 | 
				
			||||||
| 
						 | 
					@ -2506,13 +2490,12 @@ err_clk:
 | 
				
			||||||
 * pxa_udc_remove - removes the udc device driver
 | 
					 * pxa_udc_remove - removes the udc device driver
 | 
				
			||||||
 * @_dev: platform device
 | 
					 * @_dev: platform device
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int __exit pxa_udc_remove(struct platform_device *_dev)
 | 
					static int pxa_udc_remove(struct platform_device *_dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pxa_udc *udc = platform_get_drvdata(_dev);
 | 
						struct pxa_udc *udc = platform_get_drvdata(_dev);
 | 
				
			||||||
	int gpio = udc->mach->gpio_pullup;
 | 
						int gpio = udc->mach->gpio_pullup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	usb_del_gadget_udc(&udc->gadget);
 | 
						usb_del_gadget_udc(&udc->gadget);
 | 
				
			||||||
	device_del(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	usb_gadget_unregister_driver(udc->driver);
 | 
						usb_gadget_unregister_driver(udc->driver);
 | 
				
			||||||
	free_irq(udc->irq, udc);
 | 
						free_irq(udc->irq, udc);
 | 
				
			||||||
	pxa_cleanup_debugfs(udc);
 | 
						pxa_cleanup_debugfs(udc);
 | 
				
			||||||
| 
						 | 
					@ -2625,7 +2608,8 @@ static struct platform_driver udc_driver = {
 | 
				
			||||||
		.name	= "pxa27x-udc",
 | 
							.name	= "pxa27x-udc",
 | 
				
			||||||
		.owner	= THIS_MODULE,
 | 
							.owner	= THIS_MODULE,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	.remove		= __exit_p(pxa_udc_remove),
 | 
						.probe		= pxa_udc_probe,
 | 
				
			||||||
 | 
						.remove		= pxa_udc_remove,
 | 
				
			||||||
	.shutdown	= pxa_udc_shutdown,
 | 
						.shutdown	= pxa_udc_shutdown,
 | 
				
			||||||
#ifdef CONFIG_PM
 | 
					#ifdef CONFIG_PM
 | 
				
			||||||
	.suspend	= pxa_udc_suspend,
 | 
						.suspend	= pxa_udc_suspend,
 | 
				
			||||||
| 
						 | 
					@ -2633,22 +2617,7 @@ static struct platform_driver udc_driver = {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init udc_init(void)
 | 
					module_platform_driver(udc_driver);
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!cpu_is_pxa27x() && !cpu_is_pxa3xx())
 | 
					 | 
				
			||||||
		return -ENODEV;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
 | 
					 | 
				
			||||||
	return platform_driver_probe(&udc_driver, pxa_udc_probe);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
module_init(udc_init);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void __exit udc_exit(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	platform_driver_unregister(&udc_driver);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
module_exit(udc_exit);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
MODULE_DESCRIPTION(DRIVER_DESC);
 | 
					MODULE_DESCRIPTION(DRIVER_DESC);
 | 
				
			||||||
MODULE_AUTHOR("Robert Jarzmik");
 | 
					MODULE_AUTHOR("Robert Jarzmik");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1837,7 +1837,6 @@ static int __exit r8a66597_remove(struct platform_device *pdev)
 | 
				
			||||||
		clk_put(r8a66597->clk);
 | 
							clk_put(r8a66597->clk);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_unregister(&r8a66597->gadget.dev);
 | 
					 | 
				
			||||||
	kfree(r8a66597);
 | 
						kfree(r8a66597);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1915,17 +1914,8 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 | 
				
			||||||
	r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 | 
						r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r8a66597->gadget.ops = &r8a66597_gadget_ops;
 | 
						r8a66597->gadget.ops = &r8a66597_gadget_ops;
 | 
				
			||||||
	dev_set_name(&r8a66597->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
	r8a66597->gadget.max_speed = USB_SPEED_HIGH;
 | 
						r8a66597->gadget.max_speed = USB_SPEED_HIGH;
 | 
				
			||||||
	r8a66597->gadget.dev.parent = &pdev->dev;
 | 
					 | 
				
			||||||
	r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask;
 | 
					 | 
				
			||||||
	r8a66597->gadget.dev.release = pdev->dev.release;
 | 
					 | 
				
			||||||
	r8a66597->gadget.name = udc_name;
 | 
						r8a66597->gadget.name = udc_name;
 | 
				
			||||||
	ret = device_register(&r8a66597->gadget.dev);
 | 
					 | 
				
			||||||
	if (ret < 0) {
 | 
					 | 
				
			||||||
		dev_err(&pdev->dev, "device_register failed\n");
 | 
					 | 
				
			||||||
		goto clean_up;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_timer(&r8a66597->timer);
 | 
						init_timer(&r8a66597->timer);
 | 
				
			||||||
	r8a66597->timer.function = r8a66597_timer;
 | 
						r8a66597->timer.function = r8a66597_timer;
 | 
				
			||||||
| 
						 | 
					@ -1939,7 +1929,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 | 
				
			||||||
			dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
 | 
								dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
 | 
				
			||||||
				clk_name);
 | 
									clk_name);
 | 
				
			||||||
			ret = PTR_ERR(r8a66597->clk);
 | 
								ret = PTR_ERR(r8a66597->clk);
 | 
				
			||||||
			goto clean_up_dev;
 | 
								goto clean_up;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		clk_enable(r8a66597->clk);
 | 
							clk_enable(r8a66597->clk);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -2007,8 +1997,6 @@ clean_up2:
 | 
				
			||||||
		clk_disable(r8a66597->clk);
 | 
							clk_disable(r8a66597->clk);
 | 
				
			||||||
		clk_put(r8a66597->clk);
 | 
							clk_put(r8a66597->clk);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
clean_up_dev:
 | 
					 | 
				
			||||||
	device_unregister(&r8a66597->gadget.dev);
 | 
					 | 
				
			||||||
clean_up:
 | 
					clean_up:
 | 
				
			||||||
	if (r8a66597) {
 | 
						if (r8a66597) {
 | 
				
			||||||
		if (r8a66597->sudmac_reg)
 | 
							if (r8a66597->sudmac_reg)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,8 +39,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "s3c-hsotg.h"
 | 
					#include "s3c-hsotg.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DMA_ADDR_INVALID (~((dma_addr_t)0))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char * const s3c_hsotg_supply_names[] = {
 | 
					static const char * const s3c_hsotg_supply_names[] = {
 | 
				
			||||||
	"vusb_d",		/* digital USB supply, 1.2V */
 | 
						"vusb_d",		/* digital USB supply, 1.2V */
 | 
				
			||||||
	"vusb_a",		/* analog USB supply, 1.1V */
 | 
						"vusb_a",		/* analog USB supply, 1.1V */
 | 
				
			||||||
| 
						 | 
					@ -405,7 +403,6 @@ static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	INIT_LIST_HEAD(&req->queue);
 | 
						INIT_LIST_HEAD(&req->queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req->req.dma = DMA_ADDR_INVALID;
 | 
					 | 
				
			||||||
	return &req->req;
 | 
						return &req->req;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -435,24 +432,12 @@ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg,
 | 
				
			||||||
				struct s3c_hsotg_req *hs_req)
 | 
									struct s3c_hsotg_req *hs_req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usb_request *req = &hs_req->req;
 | 
						struct usb_request *req = &hs_req->req;
 | 
				
			||||||
	enum dma_data_direction dir;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* ignore this if we're not moving any data */
 | 
						/* ignore this if we're not moving any data */
 | 
				
			||||||
	if (hs_req->req.length == 0)
 | 
						if (hs_req->req.length == 0)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (hs_req->mapped) {
 | 
						usb_gadget_unmap_request(&hsotg->gadget, hs_req, hs_ep->dir_in);
 | 
				
			||||||
		/* we mapped this, so unmap and remove the dma */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		dma_unmap_single(hsotg->dev, req->dma, req->length, dir);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		req->dma = DMA_ADDR_INVALID;
 | 
					 | 
				
			||||||
		hs_req->mapped = 0;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -852,37 +837,16 @@ static int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg,
 | 
				
			||||||
			     struct s3c_hsotg_ep *hs_ep,
 | 
								     struct s3c_hsotg_ep *hs_ep,
 | 
				
			||||||
			     struct usb_request *req)
 | 
								     struct usb_request *req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	enum dma_data_direction dir;
 | 
					 | 
				
			||||||
	struct s3c_hsotg_req *hs_req = our_req(req);
 | 
						struct s3c_hsotg_req *hs_req = our_req(req);
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
	dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* if the length is zero, ignore the DMA data */
 | 
						/* if the length is zero, ignore the DMA data */
 | 
				
			||||||
	if (hs_req->req.length == 0)
 | 
						if (hs_req->req.length == 0)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (req->dma == DMA_ADDR_INVALID) {
 | 
						ret = usb_gadget_map_request(&hsotg->gadget, req, hs_ep->dir_in);
 | 
				
			||||||
		dma_addr_t dma;
 | 
						if (ret)
 | 
				
			||||||
 | 
							goto dma_error;
 | 
				
			||||||
		dma = dma_map_single(hsotg->dev, req->buf, req->length, dir);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (unlikely(dma_mapping_error(hsotg->dev, dma)))
 | 
					 | 
				
			||||||
			goto dma_error;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (dma & 3) {
 | 
					 | 
				
			||||||
			dev_err(hsotg->dev, "%s: unaligned dma buffer\n",
 | 
					 | 
				
			||||||
				__func__);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			dma_unmap_single(hsotg->dev, dma, req->length, dir);
 | 
					 | 
				
			||||||
			return -EINVAL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		hs_req->mapped = 1;
 | 
					 | 
				
			||||||
		req->dma = dma;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir);
 | 
					 | 
				
			||||||
		hs_req->mapped = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2961,9 +2925,7 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	driver->driver.bus = NULL;
 | 
						driver->driver.bus = NULL;
 | 
				
			||||||
	hsotg->driver = driver;
 | 
						hsotg->driver = driver;
 | 
				
			||||||
	hsotg->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
	hsotg->gadget.dev.of_node = hsotg->dev->of_node;
 | 
						hsotg->gadget.dev.of_node = hsotg->dev->of_node;
 | 
				
			||||||
	hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask;
 | 
					 | 
				
			||||||
	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 | 
						hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
 | 
						ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
 | 
				
			||||||
| 
						 | 
					@ -2979,7 +2941,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err:
 | 
					err:
 | 
				
			||||||
	hsotg->driver = NULL;
 | 
						hsotg->driver = NULL;
 | 
				
			||||||
	hsotg->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3014,7 +2975,6 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hsotg->driver = NULL;
 | 
						hsotg->driver = NULL;
 | 
				
			||||||
	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 | 
						hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 | 
				
			||||||
	hsotg->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_irqrestore(&hsotg->lock, flags);
 | 
						spin_unlock_irqrestore(&hsotg->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3483,16 +3443,6 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
 | 
				
			||||||
	debugfs_remove(hsotg->debug_root);
 | 
						debugfs_remove(hsotg->debug_root);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * s3c_hsotg_release - release callback for hsotg device
 | 
					 | 
				
			||||||
 * @dev: Device to for which release is called
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Nothing to do as the resource is allocated using devm_ API.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void s3c_hsotg_release(struct device *dev)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * s3c_hsotg_probe - probe function for hsotg driver
 | 
					 * s3c_hsotg_probe - probe function for hsotg driver
 | 
				
			||||||
 * @pdev: The platform information for the driver
 | 
					 * @pdev: The platform information for the driver
 | 
				
			||||||
| 
						 | 
					@ -3517,7 +3467,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 | 
						phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 | 
				
			||||||
	if (IS_ERR_OR_NULL(phy)) {
 | 
						if (IS_ERR(phy)) {
 | 
				
			||||||
		/* Fallback for pdata */
 | 
							/* Fallback for pdata */
 | 
				
			||||||
		plat = pdev->dev.platform_data;
 | 
							plat = pdev->dev.platform_data;
 | 
				
			||||||
		if (!plat) {
 | 
							if (!plat) {
 | 
				
			||||||
| 
						 | 
					@ -3567,18 +3517,10 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
 | 
						dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_initialize(&hsotg->gadget.dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dev_set_name(&hsotg->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	hsotg->gadget.max_speed = USB_SPEED_HIGH;
 | 
						hsotg->gadget.max_speed = USB_SPEED_HIGH;
 | 
				
			||||||
	hsotg->gadget.ops = &s3c_hsotg_gadget_ops;
 | 
						hsotg->gadget.ops = &s3c_hsotg_gadget_ops;
 | 
				
			||||||
	hsotg->gadget.name = dev_name(dev);
 | 
						hsotg->gadget.name = dev_name(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hsotg->gadget.dev.parent = dev;
 | 
					 | 
				
			||||||
	hsotg->gadget.dev.dma_mask = dev->dma_mask;
 | 
					 | 
				
			||||||
	hsotg->gadget.dev.release = s3c_hsotg_release;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* reset the system */
 | 
						/* reset the system */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clk_prepare_enable(hsotg->clk);
 | 
						clk_prepare_enable(hsotg->clk);
 | 
				
			||||||
| 
						 | 
					@ -3658,12 +3600,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s3c_hsotg_phy_disable(hsotg);
 | 
						s3c_hsotg_phy_disable(hsotg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = device_add(&hsotg->gadget.dev);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		put_device(&hsotg->gadget.dev);
 | 
					 | 
				
			||||||
		goto err_ep_mem;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
 | 
						ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto err_ep_mem;
 | 
							goto err_ep_mem;
 | 
				
			||||||
| 
						 | 
					@ -3702,10 +3638,8 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s3c_hsotg_phy_disable(hsotg);
 | 
						s3c_hsotg_phy_disable(hsotg);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	clk_disable_unprepare(hsotg->clk);
 | 
						clk_disable_unprepare(hsotg->clk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_unregister(&hsotg->gadget.dev);
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -283,7 +283,6 @@ static void s3c_hsudc_nuke_ep(struct s3c_hsudc_ep *hsep, int status)
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * s3c_hsudc_stop_activity - Stop activity on all endpoints.
 | 
					 * s3c_hsudc_stop_activity - Stop activity on all endpoints.
 | 
				
			||||||
 * @hsudc: Device controller for which EP activity is to be stopped.
 | 
					 * @hsudc: Device controller for which EP activity is to be stopped.
 | 
				
			||||||
 * @driver: Reference to the gadget driver which is currently active.
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * All the endpoints are stopped and any pending transfer requests if any on
 | 
					 * All the endpoints are stopped and any pending transfer requests if any on
 | 
				
			||||||
 * the endpoint are terminated.
 | 
					 * the endpoint are terminated.
 | 
				
			||||||
| 
						 | 
					@ -1154,7 +1153,6 @@ static int s3c_hsudc_start(struct usb_gadget *gadget,
 | 
				
			||||||
		return -EBUSY;
 | 
							return -EBUSY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hsudc->driver = driver;
 | 
						hsudc->driver = driver;
 | 
				
			||||||
	hsudc->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies),
 | 
						ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies),
 | 
				
			||||||
				    hsudc->supplies);
 | 
									    hsudc->supplies);
 | 
				
			||||||
| 
						 | 
					@ -1190,7 +1188,6 @@ err_otg:
 | 
				
			||||||
	regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
 | 
						regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
 | 
				
			||||||
err_supplies:
 | 
					err_supplies:
 | 
				
			||||||
	hsudc->driver = NULL;
 | 
						hsudc->driver = NULL;
 | 
				
			||||||
	hsudc->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1208,7 +1205,6 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&hsudc->lock, flags);
 | 
						spin_lock_irqsave(&hsudc->lock, flags);
 | 
				
			||||||
	hsudc->driver = NULL;
 | 
						hsudc->driver = NULL;
 | 
				
			||||||
	hsudc->gadget.dev.driver = NULL;
 | 
					 | 
				
			||||||
	hsudc->gadget.speed = USB_SPEED_UNKNOWN;
 | 
						hsudc->gadget.speed = USB_SPEED_UNKNOWN;
 | 
				
			||||||
	s3c_hsudc_uninit_phy();
 | 
						s3c_hsudc_uninit_phy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1303,15 +1299,10 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_init(&hsudc->lock);
 | 
						spin_lock_init(&hsudc->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_set_name(&hsudc->gadget.dev, "gadget");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	hsudc->gadget.max_speed = USB_SPEED_HIGH;
 | 
						hsudc->gadget.max_speed = USB_SPEED_HIGH;
 | 
				
			||||||
	hsudc->gadget.ops = &s3c_hsudc_gadget_ops;
 | 
						hsudc->gadget.ops = &s3c_hsudc_gadget_ops;
 | 
				
			||||||
	hsudc->gadget.name = dev_name(dev);
 | 
						hsudc->gadget.name = dev_name(dev);
 | 
				
			||||||
	hsudc->gadget.dev.parent = dev;
 | 
					 | 
				
			||||||
	hsudc->gadget.dev.dma_mask = dev->dma_mask;
 | 
					 | 
				
			||||||
	hsudc->gadget.ep0 = &hsudc->ep[0].ep;
 | 
						hsudc->gadget.ep0 = &hsudc->ep[0].ep;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	hsudc->gadget.is_otg = 0;
 | 
						hsudc->gadget.is_otg = 0;
 | 
				
			||||||
	hsudc->gadget.is_a_peripheral = 0;
 | 
						hsudc->gadget.is_a_peripheral = 0;
 | 
				
			||||||
	hsudc->gadget.speed = USB_SPEED_UNKNOWN;
 | 
						hsudc->gadget.speed = USB_SPEED_UNKNOWN;
 | 
				
			||||||
| 
						 | 
					@ -1345,12 +1336,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 | 
				
			||||||
	disable_irq(hsudc->irq);
 | 
						disable_irq(hsudc->irq);
 | 
				
			||||||
	local_irq_enable();
 | 
						local_irq_enable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = device_register(&hsudc->gadget.dev);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		put_device(&hsudc->gadget.dev);
 | 
					 | 
				
			||||||
		goto err_add_device;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget);
 | 
						ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto err_add_udc;
 | 
							goto err_add_udc;
 | 
				
			||||||
| 
						 | 
					@ -1359,7 +1344,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
err_add_udc:
 | 
					err_add_udc:
 | 
				
			||||||
	device_unregister(&hsudc->gadget.dev);
 | 
					 | 
				
			||||||
err_add_device:
 | 
					err_add_device:
 | 
				
			||||||
	clk_disable(hsudc->uclk);
 | 
						clk_disable(hsudc->uclk);
 | 
				
			||||||
err_res:
 | 
					err_res:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1674,7 +1674,6 @@ static int s3c2410_udc_start(struct usb_gadget *g,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Hook the driver */
 | 
						/* Hook the driver */
 | 
				
			||||||
	udc->driver = driver;
 | 
						udc->driver = driver;
 | 
				
			||||||
	udc->gadget.dev.driver = &driver->driver;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Enable udc */
 | 
						/* Enable udc */
 | 
				
			||||||
	s3c2410_udc_enable(udc);
 | 
						s3c2410_udc_enable(udc);
 | 
				
			||||||
| 
						 | 
					@ -1824,17 +1823,6 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
 | 
				
			||||||
		goto err_mem;
 | 
							goto err_mem;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_initialize(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	udc->gadget.dev.parent = &pdev->dev;
 | 
					 | 
				
			||||||
	udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Bind the driver */
 | 
					 | 
				
			||||||
	retval = device_add(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	if (retval) {
 | 
					 | 
				
			||||||
		dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval);
 | 
					 | 
				
			||||||
		goto err_device_add;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	the_controller = udc;
 | 
						the_controller = udc;
 | 
				
			||||||
	platform_set_drvdata(pdev, udc);
 | 
						platform_set_drvdata(pdev, udc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1923,8 +1911,6 @@ err_gpio_claim:
 | 
				
			||||||
err_int:
 | 
					err_int:
 | 
				
			||||||
	free_irq(IRQ_USBD, udc);
 | 
						free_irq(IRQ_USBD, udc);
 | 
				
			||||||
err_map:
 | 
					err_map:
 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
err_device_add:
 | 
					 | 
				
			||||||
	iounmap(base_addr);
 | 
						iounmap(base_addr);
 | 
				
			||||||
err_mem:
 | 
					err_mem:
 | 
				
			||||||
	release_mem_region(rsrc_start, rsrc_len);
 | 
						release_mem_region(rsrc_start, rsrc_len);
 | 
				
			||||||
| 
						 | 
					@ -1946,7 +1932,6 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
 | 
				
			||||||
		return -EBUSY;
 | 
							return -EBUSY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	usb_del_gadget_udc(&udc->gadget);
 | 
						usb_del_gadget_udc(&udc->gadget);
 | 
				
			||||||
	device_unregister(&udc->gadget.dev);
 | 
					 | 
				
			||||||
	debugfs_remove(udc->regs_info);
 | 
						debugfs_remove(udc->regs_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (udc_info && !udc_info->udc_command &&
 | 
						if (udc_info && !udc_info->udc_command &&
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/kernel.h>
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
#include <linux/device.h>
 | 
					#include <linux/device.h>
 | 
				
			||||||
 | 
					#include <linux/module.h>
 | 
				
			||||||
#include <linux/tty.h>
 | 
					#include <linux/tty.h>
 | 
				
			||||||
#include <linux/tty_flip.h>
 | 
					#include <linux/tty_flip.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,18 +28,6 @@
 | 
				
			||||||
#define GS_LONG_NAME			"Gadget Serial"
 | 
					#define GS_LONG_NAME			"Gadget Serial"
 | 
				
			||||||
#define GS_VERSION_NAME			GS_LONG_NAME " " GS_VERSION_STR
 | 
					#define GS_VERSION_NAME			GS_LONG_NAME " " GS_VERSION_STR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*-------------------------------------------------------------------------*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Kbuild is not very cooperative with respect to linking separately
 | 
					 | 
				
			||||||
 * compiled library objects into one module.  So for now we won't use
 | 
					 | 
				
			||||||
 * separate compilation ... ensuring init/exit sections work to shrink
 | 
					 | 
				
			||||||
 * the runtime footprint, and giving us at least some parts of what
 | 
					 | 
				
			||||||
 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include "f_obex.c"
 | 
					 | 
				
			||||||
#include "f_serial.c"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*-------------------------------------------------------------------------*/
 | 
					/*-------------------------------------------------------------------------*/
 | 
				
			||||||
USB_GADGET_COMPOSITE_OPTIONS();
 | 
					USB_GADGET_COMPOSITE_OPTIONS();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,27 +115,6 @@ module_param(n_ports, uint, 0);
 | 
				
			||||||
MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
 | 
					MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*-------------------------------------------------------------------------*/
 | 
					/*-------------------------------------------------------------------------*/
 | 
				
			||||||
static unsigned char tty_lines[MAX_U_SERIAL_PORTS];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __init serial_bind_obex_config(struct usb_configuration *c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned i;
 | 
					 | 
				
			||||||
	int status = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < n_ports && status == 0; i++)
 | 
					 | 
				
			||||||
		status = obex_bind_config(c, tty_lines[i]);
 | 
					 | 
				
			||||||
	return status;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __init serial_bind_gser_config(struct usb_configuration *c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned i;
 | 
					 | 
				
			||||||
	int status = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < n_ports && status == 0; i++)
 | 
					 | 
				
			||||||
		status = gser_bind_config(c, tty_lines[i]);
 | 
					 | 
				
			||||||
	return status;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_configuration serial_config_driver = {
 | 
					static struct usb_configuration serial_config_driver = {
 | 
				
			||||||
	/* .label = f(use_acm) */
 | 
						/* .label = f(use_acm) */
 | 
				
			||||||
| 
						 | 
					@ -169,15 +137,12 @@ static int serial_register_ports(struct usb_composite_dev *cdev,
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < n_ports; i++) {
 | 
						for (i = 0; i < n_ports; i++) {
 | 
				
			||||||
		struct f_serial_opts *opts;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fi_serial[i] = usb_get_function_instance(f_name);
 | 
							fi_serial[i] = usb_get_function_instance(f_name);
 | 
				
			||||||
		if (IS_ERR(fi_serial[i])) {
 | 
							if (IS_ERR(fi_serial[i])) {
 | 
				
			||||||
			ret = PTR_ERR(fi_serial[i]);
 | 
								ret = PTR_ERR(fi_serial[i]);
 | 
				
			||||||
			goto fail;
 | 
								goto fail;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		opts = container_of(fi_serial[i], struct f_serial_opts, func_inst);
 | 
					 | 
				
			||||||
		opts->port_num = tty_lines[i];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		f_serial[i] = usb_get_function(fi_serial[i]);
 | 
							f_serial[i] = usb_get_function(fi_serial[i]);
 | 
				
			||||||
		if (IS_ERR(f_serial[i])) {
 | 
							if (IS_ERR(f_serial[i])) {
 | 
				
			||||||
| 
						 | 
					@ -212,13 +177,6 @@ out:
 | 
				
			||||||
static int __init gs_bind(struct usb_composite_dev *cdev)
 | 
					static int __init gs_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int			status;
 | 
						int			status;
 | 
				
			||||||
	int			cur_line;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (cur_line = 0; cur_line < n_ports; cur_line++) {
 | 
					 | 
				
			||||||
		status = gserial_alloc_line(&tty_lines[cur_line]);
 | 
					 | 
				
			||||||
		if (status)
 | 
					 | 
				
			||||||
			goto fail;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Allocate string descriptor numbers ... note that string
 | 
						/* Allocate string descriptor numbers ... note that string
 | 
				
			||||||
	 * contents can be overridden by the composite_dev glue.
 | 
						 * contents can be overridden by the composite_dev glue.
 | 
				
			||||||
| 
						 | 
					@ -243,11 +201,12 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
				"acm");
 | 
									"acm");
 | 
				
			||||||
		usb_ep_autoconfig_reset(cdev->gadget);
 | 
							usb_ep_autoconfig_reset(cdev->gadget);
 | 
				
			||||||
	} else if (use_obex)
 | 
						} else if (use_obex)
 | 
				
			||||||
		status = usb_add_config(cdev, &serial_config_driver,
 | 
							status = serial_register_ports(cdev, &serial_config_driver,
 | 
				
			||||||
				serial_bind_obex_config);
 | 
									"obex");
 | 
				
			||||||
	else
 | 
						else {
 | 
				
			||||||
		status = usb_add_config(cdev, &serial_config_driver,
 | 
							status = serial_register_ports(cdev, &serial_config_driver,
 | 
				
			||||||
				serial_bind_gser_config);
 | 
									"gser");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (status < 0)
 | 
						if (status < 0)
 | 
				
			||||||
		goto fail;
 | 
							goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -257,9 +216,6 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fail:
 | 
					fail:
 | 
				
			||||||
	cur_line--;
 | 
					 | 
				
			||||||
	while (cur_line >= 0)
 | 
					 | 
				
			||||||
		gserial_free_line(tty_lines[cur_line--]);
 | 
					 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -270,7 +226,6 @@ static int gs_unbind(struct usb_composite_dev *cdev)
 | 
				
			||||||
	for (i = 0; i < n_ports; i++) {
 | 
						for (i = 0; i < n_ports; i++) {
 | 
				
			||||||
		usb_put_function(f_serial[i]);
 | 
							usb_put_function(f_serial[i]);
 | 
				
			||||||
		usb_put_function_instance(fi_serial[i]);
 | 
							usb_put_function_instance(fi_serial[i]);
 | 
				
			||||||
		gserial_free_line(tty_lines[i]);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct eth_dev {
 | 
					struct eth_dev {
 | 
				
			||||||
	/* lock is held while accessing port_usb
 | 
						/* lock is held while accessing port_usb
 | 
				
			||||||
	 * or updating its backlink port_usb->ioport
 | 
					 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	spinlock_t		lock;
 | 
						spinlock_t		lock;
 | 
				
			||||||
	struct gether		*port_usb;
 | 
						struct gether		*port_usb;
 | 
				
			||||||
| 
						 | 
					@ -729,8 +728,6 @@ static int get_ether_addr(const char *str, u8 *dev_addr)
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct eth_dev *the_dev;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct net_device_ops eth_netdev_ops = {
 | 
					static const struct net_device_ops eth_netdev_ops = {
 | 
				
			||||||
	.ndo_open		= eth_open,
 | 
						.ndo_open		= eth_open,
 | 
				
			||||||
	.ndo_stop		= eth_stop,
 | 
						.ndo_stop		= eth_stop,
 | 
				
			||||||
| 
						 | 
					@ -758,19 +755,16 @@ static struct device_type gadget_type = {
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns negative errno, or zero on success
 | 
					 * Returns negative errno, or zero on success
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 | 
					struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
		const char *netname)
 | 
							const char *netname)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct eth_dev		*dev;
 | 
						struct eth_dev		*dev;
 | 
				
			||||||
	struct net_device	*net;
 | 
						struct net_device	*net;
 | 
				
			||||||
	int			status;
 | 
						int			status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (the_dev)
 | 
					 | 
				
			||||||
		return -EBUSY;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	net = alloc_etherdev(sizeof *dev);
 | 
						net = alloc_etherdev(sizeof *dev);
 | 
				
			||||||
	if (!net)
 | 
						if (!net)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return ERR_PTR(-ENOMEM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev = netdev_priv(net);
 | 
						dev = netdev_priv(net);
 | 
				
			||||||
	spin_lock_init(&dev->lock);
 | 
						spin_lock_init(&dev->lock);
 | 
				
			||||||
| 
						 | 
					@ -807,12 +801,11 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
	if (status < 0) {
 | 
						if (status < 0) {
 | 
				
			||||||
		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
 | 
							dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
 | 
				
			||||||
		free_netdev(net);
 | 
							free_netdev(net);
 | 
				
			||||||
 | 
							dev = ERR_PTR(status);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		INFO(dev, "MAC %pM\n", net->dev_addr);
 | 
							INFO(dev, "MAC %pM\n", net->dev_addr);
 | 
				
			||||||
		INFO(dev, "HOST MAC %pM\n", dev->host_mac);
 | 
							INFO(dev, "HOST MAC %pM\n", dev->host_mac);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		the_dev = dev;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* two kinds of host-initiated state changes:
 | 
							/* two kinds of host-initiated state changes:
 | 
				
			||||||
		 *  - iff DATA transfer is active, carrier is "on"
 | 
							 *  - iff DATA transfer is active, carrier is "on"
 | 
				
			||||||
		 *  - tx queueing enabled if open *and* carrier is "on"
 | 
							 *  - tx queueing enabled if open *and* carrier is "on"
 | 
				
			||||||
| 
						 | 
					@ -820,7 +813,7 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
		netif_carrier_off(net);
 | 
							netif_carrier_off(net);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return status;
 | 
						return dev;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -829,19 +822,16 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This is called to free all resources allocated by @gether_setup().
 | 
					 * This is called to free all resources allocated by @gether_setup().
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void gether_cleanup(void)
 | 
					void gether_cleanup(struct eth_dev *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!the_dev)
 | 
						if (!dev)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unregister_netdev(the_dev->net);
 | 
						unregister_netdev(dev->net);
 | 
				
			||||||
	flush_work(&the_dev->work);
 | 
						flush_work(&dev->work);
 | 
				
			||||||
	free_netdev(the_dev->net);
 | 
						free_netdev(dev->net);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	the_dev = NULL;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * gether_connect - notify network layer that USB link is active
 | 
					 * gether_connect - notify network layer that USB link is active
 | 
				
			||||||
 * @link: the USB link, set up with endpoints, descriptors matching
 | 
					 * @link: the USB link, set up with endpoints, descriptors matching
 | 
				
			||||||
| 
						 | 
					@ -860,7 +850,7 @@ void gether_cleanup(void)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct net_device *gether_connect(struct gether *link)
 | 
					struct net_device *gether_connect(struct gether *link)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct eth_dev		*dev = the_dev;
 | 
						struct eth_dev		*dev = link->ioport;
 | 
				
			||||||
	int			result = 0;
 | 
						int			result = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!dev)
 | 
						if (!dev)
 | 
				
			||||||
| 
						 | 
					@ -895,7 +885,6 @@ struct net_device *gether_connect(struct gether *link)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		spin_lock(&dev->lock);
 | 
							spin_lock(&dev->lock);
 | 
				
			||||||
		dev->port_usb = link;
 | 
							dev->port_usb = link;
 | 
				
			||||||
		link->ioport = dev;
 | 
					 | 
				
			||||||
		if (netif_running(dev->net)) {
 | 
							if (netif_running(dev->net)) {
 | 
				
			||||||
			if (link->open)
 | 
								if (link->open)
 | 
				
			||||||
				link->open(link);
 | 
									link->open(link);
 | 
				
			||||||
| 
						 | 
					@ -989,6 +978,5 @@ void gether_disconnect(struct gether *link)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock(&dev->lock);
 | 
						spin_lock(&dev->lock);
 | 
				
			||||||
	dev->port_usb = NULL;
 | 
						dev->port_usb = NULL;
 | 
				
			||||||
	link->ioport = NULL;
 | 
					 | 
				
			||||||
	spin_unlock(&dev->lock);
 | 
						spin_unlock(&dev->lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "gadget_chips.h"
 | 
					#include "gadget_chips.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct eth_dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * This represents the USB side of an "ethernet" link, managed by a USB
 | 
					 * This represents the USB side of an "ethernet" link, managed by a USB
 | 
				
			||||||
| 
						 | 
					@ -70,7 +71,7 @@ struct gether {
 | 
				
			||||||
			|USB_CDC_PACKET_TYPE_DIRECTED)
 | 
								|USB_CDC_PACKET_TYPE_DIRECTED)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* variant of gether_setup that allows customizing network device name */
 | 
					/* variant of gether_setup that allows customizing network device name */
 | 
				
			||||||
int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 | 
					struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
		const char *netname);
 | 
							const char *netname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* netdev setup/teardown as directed by the gadget driver */
 | 
					/* netdev setup/teardown as directed by the gadget driver */
 | 
				
			||||||
| 
						 | 
					@ -86,12 +87,13 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns negative errno, or zero on success
 | 
					 * Returns negative errno, or zero on success
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static inline int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
 | 
					static inline struct eth_dev *gether_setup(struct usb_gadget *g,
 | 
				
			||||||
 | 
							u8 ethaddr[ETH_ALEN])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return gether_setup_name(g, ethaddr, "usb");
 | 
						return gether_setup_name(g, ethaddr, "usb");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void gether_cleanup(void);
 | 
					void gether_cleanup(struct eth_dev *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* connect/disconnect is handled by individual functions */
 | 
					/* connect/disconnect is handled by individual functions */
 | 
				
			||||||
struct net_device *gether_connect(struct gether *);
 | 
					struct net_device *gether_connect(struct gether *);
 | 
				
			||||||
| 
						 | 
					@ -111,21 +113,24 @@ static inline bool can_support_ecm(struct usb_gadget *gadget)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* each configuration may bind one instance of an ethernet link */
 | 
					/* each configuration may bind one instance of an ethernet link */
 | 
				
			||||||
int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
 | 
					int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
 | 
							struct eth_dev *dev);
 | 
				
			||||||
int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
 | 
					int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
int eem_bind_config(struct usb_configuration *c);
 | 
							struct eth_dev *dev);
 | 
				
			||||||
 | 
					int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
 | 
							struct eth_dev *dev);
 | 
				
			||||||
 | 
					int eem_bind_config(struct usb_configuration *c, struct eth_dev *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USB_ETH_RNDIS
 | 
					#ifdef USB_ETH_RNDIS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
					int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
				u32 vendorID, const char *manufacturer);
 | 
							u32 vendorID, const char *manufacturer, struct eth_dev *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int
 | 
					static inline int
 | 
				
			||||||
rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
					rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
				u32 vendorID, const char *manufacturer)
 | 
							u32 vendorID, const char *manufacturer, struct eth_dev *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -145,9 +150,9 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 | 
				
			||||||
 * for calling @gether_cleanup() before module unload.
 | 
					 * for calling @gether_cleanup() before module unload.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static inline int rndis_bind_config(struct usb_configuration *c,
 | 
					static inline int rndis_bind_config(struct usb_configuration *c,
 | 
				
			||||||
				    u8 ethaddr[ETH_ALEN])
 | 
							u8 ethaddr[ETH_ALEN], struct eth_dev *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return rndis_bind_config_vendor(c, ethaddr, 0, NULL);
 | 
						return rndis_bind_config_vendor(c, ethaddr, 0, NULL, dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,7 +65,6 @@ int gserial_connect(struct gserial *, u8 port_num);
 | 
				
			||||||
void gserial_disconnect(struct gserial *);
 | 
					void gserial_disconnect(struct gserial *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* functions are bound to configurations by a config or gadget driver */
 | 
					/* functions are bound to configurations by a config or gadget driver */
 | 
				
			||||||
int acm_bind_config(struct usb_configuration *c, u8 port_num);
 | 
					 | 
				
			||||||
int gser_bind_config(struct usb_configuration *c, u8 port_num);
 | 
					int gser_bind_config(struct usb_configuration *c, u8 port_num);
 | 
				
			||||||
int obex_bind_config(struct usb_configuration *c, u8 port_num);
 | 
					int obex_bind_config(struct usb_configuration *c, u8 port_num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,6 +101,16 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ------------------------------------------------------------------------- */
 | 
					/* ------------------------------------------------------------------------- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_gadget_set_state(struct usb_gadget *gadget,
 | 
				
			||||||
 | 
							enum usb_device_state state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						gadget->state = state;
 | 
				
			||||||
 | 
						sysfs_notify(&gadget->dev.kobj, NULL, "status");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(usb_gadget_set_state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * usb_gadget_udc_start - tells usb device controller to start up
 | 
					 * usb_gadget_udc_start - tells usb device controller to start up
 | 
				
			||||||
 * @gadget: The gadget we want to get started
 | 
					 * @gadget: The gadget we want to get started
 | 
				
			||||||
| 
						 | 
					@ -156,6 +166,87 @@ static void usb_udc_release(struct device *dev)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct attribute_group *usb_udc_attr_groups[];
 | 
					static const struct attribute_group *usb_udc_attr_groups[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void usb_udc_nop_release(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						dev_vdbg(dev, "%s\n", __func__);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
 | 
				
			||||||
 | 
					 * @parent: the parent device to this udc. Usually the controller driver's
 | 
				
			||||||
 | 
					 * device.
 | 
				
			||||||
 | 
					 * @gadget: the gadget to be added to the list.
 | 
				
			||||||
 | 
					 * @release: a gadget release function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns zero on success, negative errno otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
 | 
				
			||||||
 | 
							void (*release)(struct device *dev))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct usb_udc		*udc;
 | 
				
			||||||
 | 
						int			ret = -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						udc = kzalloc(sizeof(*udc), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!udc)
 | 
				
			||||||
 | 
							goto err1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_set_name(&gadget->dev, "gadget");
 | 
				
			||||||
 | 
						gadget->dev.parent = parent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask);
 | 
				
			||||||
 | 
						gadget->dev.dma_parms = parent->dma_parms;
 | 
				
			||||||
 | 
						gadget->dev.dma_mask = parent->dma_mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (release)
 | 
				
			||||||
 | 
							gadget->dev.release = release;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							gadget->dev.release = usb_udc_nop_release;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = device_register(&gadget->dev);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							goto err2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						device_initialize(&udc->dev);
 | 
				
			||||||
 | 
						udc->dev.release = usb_udc_release;
 | 
				
			||||||
 | 
						udc->dev.class = udc_class;
 | 
				
			||||||
 | 
						udc->dev.groups = usb_udc_attr_groups;
 | 
				
			||||||
 | 
						udc->dev.parent = parent;
 | 
				
			||||||
 | 
						ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							goto err3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						udc->gadget = gadget;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutex_lock(&udc_lock);
 | 
				
			||||||
 | 
						list_add_tail(&udc->list, &udc_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = device_add(&udc->dev);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							goto err4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutex_unlock(&udc_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err4:
 | 
				
			||||||
 | 
						list_del(&udc->list);
 | 
				
			||||||
 | 
						mutex_unlock(&udc_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err3:
 | 
				
			||||||
 | 
						put_device(&udc->dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err2:
 | 
				
			||||||
 | 
						put_device(&gadget->dev);
 | 
				
			||||||
 | 
						kfree(udc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err1:
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * usb_add_gadget_udc - adds a new gadget to the udc class driver list
 | 
					 * usb_add_gadget_udc - adds a new gadget to the udc class driver list
 | 
				
			||||||
 * @parent: the parent device to this udc. Usually the controller
 | 
					 * @parent: the parent device to this udc. Usually the controller
 | 
				
			||||||
| 
						 | 
					@ -166,43 +257,7 @@ static const struct attribute_group *usb_udc_attr_groups[];
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
 | 
					int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usb_udc		*udc;
 | 
						return usb_add_gadget_udc_release(parent, gadget, NULL);
 | 
				
			||||||
	int			ret = -ENOMEM;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
 | 
					 | 
				
			||||||
	if (!udc)
 | 
					 | 
				
			||||||
		goto err1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	device_initialize(&udc->dev);
 | 
					 | 
				
			||||||
	udc->dev.release = usb_udc_release;
 | 
					 | 
				
			||||||
	udc->dev.class = udc_class;
 | 
					 | 
				
			||||||
	udc->dev.groups = usb_udc_attr_groups;
 | 
					 | 
				
			||||||
	udc->dev.parent = parent;
 | 
					 | 
				
			||||||
	ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
 | 
					 | 
				
			||||||
	if (ret)
 | 
					 | 
				
			||||||
		goto err2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	udc->gadget = gadget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mutex_lock(&udc_lock);
 | 
					 | 
				
			||||||
	list_add_tail(&udc->list, &udc_list);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = device_add(&udc->dev);
 | 
					 | 
				
			||||||
	if (ret)
 | 
					 | 
				
			||||||
		goto err3;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mutex_unlock(&udc_lock);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
err3:
 | 
					 | 
				
			||||||
	list_del(&udc->list);
 | 
					 | 
				
			||||||
	mutex_unlock(&udc_lock);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
err2:
 | 
					 | 
				
			||||||
	put_device(&udc->dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
err1:
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
 | 
					EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -220,6 +275,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->driver = NULL;
 | 
						udc->driver = NULL;
 | 
				
			||||||
	udc->dev.driver = NULL;
 | 
						udc->dev.driver = NULL;
 | 
				
			||||||
 | 
						udc->gadget->dev.driver = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -254,6 +310,7 @@ found:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
 | 
						kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
 | 
				
			||||||
	device_unregister(&udc->dev);
 | 
						device_unregister(&udc->dev);
 | 
				
			||||||
 | 
						device_unregister(&gadget->dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
 | 
					EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -268,6 +325,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udc->driver = driver;
 | 
						udc->driver = driver;
 | 
				
			||||||
	udc->dev.driver = &driver->driver;
 | 
						udc->dev.driver = &driver->driver;
 | 
				
			||||||
 | 
						udc->gadget->dev.driver = &driver->driver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = driver->bind(udc->gadget, driver);
 | 
						ret = driver->bind(udc->gadget, driver);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
| 
						 | 
					@ -286,6 +344,7 @@ err1:
 | 
				
			||||||
			udc->driver->function, ret);
 | 
								udc->driver->function, ret);
 | 
				
			||||||
	udc->driver = NULL;
 | 
						udc->driver = NULL;
 | 
				
			||||||
	udc->dev.driver = NULL;
 | 
						udc->dev.driver = NULL;
 | 
				
			||||||
 | 
						udc->gadget->dev.driver = NULL;
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -395,6 +454,16 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
 | 
					static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ssize_t usb_gadget_state_show(struct device *dev,
 | 
				
			||||||
 | 
							struct device_attribute *attr, char *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct usb_udc		*udc = container_of(dev, struct usb_udc, dev);
 | 
				
			||||||
 | 
						struct usb_gadget	*gadget = udc->gadget;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sprintf(buf, "%s\n", usb_state_string(gadget->state));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static DEVICE_ATTR(state, S_IRUGO, usb_gadget_state_show, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define USB_UDC_SPEED_ATTR(name, param)					\
 | 
					#define USB_UDC_SPEED_ATTR(name, param)					\
 | 
				
			||||||
ssize_t usb_udc_##param##_show(struct device *dev,			\
 | 
					ssize_t usb_udc_##param##_show(struct device *dev,			\
 | 
				
			||||||
		struct device_attribute *attr, char *buf)		\
 | 
							struct device_attribute *attr, char *buf)		\
 | 
				
			||||||
| 
						 | 
					@ -403,7 +472,7 @@ ssize_t usb_udc_##param##_show(struct device *dev,			\
 | 
				
			||||||
	return snprintf(buf, PAGE_SIZE, "%s\n",				\
 | 
						return snprintf(buf, PAGE_SIZE, "%s\n",				\
 | 
				
			||||||
			usb_speed_string(udc->gadget->param));		\
 | 
								usb_speed_string(udc->gadget->param));		\
 | 
				
			||||||
}									\
 | 
					}									\
 | 
				
			||||||
static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL)
 | 
					static DEVICE_ATTR(name, S_IRUGO, usb_udc_##param##_show, NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static USB_UDC_SPEED_ATTR(current_speed, speed);
 | 
					static USB_UDC_SPEED_ATTR(current_speed, speed);
 | 
				
			||||||
static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
 | 
					static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
 | 
				
			||||||
| 
						 | 
					@ -428,6 +497,7 @@ static USB_UDC_ATTR(a_alt_hnp_support);
 | 
				
			||||||
static struct attribute *usb_udc_attrs[] = {
 | 
					static struct attribute *usb_udc_attrs[] = {
 | 
				
			||||||
	&dev_attr_srp.attr,
 | 
						&dev_attr_srp.attr,
 | 
				
			||||||
	&dev_attr_soft_connect.attr,
 | 
						&dev_attr_soft_connect.attr,
 | 
				
			||||||
 | 
						&dev_attr_state.attr,
 | 
				
			||||||
	&dev_attr_current_speed.attr,
 | 
						&dev_attr_current_speed.attr,
 | 
				
			||||||
	&dev_attr_maximum_speed.attr,
 | 
						&dev_attr_maximum_speed.attr,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,8 +98,6 @@ extern unsigned int uvc_gadget_trace_param;
 | 
				
			||||||
#define DRIVER_VERSION				"0.1.0"
 | 
					#define DRIVER_VERSION				"0.1.0"
 | 
				
			||||||
#define DRIVER_VERSION_NUMBER			KERNEL_VERSION(0, 1, 0)
 | 
					#define DRIVER_VERSION_NUMBER			KERNEL_VERSION(0, 1, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DMA_ADDR_INVALID			(~(dma_addr_t)0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define UVC_NUM_REQUESTS			4
 | 
					#define UVC_NUM_REQUESTS			4
 | 
				
			||||||
#define UVC_MAX_REQUEST_SIZE			64
 | 
					#define UVC_MAX_REQUEST_SIZE			64
 | 
				
			||||||
#define UVC_MAX_EVENTS				4
 | 
					#define UVC_MAX_EVENTS				4
 | 
				
			||||||
| 
						 | 
					@ -190,6 +188,7 @@ struct uvc_file_handle
 | 
				
			||||||
 * Functions
 | 
					 * Functions
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern void uvc_function_setup_continue(struct uvc_device *uvc);
 | 
				
			||||||
extern void uvc_endpoint_stream(struct uvc_device *dev);
 | 
					extern void uvc_endpoint_stream(struct uvc_device *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void uvc_function_connect(struct uvc_device *uvc);
 | 
					extern void uvc_function_connect(struct uvc_device *uvc);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,7 @@
 | 
				
			||||||
 *	(at your option) any later version.
 | 
					 *	(at your option) any later version.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/atomic.h>
 | 
				
			||||||
#include <linux/kernel.h>
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
#include <linux/mm.h>
 | 
					#include <linux/mm.h>
 | 
				
			||||||
#include <linux/list.h>
 | 
					#include <linux/list.h>
 | 
				
			||||||
| 
						 | 
					@ -18,7 +19,8 @@
 | 
				
			||||||
#include <linux/videodev2.h>
 | 
					#include <linux/videodev2.h>
 | 
				
			||||||
#include <linux/vmalloc.h>
 | 
					#include <linux/vmalloc.h>
 | 
				
			||||||
#include <linux/wait.h>
 | 
					#include <linux/wait.h>
 | 
				
			||||||
#include <linux/atomic.h>
 | 
					
 | 
				
			||||||
 | 
					#include <media/videobuf2-vmalloc.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "uvc.h"
 | 
					#include "uvc.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,330 +30,175 @@
 | 
				
			||||||
 * Video queues is initialized by uvc_queue_init(). The function performs
 | 
					 * Video queues is initialized by uvc_queue_init(). The function performs
 | 
				
			||||||
 * basic initialization of the uvc_video_queue struct and never fails.
 | 
					 * basic initialization of the uvc_video_queue struct and never fails.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Video buffer allocation and freeing are performed by uvc_alloc_buffers and
 | 
					 * Video buffers are managed by videobuf2. The driver uses a mutex to protect
 | 
				
			||||||
 * uvc_free_buffers respectively. The former acquires the video queue lock,
 | 
					 * the videobuf2 queue operations by serializing calls to videobuf2 and a
 | 
				
			||||||
 * while the later must be called with the lock held (so that allocation can
 | 
					 * spinlock to protect the IRQ queue that holds the buffers to be processed by
 | 
				
			||||||
 * free previously allocated buffers). Trying to free buffers that are mapped
 | 
					 * the driver.
 | 
				
			||||||
 * to user space will return -EBUSY.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Video buffers are managed using two queues. However, unlike most USB video
 | 
					 | 
				
			||||||
 * drivers that use an in queue and an out queue, we use a main queue to hold
 | 
					 | 
				
			||||||
 * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to
 | 
					 | 
				
			||||||
 * hold empty buffers. This design (copied from video-buf) minimizes locking
 | 
					 | 
				
			||||||
 * in interrupt, as only one queue is shared between interrupt and user
 | 
					 | 
				
			||||||
 * contexts.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Use cases
 | 
					 | 
				
			||||||
 * ---------
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Unless stated otherwise, all operations that modify the irq buffers queue
 | 
					 | 
				
			||||||
 * are protected by the irq spinlock.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * 1. The user queues the buffers, starts streaming and dequeues a buffer.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *    The buffers are added to the main and irq queues. Both operations are
 | 
					 | 
				
			||||||
 *    protected by the queue lock, and the later is protected by the irq
 | 
					 | 
				
			||||||
 *    spinlock as well.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *    The completion handler fetches a buffer from the irq queue and fills it
 | 
					 | 
				
			||||||
 *    with video data. If no buffer is available (irq queue empty), the handler
 | 
					 | 
				
			||||||
 *    returns immediately.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *    When the buffer is full, the completion handler removes it from the irq
 | 
					 | 
				
			||||||
 *    queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue.
 | 
					 | 
				
			||||||
 *    At that point, any process waiting on the buffer will be woken up. If a
 | 
					 | 
				
			||||||
 *    process tries to dequeue a buffer after it has been marked ready, the
 | 
					 | 
				
			||||||
 *    dequeing will succeed immediately.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * 2. Buffers are queued, user is waiting on a buffer and the device gets
 | 
					 | 
				
			||||||
 *    disconnected.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *    When the device is disconnected, the kernel calls the completion handler
 | 
					 | 
				
			||||||
 *    with an appropriate status code. The handler marks all buffers in the
 | 
					 | 
				
			||||||
 *    irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so
 | 
					 | 
				
			||||||
 *    that any process waiting on a buffer gets woken up.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *    Waking up up the first buffer on the irq list is not enough, as the
 | 
					 | 
				
			||||||
 *    process waiting on the buffer might restart the dequeue operation
 | 
					 | 
				
			||||||
 *    immediately.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					/* -----------------------------------------------------------------------------
 | 
				
			||||||
uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
 | 
					 * videobuf2 queue operations
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
 | 
				
			||||||
 | 
								   unsigned int *nbuffers, unsigned int *nplanes,
 | 
				
			||||||
 | 
								   unsigned int sizes[], void *alloc_ctxs[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	mutex_init(&queue->mutex);
 | 
						struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
 | 
				
			||||||
	spin_lock_init(&queue->irqlock);
 | 
						struct uvc_video *video = container_of(queue, struct uvc_video, queue);
 | 
				
			||||||
	INIT_LIST_HEAD(&queue->mainqueue);
 | 
					
 | 
				
			||||||
	INIT_LIST_HEAD(&queue->irqqueue);
 | 
						if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
 | 
				
			||||||
	queue->type = type;
 | 
							*nbuffers = UVC_MAX_VIDEO_BUFFERS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*nplanes = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sizes[0] = video->imagesize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					static int uvc_buffer_prepare(struct vb2_buffer *vb)
 | 
				
			||||||
 * Free the video buffers.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This function must be called with the queue lock held.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static int uvc_free_buffers(struct uvc_video_queue *queue)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int i;
 | 
						struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
 | 
				
			||||||
 | 
						struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < queue->count; ++i) {
 | 
						if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
 | 
				
			||||||
		if (queue->buffer[i].vma_use_count != 0)
 | 
						    vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
 | 
				
			||||||
			return -EBUSY;
 | 
							uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (queue->count) {
 | 
						if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED))
 | 
				
			||||||
		vfree(queue->mem);
 | 
							return -ENODEV;
 | 
				
			||||||
		queue->count = 0;
 | 
					
 | 
				
			||||||
 | 
						buf->state = UVC_BUF_STATE_QUEUED;
 | 
				
			||||||
 | 
						buf->mem = vb2_plane_vaddr(vb, 0);
 | 
				
			||||||
 | 
						buf->length = vb2_plane_size(vb, 0);
 | 
				
			||||||
 | 
						if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
 | 
				
			||||||
 | 
							buf->bytesused = 0;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							buf->bytesused = vb2_get_plane_payload(vb, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void uvc_buffer_queue(struct vb2_buffer *vb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
 | 
				
			||||||
 | 
						struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&queue->irqlock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
 | 
				
			||||||
 | 
							list_add_tail(&buf->queue, &queue->irqqueue);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/* If the device is disconnected return the buffer to userspace
 | 
				
			||||||
 | 
							 * directly. The next QBUF call will fail with -ENODEV.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							buf->state = UVC_BUF_STATE_ERROR;
 | 
				
			||||||
 | 
							vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&queue->irqlock, flags);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct vb2_ops uvc_queue_qops = {
 | 
				
			||||||
 | 
						.queue_setup = uvc_queue_setup,
 | 
				
			||||||
 | 
						.buf_prepare = uvc_buffer_prepare,
 | 
				
			||||||
 | 
						.buf_queue = uvc_buffer_queue,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int uvc_queue_init(struct uvc_video_queue *queue,
 | 
				
			||||||
 | 
								  enum v4l2_buf_type type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						queue->queue.type = type;
 | 
				
			||||||
 | 
						queue->queue.io_modes = VB2_MMAP | VB2_USERPTR;
 | 
				
			||||||
 | 
						queue->queue.drv_priv = queue;
 | 
				
			||||||
 | 
						queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
 | 
				
			||||||
 | 
						queue->queue.ops = &uvc_queue_qops;
 | 
				
			||||||
 | 
						queue->queue.mem_ops = &vb2_vmalloc_memops;
 | 
				
			||||||
 | 
						ret = vb2_queue_init(&queue->queue);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutex_init(&queue->mutex);
 | 
				
			||||||
 | 
						spin_lock_init(&queue->irqlock);
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&queue->irqqueue);
 | 
				
			||||||
 | 
						queue->flags = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Allocate the video buffers.
 | 
					 * Free the video buffers.
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Pages are reserved to make sure they will not be swapped, as they will be
 | 
					 | 
				
			||||||
 * filled in the URB completion handler.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Buffers will be individually mapped, so they must all be page aligned.
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int
 | 
					static void uvc_free_buffers(struct uvc_video_queue *queue)
 | 
				
			||||||
uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
 | 
					 | 
				
			||||||
		  unsigned int buflength)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int bufsize = PAGE_ALIGN(buflength);
 | 
					 | 
				
			||||||
	unsigned int i;
 | 
					 | 
				
			||||||
	void *mem = NULL;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (nbuffers > UVC_MAX_VIDEO_BUFFERS)
 | 
					 | 
				
			||||||
		nbuffers = UVC_MAX_VIDEO_BUFFERS;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mutex_lock(&queue->mutex);
 | 
						mutex_lock(&queue->mutex);
 | 
				
			||||||
 | 
						vb2_queue_release(&queue->queue);
 | 
				
			||||||
	if ((ret = uvc_free_buffers(queue)) < 0)
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Bail out if no buffers should be allocated. */
 | 
					 | 
				
			||||||
	if (nbuffers == 0)
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Decrement the number of buffers until allocation succeeds. */
 | 
					 | 
				
			||||||
	for (; nbuffers > 0; --nbuffers) {
 | 
					 | 
				
			||||||
		mem = vmalloc_32(nbuffers * bufsize);
 | 
					 | 
				
			||||||
		if (mem != NULL)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (mem == NULL) {
 | 
					 | 
				
			||||||
		ret = -ENOMEM;
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < nbuffers; ++i) {
 | 
					 | 
				
			||||||
		memset(&queue->buffer[i], 0, sizeof queue->buffer[i]);
 | 
					 | 
				
			||||||
		queue->buffer[i].buf.index = i;
 | 
					 | 
				
			||||||
		queue->buffer[i].buf.m.offset = i * bufsize;
 | 
					 | 
				
			||||||
		queue->buffer[i].buf.length = buflength;
 | 
					 | 
				
			||||||
		queue->buffer[i].buf.type = queue->type;
 | 
					 | 
				
			||||||
		queue->buffer[i].buf.sequence = 0;
 | 
					 | 
				
			||||||
		queue->buffer[i].buf.field = V4L2_FIELD_NONE;
 | 
					 | 
				
			||||||
		queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP;
 | 
					 | 
				
			||||||
		queue->buffer[i].buf.flags = 0;
 | 
					 | 
				
			||||||
		init_waitqueue_head(&queue->buffer[i].wait);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	queue->mem = mem;
 | 
					 | 
				
			||||||
	queue->count = nbuffers;
 | 
					 | 
				
			||||||
	queue->buf_size = bufsize;
 | 
					 | 
				
			||||||
	ret = nbuffers;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
done:
 | 
					 | 
				
			||||||
	mutex_unlock(&queue->mutex);
 | 
						mutex_unlock(&queue->mutex);
 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void __uvc_query_buffer(struct uvc_buffer *buf,
 | 
					 | 
				
			||||||
		struct v4l2_buffer *v4l2_buf)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (buf->vma_use_count)
 | 
					 | 
				
			||||||
		v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (buf->state) {
 | 
					 | 
				
			||||||
	case UVC_BUF_STATE_ERROR:
 | 
					 | 
				
			||||||
	case UVC_BUF_STATE_DONE:
 | 
					 | 
				
			||||||
		v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case UVC_BUF_STATE_QUEUED:
 | 
					 | 
				
			||||||
	case UVC_BUF_STATE_ACTIVE:
 | 
					 | 
				
			||||||
		v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case UVC_BUF_STATE_IDLE:
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int
 | 
					 | 
				
			||||||
uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mutex_lock(&queue->mutex);
 | 
					 | 
				
			||||||
	if (v4l2_buf->index >= queue->count) {
 | 
					 | 
				
			||||||
		ret = -EINVAL;
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	__uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
done:
 | 
					 | 
				
			||||||
	mutex_unlock(&queue->mutex);
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Queue a video buffer. Attempting to queue a buffer that has already been
 | 
					 * Allocate the video buffers.
 | 
				
			||||||
 * queued will return -EINVAL.
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int
 | 
					static int uvc_alloc_buffers(struct uvc_video_queue *queue,
 | 
				
			||||||
uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
 | 
								     struct v4l2_requestbuffers *rb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct uvc_buffer *buf;
 | 
						int ret;
 | 
				
			||||||
	unsigned long flags;
 | 
					 | 
				
			||||||
	int ret = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (v4l2_buf->type != queue->type ||
 | 
					 | 
				
			||||||
	    v4l2_buf->memory != V4L2_MEMORY_MMAP) {
 | 
					 | 
				
			||||||
		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
 | 
					 | 
				
			||||||
			"and/or memory (%u).\n", v4l2_buf->type,
 | 
					 | 
				
			||||||
			v4l2_buf->memory);
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&queue->mutex);
 | 
						mutex_lock(&queue->mutex);
 | 
				
			||||||
	if (v4l2_buf->index >= queue->count) {
 | 
						ret = vb2_reqbufs(&queue->queue, rb);
 | 
				
			||||||
		uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n");
 | 
					 | 
				
			||||||
		ret = -EINVAL;
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	buf = &queue->buffer[v4l2_buf->index];
 | 
					 | 
				
			||||||
	if (buf->state != UVC_BUF_STATE_IDLE) {
 | 
					 | 
				
			||||||
		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state "
 | 
					 | 
				
			||||||
			"(%u).\n", buf->state);
 | 
					 | 
				
			||||||
		ret = -EINVAL;
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
 | 
					 | 
				
			||||||
	    v4l2_buf->bytesused > buf->buf.length) {
 | 
					 | 
				
			||||||
		uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
 | 
					 | 
				
			||||||
		ret = -EINVAL;
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
 | 
					 | 
				
			||||||
		buf->buf.bytesused = 0;
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		buf->buf.bytesused = v4l2_buf->bytesused;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	spin_lock_irqsave(&queue->irqlock, flags);
 | 
					 | 
				
			||||||
	if (queue->flags & UVC_QUEUE_DISCONNECTED) {
 | 
					 | 
				
			||||||
		spin_unlock_irqrestore(&queue->irqlock, flags);
 | 
					 | 
				
			||||||
		ret = -ENODEV;
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	buf->state = UVC_BUF_STATE_QUEUED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
 | 
					 | 
				
			||||||
	queue->flags &= ~UVC_QUEUE_PAUSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	list_add_tail(&buf->stream, &queue->mainqueue);
 | 
					 | 
				
			||||||
	list_add_tail(&buf->queue, &queue->irqqueue);
 | 
					 | 
				
			||||||
	spin_unlock_irqrestore(&queue->irqlock, flags);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
done:
 | 
					 | 
				
			||||||
	mutex_unlock(&queue->mutex);
 | 
						mutex_unlock(&queue->mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret ? ret : rb->count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int uvc_query_buffer(struct uvc_video_queue *queue,
 | 
				
			||||||
 | 
								    struct v4l2_buffer *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutex_lock(&queue->mutex);
 | 
				
			||||||
 | 
						ret = vb2_querybuf(&queue->queue, buf);
 | 
				
			||||||
 | 
						mutex_unlock(&queue->mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
 | 
					static int uvc_queue_buffer(struct uvc_video_queue *queue,
 | 
				
			||||||
 | 
								    struct v4l2_buffer *buf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (nonblocking) {
 | 
						unsigned long flags;
 | 
				
			||||||
		return (buf->state != UVC_BUF_STATE_QUEUED &&
 | 
						int ret;
 | 
				
			||||||
			buf->state != UVC_BUF_STATE_ACTIVE)
 | 
					 | 
				
			||||||
			? 0 : -EAGAIN;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return wait_event_interruptible(buf->wait,
 | 
						mutex_lock(&queue->mutex);
 | 
				
			||||||
		buf->state != UVC_BUF_STATE_QUEUED &&
 | 
						ret = vb2_qbuf(&queue->queue, buf);
 | 
				
			||||||
		buf->state != UVC_BUF_STATE_ACTIVE);
 | 
						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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Dequeue a video buffer. If nonblocking is false, block until a buffer is
 | 
					 * Dequeue a video buffer. If nonblocking is false, block until a buffer is
 | 
				
			||||||
 * available.
 | 
					 * available.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int
 | 
					static int uvc_dequeue_buffer(struct uvc_video_queue *queue,
 | 
				
			||||||
uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf,
 | 
								      struct v4l2_buffer *buf, int nonblocking)
 | 
				
			||||||
		   int nonblocking)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct uvc_buffer *buf;
 | 
						int ret;
 | 
				
			||||||
	int ret = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (v4l2_buf->type != queue->type ||
 | 
					 | 
				
			||||||
	    v4l2_buf->memory != V4L2_MEMORY_MMAP) {
 | 
					 | 
				
			||||||
		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
 | 
					 | 
				
			||||||
			"and/or memory (%u).\n", v4l2_buf->type,
 | 
					 | 
				
			||||||
			v4l2_buf->memory);
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&queue->mutex);
 | 
						mutex_lock(&queue->mutex);
 | 
				
			||||||
	if (list_empty(&queue->mainqueue)) {
 | 
						ret = vb2_dqbuf(&queue->queue, buf, nonblocking);
 | 
				
			||||||
		uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n");
 | 
					 | 
				
			||||||
		ret = -EINVAL;
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
 | 
					 | 
				
			||||||
	if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0)
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n",
 | 
					 | 
				
			||||||
		buf->buf.index, buf->state, buf->buf.bytesused);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (buf->state) {
 | 
					 | 
				
			||||||
	case UVC_BUF_STATE_ERROR:
 | 
					 | 
				
			||||||
		uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data "
 | 
					 | 
				
			||||||
			"(transmission error).\n");
 | 
					 | 
				
			||||||
		ret = -EIO;
 | 
					 | 
				
			||||||
	case UVC_BUF_STATE_DONE:
 | 
					 | 
				
			||||||
		buf->state = UVC_BUF_STATE_IDLE;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case UVC_BUF_STATE_IDLE:
 | 
					 | 
				
			||||||
	case UVC_BUF_STATE_QUEUED:
 | 
					 | 
				
			||||||
	case UVC_BUF_STATE_ACTIVE:
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u "
 | 
					 | 
				
			||||||
			"(driver bug?).\n", buf->state);
 | 
					 | 
				
			||||||
		ret = -EINVAL;
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	list_del(&buf->stream);
 | 
					 | 
				
			||||||
	__uvc_query_buffer(buf, v4l2_buf);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
done:
 | 
					 | 
				
			||||||
	mutex_unlock(&queue->mutex);
 | 
						mutex_unlock(&queue->mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -361,105 +208,47 @@ done:
 | 
				
			||||||
 * This function implements video queue polling and is intended to be used by
 | 
					 * This function implements video queue polling and is intended to be used by
 | 
				
			||||||
 * the device poll handler.
 | 
					 * the device poll handler.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static unsigned int
 | 
					static unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
 | 
				
			||||||
uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
 | 
									   struct file *file, poll_table *wait)
 | 
				
			||||||
	       poll_table *wait)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct uvc_buffer *buf;
 | 
						unsigned int ret;
 | 
				
			||||||
	unsigned int mask = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&queue->mutex);
 | 
						mutex_lock(&queue->mutex);
 | 
				
			||||||
	if (list_empty(&queue->mainqueue))
 | 
						ret = vb2_poll(&queue->queue, file, wait);
 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	poll_wait(file, &buf->wait, wait);
 | 
					 | 
				
			||||||
	if (buf->state == UVC_BUF_STATE_DONE ||
 | 
					 | 
				
			||||||
	    buf->state == UVC_BUF_STATE_ERROR)
 | 
					 | 
				
			||||||
		mask |= POLLOUT | POLLWRNORM;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
done:
 | 
					 | 
				
			||||||
	mutex_unlock(&queue->mutex);
 | 
						mutex_unlock(&queue->mutex);
 | 
				
			||||||
	return mask;
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					static int uvc_queue_mmap(struct uvc_video_queue *queue,
 | 
				
			||||||
 * VMA operations.
 | 
								  struct vm_area_struct *vma)
 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void uvc_vm_open(struct vm_area_struct *vma)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct uvc_buffer *buffer = vma->vm_private_data;
 | 
						int ret;
 | 
				
			||||||
	buffer->vma_use_count++;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void uvc_vm_close(struct vm_area_struct *vma)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct uvc_buffer *buffer = vma->vm_private_data;
 | 
					 | 
				
			||||||
	buffer->vma_use_count--;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct vm_operations_struct uvc_vm_ops = {
 | 
					 | 
				
			||||||
	.open		= uvc_vm_open,
 | 
					 | 
				
			||||||
	.close		= uvc_vm_close,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Memory-map a buffer.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This function implements video buffer memory mapping and is intended to be
 | 
					 | 
				
			||||||
 * used by the device mmap handler.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static int
 | 
					 | 
				
			||||||
uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct uvc_buffer *uninitialized_var(buffer);
 | 
					 | 
				
			||||||
	struct page *page;
 | 
					 | 
				
			||||||
	unsigned long addr, start, size;
 | 
					 | 
				
			||||||
	unsigned int i;
 | 
					 | 
				
			||||||
	int ret = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	start = vma->vm_start;
 | 
					 | 
				
			||||||
	size = vma->vm_end - vma->vm_start;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&queue->mutex);
 | 
						mutex_lock(&queue->mutex);
 | 
				
			||||||
 | 
						ret = vb2_mmap(&queue->queue, vma);
 | 
				
			||||||
 | 
						mutex_unlock(&queue->mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < queue->count; ++i) {
 | 
						return ret;
 | 
				
			||||||
		buffer = &queue->buffer[i];
 | 
					}
 | 
				
			||||||
		if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (i == queue->count || size != queue->buf_size) {
 | 
					#ifndef CONFIG_MMU
 | 
				
			||||||
		ret = -EINVAL;
 | 
					/*
 | 
				
			||||||
		goto done;
 | 
					 * Get unmapped area.
 | 
				
			||||||
	}
 | 
					 *
 | 
				
			||||||
 | 
					 * NO-MMU arch need this function to make mmap() work correctly.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
 | 
				
			||||||
 | 
							unsigned long pgoff)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						mutex_lock(&queue->mutex);
 | 
				
			||||||
	 * VM_IO marks the area as being an mmaped region for I/O to a
 | 
						ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0);
 | 
				
			||||||
	 * device. It also prevents the region from being core dumped.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	vma->vm_flags |= VM_IO;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	addr = (unsigned long)queue->mem + buffer->buf.m.offset;
 | 
					 | 
				
			||||||
	while (size > 0) {
 | 
					 | 
				
			||||||
		page = vmalloc_to_page((void *)addr);
 | 
					 | 
				
			||||||
		if ((ret = vm_insert_page(vma, start, page)) < 0)
 | 
					 | 
				
			||||||
			goto done;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		start += PAGE_SIZE;
 | 
					 | 
				
			||||||
		addr += PAGE_SIZE;
 | 
					 | 
				
			||||||
		size -= PAGE_SIZE;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	vma->vm_ops = &uvc_vm_ops;
 | 
					 | 
				
			||||||
	vma->vm_private_data = buffer;
 | 
					 | 
				
			||||||
	uvc_vm_open(vma);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
done:
 | 
					 | 
				
			||||||
	mutex_unlock(&queue->mutex);
 | 
						mutex_unlock(&queue->mutex);
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Cancel the video buffers queue.
 | 
					 * Cancel the video buffers queue.
 | 
				
			||||||
| 
						 | 
					@ -484,7 +273,7 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
 | 
				
			||||||
				       queue);
 | 
									       queue);
 | 
				
			||||||
		list_del(&buf->queue);
 | 
							list_del(&buf->queue);
 | 
				
			||||||
		buf->state = UVC_BUF_STATE_ERROR;
 | 
							buf->state = UVC_BUF_STATE_ERROR;
 | 
				
			||||||
		wake_up(&buf->wait);
 | 
							vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* This must be protected by the irqlock spinlock to avoid race
 | 
						/* This must be protected by the irqlock spinlock to avoid race
 | 
				
			||||||
	 * conditions between uvc_queue_buffer and the disconnection event that
 | 
						 * conditions between uvc_queue_buffer and the disconnection event that
 | 
				
			||||||
| 
						 | 
					@ -516,26 +305,33 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
 | 
					static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned long flags;
 | 
				
			||||||
	int ret = 0;
 | 
						int ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&queue->mutex);
 | 
						mutex_lock(&queue->mutex);
 | 
				
			||||||
	if (enable) {
 | 
						if (enable) {
 | 
				
			||||||
		if (uvc_queue_streaming(queue)) {
 | 
							ret = vb2_streamon(&queue->queue, queue->queue.type);
 | 
				
			||||||
			ret = -EBUSY;
 | 
							if (ret < 0)
 | 
				
			||||||
			goto done;
 | 
								goto done;
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
		queue->sequence = 0;
 | 
							queue->sequence = 0;
 | 
				
			||||||
		queue->flags |= UVC_QUEUE_STREAMING;
 | 
					 | 
				
			||||||
		queue->buf_used = 0;
 | 
							queue->buf_used = 0;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		uvc_queue_cancel(queue, 0);
 | 
							ret = vb2_streamoff(&queue->queue, queue->queue.type);
 | 
				
			||||||
		INIT_LIST_HEAD(&queue->mainqueue);
 | 
							if (ret < 0)
 | 
				
			||||||
 | 
								goto done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (i = 0; i < queue->count; ++i)
 | 
							spin_lock_irqsave(&queue->irqlock, flags);
 | 
				
			||||||
			queue->buffer[i].state = UVC_BUF_STATE_IDLE;
 | 
							INIT_LIST_HEAD(&queue->irqqueue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		queue->flags &= ~UVC_QUEUE_STREAMING;
 | 
							/*
 | 
				
			||||||
 | 
							 * FIXME: We need to clear the DISCONNECTED flag to ensure that
 | 
				
			||||||
 | 
							 * applications will be able to queue buffers for the next
 | 
				
			||||||
 | 
							 * streaming run. However, clearing it here doesn't guarantee
 | 
				
			||||||
 | 
							 * that the device will be reconnected in the meantime.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							queue->flags &= ~UVC_QUEUE_DISCONNECTED;
 | 
				
			||||||
 | 
							spin_unlock_irqrestore(&queue->irqlock, flags);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
done:
 | 
					done:
 | 
				
			||||||
| 
						 | 
					@ -544,15 +340,15 @@ done:
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* called with &queue_irqlock held.. */
 | 
					/* called with &queue_irqlock held.. */
 | 
				
			||||||
static struct uvc_buffer *
 | 
					static struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
 | 
				
			||||||
uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
 | 
											struct uvc_buffer *buf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct uvc_buffer *nextbuf;
 | 
						struct uvc_buffer *nextbuf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
 | 
						if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
 | 
				
			||||||
	    buf->buf.length != buf->buf.bytesused) {
 | 
						     buf->length != buf->bytesused) {
 | 
				
			||||||
		buf->state = UVC_BUF_STATE_QUEUED;
 | 
							buf->state = UVC_BUF_STATE_QUEUED;
 | 
				
			||||||
		buf->buf.bytesused = 0;
 | 
							vb2_set_plane_payload(&buf->buf, 0, 0);
 | 
				
			||||||
		return buf;
 | 
							return buf;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -563,10 +359,18 @@ uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		nextbuf = NULL;
 | 
							nextbuf = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	buf->buf.sequence = queue->sequence++;
 | 
						/*
 | 
				
			||||||
	do_gettimeofday(&buf->buf.timestamp);
 | 
						 * FIXME: with videobuf2, the sequence number or timestamp fields
 | 
				
			||||||
 | 
						 * are valid only for video capture devices and the UVC gadget usually
 | 
				
			||||||
 | 
						 * is a video output device. Keeping these until the specs are clear on
 | 
				
			||||||
 | 
						 * this aspect.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						buf->buf.v4l2_buf.sequence = queue->sequence++;
 | 
				
			||||||
 | 
						do_gettimeofday(&buf->buf.v4l2_buf.timestamp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
 | 
				
			||||||
 | 
						vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wake_up(&buf->wait);
 | 
					 | 
				
			||||||
	return nextbuf;
 | 
						return nextbuf;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@
 | 
				
			||||||
#include <linux/kernel.h>
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
#include <linux/poll.h>
 | 
					#include <linux/poll.h>
 | 
				
			||||||
#include <linux/videodev2.h>
 | 
					#include <linux/videodev2.h>
 | 
				
			||||||
 | 
					#include <media/videobuf2-core.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Maximum frame size in bytes, for sanity checking. */
 | 
					/* Maximum frame size in bytes, for sanity checking. */
 | 
				
			||||||
#define UVC_MAX_FRAME_SIZE	(16*1024*1024)
 | 
					#define UVC_MAX_FRAME_SIZE	(16*1024*1024)
 | 
				
			||||||
| 
						 | 
					@ -25,42 +26,35 @@ enum uvc_buffer_state {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct uvc_buffer {
 | 
					struct uvc_buffer {
 | 
				
			||||||
	unsigned long vma_use_count;
 | 
						struct vb2_buffer buf;
 | 
				
			||||||
	struct list_head stream;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Touched by interrupt handler. */
 | 
					 | 
				
			||||||
	struct v4l2_buffer buf;
 | 
					 | 
				
			||||||
	struct list_head queue;
 | 
						struct list_head queue;
 | 
				
			||||||
	wait_queue_head_t wait;
 | 
					
 | 
				
			||||||
	enum uvc_buffer_state state;
 | 
						enum uvc_buffer_state state;
 | 
				
			||||||
 | 
						void *mem;
 | 
				
			||||||
 | 
						unsigned int length;
 | 
				
			||||||
 | 
						unsigned int bytesused;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define UVC_QUEUE_STREAMING		(1 << 0)
 | 
					#define UVC_QUEUE_DISCONNECTED		(1 << 0)
 | 
				
			||||||
#define UVC_QUEUE_DISCONNECTED		(1 << 1)
 | 
					#define UVC_QUEUE_DROP_INCOMPLETE	(1 << 1)
 | 
				
			||||||
#define UVC_QUEUE_DROP_INCOMPLETE	(1 << 2)
 | 
					#define UVC_QUEUE_PAUSED		(1 << 2)
 | 
				
			||||||
#define UVC_QUEUE_PAUSED		(1 << 3)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct uvc_video_queue {
 | 
					struct uvc_video_queue {
 | 
				
			||||||
	enum v4l2_buf_type type;
 | 
						struct vb2_queue queue;
 | 
				
			||||||
 | 
						struct mutex mutex;	/* Protects queue */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void *mem;
 | 
					 | 
				
			||||||
	unsigned int flags;
 | 
						unsigned int flags;
 | 
				
			||||||
	__u32 sequence;
 | 
						__u32 sequence;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unsigned int count;
 | 
					 | 
				
			||||||
	unsigned int buf_size;
 | 
					 | 
				
			||||||
	unsigned int buf_used;
 | 
						unsigned int buf_used;
 | 
				
			||||||
	struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS];
 | 
					 | 
				
			||||||
	struct mutex mutex;	/* protects buffers and mainqueue */
 | 
					 | 
				
			||||||
	spinlock_t irqlock;	/* protects irqqueue */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct list_head mainqueue;
 | 
						spinlock_t irqlock;	/* Protects flags and irqqueue */
 | 
				
			||||||
	struct list_head irqqueue;
 | 
						struct list_head irqqueue;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
 | 
					static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return queue->flags & UVC_QUEUE_STREAMING;
 | 
						return vb2_is_streaming(&queue->queue);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* __KERNEL__ */
 | 
					#endif /* __KERNEL__ */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,9 +41,8 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req->length = min_t(unsigned int, uvc->event_length, data->length);
 | 
						req->length = min_t(unsigned int, uvc->event_length, data->length);
 | 
				
			||||||
	req->zero = data->length < uvc->event_length;
 | 
						req->zero = data->length < uvc->event_length;
 | 
				
			||||||
	req->dma = DMA_ADDR_INVALID;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(req->buf, data->data, data->length);
 | 
						memcpy(req->buf, data->data, req->length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
 | 
						return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -148,16 +147,13 @@ uvc_v4l2_release(struct file *file)
 | 
				
			||||||
	uvc_function_disconnect(uvc);
 | 
						uvc_function_disconnect(uvc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uvc_video_enable(video, 0);
 | 
						uvc_video_enable(video, 0);
 | 
				
			||||||
	mutex_lock(&video->queue.mutex);
 | 
						uvc_free_buffers(&video->queue);
 | 
				
			||||||
	if (uvc_free_buffers(&video->queue) < 0)
 | 
					 | 
				
			||||||
		printk(KERN_ERR "uvc_v4l2_release: Unable to free "
 | 
					 | 
				
			||||||
				"buffers.\n");
 | 
					 | 
				
			||||||
	mutex_unlock(&video->queue.mutex);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	file->private_data = NULL;
 | 
						file->private_data = NULL;
 | 
				
			||||||
	v4l2_fh_del(&handle->vfh);
 | 
						v4l2_fh_del(&handle->vfh);
 | 
				
			||||||
	v4l2_fh_exit(&handle->vfh);
 | 
						v4l2_fh_exit(&handle->vfh);
 | 
				
			||||||
	kfree(handle);
 | 
						kfree(handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -178,9 +174,9 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 | 
				
			||||||
		struct v4l2_capability *cap = arg;
 | 
							struct v4l2_capability *cap = arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		memset(cap, 0, sizeof *cap);
 | 
							memset(cap, 0, sizeof *cap);
 | 
				
			||||||
		strncpy(cap->driver, "g_uvc", sizeof(cap->driver));
 | 
							strlcpy(cap->driver, "g_uvc", sizeof(cap->driver));
 | 
				
			||||||
		strncpy(cap->card, cdev->gadget->name, sizeof(cap->card));
 | 
							strlcpy(cap->card, cdev->gadget->name, sizeof(cap->card));
 | 
				
			||||||
		strncpy(cap->bus_info, dev_name(&cdev->gadget->dev),
 | 
							strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev),
 | 
				
			||||||
			sizeof cap->bus_info);
 | 
								sizeof cap->bus_info);
 | 
				
			||||||
		cap->version = DRIVER_VERSION_NUMBER;
 | 
							cap->version = DRIVER_VERSION_NUMBER;
 | 
				
			||||||
		cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
 | 
							cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
 | 
				
			||||||
| 
						 | 
					@ -192,7 +188,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		struct v4l2_format *fmt = arg;
 | 
							struct v4l2_format *fmt = arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (fmt->type != video->queue.type)
 | 
							if (fmt->type != video->queue.queue.type)
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return uvc_v4l2_get_format(video, fmt);
 | 
							return uvc_v4l2_get_format(video, fmt);
 | 
				
			||||||
| 
						 | 
					@ -202,7 +198,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		struct v4l2_format *fmt = arg;
 | 
							struct v4l2_format *fmt = arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (fmt->type != video->queue.type)
 | 
							if (fmt->type != video->queue.queue.type)
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return uvc_v4l2_set_format(video, fmt);
 | 
							return uvc_v4l2_set_format(video, fmt);
 | 
				
			||||||
| 
						 | 
					@ -213,16 +209,13 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		struct v4l2_requestbuffers *rb = arg;
 | 
							struct v4l2_requestbuffers *rb = arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (rb->type != video->queue.type ||
 | 
							if (rb->type != video->queue.queue.type)
 | 
				
			||||||
		    rb->memory != V4L2_MEMORY_MMAP)
 | 
					 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = uvc_alloc_buffers(&video->queue, rb->count,
 | 
							ret = uvc_alloc_buffers(&video->queue, rb);
 | 
				
			||||||
					video->imagesize);
 | 
					 | 
				
			||||||
		if (ret < 0)
 | 
							if (ret < 0)
 | 
				
			||||||
			return ret;
 | 
								return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		rb->count = ret;
 | 
					 | 
				
			||||||
		ret = 0;
 | 
							ret = 0;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -231,9 +224,6 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		struct v4l2_buffer *buf = arg;
 | 
							struct v4l2_buffer *buf = arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (buf->type != video->queue.type)
 | 
					 | 
				
			||||||
			return -EINVAL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return uvc_query_buffer(&video->queue, buf);
 | 
							return uvc_query_buffer(&video->queue, buf);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -251,24 +241,36 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int *type = arg;
 | 
							int *type = arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (*type != video->queue.type)
 | 
							if (*type != video->queue.queue.type)
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return uvc_video_enable(video, 1);
 | 
							/* Enable UVC video. */
 | 
				
			||||||
 | 
							ret = uvc_video_enable(video, 1);
 | 
				
			||||||
 | 
							if (ret < 0)
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Complete the alternate setting selection setup phase now that
 | 
				
			||||||
 | 
							 * userspace is ready to provide video frames.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							uvc_function_setup_continue(uvc);
 | 
				
			||||||
 | 
							uvc->state = UVC_STATE_STREAMING;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case VIDIOC_STREAMOFF:
 | 
						case VIDIOC_STREAMOFF:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int *type = arg;
 | 
							int *type = arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (*type != video->queue.type)
 | 
							if (*type != video->queue.queue.type)
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return uvc_video_enable(video, 0);
 | 
							return uvc_video_enable(video, 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Events */
 | 
						/* Events */
 | 
				
			||||||
        case VIDIOC_DQEVENT:
 | 
						case VIDIOC_DQEVENT:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		struct v4l2_event *event = arg;
 | 
							struct v4l2_event *event = arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -333,18 +335,22 @@ uvc_v4l2_poll(struct file *file, poll_table *wait)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct video_device *vdev = video_devdata(file);
 | 
						struct video_device *vdev = video_devdata(file);
 | 
				
			||||||
	struct uvc_device *uvc = video_get_drvdata(vdev);
 | 
						struct uvc_device *uvc = video_get_drvdata(vdev);
 | 
				
			||||||
	struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
 | 
					 | 
				
			||||||
	unsigned int mask = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	poll_wait(file, &handle->vfh.wait, wait);
 | 
						return uvc_queue_poll(&uvc->video.queue, file, wait);
 | 
				
			||||||
	if (v4l2_event_pending(&handle->vfh))
 | 
					 | 
				
			||||||
		mask |= POLLPRI;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mask |= uvc_queue_poll(&uvc->video.queue, file, wait);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return mask;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CONFIG_MMU
 | 
				
			||||||
 | 
					static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
 | 
				
			||||||
 | 
							unsigned long addr, unsigned long len, unsigned long pgoff,
 | 
				
			||||||
 | 
							unsigned long flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct video_device *vdev = video_devdata(file);
 | 
				
			||||||
 | 
						struct uvc_device *uvc = video_get_drvdata(vdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return uvc_queue_get_unmapped_area(&uvc->video.queue, pgoff);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct v4l2_file_operations uvc_v4l2_fops = {
 | 
					static struct v4l2_file_operations uvc_v4l2_fops = {
 | 
				
			||||||
	.owner		= THIS_MODULE,
 | 
						.owner		= THIS_MODULE,
 | 
				
			||||||
	.open		= uvc_v4l2_open,
 | 
						.open		= uvc_v4l2_open,
 | 
				
			||||||
| 
						 | 
					@ -352,5 +358,8 @@ static struct v4l2_file_operations uvc_v4l2_fops = {
 | 
				
			||||||
	.ioctl		= uvc_v4l2_ioctl,
 | 
						.ioctl		= uvc_v4l2_ioctl,
 | 
				
			||||||
	.mmap		= uvc_v4l2_mmap,
 | 
						.mmap		= uvc_v4l2_mmap,
 | 
				
			||||||
	.poll		= uvc_v4l2_poll,
 | 
						.poll		= uvc_v4l2_poll,
 | 
				
			||||||
 | 
					#ifndef CONFIG_MMU
 | 
				
			||||||
 | 
						.get_unmapped_area = uvc_v4l2_get_unmapped_area,
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,7 @@ uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf,
 | 
				
			||||||
	data[0] = 2;
 | 
						data[0] = 2;
 | 
				
			||||||
	data[1] = UVC_STREAM_EOH | video->fid;
 | 
						data[1] = UVC_STREAM_EOH | video->fid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (buf->buf.bytesused - video->queue.buf_used <= len - 2)
 | 
						if (buf->bytesused - video->queue.buf_used <= len - 2)
 | 
				
			||||||
		data[1] |= UVC_STREAM_EOF;
 | 
							data[1] |= UVC_STREAM_EOF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 2;
 | 
						return 2;
 | 
				
			||||||
| 
						 | 
					@ -47,8 +47,8 @@ uvc_video_encode_data(struct uvc_video *video, struct uvc_buffer *buf,
 | 
				
			||||||
	void *mem;
 | 
						void *mem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Copy video data to the USB buffer. */
 | 
						/* Copy video data to the USB buffer. */
 | 
				
			||||||
	mem = queue->mem + buf->buf.m.offset + queue->buf_used;
 | 
						mem = buf->mem + queue->buf_used;
 | 
				
			||||||
	nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used);
 | 
						nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(data, mem, nbytes);
 | 
						memcpy(data, mem, nbytes);
 | 
				
			||||||
	queue->buf_used += nbytes;
 | 
						queue->buf_used += nbytes;
 | 
				
			||||||
| 
						 | 
					@ -82,7 +82,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
 | 
				
			||||||
	req->length = video->req_size - len;
 | 
						req->length = video->req_size - len;
 | 
				
			||||||
	req->zero = video->payload_size == video->max_payload_size;
 | 
						req->zero = video->payload_size == video->max_payload_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (buf->buf.bytesused == video->queue.buf_used) {
 | 
						if (buf->bytesused == video->queue.buf_used) {
 | 
				
			||||||
		video->queue.buf_used = 0;
 | 
							video->queue.buf_used = 0;
 | 
				
			||||||
		buf->state = UVC_BUF_STATE_DONE;
 | 
							buf->state = UVC_BUF_STATE_DONE;
 | 
				
			||||||
		uvc_queue_next_buffer(&video->queue, buf);
 | 
							uvc_queue_next_buffer(&video->queue, buf);
 | 
				
			||||||
| 
						 | 
					@ -92,7 +92,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (video->payload_size == video->max_payload_size ||
 | 
						if (video->payload_size == video->max_payload_size ||
 | 
				
			||||||
	    buf->buf.bytesused == video->queue.buf_used)
 | 
						    buf->bytesused == video->queue.buf_used)
 | 
				
			||||||
		video->payload_size = 0;
 | 
							video->payload_size = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -115,7 +115,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req->length = video->req_size - len;
 | 
						req->length = video->req_size - len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (buf->buf.bytesused == video->queue.buf_used) {
 | 
						if (buf->bytesused == video->queue.buf_used) {
 | 
				
			||||||
		video->queue.buf_used = 0;
 | 
							video->queue.buf_used = 0;
 | 
				
			||||||
		buf->state = UVC_BUF_STATE_DONE;
 | 
							buf->state = UVC_BUF_STATE_DONE;
 | 
				
			||||||
		uvc_queue_next_buffer(&video->queue, buf);
 | 
							uvc_queue_next_buffer(&video->queue, buf);
 | 
				
			||||||
| 
						 | 
					@ -161,6 +161,7 @@ static void
 | 
				
			||||||
uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
 | 
					uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct uvc_video *video = req->context;
 | 
						struct uvc_video *video = req->context;
 | 
				
			||||||
 | 
						struct uvc_video_queue *queue = &video->queue;
 | 
				
			||||||
	struct uvc_buffer *buf;
 | 
						struct uvc_buffer *buf;
 | 
				
			||||||
	unsigned long flags;
 | 
						unsigned long flags;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					@ -169,13 +170,15 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
 | 
				
			||||||
	case 0:
 | 
						case 0:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case -ESHUTDOWN:
 | 
						case -ESHUTDOWN:	/* disconnect from host. */
 | 
				
			||||||
		printk(KERN_INFO "VS request cancelled.\n");
 | 
							printk(KERN_INFO "VS request cancelled.\n");
 | 
				
			||||||
 | 
							uvc_queue_cancel(queue, 1);
 | 
				
			||||||
		goto requeue;
 | 
							goto requeue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		printk(KERN_INFO "VS request completed with status %d.\n",
 | 
							printk(KERN_INFO "VS request completed with status %d.\n",
 | 
				
			||||||
			req->status);
 | 
								req->status);
 | 
				
			||||||
 | 
							uvc_queue_cancel(queue, 0);
 | 
				
			||||||
		goto requeue;
 | 
							goto requeue;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -229,13 +232,18 @@ uvc_video_free_requests(struct uvc_video *video)
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
uvc_video_alloc_requests(struct uvc_video *video)
 | 
					uvc_video_alloc_requests(struct uvc_video *video)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						unsigned int req_size;
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
	int ret = -ENOMEM;
 | 
						int ret = -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BUG_ON(video->req_size);
 | 
						BUG_ON(video->req_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req_size = video->ep->maxpacket
 | 
				
			||||||
 | 
							 * max_t(unsigned int, video->ep->maxburst, 1)
 | 
				
			||||||
 | 
							 * (video->ep->mult + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
 | 
						for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
 | 
				
			||||||
		video->req_buffer[i] = kmalloc(video->ep->maxpacket, GFP_KERNEL);
 | 
							video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);
 | 
				
			||||||
		if (video->req_buffer[i] == NULL)
 | 
							if (video->req_buffer[i] == NULL)
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -245,14 +253,14 @@ uvc_video_alloc_requests(struct uvc_video *video)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		video->req[i]->buf = video->req_buffer[i];
 | 
							video->req[i]->buf = video->req_buffer[i];
 | 
				
			||||||
		video->req[i]->length = 0;
 | 
							video->req[i]->length = 0;
 | 
				
			||||||
		video->req[i]->dma = DMA_ADDR_INVALID;
 | 
					 | 
				
			||||||
		video->req[i]->complete = uvc_video_complete;
 | 
							video->req[i]->complete = uvc_video_complete;
 | 
				
			||||||
		video->req[i]->context = video;
 | 
							video->req[i]->context = video;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		list_add_tail(&video->req[i]->list, &video->req_free);
 | 
							list_add_tail(&video->req[i]->list, &video->req_free);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	video->req_size = video->ep->maxpacket;
 | 
						video->req_size = req_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
error:
 | 
					error:
 | 
				
			||||||
| 
						 | 
					@ -309,7 +317,8 @@ uvc_video_pump(struct uvc_video *video)
 | 
				
			||||||
		video->encode(req, video, buf);
 | 
							video->encode(req, video, buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Queue the USB request */
 | 
							/* Queue the USB request */
 | 
				
			||||||
		if ((ret = usb_ep_queue(video->ep, req, GFP_KERNEL)) < 0) {
 | 
							ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
 | 
				
			||||||
 | 
							if (ret < 0) {
 | 
				
			||||||
			printk(KERN_INFO "Failed to queue request (%d)\n", ret);
 | 
								printk(KERN_INFO "Failed to queue request (%d)\n", ret);
 | 
				
			||||||
			usb_ep_set_halt(video->ep);
 | 
								usb_ep_set_halt(video->ep);
 | 
				
			||||||
			spin_unlock_irqrestore(&video->queue.irqlock, flags);
 | 
								spin_unlock_irqrestore(&video->queue.irqlock, flags);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -180,6 +180,7 @@ config USB_EHCI_TEGRA
 | 
				
			||||||
       boolean "NVIDIA Tegra HCD support"
 | 
					       boolean "NVIDIA Tegra HCD support"
 | 
				
			||||||
       depends on USB_EHCI_HCD && ARCH_TEGRA
 | 
					       depends on USB_EHCI_HCD && ARCH_TEGRA
 | 
				
			||||||
       select USB_EHCI_ROOT_HUB_TT
 | 
					       select USB_EHCI_ROOT_HUB_TT
 | 
				
			||||||
 | 
					       select USB_PHY
 | 
				
			||||||
       help
 | 
					       help
 | 
				
			||||||
         This driver enables support for the internal USB Host Controllers
 | 
					         This driver enables support for the internal USB Host Controllers
 | 
				
			||||||
         found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
 | 
					         found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
 | 
				
			||||||
| 
						 | 
					@ -301,7 +302,6 @@ config USB_OHCI_HCD
 | 
				
			||||||
	tristate "OHCI HCD support"
 | 
						tristate "OHCI HCD support"
 | 
				
			||||||
	depends on USB && USB_ARCH_HAS_OHCI
 | 
						depends on USB && USB_ARCH_HAS_OHCI
 | 
				
			||||||
	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
 | 
						select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
 | 
				
			||||||
	select USB_OTG_UTILS if ARCH_OMAP
 | 
					 | 
				
			||||||
	depends on USB_ISP1301 || !ARCH_LPC32XX
 | 
						depends on USB_ISP1301 || !ARCH_LPC32XX
 | 
				
			||||||
	---help---
 | 
						---help---
 | 
				
			||||||
	  The Open Host Controller Interface (OHCI) is a standard for accessing
 | 
						  The Open Host Controller Interface (OHCI) is a standard for accessing
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -145,7 +145,7 @@ static int ehci_msm_probe(struct platform_device *pdev)
 | 
				
			||||||
	 * management.
 | 
						 * management.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 | 
						phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 | 
				
			||||||
	if (IS_ERR_OR_NULL(phy)) {
 | 
						if (IS_ERR(phy)) {
 | 
				
			||||||
		dev_err(&pdev->dev, "unable to find transceiver\n");
 | 
							dev_err(&pdev->dev, "unable to find transceiver\n");
 | 
				
			||||||
		ret = -ENODEV;
 | 
							ret = -ENODEV;
 | 
				
			||||||
		goto put_hcd;
 | 
							goto put_hcd;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,25 +33,17 @@ struct ehci_hcd_mv {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct mv_usb_platform_data *pdata;
 | 
						struct mv_usb_platform_data *pdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* clock source and total clock number */
 | 
						struct clk *clk;
 | 
				
			||||||
	unsigned int clknum;
 | 
					 | 
				
			||||||
	struct clk *clk[0];
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)
 | 
					static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int i;
 | 
						clk_prepare_enable(ehci_mv->clk);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < ehci_mv->clknum; i++)
 | 
					 | 
				
			||||||
		clk_prepare_enable(ehci_mv->clk[i]);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)
 | 
					static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int i;
 | 
						clk_disable_unprepare(ehci_mv->clk);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < ehci_mv->clknum; i++)
 | 
					 | 
				
			||||||
		clk_disable_unprepare(ehci_mv->clk[i]);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
 | 
					static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
 | 
				
			||||||
| 
						 | 
					@ -144,9 +136,8 @@ static int mv_ehci_probe(struct platform_device *pdev)
 | 
				
			||||||
	struct ehci_hcd *ehci;
 | 
						struct ehci_hcd *ehci;
 | 
				
			||||||
	struct ehci_hcd_mv *ehci_mv;
 | 
						struct ehci_hcd_mv *ehci_mv;
 | 
				
			||||||
	struct resource *r;
 | 
						struct resource *r;
 | 
				
			||||||
	int clk_i, retval = -ENODEV;
 | 
						int retval = -ENODEV;
 | 
				
			||||||
	u32 offset;
 | 
						u32 offset;
 | 
				
			||||||
	size_t size;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!pdata) {
 | 
						if (!pdata) {
 | 
				
			||||||
		dev_err(&pdev->dev, "missing platform_data\n");
 | 
							dev_err(&pdev->dev, "missing platform_data\n");
 | 
				
			||||||
| 
						 | 
					@ -160,8 +151,7 @@ static int mv_ehci_probe(struct platform_device *pdev)
 | 
				
			||||||
	if (!hcd)
 | 
						if (!hcd)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum;
 | 
						ehci_mv = devm_kzalloc(&pdev->dev, sizeof(*ehci_mv), GFP_KERNEL);
 | 
				
			||||||
	ehci_mv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 | 
					 | 
				
			||||||
	if (ehci_mv == NULL) {
 | 
						if (ehci_mv == NULL) {
 | 
				
			||||||
		dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n");
 | 
							dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n");
 | 
				
			||||||
		retval = -ENOMEM;
 | 
							retval = -ENOMEM;
 | 
				
			||||||
| 
						 | 
					@ -172,16 +162,11 @@ static int mv_ehci_probe(struct platform_device *pdev)
 | 
				
			||||||
	ehci_mv->pdata = pdata;
 | 
						ehci_mv->pdata = pdata;
 | 
				
			||||||
	ehci_mv->hcd = hcd;
 | 
						ehci_mv->hcd = hcd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ehci_mv->clknum = pdata->clknum;
 | 
						ehci_mv->clk = devm_clk_get(&pdev->dev, NULL);
 | 
				
			||||||
	for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) {
 | 
						if (IS_ERR(ehci_mv->clk)) {
 | 
				
			||||||
		ehci_mv->clk[clk_i] =
 | 
							dev_err(&pdev->dev, "error getting clock\n");
 | 
				
			||||||
		    devm_clk_get(&pdev->dev, pdata->clkname[clk_i]);
 | 
							retval = PTR_ERR(ehci_mv->clk);
 | 
				
			||||||
		if (IS_ERR(ehci_mv->clk[clk_i])) {
 | 
							goto err_clear_drvdata;
 | 
				
			||||||
			dev_err(&pdev->dev, "error get clck \"%s\"\n",
 | 
					 | 
				
			||||||
				pdata->clkname[clk_i]);
 | 
					 | 
				
			||||||
			retval = PTR_ERR(ehci_mv->clk[clk_i]);
 | 
					 | 
				
			||||||
			goto err_clear_drvdata;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs");
 | 
						r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs");
 | 
				
			||||||
| 
						 | 
					@ -240,12 +225,16 @@ static int mv_ehci_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ehci_mv->mode = pdata->mode;
 | 
						ehci_mv->mode = pdata->mode;
 | 
				
			||||||
	if (ehci_mv->mode == MV_USB_MODE_OTG) {
 | 
						if (ehci_mv->mode == MV_USB_MODE_OTG) {
 | 
				
			||||||
#ifdef CONFIG_USB_OTG_UTILS
 | 
					 | 
				
			||||||
		ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 | 
							ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 | 
				
			||||||
		if (IS_ERR_OR_NULL(ehci_mv->otg)) {
 | 
							if (IS_ERR(ehci_mv->otg)) {
 | 
				
			||||||
			dev_err(&pdev->dev,
 | 
								retval = PTR_ERR(ehci_mv->otg);
 | 
				
			||||||
				"unable to find transceiver\n");
 | 
					
 | 
				
			||||||
			retval = -ENODEV;
 | 
								if (retval == -ENXIO)
 | 
				
			||||||
 | 
									dev_info(&pdev->dev, "MV_USB_MODE_OTG "
 | 
				
			||||||
 | 
											"must have CONFIG_USB_PHY enabled\n");
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									dev_err(&pdev->dev,
 | 
				
			||||||
 | 
											"unable to find transceiver\n");
 | 
				
			||||||
			goto err_disable_clk;
 | 
								goto err_disable_clk;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -258,11 +247,6 @@ static int mv_ehci_probe(struct platform_device *pdev)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		/* otg will enable clock before use as host */
 | 
							/* otg will enable clock before use as host */
 | 
				
			||||||
		mv_ehci_disable(ehci_mv);
 | 
							mv_ehci_disable(ehci_mv);
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
		dev_info(&pdev->dev, "MV_USB_MODE_OTG "
 | 
					 | 
				
			||||||
			 "must have CONFIG_USB_OTG_UTILS enabled\n");
 | 
					 | 
				
			||||||
		goto err_disable_clk;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		if (pdata->set_vbus)
 | 
							if (pdata->set_vbus)
 | 
				
			||||||
			pdata->set_vbus(1);
 | 
								pdata->set_vbus(1);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,7 +140,7 @@ static int s5p_ehci_probe(struct platform_device *pdev)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 | 
						phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 | 
				
			||||||
	if (IS_ERR_OR_NULL(phy)) {
 | 
						if (IS_ERR(phy)) {
 | 
				
			||||||
		/* Fallback to pdata */
 | 
							/* Fallback to pdata */
 | 
				
			||||||
		if (!pdata) {
 | 
							if (!pdata) {
 | 
				
			||||||
			dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
 | 
								dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -773,16 +773,14 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 | 
				
			||||||
		goto fail_phy;
 | 
							goto fail_phy;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_USB_OTG_UTILS
 | 
					 | 
				
			||||||
	if (pdata->operating_mode == TEGRA_USB_OTG) {
 | 
						if (pdata->operating_mode == TEGRA_USB_OTG) {
 | 
				
			||||||
		tegra->transceiver =
 | 
							tegra->transceiver =
 | 
				
			||||||
			devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 | 
								devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 | 
				
			||||||
		if (!IS_ERR_OR_NULL(tegra->transceiver))
 | 
							if (!IS_ERR(tegra->transceiver))
 | 
				
			||||||
			otg_set_host(tegra->transceiver->otg, &hcd->self);
 | 
								otg_set_host(tegra->transceiver->otg, &hcd->self);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		tegra->transceiver = ERR_PTR(-ENODEV);
 | 
							tegra->transceiver = ERR_PTR(-ENODEV);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 | 
						err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 | 
				
			||||||
	if (err) {
 | 
						if (err) {
 | 
				
			||||||
| 
						 | 
					@ -801,10 +799,8 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fail:
 | 
					fail:
 | 
				
			||||||
#ifdef CONFIG_USB_OTG_UTILS
 | 
						if (!IS_ERR(tegra->transceiver))
 | 
				
			||||||
	if (!IS_ERR_OR_NULL(tegra->transceiver))
 | 
					 | 
				
			||||||
		otg_set_host(tegra->transceiver->otg, NULL);
 | 
							otg_set_host(tegra->transceiver->otg, NULL);
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
fail_phy:
 | 
					fail_phy:
 | 
				
			||||||
	usb_phy_shutdown(hcd->phy);
 | 
						usb_phy_shutdown(hcd->phy);
 | 
				
			||||||
fail_io:
 | 
					fail_io:
 | 
				
			||||||
| 
						 | 
					@ -823,10 +819,8 @@ static int tegra_ehci_remove(struct platform_device *pdev)
 | 
				
			||||||
	pm_runtime_disable(&pdev->dev);
 | 
						pm_runtime_disable(&pdev->dev);
 | 
				
			||||||
	pm_runtime_put_noidle(&pdev->dev);
 | 
						pm_runtime_put_noidle(&pdev->dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_USB_OTG_UTILS
 | 
						if (!IS_ERR(tegra->transceiver))
 | 
				
			||||||
	if (!IS_ERR_OR_NULL(tegra->transceiver))
 | 
					 | 
				
			||||||
		otg_set_host(tegra->transceiver->otg, NULL);
 | 
							otg_set_host(tegra->transceiver->otg, NULL);
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	usb_phy_shutdown(hcd->phy);
 | 
						usb_phy_shutdown(hcd->phy);
 | 
				
			||||||
	usb_remove_hcd(hcd);
 | 
						usb_remove_hcd(hcd);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -128,7 +128,7 @@ static int exynos_ohci_probe(struct platform_device *pdev)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 | 
						phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 | 
				
			||||||
	if (IS_ERR_OR_NULL(phy)) {
 | 
						if (IS_ERR(phy)) {
 | 
				
			||||||
		/* Fallback to pdata */
 | 
							/* Fallback to pdata */
 | 
				
			||||||
		if (!pdata) {
 | 
							if (!pdata) {
 | 
				
			||||||
			dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
 | 
								dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,6 @@
 | 
				
			||||||
config USB_MUSB_HDRC
 | 
					config USB_MUSB_HDRC
 | 
				
			||||||
	tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
 | 
						tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
 | 
				
			||||||
	depends on USB && USB_GADGET
 | 
						depends on USB && USB_GADGET
 | 
				
			||||||
	select USB_OTG_UTILS
 | 
					 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  Say Y here if your system has a dual role high speed USB
 | 
						  Say Y here if your system has a dual role high speed USB
 | 
				
			||||||
	  controller based on the Mentor Graphics silicon IP.  Then
 | 
						  controller based on the Mentor Graphics silicon IP.  Then
 | 
				
			||||||
| 
						 | 
					@ -34,10 +33,12 @@ choice
 | 
				
			||||||
config USB_MUSB_DAVINCI
 | 
					config USB_MUSB_DAVINCI
 | 
				
			||||||
	tristate "DaVinci"
 | 
						tristate "DaVinci"
 | 
				
			||||||
	depends on ARCH_DAVINCI_DMx
 | 
						depends on ARCH_DAVINCI_DMx
 | 
				
			||||||
 | 
						depends on BROKEN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config USB_MUSB_DA8XX
 | 
					config USB_MUSB_DA8XX
 | 
				
			||||||
	tristate "DA8xx/OMAP-L1x"
 | 
						tristate "DA8xx/OMAP-L1x"
 | 
				
			||||||
	depends on ARCH_DAVINCI_DA8XX
 | 
						depends on ARCH_DAVINCI_DA8XX
 | 
				
			||||||
 | 
						depends on BROKEN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config USB_MUSB_TUSB6010
 | 
					config USB_MUSB_TUSB6010
 | 
				
			||||||
	tristate "TUSB6010"
 | 
						tristate "TUSB6010"
 | 
				
			||||||
| 
						 | 
					@ -53,7 +54,6 @@ config USB_MUSB_AM35X
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config USB_MUSB_DSPS
 | 
					config USB_MUSB_DSPS
 | 
				
			||||||
	tristate "TI DSPS platforms"
 | 
						tristate "TI DSPS platforms"
 | 
				
			||||||
	depends on SOC_TI81XX || SOC_AM33XX
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
config USB_MUSB_BLACKFIN
 | 
					config USB_MUSB_BLACKFIN
 | 
				
			||||||
	tristate "Blackfin"
 | 
						tristate "Blackfin"
 | 
				
			||||||
| 
						 | 
					@ -61,12 +61,12 @@ config USB_MUSB_BLACKFIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config USB_MUSB_UX500
 | 
					config USB_MUSB_UX500
 | 
				
			||||||
	tristate "U8500 and U5500"
 | 
						tristate "U8500 and U5500"
 | 
				
			||||||
	depends on (ARCH_U8500 && AB8500_USB)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
endchoice
 | 
					endchoice
 | 
				
			||||||
 | 
					
 | 
				
			||||||
choice
 | 
					choice
 | 
				
			||||||
	prompt 'MUSB DMA mode'
 | 
						prompt 'MUSB DMA mode'
 | 
				
			||||||
 | 
						default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM
 | 
				
			||||||
	default USB_UX500_DMA if USB_MUSB_UX500
 | 
						default USB_UX500_DMA if USB_MUSB_UX500
 | 
				
			||||||
	default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
 | 
						default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
 | 
				
			||||||
	default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI
 | 
						default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,7 +149,7 @@ static void otg_timer(unsigned long _musb)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	devctl = musb_readb(mregs, MUSB_DEVCTL);
 | 
						devctl = musb_readb(mregs, MUSB_DEVCTL);
 | 
				
			||||||
	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
 | 
						dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
 | 
				
			||||||
		otg_state_string(musb->xceiv->state));
 | 
							usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&musb->lock, flags);
 | 
						spin_lock_irqsave(&musb->lock, flags);
 | 
				
			||||||
	switch (musb->xceiv->state) {
 | 
						switch (musb->xceiv->state) {
 | 
				
			||||||
| 
						 | 
					@ -195,7 +195,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
 | 
				
			||||||
	if (musb->is_active || (musb->a_wait_bcon == 0 &&
 | 
						if (musb->is_active || (musb->a_wait_bcon == 0 &&
 | 
				
			||||||
				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 | 
									musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 | 
				
			||||||
		dev_dbg(musb->controller, "%s active, deleting timer\n",
 | 
							dev_dbg(musb->controller, "%s active, deleting timer\n",
 | 
				
			||||||
			otg_state_string(musb->xceiv->state));
 | 
								usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
		del_timer(&otg_workaround);
 | 
							del_timer(&otg_workaround);
 | 
				
			||||||
		last_timer = jiffies;
 | 
							last_timer = jiffies;
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -208,7 +208,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
 | 
				
			||||||
	last_timer = timeout;
 | 
						last_timer = timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
 | 
						dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
 | 
				
			||||||
		otg_state_string(musb->xceiv->state),
 | 
							usb_otg_state_string(musb->xceiv->state),
 | 
				
			||||||
		jiffies_to_msecs(timeout - jiffies));
 | 
							jiffies_to_msecs(timeout - jiffies));
 | 
				
			||||||
	mod_timer(&otg_workaround, timeout);
 | 
						mod_timer(&otg_workaround, timeout);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -298,7 +298,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
 | 
				
			||||||
		/* NOTE: this must complete power-on within 100 ms. */
 | 
							/* NOTE: this must complete power-on within 100 ms. */
 | 
				
			||||||
		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 | 
							dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 | 
				
			||||||
				drvvbus ? "on" : "off",
 | 
									drvvbus ? "on" : "off",
 | 
				
			||||||
				otg_state_string(musb->xceiv->state),
 | 
									usb_otg_state_string(musb->xceiv->state),
 | 
				
			||||||
				err ? " ERROR" : "",
 | 
									err ? " ERROR" : "",
 | 
				
			||||||
				devctl);
 | 
									devctl);
 | 
				
			||||||
		ret = IRQ_HANDLED;
 | 
							ret = IRQ_HANDLED;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -280,13 +280,13 @@ static void musb_conn_timer_handler(unsigned long _musb)
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		dev_dbg(musb->controller, "%s state not handled\n",
 | 
							dev_dbg(musb->controller, "%s state not handled\n",
 | 
				
			||||||
			otg_state_string(musb->xceiv->state));
 | 
								usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	spin_unlock_irqrestore(&musb->lock, flags);
 | 
						spin_unlock_irqrestore(&musb->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_dbg(musb->controller, "state is %s\n",
 | 
						dev_dbg(musb->controller, "state is %s\n",
 | 
				
			||||||
		otg_state_string(musb->xceiv->state));
 | 
							usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void bfin_musb_enable(struct musb *musb)
 | 
					static void bfin_musb_enable(struct musb *musb)
 | 
				
			||||||
| 
						 | 
					@ -307,7 +307,7 @@ static void bfin_musb_set_vbus(struct musb *musb, int is_on)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_dbg(musb->controller, "VBUS %s, devctl %02x "
 | 
						dev_dbg(musb->controller, "VBUS %s, devctl %02x "
 | 
				
			||||||
		/* otg %3x conf %08x prcm %08x */ "\n",
 | 
							/* otg %3x conf %08x prcm %08x */ "\n",
 | 
				
			||||||
		otg_state_string(musb->xceiv->state),
 | 
							usb_otg_state_string(musb->xceiv->state),
 | 
				
			||||||
		musb_readb(musb->mregs, MUSB_DEVCTL));
 | 
							musb_readb(musb->mregs, MUSB_DEVCTL));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -435,7 +435,6 @@ cppi_rndis_update(struct cppi_channel *c, int is_rx,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_USB_MUSB_DEBUG
 | 
					 | 
				
			||||||
static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
 | 
					static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	pr_debug("RXBD/%s %08x: "
 | 
						pr_debug("RXBD/%s %08x: "
 | 
				
			||||||
| 
						 | 
					@ -444,21 +443,16 @@ static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
 | 
				
			||||||
			bd->hw_next, bd->hw_bufp, bd->hw_off_len,
 | 
								bd->hw_next, bd->hw_bufp, bd->hw_off_len,
 | 
				
			||||||
			bd->hw_options);
 | 
								bd->hw_options);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void cppi_dump_rxq(int level, const char *tag, struct cppi_channel *rx)
 | 
					static void cppi_dump_rxq(int level, const char *tag, struct cppi_channel *rx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#ifdef CONFIG_USB_MUSB_DEBUG
 | 
					 | 
				
			||||||
	struct cppi_descriptor	*bd;
 | 
						struct cppi_descriptor	*bd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!_dbg_level(level))
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	cppi_dump_rx(level, rx, tag);
 | 
						cppi_dump_rx(level, rx, tag);
 | 
				
			||||||
	if (rx->last_processed)
 | 
						if (rx->last_processed)
 | 
				
			||||||
		cppi_dump_rxbd("last", rx->last_processed);
 | 
							cppi_dump_rxbd("last", rx->last_processed);
 | 
				
			||||||
	for (bd = rx->head; bd; bd = bd->next)
 | 
						for (bd = rx->head; bd; bd = bd->next)
 | 
				
			||||||
		cppi_dump_rxbd("active", bd);
 | 
							cppi_dump_rxbd("active", bd);
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -784,6 +778,7 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
 | 
				
			||||||
	void __iomem		*tibase = musb->ctrl_base;
 | 
						void __iomem		*tibase = musb->ctrl_base;
 | 
				
			||||||
	int			is_rndis = 0;
 | 
						int			is_rndis = 0;
 | 
				
			||||||
	struct cppi_rx_stateram	__iomem *rx_ram = rx->state_ram;
 | 
						struct cppi_rx_stateram	__iomem *rx_ram = rx->state_ram;
 | 
				
			||||||
 | 
						struct cppi_descriptor	*d;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (onepacket) {
 | 
						if (onepacket) {
 | 
				
			||||||
		/* almost every USB driver, host or peripheral side */
 | 
							/* almost every USB driver, host or peripheral side */
 | 
				
			||||||
| 
						 | 
					@ -897,14 +892,8 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
 | 
				
			||||||
	bd->hw_options |= CPPI_SOP_SET;
 | 
						bd->hw_options |= CPPI_SOP_SET;
 | 
				
			||||||
	tail->hw_options |= CPPI_EOP_SET;
 | 
						tail->hw_options |= CPPI_EOP_SET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_USB_MUSB_DEBUG
 | 
						for (d = rx->head; d; d = d->next)
 | 
				
			||||||
	if (_dbg_level(5)) {
 | 
							cppi_dump_rxbd("S", d);
 | 
				
			||||||
		struct cppi_descriptor	*d;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (d = rx->head; d; d = d->next)
 | 
					 | 
				
			||||||
			cppi_dump_rxbd("S", d);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* in case the preceding transfer left some state... */
 | 
						/* in case the preceding transfer left some state... */
 | 
				
			||||||
	tail = rx->last_processed;
 | 
						tail = rx->last_processed;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -198,7 +198,7 @@ static void otg_timer(unsigned long _musb)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	devctl = musb_readb(mregs, MUSB_DEVCTL);
 | 
						devctl = musb_readb(mregs, MUSB_DEVCTL);
 | 
				
			||||||
	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
 | 
						dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
 | 
				
			||||||
		otg_state_string(musb->xceiv->state));
 | 
							usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&musb->lock, flags);
 | 
						spin_lock_irqsave(&musb->lock, flags);
 | 
				
			||||||
	switch (musb->xceiv->state) {
 | 
						switch (musb->xceiv->state) {
 | 
				
			||||||
| 
						 | 
					@ -267,7 +267,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
 | 
				
			||||||
	if (musb->is_active || (musb->a_wait_bcon == 0 &&
 | 
						if (musb->is_active || (musb->a_wait_bcon == 0 &&
 | 
				
			||||||
				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 | 
									musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 | 
				
			||||||
		dev_dbg(musb->controller, "%s active, deleting timer\n",
 | 
							dev_dbg(musb->controller, "%s active, deleting timer\n",
 | 
				
			||||||
			otg_state_string(musb->xceiv->state));
 | 
								usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
		del_timer(&otg_workaround);
 | 
							del_timer(&otg_workaround);
 | 
				
			||||||
		last_timer = jiffies;
 | 
							last_timer = jiffies;
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -280,7 +280,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
 | 
				
			||||||
	last_timer = timeout;
 | 
						last_timer = timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
 | 
						dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
 | 
				
			||||||
		otg_state_string(musb->xceiv->state),
 | 
							usb_otg_state_string(musb->xceiv->state),
 | 
				
			||||||
		jiffies_to_msecs(timeout - jiffies));
 | 
							jiffies_to_msecs(timeout - jiffies));
 | 
				
			||||||
	mod_timer(&otg_workaround, timeout);
 | 
						mod_timer(&otg_workaround, timeout);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -360,7 +360,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 | 
							dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 | 
				
			||||||
				drvvbus ? "on" : "off",
 | 
									drvvbus ? "on" : "off",
 | 
				
			||||||
				otg_state_string(musb->xceiv->state),
 | 
									usb_otg_state_string(musb->xceiv->state),
 | 
				
			||||||
				err ? " ERROR" : "",
 | 
									err ? " ERROR" : "",
 | 
				
			||||||
				devctl);
 | 
									devctl);
 | 
				
			||||||
		ret = IRQ_HANDLED;
 | 
							ret = IRQ_HANDLED;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -215,7 +215,7 @@ static void otg_timer(unsigned long _musb)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	devctl = musb_readb(mregs, MUSB_DEVCTL);
 | 
						devctl = musb_readb(mregs, MUSB_DEVCTL);
 | 
				
			||||||
	dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl,
 | 
						dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl,
 | 
				
			||||||
		otg_state_string(musb->xceiv->state));
 | 
							usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&musb->lock, flags);
 | 
						spin_lock_irqsave(&musb->lock, flags);
 | 
				
			||||||
	switch (musb->xceiv->state) {
 | 
						switch (musb->xceiv->state) {
 | 
				
			||||||
| 
						 | 
					@ -349,7 +349,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci)
 | 
				
			||||||
		davinci_musb_source_power(musb, drvvbus, 0);
 | 
							davinci_musb_source_power(musb, drvvbus, 0);
 | 
				
			||||||
		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 | 
							dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 | 
				
			||||||
				drvvbus ? "on" : "off",
 | 
									drvvbus ? "on" : "off",
 | 
				
			||||||
				otg_state_string(musb->xceiv->state),
 | 
									usb_otg_state_string(musb->xceiv->state),
 | 
				
			||||||
				err ? " ERROR" : "",
 | 
									err ? " ERROR" : "",
 | 
				
			||||||
				devctl);
 | 
									devctl);
 | 
				
			||||||
		retval = IRQ_HANDLED;
 | 
							retval = IRQ_HANDLED;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -372,13 +372,13 @@ static void musb_otg_timer_func(unsigned long data)
 | 
				
			||||||
	case OTG_STATE_A_SUSPEND:
 | 
						case OTG_STATE_A_SUSPEND:
 | 
				
			||||||
	case OTG_STATE_A_WAIT_BCON:
 | 
						case OTG_STATE_A_WAIT_BCON:
 | 
				
			||||||
		dev_dbg(musb->controller, "HNP: %s timeout\n",
 | 
							dev_dbg(musb->controller, "HNP: %s timeout\n",
 | 
				
			||||||
			otg_state_string(musb->xceiv->state));
 | 
								usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
		musb_platform_set_vbus(musb, 0);
 | 
							musb_platform_set_vbus(musb, 0);
 | 
				
			||||||
		musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
 | 
							musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		dev_dbg(musb->controller, "HNP: Unhandled mode %s\n",
 | 
							dev_dbg(musb->controller, "HNP: Unhandled mode %s\n",
 | 
				
			||||||
			otg_state_string(musb->xceiv->state));
 | 
								usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	musb->ignore_disconnect = 0;
 | 
						musb->ignore_disconnect = 0;
 | 
				
			||||||
	spin_unlock_irqrestore(&musb->lock, flags);
 | 
						spin_unlock_irqrestore(&musb->lock, flags);
 | 
				
			||||||
| 
						 | 
					@ -393,13 +393,14 @@ void musb_hnp_stop(struct musb *musb)
 | 
				
			||||||
	void __iomem	*mbase = musb->mregs;
 | 
						void __iomem	*mbase = musb->mregs;
 | 
				
			||||||
	u8	reg;
 | 
						u8	reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_dbg(musb->controller, "HNP: stop from %s\n", otg_state_string(musb->xceiv->state));
 | 
						dev_dbg(musb->controller, "HNP: stop from %s\n",
 | 
				
			||||||
 | 
								usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (musb->xceiv->state) {
 | 
						switch (musb->xceiv->state) {
 | 
				
			||||||
	case OTG_STATE_A_PERIPHERAL:
 | 
						case OTG_STATE_A_PERIPHERAL:
 | 
				
			||||||
		musb_g_disconnect(musb);
 | 
							musb_g_disconnect(musb);
 | 
				
			||||||
		dev_dbg(musb->controller, "HNP: back to %s\n",
 | 
							dev_dbg(musb->controller, "HNP: back to %s\n",
 | 
				
			||||||
			otg_state_string(musb->xceiv->state));
 | 
								usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case OTG_STATE_B_HOST:
 | 
						case OTG_STATE_B_HOST:
 | 
				
			||||||
		dev_dbg(musb->controller, "HNP: Disabling HR\n");
 | 
							dev_dbg(musb->controller, "HNP: Disabling HR\n");
 | 
				
			||||||
| 
						 | 
					@ -413,7 +414,7 @@ void musb_hnp_stop(struct musb *musb)
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n",
 | 
							dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n",
 | 
				
			||||||
			otg_state_string(musb->xceiv->state));
 | 
								usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -451,7 +452,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (int_usb & MUSB_INTR_RESUME) {
 | 
						if (int_usb & MUSB_INTR_RESUME) {
 | 
				
			||||||
		handled = IRQ_HANDLED;
 | 
							handled = IRQ_HANDLED;
 | 
				
			||||||
		dev_dbg(musb->controller, "RESUME (%s)\n", otg_state_string(musb->xceiv->state));
 | 
							dev_dbg(musb->controller, "RESUME (%s)\n", usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (devctl & MUSB_DEVCTL_HM) {
 | 
							if (devctl & MUSB_DEVCTL_HM) {
 | 
				
			||||||
			void __iomem *mbase = musb->mregs;
 | 
								void __iomem *mbase = musb->mregs;
 | 
				
			||||||
| 
						 | 
					@ -493,7 +494,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				WARNING("bogus %s RESUME (%s)\n",
 | 
									WARNING("bogus %s RESUME (%s)\n",
 | 
				
			||||||
					"host",
 | 
										"host",
 | 
				
			||||||
					otg_state_string(musb->xceiv->state));
 | 
										usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			switch (musb->xceiv->state) {
 | 
								switch (musb->xceiv->state) {
 | 
				
			||||||
| 
						 | 
					@ -522,7 +523,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				WARNING("bogus %s RESUME (%s)\n",
 | 
									WARNING("bogus %s RESUME (%s)\n",
 | 
				
			||||||
					"peripheral",
 | 
										"peripheral",
 | 
				
			||||||
					otg_state_string(musb->xceiv->state));
 | 
										usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -538,7 +539,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n",
 | 
							dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n",
 | 
				
			||||||
			otg_state_string(musb->xceiv->state));
 | 
								usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* IRQ arrives from ID pin sense or (later, if VBUS power
 | 
							/* IRQ arrives from ID pin sense or (later, if VBUS power
 | 
				
			||||||
		 * is removed) SRP.  responses are time critical:
 | 
							 * is removed) SRP.  responses are time critical:
 | 
				
			||||||
| 
						 | 
					@ -602,8 +603,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dev_dbg(musb->controller, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
 | 
							dev_printk(ignore ? KERN_DEBUG : KERN_ERR, musb->controller,
 | 
				
			||||||
				otg_state_string(musb->xceiv->state),
 | 
									"VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
 | 
				
			||||||
 | 
									usb_otg_state_string(musb->xceiv->state),
 | 
				
			||||||
				devctl,
 | 
									devctl,
 | 
				
			||||||
				({ char *s;
 | 
									({ char *s;
 | 
				
			||||||
				switch (devctl & MUSB_DEVCTL_VBUS) {
 | 
									switch (devctl & MUSB_DEVCTL_VBUS) {
 | 
				
			||||||
| 
						 | 
					@ -628,7 +630,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (int_usb & MUSB_INTR_SUSPEND) {
 | 
						if (int_usb & MUSB_INTR_SUSPEND) {
 | 
				
			||||||
		dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n",
 | 
							dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n",
 | 
				
			||||||
			otg_state_string(musb->xceiv->state), devctl);
 | 
								usb_otg_state_string(musb->xceiv->state), devctl);
 | 
				
			||||||
		handled = IRQ_HANDLED;
 | 
							handled = IRQ_HANDLED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch (musb->xceiv->state) {
 | 
							switch (musb->xceiv->state) {
 | 
				
			||||||
| 
						 | 
					@ -745,12 +747,12 @@ b_host:
 | 
				
			||||||
			usb_hcd_resume_root_hub(hcd);
 | 
								usb_hcd_resume_root_hub(hcd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n",
 | 
							dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n",
 | 
				
			||||||
				otg_state_string(musb->xceiv->state), devctl);
 | 
									usb_otg_state_string(musb->xceiv->state), devctl);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {
 | 
						if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {
 | 
				
			||||||
		dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n",
 | 
							dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n",
 | 
				
			||||||
				otg_state_string(musb->xceiv->state),
 | 
									usb_otg_state_string(musb->xceiv->state),
 | 
				
			||||||
				MUSB_MODE(musb), devctl);
 | 
									MUSB_MODE(musb), devctl);
 | 
				
			||||||
		handled = IRQ_HANDLED;
 | 
							handled = IRQ_HANDLED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -787,7 +789,7 @@ b_host:
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			WARNING("unhandled DISCONNECT transition (%s)\n",
 | 
								WARNING("unhandled DISCONNECT transition (%s)\n",
 | 
				
			||||||
				otg_state_string(musb->xceiv->state));
 | 
									usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -813,7 +815,7 @@ b_host:
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			dev_dbg(musb->controller, "BUS RESET as %s\n",
 | 
								dev_dbg(musb->controller, "BUS RESET as %s\n",
 | 
				
			||||||
				otg_state_string(musb->xceiv->state));
 | 
									usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
			switch (musb->xceiv->state) {
 | 
								switch (musb->xceiv->state) {
 | 
				
			||||||
			case OTG_STATE_A_SUSPEND:
 | 
								case OTG_STATE_A_SUSPEND:
 | 
				
			||||||
				/* We need to ignore disconnect on suspend
 | 
									/* We need to ignore disconnect on suspend
 | 
				
			||||||
| 
						 | 
					@ -826,7 +828,7 @@ b_host:
 | 
				
			||||||
			case OTG_STATE_A_WAIT_BCON:	/* OPT TD.4.7-900ms */
 | 
								case OTG_STATE_A_WAIT_BCON:	/* OPT TD.4.7-900ms */
 | 
				
			||||||
				/* never use invalid T(a_wait_bcon) */
 | 
									/* never use invalid T(a_wait_bcon) */
 | 
				
			||||||
				dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n",
 | 
									dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n",
 | 
				
			||||||
					otg_state_string(musb->xceiv->state),
 | 
										usb_otg_state_string(musb->xceiv->state),
 | 
				
			||||||
					TA_WAIT_BCON(musb));
 | 
										TA_WAIT_BCON(musb));
 | 
				
			||||||
				mod_timer(&musb->otg_timer, jiffies
 | 
									mod_timer(&musb->otg_timer, jiffies
 | 
				
			||||||
					+ msecs_to_jiffies(TA_WAIT_BCON(musb)));
 | 
										+ msecs_to_jiffies(TA_WAIT_BCON(musb)));
 | 
				
			||||||
| 
						 | 
					@ -838,7 +840,7 @@ b_host:
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			case OTG_STATE_B_WAIT_ACON:
 | 
								case OTG_STATE_B_WAIT_ACON:
 | 
				
			||||||
				dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n",
 | 
									dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n",
 | 
				
			||||||
					otg_state_string(musb->xceiv->state));
 | 
										usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
				musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
 | 
									musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
 | 
				
			||||||
				musb_g_reset(musb);
 | 
									musb_g_reset(musb);
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
| 
						 | 
					@ -850,7 +852,7 @@ b_host:
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n",
 | 
									dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n",
 | 
				
			||||||
					otg_state_string(musb->xceiv->state));
 | 
										usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1632,7 +1634,7 @@ musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
 | 
				
			||||||
	int ret = -EINVAL;
 | 
						int ret = -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&musb->lock, flags);
 | 
						spin_lock_irqsave(&musb->lock, flags);
 | 
				
			||||||
	ret = sprintf(buf, "%s\n", otg_state_string(musb->xceiv->state));
 | 
						ret = sprintf(buf, "%s\n", usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
	spin_unlock_irqrestore(&musb->lock, flags);
 | 
						spin_unlock_irqrestore(&musb->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
| 
						 | 
					@ -1951,9 +1953,13 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 | 
				
			||||||
		musb_write_ulpi_buscontrol(musb->mregs, busctl);
 | 
							musb_write_ulpi_buscontrol(musb->mregs, busctl);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MUSB_DEV_MODE(musb);
 | 
						if (musb->xceiv->otg->default_a) {
 | 
				
			||||||
	musb->xceiv->otg->default_a = 0;
 | 
							MUSB_HST_MODE(musb);
 | 
				
			||||||
	musb->xceiv->state = OTG_STATE_B_IDLE;
 | 
							musb->xceiv->state = OTG_STATE_A_IDLE;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							MUSB_DEV_MODE(musb);
 | 
				
			||||||
 | 
							musb->xceiv->state = OTG_STATE_B_IDLE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = musb_gadget_setup(musb);
 | 
						status = musb_gadget_setup(musb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2008,7 +2014,6 @@ static int musb_probe(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct device	*dev = &pdev->dev;
 | 
						struct device	*dev = &pdev->dev;
 | 
				
			||||||
	int		irq = platform_get_irq_byname(pdev, "mc");
 | 
						int		irq = platform_get_irq_byname(pdev, "mc");
 | 
				
			||||||
	int		status;
 | 
					 | 
				
			||||||
	struct resource	*iomem;
 | 
						struct resource	*iomem;
 | 
				
			||||||
	void __iomem	*base;
 | 
						void __iomem	*base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2016,24 +2021,17 @@ static int musb_probe(struct platform_device *pdev)
 | 
				
			||||||
	if (!iomem || irq <= 0)
 | 
						if (!iomem || irq <= 0)
 | 
				
			||||||
		return -ENODEV;
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	base = ioremap(iomem->start, resource_size(iomem));
 | 
						base = devm_ioremap_resource(dev, iomem);
 | 
				
			||||||
	if (!base) {
 | 
						if (IS_ERR(base))
 | 
				
			||||||
		dev_err(dev, "ioremap failed\n");
 | 
							return PTR_ERR(base);
 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = musb_init_controller(dev, irq, base);
 | 
						return musb_init_controller(dev, irq, base);
 | 
				
			||||||
	if (status < 0)
 | 
					 | 
				
			||||||
		iounmap(base);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return status;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int musb_remove(struct platform_device *pdev)
 | 
					static int musb_remove(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct device	*dev = &pdev->dev;
 | 
						struct device	*dev = &pdev->dev;
 | 
				
			||||||
	struct musb	*musb = dev_to_musb(dev);
 | 
						struct musb	*musb = dev_to_musb(dev);
 | 
				
			||||||
	void __iomem	*ctrl_base = musb->ctrl_base;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* this gets called on rmmod.
 | 
						/* this gets called on rmmod.
 | 
				
			||||||
	 *  - Host mode: host may still be active
 | 
						 *  - Host mode: host may still be active
 | 
				
			||||||
| 
						 | 
					@ -2044,7 +2042,6 @@ static int musb_remove(struct platform_device *pdev)
 | 
				
			||||||
	musb_shutdown(pdev);
 | 
						musb_shutdown(pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	musb_free(musb);
 | 
						musb_free(musb);
 | 
				
			||||||
	iounmap(ctrl_base);
 | 
					 | 
				
			||||||
	device_init_wakeup(dev, 0);
 | 
						device_init_wakeup(dev, 0);
 | 
				
			||||||
#ifndef CONFIG_MUSB_PIO_ONLY
 | 
					#ifndef CONFIG_MUSB_PIO_ONLY
 | 
				
			||||||
	dma_set_mask(dev, *dev->parent->dma_mask);
 | 
						dma_set_mask(dev, *dev->parent->dma_mask);
 | 
				
			||||||
| 
						 | 
					@ -2293,8 +2290,6 @@ static int __init musb_init(void)
 | 
				
			||||||
	if (usb_disabled())
 | 
						if (usb_disabled())
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n",
 | 
					 | 
				
			||||||
		musb_driver_name);
 | 
					 | 
				
			||||||
	return platform_driver_register(&musb_driver);
 | 
						return platform_driver_register(&musb_driver);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
module_init(musb_init);
 | 
					module_init(musb_init);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,7 @@
 | 
				
			||||||
#include <linux/module.h>
 | 
					#include <linux/module.h>
 | 
				
			||||||
#include <linux/usb/nop-usb-xceiv.h>
 | 
					#include <linux/usb/nop-usb-xceiv.h>
 | 
				
			||||||
#include <linux/platform_data/usb-omap.h>
 | 
					#include <linux/platform_data/usb-omap.h>
 | 
				
			||||||
 | 
					#include <linux/sizes.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/of.h>
 | 
					#include <linux/of.h>
 | 
				
			||||||
#include <linux/of_device.h>
 | 
					#include <linux/of_device.h>
 | 
				
			||||||
| 
						 | 
					@ -224,7 +225,7 @@ static void otg_timer(unsigned long _musb)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	devctl = dsps_readb(mregs, MUSB_DEVCTL);
 | 
						devctl = dsps_readb(mregs, MUSB_DEVCTL);
 | 
				
			||||||
	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
 | 
						dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
 | 
				
			||||||
				otg_state_string(musb->xceiv->state));
 | 
									usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&musb->lock, flags);
 | 
						spin_lock_irqsave(&musb->lock, flags);
 | 
				
			||||||
	switch (musb->xceiv->state) {
 | 
						switch (musb->xceiv->state) {
 | 
				
			||||||
| 
						 | 
					@ -273,7 +274,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
 | 
				
			||||||
	if (musb->is_active || (musb->a_wait_bcon == 0 &&
 | 
						if (musb->is_active || (musb->a_wait_bcon == 0 &&
 | 
				
			||||||
				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 | 
									musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 | 
				
			||||||
		dev_dbg(musb->controller, "%s active, deleting timer\n",
 | 
							dev_dbg(musb->controller, "%s active, deleting timer\n",
 | 
				
			||||||
				otg_state_string(musb->xceiv->state));
 | 
									usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
		del_timer(&glue->timer[pdev->id]);
 | 
							del_timer(&glue->timer[pdev->id]);
 | 
				
			||||||
		glue->last_timer[pdev->id] = jiffies;
 | 
							glue->last_timer[pdev->id] = jiffies;
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -288,7 +289,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
 | 
				
			||||||
	glue->last_timer[pdev->id] = timeout;
 | 
						glue->last_timer[pdev->id] = timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
 | 
						dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
 | 
				
			||||||
		otg_state_string(musb->xceiv->state),
 | 
							usb_otg_state_string(musb->xceiv->state),
 | 
				
			||||||
			jiffies_to_msecs(timeout - jiffies));
 | 
								jiffies_to_msecs(timeout - jiffies));
 | 
				
			||||||
	mod_timer(&glue->timer[pdev->id], timeout);
 | 
						mod_timer(&glue->timer[pdev->id], timeout);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -334,7 +335,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 | 
				
			||||||
	 * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
 | 
						 * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
 | 
				
			||||||
	 * Also, DRVVBUS pulses for SRP (but not at 5V) ...
 | 
						 * Also, DRVVBUS pulses for SRP (but not at 5V) ...
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (usbintr & MUSB_INTR_BABBLE)
 | 
						if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE)
 | 
				
			||||||
		pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
 | 
							pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
 | 
						if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
 | 
				
			||||||
| 
						 | 
					@ -377,7 +378,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 | 
				
			||||||
		/* NOTE: this must complete power-on within 100 ms. */
 | 
							/* NOTE: this must complete power-on within 100 ms. */
 | 
				
			||||||
		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 | 
							dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 | 
				
			||||||
				drvvbus ? "on" : "off",
 | 
									drvvbus ? "on" : "off",
 | 
				
			||||||
				otg_state_string(musb->xceiv->state),
 | 
									usb_otg_state_string(musb->xceiv->state),
 | 
				
			||||||
				err ? " ERROR" : "",
 | 
									err ? " ERROR" : "",
 | 
				
			||||||
				devctl);
 | 
									devctl);
 | 
				
			||||||
		ret = IRQ_HANDLED;
 | 
							ret = IRQ_HANDLED;
 | 
				
			||||||
| 
						 | 
					@ -596,14 +597,13 @@ err0:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dsps_probe(struct platform_device *pdev)
 | 
					static int dsps_probe(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct device_node *np = pdev->dev.of_node;
 | 
					 | 
				
			||||||
	const struct of_device_id *match;
 | 
						const struct of_device_id *match;
 | 
				
			||||||
	const struct dsps_musb_wrapper *wrp;
 | 
						const struct dsps_musb_wrapper *wrp;
 | 
				
			||||||
	struct dsps_glue *glue;
 | 
						struct dsps_glue *glue;
 | 
				
			||||||
	struct resource *iomem;
 | 
						struct resource *iomem;
 | 
				
			||||||
	int ret, i;
 | 
						int ret, i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	match = of_match_node(musb_dsps_of_match, np);
 | 
						match = of_match_node(musb_dsps_of_match, pdev->dev.of_node);
 | 
				
			||||||
	if (!match) {
 | 
						if (!match) {
 | 
				
			||||||
		dev_err(&pdev->dev, "fail to get matching of_match struct\n");
 | 
							dev_err(&pdev->dev, "fail to get matching of_match struct\n");
 | 
				
			||||||
		ret = -EINVAL;
 | 
							ret = -EINVAL;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,48 +46,6 @@
 | 
				
			||||||
#include "musb_core.h"
 | 
					#include "musb_core.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* MUSB PERIPHERAL status 3-mar-2006:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * - EP0 seems solid.  It passes both USBCV and usbtest control cases.
 | 
					 | 
				
			||||||
 *   Minor glitches:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *     + remote wakeup to Linux hosts work, but saw USBCV failures;
 | 
					 | 
				
			||||||
 *       in one test run (operator error?)
 | 
					 | 
				
			||||||
 *     + endpoint halt tests -- in both usbtest and usbcv -- seem
 | 
					 | 
				
			||||||
 *       to break when dma is enabled ... is something wrongly
 | 
					 | 
				
			||||||
 *       clearing SENDSTALL?
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * - Mass storage behaved ok when last tested.  Network traffic patterns
 | 
					 | 
				
			||||||
 *   (with lots of short transfers etc) need retesting; they turn up the
 | 
					 | 
				
			||||||
 *   worst cases of the DMA, since short packets are typical but are not
 | 
					 | 
				
			||||||
 *   required.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * - TX/IN
 | 
					 | 
				
			||||||
 *     + both pio and dma behave in with network and g_zero tests
 | 
					 | 
				
			||||||
 *     + no cppi throughput issues other than no-hw-queueing
 | 
					 | 
				
			||||||
 *     + failed with FLAT_REG (DaVinci)
 | 
					 | 
				
			||||||
 *     + seems to behave with double buffering, PIO -and- CPPI
 | 
					 | 
				
			||||||
 *     + with gadgetfs + AIO, requests got lost?
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * - RX/OUT
 | 
					 | 
				
			||||||
 *     + both pio and dma behave in with network and g_zero tests
 | 
					 | 
				
			||||||
 *     + dma is slow in typical case (short_not_ok is clear)
 | 
					 | 
				
			||||||
 *     + double buffering ok with PIO
 | 
					 | 
				
			||||||
 *     + double buffering *FAILS* with CPPI, wrong data bytes sometimes
 | 
					 | 
				
			||||||
 *     + request lossage observed with gadgetfs
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * - ISO not tested ... might work, but only weakly isochronous
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * - Gadget driver disabling of softconnect during bind() is ignored; so
 | 
					 | 
				
			||||||
 *   drivers can't hold off host requests until userspace is ready.
 | 
					 | 
				
			||||||
 *   (Workaround:  they can turn it off later.)
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * - PORTABILITY (assumes PIO works):
 | 
					 | 
				
			||||||
 *     + DaVinci, basically works with cppi dma
 | 
					 | 
				
			||||||
 *     + OMAP 2430, ditto with mentor dma
 | 
					 | 
				
			||||||
 *     + TUSB 6010, platform-specific dma in the works
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* ----------------------------------------------------------------------- */
 | 
					/* ----------------------------------------------------------------------- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define is_buffer_mapped(req) (is_dma_capable() && \
 | 
					#define is_buffer_mapped(req) (is_dma_capable() && \
 | 
				
			||||||
| 
						 | 
					@ -280,41 +238,6 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
 | 
				
			||||||
		return ep->packet_sz;
 | 
							return ep->packet_sz;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_USB_INVENTRA_DMA
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Peripheral tx (IN) using Mentor DMA works as follows:
 | 
					 | 
				
			||||||
	Only mode 0 is used for transfers <= wPktSize,
 | 
					 | 
				
			||||||
	mode 1 is used for larger transfers,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	One of the following happens:
 | 
					 | 
				
			||||||
	- Host sends IN token which causes an endpoint interrupt
 | 
					 | 
				
			||||||
		-> TxAvail
 | 
					 | 
				
			||||||
			-> if DMA is currently busy, exit.
 | 
					 | 
				
			||||||
			-> if queue is non-empty, txstate().
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	- Request is queued by the gadget driver.
 | 
					 | 
				
			||||||
		-> if queue was previously empty, txstate()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	txstate()
 | 
					 | 
				
			||||||
		-> start
 | 
					 | 
				
			||||||
		  /\	-> setup DMA
 | 
					 | 
				
			||||||
		  |     (data is transferred to the FIFO, then sent out when
 | 
					 | 
				
			||||||
		  |	IN token(s) are recd from Host.
 | 
					 | 
				
			||||||
		  |		-> DMA interrupt on completion
 | 
					 | 
				
			||||||
		  |		   calls TxAvail.
 | 
					 | 
				
			||||||
		  |		      -> stop DMA, ~DMAENAB,
 | 
					 | 
				
			||||||
		  |		      -> set TxPktRdy for last short pkt or zlp
 | 
					 | 
				
			||||||
		  |		      -> Complete Request
 | 
					 | 
				
			||||||
		  |		      -> Continue next request (call txstate)
 | 
					 | 
				
			||||||
		  |___________________________________|
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 * Non-Mentor DMA engines can of course work differently, such as by
 | 
					 | 
				
			||||||
 * upleveling from irq-per-packet to irq-per-buffer.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * An endpoint is transmitting data. This can be called either from
 | 
					 * An endpoint is transmitting data. This can be called either from
 | 
				
			||||||
 * the IRQ routine or from ep.queue() to kickstart a request on an
 | 
					 * the IRQ routine or from ep.queue() to kickstart a request on an
 | 
				
			||||||
| 
						 | 
					@ -621,37 +544,6 @@ void musb_g_tx(struct musb *musb, u8 epnum)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ------------------------------------------------------------ */
 | 
					/* ------------------------------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_USB_INVENTRA_DMA
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Peripheral rx (OUT) using Mentor DMA works as follows:
 | 
					 | 
				
			||||||
	- Only mode 0 is used.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	- Request is queued by the gadget class driver.
 | 
					 | 
				
			||||||
		-> if queue was previously empty, rxstate()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	- Host sends OUT token which causes an endpoint interrupt
 | 
					 | 
				
			||||||
	  /\      -> RxReady
 | 
					 | 
				
			||||||
	  |	      -> if request queued, call rxstate
 | 
					 | 
				
			||||||
	  |		/\	-> setup DMA
 | 
					 | 
				
			||||||
	  |		|	     -> DMA interrupt on completion
 | 
					 | 
				
			||||||
	  |		|		-> RxReady
 | 
					 | 
				
			||||||
	  |		|		      -> stop DMA
 | 
					 | 
				
			||||||
	  |		|		      -> ack the read
 | 
					 | 
				
			||||||
	  |		|		      -> if data recd = max expected
 | 
					 | 
				
			||||||
	  |		|				by the request, or host
 | 
					 | 
				
			||||||
	  |		|				sent a short packet,
 | 
					 | 
				
			||||||
	  |		|				complete the request,
 | 
					 | 
				
			||||||
	  |		|				and start the next one.
 | 
					 | 
				
			||||||
	  |		|_____________________________________|
 | 
					 | 
				
			||||||
	  |					 else just wait for the host
 | 
					 | 
				
			||||||
	  |					    to send the next OUT token.
 | 
					 | 
				
			||||||
	  |__________________________________________________|
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 * Non-Mentor DMA engines can of course work differently.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Context: controller locked, IRQs blocked, endpoint selected
 | 
					 * Context: controller locked, IRQs blocked, endpoint selected
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -740,7 +632,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 | 
				
			||||||
				struct dma_controller	*c;
 | 
									struct dma_controller	*c;
 | 
				
			||||||
				struct dma_channel	*channel;
 | 
									struct dma_channel	*channel;
 | 
				
			||||||
				int			use_dma = 0;
 | 
									int			use_dma = 0;
 | 
				
			||||||
				int transfer_size;
 | 
									unsigned int transfer_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				c = musb->dma_controller;
 | 
									c = musb->dma_controller;
 | 
				
			||||||
				channel = musb_ep->dma;
 | 
									channel = musb_ep->dma;
 | 
				
			||||||
| 
						 | 
					@ -782,10 +674,11 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 | 
				
			||||||
						csr | MUSB_RXCSR_DMAMODE);
 | 
											csr | MUSB_RXCSR_DMAMODE);
 | 
				
			||||||
					musb_writew(epio, MUSB_RXCSR, csr);
 | 
										musb_writew(epio, MUSB_RXCSR, csr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					transfer_size = min(request->length - request->actual,
 | 
										transfer_size = min_t(unsigned int,
 | 
				
			||||||
 | 
												request->length -
 | 
				
			||||||
 | 
												request->actual,
 | 
				
			||||||
							channel->max_len);
 | 
												channel->max_len);
 | 
				
			||||||
					musb_ep->dma->desired_mode = 1;
 | 
										musb_ep->dma->desired_mode = 1;
 | 
				
			||||||
 | 
					 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					if (!musb_ep->hb_mult &&
 | 
										if (!musb_ep->hb_mult &&
 | 
				
			||||||
						musb_ep->hw_ep->rx_double_buffered)
 | 
											musb_ep->hw_ep->rx_double_buffered)
 | 
				
			||||||
| 
						 | 
					@ -815,7 +708,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				struct dma_controller *c;
 | 
									struct dma_controller *c;
 | 
				
			||||||
				struct dma_channel *channel;
 | 
									struct dma_channel *channel;
 | 
				
			||||||
				int transfer_size = 0;
 | 
									unsigned int transfer_size = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				c = musb->dma_controller;
 | 
									c = musb->dma_controller;
 | 
				
			||||||
				channel = musb_ep->dma;
 | 
									channel = musb_ep->dma;
 | 
				
			||||||
| 
						 | 
					@ -824,11 +717,13 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 | 
				
			||||||
				if (fifo_count < musb_ep->packet_sz)
 | 
									if (fifo_count < musb_ep->packet_sz)
 | 
				
			||||||
					transfer_size = fifo_count;
 | 
										transfer_size = fifo_count;
 | 
				
			||||||
				else if (request->short_not_ok)
 | 
									else if (request->short_not_ok)
 | 
				
			||||||
					transfer_size =	min(request->length -
 | 
										transfer_size =	min_t(unsigned int,
 | 
				
			||||||
 | 
												request->length -
 | 
				
			||||||
							request->actual,
 | 
												request->actual,
 | 
				
			||||||
							channel->max_len);
 | 
												channel->max_len);
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
					transfer_size = min(request->length -
 | 
										transfer_size = min_t(unsigned int,
 | 
				
			||||||
 | 
												request->length -
 | 
				
			||||||
							request->actual,
 | 
												request->actual,
 | 
				
			||||||
							(unsigned)fifo_count);
 | 
												(unsigned)fifo_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1681,7 +1576,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget)
 | 
				
			||||||
		goto done;
 | 
							goto done;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		dev_dbg(musb->controller, "Unhandled wake: %s\n",
 | 
							dev_dbg(musb->controller, "Unhandled wake: %s\n",
 | 
				
			||||||
			otg_state_string(musb->xceiv->state));
 | 
								usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
		goto done;
 | 
							goto done;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1801,13 +1696,6 @@ static const struct usb_gadget_ops musb_gadget_operations = {
 | 
				
			||||||
 * all peripheral ports are external...
 | 
					 * all peripheral ports are external...
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void musb_gadget_release(struct device *dev)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	/* kref_put(WHAT) */
 | 
					 | 
				
			||||||
	dev_dbg(dev, "%s\n", __func__);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
 | 
					init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1892,12 +1780,7 @@ int musb_gadget_setup(struct musb *musb)
 | 
				
			||||||
	musb->g.speed = USB_SPEED_UNKNOWN;
 | 
						musb->g.speed = USB_SPEED_UNKNOWN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* this "gadget" abstracts/virtualizes the controller */
 | 
						/* this "gadget" abstracts/virtualizes the controller */
 | 
				
			||||||
	dev_set_name(&musb->g.dev, "gadget");
 | 
					 | 
				
			||||||
	musb->g.dev.parent = musb->controller;
 | 
					 | 
				
			||||||
	musb->g.dev.dma_mask = musb->controller->dma_mask;
 | 
					 | 
				
			||||||
	musb->g.dev.release = musb_gadget_release;
 | 
					 | 
				
			||||||
	musb->g.name = musb_driver_name;
 | 
						musb->g.name = musb_driver_name;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	musb->g.is_otg = 1;
 | 
						musb->g.is_otg = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	musb_g_init_endpoints(musb);
 | 
						musb_g_init_endpoints(musb);
 | 
				
			||||||
| 
						 | 
					@ -1905,11 +1788,6 @@ int musb_gadget_setup(struct musb *musb)
 | 
				
			||||||
	musb->is_active = 0;
 | 
						musb->is_active = 0;
 | 
				
			||||||
	musb_platform_try_idle(musb, 0);
 | 
						musb_platform_try_idle(musb, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = device_register(&musb->g.dev);
 | 
					 | 
				
			||||||
	if (status != 0) {
 | 
					 | 
				
			||||||
		put_device(&musb->g.dev);
 | 
					 | 
				
			||||||
		return status;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	status = usb_add_gadget_udc(musb->controller, &musb->g);
 | 
						status = usb_add_gadget_udc(musb->controller, &musb->g);
 | 
				
			||||||
	if (status)
 | 
						if (status)
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
| 
						 | 
					@ -1924,8 +1802,6 @@ err:
 | 
				
			||||||
void musb_gadget_cleanup(struct musb *musb)
 | 
					void musb_gadget_cleanup(struct musb *musb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	usb_del_gadget_udc(&musb->g);
 | 
						usb_del_gadget_udc(&musb->g);
 | 
				
			||||||
	if (musb->g.dev.parent)
 | 
					 | 
				
			||||||
		device_unregister(&musb->g.dev);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -1977,9 +1853,8 @@ static int musb_gadget_start(struct usb_gadget *g,
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((musb->xceiv->last_event == USB_EVENT_ID)
 | 
						if (musb->xceiv->last_event == USB_EVENT_ID)
 | 
				
			||||||
				&& otg->set_vbus)
 | 
							musb_platform_set_vbus(musb, 1);
 | 
				
			||||||
		otg_set_vbus(otg, 1);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hcd->self.uses_pio_for_control = 1;
 | 
						hcd->self.uses_pio_for_control = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2063,6 +1938,7 @@ static int musb_gadget_stop(struct usb_gadget *g,
 | 
				
			||||||
	dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);
 | 
						dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	musb->is_active = 0;
 | 
						musb->is_active = 0;
 | 
				
			||||||
 | 
						musb->gadget_driver = NULL;
 | 
				
			||||||
	musb_platform_try_idle(musb, 0);
 | 
						musb_platform_try_idle(musb, 0);
 | 
				
			||||||
	spin_unlock_irqrestore(&musb->lock, flags);
 | 
						spin_unlock_irqrestore(&musb->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2099,7 +1975,7 @@ void musb_g_resume(struct musb *musb)
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		WARNING("unhandled RESUME transition (%s)\n",
 | 
							WARNING("unhandled RESUME transition (%s)\n",
 | 
				
			||||||
				otg_state_string(musb->xceiv->state));
 | 
									usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2129,7 +2005,7 @@ void musb_g_suspend(struct musb *musb)
 | 
				
			||||||
		 * A_PERIPHERAL may need care too
 | 
							 * A_PERIPHERAL may need care too
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		WARNING("unhandled SUSPEND transition (%s)\n",
 | 
							WARNING("unhandled SUSPEND transition (%s)\n",
 | 
				
			||||||
				otg_state_string(musb->xceiv->state));
 | 
									usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2163,7 +2039,7 @@ void musb_g_disconnect(struct musb *musb)
 | 
				
			||||||
	switch (musb->xceiv->state) {
 | 
						switch (musb->xceiv->state) {
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n",
 | 
							dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n",
 | 
				
			||||||
			otg_state_string(musb->xceiv->state));
 | 
								usb_otg_state_string(musb->xceiv->state));
 | 
				
			||||||
		musb->xceiv->state = OTG_STATE_A_IDLE;
 | 
							musb->xceiv->state = OTG_STATE_A_IDLE;
 | 
				
			||||||
		MUSB_HST_MODE(musb);
 | 
							MUSB_HST_MODE(musb);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue