Commit 780607b9 authored by Linus Torvalds's avatar Linus Torvalds

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

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

  It's been an active set of development in these subsystems for the
  past few months:

   - loads of typec features added for new hardware

   - xhci features and bugfixes

   - dwc3 features added for more hardware support

   - dwc2 fixes and new hardware support

   - cdns3 driver updates for more hardware support

   - gadget driver cleanups and minor fixes

   - usb-serial fixes, new driver, and more devices supported

   - thunderbolt feature additions for new hardware

   - lots of other tiny fixups and additions

  The chrome driver changes are in here as well, as they depended on
  some of the typec changes, and the maintainer acked them.

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

* tag 'usb-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (300 commits)
  dt-bindings: usb: mediatek: musb: add mt8516 compatbile
  dt-bindings: usb: mtk-xhci: add compatible for mt2701 and mt7623
  dt-bindings: usb: mtk-xhci: add optional assigned clock properties
  Documentation: connector: Update the description of sink-vdos
  usb: misc: usb3503: Fix logic in usb3503_init()
  dt-bindings: usb: usb-device: fix typo in required properties
  usb: Replace lkml.org links with lore
  dt-bindings: usb: dwc3: add description for rk3328
  dt-bindings: usb: convert rockchip,dwc3.txt to yaml
  usb: quirks: add quirk to start video capture on ELMO L-12F document camera reliable
  USB: quirks: sort quirk entries
  USB: serial: drop bogus to_usb_serial_port() checks
  USB: serial: make remove callback return void
  USB: serial: drop if with an always false condition
  usb: gadget: Assign boolean values to a bool variable
  usb: typec: tcpm: Get Sink VDO from fwnode
  dt-bindings: connector: Add SVDM VDO properties
  usb: typec: displayport: Fill the negotiated SVDM Version in the header
  usb: typec: ucsi: Determine common SVDM Version
  usb: typec: tcpm: Determine common SVDM Version
  ...
