Merge 54c2cc7919 ("Merge tag 'usb-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb") into android-mainline
Steps on the way to 5.19-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I276fa015c31114e7fdd76ce8bec6e66c25b9fc0d
This commit is contained in:
commit
2825770ce3
192 changed files with 3681 additions and 1487 deletions
|
|
@ -7,6 +7,7 @@ Description: UVC function directory
|
|||
streaming_maxburst 0..15 (ss only)
|
||||
streaming_maxpacket 1..1023 (fs), 1..3072 (hs/ss)
|
||||
streaming_interval 1..16
|
||||
function_name string [32]
|
||||
=================== =============================
|
||||
|
||||
What: /config/usb-gadget/gadget/functions/uvc.name/control
|
||||
|
|
|
|||
|
|
@ -293,6 +293,16 @@ Contact: thunderbolt-software@lists.01.org
|
|||
Description: This contains XDomain service specific settings as
|
||||
bitmask. Format: %x
|
||||
|
||||
What: /sys/bus/thunderbolt/devices/usb4_portX/connector
|
||||
Date: April 2022
|
||||
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
|
||||
Description:
|
||||
Symlink to the USB Type-C connector. This link is only
|
||||
created when USB Type-C Connector Class is enabled,
|
||||
and only if the system firmware is capable of
|
||||
describing the connection between a port and its
|
||||
connector.
|
||||
|
||||
What: /sys/bus/thunderbolt/devices/usb4_portX/link
|
||||
Date: Sep 2021
|
||||
KernelVersion: v5.14
|
||||
|
|
|
|||
|
|
@ -61,8 +61,9 @@ DMA
|
|||
endpoint number (0 … 14 for endpoints 1 … 15 on instance 0 and 15 … 29
|
||||
for endpoints 1 … 15 on instance 1). The second number is 0 for RX and
|
||||
1 for TX transfers.
|
||||
- #dma-channels: should be set to 30 representing the 15 endpoints for
|
||||
- dma-channels: should be set to 30 representing the 15 endpoints for
|
||||
each USB instance.
|
||||
- #dma-channels: deprecated
|
||||
|
||||
Example:
|
||||
~~~~~~~~
|
||||
|
|
@ -193,7 +194,7 @@ usb: usb@47400000 {
|
|||
interrupts = <17>;
|
||||
interrupt-names = "glue";
|
||||
#dma-cells = <2>;
|
||||
#dma-channels = <30>;
|
||||
#dma-requests = <256>;
|
||||
dma-channels = <30>;
|
||||
dma-requests = <256>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ DMA
|
|||
- #dma-cells: should be set to 2. The first number represents the
|
||||
channel number (0 … 3 for endpoints 1 … 4).
|
||||
The second number is 0 for RX and 1 for TX transfers.
|
||||
- #dma-channels: should be set to 4 representing the 4 endpoints.
|
||||
- dma-channels: should be set to 4 representing the 4 endpoints.
|
||||
- #dma-channels: deprecated
|
||||
|
||||
Example:
|
||||
usb_phy: usb-phy {
|
||||
|
|
@ -74,7 +75,7 @@ Example:
|
|||
reg-names = "controller", "scheduler", "queuemgr";
|
||||
interrupts = <58>;
|
||||
#dma-cells = <2>;
|
||||
#dma-channels = <4>;
|
||||
dma-channels = <4>;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,6 +17,13 @@ properties:
|
|||
oneOf:
|
||||
- const: brcm,bcm2835-usb
|
||||
- const: hisilicon,hi6220-usb
|
||||
- const: ingenic,jz4775-otg
|
||||
- const: ingenic,jz4780-otg
|
||||
- const: ingenic,x1000-otg
|
||||
- const: ingenic,x1600-otg
|
||||
- const: ingenic,x1700-otg
|
||||
- const: ingenic,x1830-otg
|
||||
- const: ingenic,x2000-otg
|
||||
- items:
|
||||
- const: rockchip,rk3066-usb
|
||||
- const: snps,dwc2
|
||||
|
|
|
|||
|
|
@ -71,6 +71,10 @@ properties:
|
|||
- usb2-phy
|
||||
- usb3-phy
|
||||
|
||||
reset-gpios:
|
||||
description: GPIO used for the reset ulpi-phy
|
||||
maxItems: 1
|
||||
|
||||
# Required child node:
|
||||
|
||||
patternProperties:
|
||||
|
|
|
|||
72
Documentation/devicetree/bindings/usb/fcs,fsa4480.yaml
Normal file
72
Documentation/devicetree/bindings/usb/fcs,fsa4480.yaml
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/usb/fcs,fsa4480.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: ON Semiconductor Analog Audio Switch
|
||||
|
||||
maintainers:
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fcs,fsa4480
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vcc-supply:
|
||||
description: power supply (2.7V-5.5V)
|
||||
|
||||
mode-switch:
|
||||
description: Flag the port as possible handle of altmode switching
|
||||
type: boolean
|
||||
|
||||
orientation-switch:
|
||||
description: Flag the port as possible handler of orientation switching
|
||||
type: boolean
|
||||
|
||||
port:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
A port node to link the FSA4480 to a TypeC controller for the purpose of
|
||||
handling altmode muxing and orientation switching.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c13 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
fsa4480@42 {
|
||||
compatible = "fcs,fsa4480";
|
||||
reg = <0x42>;
|
||||
|
||||
interrupts-extended = <&tlmm 2 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
vcc-supply = <&vreg_bob>;
|
||||
|
||||
mode-switch;
|
||||
orientation-switch;
|
||||
|
||||
port {
|
||||
fsa4480_ept: endpoint {
|
||||
remote-endpoint = <&typec_controller>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -55,6 +55,7 @@ properties:
|
|||
- brcm,bcm7420-ehci
|
||||
- brcm,bcm7425-ehci
|
||||
- brcm,bcm7435-ehci
|
||||
- hpe,gxp-ehci
|
||||
- ibm,476gtr-ehci
|
||||
- nxp,lpc1850-ehci
|
||||
- qca,ar7100-ehci
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ properties:
|
|||
- brcm,bcm7420-ohci
|
||||
- brcm,bcm7425-ohci
|
||||
- brcm,bcm7435-ohci
|
||||
- hpe,gxp-ohci
|
||||
- ibm,476gtr-ohci
|
||||
- ingenic,jz4740-ohci
|
||||
- snps,hsdk-v1.0-ohci
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ properties:
|
|||
- mediatek,mt8173-mtu3
|
||||
- mediatek,mt8183-mtu3
|
||||
- mediatek,mt8192-mtu3
|
||||
- mediatek,mt8195-mtu3
|
||||
- const: mediatek,mtu3
|
||||
|
||||
reg:
|
||||
|
|
|
|||
|
|
@ -16,16 +16,21 @@ properties:
|
|||
- qcom,ipq4019-dwc3
|
||||
- qcom,ipq6018-dwc3
|
||||
- qcom,ipq8064-dwc3
|
||||
- qcom,ipq8074-dwc3
|
||||
- qcom,msm8953-dwc3
|
||||
- qcom,msm8994-dwc3
|
||||
- qcom,msm8996-dwc3
|
||||
- qcom,msm8998-dwc3
|
||||
- qcom,qcs404-dwc3
|
||||
- qcom,sc7180-dwc3
|
||||
- qcom,sc7280-dwc3
|
||||
- qcom,sdm660-dwc3
|
||||
- qcom,sdm845-dwc3
|
||||
- qcom,sdx55-dwc3
|
||||
- qcom,sdx65-dwc3
|
||||
- qcom,sm4250-dwc3
|
||||
- qcom,sm6115-dwc3
|
||||
- qcom,sm6125-dwc3
|
||||
- qcom,sm6350-dwc3
|
||||
- qcom,sm8150-dwc3
|
||||
- qcom,sm8250-dwc3
|
||||
|
|
@ -50,26 +55,22 @@ properties:
|
|||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
description:
|
||||
A list of phandle and clock-specifier pairs for the clocks
|
||||
listed in clock-names.
|
||||
items:
|
||||
- description: System Config NOC clock.
|
||||
- description: Master/Core clock, has to be >= 125 MHz
|
||||
for SS operation and >= 60MHz for HS operation.
|
||||
- description: System bus AXI clock.
|
||||
- description: Mock utmi clock needed for ITP/SOF generation
|
||||
in host mode. Its frequency should be 19.2MHz.
|
||||
- description: Sleep clock, used for wakeup when
|
||||
USB3 core goes into low power mode (U3).
|
||||
description: |
|
||||
Several clocks are used, depending on the variant. Typical ones are::
|
||||
- cfg_noc:: System Config NOC clock.
|
||||
- core:: Master/Core clock, has to be >= 125 MHz for SS operation and >=
|
||||
60MHz for HS operation.
|
||||
- iface:: System bus AXI clock.
|
||||
- sleep:: Sleep clock, used for wakeup when USB3 core goes into low
|
||||
power mode (U3).
|
||||
- mock_utmi:: Mock utmi clock needed for ITP/SOF generation in host
|
||||
mode. Its frequency should be 19.2MHz.
|
||||
minItems: 1
|
||||
maxItems: 6
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: cfg_noc
|
||||
- const: core
|
||||
- const: iface
|
||||
- const: mock_utmi
|
||||
- const: sleep
|
||||
minItems: 1
|
||||
maxItems: 6
|
||||
|
||||
assigned-clocks:
|
||||
items:
|
||||
|
|
@ -132,6 +133,185 @@ required:
|
|||
- interrupts
|
||||
- interrupt-names
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq4019-dwc3
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: sleep
|
||||
- const: mock_utmi
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq8064-dwc3
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Master/Core clock, has to be >= 125 MHz
|
||||
for SS operation and >= 60MHz for HS operation.
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8953-dwc3
|
||||
- qcom,msm8996-dwc3
|
||||
- qcom,msm8998-dwc3
|
||||
- qcom,sc7180-dwc3
|
||||
- qcom,sc7280-dwc3
|
||||
- qcom,sdm845-dwc3
|
||||
- qcom,sdx55-dwc3
|
||||
- qcom,sm6350-dwc3
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 5
|
||||
clock-names:
|
||||
items:
|
||||
- const: cfg_noc
|
||||
- const: core
|
||||
- const: iface
|
||||
- const: sleep
|
||||
- const: mock_utmi
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq6018-dwc3
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 3
|
||||
maxItems: 4
|
||||
clock-names:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: core
|
||||
- const: sleep
|
||||
- const: mock_utmi
|
||||
- items:
|
||||
- const: cfg_noc
|
||||
- const: core
|
||||
- const: sleep
|
||||
- const: mock_utmi
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq8074-dwc3
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 4
|
||||
clock-names:
|
||||
items:
|
||||
- const: cfg_noc
|
||||
- const: core
|
||||
- const: sleep
|
||||
- const: mock_utmi
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8994-dwc3
|
||||
- qcom,qcs404-dwc3
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 4
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: iface
|
||||
- const: sleep
|
||||
- const: mock_utmi
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sdm660-dwc3
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 6
|
||||
clock-names:
|
||||
items:
|
||||
- const: cfg_noc
|
||||
- const: core
|
||||
- const: iface
|
||||
- const: sleep
|
||||
- const: mock_utmi
|
||||
- const: bus
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sm6125-dwc3
|
||||
- qcom,sm8150-dwc3
|
||||
- qcom,sm8250-dwc3
|
||||
- qcom,sm8450-dwc3
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 6
|
||||
clock-names:
|
||||
items:
|
||||
- const: cfg_noc
|
||||
- const: core
|
||||
- const: iface
|
||||
- const: sleep
|
||||
- const: mock_utmi
|
||||
- const: xo
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sm8350-dwc3
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 5
|
||||
maxItems: 6
|
||||
clock-names:
|
||||
minItems: 5
|
||||
items:
|
||||
- const: cfg_noc
|
||||
- const: core
|
||||
- const: iface
|
||||
- const: sleep
|
||||
- const: mock_utmi
|
||||
- const: xo
|
||||
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
|
@ -153,10 +333,13 @@ examples:
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep";
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ properties:
|
|||
- items:
|
||||
- enum:
|
||||
- renesas,usbhs-r7s9210 # RZ/A2
|
||||
- renesas,usbhs-r9a07g043 # RZ/G2UL
|
||||
- renesas,usbhs-r9a07g044 # RZ/G2{L,LC}
|
||||
- renesas,usbhs-r9a07g054 # RZ/V2L
|
||||
- const: renesas,rza2-usbhs
|
||||
|
|
@ -118,6 +119,7 @@ allOf:
|
|||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,usbhs-r9a07g043
|
||||
- renesas,usbhs-r9a07g044
|
||||
- renesas,usbhs-r9a07g054
|
||||
then:
|
||||
|
|
@ -128,6 +130,8 @@ allOf:
|
|||
- description: U2P_INT_DMA[0]
|
||||
- description: U2P_INT_DMA[1]
|
||||
- description: U2P_INT_DMAERR
|
||||
required:
|
||||
- resets
|
||||
else:
|
||||
properties:
|
||||
interrupts:
|
||||
|
|
|
|||
|
|
@ -15,9 +15,6 @@ properties:
|
|||
- samsung,exynos4210-ehci
|
||||
- samsung,exynos4210-ohci
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
|
|
@ -46,15 +43,6 @@ properties:
|
|||
Only for controller in EHCI mode, if present, specifies the GPIO that
|
||||
needs to be pulled up for the bus to be powered.
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]{1,2}$":
|
||||
description: The hard wired USB devices
|
||||
type: object
|
||||
$ref: /usb/usb-device.yaml
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- clocks
|
||||
|
|
@ -65,6 +53,7 @@ required:
|
|||
- reg
|
||||
|
||||
allOf:
|
||||
- $ref: usb-hcd.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -74,7 +63,7 @@ allOf:
|
|||
properties:
|
||||
samsung,vbus-gpio: false
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
|||
103
Documentation/devicetree/bindings/usb/ti,am62-usb.yaml
Normal file
103
Documentation/devicetree/bindings/usb/ti,am62-usb.yaml
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/usb/ti,am62-usb.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: TI's AM62 wrapper module for the Synopsys USBSS-DRD controller
|
||||
|
||||
maintainers:
|
||||
- Aswath Govindraju <a-govindraju@ti.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ti,am62-usb
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
ranges: true
|
||||
|
||||
power-domains:
|
||||
description:
|
||||
PM domain provider node and an args specifier containing
|
||||
the USB ISO device id value. See,
|
||||
Documentation/devicetree/bindings/soc/ti/sci-pm-domain.yaml
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
description: Clock phandle to usb2_refclk
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref
|
||||
|
||||
ti,vbus-divider:
|
||||
description:
|
||||
Should be present if USB VBUS line is connected to the
|
||||
VBUS pin of the SoC via a 1/3 voltage divider.
|
||||
type: boolean
|
||||
|
||||
ti,syscon-phy-pll-refclk:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
items:
|
||||
- items:
|
||||
- description: Phandle to the SYSCON entry
|
||||
- description: USB phy control register offset within SYSCON
|
||||
description:
|
||||
Specifier for conveying frequency of ref clock input, for the
|
||||
operation of USB2PHY.
|
||||
|
||||
'#address-cells':
|
||||
const: 2
|
||||
|
||||
'#size-cells':
|
||||
const: 2
|
||||
|
||||
patternProperties:
|
||||
"^usb@[0-9a-f]+$":
|
||||
$ref: snps,dwc3.yaml#
|
||||
description: Required child node
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- power-domains
|
||||
- clocks
|
||||
- clock-names
|
||||
- ti,syscon-phy-pll-refclk
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/soc/ti,sci_pm_domain.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
bus {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
usbss1: usb@f910000 {
|
||||
compatible = "ti,am62-usb";
|
||||
reg = <0x00 0x0f910000 0x00 0x800>;
|
||||
clocks = <&k3_clks 162 3>;
|
||||
clock-names = "ref";
|
||||
ti,syscon-phy-pll-refclk = <&wkup_conf 0x4018>;
|
||||
power-domains = <&k3_pds 179 TI_SCI_PD_EXCLUSIVE>;
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
usb@31100000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg =<0x00 0x31100000 0x00 0x50000>;
|
||||
interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>, /* irq.0 */
|
||||
<GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>; /* irq.0 */
|
||||
interrupt-names = "host", "peripheral";
|
||||
maximum-speed = "high-speed";
|
||||
dr_mode = "otg";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -787,6 +787,7 @@ The uvc function provides these attributes in its function directory:
|
|||
streaming_maxpacket maximum packet size this endpoint is capable of
|
||||
sending or receiving when this configuration is
|
||||
selected
|
||||
function_name name of the interface
|
||||
=================== ================================================
|
||||
|
||||
There are also "control" and "streaming" subdirectories, each of which contain
|
||||
|
|
|
|||
|
|
@ -646,7 +646,7 @@
|
|||
clocks = <&gcc GCC_USB3_MASTER_CLK>,
|
||||
<&gcc GCC_USB3_SLEEP_CLK>,
|
||||
<&gcc GCC_USB3_MOCK_UTMI_CLK>;
|
||||
clock-names = "master", "sleep", "mock_utmi";
|
||||
clock-names = "core", "sleep", "mock_utmi";
|
||||
ranges;
|
||||
status = "disabled";
|
||||
|
||||
|
|
|
|||
|
|
@ -483,10 +483,13 @@
|
|||
clocks = <&gcc GCC_USB30_SLV_AHB_CLK>,
|
||||
<&gcc GCC_USB30_MASTER_CLK>,
|
||||
<&gcc GCC_USB30_MSTR_AXI_CLK>,
|
||||
<&gcc GCC_USB30_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SLEEP_CLK>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep";
|
||||
<&gcc GCC_USB30_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_MOCK_UTMI_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_MASTER_CLK>;
|
||||
|
|
|
|||
|
|
@ -1052,22 +1052,22 @@
|
|||
&usb2 {
|
||||
status = "okay";
|
||||
extcon = <&usb2_id>;
|
||||
};
|
||||
|
||||
dwc3@7600000 {
|
||||
extcon = <&usb2_id>;
|
||||
dr_mode = "otg";
|
||||
maximum-speed = "high-speed";
|
||||
};
|
||||
&usb2_dwc3 {
|
||||
extcon = <&usb2_id>;
|
||||
dr_mode = "otg";
|
||||
maximum-speed = "high-speed";
|
||||
};
|
||||
|
||||
&usb3 {
|
||||
status = "okay";
|
||||
extcon = <&usb3_id>;
|
||||
};
|
||||
|
||||
dwc3@6a00000 {
|
||||
extcon = <&usb3_id>;
|
||||
dr_mode = "otg";
|
||||
};
|
||||
&usb3_dwc3 {
|
||||
extcon = <&usb3_id>;
|
||||
dr_mode = "otg";
|
||||
};
|
||||
|
||||
&usb3phy {
|
||||
|
|
|
|||
|
|
@ -653,7 +653,7 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
usb2: usb2@7000000 {
|
||||
usb2: usb@70f8800 {
|
||||
compatible = "qcom,ipq6018-dwc3", "qcom,dwc3";
|
||||
reg = <0x0 0x070F8800 0x0 0x400>;
|
||||
#address-cells = <2>;
|
||||
|
|
@ -662,7 +662,7 @@
|
|||
clocks = <&gcc GCC_USB1_MASTER_CLK>,
|
||||
<&gcc GCC_USB1_SLEEP_CLK>,
|
||||
<&gcc GCC_USB1_MOCK_UTMI_CLK>;
|
||||
clock-names = "master",
|
||||
clock-names = "core",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
|
|
@ -730,7 +730,7 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
usb3: usb3@8A00000 {
|
||||
usb3: usb@8af8800 {
|
||||
compatible = "qcom,ipq6018-dwc3", "qcom,dwc3";
|
||||
reg = <0x0 0x8AF8800 0x0 0x400>;
|
||||
#address-cells = <2>;
|
||||
|
|
@ -741,8 +741,8 @@
|
|||
<&gcc GCC_USB0_MASTER_CLK>,
|
||||
<&gcc GCC_USB0_SLEEP_CLK>,
|
||||
<&gcc GCC_USB0_MOCK_UTMI_CLK>;
|
||||
clock-names = "sys_noc_axi",
|
||||
"master",
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
|
|
@ -756,7 +756,7 @@
|
|||
resets = <&gcc GCC_USB0_BCR>;
|
||||
status = "disabled";
|
||||
|
||||
dwc_0: usb@8A00000 {
|
||||
dwc_0: usb@8a00000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x0 0x8A00000 0x0 0xcd00>;
|
||||
interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
|
|
|||
|
|
@ -553,7 +553,7 @@
|
|||
};
|
||||
|
||||
usb_0: usb@8af8800 {
|
||||
compatible = "qcom,dwc3";
|
||||
compatible = "qcom,ipq8074-dwc3", "qcom,dwc3";
|
||||
reg = <0x08af8800 0x400>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
|
@ -563,8 +563,8 @@
|
|||
<&gcc GCC_USB0_MASTER_CLK>,
|
||||
<&gcc GCC_USB0_SLEEP_CLK>,
|
||||
<&gcc GCC_USB0_MOCK_UTMI_CLK>;
|
||||
clock-names = "sys_noc_axi",
|
||||
"master",
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
|
|
@ -578,7 +578,7 @@
|
|||
resets = <&gcc GCC_USB0_BCR>;
|
||||
status = "disabled";
|
||||
|
||||
dwc_0: dwc3@8a00000 {
|
||||
dwc_0: usb@8a00000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x8a00000 0xcd00>;
|
||||
interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
|
@ -593,7 +593,7 @@
|
|||
};
|
||||
|
||||
usb_1: usb@8cf8800 {
|
||||
compatible = "qcom,dwc3";
|
||||
compatible = "qcom,ipq8074-dwc3", "qcom,dwc3";
|
||||
reg = <0x08cf8800 0x400>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
|
@ -603,8 +603,8 @@
|
|||
<&gcc GCC_USB1_MASTER_CLK>,
|
||||
<&gcc GCC_USB1_SLEEP_CLK>,
|
||||
<&gcc GCC_USB1_MOCK_UTMI_CLK>;
|
||||
clock-names = "sys_noc_axi",
|
||||
"master",
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
|
|
@ -618,7 +618,7 @@
|
|||
resets = <&gcc GCC_USB1_BCR>;
|
||||
status = "disabled";
|
||||
|
||||
dwc_1: dwc3@8c00000 {
|
||||
dwc_1: usb@8c00000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x8c00000 0xcd00>;
|
||||
interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
|
|
|||
|
|
@ -759,10 +759,13 @@
|
|||
clocks = <&gcc GCC_USB_PHY_CFG_AHB_CLK>,
|
||||
<&gcc GCC_USB30_MASTER_CLK>,
|
||||
<&gcc GCC_PCNOC_USB3_AXI_CLK>,
|
||||
<&gcc GCC_USB30_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SLEEP_CLK>;
|
||||
clock-names = "cfg_noc", "core", "iface",
|
||||
"mock_utmi", "sleep";
|
||||
<&gcc GCC_USB30_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_MOCK_UTMI_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_MASTER_CLK>;
|
||||
|
|
|
|||
|
|
@ -428,7 +428,7 @@
|
|||
};
|
||||
|
||||
usb3: usb@f92f8800 {
|
||||
compatible = "qcom,msm8996-dwc3", "qcom,dwc3";
|
||||
compatible = "qcom,msm8994-dwc3", "qcom,dwc3";
|
||||
reg = <0xf92f8800 0x400>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
|
@ -438,7 +438,10 @@
|
|||
<&gcc GCC_SYS_NOC_USB3_AXI_CLK>,
|
||||
<&gcc GCC_USB30_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_MOCK_UTMI_CLK>;
|
||||
clock-names = "core", "iface", "sleep", "mock_utmi", "ref", "xo";
|
||||
clock-names = "core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_MASTER_CLK>;
|
||||
|
|
|
|||
|
|
@ -308,19 +308,19 @@
|
|||
extcon = <&typec>;
|
||||
|
||||
qcom,select-utmi-as-pipe-clk;
|
||||
};
|
||||
|
||||
dwc3@6a00000 {
|
||||
extcon = <&typec>;
|
||||
&usb3_dwc3 {
|
||||
extcon = <&typec>;
|
||||
|
||||
/* usb3-phy is not used on this device */
|
||||
phys = <&hsusb_phy1>;
|
||||
phy-names = "usb2-phy";
|
||||
/* usb3-phy is not used on this device */
|
||||
phys = <&hsusb_phy1>;
|
||||
phy-names = "usb2-phy";
|
||||
|
||||
maximum-speed = "high-speed";
|
||||
snps,is-utmi-l1-suspend;
|
||||
snps,usb2-gadget-lpm-disable;
|
||||
snps,hird-threshold = /bits/ 8 <0>;
|
||||
};
|
||||
maximum-speed = "high-speed";
|
||||
snps,is-utmi-l1-suspend;
|
||||
snps,usb2-gadget-lpm-disable;
|
||||
snps,hird-threshold = /bits/ 8 <0>;
|
||||
};
|
||||
|
||||
&hsusb_phy1 {
|
||||
|
|
|
|||
|
|
@ -2718,11 +2718,15 @@
|
|||
interrupt-names = "hs_phy_irq", "ss_phy_irq";
|
||||
|
||||
clocks = <&gcc GCC_SYS_NOC_USB3_AXI_CLK>,
|
||||
<&gcc GCC_USB30_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE2_USB3_AXI_CLK>,
|
||||
<&gcc GCC_USB30_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SLEEP_CLK>,
|
||||
<&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>;
|
||||
<&gcc GCC_USB30_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE2_USB3_AXI_CLK>,
|
||||
<&gcc GCC_USB30_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_MOCK_UTMI_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_MASTER_CLK>;
|
||||
|
|
@ -2731,7 +2735,7 @@
|
|||
power-domains = <&gcc USB30_GDSC>;
|
||||
status = "disabled";
|
||||
|
||||
usb3_dwc3: dwc3@6a00000 {
|
||||
usb3_dwc3: usb@6a00000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x06a00000 0xcc00>;
|
||||
interrupts = <0 131 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
|
@ -3050,6 +3054,11 @@
|
|||
<&gcc GCC_USB20_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB20_SLEEP_CLK>,
|
||||
<&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB20_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB20_MASTER_CLK>;
|
||||
|
|
@ -3059,7 +3068,7 @@
|
|||
qcom,select-utmi-as-pipe-clk;
|
||||
status = "disabled";
|
||||
|
||||
dwc3@7600000 {
|
||||
usb2_dwc3: usb@7600000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x07600000 0xcc00>;
|
||||
interrupts = <0 138 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
|
|
|||
|
|
@ -2023,10 +2023,13 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_AXI_CLK>,
|
||||
<&gcc GCC_USB30_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE1_USB3_AXI_CLK>,
|
||||
<&gcc GCC_USB30_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SLEEP_CLK>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep";
|
||||
<&gcc GCC_USB30_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_MOCK_UTMI_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_MASTER_CLK>;
|
||||
|
|
@ -2040,7 +2043,7 @@
|
|||
|
||||
resets = <&gcc GCC_USB_30_BCR>;
|
||||
|
||||
usb3_dwc3: dwc3@a800000 {
|
||||
usb3_dwc3: usb@a800000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x0a800000 0xcd00>;
|
||||
interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
|
|
|||
|
|
@ -337,9 +337,10 @@
|
|||
&usb3 {
|
||||
status = "okay";
|
||||
|
||||
dwc3@7580000 {
|
||||
dr_mode = "host";
|
||||
};
|
||||
};
|
||||
|
||||
&usb3_dwc3 {
|
||||
dr_mode = "host";
|
||||
};
|
||||
|
||||
&usb2_phy_prim {
|
||||
|
|
|
|||
|
|
@ -529,7 +529,7 @@
|
|||
};
|
||||
|
||||
usb3: usb@7678800 {
|
||||
compatible = "qcom,dwc3";
|
||||
compatible = "qcom,qcs404-dwc3", "qcom,dwc3";
|
||||
reg = <0x07678800 0x400>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
|
@ -544,7 +544,7 @@
|
|||
assigned-clock-rates = <19200000>, <200000000>;
|
||||
status = "disabled";
|
||||
|
||||
dwc3@7580000 {
|
||||
usb3_dwc3: usb@7580000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x07580000 0xcd00>;
|
||||
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
|
@ -558,7 +558,7 @@
|
|||
};
|
||||
|
||||
usb2: usb@79b8800 {
|
||||
compatible = "qcom,dwc3";
|
||||
compatible = "qcom,qcs404-dwc3", "qcom,dwc3";
|
||||
reg = <0x079b8800 0x400>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
|
@ -573,7 +573,7 @@
|
|||
assigned-clock-rates = <19200000>, <133333333>;
|
||||
status = "disabled";
|
||||
|
||||
dwc3@78c0000 {
|
||||
usb@78c0000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x078c0000 0xcc00>;
|
||||
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
|
|
|||
|
|
@ -2755,10 +2755,13 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep";
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>;
|
||||
|
|
@ -2779,7 +2782,7 @@
|
|||
<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3 0>;
|
||||
interconnect-names = "usb-ddr", "apps-usb";
|
||||
|
||||
usb_1_dwc3: dwc3@a600000 {
|
||||
usb_1_dwc3: usb@a600000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0 0x0a600000 0 0xe000>;
|
||||
interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
|
|
|||
|
|
@ -3069,10 +3069,13 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_SEC_AXI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_SEC_AXI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_SLEEP_CLK>;
|
||||
clock-names = "cfg_noc", "core", "iface","mock_utmi",
|
||||
"sleep";
|
||||
<&gcc GCC_USB30_SEC_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MASTER_CLK>;
|
||||
|
|
@ -3102,6 +3105,12 @@
|
|||
phys = <&usb_2_hsphy>;
|
||||
phy-names = "usb2-phy";
|
||||
maximum-speed = "high-speed";
|
||||
usb-role-switch;
|
||||
port {
|
||||
usb2_role_switch: endpoint {
|
||||
remote-endpoint = <&eud_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -3194,6 +3203,36 @@
|
|||
interrupts = <GIC_SPI 582 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
eud: eud@88e0000 {
|
||||
compatible = "qcom,sc7280-eud","qcom,eud";
|
||||
reg = <0 0x88e0000 0 0x2000>,
|
||||
<0 0x88e2000 0 0x1000>;
|
||||
interrupts-extended = <&pdc 11 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ports {
|
||||
port@0 {
|
||||
eud_ep: endpoint {
|
||||
remote-endpoint = <&usb2_role_switch>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
eud_con: endpoint {
|
||||
remote-endpoint = <&con_eud>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
eud_typec: connector {
|
||||
compatible = "usb-c-connector";
|
||||
ports {
|
||||
port@0 {
|
||||
con_eud: endpoint {
|
||||
remote-endpoint = <&eud_con>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nsp_noc: interconnect@a0c0000 {
|
||||
reg = <0 0x0a0c0000 0 0x10000>;
|
||||
compatible = "qcom,sc7280-nsp-noc";
|
||||
|
|
@ -3213,21 +3252,26 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep";
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>;
|
||||
assigned-clock-rates = <19200000>, <200000000>;
|
||||
|
||||
interrupts-extended = <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<&pdc 14 IRQ_TYPE_EDGE_BOTH>,
|
||||
<&pdc 17 IRQ_TYPE_EDGE_BOTH>,
|
||||
<&pdc 15 IRQ_TYPE_EDGE_BOTH>,
|
||||
<&pdc 17 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "hs_phy_irq", "dp_hs_phy_irq",
|
||||
"dm_hs_phy_irq", "ss_phy_irq";
|
||||
<&pdc 14 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "hs_phy_irq",
|
||||
"ss_phy_irq",
|
||||
"dm_hs_phy_irq",
|
||||
"dp_hs_phy_irq";
|
||||
|
||||
power-domains = <&gcc GCC_USB30_PRIM_GDSC>;
|
||||
|
||||
|
|
|
|||
|
|
@ -1215,11 +1215,15 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_AXI_CLK>,
|
||||
<&gcc GCC_USB30_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE2_USB3_AXI_CLK>,
|
||||
<&rpmcc RPM_SMD_AGGR2_NOC_CLK>,
|
||||
<&gcc GCC_USB30_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SLEEP_CLK>;
|
||||
clock-names = "cfg_noc", "core", "iface", "bus",
|
||||
"mock_utmi", "sleep";
|
||||
<&rpmcc RPM_SMD_AGGR2_NOC_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi",
|
||||
"bus";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_MASTER_CLK>,
|
||||
|
|
|
|||
|
|
@ -3844,10 +3844,13 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep";
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>;
|
||||
|
|
@ -3868,7 +3871,7 @@
|
|||
<&gladiator_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3_0 0>;
|
||||
interconnect-names = "usb-ddr", "apps-usb";
|
||||
|
||||
usb_1_dwc3: dwc3@a600000 {
|
||||
usb_1_dwc3: usb@a600000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0 0x0a600000 0 0xcd00>;
|
||||
interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
|
@ -3892,10 +3895,13 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_SEC_AXI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_SEC_AXI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_SLEEP_CLK>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep";
|
||||
<&gcc GCC_USB30_SEC_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MASTER_CLK>;
|
||||
|
|
@ -3916,7 +3922,7 @@
|
|||
<&gladiator_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3_1 0>;
|
||||
interconnect-names = "usb-ddr", "apps-usb";
|
||||
|
||||
usb_2_dwc3: dwc3@a800000 {
|
||||
usb_2_dwc3: usb@a800000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0 0x0a800000 0 0xcd00>;
|
||||
interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
|
|
|||
|
|
@ -481,18 +481,24 @@
|
|||
};
|
||||
|
||||
usb3: usb@4ef8800 {
|
||||
compatible = "qcom,msm8996-dwc3", "qcom,dwc3";
|
||||
compatible = "qcom,sm6125-dwc3", "qcom,dwc3";
|
||||
reg = <0x04ef8800 0x400>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
clocks = <&gcc GCC_USB30_PRIM_MASTER_CLK>,
|
||||
clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>,
|
||||
<&gcc GCC_SYS_NOC_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB3_PRIM_CLKREF_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>;
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB3_PRIM_CLKREF_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi",
|
||||
"xo";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>;
|
||||
|
|
|
|||
|
|
@ -1034,10 +1034,13 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep";
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
interrupts-extended = <&intc GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<&pdc 17 IRQ_TYPE_LEVEL_HIGH>,
|
||||
|
|
|
|||
|
|
@ -3614,11 +3614,15 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB3_SEC_CLKREF_CLK>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep", "xo";
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi",
|
||||
"xo";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>;
|
||||
|
|
@ -3635,7 +3639,7 @@
|
|||
|
||||
resets = <&gcc GCC_USB30_PRIM_BCR>;
|
||||
|
||||
usb_1_dwc3: dwc3@a600000 {
|
||||
usb_1_dwc3: usb@a600000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0 0x0a600000 0 0xcd00>;
|
||||
interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
|
@ -3659,11 +3663,15 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_SEC_AXI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_SEC_AXI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB3_SEC_CLKREF_CLK>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep", "xo";
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi",
|
||||
"xo";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MASTER_CLK>;
|
||||
|
|
|
|||
|
|
@ -2995,11 +2995,15 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB3_SEC_CLKREF_EN>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep", "xo";
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi",
|
||||
"xo";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>;
|
||||
|
|
@ -3046,11 +3050,15 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_SEC_AXI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_SEC_AXI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB3_SEC_CLKREF_EN>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep", "xo";
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi",
|
||||
"xo";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MASTER_CLK>;
|
||||
|
|
|
|||
|
|
@ -2449,10 +2449,13 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep";
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>;
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>;
|
||||
|
|
@ -2492,11 +2495,15 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_SEC_AXI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_SEC_AXI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB3_SEC_CLKREF_EN>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep", "xo";
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi",
|
||||
"xo";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_SEC_MASTER_CLK>;
|
||||
|
|
|
|||
|
|
@ -3107,22 +3107,28 @@
|
|||
clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_SLEEP_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB3_0_CLKREF_EN>;
|
||||
clock-names = "cfg_noc", "core", "iface", "mock_utmi",
|
||||
"sleep", "xo";
|
||||
clock-names = "cfg_noc",
|
||||
"core",
|
||||
"iface",
|
||||
"sleep",
|
||||
"mock_utmi",
|
||||
"xo";
|
||||
|
||||
assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
|
||||
<&gcc GCC_USB30_PRIM_MASTER_CLK>;
|
||||
assigned-clock-rates = <19200000>, <200000000>;
|
||||
|
||||
interrupts-extended = <&intc GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<&pdc 14 IRQ_TYPE_EDGE_BOTH>,
|
||||
<&pdc 17 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<&pdc 15 IRQ_TYPE_EDGE_BOTH>,
|
||||
<&pdc 17 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "hs_phy_irq", "dp_hs_phy_irq",
|
||||
"dm_hs_phy_irq", "ss_phy_irq";
|
||||
<&pdc 14 IRQ_TYPE_EDGE_BOTH>;
|
||||
interrupt-names = "hs_phy_irq",
|
||||
"ss_phy_irq",
|
||||
"dm_hs_phy_irq",
|
||||
"dp_hs_phy_irq";
|
||||
|
||||
power-domains = <&gcc USB30_PRIM_GDSC>;
|
||||
|
||||
|
|
|
|||
|
|
@ -577,7 +577,7 @@
|
|||
};
|
||||
|
||||
otg: usb@13500000 {
|
||||
compatible = "ingenic,jz4780-otg", "snps,dwc2";
|
||||
compatible = "ingenic,jz4780-otg";
|
||||
reg = <0x13500000 0x40000>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
|
|
|
|||
|
|
@ -398,7 +398,7 @@
|
|||
};
|
||||
|
||||
otg: usb@13500000 {
|
||||
compatible = "ingenic,x1000-otg", "snps,dwc2";
|
||||
compatible = "ingenic,x1000-otg";
|
||||
reg = <0x13500000 0x40000>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
|
|
|
|||
|
|
@ -408,7 +408,7 @@
|
|||
};
|
||||
|
||||
otg: usb@13500000 {
|
||||
compatible = "ingenic,x1830-otg", "snps,dwc2";
|
||||
compatible = "ingenic,x1830-otg";
|
||||
reg = <0x13500000 0x40000>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
|
|
|
|||
|
|
@ -1206,15 +1206,23 @@ const void *device_get_match_data(struct device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(device_get_match_data);
|
||||
|
||||
static void *
|
||||
fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id,
|
||||
void *data, devcon_match_fn_t match)
|
||||
static unsigned int fwnode_graph_devcon_matches(struct fwnode_handle *fwnode,
|
||||
const char *con_id, void *data,
|
||||
devcon_match_fn_t match,
|
||||
void **matches,
|
||||
unsigned int matches_len)
|
||||
{
|
||||
struct fwnode_handle *node;
|
||||
struct fwnode_handle *ep;
|
||||
unsigned int count = 0;
|
||||
void *ret;
|
||||
|
||||
fwnode_graph_for_each_endpoint(fwnode, ep) {
|
||||
if (matches && count >= matches_len) {
|
||||
fwnode_handle_put(ep);
|
||||
break;
|
||||
}
|
||||
|
||||
node = fwnode_graph_get_remote_port_parent(ep);
|
||||
if (!fwnode_device_is_available(node)) {
|
||||
fwnode_handle_put(node);
|
||||
|
|
@ -1224,33 +1232,43 @@ fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id,
|
|||
ret = match(node, con_id, data);
|
||||
fwnode_handle_put(node);
|
||||
if (ret) {
|
||||
fwnode_handle_put(ep);
|
||||
return ret;
|
||||
if (matches)
|
||||
matches[count] = ret;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return count;
|
||||
}
|
||||
|
||||
static void *
|
||||
fwnode_devcon_match(struct fwnode_handle *fwnode, const char *con_id,
|
||||
void *data, devcon_match_fn_t match)
|
||||
static unsigned int fwnode_devcon_matches(struct fwnode_handle *fwnode,
|
||||
const char *con_id, void *data,
|
||||
devcon_match_fn_t match,
|
||||
void **matches,
|
||||
unsigned int matches_len)
|
||||
{
|
||||
struct fwnode_handle *node;
|
||||
unsigned int count = 0;
|
||||
unsigned int i;
|
||||
void *ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
if (matches && count >= matches_len)
|
||||
break;
|
||||
|
||||
node = fwnode_find_reference(fwnode, con_id, i);
|
||||
if (IS_ERR(node))
|
||||
break;
|
||||
|
||||
ret = match(node, NULL, data);
|
||||
fwnode_handle_put(node);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) {
|
||||
if (matches)
|
||||
matches[count] = ret;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1268,15 +1286,61 @@ void *fwnode_connection_find_match(struct fwnode_handle *fwnode,
|
|||
const char *con_id, void *data,
|
||||
devcon_match_fn_t match)
|
||||
{
|
||||
unsigned int count;
|
||||
void *ret;
|
||||
|
||||
if (!fwnode || !match)
|
||||
return NULL;
|
||||
|
||||
ret = fwnode_graph_devcon_match(fwnode, con_id, data, match);
|
||||
if (ret)
|
||||
count = fwnode_graph_devcon_matches(fwnode, con_id, data, match, &ret, 1);
|
||||
if (count)
|
||||
return ret;
|
||||
|
||||
return fwnode_devcon_match(fwnode, con_id, data, match);
|
||||
count = fwnode_devcon_matches(fwnode, con_id, data, match, &ret, 1);
|
||||
return count ? ret : NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_connection_find_match);
|
||||
|
||||
/**
|
||||
* fwnode_connection_find_matches - Find connections from a device node
|
||||
* @fwnode: Device node with the connection
|
||||
* @con_id: Identifier for the connection
|
||||
* @data: Data for the match function
|
||||
* @match: Function to check and convert the connection description
|
||||
* @matches: (Optional) array of pointers to fill with matches
|
||||
* @matches_len: Length of @matches
|
||||
*
|
||||
* Find up to @matches_len connections with unique identifier @con_id between
|
||||
* @fwnode and other device nodes. @match will be used to convert the
|
||||
* connection description to data the caller is expecting to be returned
|
||||
* through the @matches array.
|
||||
* If @matches is NULL @matches_len is ignored and the total number of resolved
|
||||
* matches is returned.
|
||||
*
|
||||
* Return: Number of matches resolved, or negative errno.
|
||||
*/
|
||||
int fwnode_connection_find_matches(struct fwnode_handle *fwnode,
|
||||
const char *con_id, void *data,
|
||||
devcon_match_fn_t match,
|
||||
void **matches, unsigned int matches_len)
|
||||
{
|
||||
unsigned int count_graph;
|
||||
unsigned int count_ref;
|
||||
|
||||
if (!fwnode || !match)
|
||||
return -EINVAL;
|
||||
|
||||
count_graph = fwnode_graph_devcon_matches(fwnode, con_id, data, match,
|
||||
matches, matches_len);
|
||||
|
||||
if (matches) {
|
||||
matches += count_graph;
|
||||
matches_len -= count_graph;
|
||||
}
|
||||
|
||||
count_ref = fwnode_devcon_matches(fwnode, con_id, data, match,
|
||||
matches, matches_len);
|
||||
|
||||
return count_graph + count_ref;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_connection_find_matches);
|
||||
|
|
|
|||
|
|
@ -387,7 +387,7 @@ static int hid_submit_ctrl(struct hid_device *hid)
|
|||
|
||||
usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0);
|
||||
maxpacket = usb_maxpacket(hid_to_usb_dev(hid),
|
||||
usbhid->urbctrl->pipe, 0);
|
||||
usbhid->urbctrl->pipe);
|
||||
len += (len == 0); /* Don't allow 0-length reports */
|
||||
len = round_up(len, maxpacket);
|
||||
if (len > usbhid->bufsize)
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ static int usb_kbd_probe(struct usb_interface *iface,
|
|||
return -ENODEV;
|
||||
|
||||
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
|
||||
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
|
||||
maxp = usb_maxpacket(dev, pipe);
|
||||
|
||||
kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
|
|||
return -ENODEV;
|
||||
|
||||
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
|
||||
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
|
||||
maxp = usb_maxpacket(dev, pipe);
|
||||
|
||||
mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
|
|
|
|||
|
|
@ -639,7 +639,7 @@ static int ati_remote2_urb_init(struct ati_remote2 *ar2)
|
|||
return -ENOMEM;
|
||||
|
||||
pipe = usb_rcvintpipe(udev, ar2->ep[i]->bEndpointAddress);
|
||||
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
|
||||
maxp = usb_maxpacket(udev, pipe);
|
||||
maxp = maxp > 4 ? 4 : maxp;
|
||||
|
||||
usb_fill_int_urb(ar2->urb[i], udev, pipe, ar2->buf[i], maxp,
|
||||
|
|
|
|||
|
|
@ -745,7 +745,7 @@ static int cm109_usb_probe(struct usb_interface *intf,
|
|||
|
||||
/* get a handle to the interrupt data pipe */
|
||||
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
|
||||
ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
|
||||
ret = usb_maxpacket(udev, pipe);
|
||||
if (ret != USB_PKT_LEN)
|
||||
dev_err(&intf->dev, "invalid payload size %d, expected %d\n",
|
||||
ret, USB_PKT_LEN);
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
|
|||
|
||||
/* get a handle to the interrupt data pipe */
|
||||
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
|
||||
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
|
||||
maxp = usb_maxpacket(udev, pipe);
|
||||
|
||||
if (maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX) {
|
||||
printk(KERN_WARNING "powermate: Expected payload of %d--%d bytes, found %d bytes!\n",
|
||||
|
|
|
|||
|
|
@ -905,7 +905,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|||
|
||||
/* get a handle to the interrupt data pipe */
|
||||
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
|
||||
ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
|
||||
ret = usb_maxpacket(udev, pipe);
|
||||
if (ret != USB_PKT_LEN)
|
||||
dev_err(&intf->dev, "invalid payload size %d, expected %zd\n",
|
||||
ret, USB_PKT_LEN);
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
|
|||
return -ENODEV;
|
||||
|
||||
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
|
||||
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
|
||||
maxp = usb_maxpacket(dev, pipe);
|
||||
|
||||
acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ static int pegasus_probe(struct usb_interface *intf,
|
|||
pegasus->intf = intf;
|
||||
|
||||
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
|
||||
pegasus->data_len = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
|
||||
pegasus->data_len = usb_maxpacket(dev, pipe);
|
||||
|
||||
pegasus->data = usb_alloc_coherent(dev, pegasus->data_len, GFP_KERNEL,
|
||||
&pegasus->data_dma);
|
||||
|
|
|
|||
|
|
@ -773,7 +773,7 @@ static int ati_remote_initialize(struct ati_remote *ati_remote)
|
|||
|
||||
/* Set up irq_urb */
|
||||
pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress);
|
||||
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
|
||||
maxp = usb_maxpacket(udev, pipe);
|
||||
maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
|
||||
|
||||
usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf,
|
||||
|
|
@ -784,7 +784,7 @@ static int ati_remote_initialize(struct ati_remote *ati_remote)
|
|||
|
||||
/* Set up out_urb */
|
||||
pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress);
|
||||
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
|
||||
maxp = usb_maxpacket(udev, pipe);
|
||||
maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
|
||||
|
||||
usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf,
|
||||
|
|
|
|||
|
|
@ -1728,7 +1728,7 @@ static int mceusb_dev_probe(struct usb_interface *intf,
|
|||
pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress);
|
||||
else
|
||||
pipe = usb_rcvbulkpipe(dev, ep_in->bEndpointAddress);
|
||||
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
|
||||
maxp = usb_maxpacket(dev, pipe);
|
||||
|
||||
ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL);
|
||||
if (!ir)
|
||||
|
|
|
|||
|
|
@ -307,7 +307,7 @@ static int streamzap_probe(struct usb_interface *intf,
|
|||
}
|
||||
|
||||
pipe = usb_rcvintpipe(usbdev, endpoint->bEndpointAddress);
|
||||
maxp = usb_maxpacket(usbdev, pipe, usb_pipeout(pipe));
|
||||
maxp = usb_maxpacket(usbdev, pipe);
|
||||
|
||||
if (maxp == 0) {
|
||||
dev_err(&intf->dev, "%s: endpoint Max Packet Size is 0!?!\n",
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ static int xbox_remote_initialize(struct xbox_remote *xbox_remote,
|
|||
|
||||
/* Set up irq_urb */
|
||||
pipe = usb_rcvintpipe(udev, endpoint_in->bEndpointAddress);
|
||||
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
|
||||
maxp = usb_maxpacket(udev, pipe);
|
||||
maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
|
||||
|
||||
usb_fill_int_urb(xbox_remote->irq_urb, udev, pipe, xbox_remote->inbuf,
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ static int tm6000_start_stream(struct tm6000_core *dev)
|
|||
pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress
|
||||
& USB_ENDPOINT_NUMBER_MASK);
|
||||
|
||||
size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
|
||||
size = usb_maxpacket(dev->udev, pipe);
|
||||
size = size * 15; /* 512 x 8 or 12 or 15 */
|
||||
|
||||
dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
|
||||
|
|
|
|||
|
|
@ -340,7 +340,7 @@ static int __tm6000_ir_int_start(struct rc_dev *rc)
|
|||
dev->int_in.endp->desc.bEndpointAddress
|
||||
& USB_ENDPOINT_NUMBER_MASK);
|
||||
|
||||
size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
|
||||
size = usb_maxpacket(dev->udev, pipe);
|
||||
dprintk(1, "IR max size: %d\n", size);
|
||||
|
||||
ir->int_urb->transfer_buffer = kzalloc(size, GFP_ATOMIC);
|
||||
|
|
|
|||
|
|
@ -570,7 +570,7 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev)
|
|||
dev->isoc_in.endp->desc.bEndpointAddress &
|
||||
USB_ENDPOINT_NUMBER_MASK);
|
||||
|
||||
size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
|
||||
size = usb_maxpacket(dev->udev, pipe);
|
||||
|
||||
if (size > dev->isoc_in.maxsize)
|
||||
size = dev->isoc_in.maxsize;
|
||||
|
|
|
|||
|
|
@ -784,7 +784,7 @@ static int mei_hdcp_component_match(struct device *dev, int subcomponent,
|
|||
{
|
||||
struct device *base = data;
|
||||
|
||||
if (strcmp(dev->driver->name, "i915") ||
|
||||
if (!dev->driver || strcmp(dev->driver->name, "i915") ||
|
||||
subcomponent != I915_COMPONENT_HDCP)
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ static int mei_pxp_component_match(struct device *dev, int subcomponent,
|
|||
{
|
||||
struct device *base = data;
|
||||
|
||||
if (strcmp(dev->driver->name, "i915") ||
|
||||
if (!dev->driver || strcmp(dev->driver->name, "i915") ||
|
||||
subcomponent != I915_COMPONENT_PXP)
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -441,7 +441,7 @@ static void cdc_ncm_update_rxtx_max(struct usbnet *dev, u32 new_rx, u32 new_tx)
|
|||
* .bind which is called before usbnet sets up dev->maxpacket
|
||||
*/
|
||||
if (val != le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize) &&
|
||||
val % usb_maxpacket(dev->udev, dev->out, 1) == 0)
|
||||
val % usb_maxpacket(dev->udev, dev->out) == 0)
|
||||
val++;
|
||||
|
||||
/* we might need to flush any pending tx buffers if running */
|
||||
|
|
@ -465,7 +465,7 @@ static void cdc_ncm_update_rxtx_max(struct usbnet *dev, u32 new_rx, u32 new_tx)
|
|||
usbnet_update_max_qlen(dev);
|
||||
|
||||
/* never pad more than 3 full USB packets per transfer */
|
||||
ctx->min_tx_pkt = clamp_t(u16, ctx->tx_max - 3 * usb_maxpacket(dev->udev, dev->out, 1),
|
||||
ctx->min_tx_pkt = clamp_t(u16, ctx->tx_max - 3 * usb_maxpacket(dev->udev, dev->out),
|
||||
CDC_NCM_MIN_TX_PKT, ctx->tx_max);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4421,7 +4421,7 @@ static int lan78xx_probe(struct usb_interface *intf,
|
|||
goto out4;
|
||||
|
||||
period = ep_intr->desc.bInterval;
|
||||
maxp = usb_maxpacket(dev->udev, dev->pipe_intr, 0);
|
||||
maxp = usb_maxpacket(dev->udev, dev->pipe_intr);
|
||||
buf = kmalloc(maxp, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
ret = -ENOMEM;
|
||||
|
|
@ -4439,7 +4439,7 @@ static int lan78xx_probe(struct usb_interface *intf,
|
|||
dev->urb_intr->transfer_flags |= URB_FREE_BUFFER;
|
||||
}
|
||||
|
||||
dev->maxpacket = usb_maxpacket(dev->udev, dev->pipe_out, 1);
|
||||
dev->maxpacket = usb_maxpacket(dev->udev, dev->pipe_out);
|
||||
|
||||
/* Reject broken descriptors. */
|
||||
if (dev->maxpacket == 0) {
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags)
|
|||
net->hard_header_len += sizeof (struct rndis_data_hdr);
|
||||
dev->hard_mtu = net->mtu + net->hard_header_len;
|
||||
|
||||
dev->maxpacket = usb_maxpacket(dev->udev, dev->out, 1);
|
||||
dev->maxpacket = usb_maxpacket(dev->udev, dev->out);
|
||||
if (dev->maxpacket == 0) {
|
||||
netif_dbg(dev, probe, dev->net,
|
||||
"dev->maxpacket can't be 0\n");
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
|
|||
pipe = usb_rcvintpipe (dev->udev,
|
||||
dev->status->desc.bEndpointAddress
|
||||
& USB_ENDPOINT_NUMBER_MASK);
|
||||
maxp = usb_maxpacket (dev->udev, pipe, 0);
|
||||
maxp = usb_maxpacket(dev->udev, pipe);
|
||||
|
||||
/* avoid 1 msec chatter: min 8 msec poll rate */
|
||||
period = max ((int) dev->status->desc.bInterval,
|
||||
|
|
@ -1789,7 +1789,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
|
|||
|
||||
if (!dev->rx_urb_size)
|
||||
dev->rx_urb_size = dev->hard_mtu;
|
||||
dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
|
||||
dev->maxpacket = usb_maxpacket(dev->udev, dev->out);
|
||||
if (dev->maxpacket == 0) {
|
||||
/* that is a broken device */
|
||||
status = -ENODEV;
|
||||
|
|
|
|||
|
|
@ -1068,7 +1068,7 @@ int __mt76u_init(struct mt76_dev *dev, struct usb_interface *intf,
|
|||
|
||||
INIT_WORK(&usb->stat_work, mt76u_tx_status_data);
|
||||
|
||||
usb->data_len = usb_maxpacket(udev, usb_sndctrlpipe(udev, 0), 1);
|
||||
usb->data_len = usb_maxpacket(udev, usb_sndctrlpipe(udev, 0));
|
||||
if (usb->data_len < 32)
|
||||
usb->data_len = 32;
|
||||
|
||||
|
|
|
|||
|
|
@ -586,10 +586,10 @@ static void rt2x00usb_assign_endpoint(struct data_queue *queue,
|
|||
|
||||
if (queue->qid == QID_RX) {
|
||||
pipe = usb_rcvbulkpipe(usb_dev, queue->usb_endpoint);
|
||||
queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 0);
|
||||
queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe);
|
||||
} else {
|
||||
pipe = usb_sndbulkpipe(usb_dev, queue->usb_endpoint);
|
||||
queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 1);
|
||||
queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe);
|
||||
}
|
||||
|
||||
if (!queue->usb_maxpacket)
|
||||
|
|
|
|||
|
|
@ -158,21 +158,20 @@ static bool tb_cfg_request_is_active(struct tb_cfg_request *req)
|
|||
static struct tb_cfg_request *
|
||||
tb_cfg_request_find(struct tb_ctl *ctl, struct ctl_pkg *pkg)
|
||||
{
|
||||
struct tb_cfg_request *req;
|
||||
bool found = false;
|
||||
struct tb_cfg_request *req = NULL, *iter;
|
||||
|
||||
mutex_lock(&pkg->ctl->request_queue_lock);
|
||||
list_for_each_entry(req, &pkg->ctl->request_queue, list) {
|
||||
tb_cfg_request_get(req);
|
||||
if (req->match(req, pkg)) {
|
||||
found = true;
|
||||
list_for_each_entry(iter, &pkg->ctl->request_queue, list) {
|
||||
tb_cfg_request_get(iter);
|
||||
if (iter->match(iter, pkg)) {
|
||||
req = iter;
|
||||
break;
|
||||
}
|
||||
tb_cfg_request_put(req);
|
||||
tb_cfg_request_put(iter);
|
||||
}
|
||||
mutex_unlock(&pkg->ctl->request_queue_lock);
|
||||
|
||||
return found ? req : NULL;
|
||||
return req;
|
||||
}
|
||||
|
||||
/* utility functions */
|
||||
|
|
|
|||
|
|
@ -1250,7 +1250,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
|
||||
nhi->pdev = pdev;
|
||||
nhi->ops = (const struct tb_nhi_ops *)id->driver_data;
|
||||
/* cannot fail - table is allocated bin pcim_iomap_regions */
|
||||
/* cannot fail - table is allocated in pcim_iomap_regions */
|
||||
nhi->iobase = pcim_iomap_table(pdev)[0];
|
||||
nhi->hop_count = ioread32(nhi->iobase + REG_HOP_COUNT) & 0x3ff;
|
||||
dev_dbg(&pdev->dev, "total paths: %d\n", nhi->hop_count);
|
||||
|
|
|
|||
|
|
@ -166,6 +166,9 @@ struct tb_path *tb_path_discover(struct tb_port *src, int src_hopid,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
tb_dbg(path->tb, "discovering %s path starting from %llx:%u\n",
|
||||
path->name, tb_route(src->sw), src->port);
|
||||
|
||||
p = src;
|
||||
h = src_hopid;
|
||||
|
||||
|
|
@ -198,10 +201,13 @@ struct tb_path *tb_path_discover(struct tb_port *src, int src_hopid,
|
|||
path->hops[i].out_port = out_port;
|
||||
path->hops[i].next_hop_index = next_hop;
|
||||
|
||||
tb_dump_hop(&path->hops[i], &hop);
|
||||
|
||||
h = next_hop;
|
||||
p = out_port->remote;
|
||||
}
|
||||
|
||||
tb_dbg(path->tb, "path discovery complete\n");
|
||||
return path;
|
||||
|
||||
err:
|
||||
|
|
|
|||
|
|
@ -693,8 +693,14 @@ static int __tb_port_enable(struct tb_port *port, bool enable)
|
|||
else
|
||||
phy |= LANE_ADP_CS_1_LD;
|
||||
|
||||
return tb_port_write(port, &phy, TB_CFG_PORT,
|
||||
port->cap_phy + LANE_ADP_CS_1, 1);
|
||||
|
||||
ret = tb_port_write(port, &phy, TB_CFG_PORT,
|
||||
port->cap_phy + LANE_ADP_CS_1, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
tb_port_dbg(port, "lane %sabled\n", enable ? "en" : "dis");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -993,7 +999,17 @@ static bool tb_port_is_width_supported(struct tb_port *port, int width)
|
|||
return !!(widths & width);
|
||||
}
|
||||
|
||||
static int tb_port_set_link_width(struct tb_port *port, unsigned int width)
|
||||
/**
|
||||
* tb_port_set_link_width() - Set target link width of the lane adapter
|
||||
* @port: Lane adapter
|
||||
* @width: Target link width (%1 or %2)
|
||||
*
|
||||
* Sets the target link width of the lane adapter to @width. Does not
|
||||
* enable/disable lane bonding. For that call tb_port_set_lane_bonding().
|
||||
*
|
||||
* Return: %0 in case of success and negative errno in case of error
|
||||
*/
|
||||
int tb_port_set_link_width(struct tb_port *port, unsigned int width)
|
||||
{
|
||||
u32 val;
|
||||
int ret;
|
||||
|
|
@ -1020,12 +1036,58 @@ static int tb_port_set_link_width(struct tb_port *port, unsigned int width)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
val |= LANE_ADP_CS_1_LB;
|
||||
|
||||
return tb_port_write(port, &val, TB_CFG_PORT,
|
||||
port->cap_phy + LANE_ADP_CS_1, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* tb_port_set_lane_bonding() - Enable/disable lane bonding
|
||||
* @port: Lane adapter
|
||||
* @bonding: enable/disable bonding
|
||||
*
|
||||
* Enables or disables lane bonding. This should be called after target
|
||||
* link width has been set (tb_port_set_link_width()). Note in most
|
||||
* cases one should use tb_port_lane_bonding_enable() instead to enable
|
||||
* lane bonding.
|
||||
*
|
||||
* As a side effect sets @port->bonding accordingly (and does the same
|
||||
* for lane 1 too).
|
||||
*
|
||||
* Return: %0 in case of success and negative errno in case of error
|
||||
*/
|
||||
int tb_port_set_lane_bonding(struct tb_port *port, bool bonding)
|
||||
{
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (!port->cap_phy)
|
||||
return -EINVAL;
|
||||
|
||||
ret = tb_port_read(port, &val, TB_CFG_PORT,
|
||||
port->cap_phy + LANE_ADP_CS_1, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (bonding)
|
||||
val |= LANE_ADP_CS_1_LB;
|
||||
else
|
||||
val &= ~LANE_ADP_CS_1_LB;
|
||||
|
||||
ret = tb_port_write(port, &val, TB_CFG_PORT,
|
||||
port->cap_phy + LANE_ADP_CS_1, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* When lane 0 bonding is set it will affect lane 1 too so
|
||||
* update both.
|
||||
*/
|
||||
port->bonded = bonding;
|
||||
port->dual_link_port->bonded = bonding;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tb_port_lane_bonding_enable() - Enable bonding on port
|
||||
* @port: port to enable
|
||||
|
|
@ -1050,22 +1112,27 @@ int tb_port_lane_bonding_enable(struct tb_port *port)
|
|||
if (ret == 1) {
|
||||
ret = tb_port_set_link_width(port, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_lane0;
|
||||
}
|
||||
|
||||
ret = tb_port_get_link_width(port->dual_link_port);
|
||||
if (ret == 1) {
|
||||
ret = tb_port_set_link_width(port->dual_link_port, 2);
|
||||
if (ret) {
|
||||
tb_port_set_link_width(port, 1);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto err_lane0;
|
||||
}
|
||||
|
||||
port->bonded = true;
|
||||
port->dual_link_port->bonded = true;
|
||||
ret = tb_port_set_lane_bonding(port, true);
|
||||
if (ret)
|
||||
goto err_lane1;
|
||||
|
||||
return 0;
|
||||
|
||||
err_lane1:
|
||||
tb_port_set_link_width(port->dual_link_port, 1);
|
||||
err_lane0:
|
||||
tb_port_set_link_width(port, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1074,13 +1141,10 @@ int tb_port_lane_bonding_enable(struct tb_port *port)
|
|||
*
|
||||
* Disable bonding by setting the link width of the port and the
|
||||
* other port in case of dual link port.
|
||||
*
|
||||
*/
|
||||
void tb_port_lane_bonding_disable(struct tb_port *port)
|
||||
{
|
||||
port->dual_link_port->bonded = false;
|
||||
port->bonded = false;
|
||||
|
||||
tb_port_set_lane_bonding(port, false);
|
||||
tb_port_set_link_width(port->dual_link_port, 1);
|
||||
tb_port_set_link_width(port, 1);
|
||||
}
|
||||
|
|
@ -1104,10 +1168,17 @@ int tb_port_wait_for_link_width(struct tb_port *port, int width,
|
|||
|
||||
do {
|
||||
ret = tb_port_get_link_width(port);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (ret == width)
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* Sometimes we get port locked error when
|
||||
* polling the lanes so we can ignore it and
|
||||
* retry.
|
||||
*/
|
||||
if (ret != -EACCES)
|
||||
return ret;
|
||||
} else if (ret == width) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
} while (ktime_before(ktime_get(), timeout));
|
||||
|
|
|
|||
|
|
@ -169,12 +169,6 @@ static void tb_discover_tunnels(struct tb *tb)
|
|||
|
||||
static int tb_port_configure_xdomain(struct tb_port *port)
|
||||
{
|
||||
/*
|
||||
* XDomain paths currently only support single lane so we must
|
||||
* disable the other lane according to USB4 spec.
|
||||
*/
|
||||
tb_port_disable(port->dual_link_port);
|
||||
|
||||
if (tb_switch_is_usb4(port->sw))
|
||||
return usb4_port_configure_xdomain(port);
|
||||
return tb_lc_configure_xdomain(port);
|
||||
|
|
@ -867,7 +861,7 @@ static struct tb_port *tb_find_dp_out(struct tb *tb, struct tb_port *in)
|
|||
|
||||
static void tb_tunnel_dp(struct tb *tb)
|
||||
{
|
||||
int available_up, available_down, ret;
|
||||
int available_up, available_down, ret, link_nr;
|
||||
struct tb_cm *tcm = tb_priv(tb);
|
||||
struct tb_port *port, *in, *out;
|
||||
struct tb_tunnel *tunnel;
|
||||
|
|
@ -912,6 +906,20 @@ static void tb_tunnel_dp(struct tb *tb)
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is only applicable to links that are not bonded (so
|
||||
* when Thunderbolt 1 hardware is involved somewhere in the
|
||||
* topology). For these try to share the DP bandwidth between
|
||||
* the two lanes.
|
||||
*/
|
||||
link_nr = 1;
|
||||
list_for_each_entry(tunnel, &tcm->tunnel_list, list) {
|
||||
if (tb_tunnel_is_dp(tunnel)) {
|
||||
link_nr = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* DP stream needs the domain to be active so runtime resume
|
||||
* both ends of the tunnel.
|
||||
|
|
@ -943,7 +951,8 @@ static void tb_tunnel_dp(struct tb *tb)
|
|||
tb_dbg(tb, "available bandwidth for new DP tunnel %u/%u Mb/s\n",
|
||||
available_up, available_down);
|
||||
|
||||
tunnel = tb_tunnel_alloc_dp(tb, in, out, available_up, available_down);
|
||||
tunnel = tb_tunnel_alloc_dp(tb, in, out, link_nr, available_up,
|
||||
available_down);
|
||||
if (!tunnel) {
|
||||
tb_port_dbg(out, "could not allocate DP tunnel\n");
|
||||
goto err_reclaim;
|
||||
|
|
|
|||
|
|
@ -674,7 +674,7 @@ static inline int tb_port_write(struct tb_port *port, const void *buffer,
|
|||
#define __TB_PORT_PRINT(level, _port, fmt, arg...) \
|
||||
do { \
|
||||
const struct tb_port *__port = (_port); \
|
||||
level(__port->sw->tb, "%llx:%x: " fmt, \
|
||||
level(__port->sw->tb, "%llx:%u: " fmt, \
|
||||
tb_route(__port->sw), __port->port, ## arg); \
|
||||
} while (0)
|
||||
#define tb_port_WARN(port, fmt, arg...) \
|
||||
|
|
@ -991,6 +991,7 @@ int tb_switch_pcie_l1_enable(struct tb_switch *sw);
|
|||
int tb_switch_xhci_connect(struct tb_switch *sw);
|
||||
void tb_switch_xhci_disconnect(struct tb_switch *sw);
|
||||
|
||||
int tb_port_state(struct tb_port *port);
|
||||
int tb_wait_for_port(struct tb_port *port, bool wait_if_unplugged);
|
||||
int tb_port_add_nfc_credits(struct tb_port *port, int credits);
|
||||
int tb_port_clear_counter(struct tb_port *port, int counter);
|
||||
|
|
@ -1023,7 +1024,8 @@ static inline bool tb_port_use_credit_allocation(const struct tb_port *port)
|
|||
|
||||
int tb_port_get_link_speed(struct tb_port *port);
|
||||
int tb_port_get_link_width(struct tb_port *port);
|
||||
int tb_port_state(struct tb_port *port);
|
||||
int tb_port_set_link_width(struct tb_port *port, unsigned int width);
|
||||
int tb_port_set_lane_bonding(struct tb_port *port, bool bonding);
|
||||
int tb_port_lane_bonding_enable(struct tb_port *port);
|
||||
void tb_port_lane_bonding_disable(struct tb_port *port);
|
||||
int tb_port_wait_for_link_width(struct tb_port *port, int width,
|
||||
|
|
|
|||
|
|
@ -527,6 +527,10 @@ enum tb_xdp_type {
|
|||
PROPERTIES_CHANGED_RESPONSE,
|
||||
ERROR_RESPONSE,
|
||||
UUID_REQUEST = 12,
|
||||
LINK_STATE_STATUS_REQUEST = 15,
|
||||
LINK_STATE_STATUS_RESPONSE,
|
||||
LINK_STATE_CHANGE_REQUEST,
|
||||
LINK_STATE_CHANGE_RESPONSE,
|
||||
};
|
||||
|
||||
struct tb_xdp_header {
|
||||
|
|
@ -540,6 +544,41 @@ struct tb_xdp_error_response {
|
|||
u32 error;
|
||||
};
|
||||
|
||||
struct tb_xdp_link_state_status {
|
||||
struct tb_xdp_header hdr;
|
||||
};
|
||||
|
||||
struct tb_xdp_link_state_status_response {
|
||||
union {
|
||||
struct tb_xdp_error_response err;
|
||||
struct {
|
||||
struct tb_xdp_header hdr;
|
||||
u32 status;
|
||||
u8 slw;
|
||||
u8 tlw;
|
||||
u8 sls;
|
||||
u8 tls;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct tb_xdp_link_state_change {
|
||||
struct tb_xdp_header hdr;
|
||||
u8 tlw;
|
||||
u8 tls;
|
||||
u16 reserved;
|
||||
};
|
||||
|
||||
struct tb_xdp_link_state_change_response {
|
||||
union {
|
||||
struct tb_xdp_error_response err;
|
||||
struct {
|
||||
struct tb_xdp_header hdr;
|
||||
u32 status;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct tb_xdp_uuid {
|
||||
struct tb_xdp_header hdr;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -311,11 +311,16 @@ struct tb_regs_port_header {
|
|||
|
||||
/* Lane adapter registers */
|
||||
#define LANE_ADP_CS_0 0x00
|
||||
#define LANE_ADP_CS_0_SUPPORTED_SPEED_MASK GENMASK(19, 16)
|
||||
#define LANE_ADP_CS_0_SUPPORTED_SPEED_SHIFT 16
|
||||
#define LANE_ADP_CS_0_SUPPORTED_WIDTH_MASK GENMASK(25, 20)
|
||||
#define LANE_ADP_CS_0_SUPPORTED_WIDTH_SHIFT 20
|
||||
#define LANE_ADP_CS_0_SUPPORTED_WIDTH_DUAL 0x2
|
||||
#define LANE_ADP_CS_0_CL0S_SUPPORT BIT(26)
|
||||
#define LANE_ADP_CS_0_CL1_SUPPORT BIT(27)
|
||||
#define LANE_ADP_CS_1 0x01
|
||||
#define LANE_ADP_CS_1_TARGET_SPEED_MASK GENMASK(3, 0)
|
||||
#define LANE_ADP_CS_1_TARGET_SPEED_GEN3 0xc
|
||||
#define LANE_ADP_CS_1_TARGET_WIDTH_MASK GENMASK(9, 4)
|
||||
#define LANE_ADP_CS_1_TARGET_WIDTH_SHIFT 4
|
||||
#define LANE_ADP_CS_1_TARGET_WIDTH_SINGLE 0x1
|
||||
|
|
|
|||
|
|
@ -341,6 +341,47 @@ static struct tb_switch *alloc_dev_with_dpin(struct kunit *test,
|
|||
return sw;
|
||||
}
|
||||
|
||||
static struct tb_switch *alloc_dev_without_dp(struct kunit *test,
|
||||
struct tb_switch *parent,
|
||||
u64 route, bool bonded)
|
||||
{
|
||||
struct tb_switch *sw;
|
||||
int i;
|
||||
|
||||
sw = alloc_dev_default(test, parent, route, bonded);
|
||||
if (!sw)
|
||||
return NULL;
|
||||
/*
|
||||
* Device with:
|
||||
* 2x USB4 Adapters (adapters 1,2 and 3,4),
|
||||
* 1x PCIe Upstream (adapter 9),
|
||||
* 1x PCIe Downstream (adapter 10),
|
||||
* 1x USB3 Upstream (adapter 16),
|
||||
* 1x USB3 Downstream (adapter 17)
|
||||
*/
|
||||
for (i = 5; i <= 8; i++)
|
||||
sw->ports[i].disabled = true;
|
||||
|
||||
for (i = 11; i <= 14; i++)
|
||||
sw->ports[i].disabled = true;
|
||||
|
||||
sw->ports[13].cap_adap = 0;
|
||||
sw->ports[14].cap_adap = 0;
|
||||
|
||||
for (i = 18; i <= 19; i++)
|
||||
sw->ports[i].disabled = true;
|
||||
|
||||
sw->generation = 4;
|
||||
sw->credit_allocation = true;
|
||||
sw->max_usb3_credits = 109;
|
||||
sw->min_dp_aux_credits = 0;
|
||||
sw->min_dp_main_credits = 0;
|
||||
sw->max_pcie_credits = 30;
|
||||
sw->max_dma_credits = 1;
|
||||
|
||||
return sw;
|
||||
}
|
||||
|
||||
static struct tb_switch *alloc_dev_usb4(struct kunit *test,
|
||||
struct tb_switch *parent,
|
||||
u64 route, bool bonded)
|
||||
|
|
@ -1348,7 +1389,7 @@ static void tb_test_tunnel_dp(struct kunit *test)
|
|||
in = &host->ports[5];
|
||||
out = &dev->ports[13];
|
||||
|
||||
tunnel = tb_tunnel_alloc_dp(NULL, in, out, 0, 0);
|
||||
tunnel = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tunnel);
|
||||
KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP);
|
||||
KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in);
|
||||
|
|
@ -1394,7 +1435,7 @@ static void tb_test_tunnel_dp_chain(struct kunit *test)
|
|||
in = &host->ports[5];
|
||||
out = &dev4->ports[14];
|
||||
|
||||
tunnel = tb_tunnel_alloc_dp(NULL, in, out, 0, 0);
|
||||
tunnel = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tunnel);
|
||||
KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP);
|
||||
KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in);
|
||||
|
|
@ -1444,7 +1485,7 @@ static void tb_test_tunnel_dp_tree(struct kunit *test)
|
|||
in = &dev2->ports[13];
|
||||
out = &dev5->ports[13];
|
||||
|
||||
tunnel = tb_tunnel_alloc_dp(NULL, in, out, 0, 0);
|
||||
tunnel = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tunnel);
|
||||
KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP);
|
||||
KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in);
|
||||
|
|
@ -1509,7 +1550,7 @@ static void tb_test_tunnel_dp_max_length(struct kunit *test)
|
|||
in = &dev6->ports[13];
|
||||
out = &dev12->ports[13];
|
||||
|
||||
tunnel = tb_tunnel_alloc_dp(NULL, in, out, 0, 0);
|
||||
tunnel = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tunnel);
|
||||
KUNIT_EXPECT_EQ(test, tunnel->type, TB_TUNNEL_DP);
|
||||
KUNIT_EXPECT_PTR_EQ(test, tunnel->src_port, in);
|
||||
|
|
@ -1627,7 +1668,7 @@ static void tb_test_tunnel_port_on_path(struct kunit *test)
|
|||
in = &dev2->ports[13];
|
||||
out = &dev5->ports[13];
|
||||
|
||||
dp_tunnel = tb_tunnel_alloc_dp(NULL, in, out, 0, 0);
|
||||
dp_tunnel = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0);
|
||||
KUNIT_ASSERT_NOT_NULL(test, dp_tunnel);
|
||||
|
||||
KUNIT_EXPECT_TRUE(test, tb_tunnel_port_on_path(dp_tunnel, in));
|
||||
|
|
@ -1996,6 +2037,56 @@ static void tb_test_credit_alloc_pcie(struct kunit *test)
|
|||
tb_tunnel_free(tunnel);
|
||||
}
|
||||
|
||||
static void tb_test_credit_alloc_without_dp(struct kunit *test)
|
||||
{
|
||||
struct tb_switch *host, *dev;
|
||||
struct tb_port *up, *down;
|
||||
struct tb_tunnel *tunnel;
|
||||
struct tb_path *path;
|
||||
|
||||
host = alloc_host_usb4(test);
|
||||
dev = alloc_dev_without_dp(test, host, 0x1, true);
|
||||
|
||||
/*
|
||||
* The device has no DP therefore baMinDPmain = baMinDPaux = 0
|
||||
*
|
||||
* Create PCIe path with buffers less than baMaxPCIe.
|
||||
*
|
||||
* For a device with buffers configurations:
|
||||
* baMaxUSB3 = 109
|
||||
* baMinDPaux = 0
|
||||
* baMinDPmain = 0
|
||||
* baMaxPCIe = 30
|
||||
* baMaxHI = 1
|
||||
* Remaining Buffers = Total - (CP + DP) = 120 - (2 + 0) = 118
|
||||
* PCIe Credits = Max(6, Min(baMaxPCIe, Remaining Buffers - baMaxUSB3)
|
||||
* = Max(6, Min(30, 9) = 9
|
||||
*/
|
||||
down = &host->ports[8];
|
||||
up = &dev->ports[9];
|
||||
tunnel = tb_tunnel_alloc_pci(NULL, up, down);
|
||||
KUNIT_ASSERT_TRUE(test, tunnel != NULL);
|
||||
KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)2);
|
||||
|
||||
/* PCIe downstream path */
|
||||
path = tunnel->paths[0];
|
||||
KUNIT_ASSERT_EQ(test, path->path_length, 2);
|
||||
KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U);
|
||||
KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U);
|
||||
KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U);
|
||||
KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 9U);
|
||||
|
||||
/* PCIe upstream path */
|
||||
path = tunnel->paths[1];
|
||||
KUNIT_ASSERT_EQ(test, path->path_length, 2);
|
||||
KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U);
|
||||
KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U);
|
||||
KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U);
|
||||
KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 64U);
|
||||
|
||||
tb_tunnel_free(tunnel);
|
||||
}
|
||||
|
||||
static void tb_test_credit_alloc_dp(struct kunit *test)
|
||||
{
|
||||
struct tb_switch *host, *dev;
|
||||
|
|
@ -2009,7 +2100,7 @@ static void tb_test_credit_alloc_dp(struct kunit *test)
|
|||
in = &host->ports[5];
|
||||
out = &dev->ports[14];
|
||||
|
||||
tunnel = tb_tunnel_alloc_dp(NULL, in, out, 0, 0);
|
||||
tunnel = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tunnel);
|
||||
KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)3);
|
||||
|
||||
|
|
@ -2245,7 +2336,7 @@ static struct tb_tunnel *TB_TEST_DP_TUNNEL1(struct kunit *test,
|
|||
|
||||
in = &host->ports[5];
|
||||
out = &dev->ports[13];
|
||||
dp_tunnel1 = tb_tunnel_alloc_dp(NULL, in, out, 0, 0);
|
||||
dp_tunnel1 = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0);
|
||||
KUNIT_ASSERT_NOT_NULL(test, dp_tunnel1);
|
||||
KUNIT_ASSERT_EQ(test, dp_tunnel1->npaths, (size_t)3);
|
||||
|
||||
|
|
@ -2282,7 +2373,7 @@ static struct tb_tunnel *TB_TEST_DP_TUNNEL2(struct kunit *test,
|
|||
|
||||
in = &host->ports[6];
|
||||
out = &dev->ports[14];
|
||||
dp_tunnel2 = tb_tunnel_alloc_dp(NULL, in, out, 0, 0);
|
||||
dp_tunnel2 = tb_tunnel_alloc_dp(NULL, in, out, 1, 0, 0);
|
||||
KUNIT_ASSERT_NOT_NULL(test, dp_tunnel2);
|
||||
KUNIT_ASSERT_EQ(test, dp_tunnel2->npaths, (size_t)3);
|
||||
|
||||
|
|
@ -2709,6 +2800,7 @@ static struct kunit_case tb_test_cases[] = {
|
|||
KUNIT_CASE(tb_test_credit_alloc_legacy_not_bonded),
|
||||
KUNIT_CASE(tb_test_credit_alloc_legacy_bonded),
|
||||
KUNIT_CASE(tb_test_credit_alloc_pcie),
|
||||
KUNIT_CASE(tb_test_credit_alloc_without_dp),
|
||||
KUNIT_CASE(tb_test_credit_alloc_dp),
|
||||
KUNIT_CASE(tb_test_credit_alloc_usb3),
|
||||
KUNIT_CASE(tb_test_credit_alloc_dma),
|
||||
|
|
|
|||
|
|
@ -102,8 +102,11 @@ static unsigned int tb_available_credits(const struct tb_port *port,
|
|||
* Maximum number of DP streams possible through the
|
||||
* lane adapter.
|
||||
*/
|
||||
ndp = (credits - (usb3 + pcie + spare)) /
|
||||
(sw->min_dp_aux_credits + sw->min_dp_main_credits);
|
||||
if (sw->min_dp_aux_credits + sw->min_dp_main_credits)
|
||||
ndp = (credits - (usb3 + pcie + spare)) /
|
||||
(sw->min_dp_aux_credits + sw->min_dp_main_credits);
|
||||
else
|
||||
ndp = 0;
|
||||
} else {
|
||||
ndp = 0;
|
||||
}
|
||||
|
|
@ -858,6 +861,7 @@ err_free:
|
|||
* @tb: Pointer to the domain structure
|
||||
* @in: DP in adapter port
|
||||
* @out: DP out adapter port
|
||||
* @link_nr: Preferred lane adapter when the link is not bonded
|
||||
* @max_up: Maximum available upstream bandwidth for the DP tunnel (%0
|
||||
* if not limited)
|
||||
* @max_down: Maximum available downstream bandwidth for the DP tunnel
|
||||
|
|
@ -869,8 +873,8 @@ err_free:
|
|||
* Return: Returns a tb_tunnel on success or NULL on failure.
|
||||
*/
|
||||
struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in,
|
||||
struct tb_port *out, int max_up,
|
||||
int max_down)
|
||||
struct tb_port *out, int link_nr,
|
||||
int max_up, int max_down)
|
||||
{
|
||||
struct tb_tunnel *tunnel;
|
||||
struct tb_path **paths;
|
||||
|
|
@ -894,21 +898,21 @@ struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in,
|
|||
paths = tunnel->paths;
|
||||
|
||||
path = tb_path_alloc(tb, in, TB_DP_VIDEO_HOPID, out, TB_DP_VIDEO_HOPID,
|
||||
1, "Video");
|
||||
link_nr, "Video");
|
||||
if (!path)
|
||||
goto err_free;
|
||||
tb_dp_init_video_path(path);
|
||||
paths[TB_DP_VIDEO_PATH_OUT] = path;
|
||||
|
||||
path = tb_path_alloc(tb, in, TB_DP_AUX_TX_HOPID, out,
|
||||
TB_DP_AUX_TX_HOPID, 1, "AUX TX");
|
||||
TB_DP_AUX_TX_HOPID, link_nr, "AUX TX");
|
||||
if (!path)
|
||||
goto err_free;
|
||||
tb_dp_init_aux_path(path);
|
||||
paths[TB_DP_AUX_PATH_OUT] = path;
|
||||
|
||||
path = tb_path_alloc(tb, out, TB_DP_AUX_RX_HOPID, in,
|
||||
TB_DP_AUX_RX_HOPID, 1, "AUX RX");
|
||||
TB_DP_AUX_RX_HOPID, link_nr, "AUX RX");
|
||||
if (!path)
|
||||
goto err_free;
|
||||
tb_dp_init_aux_path(path);
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, struct tb_port *up,
|
|||
struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in,
|
||||
bool alloc_hopid);
|
||||
struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in,
|
||||
struct tb_port *out, int max_up,
|
||||
int max_down);
|
||||
struct tb_port *out, int link_nr,
|
||||
int max_up, int max_down);
|
||||
struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi,
|
||||
struct tb_port *dst, int transmit_path,
|
||||
int transmit_ring, int receive_path,
|
||||
|
|
|
|||
|
|
@ -7,9 +7,37 @@
|
|||
*/
|
||||
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/property.h>
|
||||
|
||||
#include "tb.h"
|
||||
|
||||
static int connector_bind(struct device *dev, struct device *connector, void *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sysfs_create_link(&dev->kobj, &connector->kobj, "connector");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sysfs_create_link(&connector->kobj, &dev->kobj, dev_name(dev));
|
||||
if (ret)
|
||||
sysfs_remove_link(&dev->kobj, "connector");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void connector_unbind(struct device *dev, struct device *connector, void *data)
|
||||
{
|
||||
sysfs_remove_link(&connector->kobj, dev_name(dev));
|
||||
sysfs_remove_link(&dev->kobj, "connector");
|
||||
}
|
||||
|
||||
static const struct component_ops connector_ops = {
|
||||
.bind = connector_bind,
|
||||
.unbind = connector_unbind,
|
||||
};
|
||||
|
||||
static ssize_t link_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
|
|
@ -246,6 +274,14 @@ struct usb4_port *usb4_port_device_add(struct tb_port *port)
|
|||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (dev_fwnode(&usb4->dev)) {
|
||||
ret = component_add(&usb4->dev, &connector_ops);
|
||||
if (ret) {
|
||||
dev_err(&usb4->dev, "failed to add component\n");
|
||||
device_unregister(&usb4->dev);
|
||||
}
|
||||
}
|
||||
|
||||
pm_runtime_no_callbacks(&usb4->dev);
|
||||
pm_runtime_set_active(&usb4->dev);
|
||||
pm_runtime_enable(&usb4->dev);
|
||||
|
|
@ -265,6 +301,8 @@ struct usb4_port *usb4_port_device_add(struct tb_port *port)
|
|||
*/
|
||||
void usb4_port_device_remove(struct usb4_port *usb4)
|
||||
{
|
||||
if (dev_fwnode(&usb4->dev))
|
||||
component_del(&usb4->dev, &connector_ops);
|
||||
device_unregister(&usb4->dev);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,13 +19,38 @@
|
|||
|
||||
#include "tb.h"
|
||||
|
||||
#define XDOMAIN_DEFAULT_TIMEOUT 1000 /* ms */
|
||||
#define XDOMAIN_UUID_RETRIES 10
|
||||
#define XDOMAIN_PROPERTIES_RETRIES 10
|
||||
#define XDOMAIN_PROPERTIES_CHANGED_RETRIES 10
|
||||
#define XDOMAIN_BONDING_WAIT 100 /* ms */
|
||||
#define XDOMAIN_SHORT_TIMEOUT 100 /* ms */
|
||||
#define XDOMAIN_DEFAULT_TIMEOUT 1000 /* ms */
|
||||
#define XDOMAIN_BONDING_TIMEOUT 10000 /* ms */
|
||||
#define XDOMAIN_RETRIES 10
|
||||
#define XDOMAIN_DEFAULT_MAX_HOPID 15
|
||||
|
||||
enum {
|
||||
XDOMAIN_STATE_INIT,
|
||||
XDOMAIN_STATE_UUID,
|
||||
XDOMAIN_STATE_LINK_STATUS,
|
||||
XDOMAIN_STATE_LINK_STATE_CHANGE,
|
||||
XDOMAIN_STATE_LINK_STATUS2,
|
||||
XDOMAIN_STATE_BONDING_UUID_LOW,
|
||||
XDOMAIN_STATE_BONDING_UUID_HIGH,
|
||||
XDOMAIN_STATE_PROPERTIES,
|
||||
XDOMAIN_STATE_ENUMERATED,
|
||||
XDOMAIN_STATE_ERROR,
|
||||
};
|
||||
|
||||
static const char * const state_names[] = {
|
||||
[XDOMAIN_STATE_INIT] = "INIT",
|
||||
[XDOMAIN_STATE_UUID] = "UUID",
|
||||
[XDOMAIN_STATE_LINK_STATUS] = "LINK_STATUS",
|
||||
[XDOMAIN_STATE_LINK_STATE_CHANGE] = "LINK_STATE_CHANGE",
|
||||
[XDOMAIN_STATE_LINK_STATUS2] = "LINK_STATUS2",
|
||||
[XDOMAIN_STATE_BONDING_UUID_LOW] = "BONDING_UUID_LOW",
|
||||
[XDOMAIN_STATE_BONDING_UUID_HIGH] = "BONDING_UUID_HIGH",
|
||||
[XDOMAIN_STATE_PROPERTIES] = "PROPERTIES",
|
||||
[XDOMAIN_STATE_ENUMERATED] = "ENUMERATED",
|
||||
[XDOMAIN_STATE_ERROR] = "ERROR",
|
||||
};
|
||||
|
||||
struct xdomain_request_work {
|
||||
struct work_struct work;
|
||||
struct tb_xdp_header *pkg;
|
||||
|
|
@ -235,7 +260,7 @@ static int tb_xdp_handle_error(const struct tb_xdp_error_response *res)
|
|||
}
|
||||
|
||||
static int tb_xdp_uuid_request(struct tb_ctl *ctl, u64 route, int retry,
|
||||
uuid_t *uuid)
|
||||
uuid_t *uuid, u64 *remote_route)
|
||||
{
|
||||
struct tb_xdp_uuid_response res;
|
||||
struct tb_xdp_uuid req;
|
||||
|
|
@ -258,6 +283,8 @@ static int tb_xdp_uuid_request(struct tb_ctl *ctl, u64 route, int retry,
|
|||
return ret;
|
||||
|
||||
uuid_copy(uuid, &res.src_uuid);
|
||||
*remote_route = (u64)res.src_route_hi << 32 | res.src_route_lo;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -473,6 +500,112 @@ tb_xdp_properties_changed_response(struct tb_ctl *ctl, u64 route, u8 sequence)
|
|||
TB_CFG_PKG_XDOMAIN_RESP);
|
||||
}
|
||||
|
||||
static int tb_xdp_link_state_status_request(struct tb_ctl *ctl, u64 route,
|
||||
u8 sequence, u8 *slw, u8 *tlw,
|
||||
u8 *sls, u8 *tls)
|
||||
{
|
||||
struct tb_xdp_link_state_status_response res;
|
||||
struct tb_xdp_link_state_status req;
|
||||
int ret;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
tb_xdp_fill_header(&req.hdr, route, sequence, LINK_STATE_STATUS_REQUEST,
|
||||
sizeof(req));
|
||||
|
||||
memset(&res, 0, sizeof(res));
|
||||
ret = __tb_xdomain_request(ctl, &req, sizeof(req), TB_CFG_PKG_XDOMAIN_REQ,
|
||||
&res, sizeof(res), TB_CFG_PKG_XDOMAIN_RESP,
|
||||
XDOMAIN_DEFAULT_TIMEOUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = tb_xdp_handle_error(&res.err);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (res.status != 0)
|
||||
return -EREMOTEIO;
|
||||
|
||||
*slw = res.slw;
|
||||
*tlw = res.tlw;
|
||||
*sls = res.sls;
|
||||
*tls = res.tls;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tb_xdp_link_state_status_response(struct tb *tb, struct tb_ctl *ctl,
|
||||
struct tb_xdomain *xd, u8 sequence)
|
||||
{
|
||||
struct tb_switch *sw = tb_to_switch(xd->dev.parent);
|
||||
struct tb_xdp_link_state_status_response res;
|
||||
struct tb_port *port = tb_port_at(xd->route, sw);
|
||||
u32 val[2];
|
||||
int ret;
|
||||
|
||||
memset(&res, 0, sizeof(res));
|
||||
tb_xdp_fill_header(&res.hdr, xd->route, sequence,
|
||||
LINK_STATE_STATUS_RESPONSE, sizeof(res));
|
||||
|
||||
ret = tb_port_read(port, val, TB_CFG_PORT,
|
||||
port->cap_phy + LANE_ADP_CS_0, ARRAY_SIZE(val));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
res.slw = (val[0] & LANE_ADP_CS_0_SUPPORTED_WIDTH_MASK) >>
|
||||
LANE_ADP_CS_0_SUPPORTED_WIDTH_SHIFT;
|
||||
res.sls = (val[0] & LANE_ADP_CS_0_SUPPORTED_SPEED_MASK) >>
|
||||
LANE_ADP_CS_0_SUPPORTED_SPEED_SHIFT;
|
||||
res.tls = val[1] & LANE_ADP_CS_1_TARGET_SPEED_MASK;
|
||||
res.tlw = (val[1] & LANE_ADP_CS_1_TARGET_WIDTH_MASK) >>
|
||||
LANE_ADP_CS_1_TARGET_WIDTH_SHIFT;
|
||||
|
||||
return __tb_xdomain_response(ctl, &res, sizeof(res),
|
||||
TB_CFG_PKG_XDOMAIN_RESP);
|
||||
}
|
||||
|
||||
static int tb_xdp_link_state_change_request(struct tb_ctl *ctl, u64 route,
|
||||
u8 sequence, u8 tlw, u8 tls)
|
||||
{
|
||||
struct tb_xdp_link_state_change_response res;
|
||||
struct tb_xdp_link_state_change req;
|
||||
int ret;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
tb_xdp_fill_header(&req.hdr, route, sequence, LINK_STATE_CHANGE_REQUEST,
|
||||
sizeof(req));
|
||||
req.tlw = tlw;
|
||||
req.tls = tls;
|
||||
|
||||
memset(&res, 0, sizeof(res));
|
||||
ret = __tb_xdomain_request(ctl, &req, sizeof(req), TB_CFG_PKG_XDOMAIN_REQ,
|
||||
&res, sizeof(res), TB_CFG_PKG_XDOMAIN_RESP,
|
||||
XDOMAIN_DEFAULT_TIMEOUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = tb_xdp_handle_error(&res.err);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return res.status != 0 ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
static int tb_xdp_link_state_change_response(struct tb_ctl *ctl, u64 route,
|
||||
u8 sequence, u32 status)
|
||||
{
|
||||
struct tb_xdp_link_state_change_response res;
|
||||
|
||||
memset(&res, 0, sizeof(res));
|
||||
tb_xdp_fill_header(&res.hdr, route, sequence, LINK_STATE_CHANGE_RESPONSE,
|
||||
sizeof(res));
|
||||
|
||||
res.status = status;
|
||||
|
||||
return __tb_xdomain_response(ctl, &res, sizeof(res),
|
||||
TB_CFG_PKG_XDOMAIN_RESP);
|
||||
}
|
||||
|
||||
/**
|
||||
* tb_register_protocol_handler() - Register protocol handler
|
||||
* @handler: Handler to register
|
||||
|
|
@ -600,14 +733,13 @@ static void tb_xdp_handle_request(struct work_struct *work)
|
|||
goto out;
|
||||
}
|
||||
|
||||
tb_dbg(tb, "%llx: received XDomain request %#x\n", route, pkg->type);
|
||||
|
||||
xd = tb_xdomain_find_by_route_locked(tb, route);
|
||||
if (xd)
|
||||
update_property_block(xd);
|
||||
|
||||
switch (pkg->type) {
|
||||
case PROPERTIES_REQUEST:
|
||||
tb_dbg(tb, "%llx: received XDomain properties request\n", route);
|
||||
if (xd) {
|
||||
ret = tb_xdp_properties_response(tb, ctl, xd, sequence,
|
||||
(const struct tb_xdp_properties *)pkg);
|
||||
|
|
@ -615,6 +747,9 @@ static void tb_xdp_handle_request(struct work_struct *work)
|
|||
break;
|
||||
|
||||
case PROPERTIES_CHANGED_REQUEST:
|
||||
tb_dbg(tb, "%llx: received XDomain properties changed request\n",
|
||||
route);
|
||||
|
||||
ret = tb_xdp_properties_changed_response(ctl, route, sequence);
|
||||
|
||||
/*
|
||||
|
|
@ -622,18 +757,51 @@ static void tb_xdp_handle_request(struct work_struct *work)
|
|||
* the xdomain related to this connection as well in
|
||||
* case there is a change in services it offers.
|
||||
*/
|
||||
if (xd && device_is_registered(&xd->dev)) {
|
||||
queue_delayed_work(tb->wq, &xd->get_properties_work,
|
||||
msecs_to_jiffies(50));
|
||||
}
|
||||
if (xd && device_is_registered(&xd->dev))
|
||||
queue_delayed_work(tb->wq, &xd->state_work,
|
||||
msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
|
||||
break;
|
||||
|
||||
case UUID_REQUEST_OLD:
|
||||
case UUID_REQUEST:
|
||||
tb_dbg(tb, "%llx: received XDomain UUID request\n", route);
|
||||
ret = tb_xdp_uuid_response(ctl, route, sequence, uuid);
|
||||
break;
|
||||
|
||||
case LINK_STATE_STATUS_REQUEST:
|
||||
tb_dbg(tb, "%llx: received XDomain link state status request\n",
|
||||
route);
|
||||
|
||||
if (xd) {
|
||||
ret = tb_xdp_link_state_status_response(tb, ctl, xd,
|
||||
sequence);
|
||||
} else {
|
||||
tb_xdp_error_response(ctl, route, sequence,
|
||||
ERROR_NOT_READY);
|
||||
}
|
||||
break;
|
||||
|
||||
case LINK_STATE_CHANGE_REQUEST:
|
||||
tb_dbg(tb, "%llx: received XDomain link state change request\n",
|
||||
route);
|
||||
|
||||
if (xd && xd->state == XDOMAIN_STATE_BONDING_UUID_HIGH) {
|
||||
const struct tb_xdp_link_state_change *lsc =
|
||||
(const struct tb_xdp_link_state_change *)pkg;
|
||||
|
||||
ret = tb_xdp_link_state_change_response(ctl, route,
|
||||
sequence, 0);
|
||||
xd->target_link_width = lsc->tlw;
|
||||
queue_delayed_work(tb->wq, &xd->state_work,
|
||||
msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
|
||||
} else {
|
||||
tb_xdp_error_response(ctl, route, sequence,
|
||||
ERROR_NOT_READY);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
tb_dbg(tb, "%llx: unknown XDomain request %#x\n", route, pkg->type);
|
||||
tb_xdp_error_response(ctl, route, sequence,
|
||||
ERROR_NOT_SUPPORTED);
|
||||
break;
|
||||
|
|
@ -1000,32 +1168,38 @@ static int tb_xdomain_update_link_attributes(struct tb_xdomain *xd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void tb_xdomain_get_uuid(struct work_struct *work)
|
||||
static int tb_xdomain_get_uuid(struct tb_xdomain *xd)
|
||||
{
|
||||
struct tb_xdomain *xd = container_of(work, typeof(*xd),
|
||||
get_uuid_work.work);
|
||||
struct tb *tb = xd->tb;
|
||||
uuid_t uuid;
|
||||
u64 route;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&xd->dev, "requesting remote UUID\n");
|
||||
|
||||
ret = tb_xdp_uuid_request(tb->ctl, xd->route, xd->uuid_retries, &uuid);
|
||||
ret = tb_xdp_uuid_request(tb->ctl, xd->route, xd->state_retries, &uuid,
|
||||
&route);
|
||||
if (ret < 0) {
|
||||
if (xd->uuid_retries-- > 0) {
|
||||
if (xd->state_retries-- > 0) {
|
||||
dev_dbg(&xd->dev, "failed to request UUID, retrying\n");
|
||||
queue_delayed_work(xd->tb->wq, &xd->get_uuid_work,
|
||||
msecs_to_jiffies(100));
|
||||
return -EAGAIN;
|
||||
} else {
|
||||
dev_dbg(&xd->dev, "failed to read remote UUID\n");
|
||||
}
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_dbg(&xd->dev, "got remote UUID %pUb\n", &uuid);
|
||||
|
||||
if (uuid_equal(&uuid, xd->local_uuid))
|
||||
dev_dbg(&xd->dev, "intra-domain loop detected\n");
|
||||
if (uuid_equal(&uuid, xd->local_uuid)) {
|
||||
if (route == xd->route)
|
||||
dev_dbg(&xd->dev, "loop back detected\n");
|
||||
else
|
||||
dev_dbg(&xd->dev, "intra-domain loop detected\n");
|
||||
|
||||
/* Don't bond lanes automatically for loops */
|
||||
xd->bonding_possible = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the UUID is different, there is another domain connected
|
||||
|
|
@ -1035,27 +1209,152 @@ static void tb_xdomain_get_uuid(struct work_struct *work)
|
|||
if (xd->remote_uuid && !uuid_equal(&uuid, xd->remote_uuid)) {
|
||||
dev_dbg(&xd->dev, "remote UUID is different, unplugging\n");
|
||||
xd->is_unplugged = true;
|
||||
return;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* First time fill in the missing UUID */
|
||||
if (!xd->remote_uuid) {
|
||||
xd->remote_uuid = kmemdup(&uuid, sizeof(uuid_t), GFP_KERNEL);
|
||||
if (!xd->remote_uuid)
|
||||
return;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Now we can start the normal properties exchange */
|
||||
queue_delayed_work(xd->tb->wq, &xd->properties_changed_work,
|
||||
msecs_to_jiffies(100));
|
||||
queue_delayed_work(xd->tb->wq, &xd->get_properties_work,
|
||||
msecs_to_jiffies(1000));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tb_xdomain_get_properties(struct work_struct *work)
|
||||
static int tb_xdomain_get_link_status(struct tb_xdomain *xd)
|
||||
{
|
||||
struct tb *tb = xd->tb;
|
||||
u8 slw, tlw, sls, tls;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&xd->dev, "sending link state status request to %pUb\n",
|
||||
xd->remote_uuid);
|
||||
|
||||
ret = tb_xdp_link_state_status_request(tb->ctl, xd->route,
|
||||
xd->state_retries, &slw, &tlw, &sls,
|
||||
&tls);
|
||||
if (ret) {
|
||||
if (ret != -EOPNOTSUPP && xd->state_retries-- > 0) {
|
||||
dev_dbg(&xd->dev,
|
||||
"failed to request remote link status, retrying\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
dev_dbg(&xd->dev, "failed to receive remote link status\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_dbg(&xd->dev, "remote link supports width %#x speed %#x\n", slw, sls);
|
||||
|
||||
if (slw < LANE_ADP_CS_0_SUPPORTED_WIDTH_DUAL) {
|
||||
dev_dbg(&xd->dev, "remote adapter is single lane only\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tb_xdomain_link_state_change(struct tb_xdomain *xd,
|
||||
unsigned int width)
|
||||
{
|
||||
struct tb_switch *sw = tb_to_switch(xd->dev.parent);
|
||||
struct tb_port *port = tb_port_at(xd->route, sw);
|
||||
struct tb *tb = xd->tb;
|
||||
u8 tlw, tls;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (width == 2)
|
||||
tlw = LANE_ADP_CS_1_TARGET_WIDTH_DUAL;
|
||||
else if (width == 1)
|
||||
tlw = LANE_ADP_CS_1_TARGET_WIDTH_SINGLE;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
/* Use the current target speed */
|
||||
ret = tb_port_read(port, &val, TB_CFG_PORT, port->cap_phy + LANE_ADP_CS_1, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
tls = val & LANE_ADP_CS_1_TARGET_SPEED_MASK;
|
||||
|
||||
dev_dbg(&xd->dev, "sending link state change request with width %#x speed %#x\n",
|
||||
tlw, tls);
|
||||
|
||||
ret = tb_xdp_link_state_change_request(tb->ctl, xd->route,
|
||||
xd->state_retries, tlw, tls);
|
||||
if (ret) {
|
||||
if (ret != -EOPNOTSUPP && xd->state_retries-- > 0) {
|
||||
dev_dbg(&xd->dev,
|
||||
"failed to change remote link state, retrying\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
dev_err(&xd->dev, "failed request link state change, aborting\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_dbg(&xd->dev, "received link state change response\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tb_xdomain_bond_lanes_uuid_high(struct tb_xdomain *xd)
|
||||
{
|
||||
struct tb_port *port;
|
||||
int ret, width;
|
||||
|
||||
if (xd->target_link_width == LANE_ADP_CS_1_TARGET_WIDTH_SINGLE) {
|
||||
width = 1;
|
||||
} else if (xd->target_link_width == LANE_ADP_CS_1_TARGET_WIDTH_DUAL) {
|
||||
width = 2;
|
||||
} else {
|
||||
if (xd->state_retries-- > 0) {
|
||||
dev_dbg(&xd->dev,
|
||||
"link state change request not received yet, retrying\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
dev_dbg(&xd->dev, "timeout waiting for link change request\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
port = tb_port_at(xd->route, tb_xdomain_parent(xd));
|
||||
|
||||
/*
|
||||
* We can't use tb_xdomain_lane_bonding_enable() here because it
|
||||
* is the other side that initiates lane bonding. So here we
|
||||
* just set the width to both lane adapters and wait for the
|
||||
* link to transition bonded.
|
||||
*/
|
||||
ret = tb_port_set_link_width(port->dual_link_port, width);
|
||||
if (ret) {
|
||||
tb_port_warn(port->dual_link_port,
|
||||
"failed to set link width to %d\n", width);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tb_port_set_link_width(port, width);
|
||||
if (ret) {
|
||||
tb_port_warn(port, "failed to set link width to %d\n", width);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tb_port_wait_for_link_width(port, width, XDOMAIN_BONDING_TIMEOUT);
|
||||
if (ret) {
|
||||
dev_warn(&xd->dev, "error waiting for link width to become %d\n",
|
||||
width);
|
||||
return ret;
|
||||
}
|
||||
|
||||
port->bonded = width == 2;
|
||||
port->dual_link_port->bonded = width == 2;
|
||||
|
||||
tb_port_update_credits(port);
|
||||
tb_xdomain_update_link_attributes(xd);
|
||||
|
||||
dev_dbg(&xd->dev, "lane bonding %sabled\n", width == 2 ? "en" : "dis");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tb_xdomain_get_properties(struct tb_xdomain *xd)
|
||||
{
|
||||
struct tb_xdomain *xd = container_of(work, typeof(*xd),
|
||||
get_properties_work.work);
|
||||
struct tb_property_dir *dir;
|
||||
struct tb *tb = xd->tb;
|
||||
bool update = false;
|
||||
|
|
@ -1066,34 +1365,35 @@ static void tb_xdomain_get_properties(struct work_struct *work)
|
|||
dev_dbg(&xd->dev, "requesting remote properties\n");
|
||||
|
||||
ret = tb_xdp_properties_request(tb->ctl, xd->route, xd->local_uuid,
|
||||
xd->remote_uuid, xd->properties_retries,
|
||||
xd->remote_uuid, xd->state_retries,
|
||||
&block, &gen);
|
||||
if (ret < 0) {
|
||||
if (xd->properties_retries-- > 0) {
|
||||
if (xd->state_retries-- > 0) {
|
||||
dev_dbg(&xd->dev,
|
||||
"failed to request remote properties, retrying\n");
|
||||
queue_delayed_work(xd->tb->wq, &xd->get_properties_work,
|
||||
msecs_to_jiffies(1000));
|
||||
return -EAGAIN;
|
||||
} else {
|
||||
/* Give up now */
|
||||
dev_err(&xd->dev,
|
||||
"failed read XDomain properties from %pUb\n",
|
||||
xd->remote_uuid);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
xd->properties_retries = XDOMAIN_PROPERTIES_RETRIES;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&xd->lock);
|
||||
|
||||
/* Only accept newer generation properties */
|
||||
if (xd->remote_properties && gen <= xd->remote_property_block_gen)
|
||||
if (xd->remote_properties && gen <= xd->remote_property_block_gen) {
|
||||
ret = 0;
|
||||
goto err_free_block;
|
||||
}
|
||||
|
||||
dir = tb_property_parse_dir(block, ret);
|
||||
if (!dir) {
|
||||
dev_err(&xd->dev, "failed to parse XDomain properties\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_free_block;
|
||||
}
|
||||
|
||||
|
|
@ -1124,9 +1424,16 @@ static void tb_xdomain_get_properties(struct work_struct *work)
|
|||
* registered, we notify the userspace that it has changed.
|
||||
*/
|
||||
if (!update) {
|
||||
struct tb_port *port;
|
||||
|
||||
/* Now disable lane 1 if bonding was not enabled */
|
||||
port = tb_port_at(xd->route, tb_xdomain_parent(xd));
|
||||
if (!port->bonded)
|
||||
tb_port_disable(port->dual_link_port);
|
||||
|
||||
if (device_add(&xd->dev)) {
|
||||
dev_err(&xd->dev, "failed to add XDomain device\n");
|
||||
return;
|
||||
return -ENODEV;
|
||||
}
|
||||
dev_info(&xd->dev, "new host found, vendor=%#x device=%#x\n",
|
||||
xd->vendor, xd->device);
|
||||
|
|
@ -1138,13 +1445,193 @@ static void tb_xdomain_get_properties(struct work_struct *work)
|
|||
}
|
||||
|
||||
enumerate_services(xd);
|
||||
return;
|
||||
return 0;
|
||||
|
||||
err_free_dir:
|
||||
tb_property_free_dir(dir);
|
||||
err_free_block:
|
||||
kfree(block);
|
||||
mutex_unlock(&xd->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tb_xdomain_queue_uuid(struct tb_xdomain *xd)
|
||||
{
|
||||
xd->state = XDOMAIN_STATE_UUID;
|
||||
xd->state_retries = XDOMAIN_RETRIES;
|
||||
queue_delayed_work(xd->tb->wq, &xd->state_work,
|
||||
msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
|
||||
}
|
||||
|
||||
static void tb_xdomain_queue_link_status(struct tb_xdomain *xd)
|
||||
{
|
||||
xd->state = XDOMAIN_STATE_LINK_STATUS;
|
||||
xd->state_retries = XDOMAIN_RETRIES;
|
||||
queue_delayed_work(xd->tb->wq, &xd->state_work,
|
||||
msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
|
||||
}
|
||||
|
||||
static void tb_xdomain_queue_link_status2(struct tb_xdomain *xd)
|
||||
{
|
||||
xd->state = XDOMAIN_STATE_LINK_STATUS2;
|
||||
xd->state_retries = XDOMAIN_RETRIES;
|
||||
queue_delayed_work(xd->tb->wq, &xd->state_work,
|
||||
msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
|
||||
}
|
||||
|
||||
static void tb_xdomain_queue_bonding(struct tb_xdomain *xd)
|
||||
{
|
||||
if (memcmp(xd->local_uuid, xd->remote_uuid, UUID_SIZE) > 0) {
|
||||
dev_dbg(&xd->dev, "we have higher UUID, other side bonds the lanes\n");
|
||||
xd->state = XDOMAIN_STATE_BONDING_UUID_HIGH;
|
||||
} else {
|
||||
dev_dbg(&xd->dev, "we have lower UUID, bonding lanes\n");
|
||||
xd->state = XDOMAIN_STATE_LINK_STATE_CHANGE;
|
||||
}
|
||||
|
||||
xd->state_retries = XDOMAIN_RETRIES;
|
||||
queue_delayed_work(xd->tb->wq, &xd->state_work,
|
||||
msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
|
||||
}
|
||||
|
||||
static void tb_xdomain_queue_bonding_uuid_low(struct tb_xdomain *xd)
|
||||
{
|
||||
xd->state = XDOMAIN_STATE_BONDING_UUID_LOW;
|
||||
xd->state_retries = XDOMAIN_RETRIES;
|
||||
queue_delayed_work(xd->tb->wq, &xd->state_work,
|
||||
msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
|
||||
}
|
||||
|
||||
static void tb_xdomain_queue_properties(struct tb_xdomain *xd)
|
||||
{
|
||||
xd->state = XDOMAIN_STATE_PROPERTIES;
|
||||
xd->state_retries = XDOMAIN_RETRIES;
|
||||
queue_delayed_work(xd->tb->wq, &xd->state_work,
|
||||
msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
|
||||
}
|
||||
|
||||
static void tb_xdomain_queue_properties_changed(struct tb_xdomain *xd)
|
||||
{
|
||||
xd->properties_changed_retries = XDOMAIN_RETRIES;
|
||||
queue_delayed_work(xd->tb->wq, &xd->properties_changed_work,
|
||||
msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
|
||||
}
|
||||
|
||||
static void tb_xdomain_state_work(struct work_struct *work)
|
||||
{
|
||||
struct tb_xdomain *xd = container_of(work, typeof(*xd), state_work.work);
|
||||
int ret, state = xd->state;
|
||||
|
||||
if (WARN_ON_ONCE(state < XDOMAIN_STATE_INIT ||
|
||||
state > XDOMAIN_STATE_ERROR))
|
||||
return;
|
||||
|
||||
dev_dbg(&xd->dev, "running state %s\n", state_names[state]);
|
||||
|
||||
switch (state) {
|
||||
case XDOMAIN_STATE_INIT:
|
||||
if (xd->needs_uuid) {
|
||||
tb_xdomain_queue_uuid(xd);
|
||||
} else {
|
||||
tb_xdomain_queue_properties_changed(xd);
|
||||
tb_xdomain_queue_properties(xd);
|
||||
}
|
||||
break;
|
||||
|
||||
case XDOMAIN_STATE_UUID:
|
||||
ret = tb_xdomain_get_uuid(xd);
|
||||
if (ret) {
|
||||
if (ret == -EAGAIN)
|
||||
goto retry_state;
|
||||
xd->state = XDOMAIN_STATE_ERROR;
|
||||
} else {
|
||||
tb_xdomain_queue_properties_changed(xd);
|
||||
if (xd->bonding_possible)
|
||||
tb_xdomain_queue_link_status(xd);
|
||||
else
|
||||
tb_xdomain_queue_properties(xd);
|
||||
}
|
||||
break;
|
||||
|
||||
case XDOMAIN_STATE_LINK_STATUS:
|
||||
ret = tb_xdomain_get_link_status(xd);
|
||||
if (ret) {
|
||||
if (ret == -EAGAIN)
|
||||
goto retry_state;
|
||||
|
||||
/*
|
||||
* If any of the lane bonding states fail we skip
|
||||
* bonding completely and try to continue from
|
||||
* reading properties.
|
||||
*/
|
||||
tb_xdomain_queue_properties(xd);
|
||||
} else {
|
||||
tb_xdomain_queue_bonding(xd);
|
||||
}
|
||||
break;
|
||||
|
||||
case XDOMAIN_STATE_LINK_STATE_CHANGE:
|
||||
ret = tb_xdomain_link_state_change(xd, 2);
|
||||
if (ret) {
|
||||
if (ret == -EAGAIN)
|
||||
goto retry_state;
|
||||
tb_xdomain_queue_properties(xd);
|
||||
} else {
|
||||
tb_xdomain_queue_link_status2(xd);
|
||||
}
|
||||
break;
|
||||
|
||||
case XDOMAIN_STATE_LINK_STATUS2:
|
||||
ret = tb_xdomain_get_link_status(xd);
|
||||
if (ret) {
|
||||
if (ret == -EAGAIN)
|
||||
goto retry_state;
|
||||
tb_xdomain_queue_properties(xd);
|
||||
} else {
|
||||
tb_xdomain_queue_bonding_uuid_low(xd);
|
||||
}
|
||||
break;
|
||||
|
||||
case XDOMAIN_STATE_BONDING_UUID_LOW:
|
||||
tb_xdomain_lane_bonding_enable(xd);
|
||||
tb_xdomain_queue_properties(xd);
|
||||
break;
|
||||
|
||||
case XDOMAIN_STATE_BONDING_UUID_HIGH:
|
||||
if (tb_xdomain_bond_lanes_uuid_high(xd) == -EAGAIN)
|
||||
goto retry_state;
|
||||
tb_xdomain_queue_properties(xd);
|
||||
break;
|
||||
|
||||
case XDOMAIN_STATE_PROPERTIES:
|
||||
ret = tb_xdomain_get_properties(xd);
|
||||
if (ret) {
|
||||
if (ret == -EAGAIN)
|
||||
goto retry_state;
|
||||
xd->state = XDOMAIN_STATE_ERROR;
|
||||
} else {
|
||||
xd->state = XDOMAIN_STATE_ENUMERATED;
|
||||
}
|
||||
break;
|
||||
|
||||
case XDOMAIN_STATE_ENUMERATED:
|
||||
tb_xdomain_queue_properties(xd);
|
||||
break;
|
||||
|
||||
case XDOMAIN_STATE_ERROR:
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_warn(&xd->dev, "unexpected state %d\n", state);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
retry_state:
|
||||
queue_delayed_work(xd->tb->wq, &xd->state_work,
|
||||
msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
|
||||
}
|
||||
|
||||
static void tb_xdomain_properties_changed(struct work_struct *work)
|
||||
|
|
@ -1163,13 +1650,13 @@ static void tb_xdomain_properties_changed(struct work_struct *work)
|
|||
"failed to send properties changed notification, retrying\n");
|
||||
queue_delayed_work(xd->tb->wq,
|
||||
&xd->properties_changed_work,
|
||||
msecs_to_jiffies(1000));
|
||||
msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
|
||||
}
|
||||
dev_err(&xd->dev, "failed to send properties changed notification\n");
|
||||
return;
|
||||
}
|
||||
|
||||
xd->properties_changed_retries = XDOMAIN_PROPERTIES_CHANGED_RETRIES;
|
||||
xd->properties_changed_retries = XDOMAIN_RETRIES;
|
||||
}
|
||||
|
||||
static ssize_t device_show(struct device *dev, struct device_attribute *attr,
|
||||
|
|
@ -1304,31 +1791,17 @@ static void tb_xdomain_release(struct device *dev)
|
|||
|
||||
static void start_handshake(struct tb_xdomain *xd)
|
||||
{
|
||||
xd->uuid_retries = XDOMAIN_UUID_RETRIES;
|
||||
xd->properties_retries = XDOMAIN_PROPERTIES_RETRIES;
|
||||
xd->properties_changed_retries = XDOMAIN_PROPERTIES_CHANGED_RETRIES;
|
||||
|
||||
if (xd->needs_uuid) {
|
||||
queue_delayed_work(xd->tb->wq, &xd->get_uuid_work,
|
||||
msecs_to_jiffies(100));
|
||||
} else {
|
||||
/* Start exchanging properties with the other host */
|
||||
queue_delayed_work(xd->tb->wq, &xd->properties_changed_work,
|
||||
msecs_to_jiffies(100));
|
||||
queue_delayed_work(xd->tb->wq, &xd->get_properties_work,
|
||||
msecs_to_jiffies(1000));
|
||||
}
|
||||
xd->state = XDOMAIN_STATE_INIT;
|
||||
queue_delayed_work(xd->tb->wq, &xd->state_work,
|
||||
msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
|
||||
}
|
||||
|
||||
static void stop_handshake(struct tb_xdomain *xd)
|
||||
{
|
||||
xd->uuid_retries = 0;
|
||||
xd->properties_retries = 0;
|
||||
xd->properties_changed_retries = 0;
|
||||
|
||||
cancel_delayed_work_sync(&xd->get_uuid_work);
|
||||
cancel_delayed_work_sync(&xd->get_properties_work);
|
||||
cancel_delayed_work_sync(&xd->properties_changed_work);
|
||||
cancel_delayed_work_sync(&xd->state_work);
|
||||
xd->properties_changed_retries = 0;
|
||||
xd->state_retries = 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused tb_xdomain_suspend(struct device *dev)
|
||||
|
|
@ -1389,8 +1862,7 @@ struct tb_xdomain *tb_xdomain_alloc(struct tb *tb, struct device *parent,
|
|||
ida_init(&xd->in_hopids);
|
||||
ida_init(&xd->out_hopids);
|
||||
mutex_init(&xd->lock);
|
||||
INIT_DELAYED_WORK(&xd->get_uuid_work, tb_xdomain_get_uuid);
|
||||
INIT_DELAYED_WORK(&xd->get_properties_work, tb_xdomain_get_properties);
|
||||
INIT_DELAYED_WORK(&xd->state_work, tb_xdomain_state_work);
|
||||
INIT_DELAYED_WORK(&xd->properties_changed_work,
|
||||
tb_xdomain_properties_changed);
|
||||
|
||||
|
|
@ -1405,6 +1877,7 @@ struct tb_xdomain *tb_xdomain_alloc(struct tb *tb, struct device *parent,
|
|||
goto err_free_local_uuid;
|
||||
} else {
|
||||
xd->needs_uuid = true;
|
||||
xd->bonding_possible = !!down->dual_link_port;
|
||||
}
|
||||
|
||||
device_initialize(&xd->dev);
|
||||
|
|
@ -1523,9 +1996,9 @@ int tb_xdomain_lane_bonding_enable(struct tb_xdomain *xd)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = tb_port_wait_for_link_width(port, 2, 100);
|
||||
ret = tb_port_wait_for_link_width(port, 2, XDOMAIN_BONDING_TIMEOUT);
|
||||
if (ret) {
|
||||
tb_port_warn(port, "timeout enabling lane bonding\n");
|
||||
tb_port_warn(port, "failed to enable lane bonding\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1091,7 +1091,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
|
|||
snd_buf_bytes - (snd_buf_bytes % instance->tx_channel.stride));
|
||||
|
||||
/* rx buffer size must be a positive multiple of the endpoint maxpacket */
|
||||
maxpacket = usb_maxpacket(usb_dev, instance->rx_channel.endpoint, 0);
|
||||
maxpacket = usb_maxpacket(usb_dev, instance->rx_channel.endpoint);
|
||||
|
||||
if ((maxpacket < 1) || (maxpacket > UDSL_MAX_BUF_SIZE)) {
|
||||
dev_err(dev, "%s: invalid endpoint %02x!\n", __func__,
|
||||
|
|
|
|||
|
|
@ -189,14 +189,12 @@ static int c67x00_drv_remove(struct platform_device *pdev)
|
|||
c67x00_ll_release(c67x00);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (res)
|
||||
free_irq(res->start, c67x00);
|
||||
free_irq(res->start, c67x00);
|
||||
|
||||
iounmap(c67x00->hpi.base);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res)
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
|
||||
kfree(c67x00);
|
||||
|
||||
|
|
|
|||
|
|
@ -655,7 +655,7 @@ static int c67x00_add_data_urb(struct c67x00_hcd *c67x00, struct urb *urb)
|
|||
usb_pipeout(urb->pipe));
|
||||
remaining = urb->transfer_buffer_length - urb->actual_length;
|
||||
|
||||
maxps = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
|
||||
maxps = usb_maxpacket(urb->dev, urb->pipe);
|
||||
|
||||
need_empty = (urb->transfer_flags & URB_ZERO_PACKET) &&
|
||||
usb_pipeout(urb->pipe) && !(remaining % maxps);
|
||||
|
|
@ -866,7 +866,7 @@ static inline int c67x00_end_of_data(struct c67x00_td *td)
|
|||
if (unlikely(!act_bytes))
|
||||
return 1; /* This was an empty packet */
|
||||
|
||||
maxps = usb_maxpacket(td_udev(td), td->pipe, usb_pipeout(td->pipe));
|
||||
maxps = usb_maxpacket(td_udev(td), td->pipe);
|
||||
|
||||
if (unlikely(act_bytes < maxps))
|
||||
return 1; /* Smaller then full packet */
|
||||
|
|
|
|||
|
|
@ -2038,7 +2038,7 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
|
|||
u8 mult = 0;
|
||||
int ret;
|
||||
|
||||
buffering = CDNS3_EP_BUF_SIZE - 1;
|
||||
buffering = priv_dev->ep_buf_size - 1;
|
||||
|
||||
cdns3_configure_dmult(priv_dev, priv_ep);
|
||||
|
||||
|
|
@ -2057,7 +2057,7 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
|
|||
break;
|
||||
default:
|
||||
ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_ISOC);
|
||||
mult = CDNS3_EP_ISO_HS_MULT - 1;
|
||||
mult = priv_dev->ep_iso_burst - 1;
|
||||
buffering = mult + 1;
|
||||
}
|
||||
|
||||
|
|
@ -2073,14 +2073,14 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
|
|||
mult = 0;
|
||||
max_packet_size = 1024;
|
||||
if (priv_ep->type == USB_ENDPOINT_XFER_ISOC) {
|
||||
maxburst = CDNS3_EP_ISO_SS_BURST - 1;
|
||||
maxburst = priv_dev->ep_iso_burst - 1;
|
||||
buffering = (mult + 1) *
|
||||
(maxburst + 1);
|
||||
|
||||
if (priv_ep->interval > 1)
|
||||
buffering++;
|
||||
} else {
|
||||
maxburst = CDNS3_EP_BUF_SIZE - 1;
|
||||
maxburst = priv_dev->ep_buf_size - 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
@ -2095,6 +2095,10 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
|
|||
else
|
||||
priv_ep->trb_burst_size = 16;
|
||||
|
||||
mult = min_t(u8, mult, EP_CFG_MULT_MAX);
|
||||
buffering = min_t(u8, buffering, EP_CFG_BUFFERING_MAX);
|
||||
maxburst = min_t(u8, maxburst, EP_CFG_MAXBURST_MAX);
|
||||
|
||||
/* onchip buffer is only allocated before configuration */
|
||||
if (!priv_dev->hw_configured_flag) {
|
||||
ret = cdns3_ep_onchip_buffer_reserve(priv_dev, buffering + 1,
|
||||
|
|
@ -2961,6 +2965,40 @@ static int cdns3_gadget_udc_stop(struct usb_gadget *gadget)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cdns3_gadget_check_config - ensure cdns3 can support the USB configuration
|
||||
* @gadget: pointer to the USB gadget
|
||||
*
|
||||
* Used to record the maximum number of endpoints being used in a USB composite
|
||||
* device. (across all configurations) This is to be used in the calculation
|
||||
* of the TXFIFO sizes when resizing internal memory for individual endpoints.
|
||||
* It will help ensured that the resizing logic reserves enough space for at
|
||||
* least one max packet.
|
||||
*/
|
||||
static int cdns3_gadget_check_config(struct usb_gadget *gadget)
|
||||
{
|
||||
struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
|
||||
struct usb_ep *ep;
|
||||
int n_in = 0;
|
||||
int total;
|
||||
|
||||
list_for_each_entry(ep, &gadget->ep_list, ep_list) {
|
||||
if (ep->claimed && (ep->address & USB_DIR_IN))
|
||||
n_in++;
|
||||
}
|
||||
|
||||
/* 2KB are reserved for EP0, 1KB for out*/
|
||||
total = 2 + n_in + 1;
|
||||
|
||||
if (total > priv_dev->onchip_buffers)
|
||||
return -ENOMEM;
|
||||
|
||||
priv_dev->ep_buf_size = priv_dev->ep_iso_burst =
|
||||
(priv_dev->onchip_buffers - 2) / (n_in + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct usb_gadget_ops cdns3_gadget_ops = {
|
||||
.get_frame = cdns3_gadget_get_frame,
|
||||
.wakeup = cdns3_gadget_wakeup,
|
||||
|
|
@ -2969,6 +3007,7 @@ static const struct usb_gadget_ops cdns3_gadget_ops = {
|
|||
.udc_start = cdns3_gadget_udc_start,
|
||||
.udc_stop = cdns3_gadget_udc_stop,
|
||||
.match_ep = cdns3_gadget_match_ep,
|
||||
.check_config = cdns3_gadget_check_config,
|
||||
};
|
||||
|
||||
static void cdns3_free_all_eps(struct cdns3_device *priv_dev)
|
||||
|
|
|
|||
|
|
@ -562,15 +562,18 @@ struct cdns3_usb_regs {
|
|||
/* Max burst size (used only in SS mode). */
|
||||
#define EP_CFG_MAXBURST_MASK GENMASK(11, 8)
|
||||
#define EP_CFG_MAXBURST(p) (((p) << 8) & EP_CFG_MAXBURST_MASK)
|
||||
#define EP_CFG_MAXBURST_MAX 15
|
||||
/* ISO max burst. */
|
||||
#define EP_CFG_MULT_MASK GENMASK(15, 14)
|
||||
#define EP_CFG_MULT(p) (((p) << 14) & EP_CFG_MULT_MASK)
|
||||
#define EP_CFG_MULT_MAX 2
|
||||
/* ISO max burst. */
|
||||
#define EP_CFG_MAXPKTSIZE_MASK GENMASK(26, 16)
|
||||
#define EP_CFG_MAXPKTSIZE(p) (((p) << 16) & EP_CFG_MAXPKTSIZE_MASK)
|
||||
/* Max number of buffered packets. */
|
||||
#define EP_CFG_BUFFERING_MASK GENMASK(31, 27)
|
||||
#define EP_CFG_BUFFERING(p) (((p) << 27) & EP_CFG_BUFFERING_MASK)
|
||||
#define EP_CFG_BUFFERING_MAX 15
|
||||
|
||||
/* EP_CMD - bitmasks */
|
||||
/* Endpoint reset. */
|
||||
|
|
@ -1094,9 +1097,6 @@ struct cdns3_trb {
|
|||
#define CDNS3_ENDPOINTS_MAX_COUNT 32
|
||||
#define CDNS3_EP_ZLP_BUF_SIZE 1024
|
||||
|
||||
#define CDNS3_EP_BUF_SIZE 4 /* KB */
|
||||
#define CDNS3_EP_ISO_HS_MULT 3
|
||||
#define CDNS3_EP_ISO_SS_BURST 3
|
||||
#define CDNS3_MAX_NUM_DESCMISS_BUF 32
|
||||
#define CDNS3_DESCMIS_BUF_SIZE 2048 /* Bytes */
|
||||
#define CDNS3_WA2_NUM_BUFFERS 128
|
||||
|
|
@ -1333,6 +1333,9 @@ struct cdns3_device {
|
|||
/*in KB */
|
||||
u16 onchip_buffers;
|
||||
u16 onchip_used_size;
|
||||
|
||||
u16 ep_buf_size;
|
||||
u16 ep_iso_burst;
|
||||
};
|
||||
|
||||
void cdns3_set_register_bit(void __iomem *ptr, u32 mask);
|
||||
|
|
|
|||
|
|
@ -228,8 +228,6 @@ static char *usb_dump_interface(int speed, char *start, char *end,
|
|||
|
||||
start = usb_dump_interface_descriptor(start, end, intfc, iface, setno);
|
||||
for (i = 0; i < desc->desc.bNumEndpoints; i++) {
|
||||
if (start > end)
|
||||
return start;
|
||||
start = usb_dump_endpoint_descriptor(speed,
|
||||
start, end, &desc->endpoint[i].desc);
|
||||
}
|
||||
|
|
@ -302,8 +300,6 @@ static char *usb_dump_config(int speed, char *start, char *end,
|
|||
intfc = config->intf_cache[i];
|
||||
interface = config->interface[i];
|
||||
for (j = 0; j < intfc->num_altsetting; j++) {
|
||||
if (start > end)
|
||||
return start;
|
||||
start = usb_dump_interface(speed,
|
||||
start, end, intfc, interface, j);
|
||||
}
|
||||
|
|
@ -369,19 +365,11 @@ static char *usb_dump_desc(char *start, char *end, struct usb_device *dev)
|
|||
{
|
||||
int i;
|
||||
|
||||
if (start > end)
|
||||
return start;
|
||||
|
||||
start = usb_dump_device_descriptor(start, end, &dev->descriptor);
|
||||
|
||||
if (start > end)
|
||||
return start;
|
||||
|
||||
start = usb_dump_device_strings(start, end, dev);
|
||||
|
||||
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
|
||||
if (start > end)
|
||||
return start;
|
||||
start = usb_dump_config(dev->speed,
|
||||
start, end, dev->config + i,
|
||||
/* active ? */
|
||||
|
|
@ -390,41 +378,6 @@ static char *usb_dump_desc(char *start, char *end, struct usb_device *dev)
|
|||
return start;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PROC_EXTRA /* TBD: may want to add this code later */
|
||||
|
||||
static char *usb_dump_hub_descriptor(char *start, char *end,
|
||||
const struct usb_hub_descriptor *desc)
|
||||
{
|
||||
int leng = USB_DT_HUB_NONVAR_SIZE;
|
||||
unsigned char *ptr = (unsigned char *)desc;
|
||||
|
||||
if (start > end)
|
||||
return start;
|
||||
start += sprintf(start, "Interface:");
|
||||
while (leng && start <= end) {
|
||||
start += sprintf(start, " %02x", *ptr);
|
||||
ptr++; leng--;
|
||||
}
|
||||
*start++ = '\n';
|
||||
return start;
|
||||
}
|
||||
|
||||
static char *usb_dump_string(char *start, char *end,
|
||||
const struct usb_device *dev, char *id, int index)
|
||||
{
|
||||
if (start > end)
|
||||
return start;
|
||||
start += sprintf(start, "Interface:");
|
||||
if (index <= dev->maxstring && dev->stringindex &&
|
||||
dev->stringindex[index])
|
||||
start += sprintf(start, "%s: %.100s ", id,
|
||||
dev->stringindex[index]);
|
||||
return start;
|
||||
}
|
||||
|
||||
#endif /* PROC_EXTRA */
|
||||
|
||||
/*****************************************************************/
|
||||
|
||||
/* This is a recursive function. Parameters:
|
||||
|
|
|
|||
|
|
@ -1533,22 +1533,23 @@ static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
|
|||
{
|
||||
int w;
|
||||
|
||||
/* Remote wakeup is needed only when we actually go to sleep.
|
||||
* For things like FREEZE and QUIESCE, if the device is already
|
||||
* autosuspended then its current wakeup setting is okay.
|
||||
/*
|
||||
* For FREEZE/QUIESCE, disable remote wakeups so no interrupts get
|
||||
* generated.
|
||||
*/
|
||||
if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_QUIESCE) {
|
||||
if (udev->state != USB_STATE_SUSPENDED)
|
||||
udev->do_remote_wakeup = 0;
|
||||
return;
|
||||
w = 0;
|
||||
|
||||
} else {
|
||||
/*
|
||||
* Enable remote wakeup if it is allowed, even if no interface
|
||||
* drivers actually want it.
|
||||
*/
|
||||
w = device_may_wakeup(&udev->dev);
|
||||
}
|
||||
|
||||
/* Enable remote wakeup if it is allowed, even if no interface drivers
|
||||
* actually want it.
|
||||
*/
|
||||
w = device_may_wakeup(&udev->dev);
|
||||
|
||||
/* If the device is autosuspended with the wrong wakeup setting,
|
||||
/*
|
||||
* If the device is autosuspended with the wrong wakeup setting,
|
||||
* autoresume now so the setting can be changed.
|
||||
*/
|
||||
if (udev->state == USB_STATE_SUSPENDED && w != udev->do_remote_wakeup)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
#ifdef CONFIG_PPC_PMAC
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pmac_feature.h>
|
||||
#include <asm/prom.h>
|
||||
#endif
|
||||
|
||||
#include "usb.h"
|
||||
|
|
@ -616,10 +615,10 @@ const struct dev_pm_ops usb_hcd_pci_pm_ops = {
|
|||
.suspend_noirq = hcd_pci_suspend_noirq,
|
||||
.resume_noirq = hcd_pci_resume_noirq,
|
||||
.resume = hcd_pci_resume,
|
||||
.freeze = check_root_hub_suspended,
|
||||
.freeze = hcd_pci_suspend,
|
||||
.freeze_noirq = check_root_hub_suspended,
|
||||
.thaw_noirq = NULL,
|
||||
.thaw = NULL,
|
||||
.thaw = hcd_pci_resume,
|
||||
.poweroff = hcd_pci_suspend,
|
||||
.poweroff_noirq = hcd_pci_suspend_noirq,
|
||||
.restore_noirq = hcd_pci_resume_noirq,
|
||||
|
|
|
|||
|
|
@ -2816,6 +2816,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
|||
{
|
||||
int retval;
|
||||
struct usb_device *rhdev;
|
||||
struct usb_hcd *shared_hcd;
|
||||
|
||||
if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) {
|
||||
hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
|
||||
|
|
@ -2976,13 +2977,26 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
|||
goto err_hcd_driver_start;
|
||||
}
|
||||
|
||||
/* starting here, usbcore will pay attention to this root hub */
|
||||
retval = register_root_hub(hcd);
|
||||
if (retval != 0)
|
||||
goto err_register_root_hub;
|
||||
/* starting here, usbcore will pay attention to the shared HCD roothub */
|
||||
shared_hcd = hcd->shared_hcd;
|
||||
if (!usb_hcd_is_primary_hcd(hcd) && shared_hcd && HCD_DEFER_RH_REGISTER(shared_hcd)) {
|
||||
retval = register_root_hub(shared_hcd);
|
||||
if (retval != 0)
|
||||
goto err_register_root_hub;
|
||||
|
||||
if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
|
||||
usb_hcd_poll_rh_status(hcd);
|
||||
if (shared_hcd->uses_new_polling && HCD_POLL_RH(shared_hcd))
|
||||
usb_hcd_poll_rh_status(shared_hcd);
|
||||
}
|
||||
|
||||
/* starting here, usbcore will pay attention to this root hub */
|
||||
if (!HCD_DEFER_RH_REGISTER(hcd)) {
|
||||
retval = register_root_hub(hcd);
|
||||
if (retval != 0)
|
||||
goto err_register_root_hub;
|
||||
|
||||
if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
|
||||
usb_hcd_poll_rh_status(hcd);
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
||||
|
|
@ -3020,6 +3034,7 @@ EXPORT_SYMBOL_GPL(usb_add_hcd);
|
|||
void usb_remove_hcd(struct usb_hcd *hcd)
|
||||
{
|
||||
struct usb_device *rhdev = hcd->self.root_hub;
|
||||
bool rh_registered;
|
||||
|
||||
dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
|
||||
|
||||
|
|
@ -3030,6 +3045,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
|
|||
|
||||
dev_dbg(hcd->self.controller, "roothub graceful disconnect\n");
|
||||
spin_lock_irq (&hcd_root_hub_lock);
|
||||
rh_registered = hcd->rh_registered;
|
||||
hcd->rh_registered = 0;
|
||||
spin_unlock_irq (&hcd_root_hub_lock);
|
||||
|
||||
|
|
@ -3039,7 +3055,8 @@ void usb_remove_hcd(struct usb_hcd *hcd)
|
|||
cancel_work_sync(&hcd->died_work);
|
||||
|
||||
mutex_lock(&usb_bus_idr_lock);
|
||||
usb_disconnect(&rhdev); /* Sets rhdev to NULL */
|
||||
if (rh_registered)
|
||||
usb_disconnect(&rhdev); /* Sets rhdev to NULL */
|
||||
mutex_unlock(&usb_bus_idr_lock);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1635,7 +1635,7 @@ static int hub_configure(struct usb_hub *hub,
|
|||
* maxpktsize is defined in hcd.c's fake endpoint descriptors
|
||||
* to be big enough for at least USB_MAXCHILDREN ports. */
|
||||
pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress);
|
||||
maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe));
|
||||
maxp = usb_maxpacket(hdev, pipe);
|
||||
|
||||
if (maxp > sizeof(*hub->buffer))
|
||||
maxp = sizeof(*hub->buffer);
|
||||
|
|
@ -5511,7 +5511,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
|
|||
/* Handle notifying userspace about hub over-current events */
|
||||
static void port_over_current_notify(struct usb_port *port_dev)
|
||||
{
|
||||
char *envp[3];
|
||||
char *envp[3] = { NULL, NULL, NULL };
|
||||
struct device *hub_dev;
|
||||
char *port_dev_path;
|
||||
|
||||
|
|
@ -5528,20 +5528,18 @@ static void port_over_current_notify(struct usb_port *port_dev)
|
|||
|
||||
envp[0] = kasprintf(GFP_KERNEL, "OVER_CURRENT_PORT=%s", port_dev_path);
|
||||
if (!envp[0])
|
||||
goto exit_path;
|
||||
goto exit;
|
||||
|
||||
envp[1] = kasprintf(GFP_KERNEL, "OVER_CURRENT_COUNT=%u",
|
||||
port_dev->over_current_count);
|
||||
if (!envp[1])
|
||||
goto exit;
|
||||
|
||||
envp[2] = NULL;
|
||||
kobject_uevent_env(&hub_dev->kobj, KOBJ_CHANGE, envp);
|
||||
|
||||
kfree(envp[1]);
|
||||
exit:
|
||||
kfree(envp[1]);
|
||||
kfree(envp[0]);
|
||||
exit_path:
|
||||
kfree(port_dev_path);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -510,6 +510,9 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|||
/* DJI CineSSD */
|
||||
{ USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM },
|
||||
|
||||
/* DELL USB GEN2 */
|
||||
{ USB_DEVICE(0x413c, 0xb062), .driver_info = USB_QUIRK_NO_LPM | USB_QUIRK_RESET_RESUME },
|
||||
|
||||
/* VCOM device */
|
||||
{ USB_DEVICE(0x4296, 0x7570), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS },
|
||||
|
||||
|
|
|
|||
|
|
@ -205,8 +205,11 @@ usb_acpi_find_companion_for_device(struct usb_device *udev)
|
|||
struct usb_hub *hub;
|
||||
|
||||
if (!udev->parent) {
|
||||
/* root hub is only child (_ADR=0) under its parent, the HC */
|
||||
adev = ACPI_COMPANION(udev->dev.parent);
|
||||
/*
|
||||
* root hub is only child (_ADR=0) under its parent, the HC.
|
||||
* sysdev pointer is the HC as seen from firmware.
|
||||
*/
|
||||
adev = ACPI_COMPANION(udev->bus->sysdev);
|
||||
return acpi_find_child_device(adev, 0, false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1153,6 +1153,7 @@ static void dwc2_set_turnaround_time(struct dwc2_hsotg *hsotg)
|
|||
int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
|
||||
{
|
||||
u32 usbcfg;
|
||||
u32 otgctl;
|
||||
int retval = 0;
|
||||
|
||||
if ((hsotg->params.speed == DWC2_SPEED_PARAM_FULL ||
|
||||
|
|
@ -1187,6 +1188,14 @@ int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
|
|||
dwc2_writel(hsotg, usbcfg, GUSBCFG);
|
||||
}
|
||||
|
||||
if (!hsotg->params.activate_ingenic_overcurrent_detection) {
|
||||
if (dwc2_is_host_mode(hsotg)) {
|
||||
otgctl = readl(hsotg->regs + GOTGCTL);
|
||||
otgctl |= GOTGCTL_VBVALOEN | GOTGCTL_VBVALOVAL;
|
||||
writel(otgctl, hsotg->regs + GOTGCTL);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -426,6 +426,10 @@ enum dwc2_ep0_state {
|
|||
* detection using GGPIO register.
|
||||
* 0 - Deactivate the external level detection (default)
|
||||
* 1 - Activate the external level detection
|
||||
* @activate_ingenic_overcurrent_detection: Activate Ingenic overcurrent
|
||||
* detection.
|
||||
* 0 - Deactivate the overcurrent detection
|
||||
* 1 - Activate the overcurrent detection (default)
|
||||
* @g_dma: Enables gadget dma usage (default: autodetect).
|
||||
* @g_dma_desc: Enables gadget descriptor DMA (default: autodetect).
|
||||
* @g_rx_fifo_size: The periodic rx fifo size for the device, in
|
||||
|
|
@ -494,6 +498,7 @@ struct dwc2_core_params {
|
|||
u8 hird_threshold;
|
||||
bool activate_stm_fs_transceiver;
|
||||
bool activate_stm_id_vb_detection;
|
||||
bool activate_ingenic_overcurrent_detection;
|
||||
bool ipg_isoc_en;
|
||||
u16 max_packet_count;
|
||||
u32 max_transfer_size;
|
||||
|
|
|
|||
|
|
@ -4544,7 +4544,6 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget,
|
|||
|
||||
WARN_ON(hsotg->driver);
|
||||
|
||||
driver->driver.bus = NULL;
|
||||
hsotg->driver = driver;
|
||||
hsotg->gadget.dev.of_node = hsotg->dev->of_node;
|
||||
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
|
||||
|
|
|
|||
|
|
@ -73,6 +73,47 @@ static void dwc2_set_his_params(struct dwc2_hsotg *hsotg)
|
|||
p->power_down = DWC2_POWER_DOWN_PARAM_NONE;
|
||||
}
|
||||
|
||||
static void dwc2_set_jz4775_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
|
||||
p->otg_caps.hnp_support = false;
|
||||
p->speed = DWC2_SPEED_PARAM_HIGH;
|
||||
p->phy_type = DWC2_PHY_TYPE_PARAM_UTMI;
|
||||
p->phy_utmi_width = 16;
|
||||
p->activate_ingenic_overcurrent_detection =
|
||||
!device_property_read_bool(hsotg->dev, "disable-over-current");
|
||||
}
|
||||
|
||||
static void dwc2_set_x1600_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
|
||||
p->otg_caps.hnp_support = false;
|
||||
p->speed = DWC2_SPEED_PARAM_HIGH;
|
||||
p->host_channels = 16;
|
||||
p->phy_type = DWC2_PHY_TYPE_PARAM_UTMI;
|
||||
p->phy_utmi_width = 16;
|
||||
p->activate_ingenic_overcurrent_detection =
|
||||
!device_property_read_bool(hsotg->dev, "disable-over-current");
|
||||
}
|
||||
|
||||
static void dwc2_set_x2000_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
|
||||
p->otg_caps.hnp_support = false;
|
||||
p->speed = DWC2_SPEED_PARAM_HIGH;
|
||||
p->host_rx_fifo_size = 1024;
|
||||
p->host_nperio_tx_fifo_size = 1024;
|
||||
p->host_perio_tx_fifo_size = 1024;
|
||||
p->host_channels = 16;
|
||||
p->phy_type = DWC2_PHY_TYPE_PARAM_UTMI;
|
||||
p->phy_utmi_width = 16;
|
||||
p->activate_ingenic_overcurrent_detection =
|
||||
!device_property_read_bool(hsotg->dev, "disable-over-current");
|
||||
}
|
||||
|
||||
static void dwc2_set_s3c6400_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
|
|
@ -221,7 +262,14 @@ static void dwc2_set_stm32mp15_hsotg_params(struct dwc2_hsotg *hsotg)
|
|||
|
||||
const struct of_device_id dwc2_of_match_table[] = {
|
||||
{ .compatible = "brcm,bcm2835-usb", .data = dwc2_set_bcm_params },
|
||||
{ .compatible = "hisilicon,hi6220-usb", .data = dwc2_set_his_params },
|
||||
{ .compatible = "hisilicon,hi6220-usb", .data = dwc2_set_his_params },
|
||||
{ .compatible = "ingenic,jz4775-otg", .data = dwc2_set_jz4775_params },
|
||||
{ .compatible = "ingenic,jz4780-otg", .data = dwc2_set_jz4775_params },
|
||||
{ .compatible = "ingenic,x1000-otg", .data = dwc2_set_jz4775_params },
|
||||
{ .compatible = "ingenic,x1600-otg", .data = dwc2_set_x1600_params },
|
||||
{ .compatible = "ingenic,x1700-otg", .data = dwc2_set_x1600_params },
|
||||
{ .compatible = "ingenic,x1830-otg", .data = dwc2_set_x1600_params },
|
||||
{ .compatible = "ingenic,x2000-otg", .data = dwc2_set_x2000_params },
|
||||
{ .compatible = "rockchip,rk3066-usb", .data = dwc2_set_rk_params },
|
||||
{ .compatible = "lantiq,arx100-usb", .data = dwc2_set_ltq_params },
|
||||
{ .compatible = "lantiq,xrx200-usb", .data = dwc2_set_ltq_params },
|
||||
|
|
|
|||
|
|
@ -159,4 +159,13 @@ config USB_DWC3_XILINX
|
|||
This driver handles both ZynqMP and Versal SoC operations.
|
||||
Say 'Y' or 'M' if you have one such device.
|
||||
|
||||
config USB_DWC3_AM62
|
||||
tristate "Texas Instruments AM62 Platforms"
|
||||
depends on ARCH_K3 || COMPILE_TEST
|
||||
default USB_DWC3
|
||||
help
|
||||
Support TI's AM62 platforms with DesignWare Core USB3 IP.
|
||||
The Designware Core USB3 IP is progammed to operate in
|
||||
in USB 2.0 mode only.
|
||||
Say 'Y' or 'M' here if you have one such device
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ endif
|
|||
# and allyesconfig builds.
|
||||
##
|
||||
|
||||
obj-$(CONFIG_USB_DWC3_AM62) += dwc3-am62.o
|
||||
obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o
|
||||
obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o
|
||||
obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/reset.h>
|
||||
|
|
@ -85,7 +86,7 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc)
|
|||
* mode. If the controller supports DRD but the dr_mode is not
|
||||
* specified or set to OTG, then set the mode to peripheral.
|
||||
*/
|
||||
if (mode == USB_DR_MODE_OTG &&
|
||||
if (mode == USB_DR_MODE_OTG && !dwc->edev &&
|
||||
(!IS_ENABLED(CONFIG_USB_ROLE_SWITCH) ||
|
||||
!device_property_read_bool(dwc->dev, "usb-role-switch")) &&
|
||||
!DWC3_VER_IS_PRIOR(DWC3, 330A))
|
||||
|
|
@ -297,6 +298,7 @@ int dwc3_core_soft_reset(struct dwc3 *dwc)
|
|||
udelay(1);
|
||||
} while (--retries);
|
||||
|
||||
dev_warn(dwc->dev, "DWC3 controller soft reset failed.\n");
|
||||
return -ETIMEDOUT;
|
||||
|
||||
done:
|
||||
|
|
@ -342,7 +344,6 @@ static void dwc3_frame_length_adjustment(struct dwc3 *dwc)
|
|||
* from the default, this will set clock period in DWC3_GUCTL
|
||||
* register.
|
||||
* @dwc: Pointer to our controller context structure
|
||||
* @ref_clk_per: reference clock period in ns
|
||||
*/
|
||||
static void dwc3_ref_clk_period(struct dwc3 *dwc)
|
||||
{
|
||||
|
|
@ -964,10 +965,8 @@ static void dwc3_set_incr_burst_type(struct dwc3 *dwc)
|
|||
return;
|
||||
|
||||
vals = kcalloc(ntype, sizeof(u32), GFP_KERNEL);
|
||||
if (!vals) {
|
||||
dev_err(dev, "Error to get memory\n");
|
||||
if (!vals)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get INCR burst type, and parse it */
|
||||
ret = device_property_read_u32_array(dev,
|
||||
|
|
@ -1268,40 +1267,36 @@ static int dwc3_core_get_phy(struct dwc3 *dwc)
|
|||
|
||||
if (IS_ERR(dwc->usb2_phy)) {
|
||||
ret = PTR_ERR(dwc->usb2_phy);
|
||||
if (ret == -ENXIO || ret == -ENODEV) {
|
||||
if (ret == -ENXIO || ret == -ENODEV)
|
||||
dwc->usb2_phy = NULL;
|
||||
} else {
|
||||
else
|
||||
return dev_err_probe(dev, ret, "no usb2 phy configured\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ERR(dwc->usb3_phy)) {
|
||||
ret = PTR_ERR(dwc->usb3_phy);
|
||||
if (ret == -ENXIO || ret == -ENODEV) {
|
||||
if (ret == -ENXIO || ret == -ENODEV)
|
||||
dwc->usb3_phy = NULL;
|
||||
} else {
|
||||
else
|
||||
return dev_err_probe(dev, ret, "no usb3 phy configured\n");
|
||||
}
|
||||
}
|
||||
|
||||
dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
|
||||
if (IS_ERR(dwc->usb2_generic_phy)) {
|
||||
ret = PTR_ERR(dwc->usb2_generic_phy);
|
||||
if (ret == -ENOSYS || ret == -ENODEV) {
|
||||
if (ret == -ENOSYS || ret == -ENODEV)
|
||||
dwc->usb2_generic_phy = NULL;
|
||||
} else {
|
||||
else
|
||||
return dev_err_probe(dev, ret, "no usb2 phy configured\n");
|
||||
}
|
||||
}
|
||||
|
||||
dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
|
||||
if (IS_ERR(dwc->usb3_generic_phy)) {
|
||||
ret = PTR_ERR(dwc->usb3_generic_phy);
|
||||
if (ret == -ENOSYS || ret == -ENODEV) {
|
||||
if (ret == -ENOSYS || ret == -ENODEV)
|
||||
dwc->usb3_generic_phy = NULL;
|
||||
} else {
|
||||
else
|
||||
return dev_err_probe(dev, ret, "no usb3 phy configured\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1633,6 +1628,51 @@ static void dwc3_check_params(struct dwc3 *dwc)
|
|||
}
|
||||
}
|
||||
|
||||
static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
|
||||
{
|
||||
struct device *dev = dwc->dev;
|
||||
struct device_node *np_phy;
|
||||
struct extcon_dev *edev = NULL;
|
||||
const char *name;
|
||||
|
||||
if (device_property_read_bool(dev, "extcon"))
|
||||
return extcon_get_edev_by_phandle(dev, 0);
|
||||
|
||||
/*
|
||||
* Device tree platforms should get extcon via phandle.
|
||||
* On ACPI platforms, we get the name from a device property.
|
||||
* This device property is for kernel internal use only and
|
||||
* is expected to be set by the glue code.
|
||||
*/
|
||||
if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) {
|
||||
edev = extcon_get_extcon_dev(name);
|
||||
if (!edev)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
return edev;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to get an extcon device from the USB PHY controller's "port"
|
||||
* node. Check if it has the "port" node first, to avoid printing the
|
||||
* error message from underlying code, as it's a valid case: extcon
|
||||
* device (and "port" node) may be missing in case of "usb-role-switch"
|
||||
* or OTG mode.
|
||||
*/
|
||||
np_phy = of_parse_phandle(dev->of_node, "phys", 0);
|
||||
if (of_graph_is_present(np_phy)) {
|
||||
struct device_node *np_conn;
|
||||
|
||||
np_conn = of_graph_get_remote_node(np_phy, -1, -1);
|
||||
if (np_conn)
|
||||
edev = extcon_find_edev_by_node(np_conn);
|
||||
of_node_put(np_conn);
|
||||
}
|
||||
of_node_put(np_phy);
|
||||
|
||||
return edev;
|
||||
}
|
||||
|
||||
static int dwc3_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
|
@ -1768,6 +1808,13 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||
goto err2;
|
||||
}
|
||||
|
||||
dwc->edev = dwc3_get_extcon(dwc);
|
||||
if (IS_ERR(dwc->edev)) {
|
||||
ret = PTR_ERR(dwc->edev);
|
||||
dev_err_probe(dwc->dev, ret, "failed to get extcon\n");
|
||||
goto err3;
|
||||
}
|
||||
|
||||
ret = dwc3_get_dr_mode(dwc);
|
||||
if (ret)
|
||||
goto err3;
|
||||
|
|
|
|||
|
|
@ -1046,6 +1046,7 @@ struct dwc3_scratchpad_array {
|
|||
* @tx_thr_num_pkt_prd: periodic ESS transmit packet count
|
||||
* @tx_max_burst_prd: max periodic ESS transmit burst size
|
||||
* @tx_fifo_resize_max_num: max number of fifos allocated during txfifo resize
|
||||
* @clear_stall_protocol: endpoint number that requires a delayed status phase
|
||||
* @hsphy_interface: "utmi" or "ulpi"
|
||||
* @connected: true when we're connected to a host, false otherwise
|
||||
* @softconnect: true when gadget connect is called, false when disconnect runs
|
||||
|
|
@ -1266,6 +1267,7 @@ struct dwc3 {
|
|||
u8 tx_thr_num_pkt_prd;
|
||||
u8 tx_max_burst_prd;
|
||||
u8 tx_fifo_resize_max_num;
|
||||
u8 clear_stall_protocol;
|
||||
|
||||
const char *hsphy_interface;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/extcon.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
|
|
@ -439,51 +438,6 @@ static int dwc3_drd_notifier(struct notifier_block *nb,
|
|||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
|
||||
{
|
||||
struct device *dev = dwc->dev;
|
||||
struct device_node *np_phy;
|
||||
struct extcon_dev *edev = NULL;
|
||||
const char *name;
|
||||
|
||||
if (device_property_read_bool(dev, "extcon"))
|
||||
return extcon_get_edev_by_phandle(dev, 0);
|
||||
|
||||
/*
|
||||
* Device tree platforms should get extcon via phandle.
|
||||
* On ACPI platforms, we get the name from a device property.
|
||||
* This device property is for kernel internal use only and
|
||||
* is expected to be set by the glue code.
|
||||
*/
|
||||
if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) {
|
||||
edev = extcon_get_extcon_dev(name);
|
||||
if (!edev)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
return edev;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to get an extcon device from the USB PHY controller's "port"
|
||||
* node. Check if it has the "port" node first, to avoid printing the
|
||||
* error message from underlying code, as it's a valid case: extcon
|
||||
* device (and "port" node) may be missing in case of "usb-role-switch"
|
||||
* or OTG mode.
|
||||
*/
|
||||
np_phy = of_parse_phandle(dev->of_node, "phys", 0);
|
||||
if (of_graph_is_present(np_phy)) {
|
||||
struct device_node *np_conn;
|
||||
|
||||
np_conn = of_graph_get_remote_node(np_phy, -1, -1);
|
||||
if (np_conn)
|
||||
edev = extcon_find_edev_by_node(np_conn);
|
||||
of_node_put(np_conn);
|
||||
}
|
||||
of_node_put(np_phy);
|
||||
|
||||
return edev;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_USB_ROLE_SWITCH)
|
||||
#define ROLE_SWITCH 1
|
||||
static int dwc3_usb_role_switch_set(struct usb_role_switch *sw,
|
||||
|
|
@ -588,10 +542,6 @@ int dwc3_drd_init(struct dwc3 *dwc)
|
|||
device_property_read_bool(dwc->dev, "usb-role-switch"))
|
||||
return dwc3_setup_role_switch(dwc);
|
||||
|
||||
dwc->edev = dwc3_get_extcon(dwc);
|
||||
if (IS_ERR(dwc->edev))
|
||||
return PTR_ERR(dwc->edev);
|
||||
|
||||
if (dwc->edev) {
|
||||
dwc->edev_nb.notifier_call = dwc3_drd_notifier;
|
||||
ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,
|
||||
|
|
|
|||
332
drivers/usb/dwc3/dwc3-am62.c
Normal file
332
drivers/usb/dwc3/dwc3-am62.c
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* dwc3-am62.c - TI specific Glue layer for AM62 DWC3 USB Controller
|
||||
*
|
||||
* Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
/* USB WRAPPER register offsets */
|
||||
#define USBSS_PID 0x0
|
||||
#define USBSS_OVERCURRENT_CTRL 0x4
|
||||
#define USBSS_PHY_CONFIG 0x8
|
||||
#define USBSS_PHY_TEST 0xc
|
||||
#define USBSS_CORE_STAT 0x14
|
||||
#define USBSS_HOST_VBUS_CTRL 0x18
|
||||
#define USBSS_MODE_CONTROL 0x1c
|
||||
#define USBSS_WAKEUP_CONFIG 0x30
|
||||
#define USBSS_WAKEUP_STAT 0x34
|
||||
#define USBSS_OVERRIDE_CONFIG 0x38
|
||||
#define USBSS_IRQ_MISC_STATUS_RAW 0x430
|
||||
#define USBSS_IRQ_MISC_STATUS 0x434
|
||||
#define USBSS_IRQ_MISC_ENABLE_SET 0x438
|
||||
#define USBSS_IRQ_MISC_ENABLE_CLR 0x43c
|
||||
#define USBSS_IRQ_MISC_EOI 0x440
|
||||
#define USBSS_INTR_TEST 0x490
|
||||
#define USBSS_VBUS_FILTER 0x614
|
||||
#define USBSS_VBUS_STAT 0x618
|
||||
#define USBSS_DEBUG_CFG 0x708
|
||||
#define USBSS_DEBUG_DATA 0x70c
|
||||
#define USBSS_HOST_HUB_CTRL 0x714
|
||||
|
||||
/* PHY CONFIG register bits */
|
||||
#define USBSS_PHY_VBUS_SEL_MASK GENMASK(2, 1)
|
||||
#define USBSS_PHY_VBUS_SEL_SHIFT 1
|
||||
#define USBSS_PHY_LANE_REVERSE BIT(0)
|
||||
|
||||
/* MODE CONTROL register bits */
|
||||
#define USBSS_MODE_VALID BIT(0)
|
||||
|
||||
/* WAKEUP CONFIG register bits */
|
||||
#define USBSS_WAKEUP_CFG_OVERCURRENT_EN BIT(3)
|
||||
#define USBSS_WAKEUP_CFG_LINESTATE_EN BIT(2)
|
||||
#define USBSS_WAKEUP_CFG_SESSVALID_EN BIT(1)
|
||||
#define USBSS_WAKEUP_CFG_VBUSVALID_EN BIT(0)
|
||||
|
||||
/* WAKEUP STAT register bits */
|
||||
#define USBSS_WAKEUP_STAT_OVERCURRENT BIT(4)
|
||||
#define USBSS_WAKEUP_STAT_LINESTATE BIT(3)
|
||||
#define USBSS_WAKEUP_STAT_SESSVALID BIT(2)
|
||||
#define USBSS_WAKEUP_STAT_VBUSVALID BIT(1)
|
||||
#define USBSS_WAKEUP_STAT_CLR BIT(0)
|
||||
|
||||
/* IRQ_MISC_STATUS_RAW register bits */
|
||||
#define USBSS_IRQ_MISC_RAW_VBUSVALID BIT(22)
|
||||
#define USBSS_IRQ_MISC_RAW_SESSVALID BIT(20)
|
||||
|
||||
/* IRQ_MISC_STATUS register bits */
|
||||
#define USBSS_IRQ_MISC_VBUSVALID BIT(22)
|
||||
#define USBSS_IRQ_MISC_SESSVALID BIT(20)
|
||||
|
||||
/* IRQ_MISC_ENABLE_SET register bits */
|
||||
#define USBSS_IRQ_MISC_ENABLE_SET_VBUSVALID BIT(22)
|
||||
#define USBSS_IRQ_MISC_ENABLE_SET_SESSVALID BIT(20)
|
||||
|
||||
/* IRQ_MISC_ENABLE_CLR register bits */
|
||||
#define USBSS_IRQ_MISC_ENABLE_CLR_VBUSVALID BIT(22)
|
||||
#define USBSS_IRQ_MISC_ENABLE_CLR_SESSVALID BIT(20)
|
||||
|
||||
/* IRQ_MISC_EOI register bits */
|
||||
#define USBSS_IRQ_MISC_EOI_VECTOR BIT(0)
|
||||
|
||||
/* VBUS_STAT register bits */
|
||||
#define USBSS_VBUS_STAT_SESSVALID BIT(2)
|
||||
#define USBSS_VBUS_STAT_VBUSVALID BIT(0)
|
||||
|
||||
/* Mask for PHY PLL REFCLK */
|
||||
#define PHY_PLL_REFCLK_MASK GENMASK(3, 0)
|
||||
|
||||
#define DWC3_AM62_AUTOSUSPEND_DELAY 100
|
||||
|
||||
struct dwc3_data {
|
||||
struct device *dev;
|
||||
void __iomem *usbss;
|
||||
struct clk *usb2_refclk;
|
||||
int rate_code;
|
||||
struct regmap *syscon;
|
||||
unsigned int offset;
|
||||
unsigned int vbus_divider;
|
||||
};
|
||||
|
||||
static const int dwc3_ti_rate_table[] = { /* in KHZ */
|
||||
9600,
|
||||
10000,
|
||||
12000,
|
||||
19200,
|
||||
20000,
|
||||
24000,
|
||||
25000,
|
||||
26000,
|
||||
38400,
|
||||
40000,
|
||||
58000,
|
||||
50000,
|
||||
52000,
|
||||
};
|
||||
|
||||
static inline u32 dwc3_ti_readl(struct dwc3_data *data, u32 offset)
|
||||
{
|
||||
return readl((data->usbss) + offset);
|
||||
}
|
||||
|
||||
static inline void dwc3_ti_writel(struct dwc3_data *data, u32 offset, u32 value)
|
||||
{
|
||||
writel(value, (data->usbss) + offset);
|
||||
}
|
||||
|
||||
static int phy_syscon_pll_refclk(struct dwc3_data *data)
|
||||
{
|
||||
struct device *dev = data->dev;
|
||||
struct device_node *node = dev->of_node;
|
||||
struct of_phandle_args args;
|
||||
struct regmap *syscon;
|
||||
int ret;
|
||||
|
||||
syscon = syscon_regmap_lookup_by_phandle(node, "ti,syscon-phy-pll-refclk");
|
||||
if (IS_ERR(syscon)) {
|
||||
dev_err(dev, "unable to get ti,syscon-phy-pll-refclk regmap\n");
|
||||
return PTR_ERR(syscon);
|
||||
}
|
||||
|
||||
data->syscon = syscon;
|
||||
|
||||
ret = of_parse_phandle_with_fixed_args(node, "ti,syscon-phy-pll-refclk", 1,
|
||||
0, &args);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
data->offset = args.args[0];
|
||||
|
||||
ret = regmap_update_bits(data->syscon, data->offset, PHY_PLL_REFCLK_MASK, data->rate_code);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to set phy pll reference clock rate\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dwc3_ti_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct dwc3_data *data;
|
||||
int i, ret;
|
||||
unsigned long rate;
|
||||
u32 reg;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->dev = dev;
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
data->usbss = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(data->usbss)) {
|
||||
dev_err(dev, "can't map IOMEM resource\n");
|
||||
return PTR_ERR(data->usbss);
|
||||
}
|
||||
|
||||
data->usb2_refclk = devm_clk_get(dev, "ref");
|
||||
if (IS_ERR(data->usb2_refclk)) {
|
||||
dev_err(dev, "can't get usb2_refclk\n");
|
||||
return PTR_ERR(data->usb2_refclk);
|
||||
}
|
||||
|
||||
/* Calculate the rate code */
|
||||
rate = clk_get_rate(data->usb2_refclk);
|
||||
rate /= 1000; // To KHz
|
||||
for (i = 0; i < ARRAY_SIZE(dwc3_ti_rate_table); i++) {
|
||||
if (dwc3_ti_rate_table[i] == rate)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(dwc3_ti_rate_table)) {
|
||||
dev_err(dev, "unsupported usb2_refclk rate: %lu KHz\n", rate);
|
||||
ret = -EINVAL;
|
||||
goto err_clk_disable;
|
||||
}
|
||||
|
||||
data->rate_code = i;
|
||||
|
||||
/* Read the syscon property and set the rate code */
|
||||
ret = phy_syscon_pll_refclk(data);
|
||||
if (ret)
|
||||
goto err_clk_disable;
|
||||
|
||||
/* VBUS divider select */
|
||||
data->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider");
|
||||
reg = dwc3_ti_readl(data, USBSS_PHY_CONFIG);
|
||||
if (data->vbus_divider)
|
||||
reg |= 1 << USBSS_PHY_VBUS_SEL_SHIFT;
|
||||
|
||||
dwc3_ti_writel(data, USBSS_PHY_CONFIG, reg);
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
/*
|
||||
* Don't ignore its dependencies with its children
|
||||
*/
|
||||
pm_suspend_ignore_children(dev, false);
|
||||
clk_prepare_enable(data->usb2_refclk);
|
||||
pm_runtime_get_noresume(dev);
|
||||
|
||||
ret = of_platform_populate(node, NULL, NULL, dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to create dwc3 core: %d\n", ret);
|
||||
goto err_pm_disable;
|
||||
}
|
||||
|
||||
/* Set mode valid bit to indicate role is valid */
|
||||
reg = dwc3_ti_readl(data, USBSS_MODE_CONTROL);
|
||||
reg |= USBSS_MODE_VALID;
|
||||
dwc3_ti_writel(data, USBSS_MODE_CONTROL, reg);
|
||||
|
||||
/* Setting up autosuspend */
|
||||
pm_runtime_set_autosuspend_delay(dev, DWC3_AM62_AUTOSUSPEND_DELAY);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
return 0;
|
||||
|
||||
err_pm_disable:
|
||||
clk_disable_unprepare(data->usb2_refclk);
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_suspended(dev);
|
||||
err_clk_disable:
|
||||
clk_put(data->usb2_refclk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dwc3_ti_remove_core(struct device *dev, void *c)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
||||
platform_device_unregister(pdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dwc3_ti_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dwc3_data *data = platform_get_drvdata(pdev);
|
||||
u32 reg;
|
||||
|
||||
device_for_each_child(dev, NULL, dwc3_ti_remove_core);
|
||||
|
||||
/* Clear mode valid bit */
|
||||
reg = dwc3_ti_readl(data, USBSS_MODE_CONTROL);
|
||||
reg &= ~USBSS_MODE_VALID;
|
||||
dwc3_ti_writel(data, USBSS_MODE_CONTROL, reg);
|
||||
|
||||
pm_runtime_put_sync(dev);
|
||||
clk_disable_unprepare(data->usb2_refclk);
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_suspended(dev);
|
||||
|
||||
clk_put(data->usb2_refclk);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int dwc3_ti_suspend_common(struct device *dev)
|
||||
{
|
||||
struct dwc3_data *data = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(data->usb2_refclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dwc3_ti_resume_common(struct device *dev)
|
||||
{
|
||||
struct dwc3_data *data = dev_get_drvdata(dev);
|
||||
|
||||
clk_prepare_enable(data->usb2_refclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static UNIVERSAL_DEV_PM_OPS(dwc3_ti_pm_ops, dwc3_ti_suspend_common,
|
||||
dwc3_ti_resume_common, NULL);
|
||||
|
||||
#define DEV_PM_OPS (&dwc3_ti_pm_ops)
|
||||
#else
|
||||
#define DEV_PM_OPS NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static const struct of_device_id dwc3_ti_of_match[] = {
|
||||
{ .compatible = "ti,am62-usb"},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, dwc3_ti_of_match);
|
||||
|
||||
static struct platform_driver dwc3_ti_driver = {
|
||||
.probe = dwc3_ti_probe,
|
||||
.remove = dwc3_ti_remove,
|
||||
.driver = {
|
||||
.name = "dwc3-am62",
|
||||
.pm = DEV_PM_OPS,
|
||||
.of_match_table = dwc3_ti_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(dwc3_ti_driver);
|
||||
|
||||
MODULE_ALIAS("platform:dwc3-am62");
|
||||
MODULE_AUTHOR("Aswath Govindraju <a-govindraju@ti.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("DesignWare USB3 TI Glue Layer");
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue