USB / Thunderbolt changes for 6.0-rc1

Here is the big set of Thunderbolt and USB changes for 6.0-rc1.
 
 Lots of little things here, nothing major, just constant development on
 some new hardware support and cleanups of older drivers.  Highlights of
 this pull request are:
 	- lots of typec changes and improvements for new hardware
 	- new gadget controller driver
 	- thunderbolt support for new hardware
 	- the normal set of new usb-serial device ids and cleanups
 	- loads of dwc3 controller fixes and improvements
 	- mtu3 driver updates
 	- testusb fixes for longtime issues (not many people use this
 	  tool it seems.)
 	- minor driver fixes and improvements over the USB tree
 	- chromeos platform driver changes were added and then reverted
 	  as they depened on some typec changes, but the cross-tree
 	  merges caused problems so they will come back later through
 	  the platform tree.
 
 All of these have been in linux-next for a while now with no reported
 issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYup5Rg8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+yko/ACfYD9mdlr4WleUpVw5/uNywN6sL9EAn1tv0V8W
 cUTAoWxAf5orClAC22ZU
 =Vcqd
 -----END PGP SIGNATURE-----

Merge tag 'usb-6.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB / Thunderbolt updates from Greg KH:
 "Here is the big set of Thunderbolt and USB changes for 6.0-rc1.

  Lots of little things here, nothing major, just constant development
  on some new hardware support and cleanups of older drivers. Highlights
  are:

   - lots of typec changes and improvements for new hardware

   - new gadget controller driver

   - thunderbolt support for new hardware

   - the normal set of new usb-serial device ids and cleanups

   - loads of dwc3 controller fixes and improvements

   - mtu3 driver updates

   - testusb fixes for longtime issues (not many people use this tool it
     seems.)

   - minor driver fixes and improvements over the USB tree

   - chromeos platform driver changes were added and then reverted as
     they depened on some typec changes, but the cross-tree merges
     caused problems so they will come back later through the platform
     tree.

  All of these have been in linux-next for a while now with no reported
  issues"

* tag 'usb-6.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (193 commits)
  usb: misc: onboard_usb_hub: Remove duplicated power_on delay
  usb: misc: onboard_usb_hub: Add TI USB8041 hub support
  usb: misc: onboard_usb_hub: Add reset-gpio support
  USB: usbsevseg: convert sysfs snprintf to sysfs_emit
  dt-bindings: usb: Add binding for TI USB8041 hub controller
  ARM: multi_v7_defconfig: enable USB onboard HUB driver
  ARM: dts: stm32: add support for USB2514B onboard hub on stm32mp15xx-dkx
  usb: misc: onboard-hub: add support for Microchip USB2514B USB 2.0 hub
  dt-bindings: usb: generic-ehci: allow usb-hcd schema properties
  usb: typec: ucsi: stm32g0: add bootloader support
  usb: typec: ucsi: stm32g0: add support for stm32g0 controller
  dt-bindings: usb: typec: add bindings for stm32g0 controller
  usb: typec: ucsi: Acknowledge the GET_ERROR_STATUS command completion
  usb: cdns3: change place of 'priv_ep' assignment in cdns3_gadget_ep_dequeue(), cdns3_gadget_ep_enable()
  usb/chipidea: fix repeated words in comments
  usb: renesas-xhci: Do not print any log while fw verif success
  usb: typec: retimer: Add missing id check in match callback
  USB: xhci: Fix comment typo
  usb/typec/tcpm: fix repeated words in comments
  usb/musb: fix repeated words in comments
  ...
This commit is contained in:
Linus Torvalds 2022-08-04 11:41:28 -07:00
commit 9e2e5ea3b2
172 changed files with 8399 additions and 695 deletions

View File

@ -19,7 +19,7 @@ KernelVersion: 3.13
Description:
The attributes:
=========== ==============================================
============ ==============================================
file The path to the backing file for the LUN.
Required if LUN is not marked as removable.
ro Flag specifying access to the LUN shall be
@ -32,4 +32,10 @@ Description:
being a CD-ROM.
nofua Flag specifying that FUA flag
in SCSI WRITE(10,12)
=========== ==============================================
forced_eject This write-only file is useful only when
the function is active. It causes the backing
file to be forcibly detached from the LUN,
regardless of whether the host has allowed it.
Any non-zero number of bytes written will
result in ejection.
============ ==============================================

View File

@ -0,0 +1,8 @@
What: /sys/bus/platform/devices/<dev>/always_powered_in_suspend
Date: June 2022
KernelVersion: 5.20
Contact: Matthias Kaehlcke <matthias@kaehlcke.net>
linux-usb@vger.kernel.org
Description:
(RW) Controls whether the USB hub remains always powered
during system suspend or not.

View File

@ -253,6 +253,17 @@ Description:
only if the system firmware is capable of describing the
connection between a port and its connector.
What: /sys/bus/usb/devices/.../<hub_interface>/port<X>/disable
Date: June 2022
Contact: Michael Grzeschik <m.grzeschik@pengutronix.de>
Description:
This file controls the state of a USB port, including
Vbus power output (but only on hubs that support
power switching -- most hubs don't support it). If
a port is disabled, the port is unusable: Devices
attached to the port will not be detected, initialized,
or enumerated.
What: /sys/bus/usb/devices/.../power/usb2_lpm_l1_timeout
Date: May 2013
Contact: Mathias Nyman <mathias.nyman@linux.intel.com>

View File

@ -141,6 +141,14 @@ Description:
- "reverse": CC2 orientation
- "unknown": Orientation cannot be determined.
What: /sys/class/typec/<port>/select_usb_power_delivery
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Lists the USB Power Delivery Capabilities that the port can
advertise to the partner. The currently used capabilities are in
brackets. Selection happens by writing to the file.
USB Type-C partner devices (eg. /sys/class/typec/port0-partner/)
What: /sys/class/typec/<port>-partner/accessory_mode

View File

@ -0,0 +1,240 @@
What: /sys/class/usb_power_delivery
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Directory for USB Power Delivery devices.
What: /sys/class/usb_power_delivery/.../revision
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
File showing the USB Power Delivery Specification Revision used
in communication.
What: /sys/class/usb_power_delivery/.../version
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
This is an optional attribute file showing the version of the
specific revision of the USB Power Delivery Specification. In
most cases the specification version is not known and the file
is not available.
What: /sys/class/usb_power_delivery/.../source-capabilities
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
The source capabilities message "Source_Capabilities" contains a
set of Power Data Objects (PDO), each representing a type of
power supply. The order of the PDO objects is defined in the USB
Power Delivery Specification. Each PDO - power supply - will
have its own device, and the PDO device name will start with the
object position number as the first character followed by the
power supply type name (":" as delimiter).
/sys/class/usb_power_delivery/.../source_capabilities/<position>:<type>
What: /sys/class/usb_power_delivery/.../sink-capabilities
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
The sink capability message "Sink_Capabilities" contains a set
of Power Data Objects (PDO) just like with source capabilities,
but instead of describing the power capabilities, these objects
describe the power requirements.
The order of the objects in the sink capability message is the
same as with the source capabilities message.
Fixed Supplies
What: /sys/class/usb_power_delivery/.../<capability>/<position>:fixed_supply
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Devices containing the attributes (the bit fields) defined for
Fixed Supplies.
The device "1:fixed_supply" is special. USB Power Delivery
Specification dictates that the first PDO (at object position
1), and the only mandatory PDO, is always the vSafe5V Fixed
Supply Object. vSafe5V Object has additional fields defined for
it that the other Fixed Supply Objects do not have and that are
related to the USB capabilities rather than power capabilities.
What: /sys/class/usb_power_delivery/.../<capability>/1:fixed_supply/dual_role_power
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
This file contains boolean value that tells does the device
support both source and sink power roles.
What: /sys/class/usb_power_delivery/.../<capability>/1:fixed_supply/usb_suspend_supported
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
This file shows the value of the USB Suspend Supported bit in
vSafe5V Fixed Supply Object. If the bit is set then the device
will follow the USB 2.0 and USB 3.2 rules for suspend and
resume.
What: /sys/class/usb_power_delivery/.../<capability>/1:fixed_supply/unconstrained_power
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
This file shows the value of the Unconstrained Power bit in
vSafe5V Fixed Supply Object. The bit is set when an external
source of power, powerful enough to power the entire system on
its own, is available for the device.
What: /sys/class/usb_power_delivery/.../<capability>/1:fixed_supply/usb_communication_capable
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
This file shows the value of the USB Communication Capable bit in
vSafe5V Fixed Supply Object.
What: /sys/class/usb_power_delivery/.../<capability>/1:fixed_supply/dual_role_data
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
This file shows the value of the Dual-Role Data bit in vSafe5V
Fixed Supply Object. Dual role data means ability act as both
USB host and USB device.
What: /sys/class/usb_power_delivery/.../<capability>/1:fixed_supply/unchunked_extended_messages_supported
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
This file shows the value of the Unchunked Extended Messages
Supported bit in vSafe5V Fixed Supply Object.
What: /sys/class/usb_power_delivery/.../<capability>/<position>:fixed_supply/voltage
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
The voltage the supply supports in millivolts.
What: /sys/class/usb_power_delivery/.../source-capabilities/<position>:fixed_supply/maximum_current
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Maximum current of the fixed source supply in milliamperes.
What: /sys/class/usb_power_delivery/.../sink-capabilities/<position>:fixed_supply/operational_current
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Operational current of the sink in milliamperes.
What: /sys/class/usb_power_delivery/.../sink-capabilities/<position>:fixed_supply/fast_role_swap_current
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
This file contains the value of the "Fast Role Swap USB Type-C
Current" field that tells the current level the sink requires
after a Fast Role Swap.
0 - Fast Swap not supported"
1 - Default USB Power"
2 - 1.5A@5V"
3 - 3.0A@5V"
Variable Supplies
What: /sys/class/usb_power_delivery/.../<capability>/<position>:variable_supply
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Variable Power Supply PDO.
What: /sys/class/usb_power_delivery/.../<capability>/<position>:variable_supply/maximum_voltage
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Maximum Voltage in millivolts.
What: /sys/class/usb_power_delivery/.../<capability>/<position>:variable_supply/minimum_voltage
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Minimum Voltage in millivolts.
What: /sys/class/usb_power_delivery/.../source-capabilities/<position>:variable_supply/maximum_current
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
The maximum current in milliamperes that the source can supply
at the given Voltage range.
What: /sys/class/usb_power_delivery/.../sink-capabilities/<position>:variable_supply/operational_current
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
The operational current in milliamperes that the sink requires
at the given Voltage range.
Battery Supplies
What: /sys/class/usb_power_delivery/.../<capability>/<position>:battery
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Battery PDO.
What: /sys/class/usb_power_delivery/.../<capability>/<position>:battery/maximum_voltage
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Maximum Voltage in millivolts.
What: /sys/class/usb_power_delivery/.../<capability>/<position>:battery/minimum_voltage
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Minimum Voltage in millivolts.
What: /sys/class/usb_power_delivery/.../source-capabilities/<position>:battery/maximum_power
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Maximum allowable Power in milliwatts.
What: /sys/class/usb_power_delivery/.../sink-capabilities/<position>:battery/operational_power
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
The operational power that the sink requires at the given
voltage range.
Standard Power Range (SPR) Programmable Power Supplies
What: /sys/class/usb_power_delivery/.../<capability>/<position>:programmable_supply
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Programmable Power Supply (PPS) Augmented PDO (APDO).
What: /sys/class/usb_power_delivery/.../<capability>/<position>:programmable_supply/maximum_voltage
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Maximum Voltage in millivolts.
What: /sys/class/usb_power_delivery/.../<capability>/<position>:programmable_supply/minimum_voltage
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Minimum Voltage in millivolts.
What: /sys/class/usb_power_delivery/.../<capability>/<position>:programmable_supply/maximum_current
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Maximum Current in milliamperes.
What: /sys/class/usb_power_delivery/.../source-capabilities/<position>:programmable_supply/pps_power_limited
Date: May 2022
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
The PPS Power Limited bit indicates whether or not the source
supply will exceed the rated output power if requested.

View File

@ -0,0 +1,81 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/analogix,anx7411.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analogix ANX7411 Type-C controller bindings
maintainers:
- Xin Ji <xji@analogixsemi.com>
properties:
compatible:
enum:
- analogix,anx7411
reg:
maxItems: 1
interrupts:
maxItems: 1
connector:
type: object
$ref: ../connector/usb-connector.yaml
description:
Properties for usb c connector.
properties:
compatible:
const: usb-c-connector
power-role: true
data-role: true
try-power-role: true
required:
- compatible
required:
- compatible
- reg
- connector
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
typec@2c {
compatible = "analogix,anx7411";
reg = <0x2c>;
interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
interrupt-parent = <&gpio0>;
typec_con: connector {
compatible = "usb-c-connector";
power-role = "dual";
data-role = "dual";
try-power-role = "source";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
typec_con_ep: endpoint {
remote-endpoint = <&usbotg_hs_ep>;
};
};
};
};
};
};
...

View File

@ -0,0 +1,52 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2020 Facebook Inc.
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/aspeed,ast2600-udc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ASPEED USB 2.0 Device Controller
maintainers:
- Neal Liu <neal_liu@aspeedtech.com>
description: |+
The ASPEED USB 2.0 Device Controller implements 1 control endpoint and
4 generic endpoints for AST260x.
Supports independent DMA channel for each generic endpoint.
Supports 32/256 stages descriptor mode for all generic endpoints.
properties:
compatible:
enum:
- aspeed,ast2600-udc
reg:
maxItems: 1
clocks:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
- clocks
- interrupts
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/aspeed-clock.h>
udc: usb@1e6a2000 {
compatible = "aspeed,ast2600-udc";
reg = <0x1e6a2000 0x300>;
interrupts = <9>;
clocks = <&syscon ASPEED_CLK_GATE_USBPORT2CLK>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usb2bd_default>;
};

View File

@ -11,6 +11,7 @@ maintainers:
allOf:
- $ref: usb-drd.yaml#
- $ref: usb-hcd.yaml#
properties:
compatible:
@ -161,6 +162,8 @@ properties:
property is used.
$ref: /schemas/graph.yaml#/properties/port
tpl-support: true
dependencies:
port: [ usb-role-switch ]
role-switch-default-mode: [ usb-role-switch ]

View File

@ -131,11 +131,6 @@ properties:
Set this flag to indicate that the hardware sometimes turns on
the OC bit when an over-current isn't actually present.
companion:
$ref: /schemas/types.yaml#/definitions/phandle
description:
Phandle of a companion.
phys:
minItems: 1
maxItems: 3
@ -156,7 +151,7 @@ required:
- reg
- interrupts
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -31,6 +31,7 @@ properties:
- mediatek,mt8173-xhci
- mediatek,mt8183-xhci
- mediatek,mt8186-xhci
- mediatek,mt8188-xhci
- mediatek,mt8192-xhci
- mediatek,mt8195-xhci
- const: mediatek,mtk-xhci
@ -57,6 +58,7 @@ properties:
- description: optional, wakeup interrupt used to support runtime PM
interrupt-names:
minItems: 1
items:
- const: host
- const: wakeup
@ -113,6 +115,9 @@ properties:
vbus-supply:
description: Regulator of USB VBUS5v
resets:
maxItems: 1
usb3-lpm-capable: true
usb2-lpm-disable: true

View File

@ -107,6 +107,9 @@ properties:
maximum-speed:
enum: [super-speed-plus, super-speed, high-speed, full-speed]
resets:
maxItems: 1
"#address-cells":
enum: [1, 2]

View File

@ -24,6 +24,7 @@ properties:
- qcom,qcs404-dwc3
- qcom,sc7180-dwc3
- qcom,sc7280-dwc3
- qcom,sc8280xp-dwc3
- qcom,sdm660-dwc3
- qcom,sdm845-dwc3
- qcom,sdx55-dwc3
@ -66,11 +67,11 @@ properties:
- mock_utmi:: Mock utmi clock needed for ITP/SOF generation in host
mode. Its frequency should be 19.2MHz.
minItems: 1
maxItems: 6
maxItems: 9
clock-names:
minItems: 1
maxItems: 6
maxItems: 9
assigned-clocks:
items:
@ -93,20 +94,12 @@ properties:
- const: apps-usb
interrupts:
items:
- description: The interrupt that is asserted
when a wakeup event is received on USB2 bus.
- description: The interrupt that is asserted
when a wakeup event is received on USB3 bus.
- description: Wakeup event on DM line.
- description: Wakeup event on DP line.
minItems: 1
maxItems: 4
interrupt-names:
items:
- const: hs_phy_irq
- const: ss_phy_irq
- const: dm_hs_phy_irq
- const: dp_hs_phy_irq
minItems: 1
maxItems: 4
qcom,select-utmi-as-pipe-clk:
description:
@ -249,6 +242,28 @@ allOf:
- const: sleep
- const: mock_utmi
- if:
properties:
compatible:
contains:
enum:
- qcom,sc8280xp-dwc3
then:
properties:
clocks:
maxItems: 9
clock-names:
items:
- const: cfg_noc
- const: core
- const: iface
- const: sleep
- const: mock_utmi
- const: noc_aggr
- const: noc_aggr_north
- const: noc_aggr_south
- const: noc_sys
- if:
properties:
compatible:
@ -311,6 +326,115 @@ allOf:
- const: mock_utmi
- const: xo
- if:
properties:
compatible:
contains:
enum:
- qcom,ipq4019-dwc3
- qcom,ipq6018-dwc3
- qcom,ipq8064-dwc3
- qcom,ipq8074-dwc3
- qcom,msm8994-dwc3
- qcom,qcs404-dwc3
- qcom,sc7180-dwc3
- qcom,sdm845-dwc3
- qcom,sdx55-dwc3
- qcom,sdx65-dwc3
- qcom,sm4250-dwc3
- qcom,sm6115-dwc3
- qcom,sm6125-dwc3
- qcom,sm6350-dwc3
- qcom,sm8150-dwc3
- qcom,sm8250-dwc3
- qcom,sm8350-dwc3
- qcom,sm8450-dwc3
then:
properties:
interrupts:
items:
- description: The interrupt that is asserted
when a wakeup event is received on USB2 bus.
- description: The interrupt that is asserted
when a wakeup event is received on USB3 bus.
- description: Wakeup event on DM line.
- description: Wakeup event on DP line.
interrupt-names:
items:
- const: hs_phy_irq
- const: ss_phy_irq
- const: dm_hs_phy_irq
- const: dp_hs_phy_irq
- if:
properties:
compatible:
contains:
enum:
- qcom,msm8953-dwc3
- qcom,msm8996-dwc3
- qcom,msm8998-dwc3
then:
properties:
interrupts:
maxItems: 2
interrupt-names:
items:
- const: hs_phy_irq
- const: ss_phy_irq
- if:
properties:
compatible:
contains:
enum:
- qcom,sdm660-dwc3
then:
properties:
interrupts:
minItems: 1
maxItems: 2
interrupt-names:
minItems: 1
items:
- const: hs_phy_irq
- const: ss_phy_irq
- if:
properties:
compatible:
contains:
enum:
- qcom,sc7280-dwc3
then:
properties:
interrupts:
minItems: 3
maxItems: 4
interrupt-names:
minItems: 3
items:
- const: hs_phy_irq
- const: dp_hs_phy_irq
- const: dm_hs_phy_irq
- const: ss_phy_irq
- if:
properties:
compatible:
contains:
enum:
- qcom,sc8280xp-dwc3
then:
properties:
interrupts:
maxItems: 4
interrupt-names:
items:
- const: pwr_event
- const: dp_hs_phy_irq
- const: dm_hs_phy_irq
- const: ss_phy_irq
additionalProperties: false

View File

@ -25,13 +25,13 @@ properties:
description:
phandle to the regulator that provides power to the hub.
companion-hub:
peer-hub:
$ref: '/schemas/types.yaml#/definitions/phandle'
description:
phandle to the companion hub on the controller.
phandle to the peer hub on the controller.
required:
- companion-hub
- peer-hub
- compatible
- reg
@ -49,7 +49,7 @@ examples:
compatible = "usbbda,5411";
reg = <1>;
vdd-supply = <&pp3300_hub>;
companion-hub = <&hub_3_0>;
peer-hub = <&hub_3_0>;
};
/* 3.0 hub on port 2 */
@ -57,6 +57,6 @@ examples:
compatible = "usbbda,411";
reg = <2>;
vdd-supply = <&pp3300_hub>;
companion-hub = <&hub_2_0>;
peer-hub = <&hub_2_0>;
};
};

View File

@ -343,6 +343,11 @@ properties:
This port is used with the 'usb-role-switch' property to connect the
dwc3 to type C connector.
wakeup-source:
$ref: /schemas/types.yaml#/definitions/flag
description:
Enable USB remote wakeup.
unevaluatedProperties: false
required:

View File

@ -0,0 +1,91 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/st,typec-stm32g0.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: STMicroelectronics STM32G0 USB Type-C PD controller
description: |
The STM32G0 MCU can be programmed to control Type-C connector(s) through I2C
typically using the UCSI protocol over I2C, with a dedicated alert
(interrupt) pin.
maintainers:
- Fabrice Gasnier <fabrice.gasnier@foss.st.com>
properties:
compatible:
const: st,stm32g0-typec
reg:
maxItems: 1
interrupts:
maxItems: 1
connector:
type: object
$ref: /schemas/connector/usb-connector.yaml#
unevaluatedProperties: false
firmware-name:
description: |
Should contain the name of the default firmware image
file located on the firmware search path
wakeup-source: true
power-domains:
maxItems: 1
required:
- compatible
- reg
- interrupts
- connector
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
typec@53 {
compatible = "st,stm32g0-typec";
reg = <0x53>;
/* Alert pin on GPIO PE12 */
interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
interrupt-parent = <&gpioe>;
/* Example with one type-C connector */
connector {
compatible = "usb-c-connector";
label = "USB-C";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
con_usb_c_ep: endpoint {
remote-endpoint = <&usb_ep>;
};
};
};
};
};
};
usb {
usb-role-switch;
port {
usb_ep: endpoint {
remote-endpoint = <&con_usb_c_ep>;
};
};
};
...

View File

@ -0,0 +1,67 @@
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/ti,usb8041.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Binding for the TI USB8041 USB 3.0 hub controller
maintainers:
- Alexander Stein <alexander.stein@ew.tq-group.com>
allOf:
- $ref: usb-device.yaml#
properties:
compatible:
enum:
- usb451,8140
- usb451,8142
reg: true
reset-gpios:
items:
- description: GPIO specifier for GRST# pin.
vdd-supply:
description:
VDD power supply to the hub
peer-hub:
$ref: /schemas/types.yaml#/definitions/phandle
description:
phandle to the peer hub on the controller.
required:
- compatible
- reg
- peer-hub
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
usb {
dr_mode = "host";
#address-cells = <1>;
#size-cells = <0>;
/* 2.0 hub on port 1 */
hub_2_0: hub@1 {
compatible = "usb451,8142";
reg = <1>;
peer-hub = <&hub_3_0>;
reset-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
};
/* 3.0 hub on port 2 */
hub_3_0: hub@2 {
compatible = "usb451,8140";
reg = <2>;
peer-hub = <&hub_2_0>;
reset-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
};
};

View File

@ -333,6 +333,12 @@ In each lun directory there are the following attribute files:
being a CD-ROM.
nofua Flag specifying that FUA flag
in SCSI WRITE(10,12)
forced_eject This write-only file is useful only when
the function is active. It causes the backing
file to be forcibly detached from the LUN,
regardless of whether the host has allowed it.
Any non-zero number of bytes written will
result in ejection.
=============== ==============================================
Testing the MASS STORAGE function

View File

@ -181,6 +181,15 @@ sysfs entries
Reflects the state of nofua flag for given logical unit. It can
be read and written.
- forced_eject
When written into, it causes the backing file to be forcibly
detached from the LUN, regardless of whether the host has allowed
it. The content doesn't matter, any non-zero number of bytes
written will result in ejection.
Can not be read.
Other then those, as usual, the values of module parameters can be
read from /sys/module/g_mass_storage/parameters/* files.

View File

@ -3179,6 +3179,13 @@ S: Maintained
F: Documentation/devicetree/bindings/media/aspeed-video.txt
F: drivers/media/platform/aspeed/
ASPEED USB UDC DRIVER
M: Neal Liu <neal_liu@aspeedtech.com>
L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/usb/aspeed,ast2600-udc.yaml
F: drivers/usb/gadget/udc/aspeed_udc.c
ASUS NOTEBOOKS AND EEEPC ACPI/WMI EXTRAS DRIVERS
M: Corentin Chary <corentin.chary@gmail.com>
L: acpi4asus-user@lists.sourceforge.net
@ -15066,6 +15073,13 @@ S: Maintained
T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/ov9734.c
ONBOARD USB HUB DRIVER
M: Matthias Kaehlcke <mka@chromium.org>
L: linux-usb@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/sysfs-bus-platform-onboard-usb-hub
F: drivers/usb/misc/onboard_usb_hub.c
ONENAND FLASH DRIVER
M: Kyungmin Park <kyungmin.park@samsung.com>
L: linux-mtd@lists.infradead.org
@ -17458,6 +17472,7 @@ F: drivers/mailbox/mailbox-mpfs.c
F: drivers/pci/controller/pcie-microchip-host.c
F: drivers/soc/microchip/
F: drivers/spi/spi-microchip-core.c
F: drivers/usb/musb/mpfs.c
F: include/soc/microchip/mpfs.h
RNBD BLOCK DRIVERS

View File

@ -677,6 +677,14 @@
&usbh_ehci {
phys = <&usbphyc_port0>;
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
/* onboard HUB */
hub@1 {
compatible = "usb424,2514";
reg = <1>;
vdd-supply = <&v3v3>;
};
};
&usbotg_hs {

View File

@ -865,6 +865,7 @@ CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_ISP1760=y
CONFIG_USB_HSIC_USB3503=y
CONFIG_USB_ONBOARD_HUB=m
CONFIG_AB8500_USB=y
CONFIG_KEYSTONE_USB_PHY=m
CONFIG_NOP_USB_XCEIV=y

View File

@ -134,7 +134,7 @@ CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_STAGING=y
CONFIG_OCTEON_ETHERNET=y
CONFIG_OCTEON_USB=y
CONFIG_USB_OCTEON_HCD=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_RAS=y
CONFIG_EXT4_FS=y

View File

@ -42,8 +42,6 @@ source "drivers/staging/rts5208/Kconfig"
source "drivers/staging/octeon/Kconfig"
source "drivers/staging/octeon-usb/Kconfig"
source "drivers/staging/vt6655/Kconfig"
source "drivers/staging/vt6656/Kconfig"

View File

@ -11,7 +11,6 @@ obj-$(CONFIG_R8712U) += rtl8712/
obj-$(CONFIG_R8188EU) += r8188eu/
obj-$(CONFIG_RTS5208) += rts5208/
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
obj-$(CONFIG_OCTEON_USB) += octeon-usb/
obj-$(CONFIG_VT6655) += vt6655/
obj-$(CONFIG_VT6656) += vt6656/
obj-$(CONFIG_VME_BUS) += vme_user/

View File

@ -17,12 +17,6 @@
#define GDM_TTY_MAJOR 0
#define GDM_TTY_MINOR 32
#define ACM_CTRL_DTR 0x01
#define ACM_CTRL_RTS 0x02
#define ACM_CTRL_DSR 0x02
#define ACM_CTRL_RI 0x08
#define ACM_CTRL_DCD 0x01
#define WRITE_SIZE 2048
#define MUX_TX_MAX_SIZE 2048

View File

@ -1,11 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
config OCTEON_USB
tristate "Cavium Networks Octeon USB support"
depends on CAVIUM_OCTEON_SOC && USB
help
This driver supports USB host controller on some Cavium
Networks' products in the Octeon family.
To compile this driver as a module, choose M here. The module
will be called octeon-hcd.

View File

@ -1,2 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
obj-${CONFIG_OCTEON_USB} := octeon-hcd.o

View File

@ -1,8 +0,0 @@
This driver is functional and has been tested on EdgeRouter Lite,
D-Link DSR-1000N and EBH5600 evaluation board with USB mass storage.
TODO:
- kernel coding style
- checkpatch warnings
Contact: Aaro Koskinen <aaro.koskinen@iki.fi>

View File

@ -694,7 +694,7 @@ void tb_ctl_free(struct tb_ctl *ctl)
}
/**
* tb_cfg_start() - start/resume the control channel
* tb_ctl_start() - start/resume the control channel
* @ctl: Control channel to start
*/
void tb_ctl_start(struct tb_ctl *ctl)
@ -710,7 +710,7 @@ void tb_ctl_start(struct tb_ctl *ctl)
}
/**
* tb_ctrl_stop() - pause the control channel
* tb_ctl_stop() - pause the control channel
* @ctl: Control channel to stop
*
* All invocations of ctl->callback will have finished after this method
@ -912,7 +912,7 @@ struct tb_cfg_result tb_cfg_read_raw(struct tb_ctl *ctl, void *buffer,
}
/**
* tb_cfg_write() - write from buffer into config space
* tb_cfg_write_raw() - write from buffer into config space
* @ctl: Pointer to the control channel
* @buffer: Data to write
* @route: Route string of the router

View File

@ -35,7 +35,7 @@ struct tb_cfg_result {
* If err = 1 then this is the port that send the
* error.
* If err = 0 and if this was a cfg_read/write then
* this is the the upstream port of the responding
* this is the upstream port of the responding
* switch.
* Otherwise the field is set to zero.
*/

View File

@ -2516,6 +2516,8 @@ struct tb *icm_probe(struct tb_nhi *nhi)
case PCI_DEVICE_ID_INTEL_TGL_H_NHI1:
case PCI_DEVICE_ID_INTEL_ADL_NHI0:
case PCI_DEVICE_ID_INTEL_ADL_NHI1:
case PCI_DEVICE_ID_INTEL_RPL_NHI0:
case PCI_DEVICE_ID_INTEL_RPL_NHI1:
icm->is_supported = icm_tgl_is_supported;
icm->driver_ready = icm_icl_driver_ready;
icm->set_uuid = icm_icl_set_uuid;

View File

@ -1410,6 +1410,10 @@ static struct pci_device_id nhi_ids[] = {
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADL_NHI1),
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPL_NHI0),
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPL_NHI1),
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
/* Any USB4 compliant host */
{ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_USB4, ~0) },

View File

@ -80,6 +80,8 @@ extern const struct tb_nhi_ops icl_nhi_ops;
#define PCI_DEVICE_ID_INTEL_TGL_NHI1 0x9a1d
#define PCI_DEVICE_ID_INTEL_TGL_H_NHI0 0x9a1f
#define PCI_DEVICE_ID_INTEL_TGL_H_NHI1 0x9a21
#define PCI_DEVICE_ID_INTEL_RPL_NHI0 0xa73e
#define PCI_DEVICE_ID_INTEL_RPL_NHI1 0xa76d
#define PCI_CLASS_SERIAL_USB_USB4 0x0c0340

View File

@ -3133,9 +3133,13 @@ void tb_switch_suspend(struct tb_switch *sw, bool runtime)
/*
* Actually only needed for Titan Ridge but for simplicity can be
* done for USB4 device too as CLx is re-enabled at resume.
* CL0s and CL1 are enabled and supported together.
*/
if (tb_switch_disable_clx(sw, TB_CL0S))
tb_sw_warn(sw, "failed to disable CLx on upstream port\n");
if (tb_switch_is_clx_enabled(sw, TB_CL1)) {
if (tb_switch_disable_clx(sw, TB_CL1))
tb_sw_warn(sw, "failed to disable %s on upstream port\n",
tb_switch_clx_name(TB_CL1));
}
err = tb_plug_events_active(sw, false);
if (err)
@ -3426,13 +3430,12 @@ static bool tb_port_clx_supported(struct tb_port *port, enum tb_clx clx)
}
switch (clx) {
case TB_CL0S:
/* CL0s support requires also CL1 support */
case TB_CL1:
/* CL0s and CL1 are enabled and supported together */
mask = LANE_ADP_CS_0_CL0S_SUPPORT | LANE_ADP_CS_0_CL1_SUPPORT;
break;
/* For now we support only CL0s. Not CL1, CL2 */
case TB_CL1:
/* For now we support only CL0s and CL1. Not CL2 */
case TB_CL2:
default:
return false;
@ -3446,18 +3449,18 @@ static bool tb_port_clx_supported(struct tb_port *port, enum tb_clx clx)
return !!(val & mask);
}
static inline bool tb_port_cl0s_supported(struct tb_port *port)
{
return tb_port_clx_supported(port, TB_CL0S);
}
static int __tb_port_cl0s_set(struct tb_port *port, bool enable)
static int __tb_port_clx_set(struct tb_port *port, enum tb_clx clx, bool enable)
{
u32 phy, mask;
int ret;
/* To enable CL0s also required to enable CL1 */
mask = LANE_ADP_CS_1_CL0S_ENABLE | LANE_ADP_CS_1_CL1_ENABLE;
/* CL0s and CL1 are enabled and supported together */
if (clx == TB_CL1)
mask = LANE_ADP_CS_1_CL0S_ENABLE | LANE_ADP_CS_1_CL1_ENABLE;
else
/* For now we support only CL0s and CL1. Not CL2 */
return -EOPNOTSUPP;
ret = tb_port_read(port, &phy, TB_CFG_PORT,
port->cap_phy + LANE_ADP_CS_1, 1);
if (ret)
@ -3472,20 +3475,20 @@ static int __tb_port_cl0s_set(struct tb_port *port, bool enable)
port->cap_phy + LANE_ADP_CS_1, 1);
}
static int tb_port_cl0s_disable(struct tb_port *port)
static int tb_port_clx_disable(struct tb_port *port, enum tb_clx clx)
{
return __tb_port_cl0s_set(port, false);
return __tb_port_clx_set(port, clx, false);
}
static int tb_port_cl0s_enable(struct tb_port *port)
static int tb_port_clx_enable(struct tb_port *port, enum tb_clx clx)
{
return __tb_port_cl0s_set(port, true);
return __tb_port_clx_set(port, clx, true);
}
static int tb_switch_enable_cl0s(struct tb_switch *sw)
static int __tb_switch_enable_clx(struct tb_switch *sw, enum tb_clx clx)
{
struct tb_switch *parent = tb_switch_parent(sw);
bool up_cl0s_support, down_cl0s_support;
bool up_clx_support, down_clx_support;
struct tb_port *up, *down;
int ret;
@ -3510,37 +3513,37 @@ static int tb_switch_enable_cl0s(struct tb_switch *sw)
up = tb_upstream_port(sw);
down = tb_port_at(tb_route(sw), parent);
up_cl0s_support = tb_port_cl0s_supported(up);
down_cl0s_support = tb_port_cl0s_supported(down);
up_clx_support = tb_port_clx_supported(up, clx);
down_clx_support = tb_port_clx_supported(down, clx);
tb_port_dbg(up, "CL0s %ssupported\n",
up_cl0s_support ? "" : "not ");
tb_port_dbg(down, "CL0s %ssupported\n",
down_cl0s_support ? "" : "not ");
tb_port_dbg(up, "%s %ssupported\n", tb_switch_clx_name(clx),
up_clx_support ? "" : "not ");
tb_port_dbg(down, "%s %ssupported\n", tb_switch_clx_name(clx),
down_clx_support ? "" : "not ");
if (!up_cl0s_support || !down_cl0s_support)
if (!up_clx_support || !down_clx_support)
return -EOPNOTSUPP;
ret = tb_port_cl0s_enable(up);
ret = tb_port_clx_enable(up, clx);
if (ret)
return ret;
ret = tb_port_cl0s_enable(down);
ret = tb_port_clx_enable(down, clx);
if (ret) {
tb_port_cl0s_disable(up);
tb_port_clx_disable(up, clx);
return ret;
}
ret = tb_switch_mask_clx_objections(sw);
if (ret) {
tb_port_cl0s_disable(up);
tb_port_cl0s_disable(down);
tb_port_clx_disable(up, clx);
tb_port_clx_disable(down, clx);
return ret;
}
sw->clx = TB_CL0S;
sw->clx = clx;
tb_port_dbg(up, "CL0s enabled\n");
tb_port_dbg(up, "%s enabled\n", tb_switch_clx_name(clx));
return 0;
}
@ -3554,7 +3557,7 @@ static int tb_switch_enable_cl0s(struct tb_switch *sw)
* to improve performance. CLx is enabled only if both sides of the link
* support CLx, and if both sides of the link are not configured as two
* single lane links and only if the link is not inter-domain link. The
* complete set of conditions is descibed in CM Guide 1.0 section 8.1.
* complete set of conditions is described in CM Guide 1.0 section 8.1.
*
* Return: Returns 0 on success or an error code on failure.
*/
@ -3573,15 +3576,16 @@ int tb_switch_enable_clx(struct tb_switch *sw, enum tb_clx clx)
return 0;
switch (clx) {
case TB_CL0S:
return tb_switch_enable_cl0s(sw);
case TB_CL1:
/* CL0s and CL1 are enabled and supported together */
return __tb_switch_enable_clx(sw, clx);
default:
return -EOPNOTSUPP;
}
}
static int tb_switch_disable_cl0s(struct tb_switch *sw)
static int __tb_switch_disable_clx(struct tb_switch *sw, enum tb_clx clx)
{
struct tb_switch *parent = tb_switch_parent(sw);
struct tb_port *up, *down;
@ -3603,17 +3607,17 @@ static int tb_switch_disable_cl0s(struct tb_switch *sw)
up = tb_upstream_port(sw);
down = tb_port_at(tb_route(sw), parent);
ret = tb_port_cl0s_disable(up);
ret = tb_port_clx_disable(up, clx);
if (ret)
return ret;
ret = tb_port_cl0s_disable(down);
ret = tb_port_clx_disable(down, clx);
if (ret)
return ret;
sw->clx = TB_CLX_DISABLE;
tb_port_dbg(up, "CL0s disabled\n");
tb_port_dbg(up, "%s disabled\n", tb_switch_clx_name(clx));
return 0;
}
@ -3630,8 +3634,9 @@ int tb_switch_disable_clx(struct tb_switch *sw, enum tb_clx clx)
return 0;
switch (clx) {
case TB_CL0S:
return tb_switch_disable_cl0s(sw);
case TB_CL1:
/* CL0s and CL1 are enabled and supported together */
return __tb_switch_disable_clx(sw, clx);
default:
return -EOPNOTSUPP;

View File

@ -118,6 +118,13 @@ static void tb_switch_discover_tunnels(struct tb_switch *sw,
switch (port->config.type) {
case TB_TYPE_DP_HDMI_IN:
tunnel = tb_tunnel_discover_dp(tb, port, alloc_hopids);
/*
* In case of DP tunnel exists, change host router's
* 1st children TMU mode to HiFi for CL0s to work.
*/
if (tunnel)
tb_switch_enable_tmu_1st_child(tb->root_switch,
TB_SWITCH_TMU_RATE_HIFI);
break;
case TB_TYPE_PCIE_DOWN:
@ -215,7 +222,7 @@ static int tb_enable_tmu(struct tb_switch *sw)
int ret;
/* If it is already enabled in correct mode, don't touch it */
if (tb_switch_tmu_hifi_is_enabled(sw, sw->tmu.unidirectional_request))
if (tb_switch_tmu_is_enabled(sw, sw->tmu.unidirectional_request))
return 0;
ret = tb_switch_tmu_disable(sw);
@ -575,6 +582,7 @@ static void tb_scan_port(struct tb_port *port)
struct tb_cm *tcm = tb_priv(port->sw->tb);
struct tb_port *upstream_port;
struct tb_switch *sw;
int ret;
if (tb_is_upstream_port(port))
return;
@ -663,11 +671,24 @@ static void tb_scan_port(struct tb_port *port)
tb_switch_lane_bonding_enable(sw);
/* Set the link configured */
tb_switch_configure_link(sw);
if (tb_switch_enable_clx(sw, TB_CL0S))
tb_sw_warn(sw, "failed to enable CLx on upstream port\n");
/*
* CL0s and CL1 are enabled and supported together.
* Silently ignore CLx enabling in case CLx is not supported.
*/
ret = tb_switch_enable_clx(sw, TB_CL1);
if (ret && ret != -EOPNOTSUPP)
tb_sw_warn(sw, "failed to enable %s on upstream port\n",
tb_switch_clx_name(TB_CL1));
tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_HIFI,
tb_switch_is_clx_enabled(sw));
if (tb_switch_is_clx_enabled(sw, TB_CL1))
/*
* To support highest CLx state, we set router's TMU to
* Normal-Uni mode.
*/
tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_NORMAL, true);
else
/* If CLx disabled, configure router's TMU to HiFi-Bidir mode*/
tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_HIFI, false);
if (tb_enable_tmu(sw))
tb_sw_warn(sw, "failed to enable TMU\n");
@ -965,6 +986,12 @@ static void tb_tunnel_dp(struct tb *tb)
list_add_tail(&tunnel->list, &tcm->tunnel_list);
tb_reclaim_usb3_bandwidth(tb, in, out);
/*
* In case of DP tunnel exists, change host router's 1st children
* TMU mode to HiFi for CL0s to work.
*/
tb_switch_enable_tmu_1st_child(tb->root_switch, TB_SWITCH_TMU_RATE_HIFI);
return;
err_free:
@ -1407,7 +1434,12 @@ static int tb_start(struct tb *tb)
return ret;
}
tb_switch_tmu_configure(tb->root_switch, TB_SWITCH_TMU_RATE_HIFI, false);
/*
* To support highest CLx state, we set host router's TMU to
* Normal mode.
*/
tb_switch_tmu_configure(tb->root_switch, TB_SWITCH_TMU_RATE_NORMAL,
false);
/* Enable TMU if it is off */
tb_switch_tmu_enable(tb->root_switch);
/* Full scan to discover devices added before the driver was loaded. */
@ -1446,19 +1478,31 @@ static int tb_suspend_noirq(struct tb *tb)
static void tb_restore_children(struct tb_switch *sw)
{
struct tb_port *port;
int ret;
/* No need to restore if the router is already unplugged */
if (sw->is_unplugged)
return;
if (tb_switch_enable_clx(sw, TB_CL0S))
tb_sw_warn(sw, "failed to re-enable CLx on upstream port\n");
/*
* tb_switch_tmu_configure() was already called when the switch was
* added before entering system sleep or runtime suspend,
* so no need to call it again before enabling TMU.
* CL0s and CL1 are enabled and supported together.
* Silently ignore CLx re-enabling in case CLx is not supported.
*/
ret = tb_switch_enable_clx(sw, TB_CL1);
if (ret && ret != -EOPNOTSUPP)
tb_sw_warn(sw, "failed to re-enable %s on upstream port\n",
tb_switch_clx_name(TB_CL1));
if (tb_switch_is_clx_enabled(sw, TB_CL1))
/*
* To support highest CLx state, we set router's TMU to
* Normal-Uni mode.
*/
tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_NORMAL, true);
else
/* If CLx disabled, configure router's TMU to HiFi-Bidir mode*/
tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_HIFI, false);
if (tb_enable_tmu(sw))
tb_sw_warn(sw, "failed to restore TMU configuration\n");

View File

@ -13,6 +13,7 @@
#include <linux/pci.h>
#include <linux/thunderbolt.h>
#include <linux/uuid.h>
#include <linux/bitfield.h>
#include "tb_regs.h"
#include "ctl.h"
@ -111,7 +112,7 @@ struct tb_switch_tmu {
enum tb_clx {
TB_CLX_DISABLE,
TB_CL0S,
/* CL0s and CL1 are enabled and supported together */
TB_CL1,
TB_CL2,
};
@ -933,46 +934,49 @@ int tb_switch_tmu_enable(struct tb_switch *sw);
void tb_switch_tmu_configure(struct tb_switch *sw,
enum tb_switch_tmu_rate rate,
bool unidirectional);
void tb_switch_enable_tmu_1st_child(struct tb_switch *sw,
enum tb_switch_tmu_rate rate);
/**
* tb_switch_tmu_hifi_is_enabled() - Checks if the specified TMU mode is enabled
* tb_switch_tmu_is_enabled() - Checks if the specified TMU mode is enabled
* @sw: Router whose TMU mode to check
* @unidirectional: If uni-directional (bi-directional otherwise)
*
* Return true if hardware TMU configuration matches the one passed in
* as parameter. That is HiFi and either uni-directional or bi-directional.
* as parameter. That is HiFi/Normal and either uni-directional or bi-directional.
*/
static inline bool tb_switch_tmu_hifi_is_enabled(const struct tb_switch *sw,
bool unidirectional)
static inline bool tb_switch_tmu_is_enabled(const struct tb_switch *sw,
bool unidirectional)
{
return sw->tmu.rate == TB_SWITCH_TMU_RATE_HIFI &&
return sw->tmu.rate == sw->tmu.rate_request &&
sw->tmu.unidirectional == unidirectional;
}
static inline const char *tb_switch_clx_name(enum tb_clx clx)
{
switch (clx) {
/* CL0s and CL1 are enabled and supported together */
case TB_CL1:
return "CL0s/CL1";
default:
return "unknown";
}
}
int tb_switch_enable_clx(struct tb_switch *sw, enum tb_clx clx);
int tb_switch_disable_clx(struct tb_switch *sw, enum tb_clx clx);
/**
* tb_switch_is_clx_enabled() - Checks if the CLx is enabled
* @sw: Router to check the CLx state for
* @sw: Router to check for the CLx
* @clx: The CLx state to check for
*
* Checks if the CLx is enabled on the router upstream link.
* Checks if the specified CLx is enabled on the router upstream link.
* Not applicable for a host router.
*/
static inline bool tb_switch_is_clx_enabled(const struct tb_switch *sw)
static inline bool tb_switch_is_clx_enabled(const struct tb_switch *sw,
enum tb_clx clx)
{
return sw->clx != TB_CLX_DISABLE;
}
/**
* tb_switch_is_cl0s_enabled() - Checks if the CL0s is enabled
* @sw: Router to check for the CL0s
*
* Checks if the CL0s is enabled on the router upstream link.
* Not applicable for a host router.
*/
static inline bool tb_switch_is_cl0s_enabled(const struct tb_switch *sw)
{
return sw->clx == TB_CL0S;
return sw->clx == clx;
}
/**

View File

@ -234,6 +234,7 @@ enum usb4_switch_op {
/* Router TMU configuration */
#define TMU_RTR_CS_0 0x00
#define TMU_RTR_CS_0_FREQ_WIND_MASK GENMASK(26, 16)
#define TMU_RTR_CS_0_TD BIT(27)
#define TMU_RTR_CS_0_UCAP BIT(30)
#define TMU_RTR_CS_1 0x01
@ -244,6 +245,11 @@ enum usb4_switch_op {
#define TMU_RTR_CS_3_LOCAL_TIME_NS_MASK GENMASK(15, 0)
#define TMU_RTR_CS_3_TS_PACKET_INTERVAL_MASK GENMASK(31, 16)
#define TMU_RTR_CS_3_TS_PACKET_INTERVAL_SHIFT 16
#define TMU_RTR_CS_15 0xf
#define TMU_RTR_CS_15_FREQ_AVG_MASK GENMASK(5, 0)
#define TMU_RTR_CS_15_DELAY_AVG_MASK GENMASK(11, 6)
#define TMU_RTR_CS_15_OFFSET_AVG_MASK GENMASK(17, 12)
#define TMU_RTR_CS_15_ERROR_AVG_MASK GENMASK(23, 18)
#define TMU_RTR_CS_22 0x16
#define TMU_RTR_CS_24 0x18
#define TMU_RTR_CS_25 0x19

View File

@ -11,6 +11,55 @@
#include "tb.h"
static int tb_switch_set_tmu_mode_params(struct tb_switch *sw,
enum tb_switch_tmu_rate rate)
{
u32 freq_meas_wind[2] = { 30, 800 };
u32 avg_const[2] = { 4, 8 };
u32 freq, avg, val;
int ret;
if (rate == TB_SWITCH_TMU_RATE_NORMAL) {
freq = freq_meas_wind[0];
avg = avg_const[0];
} else if (rate == TB_SWITCH_TMU_RATE_HIFI) {
freq = freq_meas_wind[1];
avg = avg_const[1];
} else {
return 0;
}
ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
sw->tmu.cap + TMU_RTR_CS_0, 1);
if (ret)
return ret;
val &= ~TMU_RTR_CS_0_FREQ_WIND_MASK;
val |= FIELD_PREP(TMU_RTR_CS_0_FREQ_WIND_MASK, freq);
ret = tb_sw_write(sw, &val, TB_CFG_SWITCH,
sw->tmu.cap + TMU_RTR_CS_0, 1);
if (ret)
return ret;
ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
sw->tmu.cap + TMU_RTR_CS_15, 1);
if (ret)
return ret;
val &= ~TMU_RTR_CS_15_FREQ_AVG_MASK &
~TMU_RTR_CS_15_DELAY_AVG_MASK &
~TMU_RTR_CS_15_OFFSET_AVG_MASK &
~TMU_RTR_CS_15_ERROR_AVG_MASK;
val |= FIELD_PREP(TMU_RTR_CS_15_FREQ_AVG_MASK, avg) |
FIELD_PREP(TMU_RTR_CS_15_DELAY_AVG_MASK, avg) |
FIELD_PREP(TMU_RTR_CS_15_OFFSET_AVG_MASK, avg) |
FIELD_PREP(TMU_RTR_CS_15_ERROR_AVG_MASK, avg);
return tb_sw_write(sw, &val, TB_CFG_SWITCH,
sw->tmu.cap + TMU_RTR_CS_15, 1);
}
static const char *tb_switch_tmu_mode_name(const struct tb_switch *sw)
{
bool root_switch = !tb_route(sw);
@ -348,7 +397,7 @@ int tb_switch_tmu_disable(struct tb_switch *sw)
if (tb_route(sw)) {
bool unidirectional = tb_switch_tmu_hifi_is_enabled(sw, true);
bool unidirectional = sw->tmu.unidirectional;
struct tb_switch *parent = tb_switch_parent(sw);
struct tb_port *down, *up;
int ret;
@ -359,13 +408,14 @@ int tb_switch_tmu_disable(struct tb_switch *sw)
* In case of uni-directional time sync, TMU handshake is
* initiated by upstream router. In case of bi-directional
* time sync, TMU handshake is initiated by downstream router.
* Therefore, we change the rate to off in the respective
* router.
* We change downstream router's rate to off for both uni/bidir
* cases although it is needed only for the bi-directional mode.
* We avoid changing upstream router's mode since it might
* have another downstream router plugged, that is set to
* uni-directional mode and we don't want to change it's TMU
* mode.
*/
if (unidirectional)
tb_switch_tmu_rate_write(parent, TB_SWITCH_TMU_RATE_OFF);
else
tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF);
tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF);
tb_port_tmu_time_sync_disable(up);
ret = tb_port_tmu_time_sync_disable(down);
@ -411,6 +461,7 @@ static void __tb_switch_tmu_off(struct tb_switch *sw, bool unidirectional)
else
tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF);
tb_switch_set_tmu_mode_params(sw, sw->tmu.rate);
tb_port_tmu_unidirectional_disable(down);
tb_port_tmu_unidirectional_disable(up);
}
@ -492,7 +543,11 @@ static int __tb_switch_tmu_enable_unidirectional(struct tb_switch *sw)
up = tb_upstream_port(sw);
down = tb_port_at(tb_route(sw), parent);
ret = tb_switch_tmu_rate_write(parent, TB_SWITCH_TMU_RATE_HIFI);
ret = tb_switch_tmu_rate_write(parent, sw->tmu.rate_request);
if (ret)
return ret;
ret = tb_switch_set_tmu_mode_params(sw, sw->tmu.rate_request);
if (ret)
return ret;
@ -519,7 +574,83 @@ out:
return ret;
}
static int tb_switch_tmu_hifi_enable(struct tb_switch *sw)
static void __tb_switch_tmu_change_mode_prev(struct tb_switch *sw)
{
struct tb_switch *parent = tb_switch_parent(sw);
struct tb_port *down, *up;
down = tb_port_at(tb_route(sw), parent);
up = tb_upstream_port(sw);
/*
* In case of any failure in one of the steps when change mode,
* get back to the TMU configurations in previous mode.
* In case of additional failures in the functions below,
* ignore them since the caller shall already report a failure.
*/
tb_port_tmu_set_unidirectional(down, sw->tmu.unidirectional);
if (sw->tmu.unidirectional_request)
tb_switch_tmu_rate_write(parent, sw->tmu.rate);
else
tb_switch_tmu_rate_write(sw, sw->tmu.rate);
tb_switch_set_tmu_mode_params(sw, sw->tmu.rate);
tb_port_tmu_set_unidirectional(up, sw->tmu.unidirectional);
}
static int __tb_switch_tmu_change_mode(struct tb_switch *sw)
{
struct tb_switch *parent = tb_switch_parent(sw);
struct tb_port *up, *down;
int ret;
up = tb_upstream_port(sw);
down = tb_port_at(tb_route(sw), parent);
ret = tb_port_tmu_set_unidirectional(down, sw->tmu.unidirectional_request);
if (ret)
goto out;
if (sw->tmu.unidirectional_request)
ret = tb_switch_tmu_rate_write(parent, sw->tmu.rate_request);
else
ret = tb_switch_tmu_rate_write(sw, sw->tmu.rate_request);
if (ret)
return ret;
ret = tb_switch_set_tmu_mode_params(sw, sw->tmu.rate_request);
if (ret)
return ret;
ret = tb_port_tmu_set_unidirectional(up, sw->tmu.unidirectional_request);
if (ret)
goto out;
ret = tb_port_tmu_time_sync_enable(down);
if (ret)
goto out;
ret = tb_port_tmu_time_sync_enable(up);
if (ret)
goto out;
return 0;
out:
__tb_switch_tmu_change_mode_prev(sw);
return ret;
}
/**
* tb_switch_tmu_enable() - Enable TMU on a router
* @sw: Router whose TMU to enable
*
* Enables TMU of a router to be in uni-directional Normal/HiFi
* or bi-directional HiFi mode. Calling tb_switch_tmu_configure() is required
* before calling this function, to select the mode Normal/HiFi and
* directionality (uni-directional/bi-directional).
* In HiFi mode all tunneling should work. In Normal mode, DP tunneling can't
* work. Uni-directional mode is required for CLx (Link Low-Power) to work.
*/
int tb_switch_tmu_enable(struct tb_switch *sw)
{
bool unidirectional = sw->tmu.unidirectional_request;
int ret;
@ -535,12 +666,15 @@ static int tb_switch_tmu_hifi_enable(struct tb_switch *sw)
if (!tb_switch_is_clx_supported(sw))
return 0;
if (tb_switch_tmu_hifi_is_enabled(sw, sw->tmu.unidirectional_request))
if (tb_switch_tmu_is_enabled(sw, sw->tmu.unidirectional_request))
return 0;
if (tb_switch_is_titan_ridge(sw) && unidirectional) {
/* Titan Ridge supports only CL0s */
if (!tb_switch_is_cl0s_enabled(sw))
/*
* Titan Ridge supports CL0s and CL1 only. CL0s and CL1 are
* enabled and supported together.
*/
if (!tb_switch_is_clx_enabled(sw, TB_CL1))
return -EOPNOTSUPP;
ret = tb_switch_tmu_objection_mask(sw);
@ -557,7 +691,11 @@ static int tb_switch_tmu_hifi_enable(struct tb_switch *sw)
return ret;
if (tb_route(sw)) {
/* The used mode changes are from OFF to HiFi-Uni/HiFi-BiDir */
/*
* The used mode changes are from OFF to
* HiFi-Uni/HiFi-BiDir/Normal-Uni or from Normal-Uni to
* HiFi-Uni.
*/
if (sw->tmu.rate == TB_SWITCH_TMU_RATE_OFF) {
if (unidirectional)
ret = __tb_switch_tmu_enable_unidirectional(sw);
@ -565,6 +703,10 @@ static int tb_switch_tmu_hifi_enable(struct tb_switch *sw)
ret = __tb_switch_tmu_enable_bidirectional(sw);
if (ret)
return ret;
} else if (sw->tmu.rate == TB_SWITCH_TMU_RATE_NORMAL) {
ret = __tb_switch_tmu_change_mode(sw);
if (ret)
return ret;
}
sw->tmu.unidirectional = unidirectional;
} else {
@ -574,39 +716,21 @@ static int tb_switch_tmu_hifi_enable(struct tb_switch *sw)
* of the child node - see above.
* Here only the host router' rate configuration is written.
*/
ret = tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_HIFI);
ret = tb_switch_tmu_rate_write(sw, sw->tmu.rate_request);
if (ret)
return ret;
}
sw->tmu.rate = TB_SWITCH_TMU_RATE_HIFI;
sw->tmu.rate = sw->tmu.rate_request;
tb_sw_dbg(sw, "TMU: mode set to: %s\n", tb_switch_tmu_mode_name(sw));
return tb_switch_tmu_set_time_disruption(sw, false);
}
/**
* tb_switch_tmu_enable() - Enable TMU on a router
* @sw: Router whose TMU to enable
*
* Enables TMU of a router to be in uni-directional or bi-directional HiFi mode.
* Calling tb_switch_tmu_configure() is required before calling this function,
* to select the mode HiFi and directionality (uni-directional/bi-directional).
* In both modes all tunneling should work. Uni-directional mode is required for
* CLx (Link Low-Power) to work.
*/
int tb_switch_tmu_enable(struct tb_switch *sw)
{
if (sw->tmu.rate_request == TB_SWITCH_TMU_RATE_NORMAL)
return -EOPNOTSUPP;
return tb_switch_tmu_hifi_enable(sw);
}
/**
* tb_switch_tmu_configure() - Configure the TMU rate and directionality
* @sw: Router whose mode to change
* @rate: Rate to configure Off/LowRes/HiFi
* @rate: Rate to configure Off/Normal/HiFi
* @unidirectional: If uni-directional (bi-directional otherwise)
*
* Selects the rate of the TMU and directionality (uni-directional or
@ -618,3 +742,32 @@ void tb_switch_tmu_configure(struct tb_switch *sw,
sw->tmu.unidirectional_request = unidirectional;
sw->tmu.rate_request = rate;
}
static int tb_switch_tmu_config_enable(struct device *dev, void *rate)
{
if (tb_is_switch(dev)) {
struct tb_switch *sw = tb_to_switch(dev);
tb_switch_tmu_configure(sw, *(enum tb_switch_tmu_rate *)rate,
tb_switch_is_clx_enabled(sw, TB_CL1));
if (tb_switch_tmu_enable(sw))
tb_sw_dbg(sw, "fail switching TMU mode for 1st depth router\n");
}
return 0;
}
/**
* tb_switch_enable_tmu_1st_child - Configure and enable TMU for 1st chidren
* @sw: The router to configure and enable it's children TMU
* @rate: Rate of the TMU to configure the router's chidren to
*
* Configures and enables the TMU mode of 1st depth children of the specified
* router to the specified rate.
*/
void tb_switch_enable_tmu_1st_child(struct tb_switch *sw,
enum tb_switch_tmu_rate rate)
{
device_for_each_child(&sw->dev, &rate,
tb_switch_tmu_config_enable);
}

View File

@ -9,7 +9,7 @@
* HISTORY : some part of the code was base on ueagle 1.3 BSD driver,
* Damien Bergamini agree to put his code under a DUAL GPL/BSD license.
*
* The rest of the code was was rewritten from scratch.
* The rest of the code was rewritten from scratch.
*/
#include <linux/module.h>

View File

@ -220,7 +220,7 @@ int cdns3_allocate_trb_pool(struct cdns3_endpoint *priv_ep)
if (!priv_ep->trb_pool) {
priv_ep->trb_pool = dma_pool_alloc(priv_dev->eps_dma_pool,
GFP_DMA32 | GFP_ATOMIC,
GFP_ATOMIC,
&priv_ep->trb_pool_dma);
if (!priv_ep->trb_pool)
@ -625,9 +625,9 @@ static void cdns3_wa2_remove_old_request(struct cdns3_endpoint *priv_ep)
trace_cdns3_wa2(priv_ep, "removes eldest request");
kfree(priv_req->request.buf);
list_del_init(&priv_req->list);
cdns3_gadget_ep_free_request(&priv_ep->endpoint,
&priv_req->request);
list_del_init(&priv_req->list);
--priv_ep->wa2_counter;
if (!chain)
@ -2285,14 +2285,15 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep,
int val;
priv_ep = ep_to_cdns3_ep(ep);
priv_dev = priv_ep->cdns3_dev;
comp_desc = priv_ep->endpoint.comp_desc;
if (!ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT) {
dev_dbg(priv_dev->dev, "usbss: invalid parameters\n");
return -EINVAL;
}
comp_desc = priv_ep->endpoint.comp_desc;
priv_dev = priv_ep->cdns3_dev;
if (!desc->wMaxPacketSize) {
dev_err(priv_dev->dev, "usbss: missing wMaxPacketSize\n");
return -EINVAL;
@ -2600,7 +2601,7 @@ int cdns3_gadget_ep_dequeue(struct usb_ep *ep,
struct usb_request *request)
{
struct cdns3_endpoint *priv_ep = ep_to_cdns3_ep(ep);
struct cdns3_device *priv_dev = priv_ep->cdns3_dev;
struct cdns3_device *priv_dev;
struct usb_request *req, *req_temp;
struct cdns3_request *priv_req;
struct cdns3_trb *link_trb;
@ -2611,6 +2612,8 @@ int cdns3_gadget_ep_dequeue(struct usb_ep *ep,
if (!ep || !request || !ep->desc)
return -EINVAL;
priv_dev = priv_ep->cdns3_dev;
spin_lock_irqsave(&priv_dev->lock, flags);
priv_req = to_cdns3_request(request);

View File

@ -49,6 +49,7 @@ enum ci_hw_regs {
OP_USBCMD,
OP_USBSTS,
OP_USBINTR,
OP_FRINDEX,
OP_DEVICEADDR,
OP_ENDPTLISTADDR,
OP_TTCTRL,

View File

@ -348,25 +348,18 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
data->pinctrl = devm_pinctrl_get(dev);
if (PTR_ERR(data->pinctrl) == -ENODEV)
data->pinctrl = NULL;
else if (IS_ERR(data->pinctrl)) {
if (PTR_ERR(data->pinctrl) != -EPROBE_DEFER)
dev_err(dev, "pinctrl get failed, err=%ld\n",
PTR_ERR(data->pinctrl));
return PTR_ERR(data->pinctrl);
}
else if (IS_ERR(data->pinctrl))
return dev_err_probe(dev, PTR_ERR(data->pinctrl),
"pinctrl get failed\n");
data->hsic_pad_regulator =
devm_regulator_get_optional(dev, "hsic");
if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) {
/* no pad regualator is needed */
data->hsic_pad_regulator = NULL;
} else if (IS_ERR(data->hsic_pad_regulator)) {
if (PTR_ERR(data->hsic_pad_regulator) != -EPROBE_DEFER)
dev_err(dev,
"Get HSIC pad regulator error: %ld\n",
PTR_ERR(data->hsic_pad_regulator));
return PTR_ERR(data->hsic_pad_regulator);
}
} else if (IS_ERR(data->hsic_pad_regulator))
return dev_err_probe(dev, PTR_ERR(data->hsic_pad_regulator),
"Get HSIC pad regulator error\n");
if (data->hsic_pad_regulator) {
ret = regulator_enable(data->hsic_pad_regulator);
@ -458,9 +451,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
&pdata);
if (IS_ERR(data->ci_pdev)) {
ret = PTR_ERR(data->ci_pdev);
if (ret != -EPROBE_DEFER)
dev_err(dev, "ci_hdrc_add_device failed, err=%d\n",
ret);
dev_err_probe(dev, ret, "ci_hdrc_add_device failed\n");
goto err_clk;
}

View File

@ -21,7 +21,7 @@ struct imx_usbmisc_data {
unsigned int pwr_pol:1; /* power polarity */
unsigned int evdo:1; /* set external vbus divider option */
unsigned int ulpi:1; /* connected to an ULPI phy */
unsigned int hsic:1; /* HSIC controlller */
unsigned int hsic:1; /* HSIC controller */
unsigned int ext_id:1; /* ID from exteranl event */
unsigned int ext_vbus:1; /* Vbus from exteranl event */
struct usb_phy *usb_phy;

View File

@ -53,6 +53,7 @@ static const u8 ci_regs_nolpm[] = {
[OP_USBCMD] = 0x00U,
[OP_USBSTS] = 0x04U,
[OP_USBINTR] = 0x08U,
[OP_FRINDEX] = 0x0CU,
[OP_DEVICEADDR] = 0x14U,
[OP_ENDPTLISTADDR] = 0x18U,
[OP_TTCTRL] = 0x1CU,
@ -78,6 +79,7 @@ static const u8 ci_regs_lpm[] = {
[OP_USBCMD] = 0x00U,
[OP_USBSTS] = 0x04U,
[OP_USBINTR] = 0x08U,
[OP_FRINDEX] = 0x0CU,
[OP_DEVICEADDR] = 0x14U,
[OP_ENDPTLISTADDR] = 0x18U,
[OP_TTCTRL] = 0x1CU,

View File

@ -459,7 +459,7 @@ static void ci_otg_drv_vbus(struct otg_fsm *fsm, int on)
struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
if (on) {
/* Enable power power */
/* Enable power */
hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_PP,
PORTSC_PP);
if (ci->platdata->reg_vbus) {

View File

@ -1654,6 +1654,19 @@ static const struct usb_ep_ops usb_ep_ops = {
/******************************************************************************
* GADGET block
*****************************************************************************/
static int ci_udc_get_frame(struct usb_gadget *_gadget)
{
struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget);
unsigned long flags;
int ret;
spin_lock_irqsave(&ci->lock, flags);
ret = hw_read(ci, OP_FRINDEX, 0x3fff);
spin_unlock_irqrestore(&ci->lock, flags);
return ret >> 3;
}
/*
* ci_hdrc_gadget_connect: caller makes sure gadget driver is binded
*/
@ -1810,6 +1823,7 @@ static struct usb_ep *ci_udc_match_ep(struct usb_gadget *gadget,
* Check "usb_gadget.h" for details
*/
static const struct usb_gadget_ops usb_gadget_ops = {
.get_frame = ci_udc_get_frame,
.vbus_session = ci_udc_vbus_session,
.wakeup = ci_udc_wakeup,
.set_selfpowered = ci_udc_selfpowered,

View File

@ -119,7 +119,7 @@ static int acm_ctrl_msg(struct acm *acm, int request, int value,
retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
request, USB_RT_ACM, value,
acm->control->altsetting[0].desc.bInterfaceNumber,
buf, len, 5000);
buf, len, USB_CTRL_SET_TIMEOUT);
dev_dbg(&acm->control->dev,
"%s - rq 0x%02x, val %#x, len %#x, result %d\n",
@ -311,7 +311,7 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf)
dev_dbg(&acm->control->dev,
"%s - serial state: 0x%x\n", __func__, newctrl);
if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
if (!acm->clocal && (acm->ctrlin & ~newctrl & USB_CDC_SERIAL_STATE_DCD)) {
dev_dbg(&acm->control->dev,
"%s - calling hangup\n", __func__);
tty_port_tty_hangup(&acm->port, false);
@ -322,25 +322,25 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf)
acm->ctrlin = newctrl;
acm->oldcount = acm->iocount;
if (difference & ACM_CTRL_DSR)
if (difference & USB_CDC_SERIAL_STATE_DSR)
acm->iocount.dsr++;
if (difference & ACM_CTRL_DCD)
if (difference & USB_CDC_SERIAL_STATE_DCD)
acm->iocount.dcd++;
if (newctrl & ACM_CTRL_BRK) {
if (newctrl & USB_CDC_SERIAL_STATE_BREAK) {
acm->iocount.brk++;
tty_insert_flip_char(&acm->port, 0, TTY_BREAK);
}
if (newctrl & ACM_CTRL_RI)
if (newctrl & USB_CDC_SERIAL_STATE_RING_SIGNAL)
acm->iocount.rng++;
if (newctrl & ACM_CTRL_FRAMING)
if (newctrl & USB_CDC_SERIAL_STATE_FRAMING)
acm->iocount.frame++;
if (newctrl & ACM_CTRL_PARITY)
if (newctrl & USB_CDC_SERIAL_STATE_PARITY)
acm->iocount.parity++;
if (newctrl & ACM_CTRL_OVERRUN)
if (newctrl & USB_CDC_SERIAL_STATE_OVERRUN)
acm->iocount.overrun++;
spin_unlock_irqrestore(&acm->read_lock, flags);
if (newctrl & ACM_CTRL_BRK)
if (newctrl & USB_CDC_SERIAL_STATE_BREAK)
tty_flip_buffer_push(&acm->port);
if (difference)
@ -658,7 +658,7 @@ static void acm_port_dtr_rts(struct tty_port *port, int raise)
int res;
if (raise)
val = ACM_CTRL_DTR | ACM_CTRL_RTS;
val = USB_CDC_CTRL_DTR | USB_CDC_CTRL_RTS;
else
val = 0;
@ -903,11 +903,11 @@ static int acm_tty_tiocmget(struct tty_struct *tty)
{
struct acm *acm = tty->driver_data;
return (acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) |
(acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) |
(acm->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) |
(acm->ctrlin & ACM_CTRL_RI ? TIOCM_RI : 0) |
(acm->ctrlin & ACM_CTRL_DCD ? TIOCM_CD : 0) |
return (acm->ctrlout & USB_CDC_CTRL_DTR ? TIOCM_DTR : 0) |
(acm->ctrlout & USB_CDC_CTRL_RTS ? TIOCM_RTS : 0) |
(acm->ctrlin & USB_CDC_SERIAL_STATE_DSR ? TIOCM_DSR : 0) |
(acm->ctrlin & USB_CDC_SERIAL_STATE_RING_SIGNAL ? TIOCM_RI : 0) |
(acm->ctrlin & USB_CDC_SERIAL_STATE_DCD ? TIOCM_CD : 0) |
TIOCM_CTS;
}
@ -918,10 +918,10 @@ static int acm_tty_tiocmset(struct tty_struct *tty,
unsigned int newctrl;
newctrl = acm->ctrlout;
set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) |
(set & TIOCM_RTS ? ACM_CTRL_RTS : 0);
clear = (clear & TIOCM_DTR ? ACM_CTRL_DTR : 0) |
(clear & TIOCM_RTS ? ACM_CTRL_RTS : 0);
set = (set & TIOCM_DTR ? USB_CDC_CTRL_DTR : 0) |
(set & TIOCM_RTS ? USB_CDC_CTRL_RTS : 0);
clear = (clear & TIOCM_DTR ? USB_CDC_CTRL_DTR : 0) |
(clear & TIOCM_RTS ? USB_CDC_CTRL_RTS : 0);
newctrl = (newctrl & ~clear) | set;
@ -1068,9 +1068,9 @@ static void acm_tty_set_termios(struct tty_struct *tty,
if (C_BAUD(tty) == B0) {
newline.dwDTERate = acm->line.dwDTERate;
newctrl &= ~ACM_CTRL_DTR;
newctrl &= ~USB_CDC_CTRL_DTR;
} else if (termios_old && (termios_old->c_cflag & CBAUD) == B0) {
newctrl |= ACM_CTRL_DTR;
newctrl |= USB_CDC_CTRL_DTR;
}
if (newctrl != acm->ctrlout)

View File

@ -22,26 +22,6 @@
#define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
/*
* Output control lines.
*/
#define ACM_CTRL_DTR 0x01
#define ACM_CTRL_RTS 0x02
/*
* Input control lines and line errors.
*/
#define ACM_CTRL_DCD 0x01
#define ACM_CTRL_DSR 0x02
#define ACM_CTRL_BRK 0x04
#define ACM_CTRL_RI 0x08
#define ACM_CTRL_FRAMING 0x10
#define ACM_CTRL_PARITY 0x20
#define ACM_CTRL_OVERRUN 0x40
/*
* Internal driver structures.
*/

View File

@ -257,6 +257,7 @@ static int usb_conn_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, info);
device_set_wakeup_capable(&pdev->dev, true);
/* Perform initial detection */
usb_conn_queue_dwork(info, 0);
@ -286,6 +287,14 @@ static int __maybe_unused usb_conn_suspend(struct device *dev)
{
struct usb_conn_info *info = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) {
if (info->id_gpiod)
enable_irq_wake(info->id_irq);
if (info->vbus_gpiod)
enable_irq_wake(info->vbus_irq);
return 0;
}
if (info->id_gpiod)
disable_irq(info->id_irq);
if (info->vbus_gpiod)
@ -300,6 +309,14 @@ static int __maybe_unused usb_conn_resume(struct device *dev)
{
struct usb_conn_info *info = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) {
if (info->id_gpiod)
disable_irq_wake(info->id_irq);
if (info->vbus_gpiod)
disable_irq_wake(info->vbus_irq);
return 0;
}
pinctrl_pm_select_default_state(dev);
if (info->id_gpiod)

View File

@ -12,6 +12,10 @@ usbcore-$(CONFIG_OF) += of.o
usbcore-$(CONFIG_USB_PCI) += hcd-pci.o
usbcore-$(CONFIG_ACPI) += usb-acpi.o
ifdef CONFIG_USB_ONBOARD_HUB
usbcore-y += ../misc/onboard_usb_hub_pdevs.o
endif
obj-$(CONFIG_USB) += usbcore.o
obj-$(CONFIG_USB_LEDS_TRIGGER_USBPORT) += ledtrig-usbport.o

View File

@ -1482,7 +1482,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
* @msg: Power Management message describing this state transition
*
* This is the central routine for resuming USB devices. It calls the
* the resume method for @udev and then calls the resume methods for all
* resume method for @udev and then calls the resume methods for all
* the interface drivers in @udev.
*
* Autoresume requests originating from a child device or an interface

View File

@ -1691,7 +1691,6 @@ static void usb_giveback_urb_bh(struct tasklet_struct *t)
spin_lock_irq(&bh->lock);
bh->running = true;
restart:
list_replace_init(&bh->head, &local_list);
spin_unlock_irq(&bh->lock);
@ -1705,10 +1704,17 @@ static void usb_giveback_urb_bh(struct tasklet_struct *t)
bh->completing_ep = NULL;
}
/* check if there are new URBs to giveback */
/*
* giveback new URBs next time to prevent this function
* from not exiting for a long time.
*/
spin_lock_irq(&bh->lock);
if (!list_empty(&bh->head))
goto restart;
if (!list_empty(&bh->head)) {
if (bh->high_prio)
tasklet_hi_schedule(&bh->bh);
else
tasklet_schedule(&bh->bh);
}
bh->running = false;
spin_unlock_irq(&bh->lock);
}
@ -1737,7 +1743,7 @@ static void usb_giveback_urb_bh(struct tasklet_struct *t)
void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
{
struct giveback_urb_bh *bh;
bool running, high_prio_bh;
bool running;
/* pass status to tasklet via unlinked */
if (likely(!urb->unlinked))
@ -1748,13 +1754,10 @@ void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
return;
}
if (usb_pipeisoc(urb->pipe) || usb_pipeint(urb->pipe)) {
if (usb_pipeisoc(urb->pipe) || usb_pipeint(urb->pipe))
bh = &hcd->high_prio_bh;
high_prio_bh = true;
} else {
else
bh = &hcd->low_prio_bh;
high_prio_bh = false;
}
spin_lock(&bh->lock);
list_add_tail(&urb->urb_list, &bh->head);
@ -1763,7 +1766,7 @@ void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
if (running)
;
else if (high_prio_bh)
else if (bh->high_prio)
tasklet_hi_schedule(&bh->bh);
else
tasklet_schedule(&bh->bh);
@ -2959,6 +2962,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
/* initialize tasklets */
init_giveback_urb_bh(&hcd->high_prio_bh);
hcd->high_prio_bh.high_prio = true;
init_giveback_urb_bh(&hcd->low_prio_bh);
/* enable irqs just before we start the controller,
@ -3033,9 +3037,15 @@ EXPORT_SYMBOL_GPL(usb_add_hcd);
*/
void usb_remove_hcd(struct usb_hcd *hcd)
{
struct usb_device *rhdev = hcd->self.root_hub;
struct usb_device *rhdev;
bool rh_registered;
if (!hcd) {
pr_debug("%s: hcd is NULL\n", __func__);
return;
}
rhdev = hcd->self.root_hub;
dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
usb_get_dev(rhdev);

View File

@ -23,6 +23,7 @@
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
#include <linux/usb/hcd.h>
#include <linux/usb/onboard_hub.h>
#include <linux/usb/otg.h>
#include <linux/usb/quirks.h>
#include <linux/workqueue.h>
@ -613,7 +614,7 @@ static int hub_ext_port_status(struct usb_hub *hub, int port1, int type,
return ret;
}
static int hub_port_status(struct usb_hub *hub, int port1,
int usb_hub_port_status(struct usb_hub *hub, int port1,
u16 *status, u16 *change)
{
return hub_ext_port_status(hub, port1, HUB_PORT_STATUS,
@ -1126,7 +1127,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
u16 portstatus, portchange;
portstatus = portchange = 0;
status = hub_port_status(hub, port1, &portstatus, &portchange);
status = usb_hub_port_status(hub, port1, &portstatus, &portchange);
if (status)
goto abort;
@ -1752,6 +1753,8 @@ static void hub_disconnect(struct usb_interface *intf)
if (hub->quirk_disable_autosuspend)
usb_autopm_put_interface(intf);
onboard_hub_destroy_pdevs(&hub->onboard_hub_devs);
kref_put(&hub->kref, hub_release);
}
@ -1869,6 +1872,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
INIT_DELAYED_WORK(&hub->leds, led_work);
INIT_DELAYED_WORK(&hub->init_work, NULL);
INIT_WORK(&hub->events, hub_event);
INIT_LIST_HEAD(&hub->onboard_hub_devs);
spin_lock_init(&hub->irq_urb_lock);
timer_setup(&hub->irq_urb_retry, hub_retry_irq_urb, 0);
usb_get_intf(intf);
@ -1889,8 +1893,11 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
usb_autopm_get_interface_no_resume(intf);
}
if (hub_configure(hub, &desc->endpoint[0].desc) >= 0)
if (hub_configure(hub, &desc->endpoint[0].desc) >= 0) {
onboard_hub_create_pdevs(hdev, &hub->onboard_hub_devs);
return 0;
}
hub_disconnect(intf);
return -ENODEV;
@ -2855,7 +2862,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
&portstatus, &portchange,
&ext_portstatus);
else
ret = hub_port_status(hub, port1, &portstatus,
ret = usb_hub_port_status(hub, port1, &portstatus,
&portchange);
if (ret < 0)
return ret;
@ -2956,7 +2963,8 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
* If the caller hasn't explicitly requested a warm reset,
* double check and see if one is needed.
*/
if (hub_port_status(hub, port1, &portstatus, &portchange) == 0)
if (usb_hub_port_status(hub, port1, &portstatus,
&portchange) == 0)
if (hub_port_warm_reset_required(hub, port1,
portstatus))
warm = true;
@ -3008,7 +3016,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
* If a USB 3.0 device migrates from reset to an error
* state, re-issue the warm reset.
*/
if (hub_port_status(hub, port1,
if (usb_hub_port_status(hub, port1,
&portstatus, &portchange) < 0)
goto done;
@ -3074,7 +3082,7 @@ done:
}
/* Check if a port is power on */
static int port_is_power_on(struct usb_hub *hub, unsigned portstatus)
int usb_port_is_power_on(struct usb_hub *hub, unsigned int portstatus)
{
int ret = 0;
@ -3140,13 +3148,13 @@ static int check_port_resume_type(struct usb_device *udev,
}
/* Is the device still present? */
else if (status || port_is_suspended(hub, portstatus) ||
!port_is_power_on(hub, portstatus)) {
!usb_port_is_power_on(hub, portstatus)) {
if (status >= 0)
status = -ENODEV;
} else if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
if (retries--) {
usleep_range(200, 300);
status = hub_port_status(hub, port1, &portstatus,
status = usb_hub_port_status(hub, port1, &portstatus,
&portchange);
goto retry;
}
@ -3409,7 +3417,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
u16 portstatus, portchange;
portstatus = portchange = 0;
ret = hub_port_status(hub, port1, &portstatus,
ret = usb_hub_port_status(hub, port1, &portstatus,
&portchange);
dev_dbg(&port_dev->dev,
@ -3587,13 +3595,13 @@ static int wait_for_connected(struct usb_device *udev,
while (delay_ms < 2000) {
if (status || *portstatus & USB_PORT_STAT_CONNECTION)
break;
if (!port_is_power_on(hub, *portstatus)) {
if (!usb_port_is_power_on(hub, *portstatus)) {
status = -ENODEV;
break;
}
msleep(20);
delay_ms += 20;
status = hub_port_status(hub, port1, portstatus, portchange);
status = usb_hub_port_status(hub, port1, portstatus, portchange);
}
dev_dbg(&udev->dev, "Waited %dms for CONNECT\n", delay_ms);
return status;
@ -3653,7 +3661,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
usb_lock_port(port_dev);
/* Skip the initial Clear-Suspend step for a remote wakeup */
status = hub_port_status(hub, port1, &portstatus, &portchange);
status = usb_hub_port_status(hub, port1, &portstatus, &portchange);
if (status == 0 && !port_is_suspended(hub, portstatus)) {
if (portchange & USB_PORT_STAT_C_SUSPEND)
pm_wakeup_event(&udev->dev, 0);
@ -3678,7 +3686,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
* stop resume signaling. Then finish the resume
* sequence.
*/
status = hub_port_status(hub, port1, &portstatus, &portchange);
status = usb_hub_port_status(hub, port1, &portstatus, &portchange);
}
SuspendCleared:
@ -3791,7 +3799,7 @@ static int check_ports_changed(struct usb_hub *hub)
u16 portstatus, portchange;
int status;
status = hub_port_status(hub, port1, &portstatus, &portchange);
status = usb_hub_port_status(hub, port1, &portstatus, &portchange);
if (!status && portchange)
return 1;
}
@ -3946,7 +3954,7 @@ static const char * const usb3_lpm_names[] = {
* This function will fail if the SEL or PEL values for udev are greater than
* the maximum allowed values for the link state to be enabled.
*/
static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state)
static int usb_req_set_sel(struct usb_device *udev)
{
struct usb_set_sel_req *sel_values;
unsigned long long u1_sel;
@ -3955,7 +3963,7 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state)
unsigned long long u2_pel;
int ret;
if (udev->state != USB_STATE_CONFIGURED)
if (!udev->parent || udev->speed < USB_SPEED_SUPER || !udev->lpm_capable)
return 0;
/* Convert SEL and PEL stored in ns to us */
@ -3972,34 +3980,14 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state)
* latency for the link state, and could start a device-initiated
* U1/U2 when the exit latencies are too high.
*/
if ((state == USB3_LPM_U1 &&
(u1_sel > USB3_LPM_MAX_U1_SEL_PEL ||
u1_pel > USB3_LPM_MAX_U1_SEL_PEL)) ||
(state == USB3_LPM_U2 &&
(u2_sel > USB3_LPM_MAX_U2_SEL_PEL ||
u2_pel > USB3_LPM_MAX_U2_SEL_PEL))) {
dev_dbg(&udev->dev, "Device-initiated %s disabled due to long SEL %llu us or PEL %llu us\n",
usb3_lpm_names[state], u1_sel, u1_pel);
if (u1_sel > USB3_LPM_MAX_U1_SEL_PEL ||
u1_pel > USB3_LPM_MAX_U1_SEL_PEL ||
u2_sel > USB3_LPM_MAX_U2_SEL_PEL ||
u2_pel > USB3_LPM_MAX_U2_SEL_PEL) {
dev_dbg(&udev->dev, "Device-initiated U1/U2 disabled due to long SEL or PEL\n");
return -EINVAL;
}
/*
* If we're enabling device-initiated LPM for one link state,
* but the other link state has a too high SEL or PEL value,
* just set those values to the max in the Set SEL request.
*/
if (u1_sel > USB3_LPM_MAX_U1_SEL_PEL)
u1_sel = USB3_LPM_MAX_U1_SEL_PEL;
if (u1_pel > USB3_LPM_MAX_U1_SEL_PEL)
u1_pel = USB3_LPM_MAX_U1_SEL_PEL;
if (u2_sel > USB3_LPM_MAX_U2_SEL_PEL)
u2_sel = USB3_LPM_MAX_U2_SEL_PEL;
if (u2_pel > USB3_LPM_MAX_U2_SEL_PEL)
u2_pel = USB3_LPM_MAX_U2_SEL_PEL;
/*
* usb_enable_lpm() can be called as part of a failed device reset,
* which may be initiated by an error path of a mass storage driver.
@ -4021,6 +4009,10 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state)
sel_values, sizeof *(sel_values),
USB_CTRL_SET_TIMEOUT);
kfree(sel_values);
if (ret > 0)
udev->lpm_devinit_allow = 1;
return ret;
}
@ -4136,6 +4128,9 @@ static bool usb_device_may_initiate_lpm(struct usb_device *udev,
unsigned int sel; /* us */
int i, j;
if (!udev->lpm_devinit_allow)
return false;
if (state == USB3_LPM_U1)
sel = DIV_ROUND_UP(udev->u1_params.sel, 1000);
else if (state == USB3_LPM_U2)
@ -4184,7 +4179,7 @@ static bool usb_device_may_initiate_lpm(struct usb_device *udev,
static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
enum usb3_link_state state)
{
int timeout, ret;
int timeout;
__u8 u1_mel = udev->bos->ss_cap->bU1devExitLat;
__le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat;
@ -4196,17 +4191,6 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
(state == USB3_LPM_U2 && u2_mel == 0))
return;
/*
* First, let the device know about the exit latencies
* associated with the link state we're about to enable.
*/
ret = usb_req_set_sel(udev, state);
if (ret < 0) {
dev_warn(&udev->dev, "Set SEL for device-initiated %s failed.\n",
usb3_lpm_names[state]);
return;
}
/* We allow the host controller to set the U1/U2 timeout internally
* first, so that it can change its schedule to account for the
* additional latency to send data to a device in a lower power
@ -4486,6 +4470,11 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,
return 0;
}
static int usb_req_set_sel(struct usb_device *udev)
{
return 0;
}
#endif /* CONFIG_PM */
/*
@ -4554,7 +4543,7 @@ int hub_port_debounce(struct usb_hub *hub, int port1, bool must_be_connected)
struct usb_port *port_dev = hub->ports[port1 - 1];
for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {
ret = hub_port_status(hub, port1, &portstatus, &portchange);
ret = usb_hub_port_status(hub, port1, &portstatus, &portchange);
if (ret < 0)
return ret;
@ -5011,6 +5000,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
udev->lpm_capable = usb_device_supports_lpm(udev);
udev->lpm_disable_count = 1;
usb_set_lpm_parameters(udev);
usb_req_set_sel(udev);
}
}
@ -5240,7 +5230,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
* but only if the port isn't owned by someone else.
*/
if (hub_is_port_power_switchable(hub)
&& !port_is_power_on(hub, portstatus)
&& !usb_port_is_power_on(hub, portstatus)
&& !port_dev->port_owner)
set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
@ -5557,7 +5547,7 @@ static void port_event(struct usb_hub *hub, int port1)
clear_bit(port1, hub->event_bits);
clear_bit(port1, hub->wakeup_bits);
if (hub_port_status(hub, port1, &portstatus, &portchange) < 0)
if (usb_hub_port_status(hub, port1, &portstatus, &portchange) < 0)
return;
if (portchange & USB_PORT_STAT_C_CONNECTION) {
@ -5594,7 +5584,7 @@ static void port_event(struct usb_hub *hub, int port1)
USB_PORT_FEAT_C_OVER_CURRENT);
msleep(100); /* Cool down */
hub_power_on(hub, true);
hub_port_status(hub, port1, &status, &unused);
usb_hub_port_status(hub, port1, &status, &unused);
if (status & USB_PORT_STAT_OVERCURRENT)
dev_err(&port_dev->dev, "over-current condition\n");
}
@ -5638,7 +5628,7 @@ static void port_event(struct usb_hub *hub, int port1)
u16 unused;
msleep(20);
hub_port_status(hub, port1, &portstatus, &unused);
usb_hub_port_status(hub, port1, &portstatus, &unused);
dev_dbg(&port_dev->dev, "Wait for inactive link disconnect detect\n");
continue;
} else if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION)

View File

@ -73,6 +73,7 @@ struct usb_hub {
spinlock_t irq_urb_lock;
struct timer_list irq_urb_retry;
struct usb_port **ports;
struct list_head onboard_hub_devs;
};
/**
@ -121,6 +122,9 @@ extern int hub_port_debounce(struct usb_hub *hub, int port1,
bool must_be_connected);
extern int usb_clear_port_feature(struct usb_device *hdev,
int port1, int feature);
extern int usb_hub_port_status(struct usb_hub *hub, int port1,
u16 *status, u16 *change);
extern int usb_port_is_power_on(struct usb_hub *hub, unsigned int portstatus);
static inline bool hub_is_port_power_switchable(struct usb_hub *hub)
{

View File

@ -17,6 +17,88 @@ static int usb_port_block_power_off;
static const struct attribute_group *port_dev_group[];
static ssize_t disable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_port *port_dev = to_usb_port(dev);
struct usb_device *hdev = to_usb_device(dev->parent->parent);
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
struct usb_interface *intf = to_usb_interface(hub->intfdev);
int port1 = port_dev->portnum;
u16 portstatus, unused;
bool disabled;
int rc;
rc = usb_autopm_get_interface(intf);
if (rc < 0)
return rc;
usb_lock_device(hdev);
if (hub->disconnected) {
rc = -ENODEV;
goto out_hdev_lock;
}
usb_hub_port_status(hub, port1, &portstatus, &unused);
disabled = !usb_port_is_power_on(hub, portstatus);
out_hdev_lock:
usb_unlock_device(hdev);
usb_autopm_put_interface(intf);
if (rc)
return rc;
return sysfs_emit(buf, "%s\n", disabled ? "1" : "0");
}
static ssize_t disable_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct usb_port *port_dev = to_usb_port(dev);
struct usb_device *hdev = to_usb_device(dev->parent->parent);
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
struct usb_interface *intf = to_usb_interface(hub->intfdev);
int port1 = port_dev->portnum;
bool disabled;
int rc;
rc = strtobool(buf, &disabled);
if (rc)
return rc;
rc = usb_autopm_get_interface(intf);
if (rc < 0)
return rc;
usb_lock_device(hdev);
if (hub->disconnected) {
rc = -ENODEV;
goto out_hdev_lock;
}
if (disabled && port_dev->child)
usb_disconnect(&port_dev->child);
rc = usb_hub_set_port_power(hdev, hub, port1, !disabled);
if (disabled) {
usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION);
if (!port_dev->is_superspeed)
usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);
}
if (!rc)
rc = count;
out_hdev_lock:
usb_unlock_device(hdev);
usb_autopm_put_interface(intf);
return rc;
}
static DEVICE_ATTR_RW(disable);
static ssize_t location_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@ -153,6 +235,7 @@ static struct attribute *port_dev_attrs[] = {
&dev_attr_location.attr,
&dev_attr_quirks.attr,
&dev_attr_over_current_count.attr,
&dev_attr_disable.attr,
NULL,
};

View File

@ -35,7 +35,7 @@ static ssize_t field##_show(struct device *dev, \
return -EINTR; \
actconfig = udev->actconfig; \
if (actconfig) \
rc = sprintf(buf, format_string, \
rc = sysfs_emit(buf, format_string, \
actconfig->desc.field); \
usb_unlock_device(udev); \
return rc; \
@ -61,7 +61,7 @@ static ssize_t bMaxPower_show(struct device *dev,
return -EINTR;
actconfig = udev->actconfig;
if (actconfig)
rc = sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig));
rc = sysfs_emit(buf, "%dmA\n", usb_get_max_power(udev, actconfig));
usb_unlock_device(udev);
return rc;
}
@ -80,7 +80,7 @@ static ssize_t configuration_show(struct device *dev,
return -EINTR;
actconfig = udev->actconfig;
if (actconfig && actconfig->string)
rc = sprintf(buf, "%s\n", actconfig->string);
rc = sysfs_emit(buf, "%s\n", actconfig->string);
usb_unlock_device(udev);
return rc;
}
@ -114,7 +114,7 @@ static ssize_t devspec_show(struct device *dev, struct device_attribute *attr,
{
struct device_node *of_node = dev->of_node;
return sprintf(buf, "%pOF\n", of_node);
return sysfs_emit(buf, "%pOF\n", of_node);
}
static DEVICE_ATTR_RO(devspec);
#endif
@ -131,7 +131,7 @@ static ssize_t name##_show(struct device *dev, \
retval = usb_lock_device_interruptible(udev); \
if (retval < 0) \
return -EINTR; \
retval = sprintf(buf, "%s\n", udev->name); \
retval = sysfs_emit(buf, "%s\n", udev->name); \
usb_unlock_device(udev); \
return retval; \
} \
@ -175,7 +175,7 @@ static ssize_t speed_show(struct device *dev, struct device_attribute *attr,
default:
speed = "unknown";
}
return sprintf(buf, "%s\n", speed);
return sysfs_emit(buf, "%s\n", speed);
}
static DEVICE_ATTR_RO(speed);
@ -185,7 +185,7 @@ static ssize_t rx_lanes_show(struct device *dev, struct device_attribute *attr,
struct usb_device *udev;
udev = to_usb_device(dev);
return sprintf(buf, "%d\n", udev->rx_lanes);
return sysfs_emit(buf, "%d\n", udev->rx_lanes);
}
static DEVICE_ATTR_RO(rx_lanes);
@ -195,7 +195,7 @@ static ssize_t tx_lanes_show(struct device *dev, struct device_attribute *attr,
struct usb_device *udev;
udev = to_usb_device(dev);
return sprintf(buf, "%d\n", udev->tx_lanes);
return sysfs_emit(buf, "%d\n", udev->tx_lanes);
}
static DEVICE_ATTR_RO(tx_lanes);
@ -205,7 +205,7 @@ static ssize_t busnum_show(struct device *dev, struct device_attribute *attr,
struct usb_device *udev;
udev = to_usb_device(dev);
return sprintf(buf, "%d\n", udev->bus->busnum);
return sysfs_emit(buf, "%d\n", udev->bus->busnum);
}
static DEVICE_ATTR_RO(busnum);
@ -215,7 +215,7 @@ static ssize_t devnum_show(struct device *dev, struct device_attribute *attr,
struct usb_device *udev;
udev = to_usb_device(dev);
return sprintf(buf, "%d\n", udev->devnum);
return sysfs_emit(buf, "%d\n", udev->devnum);
}
static DEVICE_ATTR_RO(devnum);
@ -225,7 +225,7 @@ static ssize_t devpath_show(struct device *dev, struct device_attribute *attr,
struct usb_device *udev;
udev = to_usb_device(dev);
return sprintf(buf, "%s\n", udev->devpath);
return sysfs_emit(buf, "%s\n", udev->devpath);
}
static DEVICE_ATTR_RO(devpath);
@ -237,7 +237,7 @@ static ssize_t version_show(struct device *dev, struct device_attribute *attr,
udev = to_usb_device(dev);
bcdUSB = le16_to_cpu(udev->descriptor.bcdUSB);
return sprintf(buf, "%2x.%02x\n", bcdUSB >> 8, bcdUSB & 0xff);
return sysfs_emit(buf, "%2x.%02x\n", bcdUSB >> 8, bcdUSB & 0xff);
}
static DEVICE_ATTR_RO(version);
@ -247,7 +247,7 @@ static ssize_t maxchild_show(struct device *dev, struct device_attribute *attr,
struct usb_device *udev;
udev = to_usb_device(dev);
return sprintf(buf, "%d\n", udev->maxchild);
return sysfs_emit(buf, "%d\n", udev->maxchild);
}
static DEVICE_ATTR_RO(maxchild);
@ -257,7 +257,7 @@ static ssize_t quirks_show(struct device *dev, struct device_attribute *attr,
struct usb_device *udev;
udev = to_usb_device(dev);
return sprintf(buf, "0x%x\n", udev->quirks);
return sysfs_emit(buf, "0x%x\n", udev->quirks);
}
static DEVICE_ATTR_RO(quirks);
@ -267,7 +267,7 @@ static ssize_t avoid_reset_quirk_show(struct device *dev,
struct usb_device *udev;
udev = to_usb_device(dev);
return sprintf(buf, "%d\n", !!(udev->quirks & USB_QUIRK_RESET));
return sysfs_emit(buf, "%d\n", !!(udev->quirks & USB_QUIRK_RESET));
}
static ssize_t avoid_reset_quirk_store(struct device *dev,
@ -297,7 +297,7 @@ static ssize_t urbnum_show(struct device *dev, struct device_attribute *attr,
struct usb_device *udev;
udev = to_usb_device(dev);
return sprintf(buf, "%d\n", atomic_read(&udev->urbnum));
return sysfs_emit(buf, "%d\n", atomic_read(&udev->urbnum));
}
static DEVICE_ATTR_RO(urbnum);
@ -305,8 +305,8 @@ 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");
return sysfs_emit(buf, "%s\n", "yes");
return sysfs_emit(buf, "%s\n", "no");
}
static DEVICE_ATTR_RO(ltm_capable);
@ -317,7 +317,7 @@ static ssize_t persist_show(struct device *dev, struct device_attribute *attr,
{
struct usb_device *udev = to_usb_device(dev);
return sprintf(buf, "%d\n", udev->persist_enabled);
return sysfs_emit(buf, "%d\n", udev->persist_enabled);
}
static ssize_t persist_store(struct device *dev, struct device_attribute *attr,
@ -372,7 +372,7 @@ static ssize_t connected_duration_show(struct device *dev,
{
struct usb_device *udev = to_usb_device(dev);
return sprintf(buf, "%u\n",
return sysfs_emit(buf, "%u\n",
jiffies_to_msecs(jiffies - udev->connect_time));
}
static DEVICE_ATTR_RO(connected_duration);
@ -394,14 +394,14 @@ static ssize_t active_duration_show(struct device *dev,
duration = jiffies_to_msecs(jiffies + udev->active_duration);
else
duration = jiffies_to_msecs(udev->active_duration);
return sprintf(buf, "%u\n", duration);
return sysfs_emit(buf, "%u\n", duration);
}
static DEVICE_ATTR_RO(active_duration);
static ssize_t autosuspend_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", dev->power.autosuspend_delay / 1000);
return sysfs_emit(buf, "%d\n", dev->power.autosuspend_delay / 1000);
}
static ssize_t autosuspend_store(struct device *dev,
@ -442,7 +442,7 @@ static ssize_t level_show(struct device *dev, struct device_attribute *attr,
warn_level();
if (udev->state != USB_STATE_SUSPENDED && !udev->dev.power.runtime_auto)
p = on_string;
return sprintf(buf, "%s\n", p);
return sysfs_emit(buf, "%s\n", p);
}
static ssize_t level_store(struct device *dev, struct device_attribute *attr,
@ -490,7 +490,7 @@ static ssize_t usb2_hardware_lpm_show(struct device *dev,
else
p = "disabled";
return sprintf(buf, "%s\n", p);
return sysfs_emit(buf, "%s\n", p);
}
static ssize_t usb2_hardware_lpm_store(struct device *dev,
@ -529,7 +529,7 @@ static ssize_t usb2_lpm_l1_timeout_show(struct device *dev,
char *buf)
{
struct usb_device *udev = to_usb_device(dev);
return sprintf(buf, "%d\n", udev->l1_params.timeout);
return sysfs_emit(buf, "%d\n", udev->l1_params.timeout);
}
static ssize_t usb2_lpm_l1_timeout_store(struct device *dev,
@ -552,7 +552,7 @@ 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);
return sysfs_emit(buf, "%d\n", udev->l1_params.besl);
}
static ssize_t usb2_lpm_besl_store(struct device *dev,
@ -589,7 +589,7 @@ static ssize_t usb3_hardware_lpm_u1_show(struct device *dev,
usb_unlock_device(udev);
return sprintf(buf, "%s\n", p);
return sysfs_emit(buf, "%s\n", p);
}
static DEVICE_ATTR_RO(usb3_hardware_lpm_u1);
@ -611,7 +611,7 @@ static ssize_t usb3_hardware_lpm_u2_show(struct device *dev,
usb_unlock_device(udev);
return sprintf(buf, "%s\n", p);
return sysfs_emit(buf, "%s\n", p);
}
static DEVICE_ATTR_RO(usb3_hardware_lpm_u2);
@ -694,7 +694,7 @@ field##_show(struct device *dev, struct device_attribute *attr, \
struct usb_device *udev; \
\
udev = to_usb_device(dev); \
return sprintf(buf, format_string, \
return sysfs_emit(buf, format_string, \
le16_to_cpu(udev->descriptor.field)); \
} \
static DEVICE_ATTR_RO(field)
@ -711,7 +711,7 @@ field##_show(struct device *dev, struct device_attribute *attr, \
struct usb_device *udev; \
\
udev = to_usb_device(dev); \
return sprintf(buf, format_string, udev->descriptor.field); \
return sysfs_emit(buf, format_string, udev->descriptor.field); \
} \
static DEVICE_ATTR_RO(field)
@ -727,7 +727,7 @@ 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);
return sysfs_emit(buf, "%u\n", usb_dev->authorized);
}
/*
@ -918,7 +918,7 @@ static ssize_t authorized_default_show(struct device *dev,
struct usb_hcd *hcd;
hcd = bus_to_hcd(usb_bus);
return snprintf(buf, PAGE_SIZE, "%u\n", hcd->dev_policy);
return sysfs_emit(buf, "%u\n", hcd->dev_policy);
}
static ssize_t authorized_default_store(struct device *dev,
@ -957,7 +957,7 @@ static ssize_t interface_authorized_default_show(struct device *dev,
struct usb_device *usb_dev = to_usb_device(dev);
struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd));
return sysfs_emit(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd));
}
/*
@ -1066,7 +1066,7 @@ iad_##field##_show(struct device *dev, struct device_attribute *attr, \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
\
return sprintf(buf, format_string, \
return sysfs_emit(buf, format_string, \
intf->intf_assoc->field); \
} \
static DEVICE_ATTR_RO(iad_##field)
@ -1085,7 +1085,7 @@ field##_show(struct device *dev, struct device_attribute *attr, \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
\
return sprintf(buf, format_string, \
return sysfs_emit(buf, format_string, \
intf->cur_altsetting->desc.field); \
} \
static DEVICE_ATTR_RO(field)
@ -1107,7 +1107,7 @@ static ssize_t interface_show(struct device *dev, struct device_attribute *attr,
string = READ_ONCE(intf->cur_altsetting->string);
if (!string)
return 0;
return sprintf(buf, "%s\n", string);
return sysfs_emit(buf, "%s\n", string);
}
static DEVICE_ATTR_RO(interface);
@ -1122,7 +1122,8 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
udev = interface_to_usbdev(intf);
alt = READ_ONCE(intf->cur_altsetting);
return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X"
return sysfs_emit(buf,
"usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X"
"ic%02Xisc%02Xip%02Xin%02X\n",
le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct),
@ -1150,7 +1151,7 @@ static ssize_t supports_autosuspend_show(struct device *dev,
s = (!dev->driver || to_usb_driver(dev->driver)->supports_autosuspend);
device_unlock(dev);
return sprintf(buf, "%u\n", s);
return sysfs_emit(buf, "%u\n", s);
}
static DEVICE_ATTR_RO(supports_autosuspend);
@ -1163,7 +1164,7 @@ static ssize_t interface_authorized_show(struct device *dev,
{
struct usb_interface *intf = to_usb_interface(dev);
return sprintf(buf, "%u\n", intf->authorized);
return sysfs_emit(buf, "%u\n", intf->authorized);
}
/*

View File

@ -801,7 +801,7 @@ EXPORT_SYMBOL_GPL(usb_intf_get_dma_device);
* is simple:
*
* When locking both a device and its parent, always lock the
* the parent first.
* parent first.
*/
/**

View File

@ -3594,7 +3594,8 @@ void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)
void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg)
{
/* remove the soft-disconnect and let's go */
dwc2_clear_bit(hsotg, DCTL, DCTL_SFTDISCON);
if (!hsotg->role_sw || (dwc2_readl(hsotg, GOTGCTL) & GOTGCTL_BSESVLD))
dwc2_clear_bit(hsotg, DCTL, DCTL_SFTDISCON);
}
/**

View File

@ -52,6 +52,7 @@
#include <linux/usb/hcd.h>
#include <linux/usb/ch11.h>
#include <linux/usb/of.h>
#include "core.h"
#include "hcd.h"
@ -999,7 +1000,7 @@ static void dwc2_hc_set_even_odd_frame(struct dwc2_hsotg *hsotg,
/*
* Try to figure out if we're an even or odd frame. If we set
* even and the current frame number is even the the transfer
* even and the current frame number is even the transfer
* will happen immediately. Similar if both are odd. If one is
* even and the other is odd then the transfer will happen when
* the frame number ticks.
@ -5339,6 +5340,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
/* Don't support SG list at this point */
hcd->self.sg_tablesize = 0;
hcd->tpl_support = of_usb_host_tpl_support(hsotg->dev->of_node);
if (!IS_ERR_OR_NULL(hsotg->uphy))
otg_set_host(hsotg->uphy->otg, &hcd->self);

View File

@ -9,7 +9,7 @@ config USB_DWC3
Say Y or M here if your system has a Dual Role SuperSpeed
USB controller based on the DesignWare USB3 IP Core.
If you choose to build this driver is a dynamically linked
If you choose to build this driver as a dynamically linked
module, the module will be called dwc3.ko.
if USB_DWC3
@ -165,7 +165,7 @@ config USB_DWC3_AM62
default USB_DWC3
help
Support TI's AM62 platforms with DesignWare Core USB3 IP.
The Designware Core USB3 IP is progammed to operate in
The Designware Core USB3 IP is programmed to operate in
in USB 2.0 mode only.
Say 'Y' or 'M' here if you have one such device
endif

View File

@ -158,8 +158,13 @@ static void __dwc3_set_mode(struct work_struct *work)
break;
}
/* For DRD host or device mode only */
if (dwc->desired_dr_role != DWC3_GCTL_PRTCAP_OTG) {
/*
* When current_dr_role is not set, there's no role switching.
* Only perform GCTL.CoreSoftReset when there's DRD role switching.
*/
if (dwc->current_dr_role && ((DWC3_IP_IS(DWC3) ||
DWC3_VER_IS_PRIOR(DWC31, 190A)) &&
dwc->desired_dr_role != DWC3_GCTL_PRTCAP_OTG)) {
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg |= DWC3_GCTL_CORESOFTRESET;
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
@ -426,7 +431,7 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
* otherwise ERR_PTR(errno).
*/
static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
unsigned length)
unsigned int length)
{
struct dwc3_event_buffer *evt;
@ -469,7 +474,7 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)
* Returns 0 on success otherwise negative errno. In the error case, dwc
* may contain some buffers allocated but not all which were requested.
*/
static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned int length)
{
struct dwc3_event_buffer *evt;
@ -1029,6 +1034,37 @@ static void dwc3_set_incr_burst_type(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg);
}
static void dwc3_set_power_down_clk_scale(struct dwc3 *dwc)
{
u32 scale;
u32 reg;
if (!dwc->susp_clk)
return;
/*
* The power down scale field specifies how many suspend_clk
* periods fit into a 16KHz clock period. When performing
* the division, round up the remainder.
*
* The power down scale value is calculated using the fastest
* frequency of the suspend_clk. If it isn't fixed (but within
* the accuracy requirement), the driver may not know the max
* rate of the suspend_clk, so only update the power down scale
* if the default is less than the calculated value from
* clk_get_rate() or if the default is questionably high
* (3x or more) to be within the requirement.
*/
scale = DIV_ROUND_UP(clk_get_rate(dwc->susp_clk), 16000);
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
if ((reg & DWC3_GCTL_PWRDNSCALE_MASK) < DWC3_GCTL_PWRDNSCALE(scale) ||
(reg & DWC3_GCTL_PWRDNSCALE_MASK) > DWC3_GCTL_PWRDNSCALE(scale*3)) {
reg &= ~(DWC3_GCTL_PWRDNSCALE_MASK);
reg |= DWC3_GCTL_PWRDNSCALE(scale);
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
}
}
/**
* dwc3_core_init - Low-level initialization of DWC3 Core
* @dwc: Pointer to our controller context structure
@ -1105,6 +1141,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
if (ret)
goto err1;
/* Set power down scale of suspend_clk */
dwc3_set_power_down_clk_scale(dwc);
/* Adjust Frame Length */
dwc3_frame_length_adjustment(dwc);
@ -1782,6 +1821,7 @@ static int dwc3_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dwc);
dwc3_cache_hwparams(dwc);
device_init_wakeup(&pdev->dev, of_property_read_bool(dev->of_node, "wakeup-source"));
spin_lock_init(&dwc->lock);
mutex_init(&dwc->mutex);
@ -1943,7 +1983,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
dwc3_core_exit(dwc);
break;
case DWC3_GCTL_PRTCAP_HOST:
if (!PMSG_IS_AUTO(msg)) {
if (!PMSG_IS_AUTO(msg) && !device_can_wakeup(dwc->dev)) {
dwc3_core_exit(dwc);
break;
}
@ -2004,7 +2044,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
spin_unlock_irqrestore(&dwc->lock, flags);
break;
case DWC3_GCTL_PRTCAP_HOST:
if (!PMSG_IS_AUTO(msg)) {
if (!PMSG_IS_AUTO(msg) && !device_can_wakeup(dwc->dev)) {
ret = dwc3_core_init_for_resume(dwc);
if (ret)
return ret;
@ -2081,8 +2121,6 @@ static int dwc3_runtime_suspend(struct device *dev)
if (ret)
return ret;
device_init_wakeup(dev, true);
return 0;
}
@ -2091,8 +2129,6 @@ static int dwc3_runtime_resume(struct device *dev)
struct dwc3 *dwc = dev_get_drvdata(dev);
int ret;
device_init_wakeup(dev, false);
ret = dwc3_resume_common(dwc, PMSG_AUTO_RESUME);
if (ret)
return ret;

View File

@ -231,6 +231,7 @@
/* Global Configuration Register */
#define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19)
#define DWC3_GCTL_PWRDNSCALE_MASK GENMASK(31, 19)
#define DWC3_GCTL_U2RSTECN BIT(16)
#define DWC3_GCTL_RAMCLKSEL(x) (((x) & DWC3_GCTL_CLK_MASK) << 6)
#define DWC3_GCTL_CLK_BUS (0)
@ -1086,6 +1087,8 @@ struct dwc3_scratchpad_array {
* @dis_u1_entry_quirk: set if link entering into U1 state needs to be disabled.
* @dis_u2_entry_quirk: set if link entering into U2 state needs to be disabled.
* @dis_rxdet_inp3_quirk: set if we disable Rx.Detect in P3
* @async_callbacks: if set, indicate that async callbacks will be used.
*
* @dis_u2_freeclk_exists_quirk : set if we clear u2_freeclk_exists
* in GUSB2PHYCFG, specify that USB2 PHY doesn't
* provide a free-running PHY clock.

View File

@ -17,10 +17,12 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
#include <linux/pm_domain.h>
#include <linux/usb/of.h>
#include <linux/reset.h>
#include <linux/iopoll.h>
#include <linux/usb/hcd.h>
#include <linux/usb.h>
#include "core.h"
/* USB QSCRATCH Hardware registers */
@ -76,6 +78,7 @@ struct dwc3_qcom {
int dp_hs_phy_irq;
int dm_hs_phy_irq;
int ss_phy_irq;
enum usb_device_speed usb2_speed;
struct extcon_dev *edev;
struct extcon_dev *host_edev;
@ -296,50 +299,92 @@ static void dwc3_qcom_interconnect_exit(struct dwc3_qcom *qcom)
icc_put(qcom->icc_path_apps);
}
static enum usb_device_speed dwc3_qcom_read_usb2_speed(struct dwc3_qcom *qcom)
{
struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3);
struct usb_hcd *hcd = platform_get_drvdata(dwc->xhci);
struct usb_device *udev;
/*
* It is possible to query the speed of all children of
* USB2.0 root hub via usb_hub_for_each_child(). DWC3 code
* currently supports only 1 port per controller. So
* this is sufficient.
*/
udev = usb_hub_find_child(hcd->self.root_hub, 1);
if (!udev)
return USB_SPEED_UNKNOWN;
return udev->speed;
}
static void dwc3_qcom_enable_wakeup_irq(int irq, unsigned int polarity)
{
if (!irq)
return;
if (polarity)
irq_set_irq_type(irq, polarity);
enable_irq(irq);
enable_irq_wake(irq);
}
static void dwc3_qcom_disable_wakeup_irq(int irq)
{
if (!irq)
return;
disable_irq_wake(irq);
disable_irq_nosync(irq);
}
static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom)
{
if (qcom->hs_phy_irq) {
disable_irq_wake(qcom->hs_phy_irq);
disable_irq_nosync(qcom->hs_phy_irq);
dwc3_qcom_disable_wakeup_irq(qcom->hs_phy_irq);
if (qcom->usb2_speed == USB_SPEED_LOW) {
dwc3_qcom_disable_wakeup_irq(qcom->dm_hs_phy_irq);
} else if ((qcom->usb2_speed == USB_SPEED_HIGH) ||
(qcom->usb2_speed == USB_SPEED_FULL)) {
dwc3_qcom_disable_wakeup_irq(qcom->dp_hs_phy_irq);
} else {
dwc3_qcom_disable_wakeup_irq(qcom->dp_hs_phy_irq);
dwc3_qcom_disable_wakeup_irq(qcom->dm_hs_phy_irq);
}
if (qcom->dp_hs_phy_irq) {
disable_irq_wake(qcom->dp_hs_phy_irq);
disable_irq_nosync(qcom->dp_hs_phy_irq);
}
if (qcom->dm_hs_phy_irq) {
disable_irq_wake(qcom->dm_hs_phy_irq);
disable_irq_nosync(qcom->dm_hs_phy_irq);
}
if (qcom->ss_phy_irq) {
disable_irq_wake(qcom->ss_phy_irq);
disable_irq_nosync(qcom->ss_phy_irq);
}
dwc3_qcom_disable_wakeup_irq(qcom->ss_phy_irq);
}
static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom)
{
if (qcom->hs_phy_irq) {
enable_irq(qcom->hs_phy_irq);
enable_irq_wake(qcom->hs_phy_irq);
dwc3_qcom_enable_wakeup_irq(qcom->hs_phy_irq, 0);
/*
* Configure DP/DM line interrupts based on the USB2 device attached to
* the root hub port. When HS/FS device is connected, configure the DP line
* as falling edge to detect both disconnect and remote wakeup scenarios. When
* LS device is connected, configure DM line as falling edge to detect both
* disconnect and remote wakeup. When no device is connected, configure both
* DP and DM lines as rising edge to detect HS/HS/LS device connect scenario.
*/
if (qcom->usb2_speed == USB_SPEED_LOW) {
dwc3_qcom_enable_wakeup_irq(qcom->dm_hs_phy_irq,
IRQ_TYPE_EDGE_FALLING);
} else if ((qcom->usb2_speed == USB_SPEED_HIGH) ||
(qcom->usb2_speed == USB_SPEED_FULL)) {
dwc3_qcom_enable_wakeup_irq(qcom->dp_hs_phy_irq,
IRQ_TYPE_EDGE_FALLING);
} else {
dwc3_qcom_enable_wakeup_irq(qcom->dp_hs_phy_irq,
IRQ_TYPE_EDGE_RISING);
dwc3_qcom_enable_wakeup_irq(qcom->dm_hs_phy_irq,
IRQ_TYPE_EDGE_RISING);
}
if (qcom->dp_hs_phy_irq) {
enable_irq(qcom->dp_hs_phy_irq);
enable_irq_wake(qcom->dp_hs_phy_irq);
}
if (qcom->dm_hs_phy_irq) {
enable_irq(qcom->dm_hs_phy_irq);
enable_irq_wake(qcom->dm_hs_phy_irq);
}
if (qcom->ss_phy_irq) {
enable_irq(qcom->ss_phy_irq);
enable_irq_wake(qcom->ss_phy_irq);
}
dwc3_qcom_enable_wakeup_irq(qcom->ss_phy_irq, 0);
}
static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
@ -361,8 +406,10 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
if (ret)
dev_warn(qcom->dev, "failed to disable interconnect: %d\n", ret);
if (device_may_wakeup(qcom->dev))
if (device_may_wakeup(qcom->dev)) {
qcom->usb2_speed = dwc3_qcom_read_usb2_speed(qcom);
dwc3_qcom_enable_interrupts(qcom);
}
qcom->is_suspended = true;
@ -443,9 +490,9 @@ static int dwc3_qcom_get_irq(struct platform_device *pdev,
int ret;
if (np)
ret = platform_get_irq_byname(pdev_irq, name);
ret = platform_get_irq_byname_optional(pdev_irq, name);
else
ret = platform_get_irq(pdev_irq, num);
ret = platform_get_irq_optional(pdev_irq, num);
return ret;
}
@ -710,12 +757,13 @@ dwc3_qcom_create_urs_usb_platdev(struct device *dev)
static int dwc3_qcom_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct dwc3_qcom *qcom;
struct resource *res, *parent_res = NULL;
int ret, i;
bool ignore_pipe_clk;
struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct dwc3_qcom *qcom;
struct resource *res, *parent_res = NULL;
int ret, i;
bool ignore_pipe_clk;
struct generic_pm_domain *genpd;
qcom = devm_kzalloc(&pdev->dev, sizeof(*qcom), GFP_KERNEL);
if (!qcom)
@ -724,6 +772,8 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, qcom);
qcom->dev = &pdev->dev;
genpd = pd_to_genpd(qcom->dev->pm_domain);
if (has_acpi_companion(dev)) {
qcom->acpi_pdata = acpi_device_get_match_data(dev);
if (!qcom->acpi_pdata) {
@ -831,7 +881,17 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
if (ret)
goto interconnect_exit;
device_init_wakeup(&pdev->dev, 1);
if (device_can_wakeup(&qcom->dwc3->dev)) {
/*
* Setting GENPD_FLAG_ALWAYS_ON flag takes care of keeping
* genpd on in both runtime suspend and system suspend cases.
*/
genpd->flags |= GENPD_FLAG_ALWAYS_ON;
device_init_wakeup(&pdev->dev, true);
} else {
genpd->flags |= GENPD_FLAG_RPM_ALWAYS_ON;
}
qcom->is_suspended = false;
pm_runtime_set_active(dev);
pm_runtime_enable(dev);

View File

@ -239,6 +239,8 @@ void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
dwc3_gadget_giveback(dep, req, -ECONNRESET);
}
dwc->eps[0]->trb_enqueue = 0;
dwc->eps[1]->trb_enqueue = 0;
dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc);
}
@ -473,7 +475,7 @@ static int dwc3_ep0_handle_device(struct dwc3 *dwc,
case USB_DEVICE_REMOTE_WAKEUP:
break;
/*
* 9.4.1 says only only for SS, in AddressState only for
* 9.4.1 says only for SS, in AddressState only for
* default control pipe
*/
case USB_DEVICE_U1_ENABLE:
@ -1140,6 +1142,11 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS)
return;
if (dwc->setup_packet_pending) {
dwc3_ep0_stall_and_restart(dwc);
return;
}
dwc->ep0state = EP0_STATUS_PHASE;
if (dwc->delayed_status) {

View File

@ -657,6 +657,7 @@ static int dwc3_gadget_set_ep_config(struct dwc3_ep *dep, unsigned int action)
/**
* dwc3_gadget_calc_tx_fifo_size - calculates the txfifo size value
* @dwc: pointer to the DWC3 context
* @mult: multiplier to be used when calculating the fifo_size
*
* Calculates the size value based on the equation below:
*
@ -1182,17 +1183,49 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
return trbs_left;
}
static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
dma_addr_t dma, unsigned int length, unsigned int chain,
unsigned int node, unsigned int stream_id,
unsigned int short_not_ok, unsigned int no_interrupt,
unsigned int is_last, bool must_interrupt)
/**
* dwc3_prepare_one_trb - setup one TRB from one request
* @dep: endpoint for which this request is prepared
* @req: dwc3_request pointer
* @trb_length: buffer size of the TRB
* @chain: should this TRB be chained to the next?
* @node: only for isochronous endpoints. First TRB needs different type.
* @use_bounce_buffer: set to use bounce buffer
* @must_interrupt: set to interrupt on TRB completion
*/
static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
struct dwc3_request *req, unsigned int trb_length,
unsigned int chain, unsigned int node, bool use_bounce_buffer,
bool must_interrupt)
{
struct dwc3_trb *trb;
dma_addr_t dma;
unsigned int stream_id = req->request.stream_id;
unsigned int short_not_ok = req->request.short_not_ok;
unsigned int no_interrupt = req->request.no_interrupt;
unsigned int is_last = req->request.is_last;
struct dwc3 *dwc = dep->dwc;
struct usb_gadget *gadget = dwc->gadget;
enum usb_device_speed speed = gadget->speed;
trb->size = DWC3_TRB_SIZE_LENGTH(length);
if (use_bounce_buffer)
dma = dep->dwc->bounce_addr;
else if (req->request.num_sgs > 0)
dma = sg_dma_address(req->start_sg);
else
dma = req->request.dma;
trb = &dep->trb_pool[dep->trb_enqueue];
if (!req->trb) {
dwc3_gadget_move_started_request(req);
req->trb = trb;
req->trb_dma = dwc3_trb_dma_offset(dep, trb);
}
req->num_trbs++;
trb->size = DWC3_TRB_SIZE_LENGTH(trb_length);
trb->bpl = lower_32_bits(dma);
trb->bph = upper_32_bits(dma);
@ -1232,10 +1265,10 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
unsigned int mult = 2;
unsigned int maxp = usb_endpoint_maxp(ep->desc);
if (length <= (2 * maxp))
if (req->request.length <= (2 * maxp))
mult--;
if (length <= maxp)
if (req->request.length <= maxp)
mult--;
trb->size |= DWC3_TRB_SIZE_PCM1(mult);
@ -1309,50 +1342,6 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
trace_dwc3_prepare_trb(dep, trb);
}
/**
* dwc3_prepare_one_trb - setup one TRB from one request
* @dep: endpoint for which this request is prepared
* @req: dwc3_request pointer
* @trb_length: buffer size of the TRB
* @chain: should this TRB be chained to the next?
* @node: only for isochronous endpoints. First TRB needs different type.
* @use_bounce_buffer: set to use bounce buffer
* @must_interrupt: set to interrupt on TRB completion
*/
static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
struct dwc3_request *req, unsigned int trb_length,
unsigned int chain, unsigned int node, bool use_bounce_buffer,
bool must_interrupt)
{
struct dwc3_trb *trb;
dma_addr_t dma;
unsigned int stream_id = req->request.stream_id;
unsigned int short_not_ok = req->request.short_not_ok;
unsigned int no_interrupt = req->request.no_interrupt;
unsigned int is_last = req->request.is_last;
if (use_bounce_buffer)
dma = dep->dwc->bounce_addr;
else if (req->request.num_sgs > 0)
dma = sg_dma_address(req->start_sg);
else
dma = req->request.dma;
trb = &dep->trb_pool[dep->trb_enqueue];
if (!req->trb) {
dwc3_gadget_move_started_request(req);
req->trb = trb;
req->trb_dma = dwc3_trb_dma_offset(dep, trb);
}
req->num_trbs++;
__dwc3_prepare_one_trb(dep, trb, dma, trb_length, chain, node,
stream_id, short_not_ok, no_interrupt, is_last,
must_interrupt);
}
static bool dwc3_needs_extra_trb(struct dwc3_ep *dep, struct dwc3_request *req)
{
unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);

View File

@ -57,18 +57,8 @@ struct f_acm {
/* SetControlLineState request -- CDC 1.1 section 6.2.14 (INPUT) */
u16 port_handshake_bits;
#define ACM_CTRL_RTS (1 << 1) /* unused with full duplex */
#define ACM_CTRL_DTR (1 << 0) /* host is ready for data r/w */
/* SerialState notification -- CDC 1.1 section 6.3.5 (OUTPUT) */
u16 serial_state;
#define ACM_CTRL_OVERRUN (1 << 6)
#define ACM_CTRL_PARITY (1 << 5)
#define ACM_CTRL_FRAMING (1 << 4)
#define ACM_CTRL_RI (1 << 3)
#define ACM_CTRL_BRK (1 << 2)
#define ACM_CTRL_DSR (1 << 1)
#define ACM_CTRL_DCD (1 << 0)
};
static inline struct f_acm *func_to_acm(struct usb_function *f)
@ -387,7 +377,7 @@ static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
value = 0;
/* FIXME we should not allow data to flow until the
* host sets the ACM_CTRL_DTR bit; and when it clears
* host sets the USB_CDC_CTRL_DTR bit; and when it clears
* that bit, we should return to that no-flow state.
*/
acm->port_handshake_bits = w_value;
@ -585,7 +575,7 @@ static void acm_connect(struct gserial *port)
{
struct f_acm *acm = port_to_acm(port);
acm->serial_state |= ACM_CTRL_DSR | ACM_CTRL_DCD;
acm->serial_state |= USB_CDC_SERIAL_STATE_DSR | USB_CDC_SERIAL_STATE_DCD;
acm_notify_serial_state(acm);
}
@ -593,7 +583,7 @@ static void acm_disconnect(struct gserial *port)
{
struct f_acm *acm = port_to_acm(port);
acm->serial_state &= ~(ACM_CTRL_DSR | ACM_CTRL_DCD);
acm->serial_state &= ~(USB_CDC_SERIAL_STATE_DSR | USB_CDC_SERIAL_STATE_DCD);
acm_notify_serial_state(acm);
}
@ -603,9 +593,9 @@ static int acm_send_break(struct gserial *port, int duration)
u16 state;
state = acm->serial_state;
state &= ~ACM_CTRL_BRK;
state &= ~USB_CDC_SERIAL_STATE_BREAK;
if (duration)
state |= ACM_CTRL_BRK;
state |= USB_CDC_SERIAL_STATE_BREAK;
acm->serial_state = state;
return acm_notify_serial_state(acm);

View File

@ -1192,13 +1192,14 @@ static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh)
u8 format;
int i, len;
format = common->cmnd[2] & 0xf;
if ((common->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */
start_track > 1) {
(start_track > 1 && format != 0x1)) {
curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL;
}
format = common->cmnd[2] & 0xf;
/*
* Check if CDB is old style SFF-8020i
* i.e. format is in 2 MSBs of byte 9
@ -1208,8 +1209,8 @@ static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh)
format = (common->cmnd[9] >> 6) & 0x3;
switch (format) {
case 0:
/* Formatted TOC */
case 0: /* Formatted TOC */
case 1: /* Multi-session info */
len = 4 + 2*8; /* 4 byte header + 2 descriptors */
memset(buf, 0, len);
buf[1] = len - 2; /* TOC Length excludes length field */
@ -1250,7 +1251,7 @@ static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh)
return len;
default:
/* Multi-session, PMA, ATIP, CD-TEXT not supported/required */
/* PMA, ATIP, CD-TEXT not supported/required */
curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL;
}
@ -2650,10 +2651,21 @@ static ssize_t file_store(struct device *dev, struct device_attribute *attr,
return fsg_store_file(curlun, filesem, buf, count);
}
static ssize_t forced_eject_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct fsg_lun *curlun = fsg_lun_from_dev(dev);
struct rw_semaphore *filesem = dev_get_drvdata(dev);
return fsg_store_forced_eject(curlun, filesem, buf, count);
}
static DEVICE_ATTR_RW(nofua);
/* mode wil be set in fsg_lun_attr_is_visible() */
static DEVICE_ATTR(ro, 0, ro_show, ro_store);
static DEVICE_ATTR(file, 0, file_show, file_store);
static DEVICE_ATTR_WO(forced_eject);
/****************************** FSG COMMON ******************************/
@ -2807,6 +2819,7 @@ static struct attribute *fsg_lun_dev_attrs[] = {
&dev_attr_ro.attr,
&dev_attr_file.attr,
&dev_attr_nofua.attr,
&dev_attr_forced_eject.attr,
NULL
};
@ -3220,6 +3233,18 @@ static ssize_t fsg_lun_opts_inquiry_string_store(struct config_item *item,
CONFIGFS_ATTR(fsg_lun_opts_, inquiry_string);
static ssize_t fsg_lun_opts_forced_eject_store(struct config_item *item,
const char *page, size_t len)
{
struct fsg_lun_opts *opts = to_fsg_lun_opts(item);
struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
return fsg_store_forced_eject(opts->lun, &fsg_opts->common->filesem,
page, len);
}
CONFIGFS_ATTR_WO(fsg_lun_opts_, forced_eject);
static struct configfs_attribute *fsg_lun_attrs[] = {
&fsg_lun_opts_attr_file,
&fsg_lun_opts_attr_ro,
@ -3227,6 +3252,7 @@ static struct configfs_attribute *fsg_lun_attrs[] = {
&fsg_lun_opts_attr_cdrom,
&fsg_lun_opts_attr_nofua,
&fsg_lun_opts_attr_inquiry_string,
&fsg_lun_opts_attr_forced_eject,
NULL,
};

View File

@ -141,7 +141,8 @@ static struct usb_endpoint_descriptor uvc_fs_streaming_ep = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_SYNC_ASYNC
| USB_ENDPOINT_XFER_ISOC,
/* The wMaxPacketSize and bInterval values will be initialized from
/*
* The wMaxPacketSize and bInterval values will be initialized from
* module parameters.
*/
};
@ -152,7 +153,8 @@ static struct usb_endpoint_descriptor uvc_hs_streaming_ep = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_SYNC_ASYNC
| USB_ENDPOINT_XFER_ISOC,
/* The wMaxPacketSize and bInterval values will be initialized from
/*
* The wMaxPacketSize and bInterval values will be initialized from
* module parameters.
*/
};
@ -164,7 +166,8 @@ static struct usb_endpoint_descriptor uvc_ss_streaming_ep = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_SYNC_ASYNC
| USB_ENDPOINT_XFER_ISOC,
/* The wMaxPacketSize and bInterval values will be initialized from
/*
* The wMaxPacketSize and bInterval values will be initialized from
* module parameters.
*/
};
@ -172,7 +175,8 @@ static struct usb_endpoint_descriptor uvc_ss_streaming_ep = {
static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = {
.bLength = sizeof(uvc_ss_streaming_comp),
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* The bMaxBurst, bmAttributes and wBytesPerInterval values will be
/*
* The bMaxBurst, bmAttributes and wBytesPerInterval values will be
* initialized from module parameters.
*/
};
@ -234,7 +238,8 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
if (le16_to_cpu(ctrl->wLength) > UVC_MAX_REQUEST_SIZE)
return -EINVAL;
/* Tell the complete callback to generate an event for the next request
/*
* Tell the complete callback to generate an event for the next request
* that will be enqueued by UVCIOC_SEND_RESPONSE.
*/
uvc->event_setup_out = !(ctrl->bRequestType & USB_DIR_IN);
@ -500,7 +505,8 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
if (!uvc_control_desc || !uvc_streaming_cls)
return ERR_PTR(-ENODEV);
/* Descriptors layout
/*
* Descriptors layout
*
* uvc_iad
* uvc_control_intf
@ -597,8 +603,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
uvcg_info(f, "%s()\n", __func__);
opts = fi_to_f_uvc_opts(f->fi);
/* Sanity check the streaming endpoint module parameters.
*/
/* Sanity check the streaming endpoint module parameters. */
opts->streaming_interval = clamp(opts->streaming_interval, 1U, 16U);
opts->streaming_maxpacket = clamp(opts->streaming_maxpacket, 1U, 3072U);
opts->streaming_maxburst = min(opts->streaming_maxburst, 15U);
@ -611,7 +616,8 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
opts->streaming_maxpacket);
}
/* Fill in the FS/HS/SS Video Streaming specific descriptors from the
/*
* Fill in the FS/HS/SS Video Streaming specific descriptors from the
* module parameters.
*
* NOTE: We assume that the user knows what they are doing and won't
@ -895,7 +901,8 @@ static void uvc_function_unbind(struct usb_configuration *c,
uvcg_info(f, "%s()\n", __func__);
/* If we know we're connected via v4l2, then there should be a cleanup
/*
* If we know we're connected via v4l2, then there should be a cleanup
* of the device from userspace either via UVC_EVENT_DISCONNECT or
* though the video device removal uevent. Allow some time for the
* application to close out before things get deleted.
@ -912,7 +919,8 @@ static void uvc_function_unbind(struct usb_configuration *c,
v4l2_device_unregister(&uvc->v4l2_dev);
if (uvc->func_connected) {
/* Wait for the release to occur to ensure there are no longer any
/*
* Wait for the release to occur to ensure there are no longer any
* pending operations that may cause panics when resources are cleaned
* up.
*/

View File

@ -519,4 +519,19 @@ ssize_t fsg_store_inquiry_string(struct fsg_lun *curlun, const char *buf,
}
EXPORT_SYMBOL_GPL(fsg_store_inquiry_string);
ssize_t fsg_store_forced_eject(struct fsg_lun *curlun, struct rw_semaphore *filesem,
const char *buf, size_t count)
{
int ret;
/*
* Forcibly detach the backing file from the LUN
* regardless of whether the host has allowed it.
*/
curlun->prevent_medium_removal = 0;
ret = fsg_store_file(curlun, filesem, "", 0);
return ret < 0 ? ret : count;
}
EXPORT_SYMBOL_GPL(fsg_store_forced_eject);
MODULE_LICENSE("GPL");

View File

@ -219,5 +219,7 @@ ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf,
size_t count);
ssize_t fsg_store_inquiry_string(struct fsg_lun *curlun, const char *buf,
size_t count);
ssize_t fsg_store_forced_eject(struct fsg_lun *curlun, struct rw_semaphore *filesem,
const char *buf, size_t count);
#endif /* USB_STORAGE_COMMON_H */

View File

@ -17,7 +17,6 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
#include <linux/etherdevice.h>
#include "u_ether.h"

View File

@ -44,7 +44,8 @@ static int uvc_queue_setup(struct vb2_queue *vq,
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
struct uvc_video *video = container_of(queue, struct uvc_video, queue);
struct usb_composite_dev *cdev = video->uvc->func.config->cdev;
unsigned int req_size;
unsigned int nreq;
if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
*nbuffers = UVC_MAX_VIDEO_BUFFERS;
@ -53,10 +54,16 @@ static int uvc_queue_setup(struct vb2_queue *vq,
sizes[0] = video->imagesize;
if (cdev->gadget->speed < USB_SPEED_SUPER)
video->uvc_num_requests = 4;
else
video->uvc_num_requests = 64;
req_size = video->ep->maxpacket
* max_t(unsigned int, video->ep->maxburst, 1)
* (video->ep->mult);
/* We divide by two, to increase the chance to run
* into fewer requests for smaller framesizes.
*/
nreq = DIV_ROUND_UP(DIV_ROUND_UP(sizes[0], 2), req_size);
nreq = clamp(nreq, 4U, 64U);
video->uvc_num_requests = nreq;
return 0;
}
@ -104,7 +111,8 @@ static void uvc_buffer_queue(struct vb2_buffer *vb)
if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
list_add_tail(&buf->queue, &queue->irqqueue);
} else {
/* If the device is disconnected return the buffer to userspace
/*
* If the device is disconnected return the buffer to userspace
* directly. The next QBUF call will fail with -ENODEV.
*/
buf->state = UVC_BUF_STATE_ERROR;
@ -255,7 +263,8 @@ void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect)
}
queue->buf_used = 0;
/* This must be protected by the irqlock spinlock to avoid race
/*
* This must be protected by the irqlock spinlock to avoid race
* conditions between uvc_queue_buffer and the disconnection event that
* could result in an interruptible wait in uvc_dequeue_buffer. Do not
* blindly replace this logic by checking for the UVC_DEV_DISCONNECTED

View File

@ -261,7 +261,7 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
break;
default:
uvcg_info(&video->uvc->func,
uvcg_warn(&video->uvc->func,
"VS request completed with status %d.\n",
req->status);
uvcg_queue_cancel(queue, 0);
@ -378,7 +378,8 @@ static void uvcg_video_pump(struct work_struct *work)
int ret;
while (video->ep->enabled) {
/* Retrieve the first available USB request, protected by the
/*
* Retrieve the first available USB request, protected by the
* request lock.
*/
spin_lock_irqsave(&video->req_lock, flags);
@ -391,7 +392,8 @@ static void uvcg_video_pump(struct work_struct *work)
list_del(&req->list);
spin_unlock_irqrestore(&video->req_lock, flags);
/* Retrieve the first available video buffer and fill the
/*
* Retrieve the first available video buffer and fill the
* request, protected by the video queue irqlock.
*/
spin_lock_irqsave(&queue->irqlock, flags);
@ -403,9 +405,11 @@ static void uvcg_video_pump(struct work_struct *work)
video->encode(req, video, buf);
/* With usb3 we have more requests. This will decrease the
/*
* With usb3 we have more requests. This will decrease the
* interrupt load to a quarter but also catches the corner
* cases, which needs to be handled */
* cases, which needs to be handled.
*/
if (list_empty(&video->req_free) ||
buf->state == UVC_BUF_STATE_DONE ||
!(video->req_int_count %

View File

@ -362,6 +362,7 @@ ep_io (struct ep_data *epdata, void *buf, unsigned len)
spin_unlock_irq (&epdata->dev->lock);
DBG (epdata->dev, "endpoint gone\n");
wait_for_completion(&done);
epdata->status = -ENODEV;
}
}

View File

@ -311,7 +311,7 @@ source "drivers/usb/gadget/udc/bdc/Kconfig"
config USB_AMD5536UDC
tristate "AMD5536 UDC"
depends on USB_PCI
depends on USB_PCI && HAS_DMA
select USB_SNP_CORE
help
The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
@ -463,6 +463,19 @@ config USB_TEGRA_XUDC
dynamically linked module called "tegra_xudc" and force all
gadget drivers to also be dynamically linked.
config USB_ASPEED_UDC
tristate "Aspeed UDC driver support"
depends on ARCH_ASPEED || COMPILE_TEST
depends on USB_LIBCOMPOSITE
help
Enables Aspeed USB2.0 Device Controller driver for AST260x
family SoCs. The controller supports 1 control endpoint and
4 programmable endpoints.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "aspeed_udc" and force all
gadget drivers to also be dynamically linked.
source "drivers/usb/gadget/udc/aspeed-vhub/Kconfig"
#

View File

@ -40,5 +40,6 @@ obj-$(CONFIG_USB_GR_UDC) += gr_udc.o
obj-$(CONFIG_USB_GADGET_XILINX) += udc-xilinx.o
obj-$(CONFIG_USB_SNP_UDC_PLAT) += snps_udc_plat.o
obj-$(CONFIG_USB_ASPEED_VHUB) += aspeed-vhub/
obj-$(CONFIG_USB_ASPEED_UDC) += aspeed_udc.o
obj-$(CONFIG_USB_BDC_UDC) += bdc/
obj-$(CONFIG_USB_MAX3420_UDC) += max3420_udc.o