parents e4286926 b5a12546
...@@ -49,6 +49,15 @@ Description: Holds a comma separated list of device unique_ids that ...@@ -49,6 +49,15 @@ Description: Holds a comma separated list of device unique_ids that
If a device is authorized automatically during boot its If a device is authorized automatically during boot its
boot attribute is set to 1. boot attribute is set to 1.
What: /sys/bus/thunderbolt/devices/.../domainX/deauthorization
Date: May 2021
KernelVersion: 5.12
Contact: Mika Westerberg <mika.westerberg@linux.intel.com>
Description: This attribute tells whether the system supports
de-authorization of devices. Value of 1 means user can
de-authorize PCIe tunnel by writing 0 to authorized
attribute under each device.
What: /sys/bus/thunderbolt/devices/.../domainX/iommu_dma_protection What: /sys/bus/thunderbolt/devices/.../domainX/iommu_dma_protection
Date: Mar 2019 Date: Mar 2019
KernelVersion: 4.21 KernelVersion: 4.21
...@@ -76,6 +85,8 @@ Description: This attribute holds current Thunderbolt security level ...@@ -76,6 +85,8 @@ Description: This attribute holds current Thunderbolt security level
usbonly Automatically tunnel USB controller of the usbonly Automatically tunnel USB controller of the
connected Thunderbolt dock (and Display Port). All connected Thunderbolt dock (and Display Port). All
PCIe links downstream of the dock are removed. PCIe links downstream of the dock are removed.
nopcie USB4 system where PCIe tunneling is disabled from
the BIOS.
======= ================================================== ======= ==================================================
What: /sys/bus/thunderbolt/devices/.../authorized What: /sys/bus/thunderbolt/devices/.../authorized
...@@ -84,22 +95,25 @@ KernelVersion: 4.13 ...@@ -84,22 +95,25 @@ KernelVersion: 4.13
Contact: thunderbolt-software@lists.01.org Contact: thunderbolt-software@lists.01.org
Description: This attribute is used to authorize Thunderbolt devices Description: This attribute is used to authorize Thunderbolt devices
after they have been connected. If the device is not after they have been connected. If the device is not
authorized, no devices such as PCIe and Display port are authorized, no PCIe devices are available to the system.
available to the system.
Contents of this attribute will be 0 when the device is not Contents of this attribute will be 0 when the device is not
yet authorized. yet authorized.
Possible values are supported: Possible values are supported:
== =========================================== == ===================================================
0 The device will be de-authorized (only supported if
deauthorization attribute under domain contains 1)
1 The device will be authorized and connected 1 The device will be authorized and connected
== =========================================== == ===================================================
When key attribute contains 32 byte hex string the possible When key attribute contains 32 byte hex string the possible
values are: values are:
== ======================================================== == ========================================================
0 The device will be de-authorized (only supported if
deauthorization attribute under domain contains 1)
1 The 32 byte hex string is added to the device NVM and 1 The 32 byte hex string is added to the device NVM and
the device is authorized. the device is authorized.
2 Send a challenge based on the 32 byte hex string. If the 2 Send a challenge based on the 32 byte hex string. If the
......
...@@ -105,7 +105,25 @@ Date: April 2017 ...@@ -105,7 +105,25 @@ Date: April 2017
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description: Description:
Revision number of the supported USB Power Delivery Revision number of the supported USB Power Delivery
specification, or 0 when USB Power Delivery is not supported. specification, or 0.0 when USB Power Delivery is not supported.
Example values:
- "2.0": USB Power Delivery Release 2.0
- "3.0": USB Power Delivery Release 3.0
- "3.1": USB Power Delivery Release 3.1
What: /sys/class/typec/<port>-{partner|cable}/usb_power_delivery_revision
Date: January 2021
Contact: Benson Leung <bleung@chromium.org>
Description:
Revision number of the supported USB Power Delivery
specification of the port partner or cable, or 0.0 when USB
Power Delivery is not supported.
Example values:
- "2.0": USB Power Delivery Release 2.0
- "3.0": USB Power Delivery Release 3.0
- "3.1": USB Power Delivery Release 3.1
What: /sys/class/typec/<port>/usb_typec_revision What: /sys/class/typec/<port>/usb_typec_revision
Date: April 2017 Date: April 2017
......
...@@ -47,6 +47,9 @@ be DMA masters and thus read contents of the host memory without CPU and OS ...@@ -47,6 +47,9 @@ be DMA masters and thus read contents of the host memory without CPU and OS
knowing about it. There are ways to prevent this by setting up an IOMMU but knowing about it. There are ways to prevent this by setting up an IOMMU but
it is not always available for various reasons. it is not always available for various reasons.
Some USB4 systems have a BIOS setting to disable PCIe tunneling. This is
treated as another security level (nopcie).
The security levels are as follows: The security levels are as follows:
none none
...@@ -77,6 +80,10 @@ The security levels are as follows: ...@@ -77,6 +80,10 @@ The security levels are as follows:
Display Port in a dock. All PCIe links downstream of the dock are Display Port in a dock. All PCIe links downstream of the dock are
removed. removed.
nopcie
PCIe tunneling is disabled/forbidden from the BIOS. Available in some
USB4 systems.
The current security level can be read from The current security level can be read from
``/sys/bus/thunderbolt/devices/domainX/security`` where ``domainX`` is ``/sys/bus/thunderbolt/devices/domainX/security`` where ``domainX`` is
the Thunderbolt domain the host controller manages. There is typically the Thunderbolt domain the host controller manages. There is typically
...@@ -153,6 +160,22 @@ If the user still wants to connect the device they can either approve ...@@ -153,6 +160,22 @@ If the user still wants to connect the device they can either approve
the device without a key or write a new key and write 1 to the the device without a key or write a new key and write 1 to the
``authorized`` file to get the new key stored on the device NVM. ``authorized`` file to get the new key stored on the device NVM.
De-authorizing devices
----------------------
It is possible to de-authorize devices by writing ``0`` to their
``authorized`` attribute. This requires support from the connection
manager implementation and can be checked by reading domain
``deauthorization`` attribute. If it reads ``1`` then the feature is
supported.
When a device is de-authorized the PCIe tunnel from the parent device
PCIe downstream (or root) port to the device PCIe upstream port is torn
down. This is essentially the same thing as PCIe hot-remove and the PCIe
toplogy in question will not be accessible anymore until the device is
authorized again. If there is storage such as NVMe or similar involved,
there is a risk for data loss if the filesystem on that storage is not
properly shut down. You have been warned!
DMA protection utilizing IOMMU DMA protection utilizing IOMMU
------------------------------ ------------------------------
Recent systems from 2018 and forward with Thunderbolt ports may natively Recent systems from 2018 and forward with Thunderbolt ports may natively
......
...@@ -137,6 +137,18 @@ properties: ...@@ -137,6 +137,18 @@ properties:
maxItems: 7 maxItems: 7
$ref: /schemas/types.yaml#/definitions/uint32-array $ref: /schemas/types.yaml#/definitions/uint32-array
sink-vdos:
description: An array of u32 with each entry, a Vendor Defined Message Object (VDO),
providing additional information corresponding to the product, the detailed bit
definitions and the order of each VDO can be found in
"USB Power Delivery Specification Revision 3.0, Version 2.0 + ECNs 2020-12-10"
chapter 6.4.4.3.1 Discover Identity. User can specify the VDO array via
VDO_IDH/_CERT/_PRODUCT/_UFP/_DFP/_PCABLE/_ACABLE(1/2)/_VPD() defined in
dt-bindings/usb/pd.h.
minItems: 3
maxItems: 6
$ref: /schemas/types.yaml#/definitions/uint32-array
op-sink-microwatt: op-sink-microwatt:
description: Sink required operating power in microwatt, if source can't description: Sink required operating power in microwatt, if source can't
offer the power, Capability Mismatch is set. Required for power sink and offer the power, Capability Mismatch is set. Required for power sink and
......
...@@ -4,7 +4,7 @@ Generic Bluetooth controller over USB (btusb driver) ...@@ -4,7 +4,7 @@ Generic Bluetooth controller over USB (btusb driver)
Required properties: Required properties:
- compatible : should comply with the format "usbVID,PID" specified in - compatible : should comply with the format "usbVID,PID" specified in
Documentation/devicetree/bindings/usb/usb-device.txt Documentation/devicetree/bindings/usb/usb-device.yaml
At the time of writing, the only OF supported devices At the time of writing, the only OF supported devices
(more may be added later) are: (more may be added later) are:
......
...@@ -79,7 +79,9 @@ properties: ...@@ -79,7 +79,9 @@ properties:
patternProperties: patternProperties:
"^usb@[0-9a-f]+$": "^usb@[0-9a-f]+$":
type: object oneOf:
- $ref: dwc2.yaml#
- $ref: snps,dwc3.yaml#
additionalProperties: false additionalProperties: false
...@@ -229,6 +231,6 @@ examples: ...@@ -229,6 +231,6 @@ examples:
interrupts = <30>; interrupts = <30>;
dr_mode = "host"; dr_mode = "host";
snps,dis_u2_susphy_quirk; snps,dis_u2_susphy_quirk;
snps,quirk-frame-length-adjustment; snps,quirk-frame-length-adjustment = <0x20>;
}; };
}; };
...@@ -31,13 +31,13 @@ See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt ...@@ -31,13 +31,13 @@ See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Sub-nodes: Sub-nodes:
The dwc3 core should be added as subnode to ST DWC3 glue as shown in the The dwc3 core should be added as subnode to ST DWC3 glue as shown in the
example below. The DT binding details of dwc3 can be found in: example below. The DT binding details of dwc3 can be found in:
Documentation/devicetree/bindings/usb/dwc3.txt Documentation/devicetree/bindings/usb/snps,dwc3.yaml
NB: The dr_mode property described in [1] is NOT optional for this driver, as the default value NB: The dr_mode property described in [1] is NOT optional for this driver, as the default value
is "otg", which isn't supported by this SoC. Valid dr_mode values for dwc3-st are either "host" is "otg", which isn't supported by this SoC. Valid dr_mode values for dwc3-st are either "host"
or "device". or "device".
[1] Documentation/devicetree/bindings/usb/generic.txt [1] Documentation/devicetree/bindings/usb/usb-drd.yaml
Example: Example:
......
...@@ -19,7 +19,7 @@ Example device node: ...@@ -19,7 +19,7 @@ Example device node:
#address-cells = <0x2>; #address-cells = <0x2>;
#size-cells = <0x1>; #size-cells = <0x1>;
compatible = "xlnx,zynqmp-dwc3"; compatible = "xlnx,zynqmp-dwc3";
clock-names = "bus_clk" "ref_clk"; clock-names = "bus_clk", "ref_clk";
clocks = <&clk125>, <&clk125>; clocks = <&clk125>, <&clk125>;
ranges; ranges;
......
synopsys DWC3 CORE
DWC3- USB3 CONTROLLER. Complies to the generic USB binding properties
as described in 'usb/generic.txt'
Required properties:
- compatible: must be "snps,dwc3"
- reg : Address and length of the register set for the device
- interrupts: Interrupts used by the dwc3 controller.
- clock-names: list of clock names. Ideally should be "ref",
"bus_early", "suspend" but may be less or more.
- clocks: list of phandle and clock specifier pairs corresponding to
entries in the clock-names property.
Exception for clocks:
clocks are optional if the parent node (i.e. glue-layer) is compatible to
one of the following:
"cavium,octeon-7130-usb-uctl"
"qcom,dwc3"
"samsung,exynos5250-dwusb3"
"samsung,exynos5433-dwusb3"
"samsung,exynos7-dwusb3"
"sprd,sc9860-dwc3"
"st,stih407-dwc3"
"ti,am437x-dwc3"
"ti,dwc3"
"ti,keystone-dwc3"
"rockchip,rk3399-dwc3"
"xlnx,zynqmp-dwc3"
Optional properties:
- usb-phy : array of phandle for the PHY device. The first element
in the array is expected to be a handle to the USB2/HS PHY and
the second element is expected to be a handle to the USB3/SS PHY
- phys: from the *Generic PHY* bindings
- phy-names: from the *Generic PHY* bindings; supported names are "usb2-phy"
or "usb3-phy".
- resets: set of phandle and reset specifier pairs
- snps,usb2-lpm-disable: indicate if we don't want to enable USB2 HW LPM
- snps,usb3_lpm_capable: determines if platform is USB3 LPM capable
- snps,dis-start-transfer-quirk: when set, disable isoc START TRANSFER command
failure SW work-around for DWC_usb31 version 1.70a-ea06
and prior.
- snps,disable_scramble_quirk: true when SW should disable data scrambling.
Only really useful for FPGA builds.
- snps,has-lpm-erratum: true when DWC3 was configured with LPM Erratum enabled
- snps,lpm-nyet-threshold: LPM NYET threshold
- snps,u2exit_lfps_quirk: set if we want to enable u2exit lfps quirk
- snps,u2ss_inp3_quirk: set if we enable P3 OK for U2/SS Inactive quirk
- snps,req_p1p2p3_quirk: when set, the core will always request for
P1/P2/P3 transition sequence.
- snps,del_p1p2p3_quirk: when set core will delay P1/P2/P3 until a certain
amount of 8B10B errors occur.
- snps,del_phy_power_chg_quirk: when set core will delay PHY power change
from P0 to P1/P2/P3.
- snps,lfps_filter_quirk: when set core will filter LFPS reception.
- snps,rx_detect_poll_quirk: when set core will disable a 400us delay to start
Polling LFPS after RX.Detect.
- snps,tx_de_emphasis_quirk: when set core will set Tx de-emphasis value.
- snps,tx_de_emphasis: the value driven to the PHY is controlled by the
LTSSM during USB3 Compliance mode.
- snps,dis_u3_susphy_quirk: when set core will disable USB3 suspend phy.
- snps,dis_u2_susphy_quirk: when set core will disable USB2 suspend phy.
- snps,dis_enblslpm_quirk: when set clears the enblslpm in GUSB2PHYCFG,
disabling the suspend signal to the PHY.
- snps,dis-u1-entry-quirk: set if link entering into U1 needs to be disabled.
- snps,dis-u2-entry-quirk: set if link entering into U2 needs to be disabled.
- snps,dis_rxdet_inp3_quirk: when set core will disable receiver detection
in PHY P3 power state.
- snps,dis-u2-freeclk-exists-quirk: when set, clear the u2_freeclk_exists
in GUSB2PHYCFG, specify that USB2 PHY doesn't provide
a free-running PHY clock.
- snps,dis-del-phy-power-chg-quirk: when set core will change PHY power
from P0 to P1/P2/P3 without delay.
- snps,dis-tx-ipgap-linecheck-quirk: when set, disable u2mac linestate check
during HS transmit.
- snps,parkmode-disable-ss-quirk: when set, all SuperSpeed bus instances in
park mode are disabled.
- snps,dis_metastability_quirk: when set, disable metastability workaround.
CAUTION: use only if you are absolutely sure of it.
- snps,dis-split-quirk: when set, change the way URBs are handled by the
driver. Needed to avoid -EPROTO errors with usbhid
on some devices (Hikey 970).
- snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
utmi_l1_suspend_n, false when asserts utmi_sleep_n
- snps,hird-threshold: HIRD threshold
- snps,hsphy_interface: High-Speed PHY interface selection between "utmi" for
UTMI+ and "ulpi" for ULPI when the DWC_USB3_HSPHY_INTERFACE has value 3.
- snps,quirk-frame-length-adjustment: Value for GFLADJ_30MHZ field of GFLADJ
register for post-silicon frame length adjustment when the
fladj_30mhz_sdbnd signal is invalid or incorrect.
- snps,rx-thr-num-pkt-prd: periodic ESS RX packet threshold count - host mode
only. Set this and rx-max-burst-prd to a valid,
non-zero value 1-16 (DWC_usb31 programming guide
section 1.2.4) to enable periodic ESS RX threshold.
- snps,rx-max-burst-prd: max periodic ESS RX burst size - host mode only. Set
this and rx-thr-num-pkt-prd to a valid, non-zero value
1-16 (DWC_usb31 programming guide section 1.2.4) to
enable periodic ESS RX threshold.
- snps,tx-thr-num-pkt-prd: periodic ESS TX packet threshold count - host mode
only. Set this and tx-max-burst-prd to a valid,
non-zero value 1-16 (DWC_usb31 programming guide
section 1.2.3) to enable periodic ESS TX threshold.
- snps,tx-max-burst-prd: max periodic ESS TX burst size - host mode only. Set
this and tx-thr-num-pkt-prd to a valid, non-zero value
1-16 (DWC_usb31 programming guide section 1.2.3) to
enable periodic ESS TX threshold.
- <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to be reallocated.
- snps,incr-burst-type-adjustment: Value for INCR burst type of GSBUSCFG0
register, undefined length INCR burst type enable and INCRx type.
When just one value, which means INCRX burst mode enabled. When
more than one value, which means undefined length INCR burst type
enabled. The values can be 1, 4, 8, 16, 32, 64, 128 and 256.
- in addition all properties from usb-xhci.txt from the current directory are
supported as well
This is usually a subnode to DWC3 glue to which it is connected.
dwc3@4a030000 {
compatible = "snps,dwc3";
reg = <0x4a030000 0xcfff>;
interrupts = <0 92 4>
usb-phy = <&usb2_phy>, <&usb3,phy>;
snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
};
...@@ -93,7 +93,7 @@ Sub-nodes: ...@@ -93,7 +93,7 @@ Sub-nodes:
The dwc3 core should be added as subnode to Exynos dwc3 glue. The dwc3 core should be added as subnode to Exynos dwc3 glue.
- dwc3 : - dwc3 :
The binding details of dwc3 can be found in: The binding details of dwc3 can be found in:
Documentation/devicetree/bindings/usb/dwc3.txt Documentation/devicetree/bindings/usb/snps,dwc3.yaml
Example: Example:
usb@12000000 { usb@12000000 {
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2020 NXP
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/fsl,imx8mp-dwc3.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP iMX8MP Soc USB Controller
maintainers:
- Li Jun <jun.li@nxp.com>
properties:
compatible:
const: fsl,imx8mp-dwc3
reg:
maxItems: 1
description: Address and length of the register set for the wrapper of
dwc3 core on the SOC.
"#address-cells":
enum: [ 1, 2 ]
"#size-cells":
enum: [ 1, 2 ]
dma-ranges:
description:
See section 2.3.9 of the DeviceTree Specification.
ranges: true
interrupts:
maxItems: 1
description: The interrupt that is asserted when a wakeup event is
received.
clocks:
description:
A list of phandle and clock-specifier pairs for the clocks
listed in clock-names.
items:
- description: system hsio root clock.
- description: suspend clock, used for usb wakeup logic.
clock-names:
items:
- const: hsio
- const: suspend
# Required child node:
patternProperties:
"^dwc3@[0-9a-f]+$":
type: object
description:
A child node must exist to represent the core DWC3 IP block
The content of the node is defined in dwc3.txt.
required:
- compatible
- reg
- "#address-cells"
- "#size-cells"
- dma-ranges
- ranges
- clocks
- clock-names
- interrupts
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/imx8mp-clock.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
usb3_0: usb@32f10100 {
compatible = "fsl,imx8mp-dwc3";
reg = <0x32f10100 0x8>;
clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
<&clk IMX8MP_CLK_USB_ROOT>;
clock-names = "hsio", "suspend";
interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <1>;
dma-ranges = <0x40000000 0x40000000 0xc0000000>;
ranges;
dwc3@38100000 {
compatible = "snps,dwc3";
reg = <0x38100000 0x10000>;
clocks = <&clk IMX8MP_CLK_HSIO_AXI>,
<&clk IMX8MP_CLK_USB_CORE_REF>,
<&clk IMX8MP_CLK_USB_ROOT>;
clock-names = "bus_early", "ref", "suspend";
assigned-clocks = <&clk IMX8MP_CLK_HSIO_AXI>;
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_500M>;
assigned-clock-rates = <500000000>;
interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
phys = <&usb3_phy0>, <&usb3_phy0>;
phy-names = "usb2-phy", "usb3-phy";
snps,dis-u2-freeclk-exists-quirk;
};
};
...@@ -24,8 +24,53 @@ allOf: ...@@ -24,8 +24,53 @@ allOf:
properties: properties:
compatible: compatible:
contains: oneOf:
const: generic-ehci - items:
- enum:
- allwinner,sun4i-a10-ehci
- allwinner,sun50i-a64-ehci
- allwinner,sun50i-h6-ehci
- allwinner,sun5i-a13-ehci
- allwinner,sun6i-a31-ehci
- allwinner,sun7i-a20-ehci
- allwinner,sun8i-a23-ehci
- allwinner,sun8i-h3-ehci
- allwinner,sun8i-r40-ehci
- allwinner,sun9i-a80-ehci
- aspeed,ast2400-ehci
- aspeed,ast2500-ehci
- aspeed,ast2600-ehci
- brcm,bcm3384-ehci
- brcm,bcm63268-ehci
- brcm,bcm6328-ehci
- brcm,bcm6358-ehci
- brcm,bcm6362-ehci
- brcm,bcm6368-ehci
- brcm,bcm7125-ehci
- brcm,bcm7346-ehci
- brcm,bcm7358-ehci
- brcm,bcm7360-ehci
- brcm,bcm7362-ehci
- brcm,bcm7420-ehci
- brcm,bcm7425-ehci
- brcm,bcm7435-ehci
- ibm,476gtr-ehci
- nxp,lpc1850-ehci
- qca,ar7100-ehci
- snps,hsdk-v1.0-ehci
- socionext,uniphier-ehci
- const: generic-ehci
- items:
- enum:
- cavium,octeon-6335-ehci
- ibm,usb-ehci-440epx
- ibm,usb-ehci-460ex
- nintendo,hollywood-usb-ehci
- st,spear600-ehci
- const: usb-ehci
- enum:
- generic-ehci
- usb-ehci
reg: reg:
minItems: 1 minItems: 1
...@@ -101,7 +146,7 @@ additionalProperties: false ...@@ -101,7 +146,7 @@ additionalProperties: false
examples: examples:
- | - |
usb@e0000300 { usb@e0000300 {
compatible = "ibm,usb-ehci-440epx", "generic-ehci"; compatible = "ibm,usb-ehci-440epx", "usb-ehci";
interrupt-parent = <&UIC0>; interrupt-parent = <&UIC0>;
interrupts = <0x1a 4>; interrupts = <0x1a 4>;
reg = <0xe0000300 90>, <0xe0000390 70>; reg = <0xe0000300 90>, <0xe0000390 70>;
......
...@@ -14,8 +14,38 @@ maintainers: ...@@ -14,8 +14,38 @@ maintainers:
properties: properties:
compatible: compatible:
contains: oneOf:
const: generic-ohci - items:
- enum:
- allwinner,sun4i-a10-ohci
- allwinner,sun50i-a64-ohci
- allwinner,sun50i-h6-ohci
- allwinner,sun5i-a13-ohci
- allwinner,sun6i-a31-ohci
- allwinner,sun7i-a20-ohci
- allwinner,sun8i-a23-ohci
- allwinner,sun8i-h3-ohci
- allwinner,sun8i-r40-ohci
- allwinner,sun9i-a80-ohci
- brcm,bcm3384-ohci
- brcm,bcm63268-ohci
- brcm,bcm6328-ohci
- brcm,bcm6358-ohci
- brcm,bcm6362-ohci
- brcm,bcm6368-ohci
- brcm,bcm7125-ohci
- brcm,bcm7346-ohci
- brcm,bcm7358-ohci
- brcm,bcm7360-ohci
- brcm,bcm7362-ohci
- brcm,bcm7420-ohci
- brcm,bcm7425-ohci
- brcm,bcm7435-ohci
- ibm,476gtr-ohci
- ingenic,jz4740-ohci
- snps,hsdk-v1.0-ohci
- const: generic-ohci
- const: generic-ohci
reg: reg:
maxItems: 1 maxItems: 1
......
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/generic-xhci.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: USB xHCI Controller Device Tree Bindings
maintainers:
- Mathias Nyman <mathias.nyman@intel.com>
allOf:
- $ref: "usb-xhci.yaml#"
properties:
compatible:
oneOf:
- description: Generic xHCI device
const: generic-xhci
- description: Armada 37xx/375/38x/8k SoCs
items:
- enum:
- marvell,armada3700-xhci
- marvell,armada-375-xhci
- marvell,armada-380-xhci
- marvell,armada-8k-xhci
- const: generic-xhci
- description: Broadcom STB SoCs with xHCI
enum:
- brcm,xhci-brcm-v2
- brcm,bcm7445-xhci
- description: Generic xHCI device
const: xhci-platform
deprecated: true
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
minItems: 1
maxItems: 2
clock-names:
minItems: 1
items:
- const: core
- const: reg
unevaluatedProperties: false
required:
- compatible
- reg
- interrupts
examples:
- |
usb@f0931000 {
compatible = "generic-xhci";
reg = <0xf0931000 0x8c8>;
interrupts = <0x0 0x4e 0x0>;
};
Generic USB Properties
Optional properties:
- maximum-speed: tells USB controllers we want to work up to a certain
speed. Valid arguments are "super-speed-plus",
"super-speed", "high-speed", "full-speed" and
"low-speed". In case this isn't passed via DT, USB
controllers should default to their maximum HW
capability.
- dr_mode: tells Dual-Role USB controllers that we want to work on a
particular mode. Valid arguments are "host",
"peripheral" and "otg". In case this attribute isn't
passed via DT, USB DRD controllers should default to
OTG.
- phy_type: tells USB controllers that we want to configure the core to support
a UTMI+ PHY with an 8- or 16-bit interface if UTMI+ is
selected. Valid arguments are "utmi" and "utmi_wide".
In case this isn't passed via DT, USB controllers should
default to HW capability.
- otg-rev: tells usb driver the release number of the OTG and EH supplement
with which the device and its descriptors are compliant,
in binary-coded decimal (i.e. 2.0 is 0200H). This
property is used if any real OTG features(HNP/SRP/ADP)
is enabled, if ADP is required, otg-rev should be
0x0200 or above.
- companion: phandle of a companion
- hnp-disable: tells OTG controllers we want to disable OTG HNP, normally HNP
is the basic function of real OTG except you want it
to be a srp-capable only B device.
- srp-disable: tells OTG controllers we want to disable OTG SRP, SRP is
optional for OTG device.
- adp-disable: tells OTG controllers we want to disable OTG ADP, ADP is
optional for OTG device.
- usb-role-switch: boolean, indicates that the device is capable of assigning
the USB data role (USB host or USB device) for a given
USB connector, such as Type-C, Type-B(micro).
see connector/usb-connector.yaml.
- role-switch-default-mode: indicating if usb-role-switch is enabled, the
device default operation mode of controller while usb
role is USB_ROLE_NONE. Valid arguments are "host" and
"peripheral". Defaults to "peripheral" if not
specified.
This is an attribute to a USB controller such as:
dwc3@4a030000 {
compatible = "synopsys,dwc3";
reg = <0x4a030000 0xcfff>;
interrupts = <0 92 4>
usb-phy = <&usb2_phy>, <&usb3,phy>;
maximum-speed = "super-speed";
dr_mode = "otg";
phy_type = "utmi_wide";
otg-rev = <0x0200>;
adp-disable;
};
...@@ -34,11 +34,8 @@ properties: ...@@ -34,11 +34,8 @@ properties:
# Required child node: # Required child node:
patternProperties: patternProperties:
"^dwc3@[0-9a-f]+$": "^usb@[0-9a-f]+$":
type: object $ref: snps,dwc3.yaml#
description:
A child node must exist to represent the core DWC3 IP block.
The content of the node is defined in dwc3.txt.
required: required:
- compatible - compatible
...@@ -68,7 +65,7 @@ examples: ...@@ -68,7 +65,7 @@ examples:
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
dwc3@34000000 { usb@34000000 {
compatible = "snps,dwc3"; compatible = "snps,dwc3";
reg = <0x34000000 0x10000>; reg = <0x34000000 0x10000>;
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
......
MT8173 xHCI
The device node for Mediatek SOC USB3.0 host controller
There are two scenarios: the first one only supports xHCI driver;
the second one supports dual-role mode, and the host is based on xHCI
driver. Take account of backward compatibility, we divide bindings
into two parts.
1st: only supports xHCI driver
------------------------------------------------------------------------
Required properties:
- compatible : should be "mediatek,<soc-model>-xhci", "mediatek,mtk-xhci",
soc-model is the name of SoC, such as mt8173, mt2712 etc, when using
"mediatek,mtk-xhci" compatible string, you need SoC specific ones in
addition, one of:
- "mediatek,mt8173-xhci"
- reg : specifies physical base address and size of the registers
- reg-names: should be "mac" for xHCI MAC and "ippc" for IP port control
- interrupts : interrupt used by the controller
- power-domains : a phandle to USB power domain node to control USB's
mtcmos
- vusb33-supply : regulator of USB avdd3.3v
- clocks : a list of phandle + clock-specifier pairs, one for each
entry in clock-names
- clock-names : must contain
"sys_ck": controller clock used by normal mode,
the following ones are optional:
"ref_ck": reference clock used by low power mode etc,
"mcu_ck": mcu_bus clock for register access,
"dma_ck": dma_bus clock for data transfer by DMA,
"xhci_ck": controller clock
- phys : see usb-hcd.yaml in the current directory
Optional properties:
- wakeup-source : enable USB remote wakeup;
- mediatek,syscon-wakeup : phandle to syscon used to access the register
of the USB wakeup glue layer between xHCI and SPM; it depends on
"wakeup-source", and has two arguments:
- the first one : register base address of the glue layer in syscon;
- the second one : hardware version of the glue layer
- 1 : used by mt8173 etc
- 2 : used by mt2712 etc
- mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc;
- vbus-supply : reference to the VBUS regulator;
- usb3-lpm-capable : supports USB3.0 LPM
- pinctrl-names : a pinctrl state named "default" must be defined
- pinctrl-0 : pin control group
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
- imod-interval-ns: default interrupt moderation interval is 5000ns
additionally the properties from usb-hcd.yaml (in the current directory) are
supported.
Example:
usb30: usb@11270000 {
compatible = "mediatek,mt8173-xhci";
reg = <0 0x11270000 0 0x1000>,
<0 0x11280700 0 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>,
<&pericfg CLK_PERI_USB0>,
<&pericfg CLK_PERI_USB1>;
clock-names = "sys_ck", "ref_ck";
phys = <&phy_port0 PHY_TYPE_USB3>,
<&phy_port1 PHY_TYPE_USB2>;
vusb33-supply = <&mt6397_vusb_reg>;
vbus-supply = <&usb_p1_vbus>;
usb3-lpm-capable;
mediatek,syscon-wakeup = <&pericfg 0x400 1>;
wakeup-source;
imod-interval-ns = <10000>;
};
2nd: dual-role mode with xHCI driver
------------------------------------------------------------------------
In the case, xhci is added as subnode to mtu3. An example and the DT binding
details of mtu3 can be found in:
Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
Required properties:
- compatible : should be "mediatek,<soc-model>-xhci", "mediatek,mtk-xhci",
soc-model is the name of SoC, such as mt8173, mt2712 etc, when using
"mediatek,mtk-xhci" compatible string, you need SoC specific ones in
addition, one of:
- "mediatek,mt8173-xhci"
- reg : specifies physical base address and size of the registers
- reg-names: should be "mac" for xHCI MAC
- interrupts : interrupt used by the host controller
- power-domains : a phandle to USB power domain node to control USB's
mtcmos
- vusb33-supply : regulator of USB avdd3.3v
- clocks : a list of phandle + clock-specifier pairs, one for each
entry in clock-names
- clock-names : must contain "sys_ck", and the following ones are optional:
"ref_ck", "mcu_ck" and "dma_ck", "xhci_ck"
Optional properties:
- vbus-supply : reference to the VBUS regulator;
- usb3-lpm-capable : supports USB3.0 LPM
Example:
usb30: usb@11270000 {
compatible = "mediatek,mt8173-xhci";
reg = <0 0x11270000 0 0x1000>;
reg-names = "mac";
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>;
clock-names = "sys_ck", "ref_ck";
vusb33-supply = <&mt6397_vusb_reg>;
usb3-lpm-capable;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2020 MediaTek
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/mediatek,mtk-xhci.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek USB3 xHCI Device Tree Bindings
maintainers:
- Chunfeng Yun <chunfeng.yun@mediatek.com>
allOf:
- $ref: "usb-xhci.yaml"
description: |
There are two scenarios:
case 1: only supports xHCI driver;
case 2: supports dual-role mode, and the host is based on xHCI driver.
properties:
# common properties for both case 1 and case 2
compatible:
items:
- enum:
- mediatek,mt2701-xhci
- mediatek,mt2712-xhci
- mediatek,mt7622-xhci
- mediatek,mt7623-xhci
- mediatek,mt7629-xhci
- mediatek,mt8173-xhci
- mediatek,mt8183-xhci
- const: mediatek,mtk-xhci
reg:
minItems: 1
items:
- description: the registers of xHCI MAC
- description: the registers of IP Port Control
reg-names:
minItems: 1
items:
- const: mac
- const: ippc # optional, only needed for case 1.
interrupts:
maxItems: 1
power-domains:
description: A phandle to USB power domain node to control USB's MTCMOS
maxItems: 1
clocks:
minItems: 1
items:
- description: Controller clock used by normal mode
- description: Reference clock used by low power mode etc
- description: Mcu bus clock for register access
- description: DMA bus clock for data transfer
- description: controller clock
clock-names:
minItems: 1
items:
- const: sys_ck # required, the following ones are optional
- const: ref_ck
- const: mcu_ck
- const: dma_ck
- const: xhci_ck
assigned-clocks:
minItems: 1
maxItems: 5
assigned-clock-parents:
minItems: 1
maxItems: 5
phys:
description:
List of all PHYs used on this HCD, it's better to keep PHYs in order
as the hardware layout
minItems: 1
items:
- description: USB2/HS PHY # required, others are optional
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
vusb33-supply:
description: Regulator of USB AVDD3.3v
vbus-supply:
description: Regulator of USB VBUS5v
usb3-lpm-capable:
description: supports USB3.0 LPM
type: boolean
imod-interval-ns:
description:
Interrupt moderation interval value, it is 8 times as much as that
defined in the xHCI spec on MTK's controller.
default: 5000
# the following properties are only used for case 1
wakeup-source:
description: enable USB remote wakeup, see power/wakeup-source.txt
type: boolean
mediatek,syscon-wakeup:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
description:
A phandle to syscon used to access the register of the USB wakeup glue
layer between xHCI and SPM, the field should always be 3 cells long.
items:
items:
- description:
The first cell represents a phandle to syscon
- description:
The second cell represents the register base address of the glue
layer in syscon
- description:
The third cell represents the hardware version of the glue layer,
1 is used by mt8173 etc, 2 is used by mt2712 etc
enum: [1, 2]
mediatek,u3p-dis-msk:
$ref: /schemas/types.yaml#/definitions/uint32
description: The mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc
"#address-cells":
const: 1
"#size-cells":
const: 0
patternProperties:
"@[0-9a-f]{1}$":
type: object
description: The hard wired USB devices.
dependencies:
wakeup-source: [ 'mediatek,syscon-wakeup' ]
required:
- compatible
- reg
- reg-names
- interrupts
- clocks
- clock-names
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/mt8173-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/power/mt8173-power.h>
usb@11270000 {
compatible = "mediatek,mt8173-xhci", "mediatek,mtk-xhci";
reg = <0x11270000 0x1000>, <0x11280700 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>;
clock-names = "sys_ck", "ref_ck";
phys = <&u3port0 PHY_TYPE_USB3>, <&u2port1 PHY_TYPE_USB2>;
vusb33-supply = <&mt6397_vusb_reg>;
vbus-supply = <&usb_p1_vbus>;
imod-interval-ns = <10000>;
mediatek,syscon-wakeup = <&pericfg 0x400 1>;
wakeup-source;
usb3-lpm-capable;
};
...
The device node for Mediatek USB3.0 DRD controller
Required properties:
- compatible : should be "mediatek,<soc-model>-mtu3", "mediatek,mtu3",
soc-model is the name of SoC, such as mt8173, mt2712 etc,
when using "mediatek,mtu3" compatible string, you need SoC specific
ones in addition, one of:
- "mediatek,mt8173-mtu3"
- reg : specifies physical base address and size of the registers
- reg-names: should be "mac" for device IP and "ippc" for IP port control
- interrupts : interrupt used by the device IP
- power-domains : a phandle to USB power domain node to control USB's
mtcmos
- vusb33-supply : regulator of USB avdd3.3v
- clocks : a list of phandle + clock-specifier pairs, one for each
entry in clock-names
- clock-names : must contain "sys_ck" for clock of controller,
the following clocks are optional:
"ref_ck", "mcu_ck" and "dma_ck";
- phys : see usb-hcd.yaml in the current directory
- dr_mode : should be one of "host", "peripheral" or "otg",
refer to usb/generic.txt
Optional properties:
- #address-cells, #size-cells : should be '2' if the device has sub-nodes
with 'reg' property
- ranges : allows valid 1:1 translation between child's address space and
parent's address space
- extcon : external connector for vbus and idpin changes detection, needed
when supports dual-role mode.
it's considered valid for compatibility reasons, not allowed for
new bindings, and use "usb-role-switch" property instead.
- vbus-supply : reference to the VBUS regulator, needed when supports
dual-role mode.
it's considered valid for compatibility reasons, not allowed for
new bindings, and put into a usb-connector node.
see connector/usb-connector.yaml.
- pinctrl-names : a pinctrl state named "default" is optional, and need be
defined if auto drd switch is enabled, that means the property dr_mode
is set as "otg", and meanwhile the property "mediatek,enable-manual-drd"
is not set.
- pinctrl-0 : pin control group
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
- maximum-speed : valid arguments are "super-speed", "high-speed" and
"full-speed"; refer to usb/generic.txt
- usb-role-switch : use USB Role Switch to support dual-role switch, but
not extcon; see usb/generic.txt.
- enable-manual-drd : supports manual dual-role switch via debugfs; usually
used when receptacle is TYPE-A and also wants to support dual-role
mode.
- wakeup-source: enable USB remote wakeup of host mode.
- mediatek,syscon-wakeup : phandle to syscon used to access the register
of the USB wakeup glue layer between SSUSB and SPM; it depends on
"wakeup-source", and has two arguments:
- the first one : register base address of the glue layer in syscon;
- the second one : hardware version of the glue layer
- 1 : used by mt8173 etc
- 2 : used by mt2712 etc
- mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc;
additionally the properties from usb-hcd.yaml (in the current directory) are
supported.
Sub-nodes:
The xhci should be added as subnode to mtu3 as shown in the following example
if host mode is enabled. The DT binding details of xhci can be found in:
Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
The port would be added as subnode if use "usb-role-switch" property.
see graph.txt
Example:
ssusb: usb@11271000 {
compatible = "mediatek,mt8173-mtu3";
reg = <0 0x11271000 0 0x3000>,
<0 0x11280700 0 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>;
phys = <&phy_port0 PHY_TYPE_USB3>,
<&phy_port1 PHY_TYPE_USB2>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>,
<&pericfg CLK_PERI_USB0>,
<&pericfg CLK_PERI_USB1>;
clock-names = "sys_ck", "ref_ck";
vusb33-supply = <&mt6397_vusb_reg>;
vbus-supply = <&usb_p0_vbus>;
extcon = <&extcon_usb>;
dr_mode = "otg";
wakeup-source;
mediatek,syscon-wakeup = <&pericfg 0x400 1>;
#address-cells = <2>;
#size-cells = <2>;
ranges;
usb_host: xhci@11270000 {
compatible = "mediatek,mt8173-xhci";
reg = <0 0x11270000 0 0x1000>;
reg-names = "mac";
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>;
clock-names = "sys_ck", "ref_ck";
vusb33-supply = <&mt6397_vusb_reg>;
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2020 MediaTek
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/mediatek,mtu3.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek USB3 DRD Controller Device Tree Bindings
maintainers:
- Chunfeng Yun <chunfeng.yun@mediatek.com>
allOf:
- $ref: "usb-drd.yaml"
description: |
The DRD controller has a glue layer IPPC (IP Port Control), and its host is
based on xHCI.
properties:
compatible:
items:
- enum:
- mediatek,mt2712-mtu3
- mediatek,mt8173-mtu3
- mediatek,mt8183-mtu3
- const: mediatek,mtu3
reg:
items:
- description: the registers of device MAC
- description: the registers of IP Port Control
reg-names:
items:
- const: mac
- const: ippc
interrupts:
maxItems: 1
power-domains:
description: A phandle to USB power domain node to control USB's MTCMOS
maxItems: 1
clocks:
minItems: 1
items:
- description: Controller clock used by normal mode
- description: Reference clock used by low power mode etc
- description: Mcu bus clock for register access
- description: DMA bus clock for data transfer
clock-names:
minItems: 1
items:
- const: sys_ck # required, others are optional
- const: ref_ck
- const: mcu_ck
- const: dma_ck
phys:
description:
List of all the USB PHYs used, it's better to keep the sequence
as the hardware layout.
minItems: 1
items:
- description: USB2/HS PHY # required, others are optional
- description: USB3/SS(P) PHY
- description: USB2/HS PHY # the following for backward compatible
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
vusb33-supply:
description: Regulator of USB AVDD3.3v
vbus-supply:
deprecated: true
description: |
Regulator of USB VBUS5v, needed when supports dual-role mode.
Particularly, if use an output GPIO to control a VBUS regulator, should
model it as a regulator. See bindings/regulator/fixed-regulator.yaml
It's considered valid for compatibility reasons, not allowed for
new bindings, and put into a usb-connector node.
dr_mode:
enum: [host, peripheral, otg]
default: otg
maximum-speed:
enum: [super-speed-plus, super-speed, high-speed, full-speed]
"#address-cells":
enum: [1, 2]
"#size-cells":
enum: [1, 2]
ranges: true
extcon:
deprecated: true
description: |
Phandle to the extcon device detecting the IDDIG/VBUS state, neede
when supports dual-role mode.
It's considered valid for compatibility reasons, not allowed for
new bindings, and use "usb-role-switch" property instead.
usb-role-switch:
$ref: /schemas/types.yaml#/definitions/flag
description: Support role switch.
type: boolean
connector:
$ref: /connector/usb-connector.yaml#
description:
Connector for dual role switch, especially for "gpio-usb-b-connector"
type: object
port:
description:
Any connector to the data bus of this controller should be modelled
using the OF graph bindings specified, if the "usb-role-switch"
property is used. See graph.txt
type: object
enable-manual-drd:
$ref: /schemas/types.yaml#/definitions/flag
description:
supports manual dual-role switch via debugfs; usually used when
receptacle is TYPE-A and also wants to support dual-role mode.
type: boolean
wakeup-source:
description: enable USB remote wakeup, see power/wakeup-source.txt
type: boolean
mediatek,syscon-wakeup:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
description:
A phandle to syscon used to access the register of the USB wakeup glue
layer between xHCI and SPM, the field should always be 3 cells long.
items:
items:
- description:
The first cell represents a phandle to syscon
- description:
The second cell represents the register base address of the glue
layer in syscon
- description:
The third cell represents the hardware version of the glue layer,
1 is used by mt8173 etc, 2 is used by mt2712 etc
enum: [1, 2]
mediatek,u3p-dis-msk:
$ref: /schemas/types.yaml#/definitions/uint32
description: The mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc
# Required child node when support dual-role
patternProperties:
"^usb@[0-9a-f]+$":
type: object
$ref: /usb/mediatek,mtk-xhci.yaml#
description:
The xhci should be added as subnode to mtu3 as shown in the following
example if the host mode is enabled.
dependencies:
connector: [ 'usb-role-switch' ]
port: [ 'usb-role-switch' ]
wakeup-source: [ 'mediatek,syscon-wakeup' ]
required:
- compatible
- reg
- reg-names
- interrupts
- clocks
- clock-names
additionalProperties: false
examples:
# Dual role switch by extcon
- |
#include <dt-bindings/clock/mt8173-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/power/mt8173-power.h>
usb@11271000 {
compatible = "mediatek,mt8173-mtu3", "mediatek,mtu3";
reg = <0x11271000 0x3000>, <0x11280700 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>;
phys = <&phy_port0 PHY_TYPE_USB3>, <&phy_port1 PHY_TYPE_USB2>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>;
clock-names = "sys_ck";
vusb33-supply = <&mt6397_vusb_reg>;
vbus-supply = <&usb_p0_vbus>;
extcon = <&extcon_usb>;
dr_mode = "otg";
wakeup-source;
mediatek,syscon-wakeup = <&pericfg 0x400 1>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
xhci: usb@11270000 {
compatible = "mediatek,mt8173-xhci", "mediatek,mtk-xhci";
reg = <0x11270000 0x1000>;
reg-names = "mac";
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>;
clock-names = "sys_ck", "ref_ck";
vusb33-supply = <&mt6397_vusb_reg>;
};
};
# Enable/disable device by an input gpio for VBUS pin
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/power/mt2712-power.h>
usb@112c1000 {
compatible = "mediatek,mt2712-mtu3", "mediatek,mtu3";
reg = <0x112c1000 0x3000>, <0x112d0700 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 248 IRQ_TYPE_LEVEL_LOW>;
phys = <&u2port2 PHY_TYPE_USB2>;
power-domains = <&scpsys MT2712_POWER_DOMAIN_USB2>;
clocks = <&topckgen CLK_TOP_USB30_SEL>;
clock-names = "sys_ck";
dr_mode = "peripheral";
usb-role-switch;
connector {
compatible = "gpio-usb-b-connector", "usb-b-connector";
type = "micro";
vbus-gpios = <&pio 13 GPIO_ACTIVE_HIGH>;
};
};
# Dual role switch with type-c
- |
usb@11201000 {
compatible ="mediatek,mt8183-mtu3", "mediatek,mtu3";
reg = <0x11201000 0x2e00>, <0x11203e00 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_LOW>;
phys = <&u2port0 PHY_TYPE_USB2>;
clocks = <&clk26m>;
clock-names = "sys_ck";
mediatek,syscon-wakeup = <&pericfg 0x400 1>;
wakeup-source;
dr_mode = "otg";
usb-role-switch;
#address-cells = <1>;
#size-cells = <1>;
ranges;
host: usb@11200000 {
compatible = "mediatek,mt8183-xhci", "mediatek,mtk-xhci";
reg = <0x11200000 0x1000>;
reg-names = "mac";
interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_LOW>;
clocks = <&clk26m>;
clock-names = "sys_ck";
};
port {
usb_role_sw: endpoint {
remote-endpoint = <&hs_ep>;
};
};
};
...
MediaTek musb DRD/OTG controller
-------------------------------------------
Required properties:
- compatible : should be one of:
"mediatek,mt2701-musb"
...
followed by "mediatek,mtk-musb"
- reg : specifies physical base address and size of
the registers
- interrupts : interrupt used by musb controller
- interrupt-names : must be "mc"
- phys : PHY specifier for the OTG phy
- dr_mode : should be one of "host", "peripheral" or "otg",
refer to usb/generic.txt
- clocks : a list of phandle + clock-specifier pairs, one for
each entry in clock-names
- clock-names : must contain "main", "mcu", "univpll"
for clocks of controller
Optional properties:
- power-domains : a phandle to USB power domain node to control USB's
MTCMOS
Required child nodes:
usb connector node as defined in bindings/connector/usb-connector.yaml
Optional properties:
- id-gpios : input GPIO for USB ID pin.
- vbus-gpios : input GPIO for USB VBUS pin.
- vbus-supply : reference to the VBUS regulator, needed when supports
dual-role mode
- usb-role-switch : use USB Role Switch to support dual-role switch, see
usb/generic.txt.
Example:
usb2: usb@11200000 {
compatible = "mediatek,mt2701-musb",
"mediatek,mtk-musb";
reg = <0 0x11200000 0 0x1000>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "mc";
phys = <&u2port2 PHY_TYPE_USB2>;
dr_mode = "otg";
clocks = <&pericfg CLK_PERI_USB0>,
<&pericfg CLK_PERI_USB0_MCU>,
<&pericfg CLK_PERI_USB_SLV>;
clock-names = "main","mcu","univpll";
power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
usb-role-switch;
connector{
compatible = "gpio-usb-b-connector", "usb-b-connector";
type = "micro";
id-gpios = <&pio 44 GPIO_ACTIVE_HIGH>;
vbus-supply = <&usb_vbus>;
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2020 MediaTek
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/mediatek,musb.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek MUSB DRD/OTG Controller Device Tree Bindings
maintainers:
- Min Guo <min.guo@mediatek.com>
properties:
$nodename:
pattern: '^usb@[0-9a-f]+$'
compatible:
items:
- enum:
- mediatek,mt8516-musb
- mediatek,mt2701-musb
- const: mediatek,mtk-musb
reg:
maxItems: 1
interrupts:
maxItems: 1
interrupt-names:
items:
- const: mc
clocks:
items:
- description: The main/core clock
- description: The system bus clock
- description: The 48Mhz clock
clock-names:
items:
- const: main
- const: mcu
- const: univpll
phys:
maxItems: 1
usb-role-switch:
$ref: /schemas/types.yaml#/definitions/flag
description: Support role switch. See usb/generic.txt
type: boolean
dr_mode:
enum:
- host
- otg
- peripheral
power-domains:
description: A phandle to USB power domain node to control USB's MTCMOS
maxItems: 1
connector:
$ref: /connector/usb-connector.yaml#
description: Connector for dual role switch
type: object
dependencies:
usb-role-switch: [ 'connector' ]
connector: [ 'usb-role-switch' ]
required:
- compatible
- reg
- interrupts
- interrupt-names
- phys
- clocks
- clock-names
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/mt2701-clk.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/power/mt2701-power.h>
usb@11200000 {
compatible = "mediatek,mt2701-musb", "mediatek,mtk-musb";
reg = <0x11200000 0x1000>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "mc";
phys = <&u2port2 PHY_TYPE_USB2>;
dr_mode = "otg";
clocks = <&pericfg CLK_PERI_USB0>,
<&pericfg CLK_PERI_USB0_MCU>,
<&pericfg CLK_PERI_USB_SLV>;
clock-names = "main","mcu","univpll";
power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
usb-role-switch;
connector {
compatible = "gpio-usb-b-connector", "usb-b-connector";
type = "micro";
id-gpios = <&pio 44 GPIO_ACTIVE_HIGH>;
vbus-supply = <&usb_vbus>;
};
};
...
...@@ -65,7 +65,7 @@ Sub-nodes: ...@@ -65,7 +65,7 @@ Sub-nodes:
The dwc3 core should be added as subnode to omap dwc3 glue. The dwc3 core should be added as subnode to omap dwc3 glue.
- dwc3 : - dwc3 :
The binding details of dwc3 can be found in: The binding details of dwc3 can be found in:
Documentation/devicetree/bindings/usb/dwc3.txt Documentation/devicetree/bindings/usb/snps,dwc3.yaml
omap_dwc3 { omap_dwc3 {
compatible = "ti,dwc3"; compatible = "ti,dwc3";
......
...@@ -18,6 +18,9 @@ properties: ...@@ -18,6 +18,9 @@ properties:
- qcom,sc7180-dwc3 - qcom,sc7180-dwc3
- qcom,sdm845-dwc3 - qcom,sdm845-dwc3
- qcom,sdx55-dwc3 - qcom,sdx55-dwc3
- qcom,sm8150-dwc3
- qcom,sm8250-dwc3
- qcom,sm8350-dwc3
- const: qcom,dwc3 - const: qcom,dwc3
reg: reg:
...@@ -104,11 +107,8 @@ properties: ...@@ -104,11 +107,8 @@ properties:
# Required child node: # Required child node:
patternProperties: patternProperties:
"^dwc3@[0-9a-f]+$": "^usb@[0-9a-f]+$":
type: object $ref: snps,dwc3.yaml#
description:
A child node must exist to represent the core DWC3 IP block
The content of the node is defined in dwc3.txt.
required: required:
- compatible - compatible
...@@ -163,7 +163,7 @@ examples: ...@@ -163,7 +163,7 @@ examples:
resets = <&gcc GCC_USB30_PRIM_BCR>; resets = <&gcc GCC_USB30_PRIM_BCR>;
dwc3@a600000 { usb@a600000 {
compatible = "snps,dwc3"; compatible = "snps,dwc3";
reg = <0 0x0a600000 0 0xcd00>; reg = <0 0x0a600000 0 0xcd00>;
interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
......
...@@ -11,7 +11,7 @@ maintainers: ...@@ -11,7 +11,7 @@ maintainers:
- Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> - Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
allOf: allOf:
- $ref: "usb-hcd.yaml" - $ref: "usb-xhci.yaml"
properties: properties:
compatible: compatible:
...@@ -68,7 +68,7 @@ required: ...@@ -68,7 +68,7 @@ required:
- power-domains - power-domains
- resets - resets
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
Rockchip SuperSpeed DWC3 USB SoC controller
Required properties:
- compatible: should contain "rockchip,rk3399-dwc3" for rk3399 SoC
- clocks: A list of phandle + clock-specifier pairs for the
clocks listed in clock-names
- clock-names: Should contain the following:
"ref_clk" Controller reference clk, have to be 24 MHz
"suspend_clk" Controller suspend clk, have to be 24 MHz or 32 KHz
"bus_clk" Master/Core clock, have to be >= 62.5 MHz for SS
operation and >= 30MHz for HS operation
"grf_clk" Controller grf clk
Required child node:
A child node must exist to represent the core DWC3 IP block. The name of
the node is not important. The content of the node is defined in dwc3.txt.
Phy documentation is provided in the following places:
Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.yaml - USB2.0 PHY
Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt - Type-C PHY
Example device nodes:
usbdrd3_0: usb@fe800000 {
compatible = "rockchip,rk3399-dwc3";
clocks = <&cru SCLK_USB3OTG0_REF>, <&cru SCLK_USB3OTG0_SUSPEND>,
<&cru ACLK_USB3OTG0>, <&cru ACLK_USB3_GRF>;
clock-names = "ref_clk", "suspend_clk",
"bus_clk", "grf_clk";
#address-cells = <2>;
#size-cells = <2>;
ranges;
usbdrd_dwc3_0: dwc3@fe800000 {
compatible = "snps,dwc3";
reg = <0x0 0xfe800000 0x0 0x100000>;
interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "otg";
};
};
usbdrd3_1: usb@fe900000 {
compatible = "rockchip,rk3399-dwc3";
clocks = <&cru SCLK_USB3OTG1_REF>, <&cru SCLK_USB3OTG1_SUSPEND>,
<&cru ACLK_USB3OTG1>, <&cru ACLK_USB3_GRF>;
clock-names = "ref_clk", "suspend_clk",
"bus_clk", "grf_clk";
#address-cells = <2>;
#size-cells = <2>;
ranges;
usbdrd_dwc3_1: dwc3@fe900000 {
compatible = "snps,dwc3";
reg = <0x0 0xfe900000 0x0 0x100000>;
interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "otg";
};
};
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/rockchip,dwc3.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rockchip SuperSpeed DWC3 USB SoC controller
maintainers:
- Heiko Stuebner <heiko@sntech.de>
description:
The common content of the node is defined in snps,dwc3.yaml.
Phy documentation is provided in the following places.
USB2.0 PHY
Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.yaml
Type-C PHY
Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
allOf:
- $ref: snps,dwc3.yaml#
select:
properties:
compatible:
contains:
enum:
- rockchip,rk3328-dwc3
- rockchip,rk3399-dwc3
required:
- compatible
properties:
compatible:
items:
- enum:
- rockchip,rk3328-dwc3
- rockchip,rk3399-dwc3
- const: snps,dwc3
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
minItems: 3
items:
- description:
Controller reference clock, must to be 24 MHz
- description:
Controller suspend clock, must to be 24 MHz or 32 KHz
- description:
Master/Core clock, must to be >= 62.5 MHz for SS
operation and >= 30MHz for HS operation
- description:
Controller grf clock
clock-names:
minItems: 3
items:
- const: ref_clk
- const: suspend_clk
- const: bus_clk
- const: grf_clk
power-domains:
maxItems: 1
resets:
maxItems: 1
reset-names:
const: usb3-otg
unevaluatedProperties: false
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
examples:
- |
#include <dt-bindings/clock/rk3399-cru.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
bus {
#address-cells = <2>;
#size-cells = <2>;
usbdrd3_0: usb@fe800000 {
compatible = "rockchip,rk3399-dwc3", "snps,dwc3";
reg = <0x0 0xfe800000 0x0 0x100000>;
interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_USB3OTG0_REF>, <&cru SCLK_USB3OTG0_SUSPEND>,
<&cru ACLK_USB3OTG0>, <&cru ACLK_USB3_GRF>;
clock-names = "ref_clk", "suspend_clk",
"bus_clk", "grf_clk";
dr_mode = "otg";
};
};
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/snps,dwc3.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Synopsys DesignWare USB3 Controller
maintainers:
- Felipe Balbi <balbi@kernel.org>
description:
This is usually a subnode to DWC3 glue to which it is connected, but can also
be presented as a standalone DT node with an optional vendor-specific
compatible string.
allOf:
- $ref: usb-drd.yaml#
- if:
properties:
dr_mode:
const: peripheral
required:
- dr_mode
then:
$ref: usb.yaml#
else:
$ref: usb-xhci.yaml#
properties:
compatible:
contains:
oneOf:
- const: snps,dwc3
- const: synopsys,dwc3
deprecated: true
interrupts:
description:
It's either a single common DWC3 interrupt (dwc_usb3) or individual
interrupts for the host, gadget and DRD modes.
minItems: 1
maxItems: 3
interrupt-names:
minItems: 1
maxItems: 3
oneOf:
- const: dwc_usb3
- items:
enum: [host, peripheral, otg]
clocks:
description:
In general the core supports three types of clocks. bus_early is a
SoC Bus Clock (AHB/AXI/Native). ref generates ITP when the UTMI/ULPI
PHY is suspended. suspend clocks a small part of the USB3 core when
SS PHY in P3. But particular cases may differ from that having less
or more clock sources with another names.
clock-names:
contains:
anyOf:
- enum: [bus_early, ref, suspend]
- true
usb-phy:
minItems: 1
items:
- description: USB2/HS PHY
- description: USB3/SS PHY
phys:
minItems: 1
items:
- description: USB2/HS PHY
- description: USB3/SS PHY
phy-names:
minItems: 1
items:
- const: usb2-phy
- const: usb3-phy
resets:
minItems: 1
snps,usb2-lpm-disable:
description: Indicate if we don't want to enable USB2 HW LPM
type: boolean
snps,usb3_lpm_capable:
description: Determines if platform is USB3 LPM capable
type: boolean
snps,dis-start-transfer-quirk:
description:
When set, disable isoc START TRANSFER command failure SW work-around
for DWC_usb31 version 1.70a-ea06 and prior.
type: boolean
snps,disable_scramble_quirk:
description:
True when SW should disable data scrambling. Only really useful for FPGA
builds.
type: boolean
snps,has-lpm-erratum:
description: True when DWC3 was configured with LPM Erratum enabled
type: boolean
snps,lpm-nyet-threshold:
description: LPM NYET threshold
$ref: /schemas/types.yaml#/definitions/uint8
snps,u2exit_lfps_quirk:
description: Set if we want to enable u2exit lfps quirk
type: boolean
snps,u2ss_inp3_quirk:
description: Set if we enable P3 OK for U2/SS Inactive quirk
type: boolean
snps,req_p1p2p3_quirk:
description:
When set, the core will always request for P1/P2/P3 transition sequence.
type: boolean
snps,del_p1p2p3_quirk:
description:
When set core will delay P1/P2/P3 until a certain amount of 8B10B errors
occur.
type: boolean
snps,del_phy_power_chg_quirk:
description: When set core will delay PHY power change from P0 to P1/P2/P3.
type: boolean
snps,lfps_filter_quirk:
description: When set core will filter LFPS reception.
type: boolean
snps,rx_detect_poll_quirk:
description:
when set core will disable a 400us delay to start Polling LFPS after
RX.Detect.
type: boolean
snps,tx_de_emphasis_quirk:
description: When set core will set Tx de-emphasis value
type: boolean
snps,tx_de_emphasis:
description:
The value driven to the PHY is controlled by the LTSSM during USB3
Compliance mode.
$ref: /schemas/types.yaml#/definitions/uint8
enum:
- 0 # -6dB de-emphasis
- 1 # -3.5dB de-emphasis
- 2 # No de-emphasis
snps,dis_u3_susphy_quirk:
description: When set core will disable USB3 suspend phy
type: boolean
snps,dis_u2_susphy_quirk:
description: When set core will disable USB2 suspend phy
type: boolean
snps,dis_enblslpm_quirk:
description:
When set clears the enblslpm in GUSB2PHYCFG, disabling the suspend signal
to the PHY.
type: boolean
snps,dis-u1-entry-quirk:
description: Set if link entering into U1 needs to be disabled
type: boolean
snps,dis-u2-entry-quirk:
description: Set if link entering into U2 needs to be disabled
type: boolean
snps,dis_rxdet_inp3_quirk:
description:
When set core will disable receiver detection in PHY P3 power state.
type: boolean
snps,dis-u2-freeclk-exists-quirk:
description:
When set, clear the u2_freeclk_exists in GUSB2PHYCFG, specify that USB2
PHY doesn't provide a free-running PHY clock.
type: boolean
snps,dis-del-phy-power-chg-quirk:
description:
When set core will change PHY power from P0 to P1/P2/P3 without delay.
type: boolean
snps,dis-tx-ipgap-linecheck-quirk:
description: When set, disable u2mac linestate check during HS transmit
type: boolean
snps,parkmode-disable-ss-quirk:
description:
When set, all SuperSpeed bus instances in park mode are disabled.
type: boolean
snps,dis_metastability_quirk:
description:
When set, disable metastability workaround. CAUTION! Use only if you are
absolutely sure of it.
type: boolean
snps,dis-split-quirk:
description:
When set, change the way URBs are handled by the driver. Needed to
avoid -EPROTO errors with usbhid on some devices (Hikey 970).
type: boolean
snps,is-utmi-l1-suspend:
description:
True when DWC3 asserts output signal utmi_l1_suspend_n, false when
asserts utmi_sleep_n.
type: boolean
snps,hird-threshold:
description: HIRD threshold
$ref: /schemas/types.yaml#/definitions/uint8
snps,hsphy_interface:
description:
High-Speed PHY interface selection between UTMI+ and ULPI when the
DWC_USB3_HSPHY_INTERFACE has value 3.
$ref: /schemas/types.yaml#/definitions/uint8
enum: [utmi, ulpi]
snps,quirk-frame-length-adjustment:
description:
Value for GFLADJ_30MHZ field of GFLADJ register for post-silicon frame
length adjustment when the fladj_30mhz_sdbnd signal is invalid or
incorrect.
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0x3f
snps,rx-thr-num-pkt-prd:
description:
Periodic ESS RX packet threshold count (host mode only). Set this and
snps,rx-max-burst-prd to a valid, non-zero value 1-16 (DWC_usb31
programming guide section 1.2.4) to enable periodic ESS RX threshold.
$ref: /schemas/types.yaml#/definitions/uint8
minimum: 1
maximum: 16
snps,rx-max-burst-prd:
description:
Max periodic ESS RX burst size (host mode only). Set this and
snps,rx-thr-num-pkt-prd to a valid, non-zero value 1-16 (DWC_usb31
programming guide section 1.2.4) to enable periodic ESS RX threshold.
$ref: /schemas/types.yaml#/definitions/uint8
minimum: 1
maximum: 16
snps,tx-thr-num-pkt-prd:
description:
Periodic ESS TX packet threshold count (host mode only). Set this and
snps,tx-max-burst-prd to a valid, non-zero value 1-16 (DWC_usb31
programming guide section 1.2.3) to enable periodic ESS TX threshold.
$ref: /schemas/types.yaml#/definitions/uint8
minimum: 1
maximum: 16
snps,tx-max-burst-prd:
description:
Max periodic ESS TX burst size (host mode only). Set this and
snps,tx-thr-num-pkt-prd to a valid, non-zero value 1-16 (DWC_usb31
programming guide section 1.2.3) to enable periodic ESS TX threshold.
$ref: /schemas/types.yaml#/definitions/uint8
minimum: 1
maximum: 16
tx-fifo-resize:
description: Determines if the FIFO *has* to be reallocated
deprecated: true
type: boolean
snps,incr-burst-type-adjustment:
description:
Value for INCR burst type of GSBUSCFG0 register, undefined length INCR
burst type enable and INCRx type. A single value means INCRX burst mode
enabled. If more than one value specified, undefined length INCR burst
type will be enabled with burst lengths utilized up to the maximum
of the values passed in this property.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 8
uniqueItems: true
items:
enum: [1, 4, 8, 16, 32, 64, 128, 256]
unevaluatedProperties: false
required:
- compatible
- reg
- interrupts
examples:
- |
usb@4a030000 {
compatible = "snps,dwc3";
reg = <0x4a030000 0xcfff>;
interrupts = <0 92 4>;
usb-phy = <&usb2_phy>, <&usb3_phy>;
snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
};
- |
usb@4a000000 {
compatible = "snps,dwc3";
reg = <0x4a000000 0xcfff>;
interrupts = <0 92 4>;
clocks = <&clk 1>, <&clk 2>, <&clk 3>;
clock-names = "bus_early", "ref", "suspend";
phys = <&usb2_phy>, <&usb3_phy>;
phy-names = "usb2-phy", "usb3-phy";
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
};
...
...@@ -64,9 +64,7 @@ properties: ...@@ -64,9 +64,7 @@ properties:
patternProperties: patternProperties:
"usb@[a-f0-9]+$": "usb@[a-f0-9]+$":
type: object $ref: snps,dwc3.yaml#
description: This is the node representing the DWC3 controller instance
Documentation/devicetree/bindings/usb/dwc3.txt
required: required:
- compatible - compatible
......
Generic USB Device Properties
Usually, we only use device tree for hard wired USB device.
The reference binding doc is from:
http://www.devicetree.org/open-firmware/bindings/usb/usb-1_0.ps
Four types of device-tree nodes are defined: "host-controller nodes"
representing USB host controllers, "device nodes" representing USB devices,
"interface nodes" representing USB interfaces and "combined nodes"
representing simple USB devices.
A combined node shall be used instead of a device node and an interface node
for devices of class 0 or 9 (hub) with a single configuration and a single
interface.
A "hub node" is a combined node or an interface node that represents a USB
hub.
Required properties for device nodes:
- compatible: "usbVID,PID", where VID is the vendor id and PID the product id.
The textual representation of VID and PID shall be in lower case hexadecimal
with leading zeroes suppressed. The other compatible strings from the above
standard binding could also be used, but a device adhering to this binding
may leave out all except for "usbVID,PID".
- reg: the number of the USB hub port or the USB host-controller port to which
this device is attached. The range is 1-255.
Required properties for device nodes with interface nodes:
- #address-cells: shall be 2
- #size-cells: shall be 0
Required properties for interface nodes:
- compatible: "usbifVID,PID.configCN.IN", where VID is the vendor id, PID is
the product id, CN is the configuration value and IN is the interface
number. The textual representation of VID, PID, CN and IN shall be in lower
case hexadecimal with leading zeroes suppressed. The other compatible
strings from the above standard binding could also be used, but a device
adhering to this binding may leave out all except for
"usbifVID,PID.configCN.IN".
- reg: the interface number and configuration value
The configuration component is not included in the textual representation of
an interface-node unit address for configuration 1.
Required properties for combined nodes:
- compatible: "usbVID,PID", where VID is the vendor id and PID the product id.
The textual representation of VID and PID shall be in lower case hexadecimal
with leading zeroes suppressed. The other compatible strings from the above
standard binding could also be used, but a device adhering to this binding
may leave out all except for "usbVID,PID".
- reg: the number of the USB hub port or the USB host-controller port to which
this device is attached. The range is 1-255.
Required properties for hub nodes with device nodes:
- #address-cells: shall be 1
- #size-cells: shall be 0
Required properties for host-controller nodes with device nodes:
- #address-cells: shall be 1
- #size-cells: shall be 0
Example:
&usb1 { /* host controller */
#address-cells = <1>;
#size-cells = <0>;
hub@1 { /* hub connected to port 1 */
compatible = "usb5e3,608";
reg = <1>;
};
device@2 { /* device connected to port 2 */
compatible = "usb123,4567";
reg = <2>;
};
device@3 { /* device connected to port 3 */
compatible = "usb123,abcd";
reg = <3>;
#address-cells = <2>;
#size-cells = <0>;
interface@0 { /* interface 0 of configuration 1 */
compatible = "usbif123,abcd.config1.0";
reg = <0 1>;
};
interface@0,2 { /* interface 0 of configuration 2 */
compatible = "usbif123,abcd.config2.0";
reg = <0 2>;
};
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/usb-device.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: The device tree bindings for the Generic USB Device
maintainers:
- Greg Kroah-Hartman <gregkh@linuxfoundation.org>
description: |
Usually, we only use device tree for hard wired USB device.
The reference binding doc is from:
http://www.devicetree.org/open-firmware/bindings/usb/usb-1_0.ps
Four types of device-tree nodes are defined: "host-controller nodes"
representing USB host controllers, "device nodes" representing USB devices,
"interface nodes" representing USB interfaces and "combined nodes"
representing simple USB devices.
A combined node shall be used instead of a device node and an interface node
for devices of class 0 or 9 (hub) with a single configuration and a single
interface.
A "hub node" is a combined node or an interface node that represents a USB
hub.
properties:
compatible:
pattern: "^usb[0-9a-f]{1,4},[0-9a-f]{1,4}$"
description: Device nodes or combined nodes.
"usbVID,PID", where VID is the vendor id and PID the product id.
The textual representation of VID and PID shall be in lower case
hexadecimal with leading zeroes suppressed. The other compatible
strings from the above standard binding could also be used,
but a device adhering to this binding may leave out all except
for "usbVID,PID".
reg:
description: the number of the USB hub port or the USB host-controller
port to which this device is attached. The range is 1-255.
maxItems: 1
"#address-cells":
description: should be 1 for hub nodes with device nodes,
should be 2 for device nodes with interface nodes.
enum: [1, 2]
"#size-cells":
const: 0
patternProperties:
"^interface@[0-9a-f]{1,2}(,[0-9a-f]{1,2})$":
type: object
description: USB interface nodes.
The configuration component is not included in the textual
representation of an interface-node unit address for configuration 1.
properties:
compatible:
pattern: "^usbif[0-9a-f]{1,4},[0-9a-f]{1,4}.config[0-9a-f]{1,2}.[0-9a-f]{1,2}$"
description: Interface nodes.
"usbifVID,PID.configCN.IN", where VID is the vendor id, PID is
the product id, CN is the configuration value and IN is the interface
number. The textual representation of VID, PID, CN and IN shall be
in lower case hexadecimal with leading zeroes suppressed.
The other compatible strings from the above standard binding could
also be used, but a device adhering to this binding may leave out
all except for "usbifVID,PID.configCN.IN".
reg:
description: should be 2 cells long, the first cell represents
the interface number and the second cell represents the
configuration value.
maxItems: 1
required:
- compatible
- reg
additionalProperties: true
examples:
#hub connected to port 1
#device connected to port 2
#device connected to port 3
# interface 0 of configuration 1
# interface 0 of configuration 2
- |
usb@11270000 {
reg = <0x11270000 0x1000>;
interrupts = <0x0 0x4e 0x0>;
#address-cells = <1>;
#size-cells = <0>;
hub@1 {
compatible = "usb5e3,608";
reg = <1>;
};
device@2 {
compatible = "usb123,4567";
reg = <2>;
};
device@3 {
compatible = "usb123,abcd";
reg = <3>;
#address-cells = <2>;
#size-cells = <0>;
interface@0 {
compatible = "usbif123,abcd.config1.0";
reg = <0 1>;
};
interface@0,2 {
compatible = "usbif123,abcd.config2.0";
reg = <0 2>;
};
};
};
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/usb-drd.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic USB OTG Controller Device Tree Bindings
maintainers:
- Greg Kroah-Hartman <gregkh@linuxfoundation.org>
properties:
otg-rev:
description:
Tells usb driver the release number of the OTG and EH supplement with
which the device and its descriptors are compliant, in binary-coded
decimal (i.e. 2.0 is 0200H). This property is used if any real OTG
features (HNP/SRP/ADP) is enabled. If ADP is required, otg-rev should be
0x0200 or above.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0x0100, 0x0120, 0x0130, 0x0200]
dr_mode:
description:
Tells Dual-Role USB controllers that we want to work on a particular
mode. In case this attribute isn't passed via DT, USB DRD controllers
should default to OTG.
$ref: /schemas/types.yaml#/definitions/string
enum: [host, peripheral, otg]
hnp-disable:
description:
Tells OTG controllers we want to disable OTG HNP. Normally HNP is the
basic function of real OTG except you want it to be a srp-capable only B
device.
type: boolean
srp-disable:
description:
Tells OTG controllers we want to disable OTG SRP. SRP is optional for OTG
device.
type: boolean
adp-disable:
description:
Tells OTG controllers we want to disable OTG ADP. ADP is optional for OTG
device.
type: boolean
usb-role-switch:
description:
Indicates that the device is capable of assigning the USB data role
(USB host or USB device) for a given USB connector, such as Type-C,
Type-B(micro). See connector/usb-connector.yaml.
role-switch-default-mode:
description:
Indicates if usb-role-switch is enabled, the device default operation
mode of controller while usb role is USB_ROLE_NONE.
$ref: /schemas/types.yaml#/definitions/string
enum: [host, peripheral]
default: peripheral
additionalProperties: true
examples:
- |
usb@4a030000 {
compatible = "snps,dwc3";
reg = <0x4a030000 0xcfff>;
interrupts = <0 92 4>;
usb-phy = <&usb2_phy>, <&usb3_phy>;
maximum-speed = "super-speed";
dr_mode = "otg";
phy_type = "utmi_wide";
otg-rev = <0x0200>;
adp-disable;
};
...@@ -9,18 +9,31 @@ title: Generic USB Host Controller Device Tree Bindings ...@@ -9,18 +9,31 @@ title: Generic USB Host Controller Device Tree Bindings
maintainers: maintainers:
- Greg Kroah-Hartman <gregkh@linuxfoundation.org> - Greg Kroah-Hartman <gregkh@linuxfoundation.org>
allOf:
- $ref: usb.yaml#
properties: properties:
$nodename: companion:
pattern: "^usb(@.*)?" description: Phandle of a companion device
$ref: /schemas/types.yaml#/definitions/phandle
phys: tpl-support:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: description:
List of all the USB PHYs on this HCD Indicates if the Targeted Peripheral List is supported for given
targeted hosts (non-PC hosts).
type: boolean
phy-names: "#address-cells":
description: const: 1
Name specifier for the USB PHY
"#size-cells":
const: 0
patternProperties:
"^.*@[0-9a-f]{1,2}$":
description: The hard wired USB devices
type: object
$ref: /usb/usb-device.yaml
additionalProperties: true additionalProperties: true
...@@ -29,4 +42,11 @@ examples: ...@@ -29,4 +42,11 @@ examples:
usb { usb {
phys = <&usb2_phy1>, <&usb3_phy1>; phys = <&usb2_phy1>, <&usb3_phy1>;
phy-names = "usb"; phy-names = "usb";
#address-cells = <1>;
#size-cells = <0>;
hub@1 {
compatible = "usb5e3,610";
reg = <1>;
};
}; };
USB xHCI controllers
Required properties:
- compatible: should be one or more of
- "generic-xhci" for generic XHCI device
- "marvell,armada3700-xhci" for Armada 37xx SoCs
- "marvell,armada-375-xhci" for Armada 375 SoCs
- "marvell,armada-380-xhci" for Armada 38x SoCs
- "brcm,bcm7445-xhci" for Broadcom STB SoCs with XHCI
- "xhci-platform" (deprecated)
When compatible with the generic version, nodes must list the
SoC-specific version corresponding to the platform first
followed by the generic version.
- reg: should contain address and length of the standard XHCI
register set for the device.
- interrupts: one XHCI interrupt should be described here.
Optional properties:
- clocks: reference to the clocks
- clock-names: mandatory if there is a second clock, in this case
the name must be "core" for the first clock and "reg" for the
second one
- usb2-lpm-disable: indicate if we don't want to enable USB2 HW LPM
- usb3-lpm-capable: determines if platform is USB3 LPM capable
- quirk-broken-port-ped: set if the controller has broken port disable mechanism
- imod-interval-ns: default interrupt moderation interval is 5000ns
- phys : see usb-hcd.yaml in the current directory
additionally the properties from usb-hcd.yaml (in the current directory) are
supported.
Example:
usb@f0931000 {
compatible = "generic-xhci";
reg = <0xf0931000 0x8c8>;
interrupts = <0x0 0x4e 0x0>;
};
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/usb-xhci.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic USB xHCI Controller Device Tree Bindings
maintainers:
- Mathias Nyman <mathias.nyman@intel.com>
allOf:
- $ref: "usb-hcd.yaml#"
properties:
usb2-lpm-disable:
description: Indicates if we don't want to enable USB2 HW LPM
type: boolean
usb3-lpm-capable:
description: Determines if platform is USB3 LPM capable
type: boolean
quirk-broken-port-ped:
description: Set if the controller has broken port disable mechanism
type: boolean
imod-interval-ns:
description: Interrupt moderation interval
default: 5000
additionalProperties: true
examples:
- |
usb@f0930000 {
compatible = "generic-xhci";
reg = <0xf0930000 0x8c8>;
interrupts = <0x0 0x4e 0x0>;
usb2-lpm-disable;
usb3-lpm-capable;
};
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/usb.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic USB Controller Device Tree Bindings
maintainers:
- Greg Kroah-Hartman <gregkh@linuxfoundation.org>
select: false
properties:
$nodename:
pattern: "^usb(@.*)?"
phys:
$ref: /schemas/types.yaml#/definitions/phandle-array
description:
List of all the USB PHYs on this HCD
phy-names:
description:
Name specifier for the USB PHY
usb-phy:
$ref: /schemas/types.yaml#/definitions/phandle-array
description:
List of all the USB PHYs on this HCD to be accepted by the legacy USB
Physical Layer subsystem.
deprecated: true
phy_type:
description:
Tells USB controllers that we want to configure the core to support a
UTMI+ PHY with an 8- or 16-bit interface if UTMI+ is selected, UTMI+ low
pin interface if ULPI is specified, Serial core/PHY interconnect if
serial is specified and High-Speed Inter-Chip feature if HSIC is
selected. In case this isn't passed via DT, USB controllers should
default to HW capability.
$ref: /schemas/types.yaml#/definitions/string
enum: [utmi, utmi_wide, ulpi, serial, hsic]
maximum-speed:
description:
Tells USB controllers we want to work up to a certain speed. In case this
isn't passed via DT, USB controllers should default to their maximum HW
capability.
$ref: /schemas/types.yaml#/definitions/string
enum:
- low-speed
- full-speed
- high-speed
- super-speed
- super-speed-plus
- super-speed-plus-gen2x1
- super-speed-plus-gen1x2
- super-speed-plus-gen2x2
additionalProperties: true
...
* Freescale i.MX non-core registers * Freescale i.MX non-core registers
Required properties: Required properties:
- #index-cells: Cells used to descibe usb controller index. Should be <1> - #index-cells: Cells used to describe usb controller index. Should be <1>
- compatible: Should be one of below: - compatible: Should be one of below:
"fsl,imx6q-usbmisc" for imx6q "fsl,imx6q-usbmisc" for imx6q
"fsl,vf610-usbmisc" for Vybrid vf610 "fsl,vf610-usbmisc" for Vybrid vf610
......
...@@ -91,9 +91,9 @@ The ECM function provides these attributes in its function directory: ...@@ -91,9 +91,9 @@ The ECM function provides these attributes in its function directory:
and after creating the functions/ecm.<instance name> they contain default and after creating the functions/ecm.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected. values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a The ifname can be written to if the function is not bound. A write must be an
configuration. The ifname is read-only and contains the name of the interface interface pattern such as "usb%d", which will cause the net core to choose the
which was assigned by the net core, e. g. usb0. next free usbX interface. By default, it is set to "usb%d".
Testing the ECM function Testing the ECM function
------------------------ ------------------------
...@@ -131,9 +131,9 @@ The ECM subset function provides these attributes in its function directory: ...@@ -131,9 +131,9 @@ The ECM subset function provides these attributes in its function directory:
and after creating the functions/ecm.<instance name> they contain default and after creating the functions/ecm.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected. values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a The ifname can be written to if the function is not bound. A write must be an
configuration. The ifname is read-only and contains the name of the interface interface pattern such as "usb%d", which will cause the net core to choose the
which was assigned by the net core, e. g. usb0. next free usbX interface. By default, it is set to "usb%d".
Testing the ECM subset function Testing the ECM subset function
------------------------------- -------------------------------
...@@ -171,9 +171,9 @@ The EEM function provides these attributes in its function directory: ...@@ -171,9 +171,9 @@ The EEM function provides these attributes in its function directory:
and after creating the functions/eem.<instance name> they contain default and after creating the functions/eem.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected. values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a The ifname can be written to if the function is not bound. A write must be an
configuration. The ifname is read-only and contains the name of the interface interface pattern such as "usb%d", which will cause the net core to choose the
which was assigned by the net core, e. g. usb0. next free usbX interface. By default, it is set to "usb%d".
Testing the EEM function Testing the EEM function
------------------------ ------------------------
...@@ -453,9 +453,9 @@ The NCM function provides these attributes in its function directory: ...@@ -453,9 +453,9 @@ The NCM function provides these attributes in its function directory:
and after creating the functions/ncm.<instance name> they contain default and after creating the functions/ncm.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected. values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a The ifname can be written to if the function is not bound. A write must be an
configuration. The ifname is read-only and contains the name of the interface interface pattern such as "usb%d", which will cause the net core to choose the
which was assigned by the net core, e. g. usb0. next free usbX interface. By default, it is set to "usb%d".
Testing the NCM function Testing the NCM function
------------------------ ------------------------
...@@ -591,9 +591,9 @@ The RNDIS function provides these attributes in its function directory: ...@@ -591,9 +591,9 @@ The RNDIS function provides these attributes in its function directory:
and after creating the functions/rndis.<instance name> they contain default and after creating the functions/rndis.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected. values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a The ifname can be written to if the function is not bound. A write must be an
configuration. The ifname is read-only and contains the name of the interface interface pattern such as "usb%d", which will cause the net core to choose the
which was assigned by the net core, e. g. usb0. next free usbX interface. By default, it is set to "usb%d".
Testing the RNDIS function Testing the RNDIS function
-------------------------- --------------------------
......
...@@ -2,83 +2,93 @@ ...@@ -2,83 +2,93 @@
USB Raw Gadget USB Raw Gadget
============== ==============
USB Raw Gadget is a kernel module that provides a userspace interface for USB Raw Gadget is a gadget driver that gives userspace low-level control over
the USB Gadget subsystem. Essentially it allows to emulate USB devices the gadget's communication process.
from userspace. Enabled with CONFIG_USB_RAW_GADGET. Raw Gadget is
currently a strictly debugging feature and shouldn't be used in Like any other gadget driver, Raw Gadget implements USB devices via the
production, use GadgetFS instead. USB gadget API. Unlike most gadget drivers, Raw Gadget does not implement
any concrete USB functions itself but requires userspace to do that.
Raw Gadget is currently a strictly debugging feature and should not be used
in production. Use GadgetFS instead.
Enabled with CONFIG_USB_RAW_GADGET.
Comparison to GadgetFS Comparison to GadgetFS
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
Raw Gadget is similar to GadgetFS, but provides a more low-level and Raw Gadget is similar to GadgetFS but provides more direct access to the
direct access to the USB Gadget layer for the userspace. The key USB gadget layer for userspace. The key differences are:
differences are:
1. Every USB request is passed to the userspace to get a response, while 1. Raw Gadget passes every USB request to userspace to get a response, while
GadgetFS responds to some USB requests internally based on the provided GadgetFS responds to some USB requests internally based on the provided
descriptors. However note, that the UDC driver might respond to some descriptors. Note that the UDC driver might respond to some requests on
requests on its own and never forward them to the Gadget layer. its own and never forward them to the gadget layer.
2. GadgetFS performs some sanity checks on the provided USB descriptors, 2. Raw Gadget allows providing arbitrary data as responses to USB requests,
while Raw Gadget allows you to provide arbitrary data as responses to while GadgetFS performs sanity checks on the provided USB descriptors.
USB requests. This makes Raw Gadget suitable for fuzzing by providing malformed data as
responses to USB requests.
3. Raw Gadget provides a way to select a UDC device/driver to bind to, 3. Raw Gadget provides a way to select a UDC device/driver to bind to,
while GadgetFS currently binds to the first available UDC. while GadgetFS currently binds to the first available UDC. This allows
having multiple Raw Gadget instances bound to different UDCs.
4. Raw Gadget explicitly exposes information about endpoints addresses and 4. Raw Gadget explicitly exposes information about endpoints addresses and
capabilities allowing a user to write UDC-agnostic gadgets. capabilities. This allows the user to write UDC-agnostic gadgets.
5. Raw Gadget has ioctl-based interface instead of a filesystem-based one. 5. Raw Gadget has an ioctl-based interface instead of a filesystem-based
one.
Userspace interface Userspace interface
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
To create a Raw Gadget instance open /dev/raw-gadget. Multiple raw-gadget The user can interact with Raw Gadget by opening ``/dev/raw-gadget`` and
instances (bound to different UDCs) can be used at the same time. The issuing ioctl calls; see the comments in include/uapi/linux/usb/raw_gadget.h
interaction with the opened file happens through the ioctl() calls, see for details. Multiple Raw Gadget instances (bound to different UDCs) can be
comments in include/uapi/linux/usb/raw_gadget.h for details. used at the same time.
The typical usage of Raw Gadget looks like: A typical usage scenario of Raw Gadget:
1. Open Raw Gadget instance via /dev/raw-gadget. 1. Create a Raw Gadget instance by opening ``/dev/raw-gadget``.
2. Initialize the instance via USB_RAW_IOCTL_INIT. 2. Initialize the instance via ``USB_RAW_IOCTL_INIT``.
3. Launch the instance with USB_RAW_IOCTL_RUN. 3. Launch the instance with ``USB_RAW_IOCTL_RUN``.
4. In a loop issue USB_RAW_IOCTL_EVENT_FETCH calls to receive events from 4. In a loop issue ``USB_RAW_IOCTL_EVENT_FETCH`` to receive events from
Raw Gadget and react to those depending on what kind of USB device Raw Gadget and react to those depending on what kind of USB gadget must
needs to be emulated. be implemented.
Note, that some UDC drivers have fixed addresses assigned to endpoints, and Note that some UDC drivers have fixed addresses assigned to endpoints, and
therefore arbitrary endpoint addresses can't be used in the descriptors. therefore arbitrary endpoint addresses cannot be used in the descriptors.
Nevertheles, Raw Gadget provides a UDC-agnostic way to write USB gadgets. Nevertheless, Raw Gadget provides a UDC-agnostic way to write USB gadgets.
Once a USB_RAW_EVENT_CONNECT event is received via USB_RAW_IOCTL_EVENT_FETCH, Once ``USB_RAW_EVENT_CONNECT`` is received via ``USB_RAW_IOCTL_EVENT_FETCH``,
the USB_RAW_IOCTL_EPS_INFO ioctl can be used to find out information about ``USB_RAW_IOCTL_EPS_INFO`` can be used to find out information about the
endpoints that the UDC driver has. Based on that information, the user must endpoints that the UDC driver has. Based on that, userspace must choose UDC
chose UDC endpoints that will be used for the gadget being emulated, and endpoints for the gadget and assign addresses in the endpoint descriptors
properly assign addresses in endpoint descriptors. correspondingly.
You can find usage examples (along with a test suite) here: Raw Gadget usage examples and a test suite:
https://github.com/xairy/raw-gadget https://github.com/xairy/raw-gadget
Internal details Internal details
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
Currently every endpoint read/write ioctl submits a USB request and waits until Every Raw Gadget endpoint read/write ioctl submits a USB request and waits
its completion. This is the desired mode for coverage-guided fuzzing (as we'd until its completion. This is done deliberately to assist with coverage-guided
like all USB request processing happen during the lifetime of a syscall), fuzzing by having a single syscall fully process a single USB request. This
and must be kept in the implementation. (This might be slow for real world feature must be kept in the implementation.
applications, thus the O_NONBLOCK improvement suggestion below.)
Potential future improvements Potential future improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Report more events (suspend, resume, etc.) through USB_RAW_IOCTL_EVENT_FETCH. - Report more events (suspend, resume, etc.) through
``USB_RAW_IOCTL_EVENT_FETCH``.
- Support O_NONBLOCK I/O. - Support ``O_NONBLOCK`` I/O. This would be another mode of operation, where
Raw Gadget would not wait until the completion of each USB request.
- Support USB 3 features (accept SS endpoint companion descriptor when - Support USB 3 features (accept SS endpoint companion descriptor when
enabling endpoints; allow providing stream_id for bulk transfers). enabling endpoints; allow providing ``stream_id`` for bulk transfers).
- Support ISO transfer features (expose frame_number for completed requests). - Support ISO transfer features (expose ``frame_number`` for completed
requests).
...@@ -2071,7 +2071,7 @@ M: Chunfeng Yun <chunfeng.yun@mediatek.com> ...@@ -2071,7 +2071,7 @@ M: Chunfeng Yun <chunfeng.yun@mediatek.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/phy/phy-mtk-* F: Documentation/devicetree/bindings/phy/mediatek,*
F: drivers/phy/mediatek/ F: drivers/phy/mediatek/
ARM/Microchip (AT91) SoC support ARM/Microchip (AT91) SoC support
...@@ -3855,6 +3855,15 @@ S: Maintained ...@@ -3855,6 +3855,15 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
F: Documentation/devicetree/bindings/usb/cdns,usb3.yaml F: Documentation/devicetree/bindings/usb/cdns,usb3.yaml
F: drivers/usb/cdns3/ F: drivers/usb/cdns3/
X: drivers/usb/cdns3/cdnsp*
CADENCE USBSSP DRD IP DRIVER
M: Pawel Laszczak <pawell@cadence.com>
L: linux-usb@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
F: drivers/usb/cdns3/
X: drivers/usb/cdns3/cdns3*
CADET FM/AM RADIO RECEIVER DRIVER CADET FM/AM RADIO RECEIVER DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl> M: Hans Verkuil <hverkuil@xs4all.nl>
...@@ -11229,6 +11238,8 @@ L: linux-usb@vger.kernel.org ...@@ -11229,6 +11238,8 @@ L: linux-usb@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/usb/mediatek,*
F: drivers/usb/host/xhci-mtk*
F: drivers/usb/mtu3/ F: drivers/usb/mtu3/
MEGACHIPS STDPXXXX-GE-B850V3-FW LVDS/DP++ BRIDGES MEGACHIPS STDPXXXX-GE-B850V3-FW LVDS/DP++ BRIDGES
......
...@@ -238,12 +238,13 @@ CONFIG_USB=y ...@@ -238,12 +238,13 @@ CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_TEGRA=y CONFIG_USB_XHCI_TEGRA=y
CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_TEGRA=y
CONFIG_USB_ACM=y CONFIG_USB_ACM=y
CONFIG_USB_WDM=y CONFIG_USB_WDM=y
CONFIG_USB_STORAGE=y CONFIG_USB_STORAGE=y
CONFIG_USB_CHIPIDEA=y CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_CHIPIDEA_TEGRA=y
CONFIG_USB_GADGET=y CONFIG_USB_GADGET=y
CONFIG_MMC=y CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=16 CONFIG_MMC_BLOCK_MINORS=16
......
...@@ -127,6 +127,21 @@ &uart2 { ...@@ -127,6 +127,21 @@ &uart2 {
status = "okay"; status = "okay";
}; };
&usb3_phy1 {
status = "okay";
};
&usb3_1 {
status = "okay";
};
&usb_dwc3_1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usb1_vbus>;
dr_mode = "host";
status = "okay";
};
&usdhc2 { &usdhc2 {
assigned-clocks = <&clk IMX8MP_CLK_USDHC2>; assigned-clocks = <&clk IMX8MP_CLK_USDHC2>;
assigned-clock-rates = <400000000>; assigned-clock-rates = <400000000>;
...@@ -232,6 +247,12 @@ MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX 0x49 ...@@ -232,6 +247,12 @@ MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX 0x49
>; >;
}; };
pinctrl_usb1_vbus: usb1grp {
fsl,pins = <
MX8MP_IOMUXC_GPIO1_IO14__USB2_OTG_PWR 0x19
>;
};
pinctrl_usdhc2: usdhc2grp { pinctrl_usdhc2: usdhc2grp {
fsl,pins = < fsl,pins = <
MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x190 MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x190
......
...@@ -803,5 +803,87 @@ ddr-pmu@3d800000 { ...@@ -803,5 +803,87 @@ ddr-pmu@3d800000 {
reg = <0x3d800000 0x400000>; reg = <0x3d800000 0x400000>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
}; };
usb3_phy0: usb-phy@381f0040 {
compatible = "fsl,imx8mp-usb-phy";
reg = <0x381f0040 0x40>;
clocks = <&clk IMX8MP_CLK_USB_PHY_ROOT>;
clock-names = "phy";
assigned-clocks = <&clk IMX8MP_CLK_USB_PHY_REF>;
assigned-clock-parents = <&clk IMX8MP_CLK_24M>;
#phy-cells = <0>;
status = "disabled";
};
usb3_0: usb@32f10100 {
compatible = "fsl,imx8mp-dwc3";
reg = <0x32f10100 0x8>;
clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
<&clk IMX8MP_CLK_USB_ROOT>;
clock-names = "hsio", "suspend";
interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <1>;
dma-ranges = <0x40000000 0x40000000 0xc0000000>;
ranges;
status = "disabled";
usb_dwc3_0: dwc3@38100000 {
compatible = "snps,dwc3";
reg = <0x38100000 0x10000>;
clocks = <&clk IMX8MP_CLK_HSIO_AXI>,
<&clk IMX8MP_CLK_USB_CORE_REF>,
<&clk IMX8MP_CLK_USB_ROOT>;
clock-names = "bus_early", "ref", "suspend";
assigned-clocks = <&clk IMX8MP_CLK_HSIO_AXI>;
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_500M>;
assigned-clock-rates = <500000000>;
interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
phys = <&usb3_phy0>, <&usb3_phy0>;
phy-names = "usb2-phy", "usb3-phy";
snps,dis-u2-freeclk-exists-quirk;
};
};
usb3_phy1: usb-phy@382f0040 {
compatible = "fsl,imx8mp-usb-phy";
reg = <0x382f0040 0x40>;
clocks = <&clk IMX8MP_CLK_USB_PHY_ROOT>;
clock-names = "phy";
assigned-clocks = <&clk IMX8MP_CLK_USB_PHY_REF>;
assigned-clock-parents = <&clk IMX8MP_CLK_24M>;
#phy-cells = <0>;
};
usb3_1: usb@32f10108 {
compatible = "fsl,imx8mp-dwc3";
reg = <0x32f10108 0x8>;
clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
<&clk IMX8MP_CLK_USB_ROOT>;
clock-names = "hsio", "suspend";
interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <1>;
dma-ranges = <0x40000000 0x40000000 0xc0000000>;
ranges;
status = "disabled";
usb_dwc3_1: dwc3@38200000 {
compatible = "snps,dwc3";
reg = <0x38200000 0x10000>;
clocks = <&clk IMX8MP_CLK_HSIO_AXI>,
<&clk IMX8MP_CLK_USB_CORE_REF>,
<&clk IMX8MP_CLK_USB_ROOT>;
clock-names = "bus_early", "ref", "suspend";
assigned-clocks = <&clk IMX8MP_CLK_HSIO_AXI>;
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_500M>;
assigned-clock-rates = <500000000>;
interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
phys = <&usb3_phy1>, <&usb3_phy1>;
phy-names = "usb2-phy", "usb3-phy";
snps,dis-u2-freeclk-exists-quirk;
};
};
}; };
}; };
...@@ -281,10 +281,16 @@ bool osc_sb_apei_support_acked; ...@@ -281,10 +281,16 @@ bool osc_sb_apei_support_acked;
bool osc_pc_lpi_support_confirmed; bool osc_pc_lpi_support_confirmed;
EXPORT_SYMBOL_GPL(osc_pc_lpi_support_confirmed); EXPORT_SYMBOL_GPL(osc_pc_lpi_support_confirmed);
/*
* ACPI 6.4 Operating System Capabilities for USB.
*/
bool osc_sb_native_usb4_support_confirmed;
EXPORT_SYMBOL_GPL(osc_sb_native_usb4_support_confirmed);
static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48"; static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48";
static void acpi_bus_osc_support(void) static void acpi_bus_osc_negotiate_platform_control(void)
{ {
u32 capbuf[2]; u32 capbuf[2], *capbuf_ret;
struct acpi_osc_context context = { struct acpi_osc_context context = {
.uuid_str = sb_uuid_str, .uuid_str = sb_uuid_str,
.rev = 1, .rev = 1,
...@@ -317,21 +323,109 @@ static void acpi_bus_osc_support(void) ...@@ -317,21 +323,109 @@ static void acpi_bus_osc_support(void)
if (IS_ENABLED(CONFIG_SCHED_MC_PRIO)) if (IS_ENABLED(CONFIG_SCHED_MC_PRIO))
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_DIVERSE_HIGH_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_DIVERSE_HIGH_SUPPORT;
if (IS_ENABLED(CONFIG_USB4))
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_NATIVE_USB4_SUPPORT;
if (!ghes_disable) if (!ghes_disable)
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT;
if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
return; return;
if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
u32 *capbuf_ret = context.ret.pointer; if (ACPI_FAILURE(acpi_run_osc(handle, &context)))
if (context.ret.length > OSC_SUPPORT_DWORD) { return;
osc_sb_apei_support_acked =
capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT; capbuf_ret = context.ret.pointer;
osc_pc_lpi_support_confirmed = if (context.ret.length <= OSC_SUPPORT_DWORD) {
capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT;
}
kfree(context.ret.pointer); kfree(context.ret.pointer);
return;
}
/*
* Now run _OSC again with query flag clear and with the caps
* supported by both the OS and the platform.
*/
capbuf[OSC_QUERY_DWORD] = 0;
capbuf[OSC_SUPPORT_DWORD] = capbuf_ret[OSC_SUPPORT_DWORD];
kfree(context.ret.pointer);
if (ACPI_FAILURE(acpi_run_osc(handle, &context)))
return;
capbuf_ret = context.ret.pointer;
if (context.ret.length > OSC_SUPPORT_DWORD) {
osc_sb_apei_support_acked =
capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
osc_pc_lpi_support_confirmed =
capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT;
osc_sb_native_usb4_support_confirmed =
capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_NATIVE_USB4_SUPPORT;
} }
/* do we need to check other returned cap? Sounds no */
kfree(context.ret.pointer);
}
/*
* Native control of USB4 capabilities. If any of the tunneling bits is
* set it means OS is in control and we use software based connection
* manager.
*/
u32 osc_sb_native_usb4_control;
EXPORT_SYMBOL_GPL(osc_sb_native_usb4_control);
static void acpi_bus_decode_usb_osc(const char *msg, u32 bits)
{
printk(KERN_INFO PREFIX "%s USB3%c DisplayPort%c PCIe%c XDomain%c\n", msg,
(bits & OSC_USB_USB3_TUNNELING) ? '+' : '-',
(bits & OSC_USB_DP_TUNNELING) ? '+' : '-',
(bits & OSC_USB_PCIE_TUNNELING) ? '+' : '-',
(bits & OSC_USB_XDOMAIN) ? '+' : '-');
}
static u8 sb_usb_uuid_str[] = "23A0D13A-26AB-486C-9C5F-0FFA525A575A";
static void acpi_bus_osc_negotiate_usb_control(void)
{
u32 capbuf[3];
struct acpi_osc_context context = {
.uuid_str = sb_usb_uuid_str,
.rev = 1,
.cap.length = sizeof(capbuf),
.cap.pointer = capbuf,
};
acpi_handle handle;
acpi_status status;
u32 control;
if (!osc_sb_native_usb4_support_confirmed)
return;
if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
return;
control = OSC_USB_USB3_TUNNELING | OSC_USB_DP_TUNNELING |
OSC_USB_PCIE_TUNNELING | OSC_USB_XDOMAIN;
capbuf[OSC_QUERY_DWORD] = 0;
capbuf[OSC_SUPPORT_DWORD] = 0;
capbuf[OSC_CONTROL_DWORD] = control;
status = acpi_run_osc(handle, &context);
if (ACPI_FAILURE(status))
return;
if (context.ret.length != sizeof(capbuf)) {
printk(KERN_INFO PREFIX "USB4 _OSC: returned invalid length buffer\n");
goto out_free;
}
osc_sb_native_usb4_control =
control & ((u32 *)context.ret.pointer)[OSC_CONTROL_DWORD];
acpi_bus_decode_usb_osc("USB4 _OSC: OS supports", control);
acpi_bus_decode_usb_osc("USB4 _OSC: OS controls",
osc_sb_native_usb4_control);
out_free:
kfree(context.ret.pointer);
} }
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
...@@ -1168,7 +1262,8 @@ static int __init acpi_bus_init(void) ...@@ -1168,7 +1262,8 @@ static int __init acpi_bus_init(void)
* _OSC method may exist in module level code, * _OSC method may exist in module level code,
* so it must be run after ACPI_FULL_INITIALIZATION * so it must be run after ACPI_FULL_INITIALIZATION
*/ */
acpi_bus_osc_support(); acpi_bus_osc_negotiate_platform_control();
acpi_bus_osc_negotiate_usb_control();
/* /*
* _PDC control method may load dynamic SSDT tables, * _PDC control method may load dynamic SSDT tables,
......
...@@ -24,6 +24,7 @@ struct swnode { ...@@ -24,6 +24,7 @@ struct swnode {
struct swnode *parent; struct swnode *parent;
unsigned int allocated:1; unsigned int allocated:1;
unsigned int managed:1;
}; };
static DEFINE_IDA(swnode_root_ids); static DEFINE_IDA(swnode_root_ids);
...@@ -48,6 +49,19 @@ EXPORT_SYMBOL_GPL(is_software_node); ...@@ -48,6 +49,19 @@ EXPORT_SYMBOL_GPL(is_software_node);
struct swnode, fwnode) : NULL; \ struct swnode, fwnode) : NULL; \
}) })
static inline struct swnode *dev_to_swnode(struct device *dev)
{
struct fwnode_handle *fwnode = dev_fwnode(dev);
if (!fwnode)
return NULL;
if (!is_software_node(fwnode))
fwnode = fwnode->secondary;
return to_swnode(fwnode);
}
static struct swnode * static struct swnode *
software_node_to_swnode(const struct software_node *node) software_node_to_swnode(const struct software_node *node)
{ {
...@@ -843,22 +857,99 @@ void fwnode_remove_software_node(struct fwnode_handle *fwnode) ...@@ -843,22 +857,99 @@ void fwnode_remove_software_node(struct fwnode_handle *fwnode)
} }
EXPORT_SYMBOL_GPL(fwnode_remove_software_node); EXPORT_SYMBOL_GPL(fwnode_remove_software_node);
/**
* device_add_software_node - Assign software node to a device
* @dev: The device the software node is meant for.
* @swnode: The software node.
*
* This function will register @swnode and make it the secondary firmware node
* pointer of @dev. If @dev has no primary node, then @swnode will become the primary
* node.
*/
int device_add_software_node(struct device *dev, const struct software_node *swnode)
{
int ret;
/* Only one software node per device. */
if (dev_to_swnode(dev))
return -EBUSY;
ret = software_node_register(swnode);
if (ret)
return ret;
set_secondary_fwnode(dev, software_node_fwnode(swnode));
return 0;
}
EXPORT_SYMBOL_GPL(device_add_software_node);
/**
* device_remove_software_node - Remove device's software node
* @dev: The device with the software node.
*
* This function will unregister the software node of @dev.
*/
void device_remove_software_node(struct device *dev)
{
struct swnode *swnode;
swnode = dev_to_swnode(dev);
if (!swnode)
return;
software_node_notify(dev, KOBJ_REMOVE);
set_secondary_fwnode(dev, NULL);
kobject_put(&swnode->kobj);
}
EXPORT_SYMBOL_GPL(device_remove_software_node);
/**
* device_create_managed_software_node - Create a software node for a device
* @dev: The device the software node is assigned to.
* @properties: Device properties for the software node.
* @parent: Parent of the software node.
*
* Creates a software node as a managed resource for @dev, which means the
* lifetime of the newly created software node is tied to the lifetime of @dev.
* Software nodes created with this function should not be reused or shared
* because of that. The function takes a deep copy of @properties for the
* software node.
*
* Since the new software node is assigned directly to @dev, and since it should
* not be shared, it is not returned to the caller. The function returns 0 on
* success, and errno in case of an error.
*/
int device_create_managed_software_node(struct device *dev,
const struct property_entry *properties,
const struct software_node *parent)
{
struct fwnode_handle *p = software_node_fwnode(parent);
struct fwnode_handle *fwnode;
if (parent && !p)
return -EINVAL;
fwnode = fwnode_create_software_node(properties, p);
if (IS_ERR(fwnode))
return PTR_ERR(fwnode);
to_swnode(fwnode)->managed = true;
set_secondary_fwnode(dev, fwnode);
return 0;
}
EXPORT_SYMBOL_GPL(device_create_managed_software_node);
int software_node_notify(struct device *dev, unsigned long action) int software_node_notify(struct device *dev, unsigned long action)
{ {
struct fwnode_handle *fwnode = dev_fwnode(dev);
struct swnode *swnode; struct swnode *swnode;
int ret; int ret;
if (!fwnode) swnode = dev_to_swnode(dev);
return 0; if (!swnode)
if (!is_software_node(fwnode))
fwnode = fwnode->secondary;
if (!is_software_node(fwnode))
return 0; return 0;
swnode = to_swnode(fwnode);
switch (action) { switch (action) {
case KOBJ_ADD: case KOBJ_ADD:
ret = sysfs_create_link(&dev->kobj, &swnode->kobj, ret = sysfs_create_link(&dev->kobj, &swnode->kobj,
...@@ -878,6 +969,11 @@ int software_node_notify(struct device *dev, unsigned long action) ...@@ -878,6 +969,11 @@ int software_node_notify(struct device *dev, unsigned long action)
sysfs_remove_link(&swnode->kobj, dev_name(dev)); sysfs_remove_link(&swnode->kobj, dev_name(dev));
sysfs_remove_link(&dev->kobj, "software_node"); sysfs_remove_link(&dev->kobj, "software_node");
kobject_put(&swnode->kobj); kobject_put(&swnode->kobj);
if (swnode->managed) {
set_secondary_fwnode(dev, NULL);
kobject_put(&swnode->kobj);
}
break; break;
default: default:
break; break;
......
This diff is collapsed.
...@@ -115,3 +115,68 @@ void tb_acpi_add_links(struct tb_nhi *nhi) ...@@ -115,3 +115,68 @@ void tb_acpi_add_links(struct tb_nhi *nhi)
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
dev_warn(&nhi->pdev->dev, "failed to enumerate tunneled ports\n"); dev_warn(&nhi->pdev->dev, "failed to enumerate tunneled ports\n");
} }
/**
* tb_acpi_is_native() - Did the platform grant native TBT/USB4 control
*
* Returns %true if the platform granted OS native control over
* TBT/USB4. In this case software based connection manager can be used,
* otherwise there is firmware based connection manager running.
*/
bool tb_acpi_is_native(void)
{
return osc_sb_native_usb4_support_confirmed &&
osc_sb_native_usb4_control;
}
/**
* tb_acpi_may_tunnel_usb3() - Is USB3 tunneling allowed by the platform
*
* When software based connection manager is used, this function
* returns %true if platform allows native USB3 tunneling.
*/
bool tb_acpi_may_tunnel_usb3(void)
{
if (tb_acpi_is_native())
return osc_sb_native_usb4_control & OSC_USB_USB3_TUNNELING;
return true;
}
/**
* tb_acpi_may_tunnel_dp() - Is DisplayPort tunneling allowed by the platform
*
* When software based connection manager is used, this function
* returns %true if platform allows native DP tunneling.
*/
bool tb_acpi_may_tunnel_dp(void)
{
if (tb_acpi_is_native())
return osc_sb_native_usb4_control & OSC_USB_DP_TUNNELING;
return true;
}
/**
* tb_acpi_may_tunnel_pcie() - Is PCIe tunneling allowed by the platform
*
* When software based connection manager is used, this function
* returns %true if platform allows native PCIe tunneling.
*/
bool tb_acpi_may_tunnel_pcie(void)
{
if (tb_acpi_is_native())
return osc_sb_native_usb4_control & OSC_USB_PCIE_TUNNELING;
return true;
}
/**
* tb_acpi_is_xdomain_allowed() - Are XDomain connections allowed
*
* When software based connection manager is used, this function
* returns %true if platform allows XDomain connections.
*/
bool tb_acpi_is_xdomain_allowed(void)
{
if (tb_acpi_is_native())
return osc_sb_native_usb4_control & OSC_USB_XDOMAIN;
return true;
}
...@@ -178,7 +178,7 @@ int tb_switch_next_cap(struct tb_switch *sw, unsigned int offset) ...@@ -178,7 +178,7 @@ int tb_switch_next_cap(struct tb_switch *sw, unsigned int offset)
/** /**
* tb_switch_find_cap() - Find switch capability * tb_switch_find_cap() - Find switch capability
* @sw Switch to find the capability for * @sw: Switch to find the capability for
* @cap: Capability to look * @cap: Capability to look
* *
* Returns offset to start of capability or %-ENOENT if no such * Returns offset to start of capability or %-ENOENT if no such
......
...@@ -20,7 +20,17 @@ ...@@ -20,7 +20,17 @@
#define TB_CTL_RETRIES 4 #define TB_CTL_RETRIES 4
/** /**
* struct tb_cfg - thunderbolt control channel * struct tb_ctl - Thunderbolt control channel
* @nhi: Pointer to the NHI structure
* @tx: Transmit ring
* @rx: Receive ring
* @frame_pool: DMA pool for control messages
* @rx_packets: Received control messages
* @request_queue_lock: Lock protecting @request_queue
* @request_queue: List of outstanding requests
* @running: Is the control channel running at the moment
* @callback: Callback called when hotplug message is received
* @callback_data: Data passed to @callback
*/ */
struct tb_ctl { struct tb_ctl {
struct tb_nhi *nhi; struct tb_nhi *nhi;
...@@ -338,7 +348,7 @@ static void tb_ctl_tx_callback(struct tb_ring *ring, struct ring_frame *frame, ...@@ -338,7 +348,7 @@ static void tb_ctl_tx_callback(struct tb_ring *ring, struct ring_frame *frame,
tb_ctl_pkg_free(pkg); tb_ctl_pkg_free(pkg);
} }
/** /*
* tb_cfg_tx() - transmit a packet on the control channel * tb_cfg_tx() - transmit a packet on the control channel
* *
* len must be a multiple of four. * len must be a multiple of four.
...@@ -375,7 +385,7 @@ static int tb_ctl_tx(struct tb_ctl *ctl, const void *data, size_t len, ...@@ -375,7 +385,7 @@ static int tb_ctl_tx(struct tb_ctl *ctl, const void *data, size_t len,
return res; return res;
} }
/** /*
* tb_ctl_handle_event() - acknowledge a plug event, invoke ctl->callback * tb_ctl_handle_event() - acknowledge a plug event, invoke ctl->callback
*/ */
static bool tb_ctl_handle_event(struct tb_ctl *ctl, enum tb_cfg_pkg_type type, static bool tb_ctl_handle_event(struct tb_ctl *ctl, enum tb_cfg_pkg_type type,
...@@ -602,6 +612,9 @@ struct tb_cfg_result tb_cfg_request_sync(struct tb_ctl *ctl, ...@@ -602,6 +612,9 @@ struct tb_cfg_result tb_cfg_request_sync(struct tb_ctl *ctl,
/** /**
* tb_ctl_alloc() - allocate a control channel * tb_ctl_alloc() - allocate a control channel
* @nhi: Pointer to NHI
* @cb: Callback called for plug events
* @cb_data: Data passed to @cb
* *
* cb will be invoked once for every hot plug event. * cb will be invoked once for every hot plug event.
* *
...@@ -649,6 +662,7 @@ struct tb_ctl *tb_ctl_alloc(struct tb_nhi *nhi, event_cb cb, void *cb_data) ...@@ -649,6 +662,7 @@ struct tb_ctl *tb_ctl_alloc(struct tb_nhi *nhi, event_cb cb, void *cb_data)
/** /**
* tb_ctl_free() - free a control channel * tb_ctl_free() - free a control channel
* @ctl: Control channel to free
* *
* Must be called after tb_ctl_stop. * Must be called after tb_ctl_stop.
* *
...@@ -677,6 +691,7 @@ void tb_ctl_free(struct tb_ctl *ctl) ...@@ -677,6 +691,7 @@ void tb_ctl_free(struct tb_ctl *ctl)
/** /**
* tb_cfg_start() - start/resume the control channel * tb_cfg_start() - start/resume the control channel
* @ctl: Control channel to start
*/ */
void tb_ctl_start(struct tb_ctl *ctl) void tb_ctl_start(struct tb_ctl *ctl)
{ {
...@@ -691,7 +706,8 @@ void tb_ctl_start(struct tb_ctl *ctl) ...@@ -691,7 +706,8 @@ void tb_ctl_start(struct tb_ctl *ctl)
} }
/** /**
* control() - pause the control channel * tb_ctrl_stop() - pause the control channel
* @ctl: Control channel to stop
* *
* All invocations of ctl->callback will have finished after this method * All invocations of ctl->callback will have finished after this method
* returns. * returns.
...@@ -784,6 +800,9 @@ static bool tb_cfg_copy(struct tb_cfg_request *req, const struct ctl_pkg *pkg) ...@@ -784,6 +800,9 @@ static bool tb_cfg_copy(struct tb_cfg_request *req, const struct ctl_pkg *pkg)
/** /**
* tb_cfg_reset() - send a reset packet and wait for a response * tb_cfg_reset() - send a reset packet and wait for a response
* @ctl: Control channel pointer
* @route: Router string for the router to send reset
* @timeout_msec: Timeout in ms how long to wait for the response
* *
* If the switch at route is incorrectly configured then we will not receive a * If the switch at route is incorrectly configured then we will not receive a
* reply (even though the switch will reset). The caller should check for * reply (even though the switch will reset). The caller should check for
...@@ -820,9 +839,17 @@ struct tb_cfg_result tb_cfg_reset(struct tb_ctl *ctl, u64 route, ...@@ -820,9 +839,17 @@ struct tb_cfg_result tb_cfg_reset(struct tb_ctl *ctl, u64 route,
} }
/** /**
* tb_cfg_read() - read from config space into buffer * tb_cfg_read_raw() - read from config space into buffer
* @ctl: Pointer to the control channel
* @buffer: Buffer where the data is read
* @route: Route string of the router
* @port: Port number when reading from %TB_CFG_PORT, %0 otherwise
* @space: Config space selector
* @offset: Dword word offset of the register to start reading
* @length: Number of dwords to read
* @timeout_msec: Timeout in ms how long to wait for the response
* *
* Offset and length are in dwords. * Reads from router config space without translating the possible error.
*/ */
struct tb_cfg_result tb_cfg_read_raw(struct tb_ctl *ctl, void *buffer, struct tb_cfg_result tb_cfg_read_raw(struct tb_ctl *ctl, void *buffer,
u64 route, u32 port, enum tb_cfg_space space, u64 route, u32 port, enum tb_cfg_space space,
...@@ -884,8 +911,16 @@ struct tb_cfg_result tb_cfg_read_raw(struct tb_ctl *ctl, void *buffer, ...@@ -884,8 +911,16 @@ 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() - write from buffer into config space
* @ctl: Pointer to the control channel
* @buffer: Data to write
* @route: Route string of the router
* @port: Port number when writing to %TB_CFG_PORT, %0 otherwise
* @space: Config space selector
* @offset: Dword word offset of the register to start writing
* @length: Number of dwords to write
* @timeout_msec: Timeout in ms how long to wait for the response
* *
* Offset and length are in dwords. * Writes to router config space without translating the possible error.
*/ */
struct tb_cfg_result tb_cfg_write_raw(struct tb_ctl *ctl, const void *buffer, struct tb_cfg_result tb_cfg_write_raw(struct tb_ctl *ctl, const void *buffer,
u64 route, u32 port, enum tb_cfg_space space, u64 route, u32 port, enum tb_cfg_space space,
...@@ -1022,6 +1057,8 @@ int tb_cfg_write(struct tb_ctl *ctl, const void *buffer, u64 route, u32 port, ...@@ -1022,6 +1057,8 @@ int tb_cfg_write(struct tb_ctl *ctl, const void *buffer, u64 route, u32 port,
/** /**
* tb_cfg_get_upstream_port() - get upstream port number of switch at route * tb_cfg_get_upstream_port() - get upstream port number of switch at route
* @ctl: Pointer to the control channel
* @route: Route string of the router
* *
* Reads the first dword from the switches TB_CFG_SWITCH config area and * Reads the first dword from the switches TB_CFG_SWITCH config area and
* returns the port number from which the reply originated. * returns the port number from which the reply originated.
......
...@@ -335,6 +335,8 @@ static int dma_port_flash_write_block(struct tb_dma_port *dma, u32 address, ...@@ -335,6 +335,8 @@ static int dma_port_flash_write_block(struct tb_dma_port *dma, u32 address,
/* Write the block to MAIL_DATA registers */ /* Write the block to MAIL_DATA registers */
ret = dma_port_write(sw->tb->ctl, buf, tb_route(sw), dma->port, ret = dma_port_write(sw->tb->ctl, buf, tb_route(sw), dma->port,
dma->base + MAIL_DATA, dwords, DMA_PORT_TIMEOUT); dma->base + MAIL_DATA, dwords, DMA_PORT_TIMEOUT);
if (ret)
return ret;
in = MAIL_IN_CMD_FLASH_WRITE << MAIL_IN_CMD_SHIFT; in = MAIL_IN_CMD_FLASH_WRITE << MAIL_IN_CMD_SHIFT;
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
* Mika Westerberg <mika.westerberg@linux.intel.com> * Mika Westerberg <mika.westerberg@linux.intel.com>
*/ */
#include <linux/acpi.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -299,14 +298,12 @@ static int dma_test_submit_tx(struct dma_test *dt, size_t npackets) ...@@ -299,14 +298,12 @@ static int dma_test_submit_tx(struct dma_test *dt, size_t npackets)
tf->frame.size = 0; /* means 4096 */ tf->frame.size = 0; /* means 4096 */
tf->dma_test = dt; tf->dma_test = dt;
tf->data = kzalloc(DMA_TEST_FRAME_SIZE, GFP_KERNEL); tf->data = kmemdup(dma_test_pattern, DMA_TEST_FRAME_SIZE, GFP_KERNEL);
if (!tf->data) { if (!tf->data) {
kfree(tf); kfree(tf);
return -ENOMEM; return -ENOMEM;
} }
memcpy(tf->data, dma_test_pattern, DMA_TEST_FRAME_SIZE);
dma_addr = dma_map_single(dma_dev, tf->data, DMA_TEST_FRAME_SIZE, dma_addr = dma_map_single(dma_dev, tf->data, DMA_TEST_FRAME_SIZE,
DMA_TO_DEVICE); DMA_TO_DEVICE);
if (dma_mapping_error(dma_dev, dma_addr)) { if (dma_mapping_error(dma_dev, dma_addr)) {
......
...@@ -118,6 +118,7 @@ static const char * const tb_security_names[] = { ...@@ -118,6 +118,7 @@ static const char * const tb_security_names[] = {
[TB_SECURITY_SECURE] = "secure", [TB_SECURITY_SECURE] = "secure",
[TB_SECURITY_DPONLY] = "dponly", [TB_SECURITY_DPONLY] = "dponly",
[TB_SECURITY_USBONLY] = "usbonly", [TB_SECURITY_USBONLY] = "usbonly",
[TB_SECURITY_NOPCIE] = "nopcie",
}; };
static ssize_t boot_acl_show(struct device *dev, struct device_attribute *attr, static ssize_t boot_acl_show(struct device *dev, struct device_attribute *attr,
...@@ -238,6 +239,22 @@ static ssize_t boot_acl_store(struct device *dev, struct device_attribute *attr, ...@@ -238,6 +239,22 @@ static ssize_t boot_acl_store(struct device *dev, struct device_attribute *attr,
} }
static DEVICE_ATTR_RW(boot_acl); static DEVICE_ATTR_RW(boot_acl);
static ssize_t deauthorization_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
const struct tb *tb = container_of(dev, struct tb, dev);
bool deauthorization = false;
/* Only meaningful if authorization is supported */
if (tb->security_level == TB_SECURITY_USER ||
tb->security_level == TB_SECURITY_SECURE)
deauthorization = !!tb->cm_ops->disapprove_switch;
return sprintf(buf, "%d\n", deauthorization);
}
static DEVICE_ATTR_RO(deauthorization);
static ssize_t iommu_dma_protection_show(struct device *dev, static ssize_t iommu_dma_protection_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
...@@ -267,6 +284,7 @@ static DEVICE_ATTR_RO(security); ...@@ -267,6 +284,7 @@ static DEVICE_ATTR_RO(security);
static struct attribute *domain_attrs[] = { static struct attribute *domain_attrs[] = {
&dev_attr_boot_acl.attr, &dev_attr_boot_acl.attr,
&dev_attr_deauthorization.attr,
&dev_attr_iommu_dma_protection.attr, &dev_attr_iommu_dma_protection.attr,
&dev_attr_security.attr, &dev_attr_security.attr,
NULL, NULL,
...@@ -289,7 +307,7 @@ static umode_t domain_attr_is_visible(struct kobject *kobj, ...@@ -289,7 +307,7 @@ static umode_t domain_attr_is_visible(struct kobject *kobj,
return attr->mode; return attr->mode;
} }
static struct attribute_group domain_attr_group = { static const struct attribute_group domain_attr_group = {
.is_visible = domain_attr_is_visible, .is_visible = domain_attr_is_visible,
.attrs = domain_attrs, .attrs = domain_attrs,
}; };
...@@ -394,7 +412,9 @@ static bool tb_domain_event_cb(void *data, enum tb_cfg_pkg_type type, ...@@ -394,7 +412,9 @@ static bool tb_domain_event_cb(void *data, enum tb_cfg_pkg_type type,
switch (type) { switch (type) {
case TB_CFG_PKG_XDOMAIN_REQ: case TB_CFG_PKG_XDOMAIN_REQ:
case TB_CFG_PKG_XDOMAIN_RESP: case TB_CFG_PKG_XDOMAIN_RESP:
return tb_xdomain_handle_request(tb, type, buf, size); if (tb_is_xdomain_enabled())
return tb_xdomain_handle_request(tb, type, buf, size);
break;
default: default:
tb->cm_ops->handle_event(tb, type, buf, size); tb->cm_ops->handle_event(tb, type, buf, size);
...@@ -441,6 +461,9 @@ int tb_domain_add(struct tb *tb) ...@@ -441,6 +461,9 @@ int tb_domain_add(struct tb *tb)
goto err_ctl_stop; goto err_ctl_stop;
} }
tb_dbg(tb, "security level set to %s\n",
tb_security_names[tb->security_level]);
ret = device_add(&tb->dev); ret = device_add(&tb->dev);
if (ret) if (ret)
goto err_ctl_stop; goto err_ctl_stop;
...@@ -601,14 +624,31 @@ int tb_domain_runtime_resume(struct tb *tb) ...@@ -601,14 +624,31 @@ int tb_domain_runtime_resume(struct tb *tb)
return 0; return 0;
} }
/**
* tb_domain_disapprove_switch() - Disapprove switch
* @tb: Domain the switch belongs to
* @sw: Switch to disapprove
*
* This will disconnect PCIe tunnel from parent to this @sw.
*
* Return: %0 on success and negative errno in case of failure.
*/
int tb_domain_disapprove_switch(struct tb *tb, struct tb_switch *sw)
{
if (!tb->cm_ops->disapprove_switch)
return -EPERM;
return tb->cm_ops->disapprove_switch(tb, sw);
}
/** /**
* tb_domain_approve_switch() - Approve switch * tb_domain_approve_switch() - Approve switch
* @tb: Domain the switch belongs to * @tb: Domain the switch belongs to
* @sw: Switch to approve * @sw: Switch to approve
* *
* This will approve switch by connection manager specific means. In * This will approve switch by connection manager specific means. In
* case of success the connection manager will create tunnels for all * case of success the connection manager will create PCIe tunnel from
* supported protocols. * parent to @sw.
*/ */
int tb_domain_approve_switch(struct tb *tb, struct tb_switch *sw) int tb_domain_approve_switch(struct tb *tb, struct tb_switch *sw)
{ {
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include "tb.h" #include "tb.h"
/** /*
* tb_eeprom_ctl_write() - write control word * tb_eeprom_ctl_write() - write control word
*/ */
static int tb_eeprom_ctl_write(struct tb_switch *sw, struct tb_eeprom_ctl *ctl) static int tb_eeprom_ctl_write(struct tb_switch *sw, struct tb_eeprom_ctl *ctl)
...@@ -20,7 +20,7 @@ static int tb_eeprom_ctl_write(struct tb_switch *sw, struct tb_eeprom_ctl *ctl) ...@@ -20,7 +20,7 @@ static int tb_eeprom_ctl_write(struct tb_switch *sw, struct tb_eeprom_ctl *ctl)
return tb_sw_write(sw, ctl, TB_CFG_SWITCH, sw->cap_plug_events + 4, 1); return tb_sw_write(sw, ctl, TB_CFG_SWITCH, sw->cap_plug_events + 4, 1);
} }
/** /*
* tb_eeprom_ctl_write() - read control word * tb_eeprom_ctl_write() - read control word
*/ */
static int tb_eeprom_ctl_read(struct tb_switch *sw, struct tb_eeprom_ctl *ctl) static int tb_eeprom_ctl_read(struct tb_switch *sw, struct tb_eeprom_ctl *ctl)
...@@ -33,7 +33,7 @@ enum tb_eeprom_transfer { ...@@ -33,7 +33,7 @@ enum tb_eeprom_transfer {
TB_EEPROM_OUT, TB_EEPROM_OUT,
}; };
/** /*
* tb_eeprom_active - enable rom access * tb_eeprom_active - enable rom access
* *
* WARNING: Always disable access after usage. Otherwise the controller will * WARNING: Always disable access after usage. Otherwise the controller will
...@@ -62,7 +62,7 @@ static int tb_eeprom_active(struct tb_switch *sw, bool enable) ...@@ -62,7 +62,7 @@ static int tb_eeprom_active(struct tb_switch *sw, bool enable)
} }
} }
/** /*
* tb_eeprom_transfer - transfer one bit * tb_eeprom_transfer - transfer one bit
* *
* If TB_EEPROM_IN is passed, then the bit can be retrieved from ctl->data_in. * If TB_EEPROM_IN is passed, then the bit can be retrieved from ctl->data_in.
...@@ -90,7 +90,7 @@ static int tb_eeprom_transfer(struct tb_switch *sw, struct tb_eeprom_ctl *ctl, ...@@ -90,7 +90,7 @@ static int tb_eeprom_transfer(struct tb_switch *sw, struct tb_eeprom_ctl *ctl,
return tb_eeprom_ctl_write(sw, ctl); return tb_eeprom_ctl_write(sw, ctl);
} }
/** /*
* tb_eeprom_out - write one byte to the bus * tb_eeprom_out - write one byte to the bus
*/ */
static int tb_eeprom_out(struct tb_switch *sw, u8 val) static int tb_eeprom_out(struct tb_switch *sw, u8 val)
...@@ -110,7 +110,7 @@ static int tb_eeprom_out(struct tb_switch *sw, u8 val) ...@@ -110,7 +110,7 @@ static int tb_eeprom_out(struct tb_switch *sw, u8 val)
return 0; return 0;
} }
/** /*
* tb_eeprom_in - read one byte from the bus * tb_eeprom_in - read one byte from the bus
*/ */
static int tb_eeprom_in(struct tb_switch *sw, u8 *val) static int tb_eeprom_in(struct tb_switch *sw, u8 *val)
...@@ -131,7 +131,7 @@ static int tb_eeprom_in(struct tb_switch *sw, u8 *val) ...@@ -131,7 +131,7 @@ static int tb_eeprom_in(struct tb_switch *sw, u8 *val)
return 0; return 0;
} }
/** /*
* tb_eeprom_get_drom_offset - get drom offset within eeprom * tb_eeprom_get_drom_offset - get drom offset within eeprom
*/ */
static int tb_eeprom_get_drom_offset(struct tb_switch *sw, u16 *offset) static int tb_eeprom_get_drom_offset(struct tb_switch *sw, u16 *offset)
...@@ -162,7 +162,7 @@ static int tb_eeprom_get_drom_offset(struct tb_switch *sw, u16 *offset) ...@@ -162,7 +162,7 @@ static int tb_eeprom_get_drom_offset(struct tb_switch *sw, u16 *offset)
return 0; return 0;
} }
/** /*
* tb_eeprom_read_n - read count bytes from offset into val * tb_eeprom_read_n - read count bytes from offset into val
*/ */
static int tb_eeprom_read_n(struct tb_switch *sw, u16 offset, u8 *val, static int tb_eeprom_read_n(struct tb_switch *sw, u16 offset, u8 *val,
...@@ -279,7 +279,9 @@ struct tb_drom_entry_port { ...@@ -279,7 +279,9 @@ struct tb_drom_entry_port {
/** /**
* tb_drom_read_uid_only - read uid directly from drom * tb_drom_read_uid_only() - Read UID directly from DROM
* @sw: Router whose UID to read
* @uid: UID is placed here
* *
* Does not use the cached copy in sw->drom. Used during resume to check switch * Does not use the cached copy in sw->drom. Used during resume to check switch
* identity. * identity.
...@@ -374,7 +376,7 @@ static int tb_drom_parse_entry_port(struct tb_switch *sw, ...@@ -374,7 +376,7 @@ static int tb_drom_parse_entry_port(struct tb_switch *sw,
return 0; return 0;
} }
/** /*
* tb_drom_parse_entries - parse the linked list of drom entries * tb_drom_parse_entries - parse the linked list of drom entries
* *
* Drom must have been copied to sw->drom. * Drom must have been copied to sw->drom.
...@@ -410,7 +412,7 @@ static int tb_drom_parse_entries(struct tb_switch *sw) ...@@ -410,7 +412,7 @@ static int tb_drom_parse_entries(struct tb_switch *sw)
return 0; return 0;
} }
/** /*
* tb_drom_copy_efi - copy drom supplied by EFI to sw->drom if present * tb_drom_copy_efi - copy drom supplied by EFI to sw->drom if present
*/ */
static int tb_drom_copy_efi(struct tb_switch *sw, u16 *size) static int tb_drom_copy_efi(struct tb_switch *sw, u16 *size)
...@@ -520,7 +522,14 @@ static int tb_drom_read_n(struct tb_switch *sw, u16 offset, u8 *val, ...@@ -520,7 +522,14 @@ static int tb_drom_read_n(struct tb_switch *sw, u16 offset, u8 *val,
} }
/** /**
* tb_drom_read - copy drom to sw->drom and parse it * tb_drom_read() - Copy DROM to sw->drom and parse it
* @sw: Router whose DROM to read and parse
*
* This function reads router DROM and if successful parses the entries and
* populates the fields in @sw accordingly. Can be called for any router
* generation.
*
* Returns %0 in case of success and negative errno otherwise.
*/ */
int tb_drom_read(struct tb_switch *sw) int tb_drom_read(struct tb_switch *sw)
{ {
......
...@@ -85,8 +85,8 @@ struct usb4_switch_nvm_auth { ...@@ -85,8 +85,8 @@ struct usb4_switch_nvm_auth {
* @set_uuid: Set UUID for the root switch (optional) * @set_uuid: Set UUID for the root switch (optional)
* @device_connected: Handle device connected ICM message * @device_connected: Handle device connected ICM message
* @device_disconnected: Handle device disconnected ICM message * @device_disconnected: Handle device disconnected ICM message
* @xdomain_connected - Handle XDomain connected ICM message * @xdomain_connected: Handle XDomain connected ICM message
* @xdomain_disconnected - Handle XDomain disconnected ICM message * @xdomain_disconnected: Handle XDomain disconnected ICM message
* @rtd3_veto: Handle RTD3 veto notification ICM message * @rtd3_veto: Handle RTD3 veto notification ICM message
*/ */
struct icm { struct icm {
...@@ -1701,10 +1701,12 @@ static void icm_handle_notification(struct work_struct *work) ...@@ -1701,10 +1701,12 @@ static void icm_handle_notification(struct work_struct *work)
icm->device_disconnected(tb, n->pkg); icm->device_disconnected(tb, n->pkg);
break; break;
case ICM_EVENT_XDOMAIN_CONNECTED: case ICM_EVENT_XDOMAIN_CONNECTED:
icm->xdomain_connected(tb, n->pkg); if (tb_is_xdomain_enabled())
icm->xdomain_connected(tb, n->pkg);
break; break;
case ICM_EVENT_XDOMAIN_DISCONNECTED: case ICM_EVENT_XDOMAIN_DISCONNECTED:
icm->xdomain_disconnected(tb, n->pkg); if (tb_is_xdomain_enabled())
icm->xdomain_disconnected(tb, n->pkg);
break; break;
case ICM_EVENT_RTD3_VETO: case ICM_EVENT_RTD3_VETO:
icm->rtd3_veto(tb, n->pkg); icm->rtd3_veto(tb, n->pkg);
......
...@@ -158,6 +158,41 @@ void tb_lc_unconfigure_xdomain(struct tb_port *port) ...@@ -158,6 +158,41 @@ void tb_lc_unconfigure_xdomain(struct tb_port *port)
tb_lc_set_xdomain_configured(port, false); tb_lc_set_xdomain_configured(port, false);
} }
/**
* tb_lc_start_lane_initialization() - Start lane initialization
* @port: Device router lane 0 adapter
*
* Starts lane initialization for @port after the router resumed from
* sleep. Should be called for those downstream lane adapters that were
* not connected (tb_lc_configure_port() was not called) before sleep.
*
* Returns %0 in success and negative errno in case of failure.
*/
int tb_lc_start_lane_initialization(struct tb_port *port)
{
struct tb_switch *sw = port->sw;
int ret, cap;
u32 ctrl;
if (!tb_route(sw))
return 0;
if (sw->generation < 2)
return 0;
cap = find_port_lc_cap(port);
if (cap < 0)
return cap;
ret = tb_sw_read(sw, &ctrl, TB_CFG_SWITCH, cap + TB_LC_SX_CTRL, 1);
if (ret)
return ret;
ctrl |= TB_LC_SX_CTRL_SLI;
return tb_sw_write(sw, &ctrl, TB_CFG_SWITCH, cap + TB_LC_SX_CTRL, 1);
}
static int tb_lc_set_wake_one(struct tb_switch *sw, unsigned int offset, static int tb_lc_set_wake_one(struct tb_switch *sw, unsigned int offset,
unsigned int flags) unsigned int flags)
{ {
......
...@@ -44,7 +44,7 @@ static int ring_interrupt_index(struct tb_ring *ring) ...@@ -44,7 +44,7 @@ static int ring_interrupt_index(struct tb_ring *ring)
return bit; return bit;
} }
/** /*
* ring_interrupt_active() - activate/deactivate interrupts for a single ring * ring_interrupt_active() - activate/deactivate interrupts for a single ring
* *
* ring->nhi->lock must be held. * ring->nhi->lock must be held.
...@@ -105,7 +105,7 @@ static void ring_interrupt_active(struct tb_ring *ring, bool active) ...@@ -105,7 +105,7 @@ static void ring_interrupt_active(struct tb_ring *ring, bool active)
iowrite32(new, ring->nhi->iobase + reg); iowrite32(new, ring->nhi->iobase + reg);
} }
/** /*
* nhi_disable_interrupts() - disable interrupts for all rings * nhi_disable_interrupts() - disable interrupts for all rings
* *
* Use only during init and shutdown. * Use only during init and shutdown.
...@@ -182,7 +182,7 @@ static bool ring_empty(struct tb_ring *ring) ...@@ -182,7 +182,7 @@ static bool ring_empty(struct tb_ring *ring)
return ring->head == ring->tail; return ring->head == ring->tail;
} }
/** /*
* ring_write_descriptors() - post frames from ring->queue to the controller * ring_write_descriptors() - post frames from ring->queue to the controller
* *
* ring->lock is held. * ring->lock is held.
...@@ -212,7 +212,7 @@ static void ring_write_descriptors(struct tb_ring *ring) ...@@ -212,7 +212,7 @@ static void ring_write_descriptors(struct tb_ring *ring)
} }
} }
/** /*
* ring_work() - progress completed frames * ring_work() - progress completed frames
* *
* If the ring is shutting down then all frames are marked as canceled and * If the ring is shutting down then all frames are marked as canceled and
...@@ -592,6 +592,7 @@ EXPORT_SYMBOL_GPL(tb_ring_alloc_rx); ...@@ -592,6 +592,7 @@ EXPORT_SYMBOL_GPL(tb_ring_alloc_rx);
/** /**
* tb_ring_start() - enable a ring * tb_ring_start() - enable a ring
* @ring: Ring to start
* *
* Must not be invoked in parallel with tb_ring_stop(). * Must not be invoked in parallel with tb_ring_stop().
*/ */
...@@ -667,6 +668,7 @@ EXPORT_SYMBOL_GPL(tb_ring_start); ...@@ -667,6 +668,7 @@ EXPORT_SYMBOL_GPL(tb_ring_start);
/** /**
* tb_ring_stop() - shutdown a ring * tb_ring_stop() - shutdown a ring
* @ring: Ring to stop
* *
* Must not be invoked from a callback. * Must not be invoked from a callback.
* *
...@@ -754,7 +756,7 @@ void tb_ring_free(struct tb_ring *ring) ...@@ -754,7 +756,7 @@ void tb_ring_free(struct tb_ring *ring)
dev_dbg(&ring->nhi->pdev->dev, "freeing %s %d\n", RING_TYPE(ring), dev_dbg(&ring->nhi->pdev->dev, "freeing %s %d\n", RING_TYPE(ring),
ring->hop); ring->hop);
/** /*
* ring->work can no longer be scheduled (it is scheduled only * ring->work can no longer be scheduled (it is scheduled only
* by nhi_interrupt_work, ring_stop and ring_msix). Wait for it * by nhi_interrupt_work, ring_stop and ring_msix). Wait for it
* to finish before freeing the ring. * to finish before freeing the ring.
...@@ -1188,6 +1190,29 @@ static void tb_apple_add_links(struct tb_nhi *nhi) ...@@ -1188,6 +1190,29 @@ static void tb_apple_add_links(struct tb_nhi *nhi)
} }
} }
static struct tb *nhi_select_cm(struct tb_nhi *nhi)
{
struct tb *tb;
/*
* USB4 case is simple. If we got control of any of the
* capabilities, we use software CM.
*/
if (tb_acpi_is_native())
return tb_probe(nhi);
/*
* Either firmware based CM is running (we did not get control
* from the firmware) or this is pre-USB4 PC so try first
* firmware CM and then fallback to software CM.
*/
tb = icm_probe(nhi);
if (!tb)
tb = tb_probe(nhi);
return tb;
}
static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{ {
struct tb_nhi *nhi; struct tb_nhi *nhi;
...@@ -1256,9 +1281,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1256,9 +1281,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
tb_apple_add_links(nhi); tb_apple_add_links(nhi);
tb_acpi_add_links(nhi); tb_acpi_add_links(nhi);
tb = icm_probe(nhi); tb = nhi_select_cm(nhi);
if (!tb)
tb = tb_probe(nhi);
if (!tb) { if (!tb) {
dev_err(&nhi->pdev->dev, dev_err(&nhi->pdev->dev,
"failed to determine connection manager, aborting\n"); "failed to determine connection manager, aborting\n");
......
...@@ -466,6 +466,7 @@ void tb_path_deactivate(struct tb_path *path) ...@@ -466,6 +466,7 @@ void tb_path_deactivate(struct tb_path *path)
/** /**
* tb_path_activate() - activate a path * tb_path_activate() - activate a path
* @path: Path to activate
* *
* Activate a path starting with the last hop and iterating backwards. The * Activate a path starting with the last hop and iterating backwards. The
* caller must fill path->hops before calling tb_path_activate(). * caller must fill path->hops before calling tb_path_activate().
...@@ -561,6 +562,7 @@ int tb_path_activate(struct tb_path *path) ...@@ -561,6 +562,7 @@ int tb_path_activate(struct tb_path *path)
/** /**
* tb_path_is_invalid() - check whether any ports on the path are invalid * tb_path_is_invalid() - check whether any ports on the path are invalid
* @path: Path to check
* *
* Return: Returns true if the path is invalid, false otherwise. * Return: Returns true if the path is invalid, false otherwise.
*/ */
......
...@@ -525,6 +525,8 @@ int tb_port_state(struct tb_port *port) ...@@ -525,6 +525,8 @@ int tb_port_state(struct tb_port *port)
/** /**
* tb_wait_for_port() - wait for a port to become ready * tb_wait_for_port() - wait for a port to become ready
* @port: Port to wait
* @wait_if_unplugged: Wait also when port is unplugged
* *
* Wait up to 1 second for a port to reach state TB_PORT_UP. If * Wait up to 1 second for a port to reach state TB_PORT_UP. If
* wait_if_unplugged is set then we also wait if the port is in state * wait_if_unplugged is set then we also wait if the port is in state
...@@ -589,6 +591,8 @@ int tb_wait_for_port(struct tb_port *port, bool wait_if_unplugged) ...@@ -589,6 +591,8 @@ int tb_wait_for_port(struct tb_port *port, bool wait_if_unplugged)
/** /**
* tb_port_add_nfc_credits() - add/remove non flow controlled credits to port * tb_port_add_nfc_credits() - add/remove non flow controlled credits to port
* @port: Port to add/remove NFC credits
* @credits: Credits to add/remove
* *
* Change the number of NFC credits allocated to @port by @credits. To remove * Change the number of NFC credits allocated to @port by @credits. To remove
* NFC credits pass a negative amount of credits. * NFC credits pass a negative amount of credits.
...@@ -646,6 +650,8 @@ int tb_port_set_initial_credits(struct tb_port *port, u32 credits) ...@@ -646,6 +650,8 @@ int tb_port_set_initial_credits(struct tb_port *port, u32 credits)
/** /**
* tb_port_clear_counter() - clear a counter in TB_CFG_COUNTER * tb_port_clear_counter() - clear a counter in TB_CFG_COUNTER
* @port: Port whose counters to clear
* @counter: Counter index to clear
* *
* Return: Returns 0 on success or an error code on failure. * Return: Returns 0 on success or an error code on failure.
*/ */
...@@ -718,7 +724,7 @@ int tb_port_disable(struct tb_port *port) ...@@ -718,7 +724,7 @@ int tb_port_disable(struct tb_port *port)
return __tb_port_enable(port, false); return __tb_port_enable(port, false);
} }
/** /*
* tb_init_port() - initialize a port * tb_init_port() - initialize a port
* *
* This is a helper method for tb_switch_alloc. Does not check or initialize * This is a helper method for tb_switch_alloc. Does not check or initialize
...@@ -1065,6 +1071,17 @@ void tb_port_lane_bonding_disable(struct tb_port *port) ...@@ -1065,6 +1071,17 @@ void tb_port_lane_bonding_disable(struct tb_port *port)
tb_port_set_link_width(port, 1); tb_port_set_link_width(port, 1);
} }
static int tb_port_start_lane_initialization(struct tb_port *port)
{
int ret;
if (tb_switch_is_usb4(port->sw))
return 0;
ret = tb_lc_start_lane_initialization(port);
return ret == -EINVAL ? 0 : ret;
}
/** /**
* tb_port_is_enabled() - Is the adapter port enabled * tb_port_is_enabled() - Is the adapter port enabled
* @port: Port to check * @port: Port to check
...@@ -1302,7 +1319,7 @@ static void tb_dump_switch(const struct tb *tb, const struct tb_switch *sw) ...@@ -1302,7 +1319,7 @@ static void tb_dump_switch(const struct tb *tb, const struct tb_switch *sw)
} }
/** /**
* reset_switch() - reconfigure route, enable and send TB_CFG_PKG_RESET * tb_switch_reset() - reconfigure route, enable and send TB_CFG_PKG_RESET
* @sw: Switch to reset * @sw: Switch to reset
* *
* Return: Returns 0 on success or an error code on failure. * Return: Returns 0 on success or an error code on failure.
...@@ -1326,7 +1343,7 @@ int tb_switch_reset(struct tb_switch *sw) ...@@ -1326,7 +1343,7 @@ int tb_switch_reset(struct tb_switch *sw)
return res.err; return res.err;
} }
/** /*
* tb_plug_events_active() - enable/disable plug events on a switch * tb_plug_events_active() - enable/disable plug events on a switch
* *
* Also configures a sane plug_events_delay of 255ms. * Also configures a sane plug_events_delay of 255ms.
...@@ -1376,6 +1393,30 @@ static ssize_t authorized_show(struct device *dev, ...@@ -1376,6 +1393,30 @@ static ssize_t authorized_show(struct device *dev,
return sprintf(buf, "%u\n", sw->authorized); return sprintf(buf, "%u\n", sw->authorized);
} }
static int disapprove_switch(struct device *dev, void *not_used)
{
struct tb_switch *sw;
sw = tb_to_switch(dev);
if (sw && sw->authorized) {
int ret;
/* First children */
ret = device_for_each_child_reverse(&sw->dev, NULL, disapprove_switch);
if (ret)
return ret;
ret = tb_domain_disapprove_switch(sw->tb, sw);
if (ret)
return ret;
sw->authorized = 0;
kobject_uevent(&sw->dev.kobj, KOBJ_CHANGE);
}
return 0;
}
static int tb_switch_set_authorized(struct tb_switch *sw, unsigned int val) static int tb_switch_set_authorized(struct tb_switch *sw, unsigned int val)
{ {
int ret = -EINVAL; int ret = -EINVAL;
...@@ -1383,10 +1424,18 @@ static int tb_switch_set_authorized(struct tb_switch *sw, unsigned int val) ...@@ -1383,10 +1424,18 @@ static int tb_switch_set_authorized(struct tb_switch *sw, unsigned int val)
if (!mutex_trylock(&sw->tb->lock)) if (!mutex_trylock(&sw->tb->lock))
return restart_syscall(); return restart_syscall();
if (sw->authorized) if (!!sw->authorized == !!val)
goto unlock; goto unlock;
switch (val) { switch (val) {
/* Disapprove switch */
case 0:
if (tb_route(sw)) {
ret = disapprove_switch(&sw->dev, NULL);
goto unlock;
}
break;
/* Approve switch */ /* Approve switch */
case 1: case 1:
if (sw->key) if (sw->key)
...@@ -1725,7 +1774,11 @@ static umode_t switch_attr_is_visible(struct kobject *kobj, ...@@ -1725,7 +1774,11 @@ static umode_t switch_attr_is_visible(struct kobject *kobj,
struct device *dev = kobj_to_dev(kobj); struct device *dev = kobj_to_dev(kobj);
struct tb_switch *sw = tb_to_switch(dev); struct tb_switch *sw = tb_to_switch(dev);
if (attr == &dev_attr_device.attr) { if (attr == &dev_attr_authorized.attr) {
if (sw->tb->security_level == TB_SECURITY_NOPCIE ||
sw->tb->security_level == TB_SECURITY_DPONLY)
return 0;
} else if (attr == &dev_attr_device.attr) {
if (!sw->device) if (!sw->device)
return 0; return 0;
} else if (attr == &dev_attr_device_name.attr) { } else if (attr == &dev_attr_device_name.attr) {
...@@ -1771,7 +1824,7 @@ static umode_t switch_attr_is_visible(struct kobject *kobj, ...@@ -1771,7 +1824,7 @@ static umode_t switch_attr_is_visible(struct kobject *kobj,
return sw->safe_mode ? 0 : attr->mode; return sw->safe_mode ? 0 : attr->mode;
} }
static struct attribute_group switch_group = { static const struct attribute_group switch_group = {
.is_visible = switch_attr_is_visible, .is_visible = switch_attr_is_visible,
.attrs = switch_attrs, .attrs = switch_attrs,
}; };
...@@ -2606,6 +2659,7 @@ void tb_switch_remove(struct tb_switch *sw) ...@@ -2606,6 +2659,7 @@ void tb_switch_remove(struct tb_switch *sw)
/** /**
* tb_sw_set_unplugged() - set is_unplugged on switch and downstream switches * tb_sw_set_unplugged() - set is_unplugged on switch and downstream switches
* @sw: Router to mark unplugged
*/ */
void tb_sw_set_unplugged(struct tb_switch *sw) void tb_sw_set_unplugged(struct tb_switch *sw)
{ {
...@@ -2694,8 +2748,22 @@ int tb_switch_resume(struct tb_switch *sw) ...@@ -2694,8 +2748,22 @@ int tb_switch_resume(struct tb_switch *sw)
/* check for surviving downstream switches */ /* check for surviving downstream switches */
tb_switch_for_each_port(sw, port) { tb_switch_for_each_port(sw, port) {
if (!tb_port_has_remote(port) && !port->xdomain) if (!tb_port_has_remote(port) && !port->xdomain) {
/*
* For disconnected downstream lane adapters
* start lane initialization now so we detect
* future connects.
*/
if (!tb_is_upstream_port(port) && tb_port_is_null(port))
tb_port_start_lane_initialization(port);
continue; continue;
} else if (port->xdomain) {
/*
* Start lane initialization for XDomain so the
* link gets re-established.
*/
tb_port_start_lane_initialization(port);
}
if (tb_wait_for_port(port, true) <= 0) { if (tb_wait_for_port(port, true) <= 0) {
tb_port_warn(port, tb_port_warn(port,
......
...@@ -179,6 +179,9 @@ static void tb_scan_xdomain(struct tb_port *port) ...@@ -179,6 +179,9 @@ static void tb_scan_xdomain(struct tb_port *port)
struct tb_xdomain *xd; struct tb_xdomain *xd;
u64 route; u64 route;
if (!tb_is_xdomain_enabled())
return;
route = tb_downstream_route(port); route = tb_downstream_route(port);
xd = tb_xdomain_find_by_route(tb, route); xd = tb_xdomain_find_by_route(tb, route);
if (xd) { if (xd) {
...@@ -434,6 +437,11 @@ static int tb_tunnel_usb3(struct tb *tb, struct tb_switch *sw) ...@@ -434,6 +437,11 @@ static int tb_tunnel_usb3(struct tb *tb, struct tb_switch *sw)
struct tb_cm *tcm = tb_priv(tb); struct tb_cm *tcm = tb_priv(tb);
struct tb_tunnel *tunnel; struct tb_tunnel *tunnel;
if (!tb_acpi_may_tunnel_usb3()) {
tb_dbg(tb, "USB3 tunneling disabled, not creating tunnel\n");
return 0;
}
up = tb_switch_find_port(sw, TB_TYPE_USB3_UP); up = tb_switch_find_port(sw, TB_TYPE_USB3_UP);
if (!up) if (!up)
return 0; return 0;
...@@ -509,6 +517,9 @@ static int tb_create_usb3_tunnels(struct tb_switch *sw) ...@@ -509,6 +517,9 @@ static int tb_create_usb3_tunnels(struct tb_switch *sw)
struct tb_port *port; struct tb_port *port;
int ret; int ret;
if (!tb_acpi_may_tunnel_usb3())
return 0;
if (tb_route(sw)) { if (tb_route(sw)) {
ret = tb_tunnel_usb3(sw->tb, sw); ret = tb_tunnel_usb3(sw->tb, sw);
if (ret) if (ret)
...@@ -528,7 +539,7 @@ static int tb_create_usb3_tunnels(struct tb_switch *sw) ...@@ -528,7 +539,7 @@ static int tb_create_usb3_tunnels(struct tb_switch *sw)
static void tb_scan_port(struct tb_port *port); static void tb_scan_port(struct tb_port *port);
/** /*
* tb_scan_switch() - scan for and initialize downstream switches * tb_scan_switch() - scan for and initialize downstream switches
*/ */
static void tb_scan_switch(struct tb_switch *sw) static void tb_scan_switch(struct tb_switch *sw)
...@@ -544,7 +555,7 @@ static void tb_scan_switch(struct tb_switch *sw) ...@@ -544,7 +555,7 @@ static void tb_scan_switch(struct tb_switch *sw)
pm_runtime_put_autosuspend(&sw->dev); pm_runtime_put_autosuspend(&sw->dev);
} }
/** /*
* tb_scan_port() - check for and initialize switches below port * tb_scan_port() - check for and initialize switches below port
*/ */
static void tb_scan_port(struct tb_port *port) static void tb_scan_port(struct tb_port *port)
...@@ -704,7 +715,7 @@ static void tb_deactivate_and_free_tunnel(struct tb_tunnel *tunnel) ...@@ -704,7 +715,7 @@ static void tb_deactivate_and_free_tunnel(struct tb_tunnel *tunnel)
tb_tunnel_free(tunnel); tb_tunnel_free(tunnel);
} }
/** /*
* tb_free_invalid_tunnels() - destroy tunnels of devices that have gone away * tb_free_invalid_tunnels() - destroy tunnels of devices that have gone away
*/ */
static void tb_free_invalid_tunnels(struct tb *tb) static void tb_free_invalid_tunnels(struct tb *tb)
...@@ -719,7 +730,7 @@ static void tb_free_invalid_tunnels(struct tb *tb) ...@@ -719,7 +730,7 @@ static void tb_free_invalid_tunnels(struct tb *tb)
} }
} }
/** /*
* tb_free_unplugged_children() - traverse hierarchy and free unplugged switches * tb_free_unplugged_children() - traverse hierarchy and free unplugged switches
*/ */
static void tb_free_unplugged_children(struct tb_switch *sw) static void tb_free_unplugged_children(struct tb_switch *sw)
...@@ -838,6 +849,11 @@ static void tb_tunnel_dp(struct tb *tb) ...@@ -838,6 +849,11 @@ static void tb_tunnel_dp(struct tb *tb)
struct tb_port *port, *in, *out; struct tb_port *port, *in, *out;
struct tb_tunnel *tunnel; struct tb_tunnel *tunnel;
if (!tb_acpi_may_tunnel_dp()) {
tb_dbg(tb, "DP tunneling disabled, not creating tunnel\n");
return;
}
/* /*
* Find pair of inactive DP IN and DP OUT adapters and then * Find pair of inactive DP IN and DP OUT adapters and then
* establish a DP tunnel between them. * establish a DP tunnel between them.
...@@ -1002,6 +1018,25 @@ static void tb_disconnect_and_release_dp(struct tb *tb) ...@@ -1002,6 +1018,25 @@ static void tb_disconnect_and_release_dp(struct tb *tb)
} }
} }
static int tb_disconnect_pci(struct tb *tb, struct tb_switch *sw)
{
struct tb_tunnel *tunnel;
struct tb_port *up;
up = tb_switch_find_port(sw, TB_TYPE_PCIE_UP);
if (WARN_ON(!up))
return -ENODEV;
tunnel = tb_find_tunnel(tb, TB_TUNNEL_PCI, NULL, up);
if (WARN_ON(!tunnel))
return -ENODEV;
tb_tunnel_deactivate(tunnel);
list_del(&tunnel->list);
tb_tunnel_free(tunnel);
return 0;
}
static int tb_tunnel_pci(struct tb *tb, struct tb_switch *sw) static int tb_tunnel_pci(struct tb *tb, struct tb_switch *sw)
{ {
struct tb_port *up, *down, *port; struct tb_port *up, *down, *port;
...@@ -1101,7 +1136,7 @@ static int tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd) ...@@ -1101,7 +1136,7 @@ static int tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd)
/* hotplug handling */ /* hotplug handling */
/** /*
* tb_handle_hotplug() - handle hotplug event * tb_handle_hotplug() - handle hotplug event
* *
* Executes on tb->wq. * Executes on tb->wq.
...@@ -1210,7 +1245,7 @@ static void tb_handle_hotplug(struct work_struct *work) ...@@ -1210,7 +1245,7 @@ static void tb_handle_hotplug(struct work_struct *work)
kfree(ev); kfree(ev);
} }
/** /*
* tb_schedule_hotplug_handler() - callback function for the control channel * tb_schedule_hotplug_handler() - callback function for the control channel
* *
* Delegates to tb_handle_hotplug. * Delegates to tb_handle_hotplug.
...@@ -1512,6 +1547,7 @@ static const struct tb_cm_ops tb_cm_ops = { ...@@ -1512,6 +1547,7 @@ static const struct tb_cm_ops tb_cm_ops = {
.runtime_suspend = tb_runtime_suspend, .runtime_suspend = tb_runtime_suspend,
.runtime_resume = tb_runtime_resume, .runtime_resume = tb_runtime_resume,
.handle_event = tb_handle_event, .handle_event = tb_handle_event,
.disapprove_switch = tb_disconnect_pci,
.approve_switch = tb_tunnel_pci, .approve_switch = tb_tunnel_pci,
.approve_xdomain_paths = tb_approve_xdomain_paths, .approve_xdomain_paths = tb_approve_xdomain_paths,
.disconnect_xdomain_paths = tb_disconnect_xdomain_paths, .disconnect_xdomain_paths = tb_disconnect_xdomain_paths,
...@@ -1526,7 +1562,11 @@ struct tb *tb_probe(struct tb_nhi *nhi) ...@@ -1526,7 +1562,11 @@ struct tb *tb_probe(struct tb_nhi *nhi)
if (!tb) if (!tb)
return NULL; return NULL;
tb->security_level = TB_SECURITY_USER; if (tb_acpi_may_tunnel_pcie())
tb->security_level = TB_SECURITY_USER;
else
tb->security_level = TB_SECURITY_NOPCIE;
tb->cm_ops = &tb_cm_ops; tb->cm_ops = &tb_cm_ops;
tcm = tb_priv(tb); tcm = tb_priv(tb);
......
...@@ -138,6 +138,8 @@ struct tb_switch_tmu { ...@@ -138,6 +138,8 @@ struct tb_switch_tmu {
* *
* When the switch is being added or removed to the domain (other * When the switch is being added or removed to the domain (other
* switches) you need to have domain lock held. * switches) you need to have domain lock held.
*
* In USB4 terminology this structure represents a router.
*/ */
struct tb_switch { struct tb_switch {
struct device dev; struct device dev;
...@@ -196,6 +198,9 @@ struct tb_switch { ...@@ -196,6 +198,9 @@ struct tb_switch {
* @in_hopids: Currently allocated input HopIDs * @in_hopids: Currently allocated input HopIDs
* @out_hopids: Currently allocated output HopIDs * @out_hopids: Currently allocated output HopIDs
* @list: Used to link ports to DP resources list * @list: Used to link ports to DP resources list
*
* In USB4 terminology this structure represents an adapter (protocol or
* lane adapter).
*/ */
struct tb_port { struct tb_port {
struct tb_regs_port_header config; struct tb_regs_port_header config;
...@@ -361,6 +366,7 @@ struct tb_path { ...@@ -361,6 +366,7 @@ struct tb_path {
* @handle_event: Handle thunderbolt event * @handle_event: Handle thunderbolt event
* @get_boot_acl: Get boot ACL list * @get_boot_acl: Get boot ACL list
* @set_boot_acl: Set boot ACL list * @set_boot_acl: Set boot ACL list
* @disapprove_switch: Disapprove switch (disconnect PCIe tunnel)
* @approve_switch: Approve switch * @approve_switch: Approve switch
* @add_switch_key: Add key to switch * @add_switch_key: Add key to switch
* @challenge_switch_key: Challenge switch using key * @challenge_switch_key: Challenge switch using key
...@@ -394,6 +400,7 @@ struct tb_cm_ops { ...@@ -394,6 +400,7 @@ struct tb_cm_ops {
const void *buf, size_t size); const void *buf, size_t size);
int (*get_boot_acl)(struct tb *tb, uuid_t *uuids, size_t nuuids); int (*get_boot_acl)(struct tb *tb, uuid_t *uuids, size_t nuuids);
int (*set_boot_acl)(struct tb *tb, const uuid_t *uuids, size_t nuuids); int (*set_boot_acl)(struct tb *tb, const uuid_t *uuids, size_t nuuids);
int (*disapprove_switch)(struct tb *tb, struct tb_switch *sw);
int (*approve_switch)(struct tb *tb, struct tb_switch *sw); int (*approve_switch)(struct tb *tb, struct tb_switch *sw);
int (*add_switch_key)(struct tb *tb, struct tb_switch *sw); int (*add_switch_key)(struct tb *tb, struct tb_switch *sw);
int (*challenge_switch_key)(struct tb *tb, struct tb_switch *sw, int (*challenge_switch_key)(struct tb *tb, struct tb_switch *sw,
...@@ -629,6 +636,7 @@ int tb_domain_thaw_noirq(struct tb *tb); ...@@ -629,6 +636,7 @@ int tb_domain_thaw_noirq(struct tb *tb);
void tb_domain_complete(struct tb *tb); void tb_domain_complete(struct tb *tb);
int tb_domain_runtime_suspend(struct tb *tb); int tb_domain_runtime_suspend(struct tb *tb);
int tb_domain_runtime_resume(struct tb *tb); int tb_domain_runtime_resume(struct tb *tb);
int tb_domain_disapprove_switch(struct tb *tb, struct tb_switch *sw);
int tb_domain_approve_switch(struct tb *tb, struct tb_switch *sw); int tb_domain_approve_switch(struct tb *tb, struct tb_switch *sw);
int tb_domain_approve_switch_key(struct tb *tb, struct tb_switch *sw); int tb_domain_approve_switch_key(struct tb *tb, struct tb_switch *sw);
int tb_domain_challenge_switch_key(struct tb *tb, struct tb_switch *sw); int tb_domain_challenge_switch_key(struct tb *tb, struct tb_switch *sw);
...@@ -923,6 +931,7 @@ int tb_lc_configure_port(struct tb_port *port); ...@@ -923,6 +931,7 @@ int tb_lc_configure_port(struct tb_port *port);
void tb_lc_unconfigure_port(struct tb_port *port); void tb_lc_unconfigure_port(struct tb_port *port);
int tb_lc_configure_xdomain(struct tb_port *port); int tb_lc_configure_xdomain(struct tb_port *port);
void tb_lc_unconfigure_xdomain(struct tb_port *port); void tb_lc_unconfigure_xdomain(struct tb_port *port);
int tb_lc_start_lane_initialization(struct tb_port *port);
int tb_lc_set_wake(struct tb_switch *sw, unsigned int flags); int tb_lc_set_wake(struct tb_switch *sw, unsigned int flags);
int tb_lc_set_sleep(struct tb_switch *sw); int tb_lc_set_sleep(struct tb_switch *sw);
bool tb_lc_lane_bonding_possible(struct tb_switch *sw); bool tb_lc_lane_bonding_possible(struct tb_switch *sw);
...@@ -949,6 +958,7 @@ static inline u64 tb_downstream_route(struct tb_port *port) ...@@ -949,6 +958,7 @@ static inline u64 tb_downstream_route(struct tb_port *port)
| ((u64) port->port << (port->sw->config.depth * 8)); | ((u64) port->port << (port->sw->config.depth * 8));
} }
bool tb_is_xdomain_enabled(void);
bool tb_xdomain_handle_request(struct tb *tb, enum tb_cfg_pkg_type type, bool tb_xdomain_handle_request(struct tb *tb, enum tb_cfg_pkg_type type,
const void *buf, size_t size); const void *buf, size_t size);
struct tb_xdomain *tb_xdomain_alloc(struct tb *tb, struct device *parent, struct tb_xdomain *tb_xdomain_alloc(struct tb *tb, struct device *parent,
...@@ -1034,8 +1044,20 @@ void tb_check_quirks(struct tb_switch *sw); ...@@ -1034,8 +1044,20 @@ void tb_check_quirks(struct tb_switch *sw);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
void tb_acpi_add_links(struct tb_nhi *nhi); void tb_acpi_add_links(struct tb_nhi *nhi);
bool tb_acpi_is_native(void);
bool tb_acpi_may_tunnel_usb3(void);
bool tb_acpi_may_tunnel_dp(void);
bool tb_acpi_may_tunnel_pcie(void);
bool tb_acpi_is_xdomain_allowed(void);
#else #else
static inline void tb_acpi_add_links(struct tb_nhi *nhi) { } static inline void tb_acpi_add_links(struct tb_nhi *nhi) { }
static inline bool tb_acpi_is_native(void) { return true; }
static inline bool tb_acpi_may_tunnel_usb3(void) { return true; }
static inline bool tb_acpi_may_tunnel_dp(void) { return true; }
static inline bool tb_acpi_may_tunnel_pcie(void) { return true; }
static inline bool tb_acpi_is_xdomain_allowed(void) { return true; }
#endif #endif
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
......
...@@ -464,6 +464,7 @@ struct tb_regs_hop { ...@@ -464,6 +464,7 @@ struct tb_regs_hop {
#define TB_LC_SX_CTRL_L1D BIT(17) #define TB_LC_SX_CTRL_L1D BIT(17)
#define TB_LC_SX_CTRL_L2C BIT(20) #define TB_LC_SX_CTRL_L2C BIT(20)
#define TB_LC_SX_CTRL_L2D BIT(21) #define TB_LC_SX_CTRL_L2D BIT(21)
#define TB_LC_SX_CTRL_SLI BIT(29)
#define TB_LC_SX_CTRL_UPSTREAM BIT(30) #define TB_LC_SX_CTRL_UPSTREAM BIT(30)
#define TB_LC_SX_CTRL_SLP BIT(31) #define TB_LC_SX_CTRL_SLP BIT(31)
......
...@@ -830,7 +830,7 @@ static void tb_dma_init_path(struct tb_path *path, unsigned int isb, ...@@ -830,7 +830,7 @@ static void tb_dma_init_path(struct tb_path *path, unsigned int isb,
* @transmit_path: HopID used for transmitting packets * @transmit_path: HopID used for transmitting packets
* @receive_ring: NHI ring number used to receive packets from the * @receive_ring: NHI ring number used to receive packets from the
* other domain. Set to %0 if RX path is not needed. * other domain. Set to %0 if RX path is not needed.
* @reveive_path: HopID used for receiving packets * @receive_path: HopID used for receiving packets
* *
* Return: Returns a tb_tunnel on success or NULL on failure. * Return: Returns a tb_tunnel on success or NULL on failure.
*/ */
...@@ -932,12 +932,14 @@ static int tb_usb3_activate(struct tb_tunnel *tunnel, bool activate) ...@@ -932,12 +932,14 @@ static int tb_usb3_activate(struct tb_tunnel *tunnel, bool activate)
static int tb_usb3_consumed_bandwidth(struct tb_tunnel *tunnel, static int tb_usb3_consumed_bandwidth(struct tb_tunnel *tunnel,
int *consumed_up, int *consumed_down) int *consumed_up, int *consumed_down)
{ {
int pcie_enabled = tb_acpi_may_tunnel_pcie();
/* /*
* PCIe tunneling affects the USB3 bandwidth so take that it * PCIe tunneling, if enabled, affects the USB3 bandwidth so
* into account here. * take that it into account here.
*/ */
*consumed_up = tunnel->allocated_up * (3 + 1) / 3; *consumed_up = tunnel->allocated_up * (3 + pcie_enabled) / 3;
*consumed_down = tunnel->allocated_down * (3 + 1) / 3; *consumed_down = tunnel->allocated_down * (3 + pcie_enabled) / 3;
return 0; return 0;
} }
......
...@@ -331,13 +331,18 @@ int usb4_switch_setup(struct tb_switch *sw) ...@@ -331,13 +331,18 @@ int usb4_switch_setup(struct tb_switch *sw)
if (ret) if (ret)
return ret; return ret;
if (sw->link_usb4 && tb_switch_find_port(parent, TB_TYPE_USB3_DOWN)) { if (tb_acpi_may_tunnel_usb3() && sw->link_usb4 &&
tb_switch_find_port(parent, TB_TYPE_USB3_DOWN)) {
val |= ROUTER_CS_5_UTO; val |= ROUTER_CS_5_UTO;
xhci = false; xhci = false;
} }
/* Only enable PCIe tunneling if the parent router supports it */ /*
if (tb_switch_find_port(parent, TB_TYPE_PCIE_DOWN)) { * Only enable PCIe tunneling if the parent router supports it
* and it is not disabled.
*/
if (tb_acpi_may_tunnel_pcie() &&
tb_switch_find_port(parent, TB_TYPE_PCIE_DOWN)) {
val |= ROUTER_CS_5_PTO; val |= ROUTER_CS_5_PTO;
/* /*
* xHCI can be enabled if PCIe tunneling is supported * xHCI can be enabled if PCIe tunneling is supported
......
...@@ -30,6 +30,10 @@ struct xdomain_request_work { ...@@ -30,6 +30,10 @@ struct xdomain_request_work {
struct tb *tb; struct tb *tb;
}; };
static bool tb_xdomain_enabled = true;
module_param_named(xdomain, tb_xdomain_enabled, bool, 0444);
MODULE_PARM_DESC(xdomain, "allow XDomain protocol (default: true)");
/* Serializes access to the properties and protocol handlers below */ /* Serializes access to the properties and protocol handlers below */
static DEFINE_MUTEX(xdomain_lock); static DEFINE_MUTEX(xdomain_lock);
...@@ -47,6 +51,11 @@ static const uuid_t tb_xdp_uuid = ...@@ -47,6 +51,11 @@ static const uuid_t tb_xdp_uuid =
UUID_INIT(0xb638d70e, 0x42ff, 0x40bb, UUID_INIT(0xb638d70e, 0x42ff, 0x40bb,
0x97, 0xc2, 0x90, 0xe2, 0xc0, 0xb2, 0xff, 0x07); 0x97, 0xc2, 0x90, 0xe2, 0xc0, 0xb2, 0xff, 0x07);
bool tb_is_xdomain_enabled(void)
{
return tb_xdomain_enabled && tb_acpi_is_xdomain_allowed();
}
static bool tb_xdomain_match(const struct tb_cfg_request *req, static bool tb_xdomain_match(const struct tb_cfg_request *req,
const struct ctl_pkg *pkg) const struct ctl_pkg *pkg)
{ {
...@@ -670,7 +679,7 @@ EXPORT_SYMBOL_GPL(tb_register_service_driver); ...@@ -670,7 +679,7 @@ EXPORT_SYMBOL_GPL(tb_register_service_driver);
/** /**
* tb_unregister_service_driver() - Unregister XDomain service driver * tb_unregister_service_driver() - Unregister XDomain service driver
* @xdrv: Driver to unregister * @drv: Driver to unregister
* *
* Unregisters XDomain service driver from the bus. * Unregisters XDomain service driver from the bus.
*/ */
...@@ -756,7 +765,7 @@ static struct attribute *tb_service_attrs[] = { ...@@ -756,7 +765,7 @@ static struct attribute *tb_service_attrs[] = {
NULL, NULL,
}; };
static struct attribute_group tb_service_attr_group = { static const struct attribute_group tb_service_attr_group = {
.attrs = tb_service_attrs, .attrs = tb_service_attrs,
}; };
...@@ -1239,7 +1248,7 @@ static struct attribute *xdomain_attrs[] = { ...@@ -1239,7 +1248,7 @@ static struct attribute *xdomain_attrs[] = {
NULL, NULL,
}; };
static struct attribute_group xdomain_attr_group = { static const struct attribute_group xdomain_attr_group = {
.attrs = xdomain_attrs, .attrs = xdomain_attrs,
}; };
......
...@@ -13,7 +13,9 @@ obj-$(CONFIG_USB_DWC3) += dwc3/ ...@@ -13,7 +13,9 @@ obj-$(CONFIG_USB_DWC3) += dwc3/
obj-$(CONFIG_USB_DWC2) += dwc2/ obj-$(CONFIG_USB_DWC2) += dwc2/
obj-$(CONFIG_USB_ISP1760) += isp1760/ obj-$(CONFIG_USB_ISP1760) += isp1760/
obj-$(CONFIG_USB_CDNS_SUPPORT) += cdns3/
obj-$(CONFIG_USB_CDNS3) += cdns3/ obj-$(CONFIG_USB_CDNS3) += cdns3/
obj-$(CONFIG_USB_CDNSP_PCI) += cdns3/
obj-$(CONFIG_USB_MON) += mon/ obj-$(CONFIG_USB_MON) += mon/
obj-$(CONFIG_USB_MTU3) += mtu3/ obj-$(CONFIG_USB_MTU3) += mtu3/
......
...@@ -76,7 +76,7 @@ struct c67x00_hcd { ...@@ -76,7 +76,7 @@ struct c67x00_hcd {
u16 next_td_addr; u16 next_td_addr;
u16 next_buf_addr; u16 next_buf_addr;
struct tasklet_struct tasklet; struct work_struct work;
struct completion endpoint_disable; struct completion endpoint_disable;
......
...@@ -1123,24 +1123,26 @@ static void c67x00_do_work(struct c67x00_hcd *c67x00) ...@@ -1123,24 +1123,26 @@ static void c67x00_do_work(struct c67x00_hcd *c67x00)
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
static void c67x00_sched_tasklet(struct tasklet_struct *t) static void c67x00_sched_work(struct work_struct *work)
{ {
struct c67x00_hcd *c67x00 = from_tasklet(c67x00, t, tasklet); struct c67x00_hcd *c67x00;
c67x00 = container_of(work, struct c67x00_hcd, work);
c67x00_do_work(c67x00); c67x00_do_work(c67x00);
} }
void c67x00_sched_kick(struct c67x00_hcd *c67x00) void c67x00_sched_kick(struct c67x00_hcd *c67x00)
{ {
tasklet_hi_schedule(&c67x00->tasklet); queue_work(system_highpri_wq, &c67x00->work);
} }
int c67x00_sched_start_scheduler(struct c67x00_hcd *c67x00) int c67x00_sched_start_scheduler(struct c67x00_hcd *c67x00)
{ {
tasklet_setup(&c67x00->tasklet, c67x00_sched_tasklet); INIT_WORK(&c67x00->work, c67x00_sched_work);
return 0; return 0;
} }
void c67x00_sched_stop_scheduler(struct c67x00_hcd *c67x00) void c67x00_sched_stop_scheduler(struct c67x00_hcd *c67x00)
{ {
tasklet_kill(&c67x00->tasklet); cancel_work_sync(&c67x00->work);
} }
config USB_CDNS3 config USB_CDNS_SUPPORT
tristate "Cadence USB3 Dual-Role Controller" tristate "Cadence USB Support"
depends on USB_SUPPORT && (USB || USB_GADGET) && HAS_DMA depends on USB_SUPPORT && (USB || USB_GADGET) && HAS_DMA
select USB_XHCI_PLATFORM if USB_XHCI_HCD select USB_XHCI_PLATFORM if USB_XHCI_HCD
select USB_ROLE_SWITCH select USB_ROLE_SWITCH
help
Say Y here if your system has a Cadence USBSS or USBSSP
dual-role controller.
It supports: dual-role switch, Host-only, and Peripheral-only.
config USB_CDNS_HOST
bool
if USB_CDNS_SUPPORT
config USB_CDNS3
tristate "Cadence USB3 Dual-Role Controller"
depends on USB_CDNS_SUPPORT
help help
Say Y here if your system has a Cadence USB3 dual-role controller. Say Y here if your system has a Cadence USB3 dual-role controller.
It supports: dual-role switch, Host-only, and Peripheral-only. It supports: dual-role switch, Host-only, and Peripheral-only.
If you choose to build this driver is a dynamically linked If you choose to build this driver is a dynamically linked
as module, the module will be called cdns3.ko. as module, the module will be called cdns3.ko.
endif
if USB_CDNS3 if USB_CDNS3
...@@ -25,6 +39,7 @@ config USB_CDNS3_GADGET ...@@ -25,6 +39,7 @@ config USB_CDNS3_GADGET
config USB_CDNS3_HOST config USB_CDNS3_HOST
bool "Cadence USB3 host controller" bool "Cadence USB3 host controller"
depends on USB=y || USB=USB_CDNS3 depends on USB=y || USB=USB_CDNS3
select USB_CDNS_HOST
help help
Say Y here to enable host controller functionality of the Say Y here to enable host controller functionality of the
Cadence driver. Cadence driver.
...@@ -64,3 +79,44 @@ config USB_CDNS3_IMX ...@@ -64,3 +79,44 @@ config USB_CDNS3_IMX
For example, imx8qm and imx8qxp. For example, imx8qm and imx8qxp.
endif endif
if USB_CDNS_SUPPORT
config USB_CDNSP_PCI
tristate "Cadence CDNSP Dual-Role Controller"
depends on USB_CDNS_SUPPORT && USB_PCI && ACPI
help
Say Y here if your system has a Cadence CDNSP dual-role controller.
It supports: dual-role switch Host-only, and Peripheral-only.
If you choose to build this driver is a dynamically linked
module, the module will be called cdnsp.ko.
endif
if USB_CDNSP_PCI
config USB_CDNSP_GADGET
bool "Cadence CDNSP device controller"
depends on USB_GADGET=y || USB_GADGET=USB_CDNSP_PCI
help
Say Y here to enable device controller functionality of the
Cadence CDNSP-DEV driver.
Cadence CDNSP Device Controller in device mode is
very similar to XHCI controller. Therefore some algorithms
used has been taken from host driver.
This controller supports FF, HS, SS and SSP mode.
It doesn't support LS.
config USB_CDNSP_HOST
bool "Cadence CDNSP host controller"
depends on USB=y || USB=USB_CDNSP_PCI
select USB_CDNS_HOST
help
Say Y here to enable host controller functionality of the
Cadence driver.
Host controller is compliant with XHCI so it uses
standard XHCI driver.
endif
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# define_trace.h needs to know how to find our header # define_trace.h needs to know how to find our header
CFLAGS_trace.o := -I$(src) CFLAGS_cdns3-trace.o := -I$(src)
CFLAGS_cdnsp-trace.o := -I$(src)
cdns3-y := core.o drd.o cdns-usb-common-y := core.o drd.o
cdns3-y := cdns3-plat.o
obj-$(CONFIG_USB_CDNS3) += cdns3.o ifeq ($(CONFIG_USB),m)
cdns3-$(CONFIG_USB_CDNS3_GADGET) += gadget.o ep0.o obj-m += cdns-usb-common.o
obj-m += cdns3.o
else
obj-$(CONFIG_USB_CDNS_SUPPORT) += cdns-usb-common.o
obj-$(CONFIG_USB_CDNS3) += cdns3.o
endif
cdns-usb-common-$(CONFIG_USB_CDNS_HOST) += host.o
cdns3-$(CONFIG_USB_CDNS3_GADGET) += cdns3-gadget.o cdns3-ep0.o
ifneq ($(CONFIG_USB_CDNS3_GADGET),) ifneq ($(CONFIG_USB_CDNS3_GADGET),)
cdns3-$(CONFIG_TRACING) += trace.o cdns3-$(CONFIG_TRACING) += cdns3-trace.o
endif
obj-$(CONFIG_USB_CDNS3_PCI_WRAP) += cdns3-pci-wrap.o
obj-$(CONFIG_USB_CDNS3_TI) += cdns3-ti.o
obj-$(CONFIG_USB_CDNS3_IMX) += cdns3-imx.o
cdnsp-udc-pci-y := cdnsp-pci.o
ifdef CONFIG_USB_CDNSP_PCI
ifeq ($(CONFIG_USB),m)
obj-m += cdnsp-udc-pci.o
else
obj-$(CONFIG_USB_CDNSP_PCI) += cdnsp-udc-pci.o
endif
endif endif
cdns3-$(CONFIG_USB_CDNS3_HOST) += host.o cdnsp-udc-pci-$(CONFIG_USB_CDNSP_GADGET) += cdnsp-ring.o cdnsp-gadget.o \
cdnsp-mem.o cdnsp-ep0.o
obj-$(CONFIG_USB_CDNS3_PCI_WRAP) += cdns3-pci-wrap.o ifneq ($(CONFIG_USB_CDNSP_GADGET),)
obj-$(CONFIG_USB_CDNS3_TI) += cdns3-ti.o cdnsp-udc-pci-$(CONFIG_TRACING) += cdnsp-trace.o
obj-$(CONFIG_USB_CDNS3_IMX) += cdns3-imx.o endif
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
#include <linux/usb/composite.h> #include <linux/usb/composite.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include "gadget.h" #include "cdns3-gadget.h"
#include "trace.h" #include "cdns3-trace.h"
static struct usb_endpoint_descriptor cdns3_gadget_ep0_desc = { static struct usb_endpoint_descriptor cdns3_gadget_ep0_desc = {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
...@@ -364,7 +364,7 @@ static int cdns3_ep0_feature_handle_endpoint(struct cdns3_device *priv_dev, ...@@ -364,7 +364,7 @@ static int cdns3_ep0_feature_handle_endpoint(struct cdns3_device *priv_dev,
if (le16_to_cpu(ctrl->wValue) != USB_ENDPOINT_HALT) if (le16_to_cpu(ctrl->wValue) != USB_ENDPOINT_HALT)
return -EINVAL; return -EINVAL;
if (!(ctrl->wIndex & ~USB_DIR_IN)) if (!(le16_to_cpu(ctrl->wIndex) & ~USB_DIR_IN))
return 0; return 0;
index = cdns3_ep_addr_to_index(le16_to_cpu(ctrl->wIndex)); index = cdns3_ep_addr_to_index(le16_to_cpu(ctrl->wIndex));
...@@ -789,7 +789,7 @@ int cdns3_gadget_ep_set_wedge(struct usb_ep *ep) ...@@ -789,7 +789,7 @@ int cdns3_gadget_ep_set_wedge(struct usb_ep *ep)
return 0; return 0;
} }
const struct usb_ep_ops cdns3_gadget_ep0_ops = { static const struct usb_ep_ops cdns3_gadget_ep0_ops = {
.enable = cdns3_gadget_ep0_enable, .enable = cdns3_gadget_ep0_enable,
.disable = cdns3_gadget_ep0_disable, .disable = cdns3_gadget_ep0_disable,
.alloc_request = cdns3_gadget_ep_alloc_request, .alloc_request = cdns3_gadget_ep_alloc_request,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment