mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'usb-for-v5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
Felipe writes: USB: changes for v5.7 merge window Lots of changes on dwc3 this time, most of them from Thinh fixing a bunch of really old mishaps on the driver. DWC2 got support for STM32MP15 and a couple RockChip SoCs while DWC3 learned about Amlogic A1 family. Apart from these, we have a few spelling fixes and other minor non-critical fixes all over the place. Signed-off-by: Felipe Balbi <balbi@kernel.org> * tag 'usb-for-v5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb: (41 commits) dt-bindings: usb: add documentation for aspeed usb-vhub ARM: dts: aspeed-g4: add vhub port and endpoint properties ARM: dts: aspeed-g5: add vhub port and endpoint properties ARM: dts: aspeed-g6: add usb functions usb: gadget: aspeed: add ast2600 vhub support usb: gadget: aspeed: read vhub properties from device tree usb: gadget: aspeed: support per-vhub usb descriptors usb: gadget: f_phonet: Replace zero-length array with flexible-array member usb: gadget: composite: Inform controller driver of self-powered usb: gadget: amd5536udc: fix spelling mistake "reserverd" -> "reserved" udc: s3c-hsudc: Silence warning about supplies during deferred probe usb: dwc2: Silence warning about supplies during deferred probe dt-bindings: usb: dwc2: add compatible property for rk3368 usb dt-bindings: usb: dwc2: add compatible property for rk3328 usb usb: gadget: add raw-gadget interface usb: dwc2: Implement set_selfpowered() usb: dwc3: qcom: Replace <linux/clk-provider.h> by <linux/of_clk.h> usb: dwc3: core: don't do suspend for device mode if already suspended usb: dwc3: Rework resets initialization to be more flexible usb: dwc3: Rework clock initialization to be more flexible ...
This commit is contained in:
@@ -22,10 +22,14 @@ description: |
|
||||
The DWC3 Glue controls the PHY routing and power, an interrupt line is
|
||||
connected to the Glue to serve as OTG ID change detection.
|
||||
|
||||
The Amlogic A1 embeds a DWC3 USB IP Core configured for USB2 in
|
||||
host-only mode.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- amlogic,meson-g12a-usb-ctrl
|
||||
- amlogic,meson-a1-usb-ctrl
|
||||
|
||||
ranges: true
|
||||
|
||||
@@ -84,6 +88,25 @@ required:
|
||||
- phys
|
||||
- dr_mode
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- amlogic,meson-a1-usb-ctrl
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: usb_ctrl
|
||||
- const: usb_bus
|
||||
- const: xtal_usb_ctrl
|
||||
required:
|
||||
- clock-names
|
||||
|
||||
examples:
|
||||
- |
|
||||
usb: usb@ffe09000 {
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (c) 2020 Facebook Inc.
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/usb/aspeed,usb-vhub.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ASPEED USB 2.0 Virtual Hub Controller
|
||||
|
||||
maintainers:
|
||||
- Benjamin Herrenschmidt <benh@kernel.crashing.org>
|
||||
|
||||
description: |+
|
||||
The ASPEED USB 2.0 Virtual Hub Controller implements 1 set of USB Hub
|
||||
register and several sets of Device and Endpoint registers to support
|
||||
the Virtual Hub's downstream USB devices.
|
||||
|
||||
Supported number of devices and endpoints vary depending on hardware
|
||||
revisions. AST2400 and AST2500 Virtual Hub supports 5 downstream devices
|
||||
and 15 generic endpoints, while AST2600 Virtual Hub supports 7 downstream
|
||||
devices and 21 generic endpoints.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- aspeed,ast2400-usb-vhub
|
||||
- aspeed,ast2500-usb-vhub
|
||||
- aspeed,ast2600-usb-vhub
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
aspeed,vhub-downstream-ports:
|
||||
description: Number of downstream ports supported by the Virtual Hub
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- default: 5
|
||||
minimum: 1
|
||||
maximum: 7
|
||||
|
||||
aspeed,vhub-generic-endpoints:
|
||||
description: Number of generic endpoints supported by the Virtual Hub
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- default: 15
|
||||
minimum: 1
|
||||
maximum: 21
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- interrupts
|
||||
- aspeed,vhub-downstream-ports
|
||||
- aspeed,vhub-generic-endpoints
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/aspeed-clock.h>
|
||||
vhub: usb-vhub@1e6a0000 {
|
||||
compatible = "aspeed,ast2500-usb-vhub";
|
||||
reg = <0x1e6a0000 0x300>;
|
||||
interrupts = <5>;
|
||||
clocks = <&syscon ASPEED_CLK_GATE_USBPORT1CLK>;
|
||||
aspeed,vhub-downstream-ports = <5>;
|
||||
aspeed,vhub-generic-endpoints = <15>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_usb2ad_default>;
|
||||
};
|
||||
@@ -18,27 +18,15 @@ properties:
|
||||
- const: rockchip,rk3066-usb
|
||||
- const: snps,dwc2
|
||||
- items:
|
||||
- const: rockchip,px30-usb
|
||||
- const: rockchip,rk3066-usb
|
||||
- const: snps,dwc2
|
||||
- items:
|
||||
- const: rockchip,rk3036-usb
|
||||
- const: rockchip,rk3066-usb
|
||||
- const: snps,dwc2
|
||||
- items:
|
||||
- const: rockchip,rv1108-usb
|
||||
- const: rockchip,rk3066-usb
|
||||
- const: snps,dwc2
|
||||
- items:
|
||||
- const: rockchip,rk3188-usb
|
||||
- const: rockchip,rk3066-usb
|
||||
- const: snps,dwc2
|
||||
- items:
|
||||
- const: rockchip,rk3228-usb
|
||||
- const: rockchip,rk3066-usb
|
||||
- const: snps,dwc2
|
||||
- items:
|
||||
- const: rockchip,rk3288-usb
|
||||
- enum:
|
||||
- rockchip,px30-usb
|
||||
- rockchip,rk3036-usb
|
||||
- rockchip,rk3188-usb
|
||||
- rockchip,rk3228-usb
|
||||
- rockchip,rk3288-usb
|
||||
- rockchip,rk3328-usb
|
||||
- rockchip,rk3368-usb
|
||||
- rockchip,rv1108-usb
|
||||
- const: rockchip,rk3066-usb
|
||||
- const: snps,dwc2
|
||||
- const: lantiq,arx100-usb
|
||||
|
||||
@@ -7,7 +7,8 @@ Required properties:
|
||||
- compatible: must be "snps,dwc3"
|
||||
- reg : Address and length of the register set for the device
|
||||
- interrupts: Interrupts used by the dwc3 controller.
|
||||
- clock-names: should contain "ref", "bus_early", "suspend"
|
||||
- clock-names: list of clock names. Ideally should be "ref",
|
||||
"bus_early", "suspend" but may be less or more.
|
||||
- clocks: list of phandle and clock specifier pairs corresponding to
|
||||
entries in the clock-names property.
|
||||
|
||||
@@ -36,7 +37,7 @@ Optional properties:
|
||||
- phys: from the *Generic PHY* bindings
|
||||
- phy-names: from the *Generic PHY* bindings; supported names are "usb2-phy"
|
||||
or "usb3-phy".
|
||||
- resets: a single pair of phandle and reset specifier
|
||||
- resets: set of phandle and reset specifier pairs
|
||||
- snps,usb2-lpm-disable: indicate if we don't want to enable USB2 HW LPM
|
||||
- snps,usb3_lpm_capable: determines if platform is USB3 LPM capable
|
||||
- snps,dis-start-transfer-quirk: when set, disable isoc START TRANSFER command
|
||||
@@ -75,6 +76,8 @@ Optional properties:
|
||||
from P0 to P1/P2/P3 without delay.
|
||||
- snps,dis-tx-ipgap-linecheck-quirk: when set, disable u2mac linestate check
|
||||
during HS transmit.
|
||||
- snps,parkmode-disable-ss-quirk: when set, all SuperSpeed bus instances in
|
||||
park mode are disabled.
|
||||
- snps,dis_metastability_quirk: when set, disable metastability workaround.
|
||||
CAUTION: use only if you are absolutely sure of it.
|
||||
- snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
|
||||
|
||||
@@ -35,6 +35,12 @@ Optional properties:
|
||||
the USB data role (USB host or USB device) for a given
|
||||
USB connector, such as Type-C, Type-B(micro).
|
||||
see connector/usb-connector.txt.
|
||||
- role-switch-default-mode: indicating if usb-role-switch is enabled, the
|
||||
device default operation mode of controller while usb
|
||||
role is USB_ROLE_NONE. Valid arguments are "host" and
|
||||
"peripheral". Defaults to "peripheral" if not
|
||||
specified.
|
||||
|
||||
|
||||
This is an attribute to a USB controller such as:
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/usb/maxim,max3420-udc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MAXIM MAX3420/1 USB Peripheral Controller
|
||||
|
||||
maintainers:
|
||||
- Jassi Brar <jaswinder.singh@linaro.org>
|
||||
|
||||
description: |
|
||||
The controller provices USB2.0 compliant FullSpeed peripheral
|
||||
implementation over the SPI interface.
|
||||
|
||||
Specifications about the part can be found at:
|
||||
http://datasheets.maximintegrated.com/en/ds/MAX3420E.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- maxim,max3420-udc
|
||||
- maxim,max3421-udc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: usb irq from max3420
|
||||
- description: vbus detection irq
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: udc
|
||||
- const: vbus
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 26000000
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
spi0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
udc@0 {
|
||||
compatible = "maxim,max3420-udc";
|
||||
reg = <0>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <0 IRQ_TYPE_EDGE_FALLING>, <10 IRQ_TYPE_EDGE_BOTH>;
|
||||
interrupt-names = "udc", "vbus";
|
||||
spi-max-frequency = <12500000>;
|
||||
};
|
||||
};
|
||||
@@ -22,6 +22,7 @@ USB support
|
||||
misc_usbsevseg
|
||||
mtouchusb
|
||||
ohci
|
||||
raw-gadget
|
||||
usbip_protocol
|
||||
usbmon
|
||||
usb-serial
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
==============
|
||||
USB Raw Gadget
|
||||
==============
|
||||
|
||||
USB Raw Gadget is a kernel module that provides a userspace interface for
|
||||
the USB Gadget subsystem. Essentially it allows to emulate USB devices
|
||||
from userspace. Enabled with CONFIG_USB_RAW_GADGET. Raw Gadget is
|
||||
currently a strictly debugging feature and shouldn't be used in
|
||||
production, use GadgetFS instead.
|
||||
|
||||
Comparison to GadgetFS
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Raw Gadget is similar to GadgetFS, but provides a more low-level and
|
||||
direct access to the USB Gadget layer for the userspace. The key
|
||||
differences are:
|
||||
|
||||
1. Every USB request is passed to the userspace to get a response, while
|
||||
GadgetFS responds to some USB requests internally based on the provided
|
||||
descriptors. However note, that the UDC driver might respond to some
|
||||
requests on its own and never forward them to the Gadget layer.
|
||||
|
||||
2. GadgetFS performs some sanity checks on the provided USB descriptors,
|
||||
while Raw Gadget allows you to provide arbitrary data as responses to
|
||||
USB requests.
|
||||
|
||||
3. Raw Gadget provides a way to select a UDC device/driver to bind to,
|
||||
while GadgetFS currently binds to the first available UDC.
|
||||
|
||||
4. Raw Gadget uses predictable endpoint names (handles) across different
|
||||
UDCs (as long as UDCs have enough endpoints of each required transfer
|
||||
type).
|
||||
|
||||
5. Raw Gadget has ioctl-based interface instead of a filesystem-based one.
|
||||
|
||||
Userspace interface
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To create a Raw Gadget instance open /dev/raw-gadget. Multiple raw-gadget
|
||||
instances (bound to different UDCs) can be used at the same time. The
|
||||
interaction with the opened file happens through the ioctl() calls, see
|
||||
comments in include/uapi/linux/usb/raw_gadget.h for details.
|
||||
|
||||
The typical usage of Raw Gadget looks like:
|
||||
|
||||
1. Open Raw Gadget instance via /dev/raw-gadget.
|
||||
2. Initialize the instance via USB_RAW_IOCTL_INIT.
|
||||
3. Launch the instance with USB_RAW_IOCTL_RUN.
|
||||
4. In a loop issue USB_RAW_IOCTL_EVENT_FETCH calls to receive events from
|
||||
Raw Gadget and react to those depending on what kind of USB device
|
||||
needs to be emulated.
|
||||
|
||||
Potential future improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Implement ioctl's for setting/clearing halt status on endpoints.
|
||||
|
||||
- Reporting more events (suspend, resume, etc.) through
|
||||
USB_RAW_IOCTL_EVENT_FETCH.
|
||||
|
||||
- Support O_NONBLOCK I/O.
|
||||
@@ -164,6 +164,8 @@
|
||||
reg = <0x1e6a0000 0x300>;
|
||||
interrupts = <5>;
|
||||
clocks = <&syscon ASPEED_CLK_GATE_USBPORT1CLK>;
|
||||
aspeed,vhub-downstream-ports = <5>;
|
||||
aspeed,vhub-generic-endpoints = <15>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_usb2d_default>;
|
||||
status = "disabled";
|
||||
|
||||
@@ -195,6 +195,8 @@
|
||||
reg = <0x1e6a0000 0x300>;
|
||||
interrupts = <5>;
|
||||
clocks = <&syscon ASPEED_CLK_GATE_USBPORT1CLK>;
|
||||
aspeed,vhub-downstream-ports = <5>;
|
||||
aspeed,vhub-generic-endpoints = <15>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_usb2ad_default>;
|
||||
status = "disabled";
|
||||
|
||||
@@ -1112,6 +1112,31 @@
|
||||
groups = "UART9";
|
||||
};
|
||||
|
||||
pinctrl_usb2ah_default: usb2ah_default {
|
||||
function = "USB2AH";
|
||||
groups = "USBA";
|
||||
};
|
||||
|
||||
pinctrl_usb2ad_default: usb2ad_default {
|
||||
function = "USB2AD";
|
||||
groups = "USBA";
|
||||
};
|
||||
|
||||
pinctrl_usb2bh_default: usb2bh_default {
|
||||
function = "USB2BH";
|
||||
groups = "USBB";
|
||||
};
|
||||
|
||||
pinctrl_usb2bd_default: usb2bd_default {
|
||||
function = "USB2BD";
|
||||
groups = "USBB";
|
||||
};
|
||||
|
||||
pinctrl_usb11bhid_default: usb11bhid_default {
|
||||
function = "USB11BHID";
|
||||
groups = "USBB";
|
||||
};
|
||||
|
||||
pinctrl_vb_default: vb_default {
|
||||
function = "VB";
|
||||
groups = "VB";
|
||||
|
||||
@@ -245,6 +245,51 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ehci0: usb@1e6a1000 {
|
||||
compatible = "aspeed,ast2600-ehci", "generic-ehci";
|
||||
reg = <0x1e6a1000 0x100>;
|
||||
interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&syscon ASPEED_CLK_GATE_USBPORT1CLK>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_usb2ah_default>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ehci1: usb@1e6a3000 {
|
||||
compatible = "aspeed,ast2600-ehci", "generic-ehci";
|
||||
reg = <0x1e6a3000 0x100>;
|
||||
interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&syscon ASPEED_CLK_GATE_USBPORT2CLK>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_usb2bh_default>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uhci: usb@1e6b0000 {
|
||||
compatible = "aspeed,ast2600-uhci", "generic-uhci";
|
||||
reg = <0x1e6b0000 0x100>;
|
||||
interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#ports = <2>;
|
||||
clocks = <&syscon ASPEED_CLK_GATE_USBUHCICLK>;
|
||||
status = "disabled";
|
||||
/*
|
||||
* No default pinmux, it will follow EHCI, use an
|
||||
* explicit pinmux override if EHCI is not enabled.
|
||||
*/
|
||||
};
|
||||
|
||||
vhub: usb-vhub@1e6a0000 {
|
||||
compatible = "aspeed,ast2600-usb-vhub";
|
||||
reg = <0x1e6a0000 0x350>;
|
||||
interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&syscon ASPEED_CLK_GATE_USBPORT1CLK>;
|
||||
aspeed,vhub-downstream-ports = <7>;
|
||||
aspeed,vhub-generic-endpoints = <21>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_usb2ad_default>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
apb {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
|
||||
@@ -411,6 +411,10 @@ enum dwc2_ep0_state {
|
||||
* register.
|
||||
* 0 - Deactivate the transceiver (default)
|
||||
* 1 - Activate the transceiver
|
||||
* @activate_stm_id_vb_detection: Activate external ID pin and Vbus level
|
||||
* detection using GGPIO register.
|
||||
* 0 - Deactivate the external level detection (default)
|
||||
* 1 - Activate the external level detection
|
||||
* @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
|
||||
@@ -481,6 +485,7 @@ struct dwc2_core_params {
|
||||
bool service_interval;
|
||||
u8 hird_threshold;
|
||||
bool activate_stm_fs_transceiver;
|
||||
bool activate_stm_id_vb_detection;
|
||||
bool ipg_isoc_en;
|
||||
u16 max_packet_count;
|
||||
u32 max_transfer_size;
|
||||
@@ -874,6 +879,8 @@ struct dwc2_hregs_backup {
|
||||
* removed once all SoCs support usb transceiver.
|
||||
* @supplies: Definition of USB power supplies
|
||||
* @vbus_supply: Regulator supplying vbus.
|
||||
* @usb33d: Optional 3.3v regulator used on some stm32 devices to
|
||||
* supply ID and VBUS detection hardware.
|
||||
* @lock: Spinlock that protects all the driver data structures
|
||||
* @priv: Stores a pointer to the struct usb_hcd
|
||||
* @queuing_high_bandwidth: True if multiple packets of a high-bandwidth
|
||||
@@ -1061,6 +1068,7 @@ struct dwc2_hsotg {
|
||||
struct dwc2_hsotg_plat *plat;
|
||||
struct regulator_bulk_data supplies[DWC2_NUM_SUPPLIES];
|
||||
struct regulator *vbus_supply;
|
||||
struct regulator *usb33d;
|
||||
|
||||
spinlock_t lock;
|
||||
void *priv;
|
||||
|
||||
@@ -1646,7 +1646,8 @@ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
|
||||
|
||||
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
||||
case USB_RECIP_DEVICE:
|
||||
status = 1 << USB_DEVICE_SELF_POWERED;
|
||||
status = hsotg->gadget.is_selfpowered <<
|
||||
USB_DEVICE_SELF_POWERED;
|
||||
status |= hsotg->remote_wakeup_allowed <<
|
||||
USB_DEVICE_REMOTE_WAKEUP;
|
||||
reply = cpu_to_le16(status);
|
||||
@@ -4527,6 +4528,26 @@ static int dwc2_hsotg_gadget_getframe(struct usb_gadget *gadget)
|
||||
return dwc2_hsotg_read_frameno(to_hsotg(gadget));
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_hsotg_set_selfpowered - set if device is self/bus powered
|
||||
* @gadget: The usb gadget state
|
||||
* @is_selfpowered: Whether the device is self-powered
|
||||
*
|
||||
* Set if the device is self or bus powered.
|
||||
*/
|
||||
static int dwc2_hsotg_set_selfpowered(struct usb_gadget *gadget,
|
||||
int is_selfpowered)
|
||||
{
|
||||
struct dwc2_hsotg *hsotg = to_hsotg(gadget);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&hsotg->lock, flags);
|
||||
gadget->is_selfpowered = !!is_selfpowered;
|
||||
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_hsotg_pullup - connect/disconnect the USB PHY
|
||||
* @gadget: The usb gadget state
|
||||
@@ -4618,6 +4639,7 @@ static int dwc2_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned int mA)
|
||||
|
||||
static const struct usb_gadget_ops dwc2_hsotg_gadget_ops = {
|
||||
.get_frame = dwc2_hsotg_gadget_getframe,
|
||||
.set_selfpowered = dwc2_hsotg_set_selfpowered,
|
||||
.udc_start = dwc2_hsotg_udc_start,
|
||||
.udc_stop = dwc2_hsotg_udc_stop,
|
||||
.pullup = dwc2_hsotg_pullup,
|
||||
|
||||
@@ -54,6 +54,12 @@
|
||||
#define GOTGCTL_HSTSETHNPEN BIT(10)
|
||||
#define GOTGCTL_HNPREQ BIT(9)
|
||||
#define GOTGCTL_HSTNEGSCS BIT(8)
|
||||
#define GOTGCTL_BVALOVAL BIT(7)
|
||||
#define GOTGCTL_BVALOEN BIT(6)
|
||||
#define GOTGCTL_AVALOVAL BIT(5)
|
||||
#define GOTGCTL_AVALOEN BIT(4)
|
||||
#define GOTGCTL_VBVALOVAL BIT(3)
|
||||
#define GOTGCTL_VBVALOEN BIT(2)
|
||||
#define GOTGCTL_SESREQ BIT(1)
|
||||
#define GOTGCTL_SESREQSCS BIT(0)
|
||||
|
||||
@@ -227,6 +233,8 @@
|
||||
#define GPVNDCTL HSOTG_REG(0x0034)
|
||||
#define GGPIO HSOTG_REG(0x0038)
|
||||
#define GGPIO_STM32_OTG_GCCFG_PWRDWN BIT(16)
|
||||
#define GGPIO_STM32_OTG_GCCFG_VBDEN BIT(21)
|
||||
#define GGPIO_STM32_OTG_GCCFG_IDEN BIT(22)
|
||||
|
||||
#define GUID HSOTG_REG(0x003c)
|
||||
#define GSNPSID HSOTG_REG(0x0040)
|
||||
|
||||
@@ -163,6 +163,35 @@ static void dwc2_set_stm32f7_hsotg_params(struct dwc2_hsotg *hsotg)
|
||||
p->host_perio_tx_fifo_size = 256;
|
||||
}
|
||||
|
||||
static void dwc2_set_stm32mp15_fsotg_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
|
||||
p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE;
|
||||
p->speed = DWC2_SPEED_PARAM_FULL;
|
||||
p->host_rx_fifo_size = 128;
|
||||
p->host_nperio_tx_fifo_size = 96;
|
||||
p->host_perio_tx_fifo_size = 96;
|
||||
p->max_packet_count = 256;
|
||||
p->phy_type = DWC2_PHY_TYPE_PARAM_FS;
|
||||
p->i2c_enable = false;
|
||||
p->activate_stm_fs_transceiver = true;
|
||||
p->activate_stm_id_vb_detection = true;
|
||||
p->power_down = DWC2_POWER_DOWN_PARAM_NONE;
|
||||
}
|
||||
|
||||
static void dwc2_set_stm32mp15_hsotg_params(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
|
||||
p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE;
|
||||
p->activate_stm_id_vb_detection = true;
|
||||
p->host_rx_fifo_size = 440;
|
||||
p->host_nperio_tx_fifo_size = 256;
|
||||
p->host_perio_tx_fifo_size = 256;
|
||||
p->power_down = DWC2_POWER_DOWN_PARAM_NONE;
|
||||
}
|
||||
|
||||
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 },
|
||||
@@ -186,6 +215,10 @@ const struct of_device_id dwc2_of_match_table[] = {
|
||||
{ .compatible = "st,stm32f4x9-hsotg" },
|
||||
{ .compatible = "st,stm32f7-hsotg",
|
||||
.data = dwc2_set_stm32f7_hsotg_params },
|
||||
{ .compatible = "st,stm32mp15-fsotg",
|
||||
.data = dwc2_set_stm32mp15_fsotg_params },
|
||||
{ .compatible = "st,stm32mp15-hsotg",
|
||||
.data = dwc2_set_stm32mp15_hsotg_params },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, dwc2_of_match_table);
|
||||
|
||||
@@ -285,7 +285,9 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
|
||||
ret = devm_regulator_bulk_get(hsotg->dev, ARRAY_SIZE(hsotg->supplies),
|
||||
hsotg->supplies);
|
||||
if (ret) {
|
||||
dev_err(hsotg->dev, "failed to request supplies: %d\n", ret);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(hsotg->dev, "failed to request supplies: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
@@ -312,6 +314,9 @@ static int dwc2_driver_remove(struct platform_device *dev)
|
||||
if (hsotg->gadget_enabled)
|
||||
dwc2_hsotg_remove(hsotg);
|
||||
|
||||
if (hsotg->params.activate_stm_id_vb_detection)
|
||||
regulator_disable(hsotg->usb33d);
|
||||
|
||||
if (hsotg->ll_hw_enabled)
|
||||
dwc2_lowlevel_hw_disable(hsotg);
|
||||
|
||||
@@ -464,10 +469,35 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
||||
if (retval)
|
||||
goto error;
|
||||
|
||||
if (hsotg->params.activate_stm_id_vb_detection) {
|
||||
u32 ggpio;
|
||||
|
||||
hsotg->usb33d = devm_regulator_get(hsotg->dev, "usb33d");
|
||||
if (IS_ERR(hsotg->usb33d)) {
|
||||
retval = PTR_ERR(hsotg->usb33d);
|
||||
if (retval != -EPROBE_DEFER)
|
||||
dev_err(hsotg->dev,
|
||||
"failed to request usb33d supply: %d\n",
|
||||
retval);
|
||||
goto error;
|
||||
}
|
||||
retval = regulator_enable(hsotg->usb33d);
|
||||
if (retval) {
|
||||
dev_err(hsotg->dev,
|
||||
"failed to enable usb33d supply: %d\n", retval);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ggpio = dwc2_readl(hsotg, GGPIO);
|
||||
ggpio |= GGPIO_STM32_OTG_GCCFG_IDEN;
|
||||
ggpio |= GGPIO_STM32_OTG_GCCFG_VBDEN;
|
||||
dwc2_writel(hsotg, ggpio, GGPIO);
|
||||
}
|
||||
|
||||
if (hsotg->dr_mode != USB_DR_MODE_HOST) {
|
||||
retval = dwc2_gadget_init(hsotg);
|
||||
if (retval)
|
||||
goto error;
|
||||
goto error_init;
|
||||
hsotg->gadget_enabled = 1;
|
||||
}
|
||||
|
||||
@@ -493,7 +523,7 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
||||
if (retval) {
|
||||
if (hsotg->gadget_enabled)
|
||||
dwc2_hsotg_remove(hsotg);
|
||||
goto error;
|
||||
goto error_init;
|
||||
}
|
||||
hsotg->hcd_enabled = 1;
|
||||
}
|
||||
@@ -509,6 +539,9 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
||||
|
||||
return 0;
|
||||
|
||||
error_init:
|
||||
if (hsotg->params.activate_stm_id_vb_detection)
|
||||
regulator_disable(hsotg->usb33d);
|
||||
error:
|
||||
dwc2_lowlevel_hw_disable(hsotg);
|
||||
return retval;
|
||||
@@ -523,6 +556,37 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
|
||||
if (is_device_mode)
|
||||
dwc2_hsotg_suspend(dwc2);
|
||||
|
||||
if (dwc2->params.activate_stm_id_vb_detection) {
|
||||
unsigned long flags;
|
||||
u32 ggpio, gotgctl;
|
||||
|
||||
/*
|
||||
* Need to force the mode to the current mode to avoid Mode
|
||||
* Mismatch Interrupt when ID detection will be disabled.
|
||||
*/
|
||||
dwc2_force_mode(dwc2, !is_device_mode);
|
||||
|
||||
spin_lock_irqsave(&dwc2->lock, flags);
|
||||
gotgctl = dwc2_readl(dwc2, GOTGCTL);
|
||||
/* bypass debounce filter, enable overrides */
|
||||
gotgctl |= GOTGCTL_DBNCE_FLTR_BYPASS;
|
||||
gotgctl |= GOTGCTL_BVALOEN | GOTGCTL_AVALOEN;
|
||||
/* Force A / B session if needed */
|
||||
if (gotgctl & GOTGCTL_ASESVLD)
|
||||
gotgctl |= GOTGCTL_AVALOVAL;
|
||||
if (gotgctl & GOTGCTL_BSESVLD)
|
||||
gotgctl |= GOTGCTL_BVALOVAL;
|
||||
dwc2_writel(dwc2, gotgctl, GOTGCTL);
|
||||
spin_unlock_irqrestore(&dwc2->lock, flags);
|
||||
|
||||
ggpio = dwc2_readl(dwc2, GGPIO);
|
||||
ggpio &= ~GGPIO_STM32_OTG_GCCFG_IDEN;
|
||||
ggpio &= ~GGPIO_STM32_OTG_GCCFG_VBDEN;
|
||||
dwc2_writel(dwc2, ggpio, GGPIO);
|
||||
|
||||
regulator_disable(dwc2->usb33d);
|
||||
}
|
||||
|
||||
if (dwc2->ll_hw_enabled &&
|
||||
(is_device_mode || dwc2_host_can_poweroff_phy(dwc2))) {
|
||||
ret = __dwc2_lowlevel_hw_disable(dwc2);
|
||||
@@ -544,6 +608,34 @@ static int __maybe_unused dwc2_resume(struct device *dev)
|
||||
}
|
||||
dwc2->phy_off_for_suspend = false;
|
||||
|
||||
if (dwc2->params.activate_stm_id_vb_detection) {
|
||||
unsigned long flags;
|
||||
u32 ggpio, gotgctl;
|
||||
|
||||
ret = regulator_enable(dwc2->usb33d);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ggpio = dwc2_readl(dwc2, GGPIO);
|
||||
ggpio |= GGPIO_STM32_OTG_GCCFG_IDEN;
|
||||
ggpio |= GGPIO_STM32_OTG_GCCFG_VBDEN;
|
||||
dwc2_writel(dwc2, ggpio, GGPIO);
|
||||
|
||||
/* ID/VBUS detection startup time */
|
||||
usleep_range(5000, 7000);
|
||||
|
||||
spin_lock_irqsave(&dwc2->lock, flags);
|
||||
gotgctl = dwc2_readl(dwc2, GOTGCTL);
|
||||
gotgctl &= ~GOTGCTL_DBNCE_FLTR_BYPASS;
|
||||
gotgctl &= ~(GOTGCTL_BVALOEN | GOTGCTL_AVALOEN |
|
||||
GOTGCTL_BVALOVAL | GOTGCTL_AVALOVAL);
|
||||
dwc2_writel(dwc2, gotgctl, GOTGCTL);
|
||||
spin_unlock_irqrestore(&dwc2->lock, flags);
|
||||
}
|
||||
|
||||
/* Need to restore FORCEDEVMODE/FORCEHOSTMODE */
|
||||
dwc2_force_dr_mode(dwc2);
|
||||
|
||||
if (dwc2_is_device_mode(dwc2))
|
||||
ret = dwc2_hsotg_resume(dwc2);
|
||||
|
||||
|
||||
+13
-16
@@ -289,12 +289,6 @@ done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_bulk_data dwc3_core_clks[] = {
|
||||
{ .id = "ref" },
|
||||
{ .id = "bus_early" },
|
||||
{ .id = "suspend" },
|
||||
};
|
||||
|
||||
/*
|
||||
* dwc3_frame_length_adjustment - Adjusts frame length if required
|
||||
* @dwc3: Pointer to our controller context structure
|
||||
@@ -1029,6 +1023,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
|
||||
if (dwc->dis_tx_ipgap_linecheck_quirk)
|
||||
reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
|
||||
|
||||
if (dwc->parkmode_disable_ss_quirk)
|
||||
reg |= DWC3_GUCTL1_PARKMODE_DISABLE_SS;
|
||||
|
||||
dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
|
||||
}
|
||||
|
||||
@@ -1342,6 +1339,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
|
||||
"snps,dis-del-phy-power-chg-quirk");
|
||||
dwc->dis_tx_ipgap_linecheck_quirk = device_property_read_bool(dev,
|
||||
"snps,dis-tx-ipgap-linecheck-quirk");
|
||||
dwc->parkmode_disable_ss_quirk = device_property_read_bool(dev,
|
||||
"snps,parkmode-disable-ss-quirk");
|
||||
|
||||
dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
|
||||
"snps,tx_de_emphasis_quirk");
|
||||
@@ -1441,11 +1440,6 @@ static int dwc3_probe(struct platform_device *pdev)
|
||||
if (!dwc)
|
||||
return -ENOMEM;
|
||||
|
||||
dwc->clks = devm_kmemdup(dev, dwc3_core_clks, sizeof(dwc3_core_clks),
|
||||
GFP_KERNEL);
|
||||
if (!dwc->clks)
|
||||
return -ENOMEM;
|
||||
|
||||
dwc->dev = dev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
@@ -1476,22 +1470,23 @@ static int dwc3_probe(struct platform_device *pdev)
|
||||
|
||||
dwc3_get_properties(dwc);
|
||||
|
||||
dwc->reset = devm_reset_control_get_optional_shared(dev, NULL);
|
||||
dwc->reset = devm_reset_control_array_get(dev, true, true);
|
||||
if (IS_ERR(dwc->reset))
|
||||
return PTR_ERR(dwc->reset);
|
||||
|
||||
if (dev->of_node) {
|
||||
dwc->num_clks = ARRAY_SIZE(dwc3_core_clks);
|
||||
|
||||
ret = devm_clk_bulk_get(dev, dwc->num_clks, dwc->clks);
|
||||
ret = devm_clk_bulk_get_all(dev, &dwc->clks);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
/*
|
||||
* Clocks are optional, but new DT platforms should support all
|
||||
* clocks as required by the DT-binding.
|
||||
*/
|
||||
if (ret)
|
||||
if (ret < 0)
|
||||
dwc->num_clks = 0;
|
||||
else
|
||||
dwc->num_clks = ret;
|
||||
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(dwc->reset);
|
||||
@@ -1637,6 +1632,8 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
|
||||
|
||||
switch (dwc->current_dr_role) {
|
||||
case DWC3_GCTL_PRTCAP_DEVICE:
|
||||
if (pm_runtime_suspended(dwc->dev))
|
||||
break;
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
dwc3_gadget_suspend(dwc);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/role.h>
|
||||
#include <linux/ulpi/interface.h>
|
||||
|
||||
#include <linux/phy/phy.h>
|
||||
@@ -249,6 +250,7 @@
|
||||
#define DWC3_GUCTL_HSTINAUTORETRY BIT(14)
|
||||
|
||||
/* Global User Control 1 Register */
|
||||
#define DWC3_GUCTL1_PARKMODE_DISABLE_SS BIT(17)
|
||||
#define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28)
|
||||
#define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24)
|
||||
|
||||
@@ -953,6 +955,9 @@ struct dwc3_scratchpad_array {
|
||||
* @hsphy_mode: UTMI phy mode, one of following:
|
||||
* - USBPHY_INTERFACE_MODE_UTMI
|
||||
* - USBPHY_INTERFACE_MODE_UTMIW
|
||||
* @role_sw: usb_role_switch handle
|
||||
* @role_switch_default_mode: default operation mode of controller while
|
||||
* usb role is USB_ROLE_NONE.
|
||||
* @usb2_phy: pointer to USB2 PHY
|
||||
* @usb3_phy: pointer to USB3 PHY
|
||||
* @usb2_generic_phy: pointer to USB2 PHY
|
||||
@@ -1024,6 +1029,8 @@ struct dwc3_scratchpad_array {
|
||||
* change quirk.
|
||||
* @dis_tx_ipgap_linecheck_quirk: set if we disable u2mac linestate
|
||||
* check during HS transmit.
|
||||
* @parkmode_disable_ss_quirk: set if we need to disable all SuperSpeed
|
||||
* instances in park mode.
|
||||
* @tx_de_emphasis_quirk: set if we enable Tx de-emphasis quirk
|
||||
* @tx_de_emphasis: Tx de-emphasis value
|
||||
* 0 - -6dB de-emphasis
|
||||
@@ -1086,6 +1093,8 @@ struct dwc3 {
|
||||
struct extcon_dev *edev;
|
||||
struct notifier_block edev_nb;
|
||||
enum usb_phy_interface hsphy_mode;
|
||||
struct usb_role_switch *role_sw;
|
||||
enum usb_dr_mode role_switch_default_mode;
|
||||
|
||||
u32 fladj;
|
||||
u32 irq_gadget;
|
||||
@@ -1215,6 +1224,7 @@ struct dwc3 {
|
||||
unsigned dis_u2_freeclk_exists_quirk:1;
|
||||
unsigned dis_del_phy_power_chg_quirk:1;
|
||||
unsigned dis_tx_ipgap_linecheck_quirk:1;
|
||||
unsigned parkmode_disable_ss_quirk:1;
|
||||
|
||||
unsigned tx_de_emphasis_quirk:1;
|
||||
unsigned tx_de_emphasis:2;
|
||||
|
||||
+95
-1
@@ -476,6 +476,92 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
|
||||
return edev;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_USB_ROLE_SWITCH)
|
||||
#define ROLE_SWITCH 1
|
||||
static int dwc3_usb_role_switch_set(struct device *dev, enum usb_role role)
|
||||
{
|
||||
struct dwc3 *dwc = dev_get_drvdata(dev);
|
||||
u32 mode;
|
||||
|
||||
switch (role) {
|
||||
case USB_ROLE_HOST:
|
||||
mode = DWC3_GCTL_PRTCAP_HOST;
|
||||
break;
|
||||
case USB_ROLE_DEVICE:
|
||||
mode = DWC3_GCTL_PRTCAP_DEVICE;
|
||||
break;
|
||||
default:
|
||||
if (dwc->role_switch_default_mode == USB_DR_MODE_HOST)
|
||||
mode = DWC3_GCTL_PRTCAP_HOST;
|
||||
else
|
||||
mode = DWC3_GCTL_PRTCAP_DEVICE;
|
||||
break;
|
||||
}
|
||||
|
||||
dwc3_set_mode(dwc, mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum usb_role dwc3_usb_role_switch_get(struct device *dev)
|
||||
{
|
||||
struct dwc3 *dwc = dev_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
enum usb_role role;
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
switch (dwc->current_dr_role) {
|
||||
case DWC3_GCTL_PRTCAP_HOST:
|
||||
role = USB_ROLE_HOST;
|
||||
break;
|
||||
case DWC3_GCTL_PRTCAP_DEVICE:
|
||||
role = USB_ROLE_DEVICE;
|
||||
break;
|
||||
case DWC3_GCTL_PRTCAP_OTG:
|
||||
role = dwc->current_otg_role;
|
||||
break;
|
||||
default:
|
||||
if (dwc->role_switch_default_mode == USB_DR_MODE_HOST)
|
||||
role = USB_ROLE_HOST;
|
||||
else
|
||||
role = USB_ROLE_DEVICE;
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
return role;
|
||||
}
|
||||
|
||||
static int dwc3_setup_role_switch(struct dwc3 *dwc)
|
||||
{
|
||||
struct usb_role_switch_desc dwc3_role_switch = {NULL};
|
||||
const char *str;
|
||||
u32 mode;
|
||||
int ret;
|
||||
|
||||
ret = device_property_read_string(dwc->dev, "role-switch-default-mode",
|
||||
&str);
|
||||
if (ret >= 0 && !strncmp(str, "host", strlen("host"))) {
|
||||
dwc->role_switch_default_mode = USB_DR_MODE_HOST;
|
||||
mode = DWC3_GCTL_PRTCAP_HOST;
|
||||
} else {
|
||||
dwc->role_switch_default_mode = USB_DR_MODE_PERIPHERAL;
|
||||
mode = DWC3_GCTL_PRTCAP_DEVICE;
|
||||
}
|
||||
|
||||
dwc3_role_switch.fwnode = dev_fwnode(dwc->dev);
|
||||
dwc3_role_switch.set = dwc3_usb_role_switch_set;
|
||||
dwc3_role_switch.get = dwc3_usb_role_switch_get;
|
||||
dwc->role_sw = usb_role_switch_register(dwc->dev, &dwc3_role_switch);
|
||||
if (IS_ERR(dwc->role_sw))
|
||||
return PTR_ERR(dwc->role_sw);
|
||||
|
||||
dwc3_set_mode(dwc, mode);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define ROLE_SWITCH 0
|
||||
#define dwc3_setup_role_switch(x) 0
|
||||
#endif
|
||||
|
||||
int dwc3_drd_init(struct dwc3 *dwc)
|
||||
{
|
||||
int ret, irq;
|
||||
@@ -484,7 +570,12 @@ int dwc3_drd_init(struct dwc3 *dwc)
|
||||
if (IS_ERR(dwc->edev))
|
||||
return PTR_ERR(dwc->edev);
|
||||
|
||||
if (dwc->edev) {
|
||||
if (ROLE_SWITCH &&
|
||||
device_property_read_bool(dwc->dev, "usb-role-switch")) {
|
||||
ret = dwc3_setup_role_switch(dwc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else if (dwc->edev) {
|
||||
dwc->edev_nb.notifier_call = dwc3_drd_notifier;
|
||||
ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,
|
||||
&dwc->edev_nb);
|
||||
@@ -531,6 +622,9 @@ void dwc3_drd_exit(struct dwc3 *dwc)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (dwc->role_sw)
|
||||
usb_role_switch_unregister(dwc->role_sw);
|
||||
|
||||
if (dwc->edev)
|
||||
extcon_unregister_notifier(dwc->edev, EXTCON_USB_HOST,
|
||||
&dwc->edev_nb);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user