View File

@ -1059,8 +1059,10 @@ static int ast_vhub_init_desc(struct ast_vhub *vhub)
/* Initialize vhub String Descriptors. */
INIT_LIST_HEAD(&vhub->vhub_str_desc);
desc_np = of_get_child_by_name(vhub_np, "vhub-strings");
if (desc_np)
if (desc_np) {
ret = ast_vhub_of_parse_str_desc(vhub, desc_np);
of_node_put(desc_np);
}
else
ret = ast_vhub_str_alloc_add(vhub, &ast_vhub_strings);

File diff suppressed because it is too large Load Diff

View File

@ -2060,7 +2060,7 @@ static const struct usba_udc_errata at91sam9g45_errata = {
.pulse_bias = at91sam9g45_pulse_bias,
};
static const struct usba_ep_config ep_config_sam9[] __initconst = {
static const struct usba_ep_config ep_config_sam9[] = {
{ .nr_banks = 1 }, /* ep 0 */
{ .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 1 */
{ .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 2 */
@ -2070,7 +2070,7 @@ static const struct usba_ep_config ep_config_sam9[] __initconst = {
{ .nr_banks = 3, .can_dma = 1, .can_isoc = 1 }, /* ep 6 */
};
static const struct usba_ep_config ep_config_sama5[] __initconst = {
static const struct usba_ep_config ep_config_sama5[] = {
{ .nr_banks = 1 }, /* ep 0 */
{ .nr_banks = 3, .can_dma = 1, .can_isoc = 1 }, /* ep 1 */
{ .nr_banks = 3, .can_dma = 1, .can_isoc = 1 }, /* ep 2 */
@ -2165,6 +2165,8 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
udc->vbus_pin = devm_gpiod_get_optional(&pdev->dev, "atmel,vbus",
GPIOD_IN);
if (IS_ERR(udc->vbus_pin))
return ERR_CAST(udc->vbus_pin);
if (fifo_mode == 0) {
udc->num_ep = udc_config->num_ep;
@ -2447,6 +2449,7 @@ static int usba_udc_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(usba_udc_pm_ops, usba_udc_suspend, usba_udc_resume);
static struct platform_driver udc_driver = {
.probe = usba_udc_probe,
.remove = usba_udc_remove,
.driver = {
.name = "atmel_usba_udc",
@ -2454,8 +2457,7 @@ static struct platform_driver udc_driver = {
.of_match_table = atmel_udc_dt_ids,
},
};
module_platform_driver_probe(udc_driver, usba_udc_probe);
module_platform_driver(udc_driver);
MODULE_DESCRIPTION("Atmel USBA UDC driver");
MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");

View File

@ -307,7 +307,7 @@ int bdc_ep_clear_stall(struct bdc *bdc, int epnum)
* his will reset the seq number for non EP0.
*/
if (epnum != 1) {
/* if the endpoint it not stallled */
/* if the endpoint it not stalled */
if (!(ep->flags & BDC_EP_STALL)) {
ret = bdc_ep_set_stall(bdc, epnum);
if (ret)

View File

@ -1728,13 +1728,14 @@ static int usb_udc_uevent(struct device *dev, struct kobj_uevent_env *env)
return ret;
}
if (udc->driver) {
mutex_lock(&udc_lock);
if (udc->driver)
ret = add_uevent_var(env, "USB_UDC_DRIVER=%s",
udc->driver->function);
if (ret) {
dev_err(dev, "failed to add uevent USB_UDC_DRIVER\n");
return ret;
}
mutex_unlock(&udc_lock);
if (ret) {
dev_err(dev, "failed to add uevent USB_UDC_DRIVER\n");
return ret;
}
return 0;

View File

@ -3691,15 +3691,15 @@ static int tegra_xudc_powerdomain_init(struct tegra_xudc *xudc)
int err;
xudc->genpd_dev_device = dev_pm_domain_attach_by_name(dev, "dev");
if (IS_ERR(xudc->genpd_dev_device)) {
err = PTR_ERR(xudc->genpd_dev_device);
if (IS_ERR_OR_NULL(xudc->genpd_dev_device)) {
err = PTR_ERR(xudc->genpd_dev_device) ? : -ENODATA;
dev_err(dev, "failed to get device power domain: %d\n", err);
return err;
}
xudc->genpd_dev_ss = dev_pm_domain_attach_by_name(dev, "ss");
if (IS_ERR(xudc->genpd_dev_ss)) {
err = PTR_ERR(xudc->genpd_dev_ss);
if (IS_ERR_OR_NULL(xudc->genpd_dev_ss)) {
err = PTR_ERR(xudc->genpd_dev_ss) ? : -ENODATA;
dev_err(dev, "failed to get SuperSpeed power domain: %d\n", err);
return err;
}

View File

@ -140,7 +140,7 @@ DECLARE_EVENT_CLASS(udc_log_ep,
TP_PROTO(struct usb_ep *ep, int ret),
TP_ARGS(ep, ret),
TP_STRUCT__entry(
__dynamic_array(char, name, UDC_TRACE_STR_MAX)
__string(name, ep->name)
__field(unsigned, maxpacket)
__field(unsigned, maxpacket_limit)
__field(unsigned, max_streams)
@ -152,7 +152,7 @@ DECLARE_EVENT_CLASS(udc_log_ep,
__field(int, ret)
),
TP_fast_assign(
snprintf(__get_str(name), UDC_TRACE_STR_MAX, "%s", ep->name);
__assign_str(name, ep->name);
__entry->maxpacket = ep->maxpacket;
__entry->maxpacket_limit = ep->maxpacket_limit;
__entry->max_streams = ep->max_streams;
@ -214,7 +214,7 @@ DECLARE_EVENT_CLASS(udc_log_req,
TP_PROTO(struct usb_ep *ep, struct usb_request *req, int ret),
TP_ARGS(ep, req, ret),
TP_STRUCT__entry(
__dynamic_array(char, name, UDC_TRACE_STR_MAX)
__string(name, ep->name)
__field(unsigned, length)
__field(unsigned, actual)
__field(unsigned, num_sgs)
@ -228,7 +228,7 @@ DECLARE_EVENT_CLASS(udc_log_req,
__field(struct usb_request *, req)
),
TP_fast_assign(
snprintf(__get_str(name), UDC_TRACE_STR_MAX, "%s", ep->name);
__assign_str(name, ep->name);
__entry->length = req->length;
__entry->actual = req->actual;
__entry->num_sgs = req->num_sgs;

View File

@ -306,6 +306,16 @@ config USB_EHCI_MV
Dova, Armada 370 and Armada XP. See "Support for Marvell EBU
on-chip EHCI USB controller" for those.
config USB_OCTEON_HCD
tristate "Cavium Networks Octeon USB support"
depends on CAVIUM_OCTEON_SOC && USB
help
This driver supports USB host controller on some Cavium
Networks' products in the Octeon family.
To compile this driver as a module, choose M here. The module
will be called octeon-hcd.
config USB_CNS3XXX_EHCI
bool "Cavium CNS3XXX EHCI Module (DEPRECATED)"
depends on ARCH_CNS3XXX || COMPILE_TEST

View File

@ -63,6 +63,7 @@ obj-$(CONFIG_USB_OHCI_HCD_S3C2410) += ohci-s3c2410.o
obj-$(CONFIG_USB_OHCI_HCD_LPC32XX) += ohci-nxp.o
obj-$(CONFIG_USB_OHCI_HCD_PXA27X) += ohci-pxa27x.o
obj-$(CONFIG_USB_OHCI_HCD_DAVINCI) += ohci-da8xx.o
obj-$(CONFIG_USB_OCTEON_HCD) += octeon-hcd.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
obj-$(CONFIG_USB_FHCI_HCD) += fhci.o

View File

@ -370,6 +370,8 @@ static int ehci_platform_probe(struct platform_device *dev)
hcd->rsrc_start = res_mem->start;
hcd->rsrc_len = resource_size(res_mem);
hcd->tpl_support = of_usb_host_tpl_support(dev->dev.of_node);
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err)
goto err_power;

View File

@ -148,6 +148,7 @@ static int ehci_hcd_ppc_of_probe(struct platform_device *op)
} else {
ehci->has_amcc_usb23 = 1;
}
of_node_put(np);
}
if (of_get_property(dn, "big-endian", NULL)) {

View File

@ -1162,7 +1162,7 @@ submit_async (
* This is done in two parts: first SETUP req for GetDesc is sent then
* 15 seconds later, the IN stage for GetDesc starts to req data from dev
*
* is_setup : i/p arguement decides which of the two stage needs to be
* is_setup : i/p argument decides which of the two stage needs to be
* performed; TRUE - SETUP and FALSE - IN+STATUS
* Returns 0 if success
*/

View File

@ -312,7 +312,7 @@ static const int hrsl_to_error[] = {
/*
* See https://www.beyondlogic.org/usbnutshell/usb4.shtml#Control for a
* reasonable overview of how control transfers use the the IN/OUT
* reasonable overview of how control transfers use the IN/OUT
* tokens.
*/
#define MAX3421_HXFR_BULK_IN(ep) (0x00 | (ep)) /* bulk or interrupt */

View File

@ -13,6 +13,7 @@
* This file is licenced under the GPL.
*/
#include <linux/arm-smccc.h>
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/gpio/consumer.h>
@ -55,6 +56,7 @@ struct ohci_at91_priv {
bool clocked;
bool wakeup; /* Saved wake-up state for resume */
struct regmap *sfr_regmap;
u32 suspend_smc_id;
};
/* interface and function clocks; sometimes also an AHB clock */
@ -135,6 +137,19 @@ static void at91_stop_hc(struct platform_device *pdev)
static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
static u32 at91_dt_suspend_smc(struct device *dev)
{
u32 suspend_smc_id;
if (!dev->of_node)
return 0;
if (of_property_read_u32(dev->of_node, "microchip,suspend-smc-id", &suspend_smc_id))
return 0;
return suspend_smc_id;
}
static struct regmap *at91_dt_syscon_sfr(void)
{
struct regmap *regmap;
@ -215,9 +230,13 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
goto err;
}
ohci_at91->sfr_regmap = at91_dt_syscon_sfr();
if (!ohci_at91->sfr_regmap)
dev_dbg(dev, "failed to find sfr node\n");
ohci_at91->suspend_smc_id = at91_dt_suspend_smc(dev);
if (!ohci_at91->suspend_smc_id) {
dev_dbg(dev, "failed to find sfr suspend smc id, using regmap\n");
ohci_at91->sfr_regmap = at91_dt_syscon_sfr();
if (!ohci_at91->sfr_regmap)
dev_dbg(dev, "failed to find sfr node\n");
}
board = hcd->self.controller->platform_data;
ohci = hcd_to_ohci(hcd);
@ -303,24 +322,30 @@ static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf)
return length;
}
static int ohci_at91_port_suspend(struct regmap *regmap, u8 set)
static int ohci_at91_port_suspend(struct ohci_at91_priv *ohci_at91, u8 set)
{
struct regmap *regmap = ohci_at91->sfr_regmap;
u32 regval;
int ret;
if (!regmap)
return 0;
if (ohci_at91->suspend_smc_id) {
struct arm_smccc_res res;
ret = regmap_read(regmap, AT91_SFR_OHCIICR, &regval);
if (ret)
return ret;
arm_smccc_smc(ohci_at91->suspend_smc_id, set, 0, 0, 0, 0, 0, 0, &res);
if (res.a0)
return -EINVAL;
} else if (regmap) {
ret = regmap_read(regmap, AT91_SFR_OHCIICR, &regval);
if (ret)
return ret;
if (set)
regval |= AT91_OHCIICR_USB_SUSPEND;
else
regval &= ~AT91_OHCIICR_USB_SUSPEND;
if (set)
regval |= AT91_OHCIICR_USB_SUSPEND;
else
regval &= ~AT91_OHCIICR_USB_SUSPEND;
regmap_write(regmap, AT91_SFR_OHCIICR, regval);
regmap_write(regmap, AT91_SFR_OHCIICR, regval);
}
return 0;
}
@ -357,9 +382,8 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case USB_PORT_FEAT_SUSPEND:
dev_dbg(hcd->self.controller, "SetPortFeat: SUSPEND\n");
if (valid_port(wIndex) && ohci_at91->sfr_regmap) {
ohci_at91_port_suspend(ohci_at91->sfr_regmap,
1);
if (valid_port(wIndex)) {
ohci_at91_port_suspend(ohci_at91, 1);
return 0;
}
break;
@ -400,9 +424,8 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case USB_PORT_FEAT_SUSPEND:
dev_dbg(hcd->self.controller, "ClearPortFeature: SUSPEND\n");
if (valid_port(wIndex) && ohci_at91->sfr_regmap) {
ohci_at91_port_suspend(ohci_at91->sfr_regmap,
0);
if (valid_port(wIndex)) {
ohci_at91_port_suspend(ohci_at91, 0);
return 0;
}
break;
@ -630,10 +653,10 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
/* flush the writes */
(void) ohci_readl (ohci, &ohci->regs->control);
msleep(1);
ohci_at91_port_suspend(ohci_at91->sfr_regmap, 1);
ohci_at91_port_suspend(ohci_at91, 1);
at91_stop_clock(ohci_at91);
} else {
ohci_at91_port_suspend(ohci_at91->sfr_regmap, 1);
ohci_at91_port_suspend(ohci_at91, 1);
}
return ret;
@ -645,7 +668,7 @@ ohci_hcd_at91_drv_resume(struct device *dev)
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct ohci_at91_priv *ohci_at91 = hcd_to_ohci_at91_priv(hcd);
ohci_at91_port_suspend(ohci_at91->sfr_regmap, 0);
ohci_at91_port_suspend(ohci_at91, 0);
if (ohci_at91->wakeup)
disable_irq_wake(hcd->irq);

View File

@ -164,6 +164,7 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
}
isp1301_i2c_client = isp1301_get_client(isp1301_node);
of_node_put(isp1301_node);
if (!isp1301_i2c_client)
return -EPROBE_DEFER;

View File

@ -28,6 +28,7 @@
#include <linux/usb/ohci_pdriver.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/usb/of.h>
#include "ohci.h"
@ -210,6 +211,8 @@ static int ohci_platform_probe(struct platform_device *dev)
hcd->rsrc_start = res_mem->start;
hcd->rsrc_len = resource_size(res_mem);
hcd->tpl_support = of_usb_host_tpl_support(dev->dev.of_node);
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err)
goto err_power;

View File

@ -166,6 +166,7 @@ static int ohci_hcd_ppc_of_probe(struct platform_device *op)
release_mem_region(res.start, 0x4);
} else
pr_debug("%s: cannot get ehci offset from fdt\n", __FILE__);
of_node_put(np);
}
irq_dispose_mapping(irq);

View File

@ -153,7 +153,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
* fine. This is however not always the case - buffers may be allocated
* using kmalloc() - so the usb core needs to be told that it must copy
* data into our local memory if the buffers happen to be placed in
* regular memory. A non-null hcd->localmem_pool initialized by the
* regular memory. A non-null hcd->localmem_pool initialized by
* the call to usb_hcd_setup_local_mem() below does just that.
*/

View File

@ -43,7 +43,7 @@ static int uhci_grlib_init(struct usb_hcd *hcd)
uhci->rh_numports = uhci_count_ports(hcd);
/* Set up pointers to to generic functions */
/* Set up pointers to generic functions */
uhci->reset_hc = uhci_generic_reset_hc;
uhci->check_and_reset_hc = uhci_generic_check_and_reset_hc;
/* No special actions need to be taken for the functions below */

View File

@ -314,7 +314,7 @@ struct uhci_td {
*
* There's a special skeleton QH for Isochronous QHs which never appears
* on the schedule. Isochronous TDs go on the schedule before the
* the skeleton QHs. The hardware accesses them directly rather than
* skeleton QHs. The hardware accesses them directly rather than
* through their QH, which is used only for bookkeeping purposes.
* While the UHCI spec doesn't forbid the use of QHs for Isochronous,
* it doesn't use them either. And the spec says that queues never

View File

@ -18,6 +18,7 @@
#include <linux/pm_wakeirq.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
#include "xhci.h"
#include "xhci-mtk.h"
@ -550,6 +551,12 @@ static int xhci_mtk_probe(struct platform_device *pdev)
if (ret)
goto disable_ldos;
ret = device_reset_optional(dev);
if (ret) {
dev_err_probe(dev, ret, "failed to reset controller\n");
goto disable_clk;
}
hcd = usb_create_hcd(driver, dev, dev_name(dev));
if (!hcd) {
ret = -ENOMEM;

View File

@ -120,7 +120,6 @@ static int renesas_fw_verify(const void *fw_data,
size_t length)
{
u16 fw_version_pointer;
u16 fw_version;
/*
* The Firmware's Data Format is describe in
@ -150,9 +149,6 @@ static int renesas_fw_verify(const void *fw_data,
return -EINVAL;
}
fw_version = get_unaligned_le16(fw_data + fw_version_pointer);
pr_err("got firmware version: %02x.", fw_version);
return 0;
}

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