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:
Linus Torvalds 2013-09-03 11:35:32 -07:00
commit b3b49114c8
305 changed files with 14878 additions and 7064 deletions

View 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

View file

@ -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>

View file

@ -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>;
};
};

View file

@ -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>;

View 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";
};

View file

@ -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

View 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>;
};

View 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>;
};

View file

@ -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

View file

@ -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?

View file

@ -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

View file

@ -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/

View file

@ -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>;

View file

@ -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>;

View file

@ -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";

View file

@ -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 {

View file

@ -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>;

View file

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

View file

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

View file

@ -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 {

View file

@ -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";
};

View file

@ -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,
};

View file

@ -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),
};

View file

@ -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 */

View file

@ -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)) {

View file

@ -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)

View file

@ -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)

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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;

View file

@ -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 {

View file

@ -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

View file

@ -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/

View file

@ -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

View file

@ -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__);

View file

@ -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;

View file

@ -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() */

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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 */

View file

@ -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);

View file

@ -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 *);

View file

@ -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,

View file

@ -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");

View file

@ -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)

View file

@ -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
View 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);
}

View 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 */

View file

@ -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);
}

View file

@ -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 */

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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)
{

View file

@ -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);

View file

@ -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;

View file

@ -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)
{

View file

@ -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,

View file

@ -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,

View file

@ -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)
{

View file

@ -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

View file

@ -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)

View file

@ -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.
*/

View file

@ -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;

View file

@ -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,

View file

@ -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)
{

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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");

View file

@ -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

View file

@ -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"

View file

@ -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>

View file

@ -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");

View file

@ -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");

View file

@ -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);

View file

@ -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;

View file

@ -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");

View file

@ -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

View file

@ -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>

View file

@ -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

View 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;
};

View file

@ -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"

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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)
{

View file

@ -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);
}

View file

@ -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)
{

View file

@ -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 = {

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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