USB patches for 3.12-rc1
Here's the big USB driver pull request for 3.12-rc1 Lots of USB driver fixes and updates. Nothing major, just the normal xhci, gadget, and other driver changes. Full details in the shortlog. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.21 (GNU/Linux) iEYEABECAAYFAlIlJJ8ACgkQMUfUDdst+ymBAwCgg8czTAuwpCCK7H8LHnC2BsMj dtUAnjDisrbw4qWSXaaA/sfgSZjKW5G4 =Tman -----END PGP SIGNATURE----- Merge tag 'usb-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB patches from Greg KH: "Here's the big USB driver pull request for 3.12-rc1 Lots of USB driver fixes and updates. Nothing major, just the normal xhci, gadget, and other driver changes. Full details in the shortlog" * tag 'usb-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (352 commits) usbcore: fix incorrect type in assignment in descriptors_changed() usbcore: compare and release one bos descriptor in usb_reset_and_verify_device() ehci: remove debugging statement with ehci statistics in ehci_stop() ehci: remove duplicate debug_async_open() prototype in ehci-dbg.c ehci: enable debugging code when CONFIG_DYNAMIC_DEBUG is set ehci: remove ehci_vdbg() verbose debugging statements Documentation sysfs-bus-usb: Document which files are used by libusb Documentation sysfs-bus-usb: Document the speed file used by libusb Documentation sysfs-bus-usb: Move files with known users to stable USB: fix build error when CONFIG_PM_SLEEP isn't enabled usb: r8a66597-hcd: use platform_{get,set}_drvdata() usb: phy-tegra-usb: use platform_{get,set}_drvdata() usb: acm gadget: Null termintate strings table dma: cppi41: off by one in desc_to_chan() xhci: Fix warning introduced by disabling runtime PM. dev-core: fix build break when DEBUG is enabled USB: OHCI: Allow runtime PM without system sleep usb: ohci-at91: remove unnecessary dev_set_drvdata() usb: renesas_usbhs: use platform_{get,set}_drvdata() usb: fotg210-udc: use platform_{get,set}_drvdata() ...
This commit is contained in:
commit
b3b49114c8
142
Documentation/ABI/stable/sysfs-bus-usb
Normal file
142
Documentation/ABI/stable/sysfs-bus-usb
Normal file
|
@ -0,0 +1,142 @@
|
|||
What: /sys/bus/usb/devices/.../power/persist
|
||||
Date: May 2007
|
||||
KernelVersion: 2.6.23
|
||||
Contact: Alan Stern <stern@rowland.harvard.edu>
|
||||
Description:
|
||||
If CONFIG_USB_PERSIST is set, then each USB device directory
|
||||
will contain a file named power/persist. The file holds a
|
||||
boolean value (0 or 1) indicating whether or not the
|
||||
"USB-Persist" facility is enabled for the device. Since the
|
||||
facility is inherently dangerous, it is disabled by default
|
||||
for all devices except hubs. For more information, see
|
||||
Documentation/usb/persist.txt.
|
||||
|
||||
What: /sys/bus/usb/devices/.../power/autosuspend
|
||||
Date: March 2007
|
||||
KernelVersion: 2.6.21
|
||||
Contact: Alan Stern <stern@rowland.harvard.edu>
|
||||
Description:
|
||||
Each USB device directory will contain a file named
|
||||
power/autosuspend. This file holds the time (in seconds)
|
||||
the device must be idle before it will be autosuspended.
|
||||
0 means the device will be autosuspended as soon as
|
||||
possible. Negative values will prevent the device from
|
||||
being autosuspended at all, and writing a negative value
|
||||
will resume the device if it is already suspended.
|
||||
|
||||
The autosuspend delay for newly-created devices is set to
|
||||
the value of the usbcore.autosuspend module parameter.
|
||||
|
||||
What: /sys/bus/usb/device/.../power/connected_duration
|
||||
Date: January 2008
|
||||
KernelVersion: 2.6.25
|
||||
Contact: Sarah Sharp <sarah.a.sharp@intel.com>
|
||||
Description:
|
||||
If CONFIG_PM_RUNTIME is enabled then this file
|
||||
is present. When read, it returns the total time (in msec)
|
||||
that the USB device has been connected to the machine. This
|
||||
file is read-only.
|
||||
Users:
|
||||
PowerTOP <power@bughost.org>
|
||||
http://www.lesswatts.org/projects/powertop/
|
||||
|
||||
What: /sys/bus/usb/device/.../power/active_duration
|
||||
Date: January 2008
|
||||
KernelVersion: 2.6.25
|
||||
Contact: Sarah Sharp <sarah.a.sharp@intel.com>
|
||||
Description:
|
||||
If CONFIG_PM_RUNTIME is enabled then this file
|
||||
is present. When read, it returns the total time (in msec)
|
||||
that the USB device has been active, i.e. not in a suspended
|
||||
state. This file is read-only.
|
||||
|
||||
Tools can use this file and the connected_duration file to
|
||||
compute the percentage of time that a device has been active.
|
||||
For example,
|
||||
echo $((100 * `cat active_duration` / `cat connected_duration`))
|
||||
will give an integer percentage. Note that this does not
|
||||
account for counter wrap.
|
||||
Users:
|
||||
PowerTOP <power@bughost.org>
|
||||
http://www.lesswatts.org/projects/powertop/
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<port[.port]>...:<config num>-<interface num>/supports_autosuspend
|
||||
Date: January 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: Sarah Sharp <sarah.a.sharp@intel.com>
|
||||
Description:
|
||||
When read, this file returns 1 if the interface driver
|
||||
for this interface supports autosuspend. It also
|
||||
returns 1 if no driver has claimed this interface, as an
|
||||
unclaimed interface will not stop the device from being
|
||||
autosuspended if all other interface drivers are idle.
|
||||
The file returns 0 if autosuspend support has not been
|
||||
added to the driver.
|
||||
Users:
|
||||
USB PM tool
|
||||
git://git.moblin.org/users/sarah/usb-pm-tool/
|
||||
|
||||
What: /sys/bus/usb/device/.../avoid_reset_quirk
|
||||
Date: December 2009
|
||||
Contact: Oliver Neukum <oliver@neukum.org>
|
||||
Description:
|
||||
Writing 1 to this file tells the kernel that this
|
||||
device will morph into another mode when it is reset.
|
||||
Drivers will not use reset for error handling for
|
||||
such devices.
|
||||
Users:
|
||||
usb_modeswitch
|
||||
|
||||
What: /sys/bus/usb/devices/.../devnum
|
||||
KernelVersion: since at least 2.6.18
|
||||
Description:
|
||||
Device address on the USB bus.
|
||||
Users:
|
||||
libusb
|
||||
|
||||
What: /sys/bus/usb/devices/.../bConfigurationValue
|
||||
KernelVersion: since at least 2.6.18
|
||||
Description:
|
||||
bConfigurationValue of the *active* configuration for the
|
||||
device. Writing 0 or -1 to bConfigurationValue will reset the
|
||||
active configuration (unconfigure the device). Writing
|
||||
another value will change the active configuration.
|
||||
|
||||
Note that some devices, in violation of the USB spec, have a
|
||||
configuration with a value equal to 0. Writing 0 to
|
||||
bConfigurationValue for these devices will install that
|
||||
configuration, rather then unconfigure the device.
|
||||
|
||||
Writing -1 will always unconfigure the device.
|
||||
Users:
|
||||
libusb
|
||||
|
||||
What: /sys/bus/usb/devices/.../busnum
|
||||
KernelVersion: 2.6.22
|
||||
Description:
|
||||
Bus-number of the USB-bus the device is connected to.
|
||||
Users:
|
||||
libusb
|
||||
|
||||
What: /sys/bus/usb/devices/.../descriptors
|
||||
KernelVersion: 2.6.26
|
||||
Description:
|
||||
Binary file containing cached descriptors of the device. The
|
||||
binary data consists of the device descriptor followed by the
|
||||
descriptors for each configuration of the device.
|
||||
Note that the wTotalLength of the config descriptors can not
|
||||
be trusted, as the device may have a smaller config descriptor
|
||||
than it advertises. The bLength field of each (sub) descriptor
|
||||
can be trusted, and can be used to seek forward one (sub)
|
||||
descriptor at a time until the next config descriptor is found.
|
||||
All descriptors read from this file are in bus-endian format
|
||||
Users:
|
||||
libusb
|
||||
|
||||
What: /sys/bus/usb/devices/.../speed
|
||||
KernelVersion: since at least 2.6.18
|
||||
Description:
|
||||
Speed the device is connected with to the usb-host in
|
||||
Mbit / second. IE one of 1.5 / 12 / 480 / 5000.
|
||||
Users:
|
||||
libusb
|
|
@ -1,81 +1,3 @@
|
|||
What: /sys/bus/usb/devices/.../power/autosuspend
|
||||
Date: March 2007
|
||||
KernelVersion: 2.6.21
|
||||
Contact: Alan Stern <stern@rowland.harvard.edu>
|
||||
Description:
|
||||
Each USB device directory will contain a file named
|
||||
power/autosuspend. This file holds the time (in seconds)
|
||||
the device must be idle before it will be autosuspended.
|
||||
0 means the device will be autosuspended as soon as
|
||||
possible. Negative values will prevent the device from
|
||||
being autosuspended at all, and writing a negative value
|
||||
will resume the device if it is already suspended.
|
||||
|
||||
The autosuspend delay for newly-created devices is set to
|
||||
the value of the usbcore.autosuspend module parameter.
|
||||
|
||||
What: /sys/bus/usb/devices/.../power/persist
|
||||
Date: May 2007
|
||||
KernelVersion: 2.6.23
|
||||
Contact: Alan Stern <stern@rowland.harvard.edu>
|
||||
Description:
|
||||
If CONFIG_USB_PERSIST is set, then each USB device directory
|
||||
will contain a file named power/persist. The file holds a
|
||||
boolean value (0 or 1) indicating whether or not the
|
||||
"USB-Persist" facility is enabled for the device. Since the
|
||||
facility is inherently dangerous, it is disabled by default
|
||||
for all devices except hubs. For more information, see
|
||||
Documentation/usb/persist.txt.
|
||||
|
||||
What: /sys/bus/usb/device/.../power/connected_duration
|
||||
Date: January 2008
|
||||
KernelVersion: 2.6.25
|
||||
Contact: Sarah Sharp <sarah.a.sharp@intel.com>
|
||||
Description:
|
||||
If CONFIG_PM_RUNTIME is enabled then this file
|
||||
is present. When read, it returns the total time (in msec)
|
||||
that the USB device has been connected to the machine. This
|
||||
file is read-only.
|
||||
Users:
|
||||
PowerTOP <power@bughost.org>
|
||||
http://www.lesswatts.org/projects/powertop/
|
||||
|
||||
What: /sys/bus/usb/device/.../power/active_duration
|
||||
Date: January 2008
|
||||
KernelVersion: 2.6.25
|
||||
Contact: Sarah Sharp <sarah.a.sharp@intel.com>
|
||||
Description:
|
||||
If CONFIG_PM_RUNTIME is enabled then this file
|
||||
is present. When read, it returns the total time (in msec)
|
||||
that the USB device has been active, i.e. not in a suspended
|
||||
state. This file is read-only.
|
||||
|
||||
Tools can use this file and the connected_duration file to
|
||||
compute the percentage of time that a device has been active.
|
||||
For example,
|
||||
echo $((100 * `cat active_duration` / `cat connected_duration`))
|
||||
will give an integer percentage. Note that this does not
|
||||
account for counter wrap.
|
||||
Users:
|
||||
PowerTOP <power@bughost.org>
|
||||
http://www.lesswatts.org/projects/powertop/
|
||||
|
||||
What: /sys/bus/usb/device/<busnum>-<devnum>...:<config num>-<interface num>/supports_autosuspend
|
||||
Date: January 2008
|
||||
KernelVersion: 2.6.27
|
||||
Contact: Sarah Sharp <sarah.a.sharp@intel.com>
|
||||
Description:
|
||||
When read, this file returns 1 if the interface driver
|
||||
for this interface supports autosuspend. It also
|
||||
returns 1 if no driver has claimed this interface, as an
|
||||
unclaimed interface will not stop the device from being
|
||||
autosuspended if all other interface drivers are idle.
|
||||
The file returns 0 if autosuspend support has not been
|
||||
added to the driver.
|
||||
Users:
|
||||
USB PM tool
|
||||
git://git.moblin.org/users/sarah/usb-pm-tool/
|
||||
|
||||
What: /sys/bus/usb/device/.../authorized
|
||||
Date: July 2008
|
||||
KernelVersion: 2.6.26
|
||||
|
@ -172,17 +94,6 @@ Description:
|
|||
device IDs, exactly like reading from the entry
|
||||
"/sys/bus/usb/drivers/.../new_id"
|
||||
|
||||
What: /sys/bus/usb/device/.../avoid_reset_quirk
|
||||
Date: December 2009
|
||||
Contact: Oliver Neukum <oliver@neukum.org>
|
||||
Description:
|
||||
Writing 1 to this file tells the kernel that this
|
||||
device will morph into another mode when it is reset.
|
||||
Drivers will not use reset for error handling for
|
||||
such devices.
|
||||
Users:
|
||||
usb_modeswitch
|
||||
|
||||
What: /sys/bus/usb/devices/.../power/usb2_hardware_lpm
|
||||
Date: September 2011
|
||||
Contact: Andiry Xu <andiry.xu@amd.com>
|
||||
|
|
|
@ -1,35 +1,197 @@
|
|||
AM33XX MUSB GLUE
|
||||
- compatible : Should be "ti,musb-am33xx"
|
||||
- reg : offset and length of register sets, first usbss, then for musb instances
|
||||
- interrupts : usbss, musb instance interrupts in order
|
||||
- ti,hwmods : must be "usb_otg_hs"
|
||||
- multipoint : Should be "1" indicating the musb controller supports
|
||||
multipoint. This is a MUSB configuration-specific setting.
|
||||
- num-eps : Specifies the number of endpoints. This is also a
|
||||
MUSB configuration-specific setting. Should be set to "16"
|
||||
- ram-bits : Specifies the ram address size. Should be set to "12"
|
||||
- port0-mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
|
||||
represents PERIPHERAL.
|
||||
- port1-mode : Should be "1" to represent HOST. "3" signifies OTG and "2"
|
||||
represents PERIPHERAL.
|
||||
- power : Should be "250". This signifies the controller can supply up to
|
||||
500mA when operating in host mode.
|
||||
AM33xx MUSB
|
||||
~~~~~~~~~~~~~~~
|
||||
- compatible: ti,am33xx-usb
|
||||
- reg: offset and length of the usbss register sets
|
||||
- ti,hwmods : must be "usb_otg_hs"
|
||||
|
||||
The glue layer contains multiple child nodes. It is required the have
|
||||
at least a control module node, USB node and a PHY node. The second USB
|
||||
node and its PHY node is optional. The DMA node is also optional.
|
||||
|
||||
Reset module
|
||||
~~~~~~~~~~~~
|
||||
- compatible: ti,am335x-usb-ctrl-module
|
||||
- reg: offset and length of the "USB control registers" in the "Control
|
||||
Module" block. A second offset and length for the USB wake up control
|
||||
in the same memory block.
|
||||
- reg-names: "phy_ctrl" for the "USB control registers" and "wakeup" for
|
||||
the USB wake up control register.
|
||||
|
||||
USB PHY
|
||||
~~~~~~~
|
||||
compatible: ti,am335x-usb-phy
|
||||
reg: offset and length of the "USB PHY" register space
|
||||
ti,ctrl_mod: reference to the "reset module" node
|
||||
reg-names: phy
|
||||
The PHY should have a "phy" alias numbered properly in the alias
|
||||
node.
|
||||
|
||||
USB
|
||||
~~~
|
||||
- compatible: ti,musb-am33xx
|
||||
- reg: offset and length of "USB Controller Registers", and offset and
|
||||
length of "USB Core" register space.
|
||||
- reg-names: control for the ""USB Controller Registers" and "mc" for
|
||||
"USB Core" register space
|
||||
- interrupts: USB interrupt number
|
||||
- interrupt-names: mc
|
||||
- dr_mode: Should be one of "host", "peripheral" or "otg".
|
||||
- mentor,multipoint: Should be "1" indicating the musb controller supports
|
||||
multipoint. This is a MUSB configuration-specific setting.
|
||||
- mentor,num-eps: Specifies the number of endpoints. This is also a
|
||||
MUSB configuration-specific setting. Should be set to "16"
|
||||
- mentor,ram-bits: Specifies the ram address size. Should be set to "12"
|
||||
- mentor,power: Should be "500". This signifies the controller can supply up to
|
||||
500mA when operating in host mode.
|
||||
- phys: reference to the USB phy
|
||||
- dmas: specifies the dma channels
|
||||
- dma-names: specifies the names of the channels. Use "rxN" for receive
|
||||
and "txN" for transmit endpoints. N specifies the endpoint number.
|
||||
|
||||
The controller should have an "usb" alias numbered properly in the alias
|
||||
node.
|
||||
|
||||
DMA
|
||||
~~~
|
||||
- compatible: ti,am3359-cppi41
|
||||
- reg: offset and length of the following register spaces: USBSS, USB
|
||||
CPPI DMA Controller, USB CPPI DMA Scheduler, USB Queue Manager
|
||||
- reg-names: glue, controller, scheduler, queuemgr
|
||||
- #dma-cells: should be set to 2. The first number represents the
|
||||
endpoint number (0 … 14 for endpoints 1 … 15 on instance 0 and 15 … 29
|
||||
for endpoints 1 … 15 on instance 1). The second number is 0 for RX and
|
||||
1 for TX transfers.
|
||||
- #dma-channels: should be set to 30 representing the 15 endpoints for
|
||||
each USB instance.
|
||||
|
||||
Example:
|
||||
~~~~~~~~
|
||||
The following example contains all the nodes as used on am335x-evm:
|
||||
|
||||
usb@47400000 {
|
||||
compatible = "ti,musb-am33xx";
|
||||
reg = <0x47400000 0x1000 /* usbss */
|
||||
0x47401000 0x800 /* musb instance 0 */
|
||||
0x47401800 0x800>; /* musb instance 1 */
|
||||
interrupts = <17 /* usbss */
|
||||
18 /* musb instance 0 */
|
||||
19>; /* musb instance 1 */
|
||||
multipoint = <1>;
|
||||
num-eps = <16>;
|
||||
ram-bits = <12>;
|
||||
port0-mode = <3>;
|
||||
port1-mode = <3>;
|
||||
power = <250>;
|
||||
ti,hwmods = "usb_otg_hs";
|
||||
aliases {
|
||||
usb0 = &usb0;
|
||||
usb1 = &usb1;
|
||||
phy0 = &usb0_phy;
|
||||
phy1 = &usb1_phy;
|
||||
};
|
||||
|
||||
usb: usb@47400000 {
|
||||
compatible = "ti,am33xx-usb";
|
||||
reg = <0x47400000 0x1000>;
|
||||
ranges;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ti,hwmods = "usb_otg_hs";
|
||||
|
||||
ctrl_mod: control@44e10000 {
|
||||
compatible = "ti,am335x-usb-ctrl-module";
|
||||
reg = <0x44e10620 0x10
|
||||
0x44e10648 0x4>;
|
||||
reg-names = "phy_ctrl", "wakeup";
|
||||
};
|
||||
|
||||
usb0_phy: usb-phy@47401300 {
|
||||
compatible = "ti,am335x-usb-phy";
|
||||
reg = <0x47401300 0x100>;
|
||||
reg-names = "phy";
|
||||
ti,ctrl_mod = <&ctrl_mod>;
|
||||
};
|
||||
|
||||
usb0: usb@47401000 {
|
||||
compatible = "ti,musb-am33xx";
|
||||
reg = <0x47401400 0x400
|
||||
0x47401000 0x200>;
|
||||
reg-names = "mc", "control";
|
||||
|
||||
interrupts = <18>;
|
||||
interrupt-names = "mc";
|
||||
dr_mode = "otg"
|
||||
mentor,multipoint = <1>;
|
||||
mentor,num-eps = <16>;
|
||||
mentor,ram-bits = <12>;
|
||||
mentor,power = <500>;
|
||||
phys = <&usb0_phy>;
|
||||
|
||||
dmas = <&cppi41dma 0 0 &cppi41dma 1 0
|
||||
&cppi41dma 2 0 &cppi41dma 3 0
|
||||
&cppi41dma 4 0 &cppi41dma 5 0
|
||||
&cppi41dma 6 0 &cppi41dma 7 0
|
||||
&cppi41dma 8 0 &cppi41dma 9 0
|
||||
&cppi41dma 10 0 &cppi41dma 11 0
|
||||
&cppi41dma 12 0 &cppi41dma 13 0
|
||||
&cppi41dma 14 0 &cppi41dma 0 1
|
||||
&cppi41dma 1 1 &cppi41dma 2 1
|
||||
&cppi41dma 3 1 &cppi41dma 4 1
|
||||
&cppi41dma 5 1 &cppi41dma 6 1
|
||||
&cppi41dma 7 1 &cppi41dma 8 1
|
||||
&cppi41dma 9 1 &cppi41dma 10 1
|
||||
&cppi41dma 11 1 &cppi41dma 12 1
|
||||
&cppi41dma 13 1 &cppi41dma 14 1>;
|
||||
dma-names =
|
||||
"rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
|
||||
"rx8", "rx9", "rx10", "rx11", "rx12", "rx13",
|
||||
"rx14", "rx15",
|
||||
"tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7",
|
||||
"tx8", "tx9", "tx10", "tx11", "tx12", "tx13",
|
||||
"tx14", "tx15";
|
||||
};
|
||||
|
||||
usb1_phy: usb-phy@47401b00 {
|
||||
compatible = "ti,am335x-usb-phy";
|
||||
reg = <0x47401b00 0x100>;
|
||||
reg-names = "phy";
|
||||
ti,ctrl_mod = <&ctrl_mod>;
|
||||
};
|
||||
|
||||
usb1: usb@47401800 {
|
||||
compatible = "ti,musb-am33xx";
|
||||
reg = <0x47401c00 0x400
|
||||
0x47401800 0x200>;
|
||||
reg-names = "mc", "control";
|
||||
interrupts = <19>;
|
||||
interrupt-names = "mc";
|
||||
dr_mode = "host"
|
||||
mentor,multipoint = <1>;
|
||||
mentor,num-eps = <16>;
|
||||
mentor,ram-bits = <12>;
|
||||
mentor,power = <500>;
|
||||
phys = <&usb1_phy>;
|
||||
|
||||
dmas = <&cppi41dma 15 0 &cppi41dma 16 0
|
||||
&cppi41dma 17 0 &cppi41dma 18 0
|
||||
&cppi41dma 19 0 &cppi41dma 20 0
|
||||
&cppi41dma 21 0 &cppi41dma 22 0
|
||||
&cppi41dma 23 0 &cppi41dma 24 0
|
||||
&cppi41dma 25 0 &cppi41dma 26 0
|
||||
&cppi41dma 27 0 &cppi41dma 28 0
|
||||
&cppi41dma 29 0 &cppi41dma 15 1
|
||||
&cppi41dma 16 1 &cppi41dma 17 1
|
||||
&cppi41dma 18 1 &cppi41dma 19 1
|
||||
&cppi41dma 20 1 &cppi41dma 21 1
|
||||
&cppi41dma 22 1 &cppi41dma 23 1
|
||||
&cppi41dma 24 1 &cppi41dma 25 1
|
||||
&cppi41dma 26 1 &cppi41dma 27 1
|
||||
&cppi41dma 28 1 &cppi41dma 29 1>;
|
||||
dma-names =
|
||||
"rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
|
||||
"rx8", "rx9", "rx10", "rx11", "rx12", "rx13",
|
||||
"rx14", "rx15",
|
||||
"tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7",
|
||||
"tx8", "tx9", "tx10", "tx11", "tx12", "tx13",
|
||||
"tx14", "tx15";
|
||||
};
|
||||
|
||||
cppi41dma: dma-controller@07402000 {
|
||||
compatible = "ti,am3359-cppi41";
|
||||
reg = <0x47400000 0x1000
|
||||
0x47402000 0x1000
|
||||
0x47403000 0x1000
|
||||
0x47404000 0x4000>;
|
||||
reg-names = "glue", "controller", "scheduler", "queuemgr";
|
||||
interrupts = <17>;
|
||||
interrupt-names = "glue";
|
||||
#dma-cells = <2>;
|
||||
#dma-channels = <30>;
|
||||
#dma-requests = <256>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -3,10 +3,12 @@ synopsys DWC3 CORE
|
|||
DWC3- USB3 CONTROLLER
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "synopsys,dwc3"
|
||||
- compatible: must be "snps,dwc3"
|
||||
- reg : Address and length of the register set for the device
|
||||
- interrupts: Interrupts used by the dwc3 controller.
|
||||
- usb-phy : array of phandle for the PHY device
|
||||
- usb-phy : array of phandle for the PHY device. The first element
|
||||
in the array is expected to be a handle to the USB2/HS PHY and
|
||||
the second element is expected to be a handle to the USB3/SS PHY
|
||||
|
||||
Optional properties:
|
||||
- tx-fifo-resize: determines if the FIFO *has* to be reallocated.
|
||||
|
@ -14,7 +16,7 @@ Optional properties:
|
|||
This is usually a subnode to DWC3 glue to which it is connected.
|
||||
|
||||
dwc3@4a030000 {
|
||||
compatible = "synopsys,dwc3";
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x4a030000 0xcfff>;
|
||||
interrupts = <0 92 4>
|
||||
usb-phy = <&usb2_phy>, <&usb3,phy>;
|
||||
|
|
24
Documentation/devicetree/bindings/usb/generic.txt
Normal file
24
Documentation/devicetree/bindings/usb/generic.txt
Normal file
|
@ -0,0 +1,24 @@
|
|||
Generic USB Properties
|
||||
|
||||
Optional properties:
|
||||
- maximum-speed: tells USB controllers we want to work up to a certain
|
||||
speed. Valid arguments are "super-speed", "high-speed",
|
||||
"full-speed" and "low-speed". In case this isn't passed
|
||||
via DT, USB controllers should default to their maximum
|
||||
HW capability.
|
||||
- dr_mode: tells Dual-Role USB controllers that we want to work on a
|
||||
particular mode. Valid arguments are "host",
|
||||
"peripheral" and "otg". In case this attribute isn't
|
||||
passed via DT, USB DRD controllers should default to
|
||||
OTG.
|
||||
|
||||
This is an attribute to a USB controller such as:
|
||||
|
||||
dwc3@4a030000 {
|
||||
compatible = "synopsys,dwc3";
|
||||
reg = <0x4a030000 0xcfff>;
|
||||
interrupts = <0 92 4>
|
||||
usb-phy = <&usb2_phy>, <&usb3,phy>;
|
||||
maximum-speed = "super-speed";
|
||||
dr_mode = "otg";
|
||||
};
|
|
@ -3,7 +3,7 @@ Tegra SOC USB PHY
|
|||
The device node for Tegra SOC USB PHY:
|
||||
|
||||
Required properties :
|
||||
- compatible : Should be "nvidia,tegra20-usb-phy".
|
||||
- compatible : Should be "nvidia,tegra<chip>-usb-phy".
|
||||
- reg : Defines the following set of registers, in the order listed:
|
||||
- The PHY's own register set.
|
||||
Always present.
|
||||
|
@ -24,17 +24,26 @@ Required properties :
|
|||
Required properties for phy_type == ulpi:
|
||||
- nvidia,phy-reset-gpio : The GPIO used to reset the PHY.
|
||||
|
||||
Required PHY timing params for utmi phy:
|
||||
Required PHY timing params for utmi phy, for all chips:
|
||||
- nvidia,hssync-start-delay : Number of 480 Mhz clock cycles to wait before
|
||||
start of sync launches RxActive
|
||||
- nvidia,elastic-limit : Variable FIFO Depth of elastic input store
|
||||
- nvidia,idle-wait-delay : Number of 480 Mhz clock cycles of idle to wait
|
||||
before declare IDLE.
|
||||
- nvidia,term-range-adj : Range adjusment on terminations
|
||||
- nvidia,xcvr-setup : HS driver output control
|
||||
- Either one of the following for HS driver output control:
|
||||
- nvidia,xcvr-setup : integer, uses the provided value.
|
||||
- nvidia,xcvr-setup-use-fuses : boolean, indicates that the value is read
|
||||
from the on-chip fuses
|
||||
If both are provided, nvidia,xcvr-setup-use-fuses takes precedence.
|
||||
- nvidia,xcvr-lsfslew : LS falling slew rate control.
|
||||
- nvidia,xcvr-lsrslew : LS rising slew rate control.
|
||||
|
||||
Required PHY timing params for utmi phy, only on Tegra30 and above:
|
||||
- nvidia,xcvr-hsslew : HS slew rate control.
|
||||
- nvidia,hssquelch-level : HS squelch detector level.
|
||||
- nvidia,hsdiscon-level : HS disconnect detector level.
|
||||
|
||||
Optional properties:
|
||||
- nvidia,has-legacy-mode : boolean indicates whether this controller can
|
||||
operate in legacy mode (as APX 2500 / 2600). In legacy mode some
|
||||
|
@ -48,5 +57,5 @@ Optional properties:
|
|||
peripheral means it is device controller
|
||||
otg means it can operate as either ("on the go")
|
||||
|
||||
Required properties for dr_mode == otg:
|
||||
VBUS control (required for dr_mode == otg, optional for dr_mode == host):
|
||||
- vbus-supply: regulator for VBUS
|
||||
|
|
40
Documentation/devicetree/bindings/usb/samsung-hsotg.txt
Normal file
40
Documentation/devicetree/bindings/usb/samsung-hsotg.txt
Normal file
|
@ -0,0 +1,40 @@
|
|||
Samsung High Speed USB OTG controller
|
||||
-----------------------------
|
||||
|
||||
The Samsung HSOTG IP can be found on Samsung SoCs, from S3C6400 onwards.
|
||||
It gives functionality of OTG-compliant USB 2.0 host and device with
|
||||
support for USB 2.0 high-speed (480Mbps) and full-speed (12 Mbps)
|
||||
operation.
|
||||
|
||||
Currently only device mode is supported.
|
||||
|
||||
Binding details
|
||||
-----
|
||||
|
||||
Required properties:
|
||||
- compatible: "samsung,s3c6400-hsotg" should be used for all currently
|
||||
supported SoC,
|
||||
- interrupt-parent: phandle for the interrupt controller to which the
|
||||
interrupt signal of the HSOTG block is routed,
|
||||
- interrupts: specifier of interrupt signal of interrupt controller,
|
||||
according to bindings of interrupt controller,
|
||||
- clocks: contains an array of clock specifiers:
|
||||
- first entry: OTG clock
|
||||
- clock-names: contains array of clock names:
|
||||
- first entry: must be "otg"
|
||||
- vusb_d-supply: phandle to voltage regulator of digital section,
|
||||
- vusb_a-supply: phandle to voltage regulator of analog section.
|
||||
|
||||
Example
|
||||
-----
|
||||
|
||||
hsotg@12480000 {
|
||||
compatible = "samsung,s3c6400-hsotg";
|
||||
reg = <0x12480000 0x20000>;
|
||||
interrupts = <0 71 0>;
|
||||
clocks = <&clock 305>;
|
||||
clock-names = "otg";
|
||||
vusb_d-supply = <&vusb_reg>;
|
||||
vusb_a-supply = <&vusbdac_reg>;
|
||||
};
|
||||
|
14
Documentation/devicetree/bindings/usb/usb-xhci.txt
Normal file
14
Documentation/devicetree/bindings/usb/usb-xhci.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
USB xHCI controllers
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "xhci-platform".
|
||||
- reg: should contain address and length of the standard XHCI
|
||||
register set for the device.
|
||||
- interrupts: one XHCI interrupt should be described here.
|
||||
|
||||
Example:
|
||||
usb@f0931000 {
|
||||
compatible = "xhci-platform";
|
||||
reg = <0xf0931000 0x8c8>;
|
||||
interrupts = <0x0 0x4e 0x0>;
|
||||
};
|
|
@ -1,8 +1,11 @@
|
|||
SMSC USB3503 High-Speed Hub Controller
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "smsc,usb3503".
|
||||
- reg: Specifies the i2c slave address, it should be 0x08.
|
||||
- compatible: Should be "smsc,usb3503" or "smsc,usb3503a".
|
||||
|
||||
Optional properties:
|
||||
- reg: Specifies the i2c slave address, it is required and should be 0x08
|
||||
if I2C is used.
|
||||
- connect-gpios: Should specify GPIO for connect.
|
||||
- disabled-ports: Should specify the ports unused.
|
||||
'1' or '2' or '3' are availe for this property to describe the port
|
||||
|
|
|
@ -195,13 +195,12 @@ by the completion handler.
|
|||
|
||||
The handler is of the following type:
|
||||
|
||||
typedef void (*usb_complete_t)(struct urb *, struct pt_regs *)
|
||||
typedef void (*usb_complete_t)(struct urb *)
|
||||
|
||||
I.e., it gets the URB that caused the completion call, plus the
|
||||
register values at the time of the corresponding interrupt (if any).
|
||||
In the completion handler, you should have a look at urb->status to
|
||||
detect any USB errors. Since the context parameter is included in the URB,
|
||||
you can pass information to the completion handler.
|
||||
I.e., it gets the URB that caused the completion call. In the completion
|
||||
handler, you should have a look at urb->status to detect any USB errors.
|
||||
Since the context parameter is included in the URB, you can pass
|
||||
information to the completion handler.
|
||||
|
||||
Note that even when an error (or unlink) is reported, data may have been
|
||||
transferred. That's because USB transfers are packetized; it might take
|
||||
|
@ -210,12 +209,12 @@ have transferred successfully before the completion was called.
|
|||
|
||||
|
||||
NOTE: ***** WARNING *****
|
||||
NEVER SLEEP IN A COMPLETION HANDLER. These are normally called
|
||||
during hardware interrupt processing. If you can, defer substantial
|
||||
work to a tasklet (bottom half) to keep system latencies low. You'll
|
||||
probably need to use spinlocks to protect data structures you manipulate
|
||||
in completion handlers.
|
||||
NEVER SLEEP IN A COMPLETION HANDLER. These are often called in atomic
|
||||
context.
|
||||
|
||||
In the current kernel, completion handlers run with local interrupts
|
||||
disabled, but in the future this will be changed, so don't assume that
|
||||
local IRQs are always disabled inside completion handlers.
|
||||
|
||||
1.8. How to do isochronous (ISO) transfers?
|
||||
|
||||
|
|
|
@ -54,9 +54,12 @@ it and 002/048 sometime later.
|
|||
|
||||
These files can be read as binary data. The binary data consists
|
||||
of first the device descriptor, then the descriptors for each
|
||||
configuration of the device. Multi-byte fields in the device and
|
||||
configuration descriptors, but not other descriptors, are converted
|
||||
to host endianness by the kernel. This information is also shown
|
||||
configuration of the device. Multi-byte fields in the device descriptor
|
||||
are converted to host endianness by the kernel. The configuration
|
||||
descriptors are in bus endian format! The configuration descriptor
|
||||
are wTotalLength bytes apart. If a device returns less configuration
|
||||
descriptor data than indicated by wTotalLength there will be a hole in
|
||||
the file for the missing bytes. This information is also shown
|
||||
in text form by the /proc/bus/usb/devices file, described later.
|
||||
|
||||
These files may also be used to write user-level drivers for the USB
|
||||
|
|
|
@ -8803,7 +8803,6 @@ W: http://www.linux-usb.org
|
|||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
|
||||
S: Supported
|
||||
F: Documentation/usb/
|
||||
F: drivers/net/usb/
|
||||
F: drivers/usb/
|
||||
F: include/linux/usb.h
|
||||
F: include/linux/usb/
|
||||
|
|
|
@ -120,6 +120,35 @@
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
musb: usb@47400000 {
|
||||
status = "okay";
|
||||
|
||||
control@44e10000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb-phy@47401300 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb-phy@47401b00 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb@47401000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb@47401800 {
|
||||
status = "okay";
|
||||
dr_mode = "host";
|
||||
};
|
||||
|
||||
dma-controller@07402000 {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
i2c0: i2c@44e0b000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c0_pins>;
|
||||
|
|
|
@ -171,6 +171,35 @@
|
|||
};
|
||||
};
|
||||
|
||||
musb: usb@47400000 {
|
||||
status = "okay";
|
||||
|
||||
control@44e10000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb-phy@47401300 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb-phy@47401b00 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb@47401000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb@47401800 {
|
||||
status = "okay";
|
||||
dr_mode = "host";
|
||||
};
|
||||
|
||||
dma-controller@07402000 {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
i2c1: i2c@4802a000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c1_pins>;
|
||||
|
|
|
@ -207,6 +207,22 @@
|
|||
};
|
||||
};
|
||||
|
||||
musb: usb@47400000 {
|
||||
status = "okay";
|
||||
|
||||
control@44e10000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb-phy@47401300 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb@47401000 {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
epwmss2: epwmss@48304000 {
|
||||
status = "okay";
|
||||
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
serial5 = &uart5;
|
||||
d_can0 = &dcan0;
|
||||
d_can1 = &dcan1;
|
||||
usb0 = &usb0;
|
||||
usb1 = &usb1;
|
||||
phy0 = &usb0_phy;
|
||||
phy1 = &usb1_phy;
|
||||
};
|
||||
|
||||
cpus {
|
||||
|
@ -333,21 +337,132 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
usb@47400000 {
|
||||
compatible = "ti,musb-am33xx";
|
||||
reg = <0x47400000 0x1000 /* usbss */
|
||||
0x47401000 0x800 /* musb instance 0 */
|
||||
0x47401800 0x800>; /* musb instance 1 */
|
||||
interrupts = <17 /* usbss */
|
||||
18 /* musb instance 0 */
|
||||
19>; /* musb instance 1 */
|
||||
multipoint = <1>;
|
||||
num-eps = <16>;
|
||||
ram-bits = <12>;
|
||||
port0-mode = <3>;
|
||||
port1-mode = <3>;
|
||||
power = <250>;
|
||||
usb: usb@47400000 {
|
||||
compatible = "ti,am33xx-usb";
|
||||
reg = <0x47400000 0x1000>;
|
||||
ranges;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ti,hwmods = "usb_otg_hs";
|
||||
status = "disabled";
|
||||
|
||||
ctrl_mod: control@44e10000 {
|
||||
compatible = "ti,am335x-usb-ctrl-module";
|
||||
reg = <0x44e10620 0x10
|
||||
0x44e10648 0x4>;
|
||||
reg-names = "phy_ctrl", "wakeup";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb0_phy: usb-phy@47401300 {
|
||||
compatible = "ti,am335x-usb-phy";
|
||||
reg = <0x47401300 0x100>;
|
||||
reg-names = "phy";
|
||||
status = "disabled";
|
||||
ti,ctrl_mod = <&ctrl_mod>;
|
||||
};
|
||||
|
||||
usb0: usb@47401000 {
|
||||
compatible = "ti,musb-am33xx";
|
||||
status = "disabled";
|
||||
reg = <0x47401400 0x400
|
||||
0x47401000 0x200>;
|
||||
reg-names = "mc", "control";
|
||||
|
||||
interrupts = <18>;
|
||||
interrupt-names = "mc";
|
||||
dr_mode = "otg";
|
||||
mentor,multipoint = <1>;
|
||||
mentor,num-eps = <16>;
|
||||
mentor,ram-bits = <12>;
|
||||
mentor,power = <500>;
|
||||
phys = <&usb0_phy>;
|
||||
|
||||
dmas = <&cppi41dma 0 0 &cppi41dma 1 0
|
||||
&cppi41dma 2 0 &cppi41dma 3 0
|
||||
&cppi41dma 4 0 &cppi41dma 5 0
|
||||
&cppi41dma 6 0 &cppi41dma 7 0
|
||||
&cppi41dma 8 0 &cppi41dma 9 0
|
||||
&cppi41dma 10 0 &cppi41dma 11 0
|
||||
&cppi41dma 12 0 &cppi41dma 13 0
|
||||
&cppi41dma 14 0 &cppi41dma 0 1
|
||||
&cppi41dma 1 1 &cppi41dma 2 1
|
||||
&cppi41dma 3 1 &cppi41dma 4 1
|
||||
&cppi41dma 5 1 &cppi41dma 6 1
|
||||
&cppi41dma 7 1 &cppi41dma 8 1
|
||||
&cppi41dma 9 1 &cppi41dma 10 1
|
||||
&cppi41dma 11 1 &cppi41dma 12 1
|
||||
&cppi41dma 13 1 &cppi41dma 14 1>;
|
||||
dma-names =
|
||||
"rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
|
||||
"rx8", "rx9", "rx10", "rx11", "rx12", "rx13",
|
||||
"rx14", "rx15",
|
||||
"tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7",
|
||||
"tx8", "tx9", "tx10", "tx11", "tx12", "tx13",
|
||||
"tx14", "tx15";
|
||||
};
|
||||
|
||||
usb1_phy: usb-phy@47401b00 {
|
||||
compatible = "ti,am335x-usb-phy";
|
||||
reg = <0x47401b00 0x100>;
|
||||
reg-names = "phy";
|
||||
status = "disabled";
|
||||
ti,ctrl_mod = <&ctrl_mod>;
|
||||
};
|
||||
|
||||
usb1: usb@47401800 {
|
||||
compatible = "ti,musb-am33xx";
|
||||
status = "disabled";
|
||||
reg = <0x47401c00 0x400
|
||||
0x47401800 0x200>;
|
||||
reg-names = "mc", "control";
|
||||
interrupts = <19>;
|
||||
interrupt-names = "mc";
|
||||
dr_mode = "otg";
|
||||
mentor,multipoint = <1>;
|
||||
mentor,num-eps = <16>;
|
||||
mentor,ram-bits = <12>;
|
||||
mentor,power = <500>;
|
||||
phys = <&usb1_phy>;
|
||||
|
||||
dmas = <&cppi41dma 15 0 &cppi41dma 16 0
|
||||
&cppi41dma 17 0 &cppi41dma 18 0
|
||||
&cppi41dma 19 0 &cppi41dma 20 0
|
||||
&cppi41dma 21 0 &cppi41dma 22 0
|
||||
&cppi41dma 23 0 &cppi41dma 24 0
|
||||
&cppi41dma 25 0 &cppi41dma 26 0
|
||||
&cppi41dma 27 0 &cppi41dma 28 0
|
||||
&cppi41dma 29 0 &cppi41dma 15 1
|
||||
&cppi41dma 16 1 &cppi41dma 17 1
|
||||
&cppi41dma 18 1 &cppi41dma 19 1
|
||||
&cppi41dma 20 1 &cppi41dma 21 1
|
||||
&cppi41dma 22 1 &cppi41dma 23 1
|
||||
&cppi41dma 24 1 &cppi41dma 25 1
|
||||
&cppi41dma 26 1 &cppi41dma 27 1
|
||||
&cppi41dma 28 1 &cppi41dma 29 1>;
|
||||
dma-names =
|
||||
"rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
|
||||
"rx8", "rx9", "rx10", "rx11", "rx12", "rx13",
|
||||
"rx14", "rx15",
|
||||
"tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7",
|
||||
"tx8", "tx9", "tx10", "tx11", "tx12", "tx13",
|
||||
"tx14", "tx15";
|
||||
};
|
||||
|
||||
cppi41dma: dma-controller@07402000 {
|
||||
compatible = "ti,am3359-cppi41";
|
||||
reg = <0x47400000 0x1000
|
||||
0x47402000 0x1000
|
||||
0x47403000 0x1000
|
||||
0x47404000 0x4000>;
|
||||
reg-names = "glue", "controller", "scheduler", "queuemgr";
|
||||
interrupts = <17>;
|
||||
interrupt-names = "glue";
|
||||
#dma-cells = <2>;
|
||||
#dma-channels = <30>;
|
||||
#dma-requests = <256>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
epwmss0: epwmss@48300000 {
|
||||
|
|
|
@ -644,7 +644,7 @@
|
|||
utmi-mode = <2>;
|
||||
ranges;
|
||||
dwc3@4a030000 {
|
||||
compatible = "synopsys,dwc3";
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x4a030000 0x1000>;
|
||||
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
|
||||
usb-phy = <&usb2_phy>, <&usb3_phy>;
|
||||
|
|
|
@ -566,7 +566,6 @@
|
|||
|
||||
usb@c5000000 {
|
||||
status = "okay";
|
||||
nvidia,vbus-gpio = <&gpio TEGRA_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
|
||||
dr_mode = "otg";
|
||||
};
|
||||
|
||||
|
|
|
@ -312,7 +312,6 @@
|
|||
|
||||
usb@c5000000 {
|
||||
status = "okay";
|
||||
nvidia,vbus-gpio = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
usb-phy@c5000000 {
|
||||
|
|
|
@ -509,7 +509,6 @@
|
|||
|
||||
usb@c5000000 {
|
||||
status = "okay";
|
||||
nvidia,vbus-gpio = <&tca6416 0 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
usb-phy@c5000000 {
|
||||
|
@ -519,7 +518,6 @@
|
|||
|
||||
usb@c5008000 {
|
||||
status = "okay";
|
||||
nvidia,vbus-gpio = <&tca6416 1 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
usb-phy@c5008000 {
|
||||
|
|
|
@ -477,13 +477,13 @@
|
|||
<&tegra_car TEGRA20_CLK_USBD>;
|
||||
clock-names = "reg", "pll_u", "timer", "utmi-pads";
|
||||
nvidia,has-legacy-mode;
|
||||
hssync_start_delay = <9>;
|
||||
idle_wait_delay = <17>;
|
||||
elastic_limit = <16>;
|
||||
term_range_adj = <6>;
|
||||
xcvr_setup = <9>;
|
||||
xcvr_lsfslew = <1>;
|
||||
xcvr_lsrslew = <1>;
|
||||
nvidia,hssync-start-delay = <9>;
|
||||
nvidia,idle-wait-delay = <17>;
|
||||
nvidia,elastic-limit = <16>;
|
||||
nvidia,term-range-adj = <6>;
|
||||
nvidia,xcvr-setup = <9>;
|
||||
nvidia,xcvr-lsfslew = <1>;
|
||||
nvidia,xcvr-lsrslew = <1>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -527,13 +527,13 @@
|
|||
<&tegra_car TEGRA20_CLK_CLK_M>,
|
||||
<&tegra_car TEGRA20_CLK_USBD>;
|
||||
clock-names = "reg", "pll_u", "timer", "utmi-pads";
|
||||
hssync_start_delay = <9>;
|
||||
idle_wait_delay = <17>;
|
||||
elastic_limit = <16>;
|
||||
term_range_adj = <6>;
|
||||
xcvr_setup = <9>;
|
||||
xcvr_lsfslew = <2>;
|
||||
xcvr_lsrslew = <2>;
|
||||
nvidia,hssync-start-delay = <9>;
|
||||
nvidia,idle-wait-delay = <17>;
|
||||
nvidia,elastic-limit = <16>;
|
||||
nvidia,term-range-adj = <6>;
|
||||
nvidia,xcvr-setup = <9>;
|
||||
nvidia,xcvr-lsfslew = <2>;
|
||||
nvidia,xcvr-lsrslew = <2>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/usb/phy.h>
|
||||
#include <linux/usb/nop-usb-xceiv.h>
|
||||
#include <linux/usb/usb_phy_gen_xceiv.h>
|
||||
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
|
@ -279,7 +279,7 @@ static struct regulator_consumer_supply beagle_vsim_supply[] = {
|
|||
static struct gpio_led gpio_leds[];
|
||||
|
||||
/* PHY's VCC regulator might be added later, so flag that we need it */
|
||||
static struct nop_usb_xceiv_platform_data hsusb2_phy_data = {
|
||||
static struct usb_phy_gen_xceiv_platform_data hsusb2_phy_data = {
|
||||
.needs_vcc = true,
|
||||
};
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include <linux/i2c/twl.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/musb.h>
|
||||
#include <linux/usb/nop-usb-xceiv.h>
|
||||
#include <linux/usb/usb_phy_gen_xceiv.h>
|
||||
#include <linux/smsc911x.h>
|
||||
|
||||
#include <linux/wl12xx.h>
|
||||
|
@ -468,7 +468,7 @@ struct wl12xx_platform_data omap3evm_wlan_data __initdata = {
|
|||
static struct regulator_consumer_supply omap3evm_vaux2_supplies[] = {
|
||||
REGULATOR_SUPPLY("VDD_CSIPHY1", "omap3isp"), /* OMAP ISP */
|
||||
REGULATOR_SUPPLY("VDD_CSIPHY2", "omap3isp"), /* OMAP ISP */
|
||||
REGULATOR_SUPPLY("vcc", "nop_usb_xceiv.2"), /* hsusb port 2 */
|
||||
REGULATOR_SUPPLY("vcc", "usb_phy_gen_xceiv.2"), /* hsusb port 2 */
|
||||
REGULATOR_SUPPLY("vaux2", NULL),
|
||||
};
|
||||
|
||||
|
|
|
@ -352,7 +352,7 @@ static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = {
|
|||
};
|
||||
|
||||
static struct regulator_consumer_supply pandora_usb_phy_supply[] = {
|
||||
REGULATOR_SUPPLY("vcc", "nop_usb_xceiv.2"), /* hsusb port 2 */
|
||||
REGULATOR_SUPPLY("vcc", "usb_phy_gen_xceiv.2"), /* hsusb port 2 */
|
||||
};
|
||||
|
||||
/* ads7846 on SPI and 2 nub controllers on I2C */
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/usb/phy.h>
|
||||
#include <linux/usb/nop-usb-xceiv.h>
|
||||
#include <linux/usb/usb_phy_gen_xceiv.h>
|
||||
|
||||
#include "soc.h"
|
||||
#include "omap_device.h"
|
||||
|
@ -349,7 +349,7 @@ static struct fixed_voltage_config hsusb_reg_config = {
|
|||
/* .init_data filled later */
|
||||
};
|
||||
|
||||
static const char *nop_name = "nop_usb_xceiv"; /* NOP PHY driver */
|
||||
static const char *nop_name = "usb_phy_gen_xceiv"; /* NOP PHY driver */
|
||||
static const char *reg_name = "reg-fixed-voltage"; /* Regulator driver */
|
||||
|
||||
/**
|
||||
|
@ -460,9 +460,9 @@ int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys)
|
|||
pdevinfo.name = nop_name;
|
||||
pdevinfo.id = phy->port;
|
||||
pdevinfo.data = phy->platform_data;
|
||||
pdevinfo.size_data = sizeof(struct nop_usb_xceiv_platform_data);
|
||||
|
||||
scnprintf(phy_id, MAX_STR, "nop_usb_xceiv.%d",
|
||||
pdevinfo.size_data =
|
||||
sizeof(struct usb_phy_gen_xceiv_platform_data);
|
||||
scnprintf(phy_id, MAX_STR, "usb_phy_gen_xceiv.%d",
|
||||
phy->port);
|
||||
pdev = platform_device_register_full(&pdevinfo);
|
||||
if (IS_ERR(pdev)) {
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pda_power.h>
|
||||
#include <linux/platform_data/tegra_usb.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
@ -46,40 +45,6 @@
|
|||
#include "fuse.h"
|
||||
#include "iomap.h"
|
||||
|
||||
static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
|
||||
.operating_mode = TEGRA_USB_OTG,
|
||||
.power_down_on_bus_suspend = 1,
|
||||
.vbus_gpio = -1,
|
||||
};
|
||||
|
||||
static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
|
||||
.reset_gpio = -1,
|
||||
.clk = "cdev2",
|
||||
};
|
||||
|
||||
static struct tegra_ehci_platform_data tegra_ehci2_pdata = {
|
||||
.phy_config = &tegra_ehci2_ulpi_phy_config,
|
||||
.operating_mode = TEGRA_USB_HOST,
|
||||
.power_down_on_bus_suspend = 1,
|
||||
.vbus_gpio = -1,
|
||||
};
|
||||
|
||||
static struct tegra_ehci_platform_data tegra_ehci3_pdata = {
|
||||
.operating_mode = TEGRA_USB_HOST,
|
||||
.power_down_on_bus_suspend = 1,
|
||||
.vbus_gpio = -1,
|
||||
};
|
||||
|
||||
static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5000000, "tegra-ehci.0",
|
||||
&tegra_ehci1_pdata),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5004000, "tegra-ehci.1",
|
||||
&tegra_ehci2_pdata),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5008000, "tegra-ehci.2",
|
||||
&tegra_ehci3_pdata),
|
||||
{}
|
||||
};
|
||||
|
||||
static void __init tegra_dt_init(void)
|
||||
{
|
||||
struct soc_device_attribute *soc_dev_attr;
|
||||
|
@ -112,8 +77,7 @@ static void __init tegra_dt_init(void)
|
|||
* devices
|
||||
*/
|
||||
out:
|
||||
of_platform_populate(NULL, of_default_bus_match_table,
|
||||
tegra20_auxdata_lookup, parent);
|
||||
of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
|
||||
}
|
||||
|
||||
static void __init trimslice_init(void)
|
||||
|
|
|
@ -287,6 +287,14 @@ config DMA_OMAP
|
|||
select DMA_ENGINE
|
||||
select DMA_VIRTUAL_CHANNELS
|
||||
|
||||
config TI_CPPI41
|
||||
tristate "AM33xx CPPI41 DMA support"
|
||||
depends on ARCH_OMAP
|
||||
select DMA_ENGINE
|
||||
help
|
||||
The Communications Port Programming Interface (CPPI) 4.1 DMA engine
|
||||
is currently used by the USB driver on AM335x platforms.
|
||||
|
||||
config MMP_PDMA
|
||||
bool "MMP PDMA support"
|
||||
depends on (ARCH_MMP || ARCH_PXA)
|
||||
|
|
|
@ -39,3 +39,4 @@ obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o
|
|||
obj-$(CONFIG_DMA_OMAP) += omap-dma.o
|
||||
obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
|
||||
obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
|
||||
obj-$(CONFIG_TI_CPPI41) += cppi41.o
|
||||
|
|
1059
drivers/dma/cppi41.c
Normal file
1059
drivers/dma/cppi41.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1028,12 +1028,20 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
|
|||
dev->mii.phy_id = 0x03;
|
||||
dev->mii.supports_gmii = 1;
|
||||
|
||||
if (usb_device_no_sg_constraint(dev->udev))
|
||||
dev->can_dma_sg = 1;
|
||||
|
||||
dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
|
||||
NETIF_F_RXCSUM;
|
||||
|
||||
dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
|
||||
NETIF_F_RXCSUM;
|
||||
|
||||
if (dev->can_dma_sg) {
|
||||
dev->net->features |= NETIF_F_SG | NETIF_F_TSO;
|
||||
dev->net->hw_features |= NETIF_F_SG | NETIF_F_TSO;
|
||||
}
|
||||
|
||||
/* Enable checksum offload */
|
||||
*tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP |
|
||||
AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6;
|
||||
|
|
|
@ -1197,6 +1197,37 @@ EXPORT_SYMBOL_GPL(usbnet_tx_timeout);
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int build_dma_sg(const struct sk_buff *skb, struct urb *urb)
|
||||
{
|
||||
unsigned num_sgs, total_len = 0;
|
||||
int i, s = 0;
|
||||
|
||||
num_sgs = skb_shinfo(skb)->nr_frags + 1;
|
||||
if (num_sgs == 1)
|
||||
return 0;
|
||||
|
||||
urb->sg = kmalloc(num_sgs * sizeof(struct scatterlist), GFP_ATOMIC);
|
||||
if (!urb->sg)
|
||||
return -ENOMEM;
|
||||
|
||||
urb->num_sgs = num_sgs;
|
||||
sg_init_table(urb->sg, urb->num_sgs);
|
||||
|
||||
sg_set_buf(&urb->sg[s++], skb->data, skb_headlen(skb));
|
||||
total_len += skb_headlen(skb);
|
||||
|
||||
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
||||
struct skb_frag_struct *f = &skb_shinfo(skb)->frags[i];
|
||||
|
||||
total_len += skb_frag_size(f);
|
||||
sg_set_page(&urb->sg[i + s], f->page.p, f->size,
|
||||
f->page_offset);
|
||||
}
|
||||
urb->transfer_buffer_length = total_len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
|
||||
struct net_device *net)
|
||||
{
|
||||
|
@ -1223,7 +1254,6 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
|
|||
goto drop;
|
||||
}
|
||||
}
|
||||
length = skb->len;
|
||||
|
||||
if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) {
|
||||
netif_dbg(dev, tx_err, dev->net, "no urb\n");
|
||||
|
@ -1233,10 +1263,14 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
|
|||
entry = (struct skb_data *) skb->cb;
|
||||
entry->urb = urb;
|
||||
entry->dev = dev;
|
||||
entry->length = length;
|
||||
|
||||
usb_fill_bulk_urb (urb, dev->udev, dev->out,
|
||||
skb->data, skb->len, tx_complete, skb);
|
||||
if (dev->can_dma_sg) {
|
||||
if (build_dma_sg(skb, urb) < 0)
|
||||
goto drop;
|
||||
}
|
||||
entry->length = length = urb->transfer_buffer_length;
|
||||
|
||||
/* don't assume the hardware handles USB_ZERO_PACKET
|
||||
* NOTE: strictly conforming cdc-ether devices should expect
|
||||
|
@ -1305,7 +1339,10 @@ drop:
|
|||
not_drop:
|
||||
if (skb)
|
||||
dev_kfree_skb_any (skb);
|
||||
usb_free_urb (urb);
|
||||
if (urb) {
|
||||
kfree(urb->sg);
|
||||
usb_free_urb(urb);
|
||||
}
|
||||
} else
|
||||
netif_dbg(dev, tx_queued, dev->net,
|
||||
"> tx, len %d, type 0x%x\n", length, skb->protocol);
|
||||
|
@ -1356,6 +1393,7 @@ static void usbnet_bh (unsigned long param)
|
|||
rx_process (dev, skb);
|
||||
continue;
|
||||
case tx_done:
|
||||
kfree(entry->urb->sg);
|
||||
case rx_cleanup:
|
||||
usb_free_urb (entry->urb);
|
||||
dev_kfree_skb (skb);
|
||||
|
@ -1689,6 +1727,7 @@ int usbnet_resume (struct usb_interface *intf)
|
|||
retval = usb_submit_urb(res, GFP_ATOMIC);
|
||||
if (retval < 0) {
|
||||
dev_kfree_skb_any(skb);
|
||||
kfree(res->sg);
|
||||
usb_free_urb(res);
|
||||
usb_autopm_put_interface_async(dev->intf);
|
||||
} else {
|
||||
|
|
|
@ -6,9 +6,26 @@
|
|||
config USB_ARCH_HAS_OHCI
|
||||
bool
|
||||
|
||||
config USB_OHCI_BIG_ENDIAN_DESC
|
||||
bool
|
||||
|
||||
config USB_OHCI_BIG_ENDIAN_MMIO
|
||||
bool
|
||||
|
||||
config USB_OHCI_LITTLE_ENDIAN
|
||||
bool
|
||||
default n if STB03xxx || PPC_MPC52xx
|
||||
default y
|
||||
|
||||
config USB_ARCH_HAS_EHCI
|
||||
bool
|
||||
|
||||
config USB_EHCI_BIG_ENDIAN_MMIO
|
||||
bool
|
||||
|
||||
config USB_EHCI_BIG_ENDIAN_DESC
|
||||
bool
|
||||
|
||||
config USB_ARCH_HAS_XHCI
|
||||
bool
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ obj-$(CONFIG_USB_ISP1760_HCD) += host/
|
|||
obj-$(CONFIG_USB_IMX21_HCD) += host/
|
||||
obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/
|
||||
obj-$(CONFIG_USB_FUSBH200_HCD) += host/
|
||||
obj-$(CONFIG_USB_FOTG210_HCD) += host/
|
||||
|
||||
obj-$(CONFIG_USB_C67X00_HCD) += c67x00/
|
||||
|
||||
|
@ -45,7 +46,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/
|
|||
obj-$(CONFIG_USB_SERIAL) += serial/
|
||||
|
||||
obj-$(CONFIG_USB) += misc/
|
||||
obj-$(CONFIG_USB_PHY) += phy/
|
||||
obj-$(CONFIG_USB_SUPPORT) += phy/
|
||||
obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/
|
||||
|
||||
obj-$(CONFIG_USB_ATM) += atm/
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
#
|
||||
# Makefile for USB ATM/xDSL drivers
|
||||
#
|
||||
|
||||
ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
|
||||
|
||||
obj-$(CONFIG_USB_CXACRU) += cxacru.o
|
||||
obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o
|
||||
obj-$(CONFIG_USB_UEAGLEATM) += ueagle-atm.o
|
||||
|
|
|
@ -888,7 +888,7 @@ static int speedtch_bind(struct usbatm_data *usbatm,
|
|||
usb_fill_int_urb(instance->int_urb, usb_dev,
|
||||
usb_rcvintpipe(usb_dev, ENDPOINT_INT),
|
||||
instance->int_data, sizeof(instance->int_data),
|
||||
speedtch_handle_int, instance, 50);
|
||||
speedtch_handle_int, instance, 16);
|
||||
else
|
||||
usb_dbg(usbatm, "%s: no memory for interrupt urb!\n", __func__);
|
||||
|
||||
|
|
|
@ -311,8 +311,6 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char
|
|||
int vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4);
|
||||
u8 pti = ((source[3] & 0xe) >> 1);
|
||||
|
||||
vdbg(&instance->usb_intf->dev, "%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti);
|
||||
|
||||
if ((vci != instance->cached_vci) || (vpi != instance->cached_vpi)) {
|
||||
instance->cached_vpi = vpi;
|
||||
instance->cached_vci = vci;
|
||||
|
@ -344,7 +342,6 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char
|
|||
__func__, sarb->len, vcc);
|
||||
/* discard cells already received */
|
||||
skb_trim(sarb, 0);
|
||||
UDSL_ASSERT(instance, sarb->tail + ATM_CELL_PAYLOAD <= sarb->end);
|
||||
}
|
||||
|
||||
memcpy(skb_tail_pointer(sarb), source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
|
||||
|
@ -437,8 +434,6 @@ static void usbatm_extract_cells(struct usbatm_data *instance,
|
|||
unsigned char *cell_buf = instance->cell_buf;
|
||||
unsigned int space_left = stride - buf_usage;
|
||||
|
||||
UDSL_ASSERT(instance, buf_usage <= stride);
|
||||
|
||||
if (avail_data >= space_left) {
|
||||
/* add new data and process cell */
|
||||
memcpy(cell_buf + buf_usage, source, space_left);
|
||||
|
@ -479,10 +474,6 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance,
|
|||
unsigned int bytes_written;
|
||||
unsigned int stride = instance->tx_channel.stride;
|
||||
|
||||
vdbg(&instance->usb_intf->dev, "%s: skb->len=%d, avail_space=%u",
|
||||
__func__, skb->len, avail_space);
|
||||
UDSL_ASSERT(instance, !(avail_space % stride));
|
||||
|
||||
for (bytes_written = 0; bytes_written < avail_space && ctrl->len;
|
||||
bytes_written += stride, target += stride) {
|
||||
unsigned int data_len = min_t(unsigned int, skb->len, ATM_CELL_PAYLOAD);
|
||||
|
@ -553,8 +544,6 @@ static void usbatm_rx_process(unsigned long data)
|
|||
if (!urb->iso_frame_desc[i].status) {
|
||||
unsigned int actual_length = urb->iso_frame_desc[i].actual_length;
|
||||
|
||||
UDSL_ASSERT(instance, actual_length <= packet_size);
|
||||
|
||||
if (!merge_length)
|
||||
merge_start = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
|
||||
merge_length += actual_length;
|
||||
|
@ -645,7 +634,6 @@ static void usbatm_cancel_send(struct usbatm_data *instance,
|
|||
{
|
||||
struct sk_buff *skb, *n;
|
||||
|
||||
atm_dbg(instance, "%s entered\n", __func__);
|
||||
spin_lock_irq(&instance->sndqueue.lock);
|
||||
skb_queue_walk_safe(&instance->sndqueue, skb, n) {
|
||||
if (UDSL_SKB(skb)->atm.vcc == vcc) {
|
||||
|
@ -663,7 +651,6 @@ static void usbatm_cancel_send(struct usbatm_data *instance,
|
|||
usbatm_pop(vcc, skb);
|
||||
}
|
||||
tasklet_enable(&instance->tx_channel.tasklet);
|
||||
atm_dbg(instance, "%s done\n", __func__);
|
||||
}
|
||||
|
||||
static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
|
||||
|
@ -674,16 +661,13 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
|
|||
|
||||
/* racy disconnection check - fine */
|
||||
if (!instance || instance->disconnected) {
|
||||
#ifdef DEBUG
|
||||
#ifdef VERBOSE_DEBUG
|
||||
printk_ratelimited(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance");
|
||||
#endif
|
||||
err = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
vdbg(&instance->usb_intf->dev, "%s called (skb 0x%p, len %u)", __func__,
|
||||
skb, skb->len);
|
||||
|
||||
if (vcc->qos.aal != ATM_AAL5) {
|
||||
atm_rldbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
|
||||
err = -EINVAL;
|
||||
|
@ -723,8 +707,6 @@ static void usbatm_destroy_instance(struct kref *kref)
|
|||
{
|
||||
struct usbatm_data *instance = container_of(kref, struct usbatm_data, refcount);
|
||||
|
||||
usb_dbg(instance, "%s\n", __func__);
|
||||
|
||||
tasklet_kill(&instance->rx_channel.tasklet);
|
||||
tasklet_kill(&instance->tx_channel.tasklet);
|
||||
usb_put_dev(instance->usb_dev);
|
||||
|
@ -733,15 +715,11 @@ static void usbatm_destroy_instance(struct kref *kref)
|
|||
|
||||
static void usbatm_get_instance(struct usbatm_data *instance)
|
||||
{
|
||||
usb_dbg(instance, "%s\n", __func__);
|
||||
|
||||
kref_get(&instance->refcount);
|
||||
}
|
||||
|
||||
static void usbatm_put_instance(struct usbatm_data *instance)
|
||||
{
|
||||
usb_dbg(instance, "%s\n", __func__);
|
||||
|
||||
kref_put(&instance->refcount, usbatm_destroy_instance);
|
||||
}
|
||||
|
||||
|
@ -757,7 +735,6 @@ static void usbatm_atm_dev_close(struct atm_dev *atm_dev)
|
|||
if (!instance)
|
||||
return;
|
||||
|
||||
usb_dbg(instance, "%s\n", __func__);
|
||||
atm_dev->dev_data = NULL; /* catch bugs */
|
||||
usbatm_put_instance(instance); /* taken in usbatm_atm_init */
|
||||
}
|
||||
|
@ -813,8 +790,6 @@ static int usbatm_atm_open(struct atm_vcc *vcc)
|
|||
if (!instance)
|
||||
return -ENODEV;
|
||||
|
||||
atm_dbg(instance, "%s: vpi %hd, vci %d\n", __func__, vpi, vci);
|
||||
|
||||
/* only support AAL5 */
|
||||
if ((vcc->qos.aal != ATM_AAL5)) {
|
||||
atm_warn(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
|
||||
|
@ -891,11 +866,6 @@ static void usbatm_atm_close(struct atm_vcc *vcc)
|
|||
if (!instance || !vcc_data)
|
||||
return;
|
||||
|
||||
atm_dbg(instance, "%s entered\n", __func__);
|
||||
|
||||
atm_dbg(instance, "%s: deallocating vcc 0x%p with vpi %d vci %d\n",
|
||||
__func__, vcc_data, vcc_data->vpi, vcc_data->vci);
|
||||
|
||||
usbatm_cancel_send(instance, vcc);
|
||||
|
||||
mutex_lock(&instance->serialize); /* vs self, usbatm_atm_open, usbatm_usb_disconnect */
|
||||
|
@ -922,8 +892,6 @@ static void usbatm_atm_close(struct atm_vcc *vcc)
|
|||
clear_bit(ATM_VF_ADDR, &vcc->flags);
|
||||
|
||||
mutex_unlock(&instance->serialize);
|
||||
|
||||
atm_dbg(instance, "%s successful\n", __func__);
|
||||
}
|
||||
|
||||
static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd,
|
||||
|
@ -1060,12 +1028,6 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
|
|||
int i, length;
|
||||
unsigned int maxpacket, num_packets;
|
||||
|
||||
dev_dbg(dev, "%s: trying driver %s with vendor=%04x, product=%04x, ifnum %2d\n",
|
||||
__func__, driver->driver_name,
|
||||
le16_to_cpu(usb_dev->descriptor.idVendor),
|
||||
le16_to_cpu(usb_dev->descriptor.idProduct),
|
||||
intf->altsetting->desc.bInterfaceNumber);
|
||||
|
||||
/* instance init */
|
||||
instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);
|
||||
if (!instance) {
|
||||
|
@ -1158,14 +1120,13 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
|
|||
instance->rx_channel.buf_size = num_packets * maxpacket;
|
||||
instance->rx_channel.packet_size = maxpacket;
|
||||
|
||||
#ifdef DEBUG
|
||||
for (i = 0; i < 2; i++) {
|
||||
struct usbatm_channel *channel = i ?
|
||||
&instance->tx_channel : &instance->rx_channel;
|
||||
|
||||
dev_dbg(dev, "%s: using %d byte buffer for %s channel 0x%p\n", __func__, channel->buf_size, i ? "tx" : "rx", channel);
|
||||
dev_dbg(dev, "%s: using %d byte buffer for %s channel 0x%p\n",
|
||||
__func__, channel->buf_size, i ? "tx" : "rx", channel);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* initialize urbs */
|
||||
|
||||
|
@ -1176,8 +1137,6 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
|
|||
struct urb *urb;
|
||||
unsigned int iso_packets = usb_pipeisoc(channel->endpoint) ? channel->buf_size / channel->packet_size : 0;
|
||||
|
||||
UDSL_ASSERT(instance, !usb_pipeisoc(channel->endpoint) || usb_pipein(channel->endpoint));
|
||||
|
||||
urb = usb_alloc_urb(iso_packets, GFP_KERNEL);
|
||||
if (!urb) {
|
||||
dev_err(dev, "%s: no memory for urb %d!\n", __func__, i);
|
||||
|
@ -1266,8 +1225,6 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
|
|||
struct usbatm_vcc_data *vcc_data;
|
||||
int i;
|
||||
|
||||
dev_dbg(dev, "%s entered\n", __func__);
|
||||
|
||||
if (!instance) {
|
||||
dev_dbg(dev, "%s: NULL instance!\n", __func__);
|
||||
return;
|
||||
|
|
|
@ -39,31 +39,14 @@
|
|||
#define VERBOSE_DEBUG
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
#define UDSL_ASSERT(instance, x) BUG_ON(!(x))
|
||||
#else
|
||||
#define UDSL_ASSERT(instance, x) \
|
||||
do { \
|
||||
if (!(x)) \
|
||||
dev_warn(&(instance)->usb_intf->dev, \
|
||||
"failed assertion '%s' at line %d", \
|
||||
__stringify(x), __LINE__); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define usb_err(instance, format, arg...) \
|
||||
dev_err(&(instance)->usb_intf->dev , format , ## arg)
|
||||
#define usb_info(instance, format, arg...) \
|
||||
dev_info(&(instance)->usb_intf->dev , format , ## arg)
|
||||
#define usb_warn(instance, format, arg...) \
|
||||
dev_warn(&(instance)->usb_intf->dev , format , ## arg)
|
||||
#ifdef DEBUG
|
||||
#define usb_dbg(instance, format, arg...) \
|
||||
dev_printk(KERN_DEBUG , &(instance)->usb_intf->dev , format , ## arg)
|
||||
#else
|
||||
#define usb_dbg(instance, format, arg...) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
dev_dbg(&(instance)->usb_intf->dev , format , ## arg)
|
||||
|
||||
/* FIXME: move to dev_* once ATM is driver model aware */
|
||||
#define atm_printk(level, instance, format, arg...) \
|
||||
|
@ -76,18 +59,12 @@
|
|||
atm_printk(KERN_INFO, instance , format , ## arg)
|
||||
#define atm_warn(instance, format, arg...) \
|
||||
atm_printk(KERN_WARNING, instance , format , ## arg)
|
||||
#ifdef DEBUG
|
||||
#define atm_dbg(instance, format, arg...) \
|
||||
atm_printk(KERN_DEBUG, instance , format , ## arg)
|
||||
#define atm_rldbg(instance, format, arg...) \
|
||||
#define atm_dbg(instance, format, arg...) \
|
||||
dynamic_pr_debug("ATM dev %d: " format , \
|
||||
(instance)->atm_dev->number , ## arg)
|
||||
#define atm_rldbg(instance, format, arg...) \
|
||||
if (printk_ratelimit()) \
|
||||
atm_printk(KERN_DEBUG, instance , format , ## arg)
|
||||
#else
|
||||
#define atm_dbg(instance, format, arg...) \
|
||||
do {} while (0)
|
||||
#define atm_rldbg(instance, format, arg...) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
atm_dbg(instance , format , ## arg)
|
||||
|
||||
|
||||
/* flags, set by mini-driver in bind() */
|
||||
|
|
|
@ -131,7 +131,7 @@ static int c67x00_drv_probe(struct platform_device *pdev)
|
|||
if (!res2)
|
||||
return -ENODEV;
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
if (!pdata)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -154,7 +154,7 @@ static int c67x00_drv_probe(struct platform_device *pdev)
|
|||
|
||||
spin_lock_init(&c67x00->hpi.lock);
|
||||
c67x00->hpi.regstep = pdata->hpi_regstep;
|
||||
c67x00->pdata = pdev->dev.platform_data;
|
||||
c67x00->pdata = dev_get_platdata(&pdev->dev);
|
||||
c67x00->pdev = pdev;
|
||||
|
||||
c67x00_ll_init(c67x00);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
config USB_CHIPIDEA
|
||||
tristate "ChipIdea Highspeed Dual Role Controller"
|
||||
depends on USB || USB_GADGET
|
||||
depends on (USB_EHCI_HCD && USB_GADGET) || (USB_EHCI_HCD && !USB_GADGET) || (!USB_EHCI_HCD && USB_GADGET)
|
||||
help
|
||||
Say Y here if your system has a dual role high speed USB
|
||||
controller based on ChipIdea silicon IP. Currently, only the
|
||||
|
@ -12,15 +12,14 @@ if USB_CHIPIDEA
|
|||
|
||||
config USB_CHIPIDEA_UDC
|
||||
bool "ChipIdea device controller"
|
||||
depends on USB_GADGET=y || (USB_CHIPIDEA=m && USB_GADGET=m)
|
||||
depends on USB_GADGET
|
||||
help
|
||||
Say Y here to enable device controller functionality of the
|
||||
ChipIdea driver.
|
||||
|
||||
config USB_CHIPIDEA_HOST
|
||||
bool "ChipIdea host controller"
|
||||
depends on USB=y
|
||||
depends on USB_EHCI_HCD=y || (USB_CHIPIDEA=m && USB_EHCI_HCD=m)
|
||||
depends on USB_EHCI_HCD
|
||||
select USB_EHCI_ROOT_HUB_TT
|
||||
help
|
||||
Say Y here to enable host controller functionality of the
|
||||
|
|
|
@ -2,7 +2,7 @@ ccflags-$(CONFIG_USB_CHIPIDEA_DEBUG) := -DDEBUG
|
|||
|
||||
obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc.o
|
||||
|
||||
ci_hdrc-y := core.o
|
||||
ci_hdrc-y := core.o otg.o
|
||||
ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o
|
||||
ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o
|
||||
ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o
|
||||
|
|
|
@ -79,11 +79,21 @@
|
|||
#define OTGSC_ASVIS BIT(18)
|
||||
#define OTGSC_BSVIS BIT(19)
|
||||
#define OTGSC_BSEIS BIT(20)
|
||||
#define OTGSC_1MSIS BIT(21)
|
||||
#define OTGSC_DPIS BIT(22)
|
||||
#define OTGSC_IDIE BIT(24)
|
||||
#define OTGSC_AVVIE BIT(25)
|
||||
#define OTGSC_ASVIE BIT(26)
|
||||
#define OTGSC_BSVIE BIT(27)
|
||||
#define OTGSC_BSEIE BIT(28)
|
||||
#define OTGSC_1MSIE BIT(29)
|
||||
#define OTGSC_DPIE BIT(30)
|
||||
#define OTGSC_INT_EN_BITS (OTGSC_IDIE | OTGSC_AVVIE | OTGSC_ASVIE \
|
||||
| OTGSC_BSVIE | OTGSC_BSEIE | OTGSC_1MSIE \
|
||||
| OTGSC_DPIE)
|
||||
#define OTGSC_INT_STATUS_BITS (OTGSC_IDIS | OTGSC_AVVIS | OTGSC_ASVIS \
|
||||
| OTGSC_BSVIS | OTGSC_BSEIS | OTGSC_1MSIS \
|
||||
| OTGSC_DPIS)
|
||||
|
||||
/* USBMODE */
|
||||
#define USBMODE_CM (0x03UL << 0)
|
||||
|
|
|
@ -132,6 +132,9 @@ struct hw_bank {
|
|||
* @transceiver: pointer to USB PHY, if any
|
||||
* @hcd: pointer to usb_hcd for ehci host driver
|
||||
* @debugfs: root dentry for this controller in debugfs
|
||||
* @id_event: indicates there is an id event, and handled at ci_otg_work
|
||||
* @b_sess_valid_event: indicates there is a vbus event, and handled
|
||||
* at ci_otg_work
|
||||
*/
|
||||
struct ci_hdrc {
|
||||
struct device *dev;
|
||||
|
@ -168,6 +171,8 @@ struct ci_hdrc {
|
|||
struct usb_phy *transceiver;
|
||||
struct usb_hcd *hcd;
|
||||
struct dentry *debugfs;
|
||||
bool id_event;
|
||||
bool b_sess_valid_event;
|
||||
};
|
||||
|
||||
static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
|
||||
|
@ -303,4 +308,7 @@ int hw_port_test_set(struct ci_hdrc *ci, u8 mode);
|
|||
|
||||
u8 hw_port_test_get(struct ci_hdrc *ci);
|
||||
|
||||
int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
|
||||
u32 value, unsigned int timeout_ms);
|
||||
|
||||
#endif /* __DRIVERS_USB_CHIPIDEA_CI_H */
|
||||
|
|
|
@ -19,70 +19,56 @@
|
|||
#include <linux/dma-mapping.h>
|
||||
#include <linux/usb/chipidea.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include "ci.h"
|
||||
#include "ci_hdrc_imx.h"
|
||||
|
||||
#define pdev_to_phy(pdev) \
|
||||
((struct usb_phy *)platform_get_drvdata(pdev))
|
||||
|
||||
struct ci_hdrc_imx_data {
|
||||
struct usb_phy *phy;
|
||||
struct platform_device *ci_pdev;
|
||||
struct clk *clk;
|
||||
struct regulator *reg_vbus;
|
||||
struct imx_usbmisc_data *usbmisc_data;
|
||||
};
|
||||
|
||||
static const struct usbmisc_ops *usbmisc_ops;
|
||||
|
||||
/* Common functions shared by usbmisc drivers */
|
||||
|
||||
int usbmisc_set_ops(const struct usbmisc_ops *ops)
|
||||
{
|
||||
if (usbmisc_ops)
|
||||
return -EBUSY;
|
||||
|
||||
usbmisc_ops = ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usbmisc_set_ops);
|
||||
|
||||
void usbmisc_unset_ops(const struct usbmisc_ops *ops)
|
||||
{
|
||||
usbmisc_ops = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usbmisc_unset_ops);
|
||||
|
||||
int usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev)
|
||||
static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
struct of_phandle_args args;
|
||||
struct imx_usbmisc_data *data;
|
||||
int ret;
|
||||
|
||||
usbdev->dev = dev;
|
||||
/*
|
||||
* In case the fsl,usbmisc property is not present this device doesn't
|
||||
* need usbmisc. Return NULL (which is no error here)
|
||||
*/
|
||||
if (!of_get_property(np, "fsl,usbmisc", NULL))
|
||||
return NULL;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = of_parse_phandle_with_args(np, "fsl,usbmisc", "#index-cells",
|
||||
0, &args);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to parse property fsl,usbmisc, errno %d\n",
|
||||
ret);
|
||||
memset(usbdev, 0, sizeof(*usbdev));
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
usbdev->index = args.args[0];
|
||||
|
||||
data->index = args.args[0];
|
||||
of_node_put(args.np);
|
||||
|
||||
if (of_find_property(np, "disable-over-current", NULL))
|
||||
usbdev->disable_oc = 1;
|
||||
data->disable_oc = 1;
|
||||
|
||||
if (of_find_property(np, "external-vbus-divider", NULL))
|
||||
usbdev->evdo = 1;
|
||||
data->evdo = 1;
|
||||
|
||||
return 0;
|
||||
return data;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usbmisc_get_init_data);
|
||||
|
||||
/* End of common functions shared by usbmisc drivers*/
|
||||
|
||||
|
@ -93,27 +79,19 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
|||
.name = "ci_hdrc_imx",
|
||||
.capoffset = DEF_CAPOFFSET,
|
||||
.flags = CI_HDRC_REQUIRE_TRANSCEIVER |
|
||||
CI_HDRC_PULLUP_ON_VBUS |
|
||||
CI_HDRC_DISABLE_STREAMING,
|
||||
};
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
if (of_find_property(pdev->dev.of_node, "fsl,usbmisc", NULL)
|
||||
&& !usbmisc_ops)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
dev_err(&pdev->dev, "Failed to allocate ci_hdrc-imx data!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "Can't get device resources!\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
data->usbmisc_data = usbmisc_get_init_data(&pdev->dev);
|
||||
if (IS_ERR(data->usbmisc_data))
|
||||
return PTR_ERR(data->usbmisc_data);
|
||||
|
||||
data->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(data->clk)) {
|
||||
|
@ -141,20 +119,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
|||
goto err_clk;
|
||||
}
|
||||
|
||||
/* we only support host now, so enable vbus here */
|
||||
data->reg_vbus = devm_regulator_get(&pdev->dev, "vbus");
|
||||
if (!IS_ERR(data->reg_vbus)) {
|
||||
ret = regulator_enable(data->reg_vbus);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to enable vbus regulator, err=%d\n",
|
||||
ret);
|
||||
goto err_clk;
|
||||
}
|
||||
} else {
|
||||
data->reg_vbus = NULL;
|
||||
}
|
||||
|
||||
pdata.phy = data->phy;
|
||||
|
||||
if (!pdev->dev.dma_mask)
|
||||
|
@ -162,12 +126,12 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
|||
if (!pdev->dev.coherent_dma_mask)
|
||||
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
|
||||
|
||||
if (usbmisc_ops && usbmisc_ops->init) {
|
||||
ret = usbmisc_ops->init(&pdev->dev);
|
||||
if (data->usbmisc_data) {
|
||||
ret = imx_usbmisc_init(data->usbmisc_data);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"usbmisc init failed, ret=%d\n", ret);
|
||||
goto err;
|
||||
dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n",
|
||||
ret);
|
||||
goto err_clk;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,14 +143,14 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
|||
dev_err(&pdev->dev,
|
||||
"Can't register ci_hdrc platform device, err=%d\n",
|
||||
ret);
|
||||
goto err;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
if (usbmisc_ops && usbmisc_ops->post) {
|
||||
ret = usbmisc_ops->post(&pdev->dev);
|
||||
if (data->usbmisc_data) {
|
||||
ret = imx_usbmisc_init_post(data->usbmisc_data);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"usbmisc post failed, ret=%d\n", ret);
|
||||
dev_err(&pdev->dev, "usbmisc post failed, ret=%d\n",
|
||||
ret);
|
||||
goto disable_device;
|
||||
}
|
||||
}
|
||||
|
@ -200,9 +164,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
|||
|
||||
disable_device:
|
||||
ci_hdrc_remove_device(data->ci_pdev);
|
||||
err:
|
||||
if (data->reg_vbus)
|
||||
regulator_disable(data->reg_vbus);
|
||||
err_clk:
|
||||
clk_disable_unprepare(data->clk);
|
||||
return ret;
|
||||
|
@ -215,13 +176,8 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
|
|||
pm_runtime_disable(&pdev->dev);
|
||||
ci_hdrc_remove_device(data->ci_pdev);
|
||||
|
||||
if (data->reg_vbus)
|
||||
regulator_disable(data->reg_vbus);
|
||||
|
||||
if (data->phy) {
|
||||
if (data->phy)
|
||||
usb_phy_shutdown(data->phy);
|
||||
module_put(data->phy->dev->driver->owner);
|
||||
}
|
||||
|
||||
clk_disable_unprepare(data->clk);
|
||||
|
||||
|
|
|
@ -9,23 +9,12 @@
|
|||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/* Used to set SoC specific callbacks */
|
||||
struct usbmisc_ops {
|
||||
/* It's called once when probe a usb device */
|
||||
int (*init)(struct device *dev);
|
||||
/* It's called once after adding a usb device */
|
||||
int (*post)(struct device *dev);
|
||||
};
|
||||
|
||||
struct usbmisc_usb_device {
|
||||
struct device *dev; /* usb controller device */
|
||||
struct imx_usbmisc_data {
|
||||
int index;
|
||||
|
||||
unsigned int disable_oc:1; /* over current detect disabled */
|
||||
unsigned int evdo:1; /* set external vbus divider option */
|
||||
};
|
||||
|
||||
int usbmisc_set_ops(const struct usbmisc_ops *ops);
|
||||
void usbmisc_unset_ops(const struct usbmisc_ops *ops);
|
||||
int
|
||||
usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev);
|
||||
int imx_usbmisc_init(struct imx_usbmisc_data *);
|
||||
int imx_usbmisc_init_post(struct imx_usbmisc_data *);
|
||||
|
|
|
@ -49,7 +49,6 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
|
|||
.name = "ci_hdrc_msm",
|
||||
.flags = CI_HDRC_REGS_SHARED |
|
||||
CI_HDRC_REQUIRE_TRANSCEIVER |
|
||||
CI_HDRC_PULLUP_ON_VBUS |
|
||||
CI_HDRC_DISABLE_STREAMING,
|
||||
|
||||
.notify_event = ci_hdrc_msm_notify_event,
|
||||
|
|
|
@ -65,12 +65,14 @@
|
|||
#include <linux/usb/chipidea.h>
|
||||
#include <linux/usb/of.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include "ci.h"
|
||||
#include "udc.h"
|
||||
#include "bits.h"
|
||||
#include "host.h"
|
||||
#include "debug.h"
|
||||
#include "otg.h"
|
||||
|
||||
/* Controller register map */
|
||||
static uintptr_t ci_regs_nolpm[] = {
|
||||
|
@ -197,6 +199,12 @@ static int hw_device_init(struct ci_hdrc *ci, void __iomem *base)
|
|||
if (ci->hw_ep_max > ENDPT_MAX)
|
||||
return -ENODEV;
|
||||
|
||||
/* Disable all interrupts bits */
|
||||
hw_write(ci, OP_USBINTR, 0xffffffff, 0);
|
||||
|
||||
/* Clear all interrupts status bits*/
|
||||
hw_write(ci, OP_USBSTS, 0xffffffff, 0xffffffff);
|
||||
|
||||
dev_dbg(ci->dev, "ChipIdea HDRC found, lpm: %d; cap: %p op: %p\n",
|
||||
ci->hw_bank.lpm, ci->hw_bank.cap, ci->hw_bank.op);
|
||||
|
||||
|
@ -264,8 +272,6 @@ int hw_device_reset(struct ci_hdrc *ci, u32 mode)
|
|||
while (hw_read(ci, OP_USBCMD, USBCMD_RST))
|
||||
udelay(10); /* not RTOS friendly */
|
||||
|
||||
hw_phymode_configure(ci);
|
||||
|
||||
if (ci->platdata->notify_event)
|
||||
ci->platdata->notify_event(ci,
|
||||
CI_HDRC_CONTROLLER_RESET_EVENT);
|
||||
|
@ -289,37 +295,35 @@ int hw_device_reset(struct ci_hdrc *ci, u32 mode)
|
|||
}
|
||||
|
||||
/**
|
||||
* ci_otg_role - pick role based on ID pin state
|
||||
* hw_wait_reg: wait the register value
|
||||
*
|
||||
* Sometimes, it needs to wait register value before going on.
|
||||
* Eg, when switch to device mode, the vbus value should be lower
|
||||
* than OTGSC_BSV before connects to host.
|
||||
*
|
||||
* @ci: the controller
|
||||
* @reg: register index
|
||||
* @mask: mast bit
|
||||
* @value: the bit value to wait
|
||||
* @timeout_ms: timeout in millisecond
|
||||
*
|
||||
* This function returns an error code if timeout
|
||||
*/
|
||||
static enum ci_role ci_otg_role(struct ci_hdrc *ci)
|
||||
int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
|
||||
u32 value, unsigned int timeout_ms)
|
||||
{
|
||||
u32 sts = hw_read(ci, OP_OTGSC, ~0);
|
||||
enum ci_role role = sts & OTGSC_ID
|
||||
? CI_ROLE_GADGET
|
||||
: CI_ROLE_HOST;
|
||||
unsigned long elapse = jiffies + msecs_to_jiffies(timeout_ms);
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
/**
|
||||
* ci_role_work - perform role changing based on ID pin
|
||||
* @work: work struct
|
||||
*/
|
||||
static void ci_role_work(struct work_struct *work)
|
||||
{
|
||||
struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work);
|
||||
enum ci_role role = ci_otg_role(ci);
|
||||
|
||||
if (role != ci->role) {
|
||||
dev_dbg(ci->dev, "switching from %s to %s\n",
|
||||
ci_role(ci)->name, ci->roles[role]->name);
|
||||
|
||||
ci_role_stop(ci);
|
||||
ci_role_start(ci, role);
|
||||
while (hw_read(ci, reg, mask) != value) {
|
||||
if (time_after(jiffies, elapse)) {
|
||||
dev_err(ci->dev, "timeout waiting for %08x in %d\n",
|
||||
mask, reg);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
enable_irq(ci->irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t ci_irq(int irq, void *data)
|
||||
|
@ -331,17 +335,53 @@ static irqreturn_t ci_irq(int irq, void *data)
|
|||
if (ci->is_otg)
|
||||
otgsc = hw_read(ci, OP_OTGSC, ~0);
|
||||
|
||||
/*
|
||||
* Handle id change interrupt, it indicates device/host function
|
||||
* switch.
|
||||
*/
|
||||
if (ci->is_otg && (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS)) {
|
||||
ci->id_event = true;
|
||||
ci_clear_otg_interrupt(ci, OTGSC_IDIS);
|
||||
disable_irq_nosync(ci->irq);
|
||||
queue_work(ci->wq, &ci->work);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle vbus change interrupt, it indicates device connection
|
||||
* and disconnection events.
|
||||
*/
|
||||
if (ci->is_otg && (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS)) {
|
||||
ci->b_sess_valid_event = true;
|
||||
ci_clear_otg_interrupt(ci, OTGSC_BSVIS);
|
||||
disable_irq_nosync(ci->irq);
|
||||
queue_work(ci->wq, &ci->work);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* Handle device/host interrupt */
|
||||
if (ci->role != CI_ROLE_END)
|
||||
ret = ci_role(ci)->irq(ci);
|
||||
|
||||
if (ci->is_otg && (otgsc & OTGSC_IDIS)) {
|
||||
hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS);
|
||||
disable_irq_nosync(ci->irq);
|
||||
queue_work(ci->wq, &ci->work);
|
||||
ret = IRQ_HANDLED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ci_get_platdata(struct device *dev,
|
||||
struct ci_hdrc_platform_data *platdata)
|
||||
{
|
||||
/* Get the vbus regulator */
|
||||
platdata->reg_vbus = devm_regulator_get(dev, "vbus");
|
||||
if (PTR_ERR(platdata->reg_vbus) == -EPROBE_DEFER) {
|
||||
return -EPROBE_DEFER;
|
||||
} else if (PTR_ERR(platdata->reg_vbus) == -ENODEV) {
|
||||
platdata->reg_vbus = NULL; /* no vbus regualator is needed */
|
||||
} else if (IS_ERR(platdata->reg_vbus)) {
|
||||
dev_err(dev, "Getting regulator error: %ld\n",
|
||||
PTR_ERR(platdata->reg_vbus));
|
||||
return PTR_ERR(platdata->reg_vbus);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_IDA(ci_ida);
|
||||
|
@ -353,6 +393,10 @@ struct platform_device *ci_hdrc_add_device(struct device *dev,
|
|||
struct platform_device *pdev;
|
||||
int id, ret;
|
||||
|
||||
ret = ci_get_platdata(dev, platdata);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
id = ida_simple_get(&ci_ida, 0, 0, GFP_KERNEL);
|
||||
if (id < 0)
|
||||
return ERR_PTR(id);
|
||||
|
@ -398,6 +442,29 @@ void ci_hdrc_remove_device(struct platform_device *pdev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(ci_hdrc_remove_device);
|
||||
|
||||
static inline void ci_role_destroy(struct ci_hdrc *ci)
|
||||
{
|
||||
ci_hdrc_gadget_destroy(ci);
|
||||
ci_hdrc_host_destroy(ci);
|
||||
if (ci->is_otg)
|
||||
ci_hdrc_otg_destroy(ci);
|
||||
}
|
||||
|
||||
static void ci_get_otg_capable(struct ci_hdrc *ci)
|
||||
{
|
||||
if (ci->platdata->flags & CI_HDRC_DUAL_ROLE_NOT_OTG)
|
||||
ci->is_otg = false;
|
||||
else
|
||||
ci->is_otg = (hw_read(ci, CAP_DCCPARAMS,
|
||||
DCCPARAMS_DC | DCCPARAMS_HC)
|
||||
== (DCCPARAMS_DC | DCCPARAMS_HC));
|
||||
if (ci->is_otg) {
|
||||
dev_dbg(ci->dev, "It is OTG capable controller\n");
|
||||
ci_disable_otg_interrupt(ci, OTGSC_INT_EN_BITS);
|
||||
ci_clear_otg_interrupt(ci, OTGSC_INT_STATUS_BITS);
|
||||
}
|
||||
}
|
||||
|
||||
static int ci_hdrc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
@ -406,15 +473,13 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
|||
void __iomem *base;
|
||||
int ret;
|
||||
enum usb_dr_mode dr_mode;
|
||||
struct device_node *of_node = dev->of_node ?: dev->parent->of_node;
|
||||
|
||||
if (!dev->platform_data) {
|
||||
dev_err(dev, "platform data missing\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!dev->of_node && dev->parent)
|
||||
dev->of_node = dev->parent->of_node;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(base))
|
||||
|
@ -447,18 +512,15 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
INIT_WORK(&ci->work, ci_role_work);
|
||||
ci->wq = create_singlethread_workqueue("ci_otg");
|
||||
if (!ci->wq) {
|
||||
dev_err(dev, "can't create workqueue\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
ci_get_otg_capable(ci);
|
||||
|
||||
if (!ci->platdata->phy_mode)
|
||||
ci->platdata->phy_mode = of_usb_get_phy_mode(dev->of_node);
|
||||
ci->platdata->phy_mode = of_usb_get_phy_mode(of_node);
|
||||
|
||||
hw_phymode_configure(ci);
|
||||
|
||||
if (!ci->platdata->dr_mode)
|
||||
ci->platdata->dr_mode = of_usb_get_dr_mode(dev->of_node);
|
||||
ci->platdata->dr_mode = of_usb_get_dr_mode(of_node);
|
||||
|
||||
if (ci->platdata->dr_mode == USB_DR_MODE_UNKNOWN)
|
||||
ci->platdata->dr_mode = USB_DR_MODE_OTG;
|
||||
|
@ -479,15 +541,34 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
|||
|
||||
if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) {
|
||||
dev_err(dev, "no supported roles\n");
|
||||
ret = -ENODEV;
|
||||
goto rm_wq;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (ci->is_otg) {
|
||||
ret = ci_hdrc_otg_init(ci);
|
||||
if (ret) {
|
||||
dev_err(dev, "init otg fails, ret = %d\n", ret);
|
||||
goto stop;
|
||||
}
|
||||
}
|
||||
|
||||
if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) {
|
||||
ci->is_otg = true;
|
||||
/* ID pin needs 1ms debouce time, we delay 2ms for safe */
|
||||
mdelay(2);
|
||||
ci->role = ci_otg_role(ci);
|
||||
if (ci->is_otg) {
|
||||
/*
|
||||
* ID pin needs 1ms debouce time,
|
||||
* we delay 2ms for safe.
|
||||
*/
|
||||
mdelay(2);
|
||||
ci->role = ci_otg_role(ci);
|
||||
ci_enable_otg_interrupt(ci, OTGSC_IDIE);
|
||||
} else {
|
||||
/*
|
||||
* If the controller is not OTG capable, but support
|
||||
* role switch, the defalt role is gadget, and the
|
||||
* user can switch it through debugfs.
|
||||
*/
|
||||
ci->role = CI_ROLE_GADGET;
|
||||
}
|
||||
} else {
|
||||
ci->role = ci->roles[CI_ROLE_HOST]
|
||||
? CI_ROLE_HOST
|
||||
|
@ -497,8 +578,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
|||
ret = ci_role_start(ci, ci->role);
|
||||
if (ret) {
|
||||
dev_err(dev, "can't start %s role\n", ci_role(ci)->name);
|
||||
ret = -ENODEV;
|
||||
goto rm_wq;
|
||||
goto stop;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, ci);
|
||||
|
@ -507,19 +587,13 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto stop;
|
||||
|
||||
if (ci->is_otg)
|
||||
hw_write(ci, OP_OTGSC, OTGSC_IDIE, OTGSC_IDIE);
|
||||
|
||||
ret = dbg_create_files(ci);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
free_irq(ci->irq, ci);
|
||||
stop:
|
||||
ci_role_stop(ci);
|
||||
rm_wq:
|
||||
flush_workqueue(ci->wq);
|
||||
destroy_workqueue(ci->wq);
|
||||
ci_role_destroy(ci);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -529,10 +603,8 @@ static int ci_hdrc_remove(struct platform_device *pdev)
|
|||
struct ci_hdrc *ci = platform_get_drvdata(pdev);
|
||||
|
||||
dbg_remove_files(ci);
|
||||
flush_workqueue(ci->wq);
|
||||
destroy_workqueue(ci->wq);
|
||||
free_irq(ci->irq, ci);
|
||||
ci_role_stop(ci);
|
||||
ci_role_destroy(ci);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -548,7 +620,6 @@ static struct platform_driver ci_hdrc_driver = {
|
|||
module_platform_driver(ci_hdrc_driver);
|
||||
|
||||
MODULE_ALIAS("platform:ci_hdrc");
|
||||
MODULE_ALIAS("platform:ci13xxx");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("David Lopo <dlopo@chipidea.mips.com>");
|
||||
MODULE_DESCRIPTION("ChipIdea HDRC Driver");
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/usb.h>
|
||||
#include <linux/usb/hcd.h>
|
||||
#include <linux/usb/chipidea.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include "../host/ehci.h"
|
||||
|
||||
|
@ -63,10 +64,21 @@ static int host_start(struct ci_hdrc *ci)
|
|||
ehci = hcd_to_ehci(hcd);
|
||||
ehci->caps = ci->hw_bank.cap;
|
||||
ehci->has_hostpc = ci->hw_bank.lpm;
|
||||
ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
|
||||
|
||||
if (ci->platdata->reg_vbus) {
|
||||
ret = regulator_enable(ci->platdata->reg_vbus);
|
||||
if (ret) {
|
||||
dev_err(ci->dev,
|
||||
"Failed to enable vbus regulator, ret=%d\n",
|
||||
ret);
|
||||
goto put_hcd;
|
||||
}
|
||||
}
|
||||
|
||||
ret = usb_add_hcd(hcd, 0, 0);
|
||||
if (ret)
|
||||
usb_put_hcd(hcd);
|
||||
goto disable_reg;
|
||||
else
|
||||
ci->hcd = hcd;
|
||||
|
||||
|
@ -74,6 +86,14 @@ static int host_start(struct ci_hdrc *ci)
|
|||
hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
|
||||
|
||||
return ret;
|
||||
|
||||
disable_reg:
|
||||
regulator_disable(ci->platdata->reg_vbus);
|
||||
|
||||
put_hcd:
|
||||
usb_put_hcd(hcd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void host_stop(struct ci_hdrc *ci)
|
||||
|
@ -82,6 +102,15 @@ static void host_stop(struct ci_hdrc *ci)
|
|||
|
||||
usb_remove_hcd(hcd);
|
||||
usb_put_hcd(hcd);
|
||||
if (ci->platdata->reg_vbus)
|
||||
regulator_disable(ci->platdata->reg_vbus);
|
||||
}
|
||||
|
||||
|
||||
void ci_hdrc_host_destroy(struct ci_hdrc *ci)
|
||||
{
|
||||
if (ci->role == CI_ROLE_HOST)
|
||||
host_stop(ci);
|
||||
}
|
||||
|
||||
int ci_hdrc_host_init(struct ci_hdrc *ci)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#ifdef CONFIG_USB_CHIPIDEA_HOST
|
||||
|
||||
int ci_hdrc_host_init(struct ci_hdrc *ci);
|
||||
void ci_hdrc_host_destroy(struct ci_hdrc *ci);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -12,6 +13,11 @@ static inline int ci_hdrc_host_init(struct ci_hdrc *ci)
|
|||
return -ENXIO;
|
||||
}
|
||||
|
||||
static inline void ci_hdrc_host_destroy(struct ci_hdrc *ci)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __DRIVERS_USB_CHIPIDEA_HOST_H */
|
||||
|
|
120
drivers/usb/chipidea/otg.c
Normal file
120
drivers/usb/chipidea/otg.c
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* otg.c - ChipIdea USB IP core OTG driver
|
||||
*
|
||||
* Copyright (C) 2013 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* Author: Peter Chen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file mainly handles otgsc register, it may include OTG operation
|
||||
* in the future.
|
||||
*/
|
||||
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include <linux/usb/chipidea.h>
|
||||
|
||||
#include "ci.h"
|
||||
#include "bits.h"
|
||||
#include "otg.h"
|
||||
|
||||
/**
|
||||
* ci_otg_role - pick role based on ID pin state
|
||||
* @ci: the controller
|
||||
*/
|
||||
enum ci_role ci_otg_role(struct ci_hdrc *ci)
|
||||
{
|
||||
u32 sts = hw_read(ci, OP_OTGSC, ~0);
|
||||
enum ci_role role = sts & OTGSC_ID
|
||||
? CI_ROLE_GADGET
|
||||
: CI_ROLE_HOST;
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
void ci_handle_vbus_change(struct ci_hdrc *ci)
|
||||
{
|
||||
u32 otgsc;
|
||||
|
||||
if (!ci->is_otg)
|
||||
return;
|
||||
|
||||
otgsc = hw_read(ci, OP_OTGSC, ~0);
|
||||
|
||||
if (otgsc & OTGSC_BSV)
|
||||
usb_gadget_vbus_connect(&ci->gadget);
|
||||
else
|
||||
usb_gadget_vbus_disconnect(&ci->gadget);
|
||||
}
|
||||
|
||||
#define CI_VBUS_STABLE_TIMEOUT_MS 5000
|
||||
static void ci_handle_id_switch(struct ci_hdrc *ci)
|
||||
{
|
||||
enum ci_role role = ci_otg_role(ci);
|
||||
|
||||
if (role != ci->role) {
|
||||
dev_dbg(ci->dev, "switching from %s to %s\n",
|
||||
ci_role(ci)->name, ci->roles[role]->name);
|
||||
|
||||
ci_role_stop(ci);
|
||||
/* wait vbus lower than OTGSC_BSV */
|
||||
hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,
|
||||
CI_VBUS_STABLE_TIMEOUT_MS);
|
||||
ci_role_start(ci, role);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ci_otg_work - perform otg (vbus/id) event handle
|
||||
* @work: work struct
|
||||
*/
|
||||
static void ci_otg_work(struct work_struct *work)
|
||||
{
|
||||
struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work);
|
||||
|
||||
if (ci->id_event) {
|
||||
ci->id_event = false;
|
||||
ci_handle_id_switch(ci);
|
||||
} else if (ci->b_sess_valid_event) {
|
||||
ci->b_sess_valid_event = false;
|
||||
ci_handle_vbus_change(ci);
|
||||
} else
|
||||
dev_err(ci->dev, "unexpected event occurs at %s\n", __func__);
|
||||
|
||||
enable_irq(ci->irq);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ci_hdrc_otg_init - initialize otg struct
|
||||
* ci: the controller
|
||||
*/
|
||||
int ci_hdrc_otg_init(struct ci_hdrc *ci)
|
||||
{
|
||||
INIT_WORK(&ci->work, ci_otg_work);
|
||||
ci->wq = create_singlethread_workqueue("ci_otg");
|
||||
if (!ci->wq) {
|
||||
dev_err(ci->dev, "can't create workqueue\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ci_hdrc_otg_destroy - destroy otg struct
|
||||
* ci: the controller
|
||||
*/
|
||||
void ci_hdrc_otg_destroy(struct ci_hdrc *ci)
|
||||
{
|
||||
if (ci->wq) {
|
||||
flush_workqueue(ci->wq);
|
||||
destroy_workqueue(ci->wq);
|
||||
}
|
||||
ci_disable_otg_interrupt(ci, OTGSC_INT_EN_BITS);
|
||||
ci_clear_otg_interrupt(ci, OTGSC_INT_STATUS_BITS);
|
||||
}
|
35
drivers/usb/chipidea/otg.h
Normal file
35
drivers/usb/chipidea/otg.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* Author: Peter Chen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_USB_CHIPIDEA_OTG_H
|
||||
#define __DRIVERS_USB_CHIPIDEA_OTG_H
|
||||
|
||||
static inline void ci_clear_otg_interrupt(struct ci_hdrc *ci, u32 bits)
|
||||
{
|
||||
/* Only clear request bits */
|
||||
hw_write(ci, OP_OTGSC, OTGSC_INT_STATUS_BITS, bits);
|
||||
}
|
||||
|
||||
static inline void ci_enable_otg_interrupt(struct ci_hdrc *ci, u32 bits)
|
||||
{
|
||||
hw_write(ci, OP_OTGSC, bits, bits);
|
||||
}
|
||||
|
||||
static inline void ci_disable_otg_interrupt(struct ci_hdrc *ci, u32 bits)
|
||||
{
|
||||
hw_write(ci, OP_OTGSC, bits, 0);
|
||||
}
|
||||
|
||||
int ci_hdrc_otg_init(struct ci_hdrc *ci);
|
||||
void ci_hdrc_otg_destroy(struct ci_hdrc *ci);
|
||||
enum ci_role ci_otg_role(struct ci_hdrc *ci);
|
||||
void ci_handle_vbus_change(struct ci_hdrc *ci);
|
||||
|
||||
#endif /* __DRIVERS_USB_CHIPIDEA_OTG_H */
|
|
@ -27,6 +27,7 @@
|
|||
#include "udc.h"
|
||||
#include "bits.h"
|
||||
#include "debug.h"
|
||||
#include "otg.h"
|
||||
|
||||
/* control endpoint description */
|
||||
static const struct usb_endpoint_descriptor
|
||||
|
@ -84,8 +85,10 @@ static int hw_device_state(struct ci_hdrc *ci, u32 dma)
|
|||
/* interrupt, error, port change, reset, sleep/suspend */
|
||||
hw_write(ci, OP_USBINTR, ~0,
|
||||
USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
|
||||
hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
|
||||
} else {
|
||||
hw_write(ci, OP_USBINTR, ~0, 0);
|
||||
hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1445,9 +1448,6 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
|
|||
unsigned long flags;
|
||||
int gadget_ready = 0;
|
||||
|
||||
if (!(ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
spin_lock_irqsave(&ci->lock, flags);
|
||||
ci->vbus_active = is_active;
|
||||
if (ci->driver)
|
||||
|
@ -1459,6 +1459,7 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
|
|||
pm_runtime_get_sync(&_gadget->dev);
|
||||
hw_device_reset(ci, USBMODE_CM_DC);
|
||||
hw_device_state(ci, ci->ep0out->qh.dma);
|
||||
dev_dbg(ci->dev, "Connected to host\n");
|
||||
} else {
|
||||
hw_device_state(ci, 0);
|
||||
if (ci->platdata->notify_event)
|
||||
|
@ -1466,6 +1467,7 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
|
|||
CI_HDRC_CONTROLLER_STOPPED_EVENT);
|
||||
_gadget_stop_activity(&ci->gadget);
|
||||
pm_runtime_put_sync(&_gadget->dev);
|
||||
dev_dbg(ci->dev, "Disconnected from host\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1509,6 +1511,9 @@ static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on)
|
|||
{
|
||||
struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget);
|
||||
|
||||
if (!ci->vbus_active)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (is_on)
|
||||
hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
|
||||
else
|
||||
|
@ -1630,14 +1635,11 @@ static int ci_udc_start(struct usb_gadget *gadget,
|
|||
|
||||
ci->driver = driver;
|
||||
pm_runtime_get_sync(&ci->gadget.dev);
|
||||
if (ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS) {
|
||||
if (ci->vbus_active) {
|
||||
if (ci->platdata->flags & CI_HDRC_REGS_SHARED)
|
||||
hw_device_reset(ci, USBMODE_CM_DC);
|
||||
} else {
|
||||
pm_runtime_put_sync(&ci->gadget.dev);
|
||||
goto done;
|
||||
}
|
||||
if (ci->vbus_active) {
|
||||
hw_device_reset(ci, USBMODE_CM_DC);
|
||||
} else {
|
||||
pm_runtime_put_sync(&ci->gadget.dev);
|
||||
goto done;
|
||||
}
|
||||
|
||||
retval = hw_device_state(ci, ci->ep0out->qh.dma);
|
||||
|
@ -1660,8 +1662,7 @@ static int ci_udc_stop(struct usb_gadget *gadget,
|
|||
|
||||
spin_lock_irqsave(&ci->lock, flags);
|
||||
|
||||
if (!(ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS) ||
|
||||
ci->vbus_active) {
|
||||
if (ci->vbus_active) {
|
||||
hw_device_state(ci, 0);
|
||||
if (ci->platdata->notify_event)
|
||||
ci->platdata->notify_event(ci,
|
||||
|
@ -1796,16 +1797,15 @@ static int udc_start(struct ci_hdrc *ci)
|
|||
}
|
||||
}
|
||||
|
||||
if (!(ci->platdata->flags & CI_HDRC_REGS_SHARED)) {
|
||||
retval = hw_device_reset(ci, USBMODE_CM_DC);
|
||||
if (retval)
|
||||
goto put_transceiver;
|
||||
}
|
||||
|
||||
if (ci->transceiver) {
|
||||
retval = otg_set_peripheral(ci->transceiver->otg,
|
||||
&ci->gadget);
|
||||
if (retval)
|
||||
/*
|
||||
* If we implement all USB functions using chipidea drivers,
|
||||
* it doesn't need to call above API, meanwhile, if we only
|
||||
* use gadget function, calling above API is useless.
|
||||
*/
|
||||
if (retval && retval != -ENOTSUPP)
|
||||
goto put_transceiver;
|
||||
}
|
||||
|
||||
|
@ -1816,6 +1816,9 @@ static int udc_start(struct ci_hdrc *ci)
|
|||
pm_runtime_no_callbacks(&ci->gadget.dev);
|
||||
pm_runtime_enable(&ci->gadget.dev);
|
||||
|
||||
/* Update ci->vbus_active */
|
||||
ci_handle_vbus_change(ci);
|
||||
|
||||
return retval;
|
||||
|
||||
remove_trans:
|
||||
|
@ -1839,13 +1842,13 @@ free_qh_pool:
|
|||
}
|
||||
|
||||
/**
|
||||
* udc_remove: parent remove must call this to remove UDC
|
||||
* ci_hdrc_gadget_destroy: parent remove must call this to remove UDC
|
||||
*
|
||||
* No interrupts active, the IRQ has been released
|
||||
*/
|
||||
static void udc_stop(struct ci_hdrc *ci)
|
||||
void ci_hdrc_gadget_destroy(struct ci_hdrc *ci)
|
||||
{
|
||||
if (ci == NULL)
|
||||
if (!ci->roles[CI_ROLE_GADGET])
|
||||
return;
|
||||
|
||||
usb_del_gadget_udc(&ci->gadget);
|
||||
|
@ -1860,15 +1863,32 @@ static void udc_stop(struct ci_hdrc *ci)
|
|||
if (ci->global_phy)
|
||||
usb_put_phy(ci->transceiver);
|
||||
}
|
||||
/* my kobject is dynamic, I swear! */
|
||||
memset(&ci->gadget, 0, sizeof(ci->gadget));
|
||||
}
|
||||
|
||||
static int udc_id_switch_for_device(struct ci_hdrc *ci)
|
||||
{
|
||||
if (ci->is_otg) {
|
||||
ci_clear_otg_interrupt(ci, OTGSC_BSVIS);
|
||||
ci_enable_otg_interrupt(ci, OTGSC_BSVIE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void udc_id_switch_for_host(struct ci_hdrc *ci)
|
||||
{
|
||||
if (ci->is_otg) {
|
||||
/* host doesn't care B_SESSION_VALID event */
|
||||
ci_clear_otg_interrupt(ci, OTGSC_BSVIS);
|
||||
ci_disable_otg_interrupt(ci, OTGSC_BSVIE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ci_hdrc_gadget_init - initialize device related bits
|
||||
* ci: the controller
|
||||
*
|
||||
* This function enables the gadget role, if the device is "device capable".
|
||||
* This function initializes the gadget, if the device is "device capable".
|
||||
*/
|
||||
int ci_hdrc_gadget_init(struct ci_hdrc *ci)
|
||||
{
|
||||
|
@ -1881,11 +1901,11 @@ int ci_hdrc_gadget_init(struct ci_hdrc *ci)
|
|||
if (!rdrv)
|
||||
return -ENOMEM;
|
||||
|
||||
rdrv->start = udc_start;
|
||||
rdrv->stop = udc_stop;
|
||||
rdrv->start = udc_id_switch_for_device;
|
||||
rdrv->stop = udc_id_switch_for_host;
|
||||
rdrv->irq = udc_irq;
|
||||
rdrv->name = "gadget";
|
||||
ci->roles[CI_ROLE_GADGET] = rdrv;
|
||||
|
||||
return 0;
|
||||
return udc_start(ci);
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ struct ci_hw_req {
|
|||
#ifdef CONFIG_USB_CHIPIDEA_UDC
|
||||
|
||||
int ci_hdrc_gadget_init(struct ci_hdrc *ci);
|
||||
void ci_hdrc_gadget_destroy(struct ci_hdrc *ci);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -92,6 +93,11 @@ static inline int ci_hdrc_gadget_init(struct ci_hdrc *ci)
|
|||
return -ENXIO;
|
||||
}
|
||||
|
||||
static inline void ci_hdrc_gadget_destroy(struct ci_hdrc *ci)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __DRIVERS_USB_CHIPIDEA_UDC_H */
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
#include "ci_hdrc_imx.h"
|
||||
|
||||
#define USB_DEV_MAX 4
|
||||
|
||||
#define MX25_USB_PHY_CTRL_OFFSET 0x08
|
||||
#define MX25_BM_EXTERNAL_VBUS_DIVIDER BIT(23)
|
||||
|
||||
|
@ -32,51 +30,34 @@
|
|||
|
||||
#define MX6_BM_OVER_CUR_DIS BIT(7)
|
||||
|
||||
struct usbmisc_ops {
|
||||
/* It's called once when probe a usb device */
|
||||
int (*init)(struct imx_usbmisc_data *data);
|
||||
/* It's called once after adding a usb device */
|
||||
int (*post)(struct imx_usbmisc_data *data);
|
||||
};
|
||||
|
||||
struct imx_usbmisc {
|
||||
void __iomem *base;
|
||||
spinlock_t lock;
|
||||
struct clk *clk;
|
||||
struct usbmisc_usb_device usbdev[USB_DEV_MAX];
|
||||
const struct usbmisc_ops *ops;
|
||||
};
|
||||
|
||||
static struct imx_usbmisc *usbmisc;
|
||||
|
||||
static struct usbmisc_usb_device *get_usbdev(struct device *dev)
|
||||
static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < USB_DEV_MAX; i++) {
|
||||
if (usbmisc->usbdev[i].dev == dev)
|
||||
return &usbmisc->usbdev[i];
|
||||
else if (!usbmisc->usbdev[i].dev)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= USB_DEV_MAX)
|
||||
return ERR_PTR(-EBUSY);
|
||||
|
||||
ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return &usbmisc->usbdev[i];
|
||||
}
|
||||
|
||||
static int usbmisc_imx25_post(struct device *dev)
|
||||
{
|
||||
struct usbmisc_usb_device *usbdev;
|
||||
void __iomem *reg;
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
usbdev = get_usbdev(dev);
|
||||
if (IS_ERR(usbdev))
|
||||
return PTR_ERR(usbdev);
|
||||
if (data->index > 2)
|
||||
return -EINVAL;
|
||||
|
||||
reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
|
||||
|
||||
if (usbdev->evdo) {
|
||||
if (data->evdo) {
|
||||
spin_lock_irqsave(&usbmisc->lock, flags);
|
||||
val = readl(reg);
|
||||
writel(val | MX25_BM_EXTERNAL_VBUS_DIVIDER, reg);
|
||||
|
@ -87,20 +68,18 @@ static int usbmisc_imx25_post(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int usbmisc_imx53_init(struct device *dev)
|
||||
static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
|
||||
{
|
||||
struct usbmisc_usb_device *usbdev;
|
||||
void __iomem *reg = NULL;
|
||||
unsigned long flags;
|
||||
u32 val = 0;
|
||||
|
||||
usbdev = get_usbdev(dev);
|
||||
if (IS_ERR(usbdev))
|
||||
return PTR_ERR(usbdev);
|
||||
if (data->index > 3)
|
||||
return -EINVAL;
|
||||
|
||||
if (usbdev->disable_oc) {
|
||||
if (data->disable_oc) {
|
||||
spin_lock_irqsave(&usbmisc->lock, flags);
|
||||
switch (usbdev->index) {
|
||||
switch (data->index) {
|
||||
case 0:
|
||||
reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
|
||||
val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
|
||||
|
@ -126,22 +105,19 @@ static int usbmisc_imx53_init(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int usbmisc_imx6q_init(struct device *dev)
|
||||
static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
|
||||
{
|
||||
|
||||
struct usbmisc_usb_device *usbdev;
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
usbdev = get_usbdev(dev);
|
||||
if (IS_ERR(usbdev))
|
||||
return PTR_ERR(usbdev);
|
||||
if (data->index > 3)
|
||||
return -EINVAL;
|
||||
|
||||
if (usbdev->disable_oc) {
|
||||
if (data->disable_oc) {
|
||||
spin_lock_irqsave(&usbmisc->lock, flags);
|
||||
reg = readl(usbmisc->base + usbdev->index * 4);
|
||||
reg = readl(usbmisc->base + data->index * 4);
|
||||
writel(reg | MX6_BM_OVER_CUR_DIS,
|
||||
usbmisc->base + usbdev->index * 4);
|
||||
usbmisc->base + data->index * 4);
|
||||
spin_unlock_irqrestore(&usbmisc->lock, flags);
|
||||
}
|
||||
|
||||
|
@ -160,6 +136,26 @@ static const struct usbmisc_ops imx6q_usbmisc_ops = {
|
|||
.init = usbmisc_imx6q_init,
|
||||
};
|
||||
|
||||
int imx_usbmisc_init(struct imx_usbmisc_data *data)
|
||||
{
|
||||
if (!usbmisc)
|
||||
return -EPROBE_DEFER;
|
||||
if (!usbmisc->ops->init)
|
||||
return 0;
|
||||
return usbmisc->ops->init(data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(imx_usbmisc_init);
|
||||
|
||||
int imx_usbmisc_init_post(struct imx_usbmisc_data *data)
|
||||
{
|
||||
if (!usbmisc)
|
||||
return -EPROBE_DEFER;
|
||||
if (!usbmisc->ops->post)
|
||||
return 0;
|
||||
return usbmisc->ops->post(data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);
|
||||
|
||||
static const struct of_device_id usbmisc_imx_dt_ids[] = {
|
||||
{
|
||||
.compatible = "fsl,imx25-usbmisc",
|
||||
|
@ -216,19 +212,12 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
|
|||
of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
|
||||
data->ops = (const struct usbmisc_ops *)tmp_dev->data;
|
||||
usbmisc = data;
|
||||
ret = usbmisc_set_ops(data->ops);
|
||||
if (ret) {
|
||||
usbmisc = NULL;
|
||||
clk_disable_unprepare(data->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbmisc_imx_remove(struct platform_device *pdev)
|
||||
{
|
||||
usbmisc_unset_ops(usbmisc->ops);
|
||||
clk_disable_unprepare(usbmisc->clk);
|
||||
usbmisc = NULL;
|
||||
return 0;
|
||||
|
|
|
@ -1295,7 +1295,7 @@ skip_countries:
|
|||
usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress),
|
||||
acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm,
|
||||
/* works around buggy devices */
|
||||
epctrl->bInterval ? epctrl->bInterval : 0xff);
|
||||
epctrl->bInterval ? epctrl->bInterval : 16);
|
||||
acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
acm->ctrlurb->transfer_dma = acm->ctrl_dma;
|
||||
|
||||
|
|
|
@ -209,6 +209,7 @@ skip_error:
|
|||
static void wdm_int_callback(struct urb *urb)
|
||||
{
|
||||
int rv = 0;
|
||||
int responding;
|
||||
int status = urb->status;
|
||||
struct wdm_device *desc;
|
||||
struct usb_cdc_notification *dr;
|
||||
|
@ -262,8 +263,8 @@ static void wdm_int_callback(struct urb *urb)
|
|||
|
||||
spin_lock(&desc->iuspin);
|
||||
clear_bit(WDM_READ, &desc->flags);
|
||||
set_bit(WDM_RESPONDING, &desc->flags);
|
||||
if (!test_bit(WDM_DISCONNECTING, &desc->flags)
|
||||
responding = test_and_set_bit(WDM_RESPONDING, &desc->flags);
|
||||
if (!responding && !test_bit(WDM_DISCONNECTING, &desc->flags)
|
||||
&& !test_bit(WDM_SUSPENDING, &desc->flags)) {
|
||||
rv = usb_submit_urb(desc->response, GFP_ATOMIC);
|
||||
dev_dbg(&desc->intf->dev, "%s: usb_submit_urb %d",
|
||||
|
@ -685,16 +686,20 @@ static void wdm_rxwork(struct work_struct *work)
|
|||
{
|
||||
struct wdm_device *desc = container_of(work, struct wdm_device, rxwork);
|
||||
unsigned long flags;
|
||||
int rv;
|
||||
int rv = 0;
|
||||
int responding;
|
||||
|
||||
spin_lock_irqsave(&desc->iuspin, flags);
|
||||
if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
|
||||
spin_unlock_irqrestore(&desc->iuspin, flags);
|
||||
} else {
|
||||
responding = test_and_set_bit(WDM_RESPONDING, &desc->flags);
|
||||
spin_unlock_irqrestore(&desc->iuspin, flags);
|
||||
rv = usb_submit_urb(desc->response, GFP_KERNEL);
|
||||
if (!responding)
|
||||
rv = usb_submit_urb(desc->response, GFP_KERNEL);
|
||||
if (rv < 0 && rv != -EPERM) {
|
||||
spin_lock_irqsave(&desc->iuspin, flags);
|
||||
clear_bit(WDM_RESPONDING, &desc->flags);
|
||||
if (!test_bit(WDM_DISCONNECTING, &desc->flags))
|
||||
schedule_work(&desc->rxwork);
|
||||
spin_unlock_irqrestore(&desc->iuspin, flags);
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
* http://www.gnu.org/copyleft/gpl.html.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -119,7 +121,6 @@ static void usbtmc_delete(struct kref *kref)
|
|||
struct usbtmc_device_data *data = to_usbtmc_data(kref);
|
||||
|
||||
usb_put_dev(data->usb_dev);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static int usbtmc_open(struct inode *inode, struct file *filp)
|
||||
|
@ -130,10 +131,8 @@ static int usbtmc_open(struct inode *inode, struct file *filp)
|
|||
|
||||
intf = usb_find_interface(&usbtmc_driver, iminor(inode));
|
||||
if (!intf) {
|
||||
printk(KERN_ERR KBUILD_MODNAME
|
||||
": can not find device for minor %d", iminor(inode));
|
||||
retval = -ENODEV;
|
||||
goto exit;
|
||||
pr_err("can not find device for minor %d", iminor(inode));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data = usb_get_intfdata(intf);
|
||||
|
@ -142,7 +141,6 @@ static int usbtmc_open(struct inode *inode, struct file *filp)
|
|||
/* Store pointer in file structure's private data field */
|
||||
filp->private_data = data;
|
||||
|
||||
exit:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -394,12 +392,12 @@ static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t t
|
|||
*/
|
||||
buffer[0] = 2;
|
||||
buffer[1] = data->bTag;
|
||||
buffer[2] = ~(data->bTag);
|
||||
buffer[2] = ~data->bTag;
|
||||
buffer[3] = 0; /* Reserved */
|
||||
buffer[4] = (transfer_size) & 255;
|
||||
buffer[5] = ((transfer_size) >> 8) & 255;
|
||||
buffer[6] = ((transfer_size) >> 16) & 255;
|
||||
buffer[7] = ((transfer_size) >> 24) & 255;
|
||||
buffer[4] = transfer_size >> 0;
|
||||
buffer[5] = transfer_size >> 8;
|
||||
buffer[6] = transfer_size >> 16;
|
||||
buffer[7] = transfer_size >> 24;
|
||||
buffer[8] = data->TermCharEnabled * 2;
|
||||
/* Use term character? */
|
||||
buffer[9] = data->TermChar;
|
||||
|
@ -418,7 +416,7 @@ static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t t
|
|||
/* Increment bTag -- and increment again if zero */
|
||||
data->bTag++;
|
||||
if (!data->bTag)
|
||||
(data->bTag)++;
|
||||
data->bTag++;
|
||||
|
||||
if (retval < 0) {
|
||||
dev_err(&data->intf->dev, "usb_bulk_msg in send_request_dev_dep_msg_in() returned %d\n", retval);
|
||||
|
@ -473,7 +471,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
|
|||
done = 0;
|
||||
|
||||
while (remaining > 0) {
|
||||
if (!(data->rigol_quirk)) {
|
||||
if (!data->rigol_quirk) {
|
||||
dev_dbg(dev, "usb_bulk_msg_in: remaining(%zu), count(%zu)\n", remaining, count);
|
||||
|
||||
if (remaining > USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE - 3)
|
||||
|
@ -510,7 +508,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
|
|||
}
|
||||
|
||||
/* Parse header in first packet */
|
||||
if ((done == 0) || (!(data->rigol_quirk))) {
|
||||
if ((done == 0) || !data->rigol_quirk) {
|
||||
/* Sanity checks for the header */
|
||||
if (actual < USBTMC_HEADER_SIZE) {
|
||||
dev_err(dev, "Device sent too small first packet: %u < %u\n", actual, USBTMC_HEADER_SIZE);
|
||||
|
@ -554,14 +552,14 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
|
|||
if (remaining > n_characters)
|
||||
remaining = n_characters;
|
||||
/* Remove padding if it exists */
|
||||
if (actual > remaining)
|
||||
if (actual > remaining)
|
||||
actual = remaining;
|
||||
}
|
||||
else {
|
||||
if (this_part > n_characters)
|
||||
this_part = n_characters;
|
||||
/* Remove padding if it exists */
|
||||
if (actual > this_part)
|
||||
if (actual > this_part)
|
||||
actual = this_part;
|
||||
}
|
||||
|
||||
|
@ -570,7 +568,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
|
|||
remaining -= actual;
|
||||
|
||||
/* Terminate if end-of-message bit received from device */
|
||||
if ((buffer[8] & 0x01) && (actual >= n_characters))
|
||||
if ((buffer[8] & 0x01) && (actual >= n_characters))
|
||||
remaining = 0;
|
||||
|
||||
dev_dbg(dev, "Bulk-IN header: remaining(%zu), buf(%p), buffer(%p) done(%zu)\n", remaining,buf,buffer,done);
|
||||
|
@ -585,7 +583,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
|
|||
done += actual;
|
||||
}
|
||||
else {
|
||||
if (actual > remaining)
|
||||
if (actual > remaining)
|
||||
actual = remaining;
|
||||
|
||||
remaining -= actual;
|
||||
|
@ -651,12 +649,12 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf,
|
|||
/* Setup IO buffer for DEV_DEP_MSG_OUT message */
|
||||
buffer[0] = 1;
|
||||
buffer[1] = data->bTag;
|
||||
buffer[2] = ~(data->bTag);
|
||||
buffer[2] = ~data->bTag;
|
||||
buffer[3] = 0; /* Reserved */
|
||||
buffer[4] = this_part & 255;
|
||||
buffer[5] = (this_part >> 8) & 255;
|
||||
buffer[6] = (this_part >> 16) & 255;
|
||||
buffer[7] = (this_part >> 24) & 255;
|
||||
buffer[4] = this_part >> 0;
|
||||
buffer[5] = this_part >> 8;
|
||||
buffer[6] = this_part >> 16;
|
||||
buffer[7] = this_part >> 24;
|
||||
/* buffer[8] is set above... */
|
||||
buffer[9] = 0; /* Reserved */
|
||||
buffer[10] = 0; /* Reserved */
|
||||
|
@ -901,7 +899,7 @@ err_out:
|
|||
}
|
||||
|
||||
#define capability_attribute(name) \
|
||||
static ssize_t show_##name(struct device *dev, \
|
||||
static ssize_t name##_show(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
|
@ -909,7 +907,7 @@ static ssize_t show_##name(struct device *dev, \
|
|||
\
|
||||
return sprintf(buf, "%d\n", data->capabilities.name); \
|
||||
} \
|
||||
static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
|
||||
static DEVICE_ATTR_RO(name)
|
||||
|
||||
capability_attribute(interface_capabilities);
|
||||
capability_attribute(device_capabilities);
|
||||
|
@ -928,7 +926,7 @@ static struct attribute_group capability_attr_grp = {
|
|||
.attrs = capability_attrs,
|
||||
};
|
||||
|
||||
static ssize_t show_TermChar(struct device *dev,
|
||||
static ssize_t TermChar_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(dev);
|
||||
|
@ -937,7 +935,7 @@ static ssize_t show_TermChar(struct device *dev,
|
|||
return sprintf(buf, "%c\n", data->TermChar);
|
||||
}
|
||||
|
||||
static ssize_t store_TermChar(struct device *dev,
|
||||
static ssize_t TermChar_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
|
@ -949,10 +947,10 @@ static ssize_t store_TermChar(struct device *dev,
|
|||
data->TermChar = buf[0];
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR(TermChar, S_IRUGO, show_TermChar, store_TermChar);
|
||||
static DEVICE_ATTR_RW(TermChar);
|
||||
|
||||
#define data_attribute(name) \
|
||||
static ssize_t show_##name(struct device *dev, \
|
||||
static ssize_t name##_show(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
|
@ -960,7 +958,7 @@ static ssize_t show_##name(struct device *dev, \
|
|||
\
|
||||
return sprintf(buf, "%d\n", data->name); \
|
||||
} \
|
||||
static ssize_t store_##name(struct device *dev, \
|
||||
static ssize_t name##_store(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t count) \
|
||||
{ \
|
||||
|
@ -978,7 +976,7 @@ static ssize_t store_##name(struct device *dev, \
|
|||
else \
|
||||
return count; \
|
||||
} \
|
||||
static DEVICE_ATTR(name, S_IRUGO, show_##name, store_##name)
|
||||
static DEVICE_ATTR_RW(name)
|
||||
|
||||
data_attribute(TermCharEnabled);
|
||||
data_attribute(auto_abort);
|
||||
|
@ -1102,7 +1100,7 @@ static int usbtmc_probe(struct usb_interface *intf,
|
|||
|
||||
dev_dbg(&intf->dev, "%s called\n", __func__);
|
||||
|
||||
data = kmalloc(sizeof(struct usbtmc_device_data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
dev_err(&intf->dev, "Unable to allocate kernel memory\n");
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -43,10 +43,11 @@ static const size_t pool_max[HCD_BUFFER_POOLS] = {
|
|||
*
|
||||
* Call this as part of initializing a host controller that uses the dma
|
||||
* memory allocators. It initializes some pools of dma-coherent memory that
|
||||
* will be shared by all drivers using that controller, or returns a negative
|
||||
* errno value on error.
|
||||
* will be shared by all drivers using that controller.
|
||||
*
|
||||
* Call hcd_buffer_destroy() to clean up after using those pools.
|
||||
*
|
||||
* Return: 0 if successful. A negative errno value otherwise.
|
||||
*/
|
||||
int hcd_buffer_create(struct usb_hcd *hcd)
|
||||
{
|
||||
|
|
|
@ -424,7 +424,8 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
|
|||
|
||||
memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
|
||||
if (config->desc.bDescriptorType != USB_DT_CONFIG ||
|
||||
config->desc.bLength < USB_DT_CONFIG_SIZE) {
|
||||
config->desc.bLength < USB_DT_CONFIG_SIZE ||
|
||||
config->desc.bLength > size) {
|
||||
dev_err(ddev, "invalid descriptor for config index %d: "
|
||||
"type = 0x%X, length = %d\n", cfgidx,
|
||||
config->desc.bDescriptorType, config->desc.bLength);
|
||||
|
|
|
@ -725,15 +725,15 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
|
|||
|
||||
/*
|
||||
* check for the special corner case 'get_device_id' in the printer
|
||||
* class specification, where wIndex is (interface << 8 | altsetting)
|
||||
* instead of just interface
|
||||
* class specification, which we always want to allow as it is used
|
||||
* to query things like ink level, etc.
|
||||
*/
|
||||
if (requesttype == 0xa1 && request == 0) {
|
||||
alt_setting = usb_find_alt_setting(ps->dev->actconfig,
|
||||
index >> 8, index & 0xff);
|
||||
if (alt_setting
|
||||
&& alt_setting->desc.bInterfaceClass == USB_CLASS_PRINTER)
|
||||
index >>= 8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
index &= 0xff;
|
||||
|
|
|
@ -94,32 +94,27 @@ ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(usb_show_dynids);
|
||||
|
||||
static ssize_t show_dynids(struct device_driver *driver, char *buf)
|
||||
static ssize_t new_id_show(struct device_driver *driver, char *buf)
|
||||
{
|
||||
struct usb_driver *usb_drv = to_usb_driver(driver);
|
||||
|
||||
return usb_show_dynids(&usb_drv->dynids, buf);
|
||||
}
|
||||
|
||||
static ssize_t store_new_id(struct device_driver *driver,
|
||||
static ssize_t new_id_store(struct device_driver *driver,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct usb_driver *usb_drv = to_usb_driver(driver);
|
||||
|
||||
return usb_store_new_id(&usb_drv->dynids, driver, buf, count);
|
||||
}
|
||||
static DRIVER_ATTR(new_id, S_IRUGO | S_IWUSR, show_dynids, store_new_id);
|
||||
static DRIVER_ATTR_RW(new_id);
|
||||
|
||||
/**
|
||||
* store_remove_id - remove a USB device ID from this driver
|
||||
* @driver: target device driver
|
||||
* @buf: buffer for scanning device ID data
|
||||
* @count: input size
|
||||
*
|
||||
* Removes a dynamic usb device ID from this driver.
|
||||
/*
|
||||
* Remove a USB device ID from this driver
|
||||
*/
|
||||
static ssize_t
|
||||
store_remove_id(struct device_driver *driver, const char *buf, size_t count)
|
||||
static ssize_t remove_id_store(struct device_driver *driver, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct usb_dynid *dynid, *n;
|
||||
struct usb_driver *usb_driver = to_usb_driver(driver);
|
||||
|
@ -144,7 +139,12 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count)
|
|||
spin_unlock(&usb_driver->dynids.lock);
|
||||
return count;
|
||||
}
|
||||
static DRIVER_ATTR(remove_id, S_IRUGO | S_IWUSR, show_dynids, store_remove_id);
|
||||
|
||||
static ssize_t remove_id_show(struct device_driver *driver, char *buf)
|
||||
{
|
||||
return new_id_show(driver, buf);
|
||||
}
|
||||
static DRIVER_ATTR_RW(remove_id);
|
||||
|
||||
static int usb_create_newid_files(struct usb_driver *usb_drv)
|
||||
{
|
||||
|
@ -457,6 +457,8 @@ static int usb_unbind_interface(struct device *dev)
|
|||
* Callers must own the device lock, so driver probe() entries don't need
|
||||
* extra locking, but other call contexts may need to explicitly claim that
|
||||
* lock.
|
||||
*
|
||||
* Return: 0 on success.
|
||||
*/
|
||||
int usb_driver_claim_interface(struct usb_driver *driver,
|
||||
struct usb_interface *iface, void *priv)
|
||||
|
@ -658,6 +660,8 @@ EXPORT_SYMBOL_GPL(usb_match_one_id);
|
|||
* These device tables are exported with MODULE_DEVICE_TABLE, through
|
||||
* modutils, to support the driver loading functionality of USB hotplugging.
|
||||
*
|
||||
* Return: The first matching usb_device_id, or %NULL.
|
||||
*
|
||||
* What Matches:
|
||||
*
|
||||
* The "match_flags" element in a usb_device_id controls which
|
||||
|
@ -823,7 +827,8 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
|
|||
* Registers a USB device driver with the USB core. The list of
|
||||
* unattached devices will be rescanned whenever a new driver is
|
||||
* added, allowing the new driver to attach to any recognized devices.
|
||||
* Returns a negative error code on failure and 0 on success.
|
||||
*
|
||||
* Return: A negative error code on failure and 0 on success.
|
||||
*/
|
||||
int usb_register_device_driver(struct usb_device_driver *new_udriver,
|
||||
struct module *owner)
|
||||
|
@ -879,7 +884,8 @@ EXPORT_SYMBOL_GPL(usb_deregister_device_driver);
|
|||
* Registers a USB interface driver with the USB core. The list of
|
||||
* unattached interfaces will be rescanned whenever a new driver is
|
||||
* added, allowing the new driver to attach to any recognized interfaces.
|
||||
* Returns a negative error code on failure and 0 on success.
|
||||
*
|
||||
* Return: A negative error code on failure and 0 on success.
|
||||
*
|
||||
* NOTE: if you want your driver to use the USB major number, you must call
|
||||
* usb_register_dev() to enable that functionality. This function no longer
|
||||
|
@ -1213,6 +1219,8 @@ done:
|
|||
* unpredictable times.
|
||||
*
|
||||
* This routine can run only in process context.
|
||||
*
|
||||
* Return: 0 if the suspend succeeded.
|
||||
*/
|
||||
static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
|
||||
{
|
||||
|
@ -1294,6 +1302,8 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
|
|||
* unpredictable times.
|
||||
*
|
||||
* This routine can run only in process context.
|
||||
*
|
||||
* Return: 0 on success.
|
||||
*/
|
||||
static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
|
||||
{
|
||||
|
@ -1491,6 +1501,8 @@ void usb_autosuspend_device(struct usb_device *udev)
|
|||
* The caller must hold @udev's device lock.
|
||||
*
|
||||
* This routine can run only in process context.
|
||||
*
|
||||
* Return: 0 on success. A negative error code otherwise.
|
||||
*/
|
||||
int usb_autoresume_device(struct usb_device *udev)
|
||||
{
|
||||
|
@ -1600,6 +1612,8 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface_no_suspend);
|
|||
* However if the autoresume fails then the counter is re-decremented.
|
||||
*
|
||||
* This routine can run only in process context.
|
||||
*
|
||||
* Return: 0 on success.
|
||||
*/
|
||||
int usb_autopm_get_interface(struct usb_interface *intf)
|
||||
{
|
||||
|
@ -1633,6 +1647,8 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
|
|||
* resumed.
|
||||
*
|
||||
* This routine can run in atomic context.
|
||||
*
|
||||
* Return: 0 on success. A negative error code otherwise.
|
||||
*/
|
||||
int usb_autopm_get_interface_async(struct usb_interface *intf)
|
||||
{
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb.h"
|
||||
|
||||
|
@ -33,31 +32,31 @@ struct ep_attribute {
|
|||
container_of(_attr, struct ep_attribute, attr)
|
||||
|
||||
#define usb_ep_attr(field, format_string) \
|
||||
static ssize_t show_ep_##field(struct device *dev, \
|
||||
static ssize_t field##_show(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct ep_device *ep = to_ep_device(dev); \
|
||||
return sprintf(buf, format_string, ep->desc->field); \
|
||||
} \
|
||||
static DEVICE_ATTR(field, S_IRUGO, show_ep_##field, NULL);
|
||||
static DEVICE_ATTR_RO(field)
|
||||
|
||||
usb_ep_attr(bLength, "%02x\n")
|
||||
usb_ep_attr(bEndpointAddress, "%02x\n")
|
||||
usb_ep_attr(bmAttributes, "%02x\n")
|
||||
usb_ep_attr(bInterval, "%02x\n")
|
||||
usb_ep_attr(bLength, "%02x\n");
|
||||
usb_ep_attr(bEndpointAddress, "%02x\n");
|
||||
usb_ep_attr(bmAttributes, "%02x\n");
|
||||
usb_ep_attr(bInterval, "%02x\n");
|
||||
|
||||
static ssize_t show_ep_wMaxPacketSize(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t wMaxPacketSize_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct ep_device *ep = to_ep_device(dev);
|
||||
return sprintf(buf, "%04x\n",
|
||||
usb_endpoint_maxp(ep->desc) & 0x07ff);
|
||||
}
|
||||
static DEVICE_ATTR(wMaxPacketSize, S_IRUGO, show_ep_wMaxPacketSize, NULL);
|
||||
static DEVICE_ATTR_RO(wMaxPacketSize);
|
||||
|
||||
static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t type_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ep_device *ep = to_ep_device(dev);
|
||||
char *type = "unknown";
|
||||
|
@ -78,10 +77,10 @@ static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr,
|
|||
}
|
||||
return sprintf(buf, "%s\n", type);
|
||||
}
|
||||
static DEVICE_ATTR(type, S_IRUGO, show_ep_type, NULL);
|
||||
static DEVICE_ATTR_RO(type);
|
||||
|
||||
static ssize_t show_ep_interval(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t interval_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ep_device *ep = to_ep_device(dev);
|
||||
char unit;
|
||||
|
@ -124,10 +123,10 @@ static ssize_t show_ep_interval(struct device *dev,
|
|||
|
||||
return sprintf(buf, "%d%cs\n", interval, unit);
|
||||
}
|
||||
static DEVICE_ATTR(interval, S_IRUGO, show_ep_interval, NULL);
|
||||
static DEVICE_ATTR_RO(interval);
|
||||
|
||||
static ssize_t show_ep_direction(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t direction_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ep_device *ep = to_ep_device(dev);
|
||||
char *direction;
|
||||
|
@ -140,7 +139,7 @@ static ssize_t show_ep_direction(struct device *dev,
|
|||
direction = "out";
|
||||
return sprintf(buf, "%s\n", direction);
|
||||
}
|
||||
static DEVICE_ATTR(direction, S_IRUGO, show_ep_direction, NULL);
|
||||
static DEVICE_ATTR_RO(direction);
|
||||
|
||||
static struct attribute *ep_dev_attrs[] = {
|
||||
&dev_attr_bLength.attr,
|
||||
|
|
|
@ -153,7 +153,7 @@ void usb_major_cleanup(void)
|
|||
* usb_deregister_dev() must be called when the driver is done with
|
||||
* the minor numbers given out by this function.
|
||||
*
|
||||
* Returns -EINVAL if something bad happens with trying to register a
|
||||
* Return: -EINVAL if something bad happens with trying to register a
|
||||
* device, and 0 on success.
|
||||
*/
|
||||
int usb_register_dev(struct usb_interface *intf,
|
||||
|
|
|
@ -171,6 +171,8 @@ static void ehci_wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd,
|
|||
* through the hotplug entry's driver_data.
|
||||
*
|
||||
* Store this function in the HCD's struct pci_driver as probe().
|
||||
*
|
||||
* Return: 0 if successful.
|
||||
*/
|
||||
int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
{
|
||||
|
|
|
@ -378,9 +378,10 @@ MODULE_PARM_DESC(authorized_default,
|
|||
* @buf: Buffer for USB string descriptor (header + UTF-16LE)
|
||||
* @len: Length (in bytes; may be odd) of descriptor buffer.
|
||||
*
|
||||
* The return value is the number of bytes filled in: 2 + 2*strlen(s) or
|
||||
* buflen, whichever is less.
|
||||
* Return: The number of bytes filled in: 2 + 2*strlen(s) or @len,
|
||||
* whichever is less.
|
||||
*
|
||||
* Note:
|
||||
* USB String descriptors can contain at most 126 characters; input
|
||||
* strings longer than that are truncated.
|
||||
*/
|
||||
|
@ -416,7 +417,8 @@ ascii2desc(char const *s, u8 *buf, unsigned len)
|
|||
*
|
||||
* Produces either a manufacturer, product or serial number string for the
|
||||
* virtual root hub device.
|
||||
* Returns the number of bytes filled in: the length of the descriptor or
|
||||
*
|
||||
* Return: The number of bytes filled in: the length of the descriptor or
|
||||
* of the provided buffer, whichever is less.
|
||||
*/
|
||||
static unsigned
|
||||
|
@ -464,17 +466,13 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
|
|||
struct usb_ctrlrequest *cmd;
|
||||
u16 typeReq, wValue, wIndex, wLength;
|
||||
u8 *ubuf = urb->transfer_buffer;
|
||||
/*
|
||||
* tbuf should be as big as the BOS descriptor and
|
||||
* the USB hub descriptor.
|
||||
*/
|
||||
u8 tbuf[USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE]
|
||||
__attribute__((aligned(4)));
|
||||
const u8 *bufp = tbuf;
|
||||
unsigned len = 0;
|
||||
int status;
|
||||
u8 patch_wakeup = 0;
|
||||
u8 patch_protocol = 0;
|
||||
u16 tbuf_size;
|
||||
u8 *tbuf = NULL;
|
||||
const u8 *bufp;
|
||||
|
||||
might_sleep();
|
||||
|
||||
|
@ -494,6 +492,18 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
|
|||
if (wLength > urb->transfer_buffer_length)
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* tbuf should be at least as big as the
|
||||
* USB hub descriptor.
|
||||
*/
|
||||
tbuf_size = max_t(u16, sizeof(struct usb_hub_descriptor), wLength);
|
||||
tbuf = kzalloc(tbuf_size, GFP_KERNEL);
|
||||
if (!tbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
bufp = tbuf;
|
||||
|
||||
|
||||
urb->actual_length = 0;
|
||||
switch (typeReq) {
|
||||
|
||||
|
@ -691,18 +701,12 @@ error:
|
|||
bDeviceProtocol = USB_HUB_PR_HS_SINGLE_TT;
|
||||
}
|
||||
|
||||
kfree(tbuf);
|
||||
|
||||
/* any errors get returned through the urb completion */
|
||||
spin_lock_irq(&hcd_root_hub_lock);
|
||||
usb_hcd_unlink_urb_from_ep(hcd, urb);
|
||||
|
||||
/* This peculiar use of spinlocks echoes what real HC drivers do.
|
||||
* Avoiding calls to local_irq_disable/enable makes the code
|
||||
* RT-friendly.
|
||||
*/
|
||||
spin_unlock(&hcd_root_hub_lock);
|
||||
usb_hcd_giveback_urb(hcd, urb, status);
|
||||
spin_lock(&hcd_root_hub_lock);
|
||||
|
||||
spin_unlock_irq(&hcd_root_hub_lock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -742,9 +746,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
|
|||
memcpy(urb->transfer_buffer, buffer, length);
|
||||
|
||||
usb_hcd_unlink_urb_from_ep(hcd, urb);
|
||||
spin_unlock(&hcd_root_hub_lock);
|
||||
usb_hcd_giveback_urb(hcd, urb, 0);
|
||||
spin_lock(&hcd_root_hub_lock);
|
||||
} else {
|
||||
length = 0;
|
||||
set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);
|
||||
|
@ -834,10 +836,7 @@ static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
|||
if (urb == hcd->status_urb) {
|
||||
hcd->status_urb = NULL;
|
||||
usb_hcd_unlink_urb_from_ep(hcd, urb);
|
||||
|
||||
spin_unlock(&hcd_root_hub_lock);
|
||||
usb_hcd_giveback_urb(hcd, urb, status);
|
||||
spin_lock(&hcd_root_hub_lock);
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
@ -850,9 +849,8 @@ static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
|||
/*
|
||||
* Show & store the current value of authorized_default
|
||||
*/
|
||||
static ssize_t usb_host_authorized_default_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t authorized_default_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_device *rh_usb_dev = to_usb_device(dev);
|
||||
struct usb_bus *usb_bus = rh_usb_dev->bus;
|
||||
|
@ -864,9 +862,9 @@ static ssize_t usb_host_authorized_default_show(struct device *dev,
|
|||
return snprintf(buf, PAGE_SIZE, "%u\n", usb_hcd->authorized_default);
|
||||
}
|
||||
|
||||
static ssize_t usb_host_authorized_default_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
static ssize_t authorized_default_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
ssize_t result;
|
||||
unsigned val;
|
||||
|
@ -886,11 +884,7 @@ static ssize_t usb_host_authorized_default_store(struct device *dev,
|
|||
result = -EINVAL;
|
||||
return result;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(authorized_default, 0644,
|
||||
usb_host_authorized_default_show,
|
||||
usb_host_authorized_default_store);
|
||||
|
||||
static DEVICE_ATTR_RW(authorized_default);
|
||||
|
||||
/* Group all the USB bus attributes */
|
||||
static struct attribute *usb_bus_attrs[] = {
|
||||
|
@ -938,6 +932,8 @@ static void usb_bus_init (struct usb_bus *bus)
|
|||
*
|
||||
* Assigns a bus number, and links the controller into usbcore data
|
||||
* structures so that it can be seen by scanning the bus list.
|
||||
*
|
||||
* Return: 0 if successful. A negative error code otherwise.
|
||||
*/
|
||||
static int usb_register_bus(struct usb_bus *bus)
|
||||
{
|
||||
|
@ -1002,6 +998,8 @@ static void usb_deregister_bus (struct usb_bus *bus)
|
|||
* the device properly in the device tree and then calls usb_new_device()
|
||||
* to register the usb device. It also assigns the root hub's USB address
|
||||
* (always 1).
|
||||
*
|
||||
* Return: 0 if successful. A negative error code otherwise.
|
||||
*/
|
||||
static int register_root_hub(struct usb_hcd *hcd)
|
||||
{
|
||||
|
@ -1108,7 +1106,9 @@ EXPORT_SYMBOL_GPL(usb_hcd_end_port_resume);
|
|||
* @isoc: true for isochronous transactions, false for interrupt ones
|
||||
* @bytecount: how many bytes in the transaction.
|
||||
*
|
||||
* Returns approximate bus time in nanoseconds for a periodic transaction.
|
||||
* Return: Approximate bus time in nanoseconds for a periodic transaction.
|
||||
*
|
||||
* Note:
|
||||
* See USB 2.0 spec section 5.11.3; only periodic transfers need to be
|
||||
* scheduled in software, this function is only used for such scheduling.
|
||||
*/
|
||||
|
@ -1166,7 +1166,7 @@ EXPORT_SYMBOL_GPL(usb_calc_bus_time);
|
|||
* be disabled. The actions carried out here are required for URB
|
||||
* submission, as well as for endpoint shutdown and for usb_kill_urb.
|
||||
*
|
||||
* Returns 0 for no error, otherwise a negative error code (in which case
|
||||
* Return: 0 for no error, otherwise a negative error code (in which case
|
||||
* the enqueue() method must fail). If no error occurs but enqueue() fails
|
||||
* anyway, it must call usb_hcd_unlink_urb_from_ep() before releasing
|
||||
* the private spinlock and returning.
|
||||
|
@ -1221,7 +1221,7 @@ EXPORT_SYMBOL_GPL(usb_hcd_link_urb_to_ep);
|
|||
* be disabled. The actions carried out here are required for making
|
||||
* sure than an unlink is valid.
|
||||
*
|
||||
* Returns 0 for no error, otherwise a negative error code (in which case
|
||||
* Return: 0 for no error, otherwise a negative error code (in which case
|
||||
* the dequeue() method must fail). The possible error codes are:
|
||||
*
|
||||
* -EIDRM: @urb was not submitted or has already completed.
|
||||
|
@ -1648,6 +1648,72 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static void __usb_hcd_giveback_urb(struct urb *urb)
|
||||
{
|
||||
struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus);
|
||||
int status = urb->unlinked;
|
||||
unsigned long flags;
|
||||
|
||||
urb->hcpriv = NULL;
|
||||
if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
|
||||
urb->actual_length < urb->transfer_buffer_length &&
|
||||
!status))
|
||||
status = -EREMOTEIO;
|
||||
|
||||
unmap_urb_for_dma(hcd, urb);
|
||||
usbmon_urb_complete(&hcd->self, urb, status);
|
||||
usb_unanchor_urb(urb);
|
||||
|
||||
/* pass ownership to the completion handler */
|
||||
urb->status = status;
|
||||
|
||||
/*
|
||||
* We disable local IRQs here avoid possible deadlock because
|
||||
* drivers may call spin_lock() to hold lock which might be
|
||||
* acquired in one hard interrupt handler.
|
||||
*
|
||||
* The local_irq_save()/local_irq_restore() around complete()
|
||||
* will be removed if current USB drivers have been cleaned up
|
||||
* and no one may trigger the above deadlock situation when
|
||||
* running complete() in tasklet.
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
urb->complete(urb);
|
||||
local_irq_restore(flags);
|
||||
|
||||
atomic_dec(&urb->use_count);
|
||||
if (unlikely(atomic_read(&urb->reject)))
|
||||
wake_up(&usb_kill_urb_queue);
|
||||
usb_put_urb(urb);
|
||||
}
|
||||
|
||||
static void usb_giveback_urb_bh(unsigned long param)
|
||||
{
|
||||
struct giveback_urb_bh *bh = (struct giveback_urb_bh *)param;
|
||||
struct list_head local_list;
|
||||
|
||||
spin_lock_irq(&bh->lock);
|
||||
bh->running = true;
|
||||
restart:
|
||||
list_replace_init(&bh->head, &local_list);
|
||||
spin_unlock_irq(&bh->lock);
|
||||
|
||||
while (!list_empty(&local_list)) {
|
||||
struct urb *urb;
|
||||
|
||||
urb = list_entry(local_list.next, struct urb, urb_list);
|
||||
list_del_init(&urb->urb_list);
|
||||
__usb_hcd_giveback_urb(urb);
|
||||
}
|
||||
|
||||
/* check if there are new URBs to giveback */
|
||||
spin_lock_irq(&bh->lock);
|
||||
if (!list_empty(&bh->head))
|
||||
goto restart;
|
||||
bh->running = false;
|
||||
spin_unlock_irq(&bh->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_hcd_giveback_urb - return URB from HCD to device driver
|
||||
* @hcd: host controller returning the URB
|
||||
|
@ -1667,25 +1733,37 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
|
|||
*/
|
||||
void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
|
||||
{
|
||||
urb->hcpriv = NULL;
|
||||
if (unlikely(urb->unlinked))
|
||||
status = urb->unlinked;
|
||||
else if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
|
||||
urb->actual_length < urb->transfer_buffer_length &&
|
||||
!status))
|
||||
status = -EREMOTEIO;
|
||||
struct giveback_urb_bh *bh;
|
||||
bool running, high_prio_bh;
|
||||
|
||||
unmap_urb_for_dma(hcd, urb);
|
||||
usbmon_urb_complete(&hcd->self, urb, status);
|
||||
usb_unanchor_urb(urb);
|
||||
/* pass status to tasklet via unlinked */
|
||||
if (likely(!urb->unlinked))
|
||||
urb->unlinked = status;
|
||||
|
||||
/* pass ownership to the completion handler */
|
||||
urb->status = status;
|
||||
urb->complete (urb);
|
||||
atomic_dec (&urb->use_count);
|
||||
if (unlikely(atomic_read(&urb->reject)))
|
||||
wake_up (&usb_kill_urb_queue);
|
||||
usb_put_urb (urb);
|
||||
if (!hcd_giveback_urb_in_bh(hcd) && !is_root_hub(urb->dev)) {
|
||||
__usb_hcd_giveback_urb(urb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (usb_pipeisoc(urb->pipe) || usb_pipeint(urb->pipe)) {
|
||||
bh = &hcd->high_prio_bh;
|
||||
high_prio_bh = true;
|
||||
} else {
|
||||
bh = &hcd->low_prio_bh;
|
||||
high_prio_bh = false;
|
||||
}
|
||||
|
||||
spin_lock(&bh->lock);
|
||||
list_add_tail(&urb->urb_list, &bh->head);
|
||||
running = bh->running;
|
||||
spin_unlock(&bh->lock);
|
||||
|
||||
if (running)
|
||||
;
|
||||
else if (high_prio_bh)
|
||||
tasklet_hi_schedule(&bh->bh);
|
||||
else
|
||||
tasklet_schedule(&bh->bh);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_hcd_giveback_urb);
|
||||
|
||||
|
@ -1784,7 +1862,7 @@ rescan:
|
|||
* pass in the current alternate interface setting in cur_alt,
|
||||
* and pass in the new alternate interface setting in new_alt.
|
||||
*
|
||||
* Returns an error if the requested bandwidth change exceeds the
|
||||
* Return: An error if the requested bandwidth change exceeds the
|
||||
* bus bandwidth or host controller internal resources.
|
||||
*/
|
||||
int usb_hcd_alloc_bandwidth(struct usb_device *udev,
|
||||
|
@ -1954,9 +2032,12 @@ void usb_hcd_reset_endpoint(struct usb_device *udev,
|
|||
* @num_streams: number of streams to allocate.
|
||||
* @mem_flags: flags hcd should use to allocate memory.
|
||||
*
|
||||
* Sets up a group of bulk endpoints to have num_streams stream IDs available.
|
||||
* Sets up a group of bulk endpoints to have @num_streams stream IDs available.
|
||||
* Drivers may queue multiple transfers to different stream IDs, which may
|
||||
* complete in a different order than they were queued.
|
||||
*
|
||||
* Return: On success, the number of allocated streams. On failure, a negative
|
||||
* error code.
|
||||
*/
|
||||
int usb_alloc_streams(struct usb_interface *interface,
|
||||
struct usb_host_endpoint **eps, unsigned int num_eps,
|
||||
|
@ -2201,6 +2282,8 @@ EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
|
|||
* khubd identifying and possibly configuring the device.
|
||||
* This is needed by OTG controller drivers, where it helps meet
|
||||
* HNP protocol timing requirements for starting a port reset.
|
||||
*
|
||||
* Return: 0 if successful.
|
||||
*/
|
||||
int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num)
|
||||
{
|
||||
|
@ -2235,6 +2318,8 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
|
|||
*
|
||||
* If the controller isn't HALTed, calls the driver's irq handler.
|
||||
* Checks whether the controller is now dead.
|
||||
*
|
||||
* Return: %IRQ_HANDLED if the IRQ was handled. %IRQ_NONE otherwise.
|
||||
*/
|
||||
irqreturn_t usb_hcd_irq (int irq, void *__hcd)
|
||||
{
|
||||
|
@ -2307,6 +2392,14 @@ EXPORT_SYMBOL_GPL (usb_hc_died);
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static void init_giveback_urb_bh(struct giveback_urb_bh *bh)
|
||||
{
|
||||
|
||||
spin_lock_init(&bh->lock);
|
||||
INIT_LIST_HEAD(&bh->head);
|
||||
tasklet_init(&bh->bh, usb_giveback_urb_bh, (unsigned long)bh);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_create_shared_hcd - create and initialize an HCD structure
|
||||
* @driver: HC driver that will use this hcd
|
||||
|
@ -2320,7 +2413,8 @@ EXPORT_SYMBOL_GPL (usb_hc_died);
|
|||
* HC driver's private data. Initialize the generic members of the
|
||||
* hcd structure.
|
||||
*
|
||||
* If memory is unavailable, returns NULL.
|
||||
* Return: On success, a pointer to the created and initialized HCD structure.
|
||||
* On failure (e.g. if memory is unavailable), %NULL.
|
||||
*/
|
||||
struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
|
||||
struct device *dev, const char *bus_name,
|
||||
|
@ -2384,7 +2478,8 @@ EXPORT_SYMBOL_GPL(usb_create_shared_hcd);
|
|||
* HC driver's private data. Initialize the generic members of the
|
||||
* hcd structure.
|
||||
*
|
||||
* If memory is unavailable, returns NULL.
|
||||
* Return: On success, a pointer to the created and initialized HCD
|
||||
* structure. On failure (e.g. if memory is unavailable), %NULL.
|
||||
*/
|
||||
struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
|
||||
struct device *dev, const char *bus_name)
|
||||
|
@ -2563,7 +2658,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
|||
* should already have been reset (and boot firmware kicked off etc).
|
||||
*/
|
||||
if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {
|
||||
dev_err(hcd->self.controller, "can't setup\n");
|
||||
dev_err(hcd->self.controller, "can't setup: %d\n", retval);
|
||||
goto err_hcd_driver_setup;
|
||||
}
|
||||
hcd->rh_pollable = 1;
|
||||
|
@ -2573,6 +2668,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
|||
&& device_can_wakeup(&hcd->self.root_hub->dev))
|
||||
dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
|
||||
|
||||
/* initialize tasklets */
|
||||
init_giveback_urb_bh(&hcd->high_prio_bh);
|
||||
init_giveback_urb_bh(&hcd->low_prio_bh);
|
||||
|
||||
/* enable irqs just before we start the controller,
|
||||
* if the BIOS provides legacy PCI irqs.
|
||||
*/
|
||||
|
@ -2681,6 +2780,16 @@ void usb_remove_hcd(struct usb_hcd *hcd)
|
|||
usb_disconnect(&rhdev); /* Sets rhdev to NULL */
|
||||
mutex_unlock(&usb_bus_list_lock);
|
||||
|
||||
/*
|
||||
* tasklet_kill() isn't needed here because:
|
||||
* - driver's disconnect() called from usb_disconnect() should
|
||||
* make sure its URBs are completed during the disconnect()
|
||||
* callback
|
||||
*
|
||||
* - it is too late to run complete() here since driver may have
|
||||
* been removed already now
|
||||
*/
|
||||
|
||||
/* Prevent any more root-hub status calls from the timer.
|
||||
* The HCD might still restart the timer (if a port status change
|
||||
* interrupt occurs), but usb_hcd_poll_rh_status() won't invoke
|
||||
|
|
|
@ -451,7 +451,7 @@ static void led_work (struct work_struct *work)
|
|||
if (hdev->state != USB_STATE_CONFIGURED || hub->quiescing)
|
||||
return;
|
||||
|
||||
for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
|
||||
for (i = 0; i < hdev->maxchild; i++) {
|
||||
unsigned selector, mode;
|
||||
|
||||
/* 30%-50% duty cycle */
|
||||
|
@ -500,7 +500,7 @@ static void led_work (struct work_struct *work)
|
|||
}
|
||||
if (!changed && blinkenlights) {
|
||||
cursor++;
|
||||
cursor %= hub->descriptor->bNbrPorts;
|
||||
cursor %= hdev->maxchild;
|
||||
set_port_led(hub, cursor + 1, HUB_LED_GREEN);
|
||||
hub->indicator[cursor] = INDICATOR_CYCLE;
|
||||
changed++;
|
||||
|
@ -734,6 +734,8 @@ static void hub_tt_work(struct work_struct *work)
|
|||
*
|
||||
* call this function to control port's power via setting or
|
||||
* clearing the port's PORT_POWER feature.
|
||||
*
|
||||
* Return: 0 if successful. A negative error code otherwise.
|
||||
*/
|
||||
int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
|
||||
int port1, bool set)
|
||||
|
@ -762,6 +764,8 @@ int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
|
|||
*
|
||||
* It may not be possible for that hub to handle additional full (or low)
|
||||
* speed transactions until that state is fully cleared out.
|
||||
*
|
||||
* Return: 0 if successful. A negative error code otherwise.
|
||||
*/
|
||||
int usb_hub_clear_tt_buffer(struct urb *urb)
|
||||
{
|
||||
|
@ -826,7 +830,7 @@ static unsigned hub_power_on(struct usb_hub *hub, bool do_delay)
|
|||
else
|
||||
dev_dbg(hub->intfdev, "trying to enable port power on "
|
||||
"non-switchable hub\n");
|
||||
for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++)
|
||||
for (port1 = 1; port1 <= hub->hdev->maxchild; port1++)
|
||||
if (hub->ports[port1 - 1]->power_is_on)
|
||||
set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER);
|
||||
else
|
||||
|
@ -964,6 +968,8 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
|
|||
* see that the device has been disconnected. When the device is
|
||||
* physically unplugged and something is plugged in, the events will
|
||||
* be received and processed normally.
|
||||
*
|
||||
* Return: 0 if successful. A negative error code otherwise.
|
||||
*/
|
||||
int usb_remove_device(struct usb_device *udev)
|
||||
{
|
||||
|
@ -1464,11 +1470,10 @@ static int hub_configure(struct usb_hub *hub,
|
|||
* and battery-powered root hubs (may provide just 8 mA).
|
||||
*/
|
||||
ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus);
|
||||
if (ret < 2) {
|
||||
if (ret) {
|
||||
message = "can't get hub status";
|
||||
goto fail;
|
||||
}
|
||||
le16_to_cpus(&hubstatus);
|
||||
hcd = bus_to_hcd(hdev->bus);
|
||||
if (hdev == hdev->bus->root_hub) {
|
||||
if (hcd->power_budget > 0)
|
||||
|
@ -1557,10 +1562,15 @@ static int hub_configure(struct usb_hub *hub,
|
|||
if (hub->has_indicators && blinkenlights)
|
||||
hub->indicator [0] = INDICATOR_CYCLE;
|
||||
|
||||
for (i = 0; i < hdev->maxchild; i++)
|
||||
if (usb_hub_create_port_device(hub, i + 1) < 0)
|
||||
for (i = 0; i < hdev->maxchild; i++) {
|
||||
ret = usb_hub_create_port_device(hub, i + 1);
|
||||
if (ret < 0) {
|
||||
dev_err(hub->intfdev,
|
||||
"couldn't create port%d device.\n", i + 1);
|
||||
hdev->maxchild = i;
|
||||
goto fail_keep_maxchild;
|
||||
}
|
||||
}
|
||||
|
||||
usb_hub_adjust_deviceremovable(hdev, hub->descriptor);
|
||||
|
||||
|
@ -1568,6 +1578,8 @@ static int hub_configure(struct usb_hub *hub,
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
hdev->maxchild = 0;
|
||||
fail_keep_maxchild:
|
||||
dev_err (hub_dev, "config failed, %s (err %d)\n",
|
||||
message, ret);
|
||||
/* hub_disconnect() frees urb and descriptor */
|
||||
|
@ -2116,6 +2128,8 @@ static inline void announce_device(struct usb_device *udev) { }
|
|||
* @udev: newly addressed device (in ADDRESS state)
|
||||
*
|
||||
* Finish enumeration for On-The-Go devices
|
||||
*
|
||||
* Return: 0 if successful. A negative error code otherwise.
|
||||
*/
|
||||
static int usb_enumerate_device_otg(struct usb_device *udev)
|
||||
{
|
||||
|
@ -2198,6 +2212,8 @@ fail:
|
|||
* If the device is WUSB and not authorized, we don't attempt to read
|
||||
* the string descriptors, as they will be errored out by the device
|
||||
* until it has been authorized.
|
||||
*
|
||||
* Return: 0 if successful. A negative error code otherwise.
|
||||
*/
|
||||
static int usb_enumerate_device(struct usb_device *udev)
|
||||
{
|
||||
|
@ -2278,13 +2294,14 @@ static void set_usb_port_removable(struct usb_device *udev)
|
|||
* udev has already been installed, but udev is not yet visible through
|
||||
* sysfs or other filesystem code.
|
||||
*
|
||||
* It will return if the device is configured properly or not. Zero if
|
||||
* the interface was registered with the driver core; else a negative
|
||||
* errno value.
|
||||
*
|
||||
* This call is synchronous, and may not be used in an interrupt context.
|
||||
*
|
||||
* Only the hub driver or root-hub registrar should ever call this.
|
||||
*
|
||||
* Return: Whether the device is configured properly or not. Zero if the
|
||||
* interface was registered with the driver core; else a negative errno
|
||||
* value.
|
||||
*
|
||||
*/
|
||||
int usb_new_device(struct usb_device *udev)
|
||||
{
|
||||
|
@ -2392,6 +2409,8 @@ fail:
|
|||
*
|
||||
* We share a lock (that we have) with device_del(), so we need to
|
||||
* defer its call.
|
||||
*
|
||||
* Return: 0.
|
||||
*/
|
||||
int usb_deauthorize_device(struct usb_device *usb_dev)
|
||||
{
|
||||
|
@ -2838,20 +2857,51 @@ void usb_enable_ltm(struct usb_device *udev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(usb_enable_ltm);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/*
|
||||
* usb_disable_function_remotewakeup - disable usb3.0
|
||||
* device's function remote wakeup
|
||||
* usb_enable_remote_wakeup - enable remote wakeup for a device
|
||||
* @udev: target device
|
||||
*
|
||||
* Assume there's only one function on the USB 3.0
|
||||
* device and disable remote wake for the first
|
||||
* interface. FIXME if the interface association
|
||||
* descriptor shows there's more than one function.
|
||||
* For USB-2 devices: Set the device's remote wakeup feature.
|
||||
*
|
||||
* For USB-3 devices: Assume there's only one function on the device and
|
||||
* enable remote wake for the first interface. FIXME if the interface
|
||||
* association descriptor shows there's more than one function.
|
||||
*/
|
||||
static int usb_disable_function_remotewakeup(struct usb_device *udev)
|
||||
static int usb_enable_remote_wakeup(struct usb_device *udev)
|
||||
{
|
||||
return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
if (udev->speed < USB_SPEED_SUPER)
|
||||
return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
|
||||
USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
else
|
||||
return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
USB_REQ_SET_FEATURE, USB_RECIP_INTERFACE,
|
||||
USB_INTRF_FUNC_SUSPEND,
|
||||
USB_INTRF_FUNC_SUSPEND_RW |
|
||||
USB_INTRF_FUNC_SUSPEND_LP,
|
||||
NULL, 0, USB_CTRL_SET_TIMEOUT);
|
||||
}
|
||||
|
||||
/*
|
||||
* usb_disable_remote_wakeup - disable remote wakeup for a device
|
||||
* @udev: target device
|
||||
*
|
||||
* For USB-2 devices: Clear the device's remote wakeup feature.
|
||||
*
|
||||
* For USB-3 devices: Assume there's only one function on the device and
|
||||
* disable remote wake for the first interface. FIXME if the interface
|
||||
* association descriptor shows there's more than one function.
|
||||
*/
|
||||
static int usb_disable_remote_wakeup(struct usb_device *udev)
|
||||
{
|
||||
if (udev->speed < USB_SPEED_SUPER)
|
||||
return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
|
||||
USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
else
|
||||
return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE,
|
||||
USB_INTRF_FUNC_SUSPEND, 0, NULL, 0,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
|
@ -2918,7 +2968,6 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
|
|||
{
|
||||
struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
|
||||
struct usb_port *port_dev = hub->ports[udev->portnum - 1];
|
||||
enum pm_qos_flags_status pm_qos_stat;
|
||||
int port1 = udev->portnum;
|
||||
int status;
|
||||
bool really_suspend = true;
|
||||
|
@ -2930,33 +2979,13 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
|
|||
* we don't explicitly enable it here.
|
||||
*/
|
||||
if (udev->do_remote_wakeup) {
|
||||
if (!hub_is_superspeed(hub->hdev)) {
|
||||
status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
|
||||
USB_DEVICE_REMOTE_WAKEUP, 0,
|
||||
NULL, 0,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
} else {
|
||||
/* Assume there's only one function on the USB 3.0
|
||||
* device and enable remote wake for the first
|
||||
* interface. FIXME if the interface association
|
||||
* descriptor shows there's more than one function.
|
||||
*/
|
||||
status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
USB_REQ_SET_FEATURE,
|
||||
USB_RECIP_INTERFACE,
|
||||
USB_INTRF_FUNC_SUSPEND,
|
||||
USB_INTRF_FUNC_SUSPEND_RW |
|
||||
USB_INTRF_FUNC_SUSPEND_LP,
|
||||
NULL, 0,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
}
|
||||
status = usb_enable_remote_wakeup(udev);
|
||||
if (status) {
|
||||
dev_dbg(&udev->dev, "won't remote wakeup, status %d\n",
|
||||
status);
|
||||
/* bail if autosuspend is requested */
|
||||
if (PMSG_IS_AUTO(msg))
|
||||
return status;
|
||||
goto err_wakeup;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2965,14 +2994,16 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
|
|||
usb_set_usb2_hardware_lpm(udev, 0);
|
||||
|
||||
if (usb_disable_ltm(udev)) {
|
||||
dev_err(&udev->dev, "%s Failed to disable LTM before suspend\n.",
|
||||
__func__);
|
||||
return -ENOMEM;
|
||||
dev_err(&udev->dev, "Failed to disable LTM before suspend\n.");
|
||||
status = -ENOMEM;
|
||||
if (PMSG_IS_AUTO(msg))
|
||||
goto err_ltm;
|
||||
}
|
||||
if (usb_unlocked_disable_lpm(udev)) {
|
||||
dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.",
|
||||
__func__);
|
||||
return -ENOMEM;
|
||||
dev_err(&udev->dev, "Failed to disable LPM before suspend\n.");
|
||||
status = -ENOMEM;
|
||||
if (PMSG_IS_AUTO(msg))
|
||||
goto err_lpm3;
|
||||
}
|
||||
|
||||
/* see 7.1.7.6 */
|
||||
|
@ -3000,28 +3031,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
|
|||
if (status) {
|
||||
dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
|
||||
port1, status);
|
||||
/* paranoia: "should not happen" */
|
||||
if (udev->do_remote_wakeup) {
|
||||
if (!hub_is_superspeed(hub->hdev)) {
|
||||
(void) usb_control_msg(udev,
|
||||
usb_sndctrlpipe(udev, 0),
|
||||
USB_REQ_CLEAR_FEATURE,
|
||||
USB_RECIP_DEVICE,
|
||||
USB_DEVICE_REMOTE_WAKEUP, 0,
|
||||
NULL, 0,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
} else
|
||||
(void) usb_disable_function_remotewakeup(udev);
|
||||
|
||||
}
|
||||
|
||||
/* Try to enable USB3 LPM and LTM again */
|
||||
usb_unlocked_enable_lpm(udev);
|
||||
err_lpm3:
|
||||
usb_enable_ltm(udev);
|
||||
err_ltm:
|
||||
/* Try to enable USB2 hardware LPM again */
|
||||
if (udev->usb2_hw_lpm_capable == 1)
|
||||
usb_set_usb2_hardware_lpm(udev, 1);
|
||||
|
||||
/* Try to enable USB3 LTM and LPM again */
|
||||
usb_enable_ltm(udev);
|
||||
usb_unlocked_enable_lpm(udev);
|
||||
if (udev->do_remote_wakeup)
|
||||
(void) usb_disable_remote_wakeup(udev);
|
||||
err_wakeup:
|
||||
|
||||
/* System sleep transitions should never fail */
|
||||
if (!PMSG_IS_AUTO(msg))
|
||||
|
@ -3039,16 +3061,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
|
|||
usb_set_device_state(udev, USB_STATE_SUSPENDED);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether current status meets the requirement of
|
||||
* usb port power off mechanism
|
||||
*/
|
||||
pm_qos_stat = dev_pm_qos_flags(&port_dev->dev,
|
||||
PM_QOS_FLAG_NO_POWER_OFF);
|
||||
if (!udev->do_remote_wakeup
|
||||
&& pm_qos_stat != PM_QOS_FLAGS_ALL
|
||||
&& udev->persist_enabled
|
||||
&& !status) {
|
||||
if (status == 0 && !udev->do_remote_wakeup && udev->persist_enabled) {
|
||||
pm_runtime_put_sync(&port_dev->dev);
|
||||
port_dev->did_runtime_put = true;
|
||||
}
|
||||
|
@ -3102,8 +3115,6 @@ static int finish_port_resume(struct usb_device *udev)
|
|||
if (status == 0) {
|
||||
devstatus = 0;
|
||||
status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
|
||||
if (status >= 0)
|
||||
status = (status > 0 ? 0 : -ENODEV);
|
||||
|
||||
/* If a normal resume failed, try doing a reset-resume */
|
||||
if (status && !udev->reset_resume && udev->persist_enabled) {
|
||||
|
@ -3123,24 +3134,15 @@ static int finish_port_resume(struct usb_device *udev)
|
|||
* udev->reset_resume
|
||||
*/
|
||||
} else if (udev->actconfig && !udev->reset_resume) {
|
||||
if (!hub_is_superspeed(udev->parent)) {
|
||||
le16_to_cpus(&devstatus);
|
||||
if (udev->speed < USB_SPEED_SUPER) {
|
||||
if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
|
||||
status = usb_control_msg(udev,
|
||||
usb_sndctrlpipe(udev, 0),
|
||||
USB_REQ_CLEAR_FEATURE,
|
||||
USB_RECIP_DEVICE,
|
||||
USB_DEVICE_REMOTE_WAKEUP, 0,
|
||||
NULL, 0,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
status = usb_disable_remote_wakeup(udev);
|
||||
} else {
|
||||
status = usb_get_status(udev, USB_RECIP_INTERFACE, 0,
|
||||
&devstatus);
|
||||
le16_to_cpus(&devstatus);
|
||||
if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP
|
||||
| USB_INTRF_STAT_FUNC_RW))
|
||||
status =
|
||||
usb_disable_function_remotewakeup(udev);
|
||||
status = usb_disable_remote_wakeup(udev);
|
||||
}
|
||||
|
||||
if (status)
|
||||
|
@ -3274,8 +3276,6 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
|
|||
return status;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
|
||||
/* caller has locked udev */
|
||||
|
@ -3843,7 +3843,8 @@ EXPORT_SYMBOL_GPL(usb_disable_ltm);
|
|||
|
||||
void usb_enable_ltm(struct usb_device *udev) { }
|
||||
EXPORT_SYMBOL_GPL(usb_enable_ltm);
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
|
||||
/* USB 2.0 spec, 7.1.7.3 / fig 7-29:
|
||||
|
@ -4483,11 +4484,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
|
|||
|
||||
status = usb_get_status(udev, USB_RECIP_DEVICE, 0,
|
||||
&devstat);
|
||||
if (status < 2) {
|
||||
if (status) {
|
||||
dev_dbg(&udev->dev, "get status %d ?\n", status);
|
||||
goto loop_disable;
|
||||
}
|
||||
le16_to_cpus(&devstat);
|
||||
if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
|
||||
dev_err(&udev->dev,
|
||||
"can't connect bus-powered hub "
|
||||
|
@ -4648,9 +4648,7 @@ static void hub_events(void)
|
|||
hub_dev = hub->intfdev;
|
||||
intf = to_usb_interface(hub_dev);
|
||||
dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
|
||||
hdev->state, hub->descriptor
|
||||
? hub->descriptor->bNbrPorts
|
||||
: 0,
|
||||
hdev->state, hdev->maxchild,
|
||||
/* NOTE: expects max 15 ports... */
|
||||
(u16) hub->change_bits[0],
|
||||
(u16) hub->event_bits[0]);
|
||||
|
@ -4695,7 +4693,7 @@ static void hub_events(void)
|
|||
}
|
||||
|
||||
/* deal with port status changes */
|
||||
for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {
|
||||
for (i = 1; i <= hdev->maxchild; i++) {
|
||||
if (test_bit(i, hub->busy_bits))
|
||||
continue;
|
||||
connect_change = test_bit(i, hub->change_bits);
|
||||
|
@ -4946,7 +4944,8 @@ void usb_hub_cleanup(void)
|
|||
} /* usb_hub_cleanup() */
|
||||
|
||||
static int descriptors_changed(struct usb_device *udev,
|
||||
struct usb_device_descriptor *old_device_descriptor)
|
||||
struct usb_device_descriptor *old_device_descriptor,
|
||||
struct usb_host_bos *old_bos)
|
||||
{
|
||||
int changed = 0;
|
||||
unsigned index;
|
||||
|
@ -4960,6 +4959,16 @@ static int descriptors_changed(struct usb_device *udev,
|
|||
sizeof(*old_device_descriptor)) != 0)
|
||||
return 1;
|
||||
|
||||
if ((old_bos && !udev->bos) || (!old_bos && udev->bos))
|
||||
return 1;
|
||||
if (udev->bos) {
|
||||
len = le16_to_cpu(udev->bos->desc->wTotalLength);
|
||||
if (len != le16_to_cpu(old_bos->desc->wTotalLength))
|
||||
return 1;
|
||||
if (memcmp(udev->bos->desc, old_bos->desc, len))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Since the idVendor, idProduct, and bcdDevice values in the
|
||||
* device descriptor haven't changed, we will assume the
|
||||
* Manufacturer and Product strings haven't changed either.
|
||||
|
@ -5035,10 +5044,11 @@ static int descriptors_changed(struct usb_device *udev,
|
|||
* re-connected. All drivers will be unbound, and the device will be
|
||||
* re-enumerated and probed all over again.
|
||||
*
|
||||
* Returns 0 if the reset succeeded, -ENODEV if the device has been
|
||||
* Return: 0 if the reset succeeded, -ENODEV if the device has been
|
||||
* flagged for logical disconnection, or some other negative error code
|
||||
* if the reset wasn't even attempted.
|
||||
*
|
||||
* Note:
|
||||
* The caller must own the device lock. For example, it's safe to use
|
||||
* this from a driver probe() routine after downloading new firmware.
|
||||
* For calls that might not occur during probe(), drivers should lock
|
||||
|
@ -5055,6 +5065,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
|
|||
struct usb_hub *parent_hub;
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
struct usb_device_descriptor descriptor = udev->descriptor;
|
||||
struct usb_host_bos *bos;
|
||||
int i, ret = 0;
|
||||
int port1 = udev->portnum;
|
||||
|
||||
|
@ -5072,6 +5083,9 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
|
|||
}
|
||||
parent_hub = usb_hub_to_struct_hub(parent_hdev);
|
||||
|
||||
bos = udev->bos;
|
||||
udev->bos = NULL;
|
||||
|
||||
/* Disable LPM and LTM while we reset the device and reinstall the alt
|
||||
* settings. Device-initiated LPM settings, and system exit latency
|
||||
* settings are cleared when the device is reset, so we have to set
|
||||
|
@ -5105,7 +5119,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
|
|||
goto re_enumerate;
|
||||
|
||||
/* Device might have changed firmware (DFU or similar) */
|
||||
if (descriptors_changed(udev, &descriptor)) {
|
||||
if (descriptors_changed(udev, &descriptor, bos)) {
|
||||
dev_info(&udev->dev, "device firmware changed\n");
|
||||
udev->descriptor = descriptor; /* for disconnect() calls */
|
||||
goto re_enumerate;
|
||||
|
@ -5178,11 +5192,15 @@ done:
|
|||
/* Now that the alt settings are re-installed, enable LTM and LPM. */
|
||||
usb_unlocked_enable_lpm(udev);
|
||||
usb_enable_ltm(udev);
|
||||
usb_release_bos_descriptor(udev);
|
||||
udev->bos = bos;
|
||||
return 0;
|
||||
|
||||
re_enumerate:
|
||||
/* LPM state doesn't matter when we're about to destroy the device. */
|
||||
hub_port_logical_disconnect(parent_hub, port1);
|
||||
usb_release_bos_descriptor(udev);
|
||||
udev->bos = bos;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -5194,8 +5212,9 @@ re_enumerate:
|
|||
* method), performs the port reset, and then lets the drivers know that
|
||||
* the reset is over (using their post_reset method).
|
||||
*
|
||||
* Return value is the same as for usb_reset_and_verify_device().
|
||||
* Return: The same as for usb_reset_and_verify_device().
|
||||
*
|
||||
* Note:
|
||||
* The caller must own the device lock. For example, it's safe to use
|
||||
* this from a driver probe() routine after downloading new firmware.
|
||||
* For calls that might not occur during probe(), drivers should lock
|
||||
|
@ -5333,7 +5352,7 @@ EXPORT_SYMBOL_GPL(usb_queue_reset_device);
|
|||
* USB drivers call this function to get hub's child device
|
||||
* pointer.
|
||||
*
|
||||
* Return NULL if input param is invalid and
|
||||
* Return: %NULL if input param is invalid and
|
||||
* child's usb_device pointer if non-NULL.
|
||||
*/
|
||||
struct usb_device *usb_hub_find_child(struct usb_device *hdev,
|
||||
|
@ -5367,8 +5386,8 @@ void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1,
|
|||
* @hdev: USB device belonging to the usb hub
|
||||
* @port1: port num of the port
|
||||
*
|
||||
* Return connect type of the port and if input params are
|
||||
* invalid, return USB_PORT_CONNECT_TYPE_UNKNOWN.
|
||||
* Return: The connect type of the port if successful. Or
|
||||
* USB_PORT_CONNECT_TYPE_UNKNOWN if input params are invalid.
|
||||
*/
|
||||
enum usb_port_connect_type
|
||||
usb_get_hub_port_connect_type(struct usb_device *hdev, int port1)
|
||||
|
@ -5428,8 +5447,8 @@ void usb_hub_adjust_deviceremovable(struct usb_device *hdev,
|
|||
* @hdev: USB device belonging to the usb hub
|
||||
* @port1: port num of the port
|
||||
*
|
||||
* Return port's acpi handle if successful, NULL if params are
|
||||
* invaild.
|
||||
* Return: Port's acpi handle if successful, %NULL if params are
|
||||
* invalid.
|
||||
*/
|
||||
acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev,
|
||||
int port1)
|
||||
|
|
|
@ -119,15 +119,15 @@ static int usb_internal_control_msg(struct usb_device *usb_dev,
|
|||
* This function sends a simple control message to a specified endpoint and
|
||||
* waits for the message to complete, or timeout.
|
||||
*
|
||||
* If successful, it returns the number of bytes transferred, otherwise a
|
||||
* negative error number.
|
||||
*
|
||||
* Don't use this function from within an interrupt context, like a bottom half
|
||||
* handler. If you need an asynchronous message, or need to send a message
|
||||
* from within interrupt context, use usb_submit_urb().
|
||||
* If a thread in your driver uses this call, make sure your disconnect()
|
||||
* method can wait for it to complete. Since you don't have a handle on the
|
||||
* URB used, you can't cancel the request.
|
||||
*
|
||||
* Return: If successful, the number of bytes transferred. Otherwise, a negative
|
||||
* error number.
|
||||
*/
|
||||
int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
|
||||
__u8 requesttype, __u16 value, __u16 index, void *data,
|
||||
|
@ -170,15 +170,16 @@ EXPORT_SYMBOL_GPL(usb_control_msg);
|
|||
* This function sends a simple interrupt message to a specified endpoint and
|
||||
* waits for the message to complete, or timeout.
|
||||
*
|
||||
* If successful, it returns 0, otherwise a negative error number. The number
|
||||
* of actual bytes transferred will be stored in the actual_length paramater.
|
||||
*
|
||||
* Don't use this function from within an interrupt context, like a bottom half
|
||||
* handler. If you need an asynchronous message, or need to send a message
|
||||
* from within interrupt context, use usb_submit_urb() If a thread in your
|
||||
* driver uses this call, make sure your disconnect() method can wait for it to
|
||||
* complete. Since you don't have a handle on the URB used, you can't cancel
|
||||
* the request.
|
||||
*
|
||||
* Return:
|
||||
* If successful, 0. Otherwise a negative error number. The number of actual
|
||||
* bytes transferred will be stored in the @actual_length paramater.
|
||||
*/
|
||||
int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
|
||||
void *data, int len, int *actual_length, int timeout)
|
||||
|
@ -203,9 +204,6 @@ EXPORT_SYMBOL_GPL(usb_interrupt_msg);
|
|||
* This function sends a simple bulk message to a specified endpoint
|
||||
* and waits for the message to complete, or timeout.
|
||||
*
|
||||
* If successful, it returns 0, otherwise a negative error number. The number
|
||||
* of actual bytes transferred will be stored in the actual_length paramater.
|
||||
*
|
||||
* Don't use this function from within an interrupt context, like a bottom half
|
||||
* handler. If you need an asynchronous message, or need to send a message
|
||||
* from within interrupt context, use usb_submit_urb() If a thread in your
|
||||
|
@ -217,6 +215,11 @@ EXPORT_SYMBOL_GPL(usb_interrupt_msg);
|
|||
* users are forced to abuse this routine by using it to submit URBs for
|
||||
* interrupt endpoints. We will take the liberty of creating an interrupt URB
|
||||
* (with the default interval) if the target is an interrupt endpoint.
|
||||
*
|
||||
* Return:
|
||||
* If successful, 0. Otherwise a negative error number. The number of actual
|
||||
* bytes transferred will be stored in the @actual_length paramater.
|
||||
*
|
||||
*/
|
||||
int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
|
||||
void *data, int len, int *actual_length, int timeout)
|
||||
|
@ -341,9 +344,9 @@ static void sg_complete(struct urb *urb)
|
|||
* send every byte identified in the list.
|
||||
* @mem_flags: SLAB_* flags affecting memory allocations in this call
|
||||
*
|
||||
* Returns zero for success, else a negative errno value. This initializes a
|
||||
* scatter/gather request, allocating resources such as I/O mappings and urb
|
||||
* memory (except maybe memory used by USB controller drivers).
|
||||
* This initializes a scatter/gather request, allocating resources such as
|
||||
* I/O mappings and urb memory (except maybe memory used by USB controller
|
||||
* drivers).
|
||||
*
|
||||
* The request must be issued using usb_sg_wait(), which waits for the I/O to
|
||||
* complete (or to be canceled) and then cleans up all resources allocated by
|
||||
|
@ -351,6 +354,8 @@ static void sg_complete(struct urb *urb)
|
|||
*
|
||||
* The request may be canceled with usb_sg_cancel(), either before or after
|
||||
* usb_sg_wait() is called.
|
||||
*
|
||||
* Return: Zero for success, else a negative errno value.
|
||||
*/
|
||||
int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
|
||||
unsigned pipe, unsigned period, struct scatterlist *sg,
|
||||
|
@ -623,7 +628,7 @@ EXPORT_SYMBOL_GPL(usb_sg_cancel);
|
|||
*
|
||||
* This call is synchronous, and may not be used in an interrupt context.
|
||||
*
|
||||
* Returns the number of bytes received on success, or else the status code
|
||||
* Return: The number of bytes received on success, or else the status code
|
||||
* returned by the underlying usb_control_msg() call.
|
||||
*/
|
||||
int usb_get_descriptor(struct usb_device *dev, unsigned char type,
|
||||
|
@ -671,7 +676,7 @@ EXPORT_SYMBOL_GPL(usb_get_descriptor);
|
|||
*
|
||||
* This call is synchronous, and may not be used in an interrupt context.
|
||||
*
|
||||
* Returns the number of bytes received on success, or else the status code
|
||||
* Return: The number of bytes received on success, or else the status code
|
||||
* returned by the underlying usb_control_msg() call.
|
||||
*/
|
||||
static int usb_get_string(struct usb_device *dev, unsigned short langid,
|
||||
|
@ -805,7 +810,7 @@ static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf)
|
|||
*
|
||||
* This call is synchronous, and may not be used in an interrupt context.
|
||||
*
|
||||
* Returns length of the string (>= 0) or usb_control_msg status (< 0).
|
||||
* Return: length of the string (>= 0) or usb_control_msg status (< 0).
|
||||
*/
|
||||
int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
|
||||
{
|
||||
|
@ -853,8 +858,8 @@ EXPORT_SYMBOL_GPL(usb_string);
|
|||
* @udev: the device whose string descriptor is being read
|
||||
* @index: the descriptor index
|
||||
*
|
||||
* Returns a pointer to a kmalloc'ed buffer containing the descriptor string,
|
||||
* or NULL if the index is 0 or the string could not be read.
|
||||
* Return: A pointer to a kmalloc'ed buffer containing the descriptor string,
|
||||
* or %NULL if the index is 0 or the string could not be read.
|
||||
*/
|
||||
char *usb_cache_string(struct usb_device *udev, int index)
|
||||
{
|
||||
|
@ -894,7 +899,7 @@ char *usb_cache_string(struct usb_device *udev, int index)
|
|||
*
|
||||
* This call is synchronous, and may not be used in an interrupt context.
|
||||
*
|
||||
* Returns the number of bytes received on success, or else the status code
|
||||
* Return: The number of bytes received on success, or else the status code
|
||||
* returned by the underlying usb_control_msg() call.
|
||||
*/
|
||||
int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
|
||||
|
@ -934,13 +939,13 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
|
|||
*
|
||||
* This call is synchronous, and may not be used in an interrupt context.
|
||||
*
|
||||
* Returns the number of bytes received on success, or else the status code
|
||||
* returned by the underlying usb_control_msg() call.
|
||||
* Returns 0 and the status value in *@data (in host byte order) on success,
|
||||
* or else the status code from the underlying usb_control_msg() call.
|
||||
*/
|
||||
int usb_get_status(struct usb_device *dev, int type, int target, void *data)
|
||||
{
|
||||
int ret;
|
||||
u16 *status = kmalloc(sizeof(*status), GFP_KERNEL);
|
||||
__le16 *status = kmalloc(sizeof(*status), GFP_KERNEL);
|
||||
|
||||
if (!status)
|
||||
return -ENOMEM;
|
||||
|
@ -949,7 +954,12 @@ int usb_get_status(struct usb_device *dev, int type, int target, void *data)
|
|||
USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status,
|
||||
sizeof(*status), USB_CTRL_GET_TIMEOUT);
|
||||
|
||||
*(u16 *)data = *status;
|
||||
if (ret == 2) {
|
||||
*(u16 *) data = le16_to_cpu(*status);
|
||||
ret = 0;
|
||||
} else if (ret >= 0) {
|
||||
ret = -EIO;
|
||||
}
|
||||
kfree(status);
|
||||
return ret;
|
||||
}
|
||||
|
@ -975,7 +985,7 @@ EXPORT_SYMBOL_GPL(usb_get_status);
|
|||
*
|
||||
* This call is synchronous, and may not be used in an interrupt context.
|
||||
*
|
||||
* Returns zero on success, or else the status code returned by the
|
||||
* Return: Zero on success, or else the status code returned by the
|
||||
* underlying usb_control_msg() call.
|
||||
*/
|
||||
int usb_clear_halt(struct usb_device *dev, int pipe)
|
||||
|
@ -1272,7 +1282,7 @@ void usb_enable_interface(struct usb_device *dev,
|
|||
* endpoints in that interface; all such urbs must first be completed
|
||||
* (perhaps forced by unlinking).
|
||||
*
|
||||
* Returns zero on success, or else the status code returned by the
|
||||
* Return: Zero on success, or else the status code returned by the
|
||||
* underlying usb_control_msg() call.
|
||||
*/
|
||||
int usb_set_interface(struct usb_device *dev, int interface, int alternate)
|
||||
|
@ -1426,7 +1436,7 @@ EXPORT_SYMBOL_GPL(usb_set_interface);
|
|||
*
|
||||
* The caller must own the device lock.
|
||||
*
|
||||
* Returns zero on success, else a negative error code.
|
||||
* Return: Zero on success, else a negative error code.
|
||||
*/
|
||||
int usb_reset_configuration(struct usb_device *dev)
|
||||
{
|
||||
|
@ -1968,7 +1978,7 @@ static void cancel_async_set_config(struct usb_device *udev)
|
|||
* routine gets around the normal restrictions by using a work thread to
|
||||
* submit the change-config request.
|
||||
*
|
||||
* Returns 0 if the request was successfully queued, error code otherwise.
|
||||
* Return: 0 if the request was successfully queued, error code otherwise.
|
||||
* The caller has no way to know whether the queued request will eventually
|
||||
* succeed.
|
||||
*/
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
|
||||
static const struct attribute_group *port_dev_group[];
|
||||
|
||||
static ssize_t show_port_connect_type(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t connect_type_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_port *port_dev = to_usb_port(dev);
|
||||
char *result;
|
||||
|
@ -46,8 +46,7 @@ static ssize_t show_port_connect_type(struct device *dev,
|
|||
|
||||
return sprintf(buf, "%s\n", result);
|
||||
}
|
||||
static DEVICE_ATTR(connect_type, S_IRUGO, show_port_connect_type,
|
||||
NULL);
|
||||
static DEVICE_ATTR_RO(connect_type);
|
||||
|
||||
static struct attribute *port_dev_attrs[] = {
|
||||
&dev_attr_connect_type.attr,
|
||||
|
@ -89,22 +88,19 @@ static int usb_port_runtime_resume(struct device *dev)
|
|||
retval = usb_hub_set_port_power(hdev, hub, port1, true);
|
||||
if (port_dev->child && !retval) {
|
||||
/*
|
||||
* Wait for usb hub port to be reconnected in order to make
|
||||
* the resume procedure successful.
|
||||
* Attempt to wait for usb hub port to be reconnected in order
|
||||
* to make the resume procedure successful. The device may have
|
||||
* disconnected while the port was powered off, so ignore the
|
||||
* return status.
|
||||
*/
|
||||
retval = hub_port_debounce_be_connected(hub, port1);
|
||||
if (retval < 0) {
|
||||
if (retval < 0)
|
||||
dev_dbg(&port_dev->dev, "can't get reconnection after setting port power on, status %d\n",
|
||||
retval);
|
||||
goto out;
|
||||
}
|
||||
usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);
|
||||
|
||||
/* Set return value to 0 if debounce successful */
|
||||
retval = 0;
|
||||
}
|
||||
|
||||
out:
|
||||
clear_bit(port1, hub->busy_bits);
|
||||
usb_autopm_put_interface(intf);
|
||||
return retval;
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
/* Active configuration fields */
|
||||
#define usb_actconfig_show(field, format_string) \
|
||||
static ssize_t show_##field(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
static ssize_t field##_show(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct usb_device *udev; \
|
||||
struct usb_host_config *actconfig; \
|
||||
|
@ -35,12 +35,12 @@ static ssize_t show_##field(struct device *dev, \
|
|||
|
||||
#define usb_actconfig_attr(field, format_string) \
|
||||
usb_actconfig_show(field, format_string) \
|
||||
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
|
||||
static DEVICE_ATTR_RO(field)
|
||||
|
||||
usb_actconfig_attr(bNumInterfaces, "%2d\n")
|
||||
usb_actconfig_attr(bmAttributes, "%2x\n")
|
||||
usb_actconfig_attr(bNumInterfaces, "%2d\n");
|
||||
usb_actconfig_attr(bmAttributes, "%2x\n");
|
||||
|
||||
static ssize_t show_bMaxPower(struct device *dev,
|
||||
static ssize_t bMaxPower_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
|
@ -52,9 +52,9 @@ static ssize_t show_bMaxPower(struct device *dev,
|
|||
return 0;
|
||||
return sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig));
|
||||
}
|
||||
static DEVICE_ATTR(bMaxPower, S_IRUGO, show_bMaxPower, NULL);
|
||||
static DEVICE_ATTR_RO(bMaxPower);
|
||||
|
||||
static ssize_t show_configuration_string(struct device *dev,
|
||||
static ssize_t configuration_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
|
@ -66,14 +66,14 @@ static ssize_t show_configuration_string(struct device *dev,
|
|||
return 0;
|
||||
return sprintf(buf, "%s\n", actconfig->string);
|
||||
}
|
||||
static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
|
||||
static DEVICE_ATTR_RO(configuration);
|
||||
|
||||
/* configuration value is always present, and r/w */
|
||||
usb_actconfig_show(bConfigurationValue, "%u\n");
|
||||
|
||||
static ssize_t
|
||||
set_bConfigurationValue(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t bConfigurationValue_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
int config, value;
|
||||
|
@ -85,13 +85,12 @@ set_bConfigurationValue(struct device *dev, struct device_attribute *attr,
|
|||
usb_unlock_device(udev);
|
||||
return (value < 0) ? value : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_IGNORE_LOCKDEP(bConfigurationValue, S_IRUGO | S_IWUSR,
|
||||
show_bConfigurationValue, set_bConfigurationValue);
|
||||
bConfigurationValue_show, bConfigurationValue_store);
|
||||
|
||||
/* String fields */
|
||||
#define usb_string_attr(name) \
|
||||
static ssize_t show_##name(struct device *dev, \
|
||||
static ssize_t name##_show(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct usb_device *udev; \
|
||||
|
@ -103,14 +102,14 @@ static ssize_t show_##name(struct device *dev, \
|
|||
usb_unlock_device(udev); \
|
||||
return retval; \
|
||||
} \
|
||||
static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
|
||||
static DEVICE_ATTR_RO(name)
|
||||
|
||||
usb_string_attr(product);
|
||||
usb_string_attr(manufacturer);
|
||||
usb_string_attr(serial);
|
||||
|
||||
static ssize_t
|
||||
show_speed(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t speed_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
char *speed;
|
||||
|
@ -139,40 +138,40 @@ show_speed(struct device *dev, struct device_attribute *attr, char *buf)
|
|||
}
|
||||
return sprintf(buf, "%s\n", speed);
|
||||
}
|
||||
static DEVICE_ATTR(speed, S_IRUGO, show_speed, NULL);
|
||||
static DEVICE_ATTR_RO(speed);
|
||||
|
||||
static ssize_t
|
||||
show_busnum(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t busnum_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
|
||||
udev = to_usb_device(dev);
|
||||
return sprintf(buf, "%d\n", udev->bus->busnum);
|
||||
}
|
||||
static DEVICE_ATTR(busnum, S_IRUGO, show_busnum, NULL);
|
||||
static DEVICE_ATTR_RO(busnum);
|
||||
|
||||
static ssize_t
|
||||
show_devnum(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t devnum_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
|
||||
udev = to_usb_device(dev);
|
||||
return sprintf(buf, "%d\n", udev->devnum);
|
||||
}
|
||||
static DEVICE_ATTR(devnum, S_IRUGO, show_devnum, NULL);
|
||||
static DEVICE_ATTR_RO(devnum);
|
||||
|
||||
static ssize_t
|
||||
show_devpath(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t devpath_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
|
||||
udev = to_usb_device(dev);
|
||||
return sprintf(buf, "%s\n", udev->devpath);
|
||||
}
|
||||
static DEVICE_ATTR(devpath, S_IRUGO, show_devpath, NULL);
|
||||
static DEVICE_ATTR_RO(devpath);
|
||||
|
||||
static ssize_t
|
||||
show_version(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t version_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
u16 bcdUSB;
|
||||
|
@ -181,30 +180,30 @@ show_version(struct device *dev, struct device_attribute *attr, char *buf)
|
|||
bcdUSB = le16_to_cpu(udev->descriptor.bcdUSB);
|
||||
return sprintf(buf, "%2x.%02x\n", bcdUSB >> 8, bcdUSB & 0xff);
|
||||
}
|
||||
static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
|
||||
static DEVICE_ATTR_RO(version);
|
||||
|
||||
static ssize_t
|
||||
show_maxchild(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t maxchild_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
|
||||
udev = to_usb_device(dev);
|
||||
return sprintf(buf, "%d\n", udev->maxchild);
|
||||
}
|
||||
static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL);
|
||||
static DEVICE_ATTR_RO(maxchild);
|
||||
|
||||
static ssize_t
|
||||
show_quirks(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t quirks_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
|
||||
udev = to_usb_device(dev);
|
||||
return sprintf(buf, "0x%x\n", udev->quirks);
|
||||
}
|
||||
static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
|
||||
static DEVICE_ATTR_RO(quirks);
|
||||
|
||||
static ssize_t
|
||||
show_avoid_reset_quirk(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t avoid_reset_quirk_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
|
||||
|
@ -212,9 +211,9 @@ show_avoid_reset_quirk(struct device *dev, struct device_attribute *attr, char *
|
|||
return sprintf(buf, "%d\n", !!(udev->quirks & USB_QUIRK_RESET));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
set_avoid_reset_quirk(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t avoid_reset_quirk_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
int val;
|
||||
|
@ -229,22 +228,20 @@ set_avoid_reset_quirk(struct device *dev, struct device_attribute *attr,
|
|||
usb_unlock_device(udev);
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(avoid_reset_quirk);
|
||||
|
||||
static DEVICE_ATTR(avoid_reset_quirk, S_IRUGO | S_IWUSR,
|
||||
show_avoid_reset_quirk, set_avoid_reset_quirk);
|
||||
|
||||
static ssize_t
|
||||
show_urbnum(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t urbnum_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
|
||||
udev = to_usb_device(dev);
|
||||
return sprintf(buf, "%d\n", atomic_read(&udev->urbnum));
|
||||
}
|
||||
static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL);
|
||||
static DEVICE_ATTR_RO(urbnum);
|
||||
|
||||
static ssize_t
|
||||
show_removable(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t removable_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
char *state;
|
||||
|
@ -264,30 +261,29 @@ show_removable(struct device *dev, struct device_attribute *attr, char *buf)
|
|||
|
||||
return sprintf(buf, "%s\n", state);
|
||||
}
|
||||
static DEVICE_ATTR(removable, S_IRUGO, show_removable, NULL);
|
||||
static DEVICE_ATTR_RO(removable);
|
||||
|
||||
static ssize_t
|
||||
show_ltm_capable(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t ltm_capable_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (usb_device_supports_ltm(to_usb_device(dev)))
|
||||
return sprintf(buf, "%s\n", "yes");
|
||||
return sprintf(buf, "%s\n", "no");
|
||||
}
|
||||
static DEVICE_ATTR(ltm_capable, S_IRUGO, show_ltm_capable, NULL);
|
||||
static DEVICE_ATTR_RO(ltm_capable);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static ssize_t
|
||||
show_persist(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t persist_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", udev->persist_enabled);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
set_persist(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t persist_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
int value;
|
||||
|
@ -304,8 +300,7 @@ set_persist(struct device *dev, struct device_attribute *attr,
|
|||
usb_unlock_device(udev);
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(persist, S_IRUGO | S_IWUSR, show_persist, set_persist);
|
||||
static DEVICE_ATTR_RW(persist);
|
||||
|
||||
static int add_persist_attributes(struct device *dev)
|
||||
{
|
||||
|
@ -340,17 +335,15 @@ static void remove_persist_attributes(struct device *dev)
|
|||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
|
||||
static ssize_t
|
||||
show_connected_duration(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t connected_duration_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
|
||||
return sprintf(buf, "%u\n",
|
||||
jiffies_to_msecs(jiffies - udev->connect_time));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(connected_duration, S_IRUGO, show_connected_duration, NULL);
|
||||
static DEVICE_ATTR_RO(connected_duration);
|
||||
|
||||
/*
|
||||
* If the device is resumed, the last time the device was suspended has
|
||||
|
@ -359,9 +352,8 @@ static DEVICE_ATTR(connected_duration, S_IRUGO, show_connected_duration, NULL);
|
|||
*
|
||||
* If the device is suspended, the active_duration is up-to-date.
|
||||
*/
|
||||
static ssize_t
|
||||
show_active_duration(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t active_duration_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
int duration;
|
||||
|
@ -372,18 +364,17 @@ show_active_duration(struct device *dev, struct device_attribute *attr,
|
|||
duration = jiffies_to_msecs(udev->active_duration);
|
||||
return sprintf(buf, "%u\n", duration);
|
||||
}
|
||||
static DEVICE_ATTR_RO(active_duration);
|
||||
|
||||
static DEVICE_ATTR(active_duration, S_IRUGO, show_active_duration, NULL);
|
||||
|
||||
static ssize_t
|
||||
show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t autosuspend_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", dev->power.autosuspend_delay / 1000);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
set_autosuspend(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t autosuspend_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
int value;
|
||||
|
||||
|
@ -394,9 +385,7 @@ set_autosuspend(struct device *dev, struct device_attribute *attr,
|
|||
pm_runtime_set_autosuspend_delay(dev, value * 1000);
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR,
|
||||
show_autosuspend, set_autosuspend);
|
||||
static DEVICE_ATTR_RW(autosuspend);
|
||||
|
||||
static const char on_string[] = "on";
|
||||
static const char auto_string[] = "auto";
|
||||
|
@ -411,8 +400,8 @@ static void warn_level(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
show_level(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t level_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
const char *p = auto_string;
|
||||
|
@ -423,9 +412,8 @@ show_level(struct device *dev, struct device_attribute *attr, char *buf)
|
|||
return sprintf(buf, "%s\n", p);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
set_level(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t level_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
int len = count;
|
||||
|
@ -453,12 +441,10 @@ set_level(struct device *dev, struct device_attribute *attr,
|
|||
usb_unlock_device(udev);
|
||||
return rc;
|
||||
}
|
||||
static DEVICE_ATTR_RW(level);
|
||||
|
||||
static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
|
||||
|
||||
static ssize_t
|
||||
show_usb2_hardware_lpm(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t usb2_hardware_lpm_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
const char *p;
|
||||
|
@ -471,9 +457,9 @@ show_usb2_hardware_lpm(struct device *dev, struct device_attribute *attr,
|
|||
return sprintf(buf, "%s\n", p);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
set_usb2_hardware_lpm(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t usb2_hardware_lpm_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
bool value;
|
||||
|
@ -493,21 +479,19 @@ set_usb2_hardware_lpm(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR_RW(usb2_hardware_lpm);
|
||||
|
||||
static DEVICE_ATTR(usb2_hardware_lpm, S_IRUGO | S_IWUSR, show_usb2_hardware_lpm,
|
||||
set_usb2_hardware_lpm);
|
||||
|
||||
static ssize_t
|
||||
show_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t usb2_lpm_l1_timeout_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
return sprintf(buf, "%d\n", udev->l1_params.timeout);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
set_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t usb2_lpm_l1_timeout_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
u16 timeout;
|
||||
|
@ -519,21 +503,18 @@ set_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(usb2_lpm_l1_timeout);
|
||||
|
||||
static DEVICE_ATTR(usb2_lpm_l1_timeout, S_IRUGO | S_IWUSR,
|
||||
show_usb2_lpm_l1_timeout, set_usb2_lpm_l1_timeout);
|
||||
|
||||
static ssize_t
|
||||
show_usb2_lpm_besl(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t usb2_lpm_besl_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
return sprintf(buf, "%d\n", udev->l1_params.besl);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
set_usb2_lpm_besl(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t usb2_lpm_besl_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
u8 besl;
|
||||
|
@ -545,9 +526,7 @@ set_usb2_lpm_besl(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(usb2_lpm_besl, S_IRUGO | S_IWUSR,
|
||||
show_usb2_lpm_besl, set_usb2_lpm_besl);
|
||||
static DEVICE_ATTR_RW(usb2_lpm_besl);
|
||||
|
||||
static struct attribute *usb2_hardware_lpm_attr[] = {
|
||||
&dev_attr_usb2_hardware_lpm.attr,
|
||||
|
@ -604,7 +583,7 @@ static void remove_power_attributes(struct device *dev)
|
|||
/* Descriptor fields */
|
||||
#define usb_descriptor_attr_le16(field, format_string) \
|
||||
static ssize_t \
|
||||
show_##field(struct device *dev, struct device_attribute *attr, \
|
||||
field##_show(struct device *dev, struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct usb_device *udev; \
|
||||
|
@ -613,15 +592,15 @@ show_##field(struct device *dev, struct device_attribute *attr, \
|
|||
return sprintf(buf, format_string, \
|
||||
le16_to_cpu(udev->descriptor.field)); \
|
||||
} \
|
||||
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
|
||||
static DEVICE_ATTR_RO(field)
|
||||
|
||||
usb_descriptor_attr_le16(idVendor, "%04x\n")
|
||||
usb_descriptor_attr_le16(idProduct, "%04x\n")
|
||||
usb_descriptor_attr_le16(bcdDevice, "%04x\n")
|
||||
usb_descriptor_attr_le16(idVendor, "%04x\n");
|
||||
usb_descriptor_attr_le16(idProduct, "%04x\n");
|
||||
usb_descriptor_attr_le16(bcdDevice, "%04x\n");
|
||||
|
||||
#define usb_descriptor_attr(field, format_string) \
|
||||
static ssize_t \
|
||||
show_##field(struct device *dev, struct device_attribute *attr, \
|
||||
field##_show(struct device *dev, struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct usb_device *udev; \
|
||||
|
@ -629,34 +608,31 @@ show_##field(struct device *dev, struct device_attribute *attr, \
|
|||
udev = to_usb_device(dev); \
|
||||
return sprintf(buf, format_string, udev->descriptor.field); \
|
||||
} \
|
||||
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
|
||||
|
||||
usb_descriptor_attr(bDeviceClass, "%02x\n")
|
||||
usb_descriptor_attr(bDeviceSubClass, "%02x\n")
|
||||
usb_descriptor_attr(bDeviceProtocol, "%02x\n")
|
||||
usb_descriptor_attr(bNumConfigurations, "%d\n")
|
||||
usb_descriptor_attr(bMaxPacketSize0, "%d\n")
|
||||
static DEVICE_ATTR_RO(field)
|
||||
|
||||
usb_descriptor_attr(bDeviceClass, "%02x\n");
|
||||
usb_descriptor_attr(bDeviceSubClass, "%02x\n");
|
||||
usb_descriptor_attr(bDeviceProtocol, "%02x\n");
|
||||
usb_descriptor_attr(bNumConfigurations, "%d\n");
|
||||
usb_descriptor_attr(bMaxPacketSize0, "%d\n");
|
||||
|
||||
|
||||
/* show if the device is authorized (1) or not (0) */
|
||||
static ssize_t usb_dev_authorized_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t authorized_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_device *usb_dev = to_usb_device(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n", usb_dev->authorized);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Authorize a device to be used in the system
|
||||
*
|
||||
* Writing a 0 deauthorizes the device, writing a 1 authorizes it.
|
||||
*/
|
||||
static ssize_t usb_dev_authorized_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
static ssize_t authorized_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
ssize_t result;
|
||||
struct usb_device *usb_dev = to_usb_device(dev);
|
||||
|
@ -670,14 +646,12 @@ static ssize_t usb_dev_authorized_store(struct device *dev,
|
|||
result = usb_authorize_device(usb_dev);
|
||||
return result < 0? result : size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_IGNORE_LOCKDEP(authorized, 0644,
|
||||
usb_dev_authorized_show, usb_dev_authorized_store);
|
||||
static DEVICE_ATTR_IGNORE_LOCKDEP(authorized, S_IRUGO | S_IWUSR,
|
||||
authorized_show, authorized_store);
|
||||
|
||||
/* "Safely remove a device" */
|
||||
static ssize_t usb_remove_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t remove_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
int rc = 0;
|
||||
|
@ -694,7 +668,7 @@ static ssize_t usb_remove_store(struct device *dev,
|
|||
usb_unlock_device(udev);
|
||||
return rc;
|
||||
}
|
||||
static DEVICE_ATTR_IGNORE_LOCKDEP(remove, 0200, NULL, usb_remove_store);
|
||||
static DEVICE_ATTR_IGNORE_LOCKDEP(remove, S_IWUSR, NULL, remove_store);
|
||||
|
||||
|
||||
static struct attribute *dev_attrs[] = {
|
||||
|
@ -853,7 +827,7 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
|
|||
/* Interface Accociation Descriptor fields */
|
||||
#define usb_intf_assoc_attr(field, format_string) \
|
||||
static ssize_t \
|
||||
show_iad_##field(struct device *dev, struct device_attribute *attr, \
|
||||
iad_##field##_show(struct device *dev, struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
|
@ -861,18 +835,18 @@ show_iad_##field(struct device *dev, struct device_attribute *attr, \
|
|||
return sprintf(buf, format_string, \
|
||||
intf->intf_assoc->field); \
|
||||
} \
|
||||
static DEVICE_ATTR(iad_##field, S_IRUGO, show_iad_##field, NULL);
|
||||
static DEVICE_ATTR_RO(iad_##field)
|
||||
|
||||
usb_intf_assoc_attr(bFirstInterface, "%02x\n")
|
||||
usb_intf_assoc_attr(bInterfaceCount, "%02d\n")
|
||||
usb_intf_assoc_attr(bFunctionClass, "%02x\n")
|
||||
usb_intf_assoc_attr(bFunctionSubClass, "%02x\n")
|
||||
usb_intf_assoc_attr(bFunctionProtocol, "%02x\n")
|
||||
usb_intf_assoc_attr(bFirstInterface, "%02x\n");
|
||||
usb_intf_assoc_attr(bInterfaceCount, "%02d\n");
|
||||
usb_intf_assoc_attr(bFunctionClass, "%02x\n");
|
||||
usb_intf_assoc_attr(bFunctionSubClass, "%02x\n");
|
||||
usb_intf_assoc_attr(bFunctionProtocol, "%02x\n");
|
||||
|
||||
/* Interface fields */
|
||||
#define usb_intf_attr(field, format_string) \
|
||||
static ssize_t \
|
||||
show_##field(struct device *dev, struct device_attribute *attr, \
|
||||
field##_show(struct device *dev, struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
|
@ -880,17 +854,17 @@ show_##field(struct device *dev, struct device_attribute *attr, \
|
|||
return sprintf(buf, format_string, \
|
||||
intf->cur_altsetting->desc.field); \
|
||||
} \
|
||||
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
|
||||
static DEVICE_ATTR_RO(field)
|
||||
|
||||
usb_intf_attr(bInterfaceNumber, "%02x\n")
|
||||
usb_intf_attr(bAlternateSetting, "%2d\n")
|
||||
usb_intf_attr(bNumEndpoints, "%02x\n")
|
||||
usb_intf_attr(bInterfaceClass, "%02x\n")
|
||||
usb_intf_attr(bInterfaceSubClass, "%02x\n")
|
||||
usb_intf_attr(bInterfaceProtocol, "%02x\n")
|
||||
usb_intf_attr(bInterfaceNumber, "%02x\n");
|
||||
usb_intf_attr(bAlternateSetting, "%2d\n");
|
||||
usb_intf_attr(bNumEndpoints, "%02x\n");
|
||||
usb_intf_attr(bInterfaceClass, "%02x\n");
|
||||
usb_intf_attr(bInterfaceSubClass, "%02x\n");
|
||||
usb_intf_attr(bInterfaceProtocol, "%02x\n");
|
||||
|
||||
static ssize_t show_interface_string(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t interface_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_interface *intf;
|
||||
char *string;
|
||||
|
@ -903,10 +877,10 @@ static ssize_t show_interface_string(struct device *dev,
|
|||
return 0;
|
||||
return sprintf(buf, "%s\n", string);
|
||||
}
|
||||
static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL);
|
||||
static DEVICE_ATTR_RO(interface);
|
||||
|
||||
static ssize_t show_modalias(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_interface *intf;
|
||||
struct usb_device *udev;
|
||||
|
@ -929,10 +903,11 @@ static ssize_t show_modalias(struct device *dev,
|
|||
alt->desc.bInterfaceProtocol,
|
||||
alt->desc.bInterfaceNumber);
|
||||
}
|
||||
static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
|
||||
static DEVICE_ATTR_RO(modalias);
|
||||
|
||||
static ssize_t show_supports_autosuspend(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t supports_autosuspend_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_interface *intf;
|
||||
struct usb_device *udev;
|
||||
|
@ -952,7 +927,7 @@ static ssize_t show_supports_autosuspend(struct device *dev,
|
|||
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR(supports_autosuspend, S_IRUGO, show_supports_autosuspend, NULL);
|
||||
static DEVICE_ATTR_RO(supports_autosuspend);
|
||||
|
||||
static struct attribute *intf_attrs[] = {
|
||||
&dev_attr_bInterfaceNumber.attr,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/usb.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/usb/hcd.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
#define to_urb(d) container_of(d, struct urb, kref)
|
||||
|
||||
|
@ -54,12 +55,12 @@ EXPORT_SYMBOL_GPL(usb_init_urb);
|
|||
* Creates an urb for the USB driver to use, initializes a few internal
|
||||
* structures, incrementes the usage counter, and returns a pointer to it.
|
||||
*
|
||||
* If no memory is available, NULL is returned.
|
||||
*
|
||||
* If the driver want to use this urb for interrupt, control, or bulk
|
||||
* endpoints, pass '0' as the number of iso packets.
|
||||
*
|
||||
* The driver must call usb_free_urb() when it is finished with the urb.
|
||||
*
|
||||
* Return: A pointer to the new urb, or %NULL if no memory is available.
|
||||
*/
|
||||
struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
|
||||
{
|
||||
|
@ -102,7 +103,7 @@ EXPORT_SYMBOL_GPL(usb_free_urb);
|
|||
* host controller driver. This allows proper reference counting to happen
|
||||
* for urbs.
|
||||
*
|
||||
* A pointer to the urb with the incremented reference counter is returned.
|
||||
* Return: A pointer to the urb with the incremented reference counter.
|
||||
*/
|
||||
struct urb *usb_get_urb(struct urb *urb)
|
||||
{
|
||||
|
@ -199,13 +200,12 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
|
|||
* the particular kind of transfer, although they will not initialize
|
||||
* any transfer flags.
|
||||
*
|
||||
* Successful submissions return 0; otherwise this routine returns a
|
||||
* negative error number. If the submission is successful, the complete()
|
||||
* callback from the URB will be called exactly once, when the USB core and
|
||||
* Host Controller Driver (HCD) are finished with the URB. When the completion
|
||||
* function is called, control of the URB is returned to the device
|
||||
* driver which issued the request. The completion handler may then
|
||||
* immediately free or reuse that URB.
|
||||
* If the submission is successful, the complete() callback from the URB
|
||||
* will be called exactly once, when the USB core and Host Controller Driver
|
||||
* (HCD) are finished with the URB. When the completion function is called,
|
||||
* control of the URB is returned to the device driver which issued the
|
||||
* request. The completion handler may then immediately free or reuse that
|
||||
* URB.
|
||||
*
|
||||
* With few exceptions, USB device drivers should never access URB fields
|
||||
* provided by usbcore or the HCD until its complete() is called.
|
||||
|
@ -240,6 +240,9 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
|
|||
* that are standardized in the USB 2.0 specification. For bulk
|
||||
* endpoints, a synchronous usb_bulk_msg() call is available.
|
||||
*
|
||||
* Return:
|
||||
* 0 on successful submissions. A negative error number otherwise.
|
||||
*
|
||||
* Request Queuing:
|
||||
*
|
||||
* URBs may be submitted to endpoints before previous ones complete, to
|
||||
|
@ -413,6 +416,14 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
|||
urb->iso_frame_desc[n].status = -EXDEV;
|
||||
urb->iso_frame_desc[n].actual_length = 0;
|
||||
}
|
||||
} else if (urb->num_sgs && !urb->dev->bus->no_sg_constraint &&
|
||||
dev->speed != USB_SPEED_WIRELESS) {
|
||||
struct scatterlist *sg;
|
||||
int i;
|
||||
|
||||
for_each_sg(urb->sg, sg, urb->num_sgs - 1, i)
|
||||
if (sg->length % max)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* the I/O buffer must be mapped/unmapped, except when length=0 */
|
||||
|
@ -564,6 +575,9 @@ EXPORT_SYMBOL_GPL(usb_submit_urb);
|
|||
* particular, when a driver calls this routine, it must insure that the
|
||||
* completion handler cannot deallocate the URB.
|
||||
*
|
||||
* Return: -EINPROGRESS on success. See description for other values on
|
||||
* failure.
|
||||
*
|
||||
* Unlinking and Endpoint Queues:
|
||||
*
|
||||
* [The behaviors and guarantees described below do not apply to virtual
|
||||
|
@ -838,6 +852,8 @@ EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
|
|||
*
|
||||
* Call this is you want to be sure all an anchor's
|
||||
* URBs have finished
|
||||
*
|
||||
* Return: Non-zero if the anchor became unused. Zero on timeout.
|
||||
*/
|
||||
int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
|
||||
unsigned int timeout)
|
||||
|
@ -851,8 +867,11 @@ EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout);
|
|||
* usb_get_from_anchor - get an anchor's oldest urb
|
||||
* @anchor: the anchor whose urb you want
|
||||
*
|
||||
* this will take the oldest urb from an anchor,
|
||||
* This will take the oldest urb from an anchor,
|
||||
* unanchor and return it
|
||||
*
|
||||
* Return: The oldest urb from @anchor, or %NULL if @anchor has no
|
||||
* urbs associated with it.
|
||||
*/
|
||||
struct urb *usb_get_from_anchor(struct usb_anchor *anchor)
|
||||
{
|
||||
|
@ -901,7 +920,7 @@ EXPORT_SYMBOL_GPL(usb_scuttle_anchored_urbs);
|
|||
* usb_anchor_empty - is an anchor empty
|
||||
* @anchor: the anchor you want to query
|
||||
*
|
||||
* returns 1 if the anchor has no urbs associated with it
|
||||
* Return: 1 if the anchor has no urbs associated with it.
|
||||
*/
|
||||
int usb_anchor_empty(struct usb_anchor *anchor)
|
||||
{
|
||||
|
|
|
@ -68,6 +68,8 @@ MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
|
|||
* @alt_num: alternate interface setting number to search for.
|
||||
*
|
||||
* Search the configuration's interface cache for the given alt setting.
|
||||
*
|
||||
* Return: The alternate setting, if found. %NULL otherwise.
|
||||
*/
|
||||
struct usb_host_interface *usb_find_alt_setting(
|
||||
struct usb_host_config *config,
|
||||
|
@ -103,8 +105,7 @@ EXPORT_SYMBOL_GPL(usb_find_alt_setting);
|
|||
* @ifnum: the desired interface
|
||||
*
|
||||
* This walks the device descriptor for the currently active configuration
|
||||
* and returns a pointer to the interface with that particular interface
|
||||
* number, or null.
|
||||
* to find the interface object with the particular interface number.
|
||||
*
|
||||
* Note that configuration descriptors are not required to assign interface
|
||||
* numbers sequentially, so that it would be incorrect to assume that
|
||||
|
@ -115,6 +116,9 @@ EXPORT_SYMBOL_GPL(usb_find_alt_setting);
|
|||
*
|
||||
* Don't call this function unless you are bound to one of the interfaces
|
||||
* on this device or you have locked the device!
|
||||
*
|
||||
* Return: A pointer to the interface that has @ifnum as interface number,
|
||||
* if found. %NULL otherwise.
|
||||
*/
|
||||
struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,
|
||||
unsigned ifnum)
|
||||
|
@ -139,8 +143,7 @@ EXPORT_SYMBOL_GPL(usb_ifnum_to_if);
|
|||
* @altnum: the desired alternate setting number
|
||||
*
|
||||
* This searches the altsetting array of the specified interface for
|
||||
* an entry with the correct bAlternateSetting value and returns a pointer
|
||||
* to that entry, or null.
|
||||
* an entry with the correct bAlternateSetting value.
|
||||
*
|
||||
* Note that altsettings need not be stored sequentially by number, so
|
||||
* it would be incorrect to assume that the first altsetting entry in
|
||||
|
@ -149,6 +152,9 @@ EXPORT_SYMBOL_GPL(usb_ifnum_to_if);
|
|||
*
|
||||
* Don't call this function unless you are bound to the intf interface
|
||||
* or you have locked the device!
|
||||
*
|
||||
* Return: A pointer to the entry of the altsetting array of @intf that
|
||||
* has @altnum as the alternate setting number. %NULL if not found.
|
||||
*/
|
||||
struct usb_host_interface *usb_altnum_to_altsetting(
|
||||
const struct usb_interface *intf,
|
||||
|
@ -191,6 +197,8 @@ static int __find_interface(struct device *dev, void *data)
|
|||
* This walks the bus device list and returns a pointer to the interface
|
||||
* with the matching minor and driver. Note, this only works for devices
|
||||
* that share the USB major number.
|
||||
*
|
||||
* Return: A pointer to the interface with the matching major and @minor.
|
||||
*/
|
||||
struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
|
||||
{
|
||||
|
@ -390,6 +398,9 @@ static unsigned usb_bus_is_wusb(struct usb_bus *bus)
|
|||
* controllers) should ever call this.
|
||||
*
|
||||
* This call may not be used in a non-sleeping context.
|
||||
*
|
||||
* Return: On success, a pointer to the allocated usb device. %NULL on
|
||||
* failure.
|
||||
*/
|
||||
struct usb_device *usb_alloc_dev(struct usb_device *parent,
|
||||
struct usb_bus *bus, unsigned port1)
|
||||
|
@ -501,7 +512,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
|
|||
* their probe() methods, when they bind to an interface, and release
|
||||
* them by calling usb_put_dev(), in their disconnect() methods.
|
||||
*
|
||||
* A pointer to the device with the incremented reference counter is returned.
|
||||
* Return: A pointer to the device with the incremented reference counter.
|
||||
*/
|
||||
struct usb_device *usb_get_dev(struct usb_device *dev)
|
||||
{
|
||||
|
@ -535,8 +546,7 @@ EXPORT_SYMBOL_GPL(usb_put_dev);
|
|||
* their probe() methods, when they bind to an interface, and release
|
||||
* them by calling usb_put_intf(), in their disconnect() methods.
|
||||
*
|
||||
* A pointer to the interface with the incremented reference counter is
|
||||
* returned.
|
||||
* Return: A pointer to the interface with the incremented reference counter.
|
||||
*/
|
||||
struct usb_interface *usb_get_intf(struct usb_interface *intf)
|
||||
{
|
||||
|
@ -589,7 +599,7 @@ EXPORT_SYMBOL_GPL(usb_put_intf);
|
|||
* disconnect; in some drivers (such as usb-storage) the disconnect()
|
||||
* or suspend() method will block waiting for a device reset to complete.
|
||||
*
|
||||
* Returns a negative error code for failure, otherwise 0.
|
||||
* Return: A negative error code for failure, otherwise 0.
|
||||
*/
|
||||
int usb_lock_device_for_reset(struct usb_device *udev,
|
||||
const struct usb_interface *iface)
|
||||
|
@ -628,14 +638,15 @@ EXPORT_SYMBOL_GPL(usb_lock_device_for_reset);
|
|||
* usb_get_current_frame_number - return current bus frame number
|
||||
* @dev: the device whose bus is being queried
|
||||
*
|
||||
* Returns the current frame number for the USB host controller
|
||||
* used with the given USB device. This can be used when scheduling
|
||||
* Return: The current frame number for the USB host controller used
|
||||
* with the given USB device. This can be used when scheduling
|
||||
* isochronous requests.
|
||||
*
|
||||
* Note that different kinds of host controller have different
|
||||
* "scheduling horizons". While one type might support scheduling only
|
||||
* 32 frames into the future, others could support scheduling up to
|
||||
* 1024 frames into the future.
|
||||
* Note: Different kinds of host controller have different "scheduling
|
||||
* horizons". While one type might support scheduling only 32 frames
|
||||
* into the future, others could support scheduling up to 1024 frames
|
||||
* into the future.
|
||||
*
|
||||
*/
|
||||
int usb_get_current_frame_number(struct usb_device *dev)
|
||||
{
|
||||
|
@ -685,11 +696,12 @@ EXPORT_SYMBOL_GPL(__usb_get_extra_descriptor);
|
|||
* @mem_flags: affect whether allocation may block
|
||||
* @dma: used to return DMA address of buffer
|
||||
*
|
||||
* Return value is either null (indicating no buffer could be allocated), or
|
||||
* the cpu-space pointer to a buffer that may be used to perform DMA to the
|
||||
* Return: Either null (indicating no buffer could be allocated), or the
|
||||
* cpu-space pointer to a buffer that may be used to perform DMA to the
|
||||
* specified device. Such cpu-space buffers are returned along with the DMA
|
||||
* address (through the pointer provided).
|
||||
*
|
||||
* Note:
|
||||
* These buffers are used with URB_NO_xxx_DMA_MAP set in urb->transfer_flags
|
||||
* to avoid behaviors like using "DMA bounce buffers", or thrashing IOMMU
|
||||
* hardware during URB completion/resubmit. The implementation varies between
|
||||
|
@ -735,17 +747,18 @@ EXPORT_SYMBOL_GPL(usb_free_coherent);
|
|||
* usb_buffer_map - create DMA mapping(s) for an urb
|
||||
* @urb: urb whose transfer_buffer/setup_packet will be mapped
|
||||
*
|
||||
* Return value is either null (indicating no buffer could be mapped), or
|
||||
* the parameter. URB_NO_TRANSFER_DMA_MAP is
|
||||
* added to urb->transfer_flags if the operation succeeds. If the device
|
||||
* is connected to this system through a non-DMA controller, this operation
|
||||
* always succeeds.
|
||||
* URB_NO_TRANSFER_DMA_MAP is added to urb->transfer_flags if the operation
|
||||
* succeeds. If the device is connected to this system through a non-DMA
|
||||
* controller, this operation always succeeds.
|
||||
*
|
||||
* This call would normally be used for an urb which is reused, perhaps
|
||||
* as the target of a large periodic transfer, with usb_buffer_dmasync()
|
||||
* calls to synchronize memory and dma state.
|
||||
*
|
||||
* Reverse the effect of this call with usb_buffer_unmap().
|
||||
*
|
||||
* Return: Either %NULL (indicating no buffer could be mapped), or @urb.
|
||||
*
|
||||
*/
|
||||
#if 0
|
||||
struct urb *usb_buffer_map(struct urb *urb)
|
||||
|
@ -850,9 +863,10 @@ EXPORT_SYMBOL_GPL(usb_buffer_unmap);
|
|||
* @sg: the scatterlist to map
|
||||
* @nents: the number of entries in the scatterlist
|
||||
*
|
||||
* Return value is either < 0 (indicating no buffers could be mapped), or
|
||||
* the number of DMA mapping array entries in the scatterlist.
|
||||
* Return: Either < 0 (indicating no buffers could be mapped), or the
|
||||
* number of DMA mapping array entries in the scatterlist.
|
||||
*
|
||||
* Note:
|
||||
* The caller is responsible for placing the resulting DMA addresses from
|
||||
* the scatterlist into URB transfer buffer pointers, and for setting the
|
||||
* URB_NO_TRANSFER_DMA_MAP transfer flag in each of those URBs.
|
||||
|
|
|
@ -40,6 +40,38 @@ config USB_DWC3_DUAL_ROLE
|
|||
|
||||
endchoice
|
||||
|
||||
comment "Platform Glue Driver Support"
|
||||
|
||||
config USB_DWC3_OMAP
|
||||
tristate "Texas Instruments OMAP5 and similar Platforms"
|
||||
depends on EXTCON
|
||||
default USB_DWC3
|
||||
help
|
||||
Some platforms from Texas Instruments like OMAP5, DRA7xxx and
|
||||
AM437x use this IP for USB2/3 functionality.
|
||||
|
||||
Say 'Y' or 'M' here if you have one such device
|
||||
|
||||
config USB_DWC3_EXYNOS
|
||||
tristate "Samsung Exynos Platform"
|
||||
default USB_DWC3
|
||||
help
|
||||
Recent Exynos5 SoCs ship with one DesignWare Core USB3 IP inside,
|
||||
say 'Y' or 'M' if you have one such device.
|
||||
|
||||
config USB_DWC3_PCI
|
||||
tristate "PCIe-based Platforms"
|
||||
depends on PCI
|
||||
default USB_DWC3
|
||||
help
|
||||
If you're using the DesignWare Core IP with a PCIe, please say
|
||||
'Y' or 'M' here.
|
||||
|
||||
One such PCIe-based platform is Synopsys' PCIe HAPS model of
|
||||
this IP.
|
||||
|
||||
comment "Debugging features"
|
||||
|
||||
config USB_DWC3_DEBUG
|
||||
bool "Enable Debugging Messages"
|
||||
help
|
||||
|
|
|
@ -27,15 +27,8 @@ endif
|
|||
# the entire driver (with all its glue layers) on several architectures
|
||||
# and make sure it compiles fine. This will also help with allmodconfig
|
||||
# and allyesconfig builds.
|
||||
#
|
||||
# The only exception is the PCI glue layer, but that's only because
|
||||
# PCI doesn't provide nops if CONFIG_PCI isn't enabled.
|
||||
##
|
||||
|
||||
obj-$(CONFIG_USB_DWC3) += dwc3-omap.o
|
||||
obj-$(CONFIG_USB_DWC3) += dwc3-exynos.o
|
||||
|
||||
ifneq ($(CONFIG_PCI),)
|
||||
obj-$(CONFIG_USB_DWC3) += dwc3-pci.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o
|
||||
obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o
|
||||
obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o
|
||||
|
|
|
@ -6,34 +6,17 @@
|
|||
* Authors: Felipe Balbi <balbi@ti.com>,
|
||||
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 of
|
||||
* the License as published by the Free Software Foundation.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -50,20 +33,18 @@
|
|||
#include <linux/dma-mapping.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include <linux/usb/of.h>
|
||||
#include <linux/usb/otg.h>
|
||||
|
||||
#include "platform_data.h"
|
||||
#include "core.h"
|
||||
#include "gadget.h"
|
||||
#include "io.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
static char *maximum_speed = "super";
|
||||
module_param(maximum_speed, charp, 0);
|
||||
MODULE_PARM_DESC(maximum_speed, "Maximum supported speed.");
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
|
||||
|
@ -236,7 +217,7 @@ static int dwc3_event_buffers_setup(struct dwc3 *dwc)
|
|||
dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
|
||||
upper_32_bits(evt->dma));
|
||||
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
|
||||
evt->length & 0xffff);
|
||||
DWC3_GEVNTSIZ_SIZE(evt->length));
|
||||
dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
|
||||
}
|
||||
|
||||
|
@ -255,7 +236,8 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
|
|||
|
||||
dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
|
||||
dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
|
||||
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0);
|
||||
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK
|
||||
| DWC3_GEVNTSIZ_SIZE(0));
|
||||
dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
|
||||
}
|
||||
}
|
||||
|
@ -367,18 +349,17 @@ static void dwc3_core_exit(struct dwc3 *dwc)
|
|||
|
||||
static int dwc3_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dwc3_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct device_node *node = dev->of_node;
|
||||
struct resource *res;
|
||||
struct dwc3 *dwc;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
int ret = -ENOMEM;
|
||||
|
||||
void __iomem *regs;
|
||||
void *mem;
|
||||
|
||||
u8 mode;
|
||||
|
||||
mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
|
||||
if (!mem) {
|
||||
dev_err(dev, "not enough memory\n");
|
||||
|
@ -402,38 +383,32 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||
dev_err(dev, "missing memory resource\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
dwc->xhci_resources[0].start = res->start;
|
||||
dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
|
||||
DWC3_XHCI_REGS_END;
|
||||
dwc->xhci_resources[0].flags = res->flags;
|
||||
dwc->xhci_resources[0].name = res->name;
|
||||
|
||||
/*
|
||||
* Request memory region but exclude xHCI regs,
|
||||
* since it will be requested by the xhci-plat driver.
|
||||
*/
|
||||
res = devm_request_mem_region(dev, res->start + DWC3_GLOBALS_REGS_START,
|
||||
resource_size(res) - DWC3_GLOBALS_REGS_START,
|
||||
dev_name(dev));
|
||||
if (!res) {
|
||||
dev_err(dev, "can't request mem region\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
|
||||
if (!regs) {
|
||||
dev_err(dev, "ioremap failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
dwc->maximum_speed = of_usb_get_maximum_speed(node);
|
||||
|
||||
dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
|
||||
dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
|
||||
|
||||
dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
|
||||
dwc->dr_mode = of_usb_get_dr_mode(node);
|
||||
} else if (pdata) {
|
||||
dwc->maximum_speed = pdata->maximum_speed;
|
||||
|
||||
dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
|
||||
dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
|
||||
|
||||
dwc->needs_fifo_resize = pdata->tx_fifo_resize;
|
||||
dwc->dr_mode = pdata->dr_mode;
|
||||
} else {
|
||||
dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
|
||||
dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
|
||||
}
|
||||
|
||||
/* default to superspeed if no maximum_speed passed */
|
||||
if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
|
||||
dwc->maximum_speed = USB_SPEED_SUPER;
|
||||
|
||||
if (IS_ERR(dwc->usb2_phy)) {
|
||||
ret = PTR_ERR(dwc->usb2_phy);
|
||||
|
||||
|
@ -464,6 +439,22 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
dwc->xhci_resources[0].start = res->start;
|
||||
dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
|
||||
DWC3_XHCI_REGS_END;
|
||||
dwc->xhci_resources[0].flags = res->flags;
|
||||
dwc->xhci_resources[0].name = res->name;
|
||||
|
||||
res->start += DWC3_GLOBALS_REGS_START;
|
||||
|
||||
/*
|
||||
* Request memory region but exclude xHCI regs,
|
||||
* since it will be requested by the xhci-plat driver.
|
||||
*/
|
||||
regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
|
||||
usb_phy_set_suspend(dwc->usb2_phy, 0);
|
||||
usb_phy_set_suspend(dwc->usb3_phy, 0);
|
||||
|
||||
|
@ -478,19 +469,6 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||
dev->dma_parms = dev->parent->dma_parms;
|
||||
dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
|
||||
|
||||
if (!strncmp("super", maximum_speed, 5))
|
||||
dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
|
||||
else if (!strncmp("high", maximum_speed, 4))
|
||||
dwc->maximum_speed = DWC3_DCFG_HIGHSPEED;
|
||||
else if (!strncmp("full", maximum_speed, 4))
|
||||
dwc->maximum_speed = DWC3_DCFG_FULLSPEED1;
|
||||
else if (!strncmp("low", maximum_speed, 3))
|
||||
dwc->maximum_speed = DWC3_DCFG_LOWSPEED;
|
||||
else
|
||||
dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
|
||||
|
||||
dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
pm_runtime_forbid(dev);
|
||||
|
@ -517,14 +495,15 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
|
||||
mode = DWC3_MODE_HOST;
|
||||
dwc->dr_mode = USB_DR_MODE_HOST;
|
||||
else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
|
||||
mode = DWC3_MODE_DEVICE;
|
||||
else
|
||||
mode = DWC3_MODE_DRD;
|
||||
dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
|
||||
|
||||
switch (mode) {
|
||||
case DWC3_MODE_DEVICE:
|
||||
if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
|
||||
dwc->dr_mode = USB_DR_MODE_OTG;
|
||||
|
||||
switch (dwc->dr_mode) {
|
||||
case USB_DR_MODE_PERIPHERAL:
|
||||
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
|
||||
ret = dwc3_gadget_init(dwc);
|
||||
if (ret) {
|
||||
|
@ -532,7 +511,7 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||
goto err2;
|
||||
}
|
||||
break;
|
||||
case DWC3_MODE_HOST:
|
||||
case USB_DR_MODE_HOST:
|
||||
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
|
||||
ret = dwc3_host_init(dwc);
|
||||
if (ret) {
|
||||
|
@ -540,7 +519,7 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||
goto err2;
|
||||
}
|
||||
break;
|
||||
case DWC3_MODE_DRD:
|
||||
case USB_DR_MODE_OTG:
|
||||
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
|
||||
ret = dwc3_host_init(dwc);
|
||||
if (ret) {
|
||||
|
@ -555,10 +534,9 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Unsupported mode of operation %d\n", mode);
|
||||
dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
|
||||
goto err2;
|
||||
}
|
||||
dwc->mode = mode;
|
||||
|
||||
ret = dwc3_debugfs_init(dwc);
|
||||
if (ret) {
|
||||
|
@ -571,14 +549,14 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
err3:
|
||||
switch (mode) {
|
||||
case DWC3_MODE_DEVICE:
|
||||
switch (dwc->dr_mode) {
|
||||
case USB_DR_MODE_PERIPHERAL:
|
||||
dwc3_gadget_exit(dwc);
|
||||
break;
|
||||
case DWC3_MODE_HOST:
|
||||
case USB_DR_MODE_HOST:
|
||||
dwc3_host_exit(dwc);
|
||||
break;
|
||||
case DWC3_MODE_DRD:
|
||||
case USB_DR_MODE_OTG:
|
||||
dwc3_host_exit(dwc);
|
||||
dwc3_gadget_exit(dwc);
|
||||
break;
|
||||
|
@ -611,14 +589,14 @@ static int dwc3_remove(struct platform_device *pdev)
|
|||
|
||||
dwc3_debugfs_exit(dwc);
|
||||
|
||||
switch (dwc->mode) {
|
||||
case DWC3_MODE_DEVICE:
|
||||
switch (dwc->dr_mode) {
|
||||
case USB_DR_MODE_PERIPHERAL:
|
||||
dwc3_gadget_exit(dwc);
|
||||
break;
|
||||
case DWC3_MODE_HOST:
|
||||
case USB_DR_MODE_HOST:
|
||||
dwc3_host_exit(dwc);
|
||||
break;
|
||||
case DWC3_MODE_DRD:
|
||||
case USB_DR_MODE_OTG:
|
||||
dwc3_host_exit(dwc);
|
||||
dwc3_gadget_exit(dwc);
|
||||
break;
|
||||
|
@ -642,12 +620,12 @@ static int dwc3_prepare(struct device *dev)
|
|||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
|
||||
switch (dwc->mode) {
|
||||
case DWC3_MODE_DEVICE:
|
||||
case DWC3_MODE_DRD:
|
||||
switch (dwc->dr_mode) {
|
||||
case USB_DR_MODE_PERIPHERAL:
|
||||
case USB_DR_MODE_OTG:
|
||||
dwc3_gadget_prepare(dwc);
|
||||
/* FALLTHROUGH */
|
||||
case DWC3_MODE_HOST:
|
||||
case USB_DR_MODE_HOST:
|
||||
default:
|
||||
dwc3_event_buffers_cleanup(dwc);
|
||||
break;
|
||||
|
@ -665,12 +643,12 @@ static void dwc3_complete(struct device *dev)
|
|||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
|
||||
switch (dwc->mode) {
|
||||
case DWC3_MODE_DEVICE:
|
||||
case DWC3_MODE_DRD:
|
||||
switch (dwc->dr_mode) {
|
||||
case USB_DR_MODE_PERIPHERAL:
|
||||
case USB_DR_MODE_OTG:
|
||||
dwc3_gadget_complete(dwc);
|
||||
/* FALLTHROUGH */
|
||||
case DWC3_MODE_HOST:
|
||||
case USB_DR_MODE_HOST:
|
||||
default:
|
||||
dwc3_event_buffers_setup(dwc);
|
||||
break;
|
||||
|
@ -686,12 +664,12 @@ static int dwc3_suspend(struct device *dev)
|
|||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
|
||||
switch (dwc->mode) {
|
||||
case DWC3_MODE_DEVICE:
|
||||
case DWC3_MODE_DRD:
|
||||
switch (dwc->dr_mode) {
|
||||
case USB_DR_MODE_PERIPHERAL:
|
||||
case USB_DR_MODE_OTG:
|
||||
dwc3_gadget_suspend(dwc);
|
||||
/* FALLTHROUGH */
|
||||
case DWC3_MODE_HOST:
|
||||
case USB_DR_MODE_HOST:
|
||||
default:
|
||||
/* do nothing */
|
||||
break;
|
||||
|
@ -719,12 +697,12 @@ static int dwc3_resume(struct device *dev)
|
|||
|
||||
dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl);
|
||||
|
||||
switch (dwc->mode) {
|
||||
case DWC3_MODE_DEVICE:
|
||||
case DWC3_MODE_DRD:
|
||||
switch (dwc->dr_mode) {
|
||||
case USB_DR_MODE_PERIPHERAL:
|
||||
case USB_DR_MODE_OTG:
|
||||
dwc3_gadget_resume(dwc);
|
||||
/* FALLTHROUGH */
|
||||
case DWC3_MODE_HOST:
|
||||
case USB_DR_MODE_HOST:
|
||||
default:
|
||||
/* do nothing */
|
||||
break;
|
||||
|
@ -753,6 +731,9 @@ static const struct dev_pm_ops dwc3_dev_pm_ops = {
|
|||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id of_dwc3_match[] = {
|
||||
{
|
||||
.compatible = "snps,dwc3"
|
||||
},
|
||||
{
|
||||
.compatible = "synopsys,dwc3"
|
||||
},
|
||||
|
@ -775,5 +756,5 @@ module_platform_driver(dwc3_driver);
|
|||
|
||||
MODULE_ALIAS("platform:dwc3");
|
||||
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
|
||||
|
|
|
@ -6,34 +6,14 @@
|
|||
* Authors: Felipe Balbi <balbi@ti.com>,
|
||||
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 of
|
||||
* the License as published by the Free Software Foundation.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_USB_DWC3_CORE_H
|
||||
|
@ -49,6 +29,7 @@
|
|||
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include <linux/usb/otg.h>
|
||||
|
||||
/* Global constants */
|
||||
#define DWC3_EP0_BOUNCE_SIZE 512
|
||||
|
@ -194,6 +175,10 @@
|
|||
#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff)
|
||||
#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000)
|
||||
|
||||
/* Global Event Size Registers */
|
||||
#define DWC3_GEVNTSIZ_INTMASK (1 << 31)
|
||||
#define DWC3_GEVNTSIZ_SIZE(n) ((n) & 0xffff)
|
||||
|
||||
/* Global HWPARAMS1 Register */
|
||||
#define DWC3_GHWPARAMS1_EN_PWROPT(n) (((n) & (3 << 24)) >> 24)
|
||||
#define DWC3_GHWPARAMS1_EN_PWROPT_NO 0
|
||||
|
@ -207,7 +192,6 @@
|
|||
#define DWC3_MAX_HIBER_SCRATCHBUFS 15
|
||||
|
||||
/* Device Configuration Register */
|
||||
#define DWC3_DCFG_LPM_CAP (1 << 22)
|
||||
#define DWC3_DCFG_DEVADDR(addr) ((addr) << 3)
|
||||
#define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f)
|
||||
|
||||
|
@ -367,7 +351,6 @@ struct dwc3_trb;
|
|||
|
||||
/**
|
||||
* struct dwc3_event_buffer - Software event buffer representation
|
||||
* @list: a list of event buffers
|
||||
* @buf: _THE_ buffer
|
||||
* @length: size of this buffer
|
||||
* @lpos: event offset
|
||||
|
@ -415,7 +398,7 @@ struct dwc3_event_buffer {
|
|||
* @number: endpoint number (1 - 15)
|
||||
* @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
|
||||
* @resource_index: Resource transfer index
|
||||
* @interval: the intervall on which the ISOC transfer is started
|
||||
* @interval: the interval on which the ISOC transfer is started
|
||||
* @name: a human readable name e.g. ep1out-bulk
|
||||
* @direction: true for TX, false for RX
|
||||
* @stream_capable: true when streams are enabled
|
||||
|
@ -566,11 +549,6 @@ struct dwc3_hwparams {
|
|||
/* HWPARAMS0 */
|
||||
#define DWC3_MODE(n) ((n) & 0x7)
|
||||
|
||||
#define DWC3_MODE_DEVICE 0
|
||||
#define DWC3_MODE_HOST 1
|
||||
#define DWC3_MODE_DRD 2
|
||||
#define DWC3_MODE_HUB 3
|
||||
|
||||
#define DWC3_MDWIDTH(n) (((n) & 0xff00) >> 8)
|
||||
|
||||
/* HWPARAMS1 */
|
||||
|
@ -632,7 +610,7 @@ struct dwc3_scratchpad_array {
|
|||
* @u1u2: only used on revisions <1.83a for workaround
|
||||
* @maximum_speed: maximum speed requested (mainly for testing purposes)
|
||||
* @revision: revision register contents
|
||||
* @mode: mode of operation
|
||||
* @dr_mode: requested mode of operation
|
||||
* @usb2_phy: pointer to USB2 PHY
|
||||
* @usb3_phy: pointer to USB3 PHY
|
||||
* @dcfg: saved contents of DCFG register
|
||||
|
@ -690,6 +668,8 @@ struct dwc3 {
|
|||
void __iomem *regs;
|
||||
size_t regs_size;
|
||||
|
||||
enum usb_dr_mode dr_mode;
|
||||
|
||||
/* used for suspend/resume */
|
||||
u32 dcfg;
|
||||
u32 gctl;
|
||||
|
@ -698,7 +678,6 @@ struct dwc3 {
|
|||
u32 u1u2;
|
||||
u32 maximum_speed;
|
||||
u32 revision;
|
||||
u32 mode;
|
||||
|
||||
#define DWC3_REVISION_173A 0x5533173a
|
||||
#define DWC3_REVISION_175A 0x5533175a
|
||||
|
|
|
@ -6,34 +6,14 @@
|
|||
* Authors: Felipe Balbi <balbi@ti.com>,
|
||||
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 of
|
||||
* the License as published by the Free Software Foundation.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
|
|
|
@ -6,34 +6,14 @@
|
|||
* Authors: Felipe Balbi <balbi@ti.com>,
|
||||
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 of
|
||||
* the License as published by the Free Software Foundation.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -6,10 +6,14 @@
|
|||
*
|
||||
* Author: Anton Tikhomirov <av.tikhomirov@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 of
|
||||
* the License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -20,7 +24,7 @@
|
|||
#include <linux/dma-mapping.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/nop-usb-xceiv.h>
|
||||
#include <linux/usb/usb_phy_gen_xceiv.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
|
@ -34,13 +38,13 @@ struct dwc3_exynos {
|
|||
|
||||
static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
|
||||
{
|
||||
struct nop_usb_xceiv_platform_data pdata;
|
||||
struct usb_phy_gen_xceiv_platform_data pdata;
|
||||
struct platform_device *pdev;
|
||||
int ret;
|
||||
|
||||
memset(&pdata, 0x00, sizeof(pdata));
|
||||
|
||||
pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
|
||||
pdev = platform_device_alloc("usb_phy_gen_xceiv", PLATFORM_DEVID_AUTO);
|
||||
if (!pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -51,7 +55,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
|
|||
if (ret)
|
||||
goto err1;
|
||||
|
||||
pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
|
||||
pdev = platform_device_alloc("usb_phy_gen_xceiv", PLATFORM_DEVID_AUTO);
|
||||
if (!pdev) {
|
||||
ret = -ENOMEM;
|
||||
goto err1;
|
||||
|
@ -228,5 +232,5 @@ module_platform_driver(dwc3_exynos_driver);
|
|||
|
||||
MODULE_ALIAS("platform:exynos-dwc3");
|
||||
MODULE_AUTHOR("Anton Tikhomirov <av.tikhomirov@samsung.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("DesignWare USB3 EXYNOS Glue Layer");
|
||||
|
|
|
@ -6,34 +6,14 @@
|
|||
* Authors: Felipe Balbi <balbi@ti.com>,
|
||||
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 of
|
||||
* the License as published by the Free Software Foundation.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -409,11 +389,9 @@ static int dwc3_omap_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
base = devm_ioremap_nocache(dev, res->start, resource_size(res));
|
||||
if (!base) {
|
||||
dev_err(dev, "ioremap failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
spin_lock_init(&omap->lock);
|
||||
|
||||
|
@ -610,5 +588,5 @@ module_platform_driver(dwc3_omap_driver);
|
|||
|
||||
MODULE_ALIAS("platform:omap-dwc3");
|
||||
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("DesignWare USB3 OMAP Glue Layer");
|
||||
|
|
|
@ -6,34 +6,14 @@
|
|||
* Authors: Felipe Balbi <balbi@ti.com>,
|
||||
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 of
|
||||
* the License as published by the Free Software Foundation.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -43,7 +23,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/nop-usb-xceiv.h>
|
||||
#include <linux/usb/usb_phy_gen_xceiv.h>
|
||||
|
||||
/* FIXME define these in <linux/pci_ids.h> */
|
||||
#define PCI_VENDOR_ID_SYNOPSYS 0x16c3
|
||||
|
@ -58,13 +38,13 @@ struct dwc3_pci {
|
|||
|
||||
static int dwc3_pci_register_phys(struct dwc3_pci *glue)
|
||||
{
|
||||
struct nop_usb_xceiv_platform_data pdata;
|
||||
struct usb_phy_gen_xceiv_platform_data pdata;
|
||||
struct platform_device *pdev;
|
||||
int ret;
|
||||
|
||||
memset(&pdata, 0x00, sizeof(pdata));
|
||||
|
||||
pdev = platform_device_alloc("nop_usb_xceiv", 0);
|
||||
pdev = platform_device_alloc("usb_phy_gen_xceiv", 0);
|
||||
if (!pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -75,7 +55,7 @@ static int dwc3_pci_register_phys(struct dwc3_pci *glue)
|
|||
if (ret)
|
||||
goto err1;
|
||||
|
||||
pdev = platform_device_alloc("nop_usb_xceiv", 1);
|
||||
pdev = platform_device_alloc("usb_phy_gen_xceiv", 1);
|
||||
if (!pdev) {
|
||||
ret = -ENOMEM;
|
||||
goto err1;
|
||||
|
@ -211,7 +191,7 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int dwc3_pci_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pci = to_pci_dev(dev);
|
||||
|
@ -236,28 +216,24 @@ static int dwc3_pci_resume(struct device *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static const struct dev_pm_ops dwc3_pci_dev_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
|
||||
};
|
||||
|
||||
#define DEV_PM_OPS (&dwc3_pci_dev_pm_ops)
|
||||
#else
|
||||
#define DEV_PM_OPS NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct pci_driver dwc3_pci_driver = {
|
||||
.name = "dwc3-pci",
|
||||
.id_table = dwc3_pci_id_table,
|
||||
.probe = dwc3_pci_probe,
|
||||
.remove = dwc3_pci_remove,
|
||||
.driver = {
|
||||
.pm = DEV_PM_OPS,
|
||||
.pm = &dwc3_pci_dev_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer");
|
||||
|
||||
module_pci_driver(dwc3_pci_driver);
|
||||
|
|
|
@ -6,34 +6,14 @@
|
|||
* Authors: Felipe Balbi <balbi@ti.com>,
|
||||
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 of
|
||||
* the License as published by the Free Software Foundation.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -168,6 +148,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
|
|||
|
||||
direction = !dwc->ep0_expect_in;
|
||||
dwc->delayed_status = false;
|
||||
usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED);
|
||||
|
||||
if (dwc->ep0state == EP0_STATUS_PHASE)
|
||||
__dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
|
||||
|
@ -553,8 +534,16 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
|
|||
ret = dwc3_ep0_delegate_req(dwc, ctrl);
|
||||
/* if the cfg matches and the cfg is non zero */
|
||||
if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
|
||||
usb_gadget_set_state(&dwc->gadget,
|
||||
USB_STATE_CONFIGURED);
|
||||
|
||||
/*
|
||||
* only change state if set_config has already
|
||||
* been processed. If gadget driver returns
|
||||
* USB_GADGET_DELAYED_STATUS, we will wait
|
||||
* to change the state on the next usb_ep_queue()
|
||||
*/
|
||||
if (ret == 0)
|
||||
usb_gadget_set_state(&dwc->gadget,
|
||||
USB_STATE_CONFIGURED);
|
||||
|
||||
/*
|
||||
* Enable transition to U1/U2 state when
|
||||
|
@ -571,7 +560,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
|
|||
|
||||
case USB_STATE_CONFIGURED:
|
||||
ret = dwc3_ep0_delegate_req(dwc, ctrl);
|
||||
if (!cfg)
|
||||
if (!cfg && !ret)
|
||||
usb_gadget_set_state(&dwc->gadget,
|
||||
USB_STATE_ADDRESS);
|
||||
break;
|
||||
|
|
|
@ -6,34 +6,14 @@
|
|||
* Authors: Felipe Balbi <balbi@ti.com>,
|
||||
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 of
|
||||
* the License as published by the Free Software Foundation.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -520,6 +500,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
|
|||
u32 reg;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
dev_vdbg(dwc->dev, "Enabling %s\n", dep->name);
|
||||
|
||||
if (!(dep->flags & DWC3_EP_ENABLED)) {
|
||||
ret = dwc3_gadget_start_config(dwc, dep);
|
||||
if (ret)
|
||||
|
@ -676,8 +658,6 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
|
|||
dev_err(dwc->dev, "invalid endpoint transfer type\n");
|
||||
}
|
||||
|
||||
dev_vdbg(dwc->dev, "Enabling %s\n", dep->name);
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
@ -1508,6 +1488,15 @@ static int dwc3_gadget_start(struct usb_gadget *g,
|
|||
int irq;
|
||||
u32 reg;
|
||||
|
||||
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
|
||||
ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
|
||||
IRQF_SHARED, "dwc3", dwc);
|
||||
if (ret) {
|
||||
dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
|
||||
irq, ret);
|
||||
goto err0;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
|
||||
if (dwc->gadget_driver) {
|
||||
|
@ -1515,7 +1504,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
|
|||
dwc->gadget.name,
|
||||
dwc->gadget_driver->driver.name);
|
||||
ret = -EBUSY;
|
||||
goto err0;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
dwc->gadget_driver = driver;
|
||||
|
@ -1536,10 +1525,25 @@ static int dwc3_gadget_start(struct usb_gadget *g,
|
|||
* STAR#9000525659: Clock Domain Crossing on DCTL in
|
||||
* USB 2.0 Mode
|
||||
*/
|
||||
if (dwc->revision < DWC3_REVISION_220A)
|
||||
if (dwc->revision < DWC3_REVISION_220A) {
|
||||
reg |= DWC3_DCFG_SUPERSPEED;
|
||||
else
|
||||
reg |= dwc->maximum_speed;
|
||||
} else {
|
||||
switch (dwc->maximum_speed) {
|
||||
case USB_SPEED_LOW:
|
||||
reg |= DWC3_DSTS_LOWSPEED;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
reg |= DWC3_DSTS_FULLSPEED1;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
reg |= DWC3_DSTS_HIGHSPEED;
|
||||
break;
|
||||
case USB_SPEED_SUPER: /* FALLTHROUGH */
|
||||
case USB_SPEED_UNKNOWN: /* FALTHROUGH */
|
||||
default:
|
||||
reg |= DWC3_DSTS_SUPERSPEED;
|
||||
}
|
||||
}
|
||||
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
|
||||
|
||||
dwc->start_config_issued = false;
|
||||
|
@ -1551,42 +1555,38 @@ static int dwc3_gadget_start(struct usb_gadget *g,
|
|||
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
|
||||
if (ret) {
|
||||
dev_err(dwc->dev, "failed to enable %s\n", dep->name);
|
||||
goto err0;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
dep = dwc->eps[1];
|
||||
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
|
||||
if (ret) {
|
||||
dev_err(dwc->dev, "failed to enable %s\n", dep->name);
|
||||
goto err1;
|
||||
goto err3;
|
||||
}
|
||||
|
||||
/* begin to receive SETUP packets */
|
||||
dwc->ep0state = EP0_SETUP_PHASE;
|
||||
dwc3_ep0_out_start(dwc);
|
||||
|
||||
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
|
||||
ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
|
||||
IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
|
||||
if (ret) {
|
||||
dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
|
||||
irq, ret);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
dwc3_gadget_enable_irq(dwc);
|
||||
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
||||
err1:
|
||||
err3:
|
||||
__dwc3_gadget_ep_disable(dwc->eps[0]);
|
||||
|
||||
err0:
|
||||
err2:
|
||||
dwc->gadget_driver = NULL;
|
||||
|
||||
err1:
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
free_irq(irq, dwc);
|
||||
|
||||
err0:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1600,9 +1600,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
|
|||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
|
||||
dwc3_gadget_disable_irq(dwc);
|
||||
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
|
||||
free_irq(irq, dwc);
|
||||
|
||||
__dwc3_gadget_ep_disable(dwc->eps[0]);
|
||||
__dwc3_gadget_ep_disable(dwc->eps[1]);
|
||||
|
||||
|
@ -1610,6 +1607,9 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
|
|||
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
|
||||
free_irq(irq, dwc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1642,13 +1642,15 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
|
|||
|
||||
dep->dwc = dwc;
|
||||
dep->number = epnum;
|
||||
dep->direction = !!direction;
|
||||
dwc->eps[epnum] = dep;
|
||||
|
||||
snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
|
||||
(epnum & 1) ? "in" : "out");
|
||||
|
||||
dep->endpoint.name = dep->name;
|
||||
dep->direction = (epnum & 1);
|
||||
|
||||
dev_vdbg(dwc->dev, "initializing %s\n", dep->name);
|
||||
|
||||
if (epnum == 0 || epnum == 1) {
|
||||
dep->endpoint.maxpacket = 512;
|
||||
|
@ -2105,34 +2107,6 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
|
|||
dwc->setup_packet_pending = false;
|
||||
}
|
||||
|
||||
static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
|
||||
|
||||
if (suspend)
|
||||
reg |= DWC3_GUSB3PIPECTL_SUSPHY;
|
||||
else
|
||||
reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
|
||||
|
||||
dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
|
||||
}
|
||||
|
||||
static void dwc3_gadget_usb2_phy_suspend(struct dwc3 *dwc, int suspend)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
|
||||
|
||||
if (suspend)
|
||||
reg |= DWC3_GUSB2PHYCFG_SUSPHY;
|
||||
else
|
||||
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
|
||||
|
||||
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
|
||||
}
|
||||
|
||||
static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
|
||||
{
|
||||
u32 reg;
|
||||
|
@ -2173,13 +2147,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
|
|||
/* after reset -> Default State */
|
||||
usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
|
||||
|
||||
/* Recent versions support automatic phy suspend and don't need this */
|
||||
if (dwc->revision < DWC3_REVISION_194A) {
|
||||
/* Resume PHYs */
|
||||
dwc3_gadget_usb2_phy_suspend(dwc, false);
|
||||
dwc3_gadget_usb3_phy_suspend(dwc, false);
|
||||
}
|
||||
|
||||
if (dwc->gadget.speed != USB_SPEED_UNKNOWN)
|
||||
dwc3_disconnect_gadget(dwc);
|
||||
|
||||
|
@ -2223,20 +2190,6 @@ static void dwc3_update_ram_clk_sel(struct dwc3 *dwc, u32 speed)
|
|||
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
|
||||
}
|
||||
|
||||
static void dwc3_gadget_phy_suspend(struct dwc3 *dwc, u8 speed)
|
||||
{
|
||||
switch (speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
dwc3_gadget_usb2_phy_suspend(dwc, true);
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
case USB_SPEED_FULL:
|
||||
case USB_SPEED_LOW:
|
||||
dwc3_gadget_usb3_phy_suspend(dwc, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
|
||||
{
|
||||
struct dwc3_ep *dep;
|
||||
|
@ -2312,12 +2265,6 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
|
|||
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
|
||||
}
|
||||
|
||||
/* Recent versions support automatic phy suspend and don't need this */
|
||||
if (dwc->revision < DWC3_REVISION_194A) {
|
||||
/* Suspend unneeded PHY */
|
||||
dwc3_gadget_phy_suspend(dwc, dwc->gadget.speed);
|
||||
}
|
||||
|
||||
dep = dwc->eps[0];
|
||||
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true);
|
||||
if (ret) {
|
||||
|
@ -2495,6 +2442,53 @@ static void dwc3_process_event_entry(struct dwc3 *dwc,
|
|||
}
|
||||
}
|
||||
|
||||
static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
|
||||
{
|
||||
struct dwc3_event_buffer *evt;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
int left;
|
||||
u32 reg;
|
||||
|
||||
evt = dwc->ev_buffs[buf];
|
||||
left = evt->count;
|
||||
|
||||
if (!(evt->flags & DWC3_EVENT_PENDING))
|
||||
return IRQ_NONE;
|
||||
|
||||
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(buf), 4);
|
||||
}
|
||||
|
||||
evt->count = 0;
|
||||
evt->flags &= ~DWC3_EVENT_PENDING;
|
||||
ret = IRQ_HANDLED;
|
||||
|
||||
/* Unmask interrupt */
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(buf));
|
||||
reg &= ~DWC3_GEVNTSIZ_INTMASK;
|
||||
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
|
||||
{
|
||||
struct dwc3 *dwc = _dwc;
|
||||
|
@ -2504,52 +2498,19 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
|
|||
|
||||
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;
|
||||
}
|
||||
for (i = 0; i < dwc->num_event_buffers; i++)
|
||||
ret |= dwc3_process_event_buf(dwc, i);
|
||||
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
|
||||
static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc, u32 buf)
|
||||
{
|
||||
struct dwc3_event_buffer *evt;
|
||||
u32 count;
|
||||
u32 reg;
|
||||
|
||||
evt = dwc->ev_buffs[buf];
|
||||
|
||||
|
@ -2561,6 +2522,11 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
|
|||
evt->count = count;
|
||||
evt->flags |= DWC3_EVENT_PENDING;
|
||||
|
||||
/* Mask interrupt */
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(buf));
|
||||
reg |= DWC3_GEVNTSIZ_INTMASK;
|
||||
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg);
|
||||
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
|
@ -2575,7 +2541,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
|
|||
for (i = 0; i < dwc->num_event_buffers; i++) {
|
||||
irqreturn_t status;
|
||||
|
||||
status = dwc3_process_event_buf(dwc, i);
|
||||
status = dwc3_check_event_buf(dwc, i);
|
||||
if (status == IRQ_WAKE_THREAD)
|
||||
ret = status;
|
||||
}
|
||||
|
@ -2593,7 +2559,6 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
|
|||
*/
|
||||
int dwc3_gadget_init(struct dwc3 *dwc)
|
||||
{
|
||||
u32 reg;
|
||||
int ret;
|
||||
|
||||
dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
|
||||
|
@ -2643,16 +2608,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
|
|||
if (ret)
|
||||
goto err4;
|
||||
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
|
||||
reg |= DWC3_DCFG_LPM_CAP;
|
||||
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
|
||||
|
||||
/* Enable USB2 LPM and automatic phy suspend only on recent versions */
|
||||
if (dwc->revision >= DWC3_REVISION_194A) {
|
||||
dwc3_gadget_usb2_phy_suspend(dwc, false);
|
||||
dwc3_gadget_usb3_phy_suspend(dwc, false);
|
||||
}
|
||||
|
||||
ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
|
||||
if (ret) {
|
||||
dev_err(dwc->dev, "failed to register udc\n");
|
||||
|
|
|
@ -6,34 +6,14 @@
|
|||
* Authors: Felipe Balbi <balbi@ti.com>,
|
||||
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 of
|
||||
* the License as published by the Free Software Foundation.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_USB_DWC3_GADGET_H
|
||||
|
|
|
@ -5,34 +5,14 @@
|
|||
*
|
||||
* Authors: Felipe Balbi <balbi@ti.com>,
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 of
|
||||
* the License as published by the Free Software Foundation.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
|
|
@ -6,34 +6,14 @@
|
|||
* Authors: Felipe Balbi <balbi@ti.com>,
|
||||
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 of
|
||||
* the License as published by the Free Software Foundation.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_USB_DWC3_IO_H
|
||||
|
|
27
drivers/usb/dwc3/platform_data.h
Normal file
27
drivers/usb/dwc3/platform_data.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* platform_data.h - USB DWC3 Platform Data Support
|
||||
*
|
||||
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
|
||||
* Author: Felipe Balbi <balbi@ti.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 of
|
||||
* the License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/otg.h>
|
||||
|
||||
struct dwc3_platform_data {
|
||||
enum usb_device_speed maximum_speed;
|
||||
enum usb_dr_mode dr_mode;
|
||||
bool tx_fifo_resize;
|
||||
};
|
|
@ -144,7 +144,6 @@ config USB_AT91
|
|||
config USB_LPC32XX
|
||||
tristate "LPC32XX USB Peripheral Controller"
|
||||
depends on ARCH_LPC32XX
|
||||
depends on USB_PHY
|
||||
select USB_ISP1301
|
||||
help
|
||||
This option selects the USB device controller in the LPC32xx SoC.
|
||||
|
@ -188,7 +187,7 @@ config USB_FSL_USB2
|
|||
|
||||
config USB_FUSB300
|
||||
tristate "Faraday FUSB300 USB Peripheral Controller"
|
||||
depends on !PHYS_ADDR_T_64BIT
|
||||
depends on !PHYS_ADDR_T_64BIT && HAS_DMA
|
||||
help
|
||||
Faraday usb device controller FUSB300 driver
|
||||
|
||||
|
@ -206,7 +205,6 @@ config USB_FOTG210_UDC
|
|||
config USB_OMAP
|
||||
tristate "OMAP USB Device Controller"
|
||||
depends on ARCH_OMAP1
|
||||
depends on USB_PHY
|
||||
select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
|
||||
help
|
||||
Many Texas Instruments OMAP processors have flexible full
|
||||
|
@ -246,6 +244,7 @@ config USB_PXA25X_SMALL
|
|||
|
||||
config USB_R8A66597
|
||||
tristate "Renesas R8A66597 USB Peripheral Controller"
|
||||
depends on HAS_DMA
|
||||
help
|
||||
R8A66597 is a discrete USB host and peripheral controller chip that
|
||||
supports both full and high speed USB 2.0 data transfers.
|
||||
|
@ -287,21 +286,6 @@ config USB_S3C_HSOTG
|
|||
The Samsung S3C64XX USB2.0 high-speed gadget controller
|
||||
integrated into the S3C64XX series SoC.
|
||||
|
||||
config USB_IMX
|
||||
tristate "Freescale i.MX1 USB Peripheral Controller"
|
||||
depends on ARCH_MXC
|
||||
depends on BROKEN
|
||||
help
|
||||
Freescale's i.MX1 includes an integrated full speed
|
||||
USB 1.1 device controller.
|
||||
|
||||
It has Six fixed-function endpoints, as well as endpoint
|
||||
zero (for control transfers).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "imx_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_S3C2410
|
||||
tristate "S3C2410 USB Device Controller"
|
||||
depends on ARCH_S3C24XX
|
||||
|
@ -402,7 +386,7 @@ config USB_NET2272
|
|||
|
||||
config USB_NET2272_DMA
|
||||
boolean "Support external DMA controller"
|
||||
depends on USB_NET2272
|
||||
depends on USB_NET2272 && HAS_DMA
|
||||
help
|
||||
The NET2272 part can optionally support an external DMA
|
||||
controller, but your board has to have support in the
|
||||
|
@ -572,7 +556,7 @@ config USB_CONFIGFS
|
|||
specified simply by creating appropriate directories in configfs.
|
||||
Associating functions with configurations is done by creating
|
||||
appropriate symbolic links.
|
||||
For more information see Documentation/usb/gadget-configfs.txt.
|
||||
For more information see Documentation/usb/gadget_configfs.txt.
|
||||
|
||||
config USB_CONFIGFS_SERIAL
|
||||
boolean "Generic serial bulk in/out"
|
||||
|
|
|
@ -13,7 +13,6 @@ obj-$(CONFIG_USB_NET2280) += net2280.o
|
|||
obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o
|
||||
obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o
|
||||
obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o
|
||||
obj-$(CONFIG_USB_IMX) += imx_udc.o
|
||||
obj-$(CONFIG_USB_GOKU) += goku_udc.o
|
||||
obj-$(CONFIG_USB_OMAP) += omap_udc.o
|
||||
obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o
|
||||
|
|
|
@ -1122,7 +1122,7 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
|
|||
goto finished;
|
||||
}
|
||||
if (ep->dma) {
|
||||
retval = prep_dma(ep, req, gfp);
|
||||
retval = prep_dma(ep, req, GFP_ATOMIC);
|
||||
if (retval != 0)
|
||||
goto finished;
|
||||
/* write desc pointer to enable DMA */
|
||||
|
@ -1190,7 +1190,7 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
|
|||
* for PPB modes, because of chain creation reasons
|
||||
*/
|
||||
if (ep->in) {
|
||||
retval = prep_dma(ep, req, gfp);
|
||||
retval = prep_dma(ep, req, GFP_ATOMIC);
|
||||
if (retval != 0)
|
||||
goto finished;
|
||||
}
|
||||
|
|
|
@ -870,6 +870,11 @@ static void clk_on(struct at91_udc *udc)
|
|||
if (udc->clocked)
|
||||
return;
|
||||
udc->clocked = 1;
|
||||
|
||||
if (IS_ENABLED(CONFIG_COMMON_CLK)) {
|
||||
clk_set_rate(udc->uclk, 48000000);
|
||||
clk_prepare_enable(udc->uclk);
|
||||
}
|
||||
clk_prepare_enable(udc->iclk);
|
||||
clk_prepare_enable(udc->fclk);
|
||||
}
|
||||
|
@ -882,6 +887,8 @@ static void clk_off(struct at91_udc *udc)
|
|||
udc->gadget.speed = USB_SPEED_UNKNOWN;
|
||||
clk_disable_unprepare(udc->fclk);
|
||||
clk_disable_unprepare(udc->iclk);
|
||||
if (IS_ENABLED(CONFIG_COMMON_CLK))
|
||||
clk_disable_unprepare(udc->uclk);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1697,7 +1704,7 @@ static int at91udc_probe(struct platform_device *pdev)
|
|||
int retval;
|
||||
struct resource *res;
|
||||
|
||||
if (!dev->platform_data && !pdev->dev.of_node) {
|
||||
if (!dev_get_platdata(dev) && !pdev->dev.of_node) {
|
||||
/* small (so we copy it) but critical! */
|
||||
DBG("missing platform_data\n");
|
||||
return -ENODEV;
|
||||
|
@ -1728,7 +1735,7 @@ static int at91udc_probe(struct platform_device *pdev)
|
|||
if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
|
||||
at91udc_of_init(udc, pdev->dev.of_node);
|
||||
else
|
||||
memcpy(&udc->board, dev->platform_data,
|
||||
memcpy(&udc->board, dev_get_platdata(dev),
|
||||
sizeof(struct at91_udc_data));
|
||||
udc->pdev = pdev;
|
||||
udc->enabled = 0;
|
||||
|
@ -1774,10 +1781,12 @@ static int at91udc_probe(struct platform_device *pdev)
|
|||
/* get interface and function clocks */
|
||||
udc->iclk = clk_get(dev, "udc_clk");
|
||||
udc->fclk = clk_get(dev, "udpck");
|
||||
if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) {
|
||||
if (IS_ENABLED(CONFIG_COMMON_CLK))
|
||||
udc->uclk = clk_get(dev, "usb_clk");
|
||||
if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk) ||
|
||||
(IS_ENABLED(CONFIG_COMMON_CLK) && IS_ERR(udc->uclk))) {
|
||||
DBG("clocks missing\n");
|
||||
retval = -ENODEV;
|
||||
/* NOTE: we "know" here that refcounts on these are NOPs */
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
|
@ -1851,6 +1860,12 @@ fail3:
|
|||
fail2:
|
||||
free_irq(udc->udp_irq, udc);
|
||||
fail1:
|
||||
if (IS_ENABLED(CONFIG_COMMON_CLK) && !IS_ERR(udc->uclk))
|
||||
clk_put(udc->uclk);
|
||||
if (!IS_ERR(udc->fclk))
|
||||
clk_put(udc->fclk);
|
||||
if (!IS_ERR(udc->iclk))
|
||||
clk_put(udc->iclk);
|
||||
iounmap(udc->udp_baseaddr);
|
||||
fail0a:
|
||||
if (cpu_is_at91rm9200())
|
||||
|
@ -1894,6 +1909,8 @@ static int __exit at91udc_remove(struct platform_device *pdev)
|
|||
|
||||
clk_put(udc->iclk);
|
||||
clk_put(udc->fclk);
|
||||
if (IS_ENABLED(CONFIG_COMMON_CLK))
|
||||
clk_put(udc->uclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ struct at91_udc {
|
|||
unsigned active_suspend:1;
|
||||
u8 addr;
|
||||
struct at91_udc_data board;
|
||||
struct clk *iclk, *fclk;
|
||||
struct clk *iclk, *fclk, *uclk;
|
||||
struct platform_device *pdev;
|
||||
struct proc_dir_entry *pde;
|
||||
void __iomem *udp_baseaddr;
|
||||
|
|
|
@ -1772,6 +1772,7 @@ out:
|
|||
static int atmel_usba_start(struct usb_gadget *gadget,
|
||||
struct usb_gadget_driver *driver)
|
||||
{
|
||||
int ret;
|
||||
struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -1781,8 +1782,14 @@ static int atmel_usba_start(struct usb_gadget *gadget,
|
|||
udc->driver = driver;
|
||||
spin_unlock_irqrestore(&udc->lock, flags);
|
||||
|
||||
clk_enable(udc->pclk);
|
||||
clk_enable(udc->hclk);
|
||||
ret = clk_prepare_enable(udc->pclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = clk_prepare_enable(udc->hclk);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(udc->pclk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name);
|
||||
|
||||
|
@ -1822,8 +1829,8 @@ static int atmel_usba_stop(struct usb_gadget *gadget,
|
|||
|
||||
udc->driver = NULL;
|
||||
|
||||
clk_disable(udc->hclk);
|
||||
clk_disable(udc->pclk);
|
||||
clk_disable_unprepare(udc->hclk);
|
||||
clk_disable_unprepare(udc->pclk);
|
||||
|
||||
DBG(DBG_GADGET, "unregistered driver `%s'\n", driver->driver.name);
|
||||
|
||||
|
@ -1922,7 +1929,7 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
|
|||
static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
|
||||
struct usba_udc *udc)
|
||||
{
|
||||
struct usba_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct usba_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct usba_ep *eps;
|
||||
int i;
|
||||
|
||||
|
@ -2022,10 +2029,14 @@ static int __init usba_udc_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, udc);
|
||||
|
||||
/* Make sure we start from a clean slate */
|
||||
clk_enable(pclk);
|
||||
ret = clk_prepare_enable(pclk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Unable to enable pclk, aborting.\n");
|
||||
goto err_clk_enable;
|
||||
}
|
||||
toggle_bias(0);
|
||||
usba_writel(udc, CTRL, USBA_DISABLE_MASK);
|
||||
clk_disable(pclk);
|
||||
clk_disable_unprepare(pclk);
|
||||
|
||||
if (pdev->dev.of_node)
|
||||
udc->usba_ep = atmel_udc_of_init(pdev, udc);
|
||||
|
@ -2081,6 +2092,7 @@ err_add_udc:
|
|||
free_irq(irq, udc);
|
||||
err_request_irq:
|
||||
err_alloc_ep:
|
||||
err_clk_enable:
|
||||
iounmap(udc->fifo);
|
||||
err_map_fifo:
|
||||
iounmap(udc->regs);
|
||||
|
|
|
@ -2313,7 +2313,7 @@ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc)
|
|||
static int bcm63xx_udc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct bcm63xx_usbd_platform_data *pd = dev->platform_data;
|
||||
struct bcm63xx_usbd_platform_data *pd = dev_get_platdata(dev);
|
||||
struct bcm63xx_udc *udc;
|
||||
struct resource *res;
|
||||
int rc = -ENOMEM, i, irq;
|
||||
|
|
|
@ -1497,17 +1497,15 @@ void composite_disconnect(struct usb_gadget *gadget)
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static ssize_t composite_show_suspended(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static ssize_t suspended_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_gadget *gadget = dev_to_usb_gadget(dev);
|
||||
struct usb_composite_dev *cdev = get_gadget_data(gadget);
|
||||
|
||||
return sprintf(buf, "%d\n", cdev->suspended);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(suspended, 0444, composite_show_suspended, NULL);
|
||||
static DEVICE_ATTR_RO(suspended);
|
||||
|
||||
static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver)
|
||||
{
|
||||
|
|
|
@ -859,8 +859,10 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
|
|||
list_for_each_entry_safe(f, tmp, &cfg->func_list, list) {
|
||||
list_del(&f->list);
|
||||
ret = usb_add_function(c, f);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
list_add(&f->list, &cfg->func_list);
|
||||
goto err_purge_funcs;
|
||||
}
|
||||
}
|
||||
usb_ep_autoconfig_reset(cdev->gadget);
|
||||
}
|
||||
|
|
|
@ -868,7 +868,7 @@ static const struct usb_gadget_ops dummy_ops = {
|
|||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* "function" sysfs attribute */
|
||||
static ssize_t show_function(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t function_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct dummy *dum = gadget_dev_to_dummy(dev);
|
||||
|
@ -877,7 +877,7 @@ static ssize_t show_function(struct device *dev, struct device_attribute *attr,
|
|||
return 0;
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", dum->driver->function);
|
||||
}
|
||||
static DEVICE_ATTR(function, S_IRUGO, show_function, NULL);
|
||||
static DEVICE_ATTR_RO(function);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -2290,7 +2290,7 @@ static inline ssize_t show_urb(char *buf, size_t size, struct urb *urb)
|
|||
urb->actual_length, urb->transfer_buffer_length);
|
||||
}
|
||||
|
||||
static ssize_t show_urbs(struct device *dev, struct device_attribute *attr,
|
||||
static ssize_t urbs_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
||||
|
@ -2311,7 +2311,7 @@ static ssize_t show_urbs(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR(urbs, S_IRUGO, show_urbs, NULL);
|
||||
static DEVICE_ATTR_RO(urbs);
|
||||
|
||||
static int dummy_start_ss(struct dummy_hcd *dum_hcd)
|
||||
{
|
||||
|
|
|
@ -285,6 +285,7 @@ static struct usb_string acm_string_defs[] = {
|
|||
[ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)",
|
||||
[ACM_DATA_IDX].s = "CDC ACM Data",
|
||||
[ACM_IAD_IDX ].s = "CDC Serial",
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings acm_string_table = {
|
||||
|
|
|
@ -1417,8 +1417,8 @@ static void functionfs_unbind(struct ffs_data *ffs)
|
|||
usb_ep_free_request(ffs->gadget->ep0, ffs->ep0req);
|
||||
ffs->ep0req = NULL;
|
||||
ffs->gadget = NULL;
|
||||
ffs_data_put(ffs);
|
||||
clear_bit(FFS_FL_BOUND, &ffs->flags);
|
||||
ffs_data_put(ffs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2578,14 +2578,12 @@ static int fsg_main_thread(void *common_)
|
|||
|
||||
/*************************** DEVICE ATTRIBUTES ***************************/
|
||||
|
||||
static DEVICE_ATTR(ro, 0644, fsg_show_ro, fsg_store_ro);
|
||||
static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, fsg_store_nofua);
|
||||
static DEVICE_ATTR(file, 0644, fsg_show_file, fsg_store_file);
|
||||
static DEVICE_ATTR_RW(ro);
|
||||
static DEVICE_ATTR_RW(nofua);
|
||||
static DEVICE_ATTR_RW(file);
|
||||
|
||||
static struct device_attribute dev_attr_ro_cdrom =
|
||||
__ATTR(ro, 0444, fsg_show_ro, NULL);
|
||||
static struct device_attribute dev_attr_file_nonremovable =
|
||||
__ATTR(file, 0444, fsg_show_file, NULL);
|
||||
static struct device_attribute dev_attr_ro_cdrom = __ATTR_RO(ro);
|
||||
static struct device_attribute dev_attr_file_nonremovable = __ATTR_RO(file);
|
||||
|
||||
|
||||
/****************************** FSG COMMON ******************************/
|
||||
|
@ -3043,12 +3041,12 @@ fsg_config_from_params(struct fsg_config *cfg,
|
|||
lun->filename =
|
||||
params->file_count > i && params->file[i][0]
|
||||
? params->file[i]
|
||||
: 0;
|
||||
: NULL;
|
||||
}
|
||||
|
||||
/* Let MSF use defaults */
|
||||
cfg->vendor_name = 0;
|
||||
cfg->product_name = 0;
|
||||
cfg->vendor_name = NULL;
|
||||
cfg->product_name = NULL;
|
||||
|
||||
cfg->ops = NULL;
|
||||
cfg->private_data = NULL;
|
||||
|
|
|
@ -695,7 +695,7 @@ static int generic_get_cmd(struct usb_audio_control *con, u8 cmd)
|
|||
}
|
||||
|
||||
/* Todo: add more control selecotor dynamically */
|
||||
int __init control_selector_init(struct f_audio *audio)
|
||||
static int __init control_selector_init(struct f_audio *audio)
|
||||
{
|
||||
INIT_LIST_HEAD(&audio->cs);
|
||||
list_add(&feature_unit.list, &audio->cs);
|
||||
|
@ -719,7 +719,7 @@ int __init control_selector_init(struct f_audio *audio)
|
|||
*
|
||||
* Returns zero on success, else negative errno.
|
||||
*/
|
||||
int __init audio_bind_config(struct usb_configuration *c)
|
||||
static int __init audio_bind_config(struct usb_configuration *c)
|
||||
{
|
||||
struct f_audio *audio;
|
||||
int status;
|
||||
|
|
|
@ -1076,7 +1076,7 @@ static struct usb_gadget_ops fotg210_gadget_ops = {
|
|||
|
||||
static int fotg210_udc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct fotg210_udc *fotg210 = dev_get_drvdata(&pdev->dev);
|
||||
struct fotg210_udc *fotg210 = platform_get_drvdata(pdev);
|
||||
|
||||
usb_del_gadget_udc(&fotg210->gadget);
|
||||
iounmap(fotg210->reg);
|
||||
|
@ -1134,7 +1134,7 @@ static int fotg210_udc_probe(struct platform_device *pdev)
|
|||
|
||||
spin_lock_init(&fotg210->lock);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, fotg210);
|
||||
platform_set_drvdata(pdev, fotg210);
|
||||
|
||||
fotg210->gadget.ops = &fotg210_gadget_ops;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue