summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/usb/amlogic,meson-g12a-usb-ctrl.yaml23
-rw-r--r--Documentation/devicetree/bindings/usb/aspeed,usb-vhub.yaml77
-rw-r--r--Documentation/devicetree/bindings/usb/dwc2.yaml30
-rw-r--r--Documentation/devicetree/bindings/usb/dwc3.txt7
-rw-r--r--Documentation/devicetree/bindings/usb/generic.txt6
-rw-r--r--Documentation/devicetree/bindings/usb/maxim,max3420-udc.yaml69
-rw-r--r--Documentation/usb/index.rst1
-rw-r--r--Documentation/usb/raw-gadget.rst61
-rw-r--r--arch/arm/boot/dts/aspeed-g4.dtsi2
-rw-r--r--arch/arm/boot/dts/aspeed-g5.dtsi2
-rw-r--r--arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi25
-rw-r--r--arch/arm/boot/dts/aspeed-g6.dtsi45
-rw-r--r--drivers/usb/dwc2/core.h8
-rw-r--r--drivers/usb/dwc2/gadget.c24
-rw-r--r--drivers/usb/dwc2/hw.h8
-rw-r--r--drivers/usb/dwc2/params.c33
-rw-r--r--drivers/usb/dwc2/platform.c98
-rw-r--r--drivers/usb/dwc3/core.c29
-rw-r--r--drivers/usb/dwc3/core.h10
-rw-r--r--drivers/usb/dwc3/drd.c96
-rw-r--r--drivers/usb/dwc3/dwc3-exynos.c9
-rw-r--r--drivers/usb/dwc3/dwc3-meson-g12a.c174
-rw-r--r--drivers/usb/dwc3/gadget.c6
-rw-r--r--drivers/usb/dwc3/host.c4
-rw-r--r--drivers/usb/dwc3/trace.h9
-rw-r--r--drivers/usb/gadget/composite.c9
-rw-r--r--drivers/usb/gadget/legacy/Kconfig11
-rw-r--r--drivers/usb/gadget/legacy/Makefile1
-rw-r--r--drivers/usb/gadget/legacy/raw_gadget.c1078
-rw-r--r--drivers/usb/gadget/udc/Kconfig10
-rw-r--r--drivers/usb/gadget/udc/Makefile1
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/Kconfig4
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/core.c71
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/dev.c30
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/epn.c4
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/hub.c58
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/vhub.h43
-rw-r--r--drivers/usb/gadget/udc/max3420_udc.c1331
-rw-r--r--drivers/usb/gadget/udc/tegra-xudc.c5
-rw-r--r--include/uapi/linux/usb/raw_gadget.h167
40 files changed, 3496 insertions, 183 deletions
diff --git a/Documentation/devicetree/bindings/usb/amlogic,meson-g12a-usb-ctrl.yaml b/Documentation/devicetree/bindings/usb/amlogic,meson-g12a-usb-ctrl.yaml
index 267fce165994..b0e5e0fe9386 100644
--- a/Documentation/devicetree/bindings/usb/amlogic,meson-g12a-usb-ctrl.yaml
+++ b/Documentation/devicetree/bindings/usb/amlogic,meson-g12a-usb-ctrl.yaml
@@ -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 {
diff --git a/Documentation/devicetree/bindings/usb/aspeed,usb-vhub.yaml b/Documentation/devicetree/bindings/usb/aspeed,usb-vhub.yaml
new file mode 100644
index 000000000000..06399ba0d9e4
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/aspeed,usb-vhub.yaml
@@ -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>;
+ };
diff --git a/Documentation/devicetree/bindings/usb/dwc2.yaml b/Documentation/devicetree/bindings/usb/dwc2.yaml
index 71cf7ba32237..6baf00e7d0a9 100644
--- a/Documentation/devicetree/bindings/usb/dwc2.yaml
+++ b/Documentation/devicetree/bindings/usb/dwc2.yaml
@@ -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
diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
index 66780a47ad85..9946ff9ba735 100644
--- a/Documentation/devicetree/bindings/usb/dwc3.txt
+++ b/Documentation/devicetree/bindings/usb/dwc3.txt
@@ -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
diff --git a/Documentation/devicetree/bindings/usb/generic.txt b/Documentation/devicetree/bindings/usb/generic.txt
index e6790d2a4da9..67c51759a642 100644
--- a/Documentation/devicetree/bindings/usb/generic.txt
+++ b/Documentation/devicetree/bindings/usb/generic.txt
@@ -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:
diff --git a/Documentation/devicetree/bindings/usb/maxim,max3420-udc.yaml b/Documentation/devicetree/bindings/usb/maxim,max3420-udc.yaml
new file mode 100644
index 000000000000..4241d38d5864
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/maxim,max3420-udc.yaml
@@ -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>;
+ };
+ };
diff --git a/Documentation/usb/index.rst b/Documentation/usb/index.rst
index 36b6ebd9a9d9..b656c9be23ed 100644
--- a/Documentation/usb/index.rst
+++ b/Documentation/usb/index.rst
@@ -22,6 +22,7 @@ USB support
misc_usbsevseg
mtouchusb
ohci
+ raw-gadget
usbip_protocol
usbmon
usb-serial
diff --git a/Documentation/usb/raw-gadget.rst b/Documentation/usb/raw-gadget.rst
new file mode 100644
index 000000000000..9e78cb858f86
--- /dev/null
+++ b/Documentation/usb/raw-gadget.rst
@@ -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.
diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
index 807a0fc20670..8e04303e8514 100644
--- a/arch/arm/boot/dts/aspeed-g4.dtsi
+++ b/arch/arm/boot/dts/aspeed-g4.dtsi
@@ -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";
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
index ebec0fa8baa7..f12ec04d3cbc 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
@@ -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";
diff --git a/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi b/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
index 045ce66ca876..7028e21bdd98 100644
--- a/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
+++ b/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
@@ -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";
diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
index 796976d275e1..0a29b3b57a9d 100644
--- a/arch/arm/boot/dts/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed-g6.dtsi
@@ -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>;
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 968e03b89d04..99b0bdfe0012 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -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;
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 92ed32ec1607..12b98b466287 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -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);
@@ -4528,6 +4529,26 @@ static int dwc2_hsotg_gadget_getframe(struct usb_gadget *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
* @is_on: Current state of the USB PHY
@@ -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,
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h
index 510e87ec0be8..c4027bbcedec 100644
--- a/drivers/usb/dwc2/hw.h
+++ b/drivers/usb/dwc2/hw.h
@@ -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)
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 31e090ac9f1e..8ccc83f7eb3f 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -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);
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index 3c6ce09a6db5..8ea4a24637fa 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -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