diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc b/Documentation/ABI/testing/configfs-usb-gadget-uvc
index 80b98a4a4d0fc8f87bebdd8f7e2d9e1d690622f3..4feb692c4c1d37190c04cff86ace614648e3db03 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
@@ -76,7 +76,7 @@ Date:		Dec 2014
 KernelVersion:	4.0
 Description:	Default camera terminal descriptors
 
-		All attributes read only:
+		All attributes read only except bmControls, which is read/write:
 
 		========================  ====================================
 		bmControls		  bitmap specifying which controls are
@@ -101,7 +101,7 @@ Date:		Dec 2014
 KernelVersion:	4.0
 Description:	Default processing unit descriptors
 
-		All attributes read only:
+		All attributes read only except bmControls, which is read/write:
 
 		===============	========================================
 		iProcessing	index of string descriptor
diff --git a/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd b/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd
index 0088aba4caa86969bf6fdb0a79f059a859ea2fdf..5a775b8f654351b29bfcacfb0d1c10afe217ad62 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd
+++ b/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd
@@ -23,3 +23,55 @@ Description:
 		Reading this attribute gives the state of the DbC. It
 		can be one of the following states: disabled, enabled,
 		initialized, connected, configured and stalled.
+
+What:		/sys/bus/pci/drivers/xhci_hcd/.../dbc_idVendor
+Date:		March 2023
+Contact:	Mathias Nyman <mathias.nyman@linux.intel.com>
+Description:
+		This dbc_idVendor attribute lets us change the idVendor field
+		presented in the USB device descriptor by this xhci debug
+		device.
+		Value can only be changed while debug capability (DbC) is in
+		disabled state to prevent USB device descriptor change while
+		connected to a USB host.
+		The default value is 0x1d6b (Linux Foundation).
+		It can be any 16-bit integer.
+
+What:		/sys/bus/pci/drivers/xhci_hcd/.../dbc_idProduct
+Date:		March 2023
+Contact:	Mathias Nyman <mathias.nyman@linux.intel.com>
+Description:
+		This dbc_idProduct attribute lets us change the idProduct field
+		presented in the USB device descriptor by this xhci debug
+		device.
+		Value can only be changed while debug capability (DbC) is in
+		disabled state to prevent USB device descriptor change while
+		connected to a USB host.
+		The default value is 0x0010. It can be any 16-bit integer.
+
+What:		/sys/bus/pci/drivers/xhci_hcd/.../dbc_bcdDevice
+Date:		March 2023
+Contact:	Mathias Nyman <mathias.nyman@linux.intel.com>
+Description:
+		This dbc_bcdDevice attribute lets us change the bcdDevice field
+		presented in the USB device descriptor by this xhci debug
+		device.
+		Value can only be changed while debug capability (DbC) is in
+		disabled state to prevent USB device descriptor change while
+		connected to a USB host.
+		The default value is 0x0010. (device rev 0.10)
+		It can be any 16-bit integer.
+
+What:		/sys/bus/pci/drivers/xhci_hcd/.../dbc_bInterfaceProtocol
+Date:		March 2023
+Contact:	Mathias Nyman <mathias.nyman@linux.intel.com>
+Description:
+		This attribute lets us change the bInterfaceProtocol field
+		presented in the USB Interface descriptor by the xhci debug
+		device.
+		Value can only be changed while debug capability (DbC) is in
+		disabled state to prevent USB descriptor change while
+		connected to a USB host.
+		The default value is 1  (GNU Remote Debug command).
+		Other permissible value is 0 which is for vendor defined debug
+		target.
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 f38a2be07edaa43ce36b78b3e6bb5c0197d1738b..da757c1155d4b083a34deb173a0cc01d25eeeab2 100644
--- a/Documentation/devicetree/bindings/usb/amlogic,meson-g12a-usb-ctrl.yaml
+++ b/Documentation/devicetree/bindings/usb/amlogic,meson-g12a-usb-ctrl.yaml
@@ -2,8 +2,8 @@
 # Copyright 2019 BayLibre, SAS
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/usb/amlogic,meson-g12a-usb-ctrl.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/usb/amlogic,meson-g12a-usb-ctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Amlogic Meson G12A DWC3 USB SoC Controller Glue
 
diff --git a/Documentation/devicetree/bindings/usb/brcm,bcm7445-ehci.yaml b/Documentation/devicetree/bindings/usb/brcm,bcm7445-ehci.yaml
index ad075407d85e8f03060f141a74d417081a8af228..1536cbec63340014c5a728ccb7430b6ff68f797f 100644
--- a/Documentation/devicetree/bindings/usb/brcm,bcm7445-ehci.yaml
+++ b/Documentation/devicetree/bindings/usb/brcm,bcm7445-ehci.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Broadcom STB USB EHCI Controller
 
 allOf:
-  - $ref: "usb-hcd.yaml"
+  - $ref: usb-hcd.yaml
 
 maintainers:
   - Al Cooper <alcooperx@gmail.com>
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
deleted file mode 100644
index 72ceea575d58016ec65ced81901e2d9c3b2edf63..0000000000000000000000000000000000000000
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
+++ /dev/null
@@ -1,159 +0,0 @@
-* USB2 ChipIdea USB controller for ci13xxx
-
-Required properties:
-- compatible: should be one of:
-	"fsl,imx23-usb"
-	"fsl,imx27-usb"
-	"fsl,imx28-usb"
-	"fsl,imx6q-usb"
-	"fsl,imx6sl-usb"
-	"fsl,imx6sx-usb"
-	"fsl,imx6ul-usb"
-	"fsl,imx7d-usb"
-	"fsl,imx7ulp-usb"
-	"fsl,imx8mm-usb"
-	"lsi,zevio-usb"
-	"qcom,ci-hdrc"
-	"chipidea,usb2"
-	"xlnx,zynq-usb-2.20a"
-	"nvidia,tegra20-udc"
-	"nvidia,tegra30-udc"
-	"nvidia,tegra114-udc"
-	"nvidia,tegra124-udc"
-- reg: base address and length of the registers
-- interrupts: interrupt for the USB controller
-
-Recommended properies:
-- phy_type: the type of the phy connected to the core. Should be one
-  of "utmi", "utmi_wide", "ulpi", "serial" or "hsic". Without this
-  property the PORTSC register won't be touched.
-- dr_mode: One of "host", "peripheral" or "otg". Defaults to "otg"
-
-Deprecated properties:
-- usb-phy:      phandle for the PHY device. Use "phys" instead.
-- fsl,usbphy: phandle of usb phy that connects to the port. Use "phys" instead.
-
-Optional properties:
-- clocks: reference to the USB clock
-- phys: reference to the USB PHY
-- phy-names: should be "usb-phy"
-- vbus-supply: reference to the VBUS regulator
-- maximum-speed: limit the maximum connection speed to "full-speed".
-- tpl-support: TPL (Targeted Peripheral List) feature for targeted hosts
-- itc-setting: interrupt threshold control register control, the setting
-  should be aligned with ITC bits at register USBCMD.
-- ahb-burst-config: it is vendor dependent, the required value should be
-  aligned with AHBBRST at SBUSCFG, the range is from 0x0 to 0x7. This
-  property is used to change AHB burst configuration, check the chipidea
-  spec for meaning of each value. If this property is not existed, it
-  will use the reset value.
-- tx-burst-size-dword: it is vendor dependent, the tx burst size in dword
-  (4 bytes), This register represents the maximum length of a the burst
-  in 32-bit words while moving data from system memory to the USB
-  bus, the value of this property will only take effect if property
-  "ahb-burst-config" is set to 0, if this property is missing the reset
-  default of the hardware implementation will be used.
-- rx-burst-size-dword: it is vendor dependent, the rx burst size in dword
-  (4 bytes), This register represents the maximum length of a the burst
-  in 32-bit words while moving data from the USB bus to system memory,
-  the value of this property will only take effect if property
-  "ahb-burst-config" is set to 0, if this property is missing the reset
-  default of the hardware implementation will be used.
-- extcon: phandles to external connector devices. First phandle should point to
-  external connector, which provide "USB" cable events, the second should point
-  to external connector device, which provide "USB-HOST" cable events. If one
-  of the external connector devices is not required, empty <0> phandle should
-  be specified.
-- phy-clkgate-delay-us: the delay time (us) between putting the PHY into
-  low power mode and gating the PHY clock.
-- non-zero-ttctrl-ttha: after setting this property, the value of register
-  ttctrl.ttha will be 0x7f; if not, the value will be 0x0, this is the default
-  value. It needs to be very carefully for setting this property, it is
-  recommended that consult with your IC engineer before setting this value.
-  On the most of chipidea platforms, the "usage_tt" flag at RTL is 0, so this
-  property only affects siTD.
-  If this property is not set, the max packet size is 1023 bytes, and if
-  the total of packet size for pervious transactions are more than 256 bytes,
-  it can't accept any transactions within this frame. The use case is single
-  transaction, but higher frame rate.
-  If this property is set, the max packet size is 188 bytes, it can handle
-  more transactions than above case, it can accept transactions until it
-  considers the left room size within frame is less than 188 bytes, software
-  needs to make sure it does not send more than 90%
-  maximum_periodic_data_per_frame. The use case is multiple transactions, but
-  less frame rate.
-- mux-controls: The mux control for toggling host/device output of this
-  controller. It's expected that a mux state of 0 indicates device mode and a
-  mux state of 1 indicates host mode.
-- mux-control-names: Shall be "usb_switch" if mux-controls is specified.
-- pinctrl-names: Names for optional pin modes in "default", "host", "device".
-  In case of HSIC-mode, "idle" and "active" pin modes are mandatory. In this
-  case, the "idle" state needs to pull down the data and strobe pin
-  and the "active" state needs to pull up the strobe pin.
-- pinctrl-n: alternate pin modes
-
-i.mx specific properties
-- fsl,usbmisc: phandler of non-core register device, with one
-  argument that indicate usb controller index
-- disable-over-current: disable over current detect
-- over-current-active-low: over current signal polarity is active low.
-- over-current-active-high: over current signal polarity is active high.
-  It's recommended to specify the over current polarity.
-- power-active-high: power signal polarity is active high
-- external-vbus-divider: enables off-chip resistor divider for Vbus
-- samsung,picophy-pre-emp-curr-control: HS Transmitter Pre-Emphasis Current
-  Control. This signal controls the amount of current sourced to the
-  USB_OTG*_DP and USB_OTG*_DN pins after a J-to-K or K-to-J transition.
-  The range is from 0x0 to 0x3, the default value is 0x1.
-  Details can refer to TXPREEMPAMPTUNE0 bits of USBNC_n_PHY_CFG1.
-- samsung,picophy-dc-vol-level-adjust: HS DC Voltage Level Adjustment.
-  Adjust the high-speed transmitter DC level voltage.
-  The range is from 0x0 to 0xf, the default value is 0x3.
-  Details can refer to TXVREFTUNE0 bits of USBNC_n_PHY_CFG1.
-
-Example:
-
-	usb@f7ed0000 {
-		compatible = "chipidea,usb2";
-		reg = <0xf7ed0000 0x10000>;
-		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&chip CLKID_USB0>;
-		phys = <&usb_phy0>;
-		phy-names = "usb-phy";
-		vbus-supply = <&reg_usb0_vbus>;
-		itc-setting = <0x4>; /* 4 micro-frames */
-		 /* Incremental burst of unspecified length */
-		ahb-burst-config = <0x0>;
-		tx-burst-size-dword = <0x10>; /* 64 bytes */
-		rx-burst-size-dword = <0x10>;
-		extcon = <0>, <&usb_id>;
-		phy-clkgate-delay-us = <400>;
-		mux-controls = <&usb_switch>;
-		mux-control-names = "usb_switch";
-	};
-
-Example for HSIC:
-
-	usb@2184400 {
-		compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
-		reg = <0x02184400 0x200>;
-		interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&clks IMX6QDL_CLK_USBOH3>;
-		fsl,usbphy = <&usbphynop1>;
-		fsl,usbmisc = <&usbmisc 2>;
-		phy_type = "hsic";
-		dr_mode = "host";
-		ahb-burst-config = <0x0>;
-		tx-burst-size-dword = <0x10>;
-		rx-burst-size-dword = <0x10>;
-		pinctrl-names = "idle", "active";
-		pinctrl-0 = <&pinctrl_usbh2_idle>;
-		pinctrl-1 = <&pinctrl_usbh2_active>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		usbnet: ethernet@1 {
-			compatible = "usb424,9730";
-			reg = <1>;
-		};
-	};
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.yaml b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b26d26c2b023862758f2d284e846c4489df38364
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.yaml
@@ -0,0 +1,448 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/ci-hdrc-usb2.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: USB2 ChipIdea USB controller
+
+maintainers:
+  - Xu Yang <xu.yang_2@nxp.com>
+  - Peng Fan <peng.fan@nxp.com>
+
+properties:
+  compatible:
+    oneOf:
+      - enum:
+          - chipidea,usb2
+          - lsi,zevio-usb
+          - nvidia,tegra20-ehci
+          - nvidia,tegra20-udc
+          - nvidia,tegra30-ehci
+          - nvidia,tegra30-udc
+          - nvidia,tegra114-udc
+          - nvidia,tegra124-udc
+          - qcom,ci-hdrc
+      - items:
+          - enum:
+              - nvidia,tegra114-ehci
+              - nvidia,tegra124-ehci
+              - nvidia,tegra210-ehci
+          - const: nvidia,tegra30-ehci
+      - items:
+          - enum:
+              - fsl,imx23-usb
+              - fsl,imx25-usb
+              - fsl,imx28-usb
+              - fsl,imx50-usb
+              - fsl,imx51-usb
+              - fsl,imx53-usb
+              - fsl,imx6q-usb
+              - fsl,imx6sl-usb
+              - fsl,imx6sx-usb
+              - fsl,imx6ul-usb
+              - fsl,imx7d-usb
+              - fsl,vf610-usb
+          - const: fsl,imx27-usb
+      - items:
+          - const: fsl,imx8dxl-usb
+          - const: fsl,imx7ulp-usb
+          - const: fsl,imx6ul-usb
+      - items:
+          - enum:
+              - fsl,imx8mm-usb
+              - fsl,imx8mn-usb
+          - const: fsl,imx7d-usb
+          - const: fsl,imx27-usb
+      - items:
+          - enum:
+              - fsl,imx6sll-usb
+              - fsl,imx7ulp-usb
+          - const: fsl,imx6ul-usb
+          - const: fsl,imx27-usb
+      - items:
+          - const: xlnx,zynq-usb-2.20a
+          - const: chipidea,usb2
+
+  reg:
+    minItems: 1
+    maxItems: 2
+
+  interrupts:
+    minItems: 1
+    maxItems: 2
+
+  clocks:
+    minItems: 1
+    maxItems: 2
+
+  clock-names:
+    minItems: 1
+    maxItems: 2
+
+  dr_mode: true
+
+  power-domains:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    maxItems: 1
+
+  "#reset-cells":
+    const: 1
+
+  phy_type: true
+
+  itc-setting:
+    description:
+      interrupt threshold control register control, the setting should be
+      aligned with ITC bits at register USBCMD.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  ahb-burst-config:
+    description:
+      it is vendor dependent, the required value should be aligned with
+      AHBBRST at SBUSCFG, the range is from 0x0 to 0x7. This property is
+      used to change AHB burst configuration, check the chipidea spec for
+      meaning of each value. If this property is not existed, it will use
+      the reset value.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0x0
+    maximum: 0x7
+
+  tx-burst-size-dword:
+    description:
+      it is vendor dependent, the tx burst size in dword (4 bytes), This
+      register represents the maximum length of a the burst in 32-bit
+      words while moving data from system memory to the USB bus, the value
+      of this property will only take effect if property "ahb-burst-config"
+      is set to 0, if this property is missing the reset default of the
+      hardware implementation will be used.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0x0
+    maximum: 0x20
+
+  rx-burst-size-dword:
+    description:
+      it is vendor dependent, the rx burst size in dword (4 bytes), This
+      register represents the maximum length of a the burst in 32-bit words
+      while moving data from the USB bus to system memory, the value of
+      this property will only take effect if property "ahb-burst-config"
+      is set to 0, if this property is missing the reset default of the
+      hardware implementation will be used.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0x0
+    maximum: 0x20
+
+  extcon:
+    description:
+      Phandles to external connector devices. First phandle should point
+      to external connector, which provide "USB" cable events, the second
+      should point to external connector device, which provide "USB-HOST"
+      cable events. If one of the external connector devices is not
+      required, empty <0> phandle should be specified.
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    minItems: 1
+    items:
+      - description: vbus extcon
+      - description: id extcon
+
+  phy-clkgate-delay-us:
+    description:
+      The delay time (us) between putting the PHY into low power mode and
+      gating the PHY clock.
+
+  non-zero-ttctrl-ttha:
+    description:
+      After setting this property, the value of register ttctrl.ttha
+      will be 0x7f; if not, the value will be 0x0, this is the default
+      value. It needs to be very carefully for setting this property, it
+      is recommended that consult with your IC engineer before setting
+      this value.  On the most of chipidea platforms, the "usage_tt" flag
+      at RTL is 0, so this property only affects siTD.
+
+      If this property is not set, the max packet size is 1023 bytes, and
+      if the total of packet size for pervious transactions are more than
+      256 bytes, it can't accept any transactions within this frame. The
+      use case is single transaction, but higher frame rate.
+
+      If this property is set, the max packet size is 188 bytes, it can
+      handle more transactions than above case, it can accept transactions
+      until it considers the left room size within frame is less than 188
+      bytes, software needs to make sure it does not send more than 90%
+      maximum_periodic_data_per_frame. The use case is multiple
+      transactions, but less frame rate.
+    type: boolean
+
+  mux-controls:
+    description:
+      The mux control for toggling host/device output of this controller.
+      It's expected that a mux state of 0 indicates device mode and a mux
+      state of 1 indicates host mode.
+    maxItems: 1
+
+  mux-control-names:
+    const: usb_switch
+
+  operating-points-v2:
+    description: A phandle to the OPP table containing the performance states.
+    $ref: /schemas/types.yaml#/definitions/phandle
+
+  pinctrl-names:
+    description:
+      Names for optional pin modes in "default", "host", "device".
+      In case of HSIC-mode, "idle" and "active" pin modes are mandatory.
+      In this case, the "idle" state needs to pull down the data and
+      strobe pin and the "active" state needs to pull up the strobe pin.
+    oneOf:
+      - items:
+          - const: idle
+          - const: active
+      - items:
+          - const: default
+          - enum:
+              - host
+              - device
+      - items:
+          - const: default
+
+  pinctrl-0:
+    maxItems: 1
+
+  pinctrl-1:
+    maxItems: 1
+
+  phys:
+    maxItems: 1
+
+  phy-names:
+    const: usb-phy
+
+  phy-select:
+    description:
+      Phandler of TCSR node with two argument that indicate register
+      offset, and phy index
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    items:
+      - description: phandle to TCSR node
+      - description: register offset
+      - description: phy index
+
+  vbus-supply:
+    description: reference to the VBUS regulator.
+
+  fsl,usbmisc:
+    description:
+      Phandler of non-core register device, with one argument that
+      indicate usb controller index
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    items:
+      - items:
+          - description: phandle to usbmisc node
+          - description: index of usb controller
+
+  fsl,anatop:
+    description: phandle for the anatop node.
+    $ref: /schemas/types.yaml#/definitions/phandle
+
+  disable-over-current:
+    type: boolean
+    description: disable over current detect
+
+  over-current-active-low:
+    type: boolean
+    description: over current signal polarity is active low
+
+  over-current-active-high:
+    type: boolean
+    description:
+      Over current signal polarity is active high. It's recommended to
+      specify the over current polarity.
+
+  power-active-high:
+    type: boolean
+    description: power signal polarity is active high
+
+  external-vbus-divider:
+    type: boolean
+    description: enables off-chip resistor divider for Vbus
+
+  samsung,picophy-pre-emp-curr-control:
+    description:
+      HS Transmitter Pre-Emphasis Current Control. This signal controls
+      the amount of current sourced to the USB_OTG*_DP and USB_OTG*_DN
+      pins after a J-to-K or K-to-J transition. The range is from 0x0 to
+      0x3, the default value is 0x1. Details can refer to TXPREEMPAMPTUNE0
+      bits of USBNC_n_PHY_CFG1.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0x0
+    maximum: 0x3
+
+  samsung,picophy-dc-vol-level-adjust:
+    description:
+      HS DC Voltage Level Adjustment. Adjust the high-speed transmitter DC
+      level voltage. The range is from 0x0 to 0xf, the default value is
+      0x3. Details can refer to TXVREFTUNE0 bits of USBNC_n_PHY_CFG1.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0x0
+    maximum: 0xf
+
+  usb-phy:
+    description: phandle for the PHY device. Use "phys" instead.
+    $ref: /schemas/types.yaml#/definitions/phandle
+    deprecated: true
+
+  fsl,usbphy:
+    description: phandle of usb phy that connects to the port. Use "phys" instead.
+    $ref: /schemas/types.yaml#/definitions/phandle
+    deprecated: true
+
+  nvidia,phy:
+    description: phandle of usb phy that connects to the port. Use "phys" instead.
+    $ref: /schemas/types.yaml#/definitions/phandle
+    deprecated: true
+
+  nvidia,needs-double-reset:
+    description: Indicates double reset or not.
+    type: boolean
+    deprecated: true
+
+  port:
+    description:
+      Any connector to the data bus of this controller should be modelled
+      using the OF graph bindings specified, if the "usb-role-switch"
+      property is used.
+    $ref: /schemas/graph.yaml#/properties/port
+
+  reset-gpios:
+    maxItems: 1
+
+  ulpi:
+    type: object
+    additionalProperties: false
+    patternProperties:
+      "^phy(-[0-9])?$":
+        description: The phy child node for Qcom chips.
+        type: object
+        $ref: /schemas/phy/qcom,usb-hs-phy.yaml
+
+dependencies:
+  port: [ usb-role-switch ]
+  mux-controls: [ mux-control-names ]
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+allOf:
+  - $ref: usb-hcd.yaml#
+  - $ref: usb-drd.yaml#
+  - if:
+      properties:
+        phy_type:
+          const: hsic
+      required:
+        - phy_type
+    then:
+      properties:
+        pinctrl-names:
+          items:
+            - const: idle
+            - const: active
+    else:
+      properties:
+        pinctrl-names:
+          minItems: 1
+          maxItems: 2
+          oneOf:
+            - items:
+                - const: default
+                - enum:
+                    - host
+                    - device
+            - items:
+                - const: default
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - chipidea,usb2
+              - lsi,zevio-usb
+              - nvidia,tegra20-udc
+              - nvidia,tegra30-udc
+              - nvidia,tegra114-udc
+              - nvidia,tegra124-udc
+              - qcom,ci-hdrc
+              - xlnx,zynq-usb-2.20a
+    then:
+      properties:
+        fsl,usbmisc: false
+        disable-over-current: false
+        over-current-active-low: false
+        over-current-active-high: false
+        power-active-high: false
+        external-vbus-divider: false
+        samsung,picophy-pre-emp-curr-control: false
+        samsung,picophy-dc-vol-level-adjust: false
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/berlin2.h>
+
+    usb@f7ed0000 {
+        compatible = "chipidea,usb2";
+        reg = <0xf7ed0000 0x10000>;
+        interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&chip CLKID_USB0>;
+        phys = <&usb_phy0>;
+        phy-names = "usb-phy";
+        vbus-supply = <&reg_usb0_vbus>;
+        itc-setting = <0x4>; /* 4 micro-frames */
+         /* Incremental burst of unspecified length */
+        ahb-burst-config = <0x0>;
+        tx-burst-size-dword = <0x10>; /* 64 bytes */
+        rx-burst-size-dword = <0x10>;
+        extcon = <0>, <&usb_id>;
+        phy-clkgate-delay-us = <400>;
+        mux-controls = <&usb_switch>;
+        mux-control-names = "usb_switch";
+    };
+
+  # Example for HSIC:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/imx6qdl-clock.h>
+
+    usb@2184400 {
+        compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+        reg = <0x02184400 0x200>;
+        interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&clks IMX6QDL_CLK_USBOH3>;
+        fsl,usbphy = <&usbphynop1>;
+        fsl,usbmisc = <&usbmisc 2>;
+        phy_type = "hsic";
+        dr_mode = "host";
+        ahb-burst-config = <0x0>;
+        tx-burst-size-dword = <0x10>;
+        rx-burst-size-dword = <0x10>;
+        pinctrl-names = "idle", "active";
+        pinctrl-0 = <&pinctrl_usbh2_idle>;
+        pinctrl-1 = <&pinctrl_usbh2_active>;
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        ethernet@1 {
+            compatible = "usb424,9730";
+            reg = <1>;
+        };
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/usb/dwc2.yaml b/Documentation/devicetree/bindings/usb/dwc2.yaml
index 371ba93f3ce5895c17e440c5d4d27ea2a541f39a..d3506090f8b142d9b4fbf3212b1c06e607f41285 100644
--- a/Documentation/devicetree/bindings/usb/dwc2.yaml
+++ b/Documentation/devicetree/bindings/usb/dwc2.yaml
@@ -75,11 +75,14 @@ properties:
     maxItems: 1
 
   clocks:
-    maxItems: 1
+    minItems: 1
+    maxItems: 2
 
   clock-names:
     items:
       - const: otg
+      - const: utmi
+    minItems: 1
 
   disable-over-current:
     type: boolean
diff --git a/Documentation/devicetree/bindings/usb/fcs,fsa4480.yaml b/Documentation/devicetree/bindings/usb/fcs,fsa4480.yaml
index 51120fe903223c289be82dd920a5fe44d469b0dc..f6e7a5c1ff0b0998d00b49b8843ce90776b123a3 100644
--- a/Documentation/devicetree/bindings/usb/fcs,fsa4480.yaml
+++ b/Documentation/devicetree/bindings/usb/fcs,fsa4480.yaml
@@ -1,8 +1,8 @@
 # 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#"
+$id: http://devicetree.org/schemas/usb/fcs,fsa4480.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: ON Semiconductor Analog Audio Switch
 
diff --git a/Documentation/devicetree/bindings/usb/fsl,imx8mq-dwc3.yaml b/Documentation/devicetree/bindings/usb/fsl,imx8mq-dwc3.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..50569d3ee76708aa46a02fd39dfb180961264c13
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/fsl,imx8mq-dwc3.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/fsl,imx8mq-dwc3.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP iMX8MQ Soc USB Controller
+
+maintainers:
+  - Li Jun <jun.li@nxp.com>
+  - Peng Fan <peng.fan@nxp.com>
+
+select:
+  properties:
+    compatible:
+      contains:
+        enum:
+          - fsl,imx8mq-dwc3
+  required:
+    - compatible
+
+properties:
+  compatible:
+    items:
+      - const: fsl,imx8mq-dwc3
+      - const: snps,dwc3
+
+allOf:
+  - $ref: snps,dwc3.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/imx8mq-clock.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    usb_dwc3_1: usb@38200000 {
+        compatible = "fsl,imx8mq-dwc3", "snps,dwc3";
+        reg = <0x38200000 0x10000>;
+        clocks = <&clk IMX8MQ_CLK_USB2_CTRL_ROOT>,
+                 <&clk IMX8MQ_CLK_USB_CORE_REF>,
+                 <&clk IMX8MQ_CLK_32K>;
+        clock-names = "bus_early", "ref", "suspend";
+        interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+        phys = <&usb3_phy1>, <&usb3_phy1>;
+        phy-names = "usb2-phy", "usb3-phy";
+    };
diff --git a/Documentation/devicetree/bindings/usb/fsl,usbmisc.yaml b/Documentation/devicetree/bindings/usb/fsl,usbmisc.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..2d3589d284b220a0623a538cedd094b70c2797d1
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/fsl,usbmisc.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/fsl,usbmisc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX wrapper module for Chipidea USB2 controller
+
+maintainers:
+  - Xu Yang <xu.yang_2@nxp.com>
+  - Peng Fan <peng.fan@nxp.com>
+
+properties:
+  compatible:
+    oneOf:
+      - enum:
+          - fsl,imx25-usbmisc
+          - fsl,imx27-usbmisc
+          - fsl,imx35-usbmisc
+          - fsl,imx51-usbmisc
+          - fsl,imx53-usbmisc
+          - fsl,imx6q-usbmisc
+          - fsl,vf610-usbmisc
+      - items:
+          - enum:
+              - fsl,imx6ul-usbmisc
+              - fsl,imx6sl-usbmisc
+              - fsl,imx6sx-usbmisc
+              - fsl,imx7d-usbmisc
+          - const: fsl,imx6q-usbmisc
+      - items:
+          - enum:
+              - fsl,imx7ulp-usbmisc
+              - fsl,imx8mm-usbmisc
+              - fsl,imx8mn-usbmisc
+          - const: fsl,imx7d-usbmisc
+          - const: fsl,imx6q-usbmisc
+      - items:
+          - const: fsl,imx6sll-usbmisc
+          - const: fsl,imx6ul-usbmisc
+          - const: fsl,imx6q-usbmisc
+
+  clocks:
+    maxItems: 1
+
+  reg:
+    maxItems: 1
+
+  '#index-cells':
+    const: 1
+    description: Cells used to describe usb controller index.
+    deprecated: true
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    usbmisc@2184800 {
+        compatible = "fsl,imx6q-usbmisc";
+        reg = <0x02184800 0x200>;
+        #index-cells = <1>;
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/usb/generic-ehci.yaml b/Documentation/devicetree/bindings/usb/generic-ehci.yaml
index 050cfd5acdaa18ec3ac91c1f5b80df2d6e11c345..9445764bd8de7f49ef7197f47db74109cca262e5 100644
--- a/Documentation/devicetree/bindings/usb/generic-ehci.yaml
+++ b/Documentation/devicetree/bindings/usb/generic-ehci.yaml
@@ -10,7 +10,7 @@ maintainers:
   - Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 
 allOf:
-  - $ref: "usb-hcd.yaml"
+  - $ref: usb-hcd.yaml
   - if:
       properties:
         compatible:
diff --git a/Documentation/devicetree/bindings/usb/generic-ohci.yaml b/Documentation/devicetree/bindings/usb/generic-ohci.yaml
index a9ba7257b884288ac18e956d36411b3ec4c7e0b9..d06d1e7d8876255f85f77418e0fabcb4d533ef77 100644
--- a/Documentation/devicetree/bindings/usb/generic-ohci.yaml
+++ b/Documentation/devicetree/bindings/usb/generic-ohci.yaml
@@ -148,7 +148,7 @@ allOf:
       properties:
         transceiver: false
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
diff --git a/Documentation/devicetree/bindings/usb/generic-xhci.yaml b/Documentation/devicetree/bindings/usb/generic-xhci.yaml
index db841589fc334f602e5032adbf258eb7f4d6ecba..594ebb3ee432037f98adaa3e7cfcdaa4fae81ff2 100644
--- a/Documentation/devicetree/bindings/usb/generic-xhci.yaml
+++ b/Documentation/devicetree/bindings/usb/generic-xhci.yaml
@@ -10,7 +10,7 @@ maintainers:
   - Mathias Nyman <mathias.nyman@intel.com>
 
 allOf:
-  - $ref: "usb-xhci.yaml#"
+  - $ref: usb-xhci.yaml#
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/usb/gpio-sbu-mux.yaml b/Documentation/devicetree/bindings/usb/gpio-sbu-mux.yaml
index bf4b1d016e1f8d87b75c804bc03bec9921229b63..f196beb826d8d34aad5bd8de4de90d44e1b38f61 100644
--- a/Documentation/devicetree/bindings/usb/gpio-sbu-mux.yaml
+++ b/Documentation/devicetree/bindings/usb/gpio-sbu-mux.yaml
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/usb/gpio-sbu-mux.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/usb/gpio-sbu-mux.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: GPIO-based SBU mux
 
diff --git a/Documentation/devicetree/bindings/usb/maxim,max33359.yaml b/Documentation/devicetree/bindings/usb/maxim,max33359.yaml
index 3cb631ea7079c0fc00b3a3057de7a099f515794f..276bf7554215e6ec8a71cb46faedf48d7b13087e 100644
--- a/Documentation/devicetree/bindings/usb/maxim,max33359.yaml
+++ b/Documentation/devicetree/bindings/usb/maxim,max33359.yaml
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/usb/maxim,max33359.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/usb/maxim,max33359.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Maxim TCPCI Type-C PD controller
 
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mt6360-tcpc.yaml b/Documentation/devicetree/bindings/usb/mediatek,mt6360-tcpc.yaml
index 6cad7ae2c70dc9a5b3cc9a77f15ecfcb8aa3ed1e..053264e605836d7875493a37f7ac92fa5dce2dc6 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mt6360-tcpc.yaml
+++ b/Documentation/devicetree/bindings/usb/mediatek,mt6360-tcpc.yaml
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/usb/mediatek,mt6360-tcpc.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/usb/mediatek,mt6360-tcpc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Mediatek MT6360 Type-C Port Switch and Power Delivery controller
 
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mt6370-tcpc.yaml b/Documentation/devicetree/bindings/usb/mediatek,mt6370-tcpc.yaml
index 72f56cc88457436f60a00c85b7c0624c5886f44f..747d0f16d9b6e88387addb3b98a6aecc32272eda 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mt6370-tcpc.yaml
+++ b/Documentation/devicetree/bindings/usb/mediatek,mt6370-tcpc.yaml
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/usb/mediatek,mt6370-tcpc.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/usb/mediatek,mt6370-tcpc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: MediatTek MT6370 Type-C Port Switch and Power Delivery controller
 
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
index c119caa9ad168c78420e569e7fc21d9e9d9d4363..e9644e333d78135d83c3bc88cf903960140315f5 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
@@ -11,7 +11,7 @@ maintainers:
   - Chunfeng Yun <chunfeng.yun@mediatek.com>
 
 allOf:
-  - $ref: "usb-xhci.yaml"
+  - $ref: usb-xhci.yaml
 
 description: |
   There are two scenarios:
@@ -77,6 +77,7 @@ properties:
       - description: Mcu bus clock for register access
       - description: DMA bus clock for data transfer
       - description: controller clock
+      - description: frame count clock
 
   clock-names:
     minItems: 1
@@ -86,14 +87,7 @@ properties:
       - const: mcu_ck
       - const: dma_ck
       - const: xhci_ck
-
-  assigned-clocks:
-    minItems: 1
-    maxItems: 5
-
-  assigned-clock-parents:
-    minItems: 1
-    maxItems: 5
+      - const: frmcnt_ck
 
   phys:
     description:
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml b/Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml
index d2655173e108cfa471f8a7e197e19d74767fe8b2..478214ab045e3b15e89e41b02364b72ee236d91a 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml
@@ -11,7 +11,7 @@ maintainers:
   - Chunfeng Yun <chunfeng.yun@mediatek.com>
 
 allOf:
-  - $ref: "usb-drd.yaml"
+  - $ref: usb-drd.yaml
 
 description: |
   The DRD controller has a glue layer IPPC (IP Port Control), and its host is
@@ -66,6 +66,8 @@ properties:
       - description: Reference clock used by low power mode etc
       - description: Mcu bus clock for register access
       - description: DMA bus clock for data transfer
+      - description: DRD controller clock
+      - description: Frame count clock
 
   clock-names:
     minItems: 1
@@ -74,6 +76,8 @@ properties:
       - const: ref_ck
       - const: mcu_ck
       - const: dma_ck
+      - const: xhci_ck
+      - const: frmcnt_ck
 
   phys:
     description:
@@ -204,9 +208,9 @@ patternProperties:
       example if the host mode is enabled.
 
 dependencies:
-  connector: [ 'usb-role-switch' ]
-  port: [ 'usb-role-switch' ]
-  role-switch-default-mode: [ 'usb-role-switch' ]
+  connector: [ usb-role-switch ]
+  port: [ usb-role-switch ]
+  role-switch-default-mode: [ usb-role-switch ]
   wakeup-source: [ 'mediatek,syscon-wakeup' ]
 
 required:
diff --git a/Documentation/devicetree/bindings/usb/mediatek,musb.yaml b/Documentation/devicetree/bindings/usb/mediatek,musb.yaml
index f16ab30a95d274083597faf55dda3ee89c98de9a..a39d38db7714719c110909fb424b5d43d2e66272 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,musb.yaml
+++ b/Documentation/devicetree/bindings/usb/mediatek,musb.yaml
@@ -68,8 +68,8 @@ properties:
     type: object
 
 dependencies:
-  usb-role-switch: [ 'connector' ]
-  connector: [ 'usb-role-switch' ]
+  usb-role-switch: [ connector ]
+  connector: [ usb-role-switch ]
 
 required:
   - compatible
diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml b/Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml
index e638f77658fc1bee023d184501e090803ecdfd68..e2270ce0c56b2af67f96556193f28564835ea44a 100644
--- a/Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/usb/nvidia,tegra-xudc.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/usb/nvidia,tegra-xudc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: NVIDIA Tegra XUSB device mode controller (XUDC)
 
diff --git a/Documentation/devicetree/bindings/usb/nxp,ptn5110.yaml b/Documentation/devicetree/bindings/usb/nxp,ptn5110.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..28eb25ecba74ee1633c24ad726d1834ba60a2d9b
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/nxp,ptn5110.yaml
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/nxp,ptn5110.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP PTN5110 Typec Port Cotroller
+
+maintainers:
+  - Li Jun <jun.li@nxp.com>
+
+properties:
+  compatible:
+    const: nxp,ptn5110
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  connector:
+    type: object
+    $ref: /schemas/connector/usb-connector.yaml#
+    unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - connector
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/usb/pd.h>
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        tcpci@50 {
+            compatible = "nxp,ptn5110";
+            reg = <0x50>;
+            interrupt-parent = <&gpio3>;
+            interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+
+            usb_con: connector {
+                compatible = "usb-c-connector";
+                label = "USB-C";
+                data-role = "dual";
+                power-role = "dual";
+                try-power-role = "sink";
+                source-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)>;
+                sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM) PDO_VAR(5000, 12000, 2000)>;
+                op-sink-microwatt = <10000000>;
+
+                ports {
+                    #address-cells = <1>;
+                    #size-cells = <0>;
+
+                    port@0 {
+                       reg = <0>;
+                       typec1_dr_sw: endpoint {
+                           remote-endpoint = <&usb1_drd_sw>;
+                       };
+                    };
+                };
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
index 3e401014e3bc298e9f890bfde98aa9547ddd80a6..d84281926f10bdf8e092c826a4d4b0c7af4364de 100644
--- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
@@ -21,6 +21,7 @@ properties:
           - qcom,msm8994-dwc3
           - qcom,msm8996-dwc3
           - qcom,msm8998-dwc3
+          - qcom,qcm2290-dwc3
           - qcom,qcs404-dwc3
           - qcom,sc7180-dwc3
           - qcom,sc7280-dwc3
@@ -301,6 +302,7 @@ allOf:
         compatible:
           contains:
             enum:
+              - qcom,qcm2290-dwc3
               - qcom,sm6115-dwc3
               - qcom,sm6125-dwc3
               - qcom,sm8150-dwc3
diff --git a/Documentation/devicetree/bindings/usb/realtek,rts5411.yaml b/Documentation/devicetree/bindings/usb/realtek,rts5411.yaml
index 623d04a88a81750ddc0e3359d5e8c9b24a875206..9309f003cd07aef66a19c5d37ee139cede1d3e22 100644
--- a/Documentation/devicetree/bindings/usb/realtek,rts5411.yaml
+++ b/Documentation/devicetree/bindings/usb/realtek,rts5411.yaml
@@ -26,7 +26,7 @@ properties:
       phandle to the regulator that provides power to the hub.
 
   peer-hub:
-    $ref: '/schemas/types.yaml#/definitions/phandle'
+    $ref: /schemas/types.yaml#/definitions/phandle
     description:
       phandle to the peer hub on the controller.
 
diff --git a/Documentation/devicetree/bindings/usb/richtek,rt1711h.yaml b/Documentation/devicetree/bindings/usb/richtek,rt1711h.yaml
index dd864b25a148efce8ce10e3636d66a65953071dc..8da4d2ad1a91bf10fe8dc0f06f2297c820ebff02 100644
--- a/Documentation/devicetree/bindings/usb/richtek,rt1711h.yaml
+++ b/Documentation/devicetree/bindings/usb/richtek,rt1711h.yaml
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/usb/richtek,rt1711h.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/usb/richtek,rt1711h.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Richtek RT1711H Type-C Port Switch and Power Delivery controller
 
diff --git a/Documentation/devicetree/bindings/usb/richtek,rt1719.yaml b/Documentation/devicetree/bindings/usb/richtek,rt1719.yaml
index 8b9bd2cc58e94b538743e5fe20fe022c9f1cb81d..4ced2f68e2a9550d71235aff7bcba87b1481496a 100644
--- a/Documentation/devicetree/bindings/usb/richtek,rt1719.yaml
+++ b/Documentation/devicetree/bindings/usb/richtek,rt1719.yaml
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/usb/richtek,rt1719.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/usb/richtek,rt1719.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Richtek RT1719 sink-only Type-C PD controller
 
diff --git a/Documentation/devicetree/bindings/usb/smsc,usb3503.yaml b/Documentation/devicetree/bindings/usb/smsc,usb3503.yaml
index a09f4528aea3c257042e7a9eb5c0ab52ca6cdea2..6156dc26e65c7807495fcf1238f12c4592edb0ef 100644
--- a/Documentation/devicetree/bindings/usb/smsc,usb3503.yaml
+++ b/Documentation/devicetree/bindings/usb/smsc,usb3503.yaml
@@ -14,6 +14,7 @@ properties:
     enum:
       - smsc,usb3503
       - smsc,usb3503a
+      - smsc,usb3803
 
   reg:
     maxItems: 1
@@ -33,6 +34,12 @@ properties:
     description: >
       GPIO for reset
 
+  bypass-gpios:
+    maxItems: 1
+    description: >
+      GPIO for bypass.
+      Control signal to select between HUB MODE and BYPASS MODE.
+
   disabled-ports:
     $ref: /schemas/types.yaml#/definitions/uint32-array
     minItems: 1
@@ -46,9 +53,10 @@ properties:
 
   initial-mode:
     $ref: /schemas/types.yaml#/definitions/uint32
-    enum: [1, 2]
     description: >
-      Specifies initial mode. 1 for Hub mode, 2 for standby mode.
+      Specifies initial mode. 1 for Hub mode, 2 for standby mode and 3 for bypass mode.
+      In bypass mode the downstream port 3 is connected to the upstream port with low
+      switch resistance R_on.
 
   clocks:
     maxItems: 1
@@ -71,6 +79,29 @@ properties:
 required:
   - compatible
 
+allOf:
+  - if:
+      not:
+        properties:
+          compatible:
+            enum:
+              - smsc,usb3803
+    then:
+      properties:
+        bypass-gpios: false
+
+  - if:
+      required:
+        - bypass-gpios
+    then:
+      properties:
+        initial-mode:
+          enum: [1, 2, 3]
+    else:
+      properties:
+        initial-mode:
+          enum: [1, 2]
+
 additionalProperties: false
 
 examples:
@@ -92,6 +123,25 @@ examples:
           };
       };
 
+  - |
+      i2c {
+          #address-cells = <1>;
+          #size-cells = <0>;
+
+          usb-hub@8 {
+              compatible = "smsc,usb3803";
+              reg = <0x08>;
+              connect-gpios = <&gpx3 0 1>;
+              disabled-ports = <2 3>;
+              intn-gpios = <&gpx3 4 1>;
+              reset-gpios = <&gpx3 5 1>;
+              bypass-gpios = <&gpx3 6 1>;
+              initial-mode = <3>;
+              clocks = <&clks 80>;
+              clock-names = "refclk";
+          };
+      };
+
   - |
       #include <dt-bindings/gpio/gpio.h>
 
diff --git a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
index be36956af53b0c8a2def1b476f8be2d5155aa2b5..50edc4da780e9caf68f7821bcff9c06ffa80bba2 100644
--- a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
@@ -70,6 +70,10 @@ properties:
 
   dma-coherent: true
 
+  extcon:
+    maxItems: 1
+    deprecated: true
+
   iommus:
     maxItems: 1
 
@@ -232,6 +236,11 @@ properties:
       When set, all SuperSpeed bus instances in park mode are disabled.
     type: boolean
 
+  snps,parkmode-disable-hs-quirk:
+    description:
+      When set, all HighSpeed bus instances in park mode are disabled.
+    type: boolean
+
   snps,dis_metastability_quirk:
     description:
       When set, disable metastability workaround. CAUTION! Use only if you are
@@ -256,6 +265,14 @@ properties:
       of resume. This option is to support certain legacy ULPI PHYs.
     type: boolean
 
+  snps,ulpi-ext-vbus-drv:
+    description:
+      Some ULPI USB PHY does not support internal VBUS supply, and driving
+      the CPEN pin, requires the configuration of the ulpi DRVVBUSEXTERNAL
+      bit. When set, the xhci host will configure the USB2 PHY drives VBUS
+      with an external supply.
+    type: boolean
+
   snps,is-utmi-l1-suspend:
     description:
       True when DWC3 asserts output signal utmi_l1_suspend_n, false when
@@ -365,6 +382,22 @@ properties:
       This port is used with the 'usb-role-switch' property  to connect the
       dwc3 to type C connector.
 
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+    description:
+      Those ports should be used with any connector to the data bus of this
+      controller using the OF graph bindings specified if the "usb-role-switch"
+      property is used.
+
+    properties:
+      port@0:
+        $ref: /schemas/graph.yaml#/properties/port
+        description: High Speed (HS) data bus.
+
+      port@1:
+        $ref: /schemas/graph.yaml#/properties/port
+        description: Super Speed (SS) data bus.
+
   wakeup-source:
     $ref: /schemas/types.yaml#/definitions/flag
     description:
diff --git a/Documentation/devicetree/bindings/usb/st,stusb160x.yaml b/Documentation/devicetree/bindings/usb/st,stusb160x.yaml
index f6840cd5750d40fa0ed4d912d2b1f13fc0faf0af..acda2f47fbc993ac6aa987d27077a180db17c54d 100644
--- a/Documentation/devicetree/bindings/usb/st,stusb160x.yaml
+++ b/Documentation/devicetree/bindings/usb/st,stusb160x.yaml
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/usb/st,stusb160x.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/usb/st,stusb160x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: STMicroelectronics STUSB160x Type-C controller
 
diff --git a/Documentation/devicetree/bindings/usb/ti,j721e-usb.yaml b/Documentation/devicetree/bindings/usb/ti,j721e-usb.yaml
index f81ba3e902973c087680f7fc0b8de5345548915d..95ff9791baea09c76e13e144d86b5946b4aa5ded 100644
--- a/Documentation/devicetree/bindings/usb/ti,j721e-usb.yaml
+++ b/Documentation/devicetree/bindings/usb/ti,j721e-usb.yaml
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/usb/ti,j721e-usb.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/usb/ti,j721e-usb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: TI wrapper module for the Cadence USBSS-DRD controller
 
@@ -53,12 +53,6 @@ properties:
       VBUS pin of the SoC via a 1/3 voltage divider.
     type: boolean
 
-  assigned-clocks:
-    maxItems: 1
-
-  assigned-clock-parents:
-    maxItems: 1
-
   '#address-cells':
     const: 2
 
diff --git a/Documentation/devicetree/bindings/usb/ti,keystone-dwc3.yaml b/Documentation/devicetree/bindings/usb/ti,keystone-dwc3.yaml
index c1f0194ad0d526b0b6b3530e5c3c098c7a9a36a5..9252d893f6947746c0ad439421ee5cef2664bdbc 100644
--- a/Documentation/devicetree/bindings/usb/ti,keystone-dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/ti,keystone-dwc3.yaml
@@ -34,14 +34,6 @@ properties:
     minItems: 1
     maxItems: 2
 
-  assigned-clocks:
-    minItems: 1
-    maxItems: 2
-
-  assigned-clock-parents:
-    minItems: 1
-    maxItems: 2
-
   power-domains:
     maxItems: 1
     description: Should contain a phandle to a PM domain provider node
diff --git a/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml b/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml
index 7dfa34d11b0e5ce2202298bb937c8c9c8e23ac34..5497a60cddbc6949699af1bc3d8aeeccc70393c4 100644
--- a/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml
+++ b/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/usb/ti,tps6598x.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/usb/ti,tps6598x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Texas Instruments 6598x Type-C Port Switch and Power Delivery controller
 
@@ -35,8 +35,6 @@ properties:
 required:
   - compatible
   - reg
-  - interrupts
-  - interrupt-names
 
 additionalProperties: true
 
diff --git a/Documentation/devicetree/bindings/usb/typec-tcpci.txt b/Documentation/devicetree/bindings/usb/typec-tcpci.txt
deleted file mode 100644
index 2082522b1c326069e3b622508669a4b77a33034d..0000000000000000000000000000000000000000
--- a/Documentation/devicetree/bindings/usb/typec-tcpci.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-TCPCI(Typec port cotroller interface) binding
----------------------------------------------
-
-Required properties:
-- compatible:       should be set one of following:
-		    - "nxp,ptn5110" for NXP USB PD TCPC PHY IC ptn5110.
-
-- reg:              the i2c slave address of typec port controller device.
-- interrupt-parent: the phandle to the interrupt controller which provides
-                    the interrupt.
-- interrupts:       interrupt specification for tcpci alert.
-
-Required sub-node:
-- connector: The "usb-c-connector" attached to the tcpci chip, the bindings
-  of connector node are specified in
-  Documentation/devicetree/bindings/connector/usb-connector.yaml
-
-Example:
-
-ptn5110@50 {
-	compatible = "nxp,ptn5110";
-	reg = <0x50>;
-	interrupt-parent = <&gpio3>;
-	interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
-
-	usb_con: connector {
-		compatible = "usb-c-connector";
-		label = "USB-C";
-		data-role = "dual";
-		power-role = "dual";
-		try-power-role = "sink";
-		source-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)>;
-		sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)
-			     PDO_VAR(5000, 12000, 2000)>;
-		op-sink-microwatt = <10000000>;
-
-		ports {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			port@1 {
-				reg = <1>;
-				usb_con_ss: endpoint {
-					remote-endpoint = <&usb3_data_ss>;
-				};
-			};
-		};
-	};
-};
diff --git a/Documentation/devicetree/bindings/usb/usb-device.yaml b/Documentation/devicetree/bindings/usb/usb-device.yaml
index 7a771125ec76c30afe8ab2248ac0aec2751ab576..da890ee60ce6e71a11910c565b6f805470782e4f 100644
--- a/Documentation/devicetree/bindings/usb/usb-device.yaml
+++ b/Documentation/devicetree/bindings/usb/usb-device.yaml
@@ -76,7 +76,6 @@ patternProperties:
         maxItems: 1
 
 required:
-  - compatible
   - reg
 
 additionalProperties: true
diff --git a/Documentation/devicetree/bindings/usb/usb-nop-xceiv.yaml b/Documentation/devicetree/bindings/usb/usb-nop-xceiv.yaml
index 921b986adc477e2de02439e1f45e9ed0a391f18c..6734f4d3aa789f829ed8bbb8c7cf5f7e8b03f7eb 100644
--- a/Documentation/devicetree/bindings/usb/usb-nop-xceiv.yaml
+++ b/Documentation/devicetree/bindings/usb/usb-nop-xceiv.yaml
@@ -27,6 +27,9 @@ properties:
   vcc-supply:
     description: phandle to the regulator that provides power to the PHY.
 
+  power-domains:
+    maxItems: 1
+
   reset-gpios:
     maxItems: 1
 
diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.yaml b/Documentation/devicetree/bindings/usb/usb-xhci.yaml
index f2139a9f35fb8e944b5feff936be3db10f0d7e21..180a261c3e8f376311ffcfca624ec14332f807ae 100644
--- a/Documentation/devicetree/bindings/usb/usb-xhci.yaml
+++ b/Documentation/devicetree/bindings/usb/usb-xhci.yaml
@@ -10,7 +10,7 @@ maintainers:
   - Mathias Nyman <mathias.nyman@intel.com>
 
 allOf:
-  - $ref: "usb-hcd.yaml#"
+  - $ref: usb-hcd.yaml#
 
 properties:
   usb2-lpm-disable:
diff --git a/Documentation/devicetree/bindings/usb/usbmisc-imx.txt b/Documentation/devicetree/bindings/usb/usbmisc-imx.txt
deleted file mode 100644
index 29b8f65ff849d7337bffda7f4af3186d8c1347da..0000000000000000000000000000000000000000
--- a/Documentation/devicetree/bindings/usb/usbmisc-imx.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-* Freescale i.MX non-core registers
-
-Required properties:
-- #index-cells: Cells used to describe usb controller index. Should be <1>
-- compatible: Should be one of below:
-	"fsl,imx6q-usbmisc" for imx6q
-	"fsl,vf610-usbmisc" for Vybrid vf610
-	"fsl,imx6sx-usbmisc" for imx6sx
-	"fsl,imx7d-usbmisc" for imx7d
-	"fsl,imx7ulp-usbmisc" for imx7ulp
-	"fsl,imx8mm-usbmisc" for imx8mm
-- reg: Should contain registers location and length
-
-Examples:
-usbmisc@2184800 {
-	#index-cells = <1>;
-	compatible = "fsl,imx6q-usbmisc";
-	reg = <0x02184800 0x200>;
-};
diff --git a/Documentation/usb/gadget_uvc.rst b/Documentation/usb/gadget_uvc.rst
index 6d22faceb1a0b309c9502aad2629d512cb90a6b4..62bd81ba3dd1fe6f7426eb58baac2e62360fdc0d 100644
--- a/Documentation/usb/gadget_uvc.rst
+++ b/Documentation/usb/gadget_uvc.rst
@@ -275,6 +275,34 @@ out with 0x00, for example:
 
 bNrInPins and baSourceID function in the same way.
 
+Configuring Supported Controls for Camera Terminal and Processing Unit
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The Camera Terminal and Processing Units in the UVC chain also have bmControls
+attributes which function similarly to the same field in an Extension Unit.
+Unlike XUs however, the meaning of the bitflag for these units is defined in
+the UVC specification; you should consult the "Camera Terminal Descriptor" and
+"Processing Unit Descriptor" sections for an enumeration of the flags.
+
+.. code-block:: bash
+
+        # Set the Processing Unit's bmControls, flagging Brightness, Contrast
+        # and Hue as available controls:
+        echo 0x05 > $FUNCTION/control/processing/default/bmControls
+
+        # Set the Camera Terminal's bmControls, flagging Focus Absolute and
+        # Focus Relative as available controls:
+        echo 0x60 > $FUNCTION/control/terminal/camera/default/bmControls
+
+If you do not set these fields then by default the Auto-Exposure Mode control
+for the Camera Terminal and the Brightness control for the Processing Unit will
+be flagged as available; if they are not supported you should set the field to
+0x00.
+
+Note that the size of the bmControls field for a Camera Terminal or Processing
+Unit is fixed by the UVC specification, and so the bControlSize attribute is
+read-only here.
+
 Custom Strings Support
 ~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
index 7f7d2d5122fb629f437e84eb6b3008575de8ba4c..f91bf719d4e2fc418e57dcf31f58946a963c7aa7 100644
--- a/arch/arm/boot/dts/imx7ulp.dtsi
+++ b/arch/arm/boot/dts/imx7ulp.dtsi
@@ -189,7 +189,7 @@ tpm5: tpm@40260000 {
 		};
 
 		usbotg1: usb@40330000 {
-			compatible = "fsl,imx7ulp-usb", "fsl,imx6ul-usb";
+			compatible = "fsl,imx7ulp-usb", "fsl,imx6ul-usb", "fsl,imx27-usb";
 			reg = <0x40330000 0x200>;
 			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&pcc2 IMX7ULP_CLK_USB0>;
@@ -202,7 +202,8 @@ usbotg1: usb@40330000 {
 		};
 
 		usbmisc1: usbmisc@40330200 {
-			compatible = "fsl,imx7ulp-usbmisc", "fsl,imx7d-usbmisc";
+			compatible = "fsl,imx7ulp-usbmisc", "fsl,imx7d-usbmisc",
+				     "fsl,imx6q-usbmisc";
 			#index-cells = <1>;
 			reg = <0x40330200 0x200>;
 		};
diff --git a/arch/arm/boot/dts/stm32mp151.dtsi b/arch/arm/boot/dts/stm32mp151.dtsi
index 4e437d3f2ed66e7bcc203f3a240ad0f29d083b0b..63f4c78fcc1dc9a4cc0d76ec27ff6a8364a07280 100644
--- a/arch/arm/boot/dts/stm32mp151.dtsi
+++ b/arch/arm/boot/dts/stm32mp151.dtsi
@@ -1130,8 +1130,8 @@ sdmmc3: mmc@48004000 {
 		usbotg_hs: usb-otg@49000000 {
 			compatible = "st,stm32mp15-hsotg", "snps,dwc2";
 			reg = <0x49000000 0x10000>;
-			clocks = <&rcc USBO_K>;
-			clock-names = "otg";
+			clocks = <&rcc USBO_K>, <&usbphyc>;
+			clock-names = "otg", "utmi";
 			resets = <&rcc USBO_R>;
 			reset-names = "dwc2";
 			interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
index b32c2e199c160669bada51721e59f7b44a3abc28..2209c1ac6e9b011726b31b4269deac85b6445a92 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
@@ -35,7 +35,7 @@ conn_ipg_clk: clock-conn-ipg {
 	};
 
 	usbotg1: usb@5b0d0000 {
-		compatible = "fsl,imx7ulp-usb";
+		compatible = "fsl,imx7ulp-usb", "fsl,imx6ul-usb", "fsl,imx27-usb";
 		reg = <0x5b0d0000 0x200>;
 		interrupt-parent = <&gic>;
 		interrupts = <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>;
@@ -51,7 +51,7 @@ usbotg1: usb@5b0d0000 {
 
 	usbmisc1: usbmisc@5b0d0200 {
 		#index-cells = <1>;
-		compatible = "fsl,imx7ulp-usbmisc", "fsl,imx6q-usbmisc";
+		compatible = "fsl,imx7ulp-usbmisc", "fsl,imx7d-usbmisc", "fsl,imx6q-usbmisc";
 		reg = <0x5b0d0200 0x200>;
 	};
 
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
index ca195e6d8f37a71cb34d84a24851c6cdb606d20a..652493ae4bb52e2771fcf94c08cdfa68b8eb1e63 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
@@ -34,7 +34,7 @@ eqos: ethernet@5b050000 {
 	};
 
 	usbotg2: usb@5b0e0000 {
-		compatible = "fsl,imx8dxl-usb", "fsl,imx7ulp-usb";
+		compatible = "fsl,imx8dxl-usb", "fsl,imx7ulp-usb", "fsl,imx6ul-usb";
 		reg = <0x5b0e0000 0x200>;
 		interrupt-parent = <&gic>;
 		interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
@@ -49,7 +49,6 @@ usbotg2: usb@5b0e0000 {
 		ahb-burst-config = <0x0>;
 		tx-burst-size-dword = <0x10>;
 		rx-burst-size-dword = <0x10>;
-		#stream-id-cells = <1>;
 		power-domains = <&pd IMX_SC_R_USB_1>;
 		status = "disabled";
 
@@ -63,7 +62,7 @@ clk_dummy: clock-dummy {
 
 	usbmisc2: usbmisc@5b0e0200 {
 		#index-cells = <1>;
-		compatible = "fsl,imx7ulp-usbmisc";
+		compatible = "fsl,imx7ulp-usbmisc", "fsl,imx7d-usbmisc", "fsl,imx6q-usbmisc";
 		reg = <0x5b0e0200 0x200>;
 	};
 
diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
index ba06b5273b9127c0d3bfcb4b027a1e91efd749df..d6b36f04f3dc155e19409cd194c849f12d3b4993 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
@@ -1253,7 +1253,7 @@ imx8mm_mipi_csi_out: endpoint {
 			};
 
 			usbotg1: usb@32e40000 {
-				compatible = "fsl,imx8mm-usb", "fsl,imx7d-usb";
+				compatible = "fsl,imx8mm-usb", "fsl,imx7d-usb", "fsl,imx27-usb";
 				reg = <0x32e40000 0x200>;
 				interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clk IMX8MM_CLK_USB1_CTRL_ROOT>;
@@ -1267,13 +1267,14 @@ usbotg1: usb@32e40000 {
 			};
 
 			usbmisc1: usbmisc@32e40200 {
-				compatible = "fsl,imx8mm-usbmisc", "fsl,imx7d-usbmisc";
+				compatible = "fsl,imx8mm-usbmisc", "fsl,imx7d-usbmisc",
+					     "fsl,imx6q-usbmisc";
 				#index-cells = <1>;
 				reg = <0x32e40200 0x200>;
 			};
 
 			usbotg2: usb@32e50000 {
-				compatible = "fsl,imx8mm-usb", "fsl,imx7d-usb";
+				compatible = "fsl,imx8mm-usb", "fsl,imx7d-usb", "fsl,imx27-usb";
 				reg = <0x32e50000 0x200>;
 				interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clk IMX8MM_CLK_USB1_CTRL_ROOT>;
@@ -1287,7 +1288,8 @@ usbotg2: usb@32e50000 {
 			};
 
 			usbmisc2: usbmisc@32e50200 {
-				compatible = "fsl,imx8mm-usbmisc", "fsl,imx7d-usbmisc";
+				compatible = "fsl,imx8mm-usbmisc", "fsl,imx7d-usbmisc",
+					     "fsl,imx6q-usbmisc";
 				#index-cells = <1>;
 				reg = <0x32e50200 0x200>;
 			};
diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
index c94ab45ee96c38dbcc13a4c2bca334985892d9fa..bd84db55005313ac4e6c96b2929cf3b684e95c67 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
@@ -1146,7 +1146,7 @@ disp_blk_ctrl: blk-ctrl@32e28000 {
 			};
 
 			usbotg1: usb@32e40000 {
-				compatible = "fsl,imx8mn-usb", "fsl,imx7d-usb";
+				compatible = "fsl,imx8mn-usb", "fsl,imx7d-usb", "fsl,imx27-usb";
 				reg = <0x32e40000 0x200>;
 				interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clk IMX8MN_CLK_USB1_CTRL_ROOT>;
@@ -1160,7 +1160,8 @@ usbotg1: usb@32e40000 {
 			};
 
 			usbmisc1: usbmisc@32e40200 {
-				compatible = "fsl,imx8mn-usbmisc", "fsl,imx7d-usbmisc";
+				compatible = "fsl,imx8mn-usbmisc", "fsl,imx7d-usbmisc",
+					     "fsl,imx6q-usbmisc";
 				#index-cells = <1>;
 				reg = <0x32e40200 0x200>;
 			};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index cd925c0ac911513255321bb87a3bc8891211fcdf..0492556a10dbc4151c1c02e03c93c385d7c28df1 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -1453,7 +1453,6 @@ usb_dwc3_0: usb@38100000 {
 			phys = <&usb3_phy0>, <&usb3_phy0>;
 			phy-names = "usb2-phy", "usb3-phy";
 			power-domains = <&pgc_otg1>;
-			usb3-resume-missing-cas;
 			status = "disabled";
 		};
 
@@ -1485,7 +1484,6 @@ usb_dwc3_1: usb@38200000 {
 			phys = <&usb3_phy1>, <&usb3_phy1>;
 			phy-names = "usb2-phy", "usb3-phy";
 			power-domains = <&pgc_otg2>;
-			usb3-resume-missing-cas;
 			status = "disabled";
 		};
 
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
index e1b66aac7025cb165b8a6048fcd6dff339fc7106..a5c68e9b0482dcedc3c3b8a8516c5e5190b53728 100644
--- a/arch/mips/configs/mtx1_defconfig
+++ b/arch/mips/configs/mtx1_defconfig
@@ -497,7 +497,6 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_OHCI_HCD=m
 CONFIG_USB_OHCI_HCD_PLATFORM=m
 CONFIG_USB_UHCI_HCD=m
-CONFIG_USB_U132_HCD=m
 CONFIG_USB_SL811_HCD=m
 CONFIG_USB_SL811_CS=m
 CONFIG_USB_ACM=m
@@ -554,7 +553,6 @@ CONFIG_USB_LCD=m
 CONFIG_USB_CYPRESS_CY7C63=m
 CONFIG_USB_CYTHERM=m
 CONFIG_USB_IDMOUSE=m
-CONFIG_USB_FTDI_ELAN=m
 CONFIG_USB_APPLEDISPLAY=m
 CONFIG_USB_SISUSBVGA=m
 CONFIG_USB_LD=m
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index 5927b2312936f2634a232b743b59cc1d6929d3ca..adc314049fdd80c5827c0b2816ac500bb8664249 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -845,7 +845,6 @@ CONFIG_USB_OHCI_HCD=m
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
 CONFIG_USB_UHCI_HCD=m
-CONFIG_USB_U132_HCD=m
 CONFIG_USB_SL811_HCD=m
 CONFIG_USB_ACM=m
 CONFIG_USB_PRINTER=m
@@ -908,7 +907,6 @@ CONFIG_USB_SEVSEG=m
 CONFIG_USB_LEGOTOWER=m
 CONFIG_USB_LCD=m
 CONFIG_USB_IDMOUSE=m
-CONFIG_USB_FTDI_ELAN=m
 CONFIG_USB_APPLEDISPLAY=m
 CONFIG_USB_SISUSBVGA=m
 CONFIG_USB_LD=m
diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c
index 8230da828d0ee677ec89498b569c6d6fd0c9c472..127a3be0e0f0708b88270a3880a868d7bf9ab463 100644
--- a/drivers/media/radio/radio-shark.c
+++ b/drivers/media/radio/radio-shark.c
@@ -316,6 +316,16 @@ static int usb_shark_probe(struct usb_interface *intf,
 {
 	struct shark_device *shark;
 	int retval = -ENOMEM;
+	static const u8 ep_addresses[] = {
+		SHARK_IN_EP | USB_DIR_IN,
+		SHARK_OUT_EP | USB_DIR_OUT,
+		0};
+
+	/* Are the expected endpoints present? */
+	if (!usb_check_int_endpoints(intf, ep_addresses)) {
+		dev_err(&intf->dev, "Invalid radioSHARK device\n");
+		return -EINVAL;
+	}
 
 	shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);
 	if (!shark)
diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c
index d150f12382c60e441e155c63a0ec21276b1d2482..f1c5c0a6a335cbf1972c9990668648c4b739fe75 100644
--- a/drivers/media/radio/radio-shark2.c
+++ b/drivers/media/radio/radio-shark2.c
@@ -282,6 +282,16 @@ static int usb_shark_probe(struct usb_interface *intf,
 {
 	struct shark_device *shark;
 	int retval = -ENOMEM;
+	static const u8 ep_addresses[] = {
+		SHARK_IN_EP | USB_DIR_IN,
+		SHARK_OUT_EP | USB_DIR_OUT,
+		0};
+
+	/* Are the expected endpoints present? */
+	if (!usb_check_int_endpoints(intf, ep_addresses)) {
+		dev_err(&intf->dev, "Invalid radioSHARK2 device\n");
+		return -EINVAL;
+	}
 
 	shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);
 	if (!shark)
diff --git a/drivers/thunderbolt/acpi.c b/drivers/thunderbolt/acpi.c
index 628225deb8fef2f0b44cb95205edebdd246ea021..3514bf65b7a49e7c825b8191d8c61e636db06a9f 100644
--- a/drivers/thunderbolt/acpi.c
+++ b/drivers/thunderbolt/acpi.c
@@ -341,7 +341,7 @@ static struct acpi_device *tb_acpi_find_companion(struct device *dev)
 	 */
 	if (tb_is_switch(dev))
 		return tb_acpi_switch_find_companion(tb_to_switch(dev));
-	else if (tb_is_usb4_port_device(dev))
+	if (tb_is_usb4_port_device(dev))
 		return acpi_find_child_by_adr(ACPI_COMPANION(dev->parent),
 					      tb_to_usb4_port_device(dev)->port->port);
 	return NULL;
diff --git a/drivers/thunderbolt/ctl.c b/drivers/thunderbolt/ctl.c
index 6e7d28e8d81aaffa064c02ec40b0288f9a6d876c..3a213322ec7a9dae5082bdfe5de970494c30f015 100644
--- a/drivers/thunderbolt/ctl.c
+++ b/drivers/thunderbolt/ctl.c
@@ -1033,7 +1033,7 @@ static int tb_cfg_get_error(struct tb_ctl *ctl, enum tb_cfg_space space,
 
 	if (res->tb_error == TB_CFG_ERROR_LOCK)
 		return -EACCES;
-	else if (res->tb_error == TB_CFG_ERROR_PORT_NOT_CONNECTED)
+	if (res->tb_error == TB_CFG_ERROR_PORT_NOT_CONNECTED)
 		return -ENOTCONN;
 
 	return -EIO;
diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c
index c90d22f56d4e1c60c6f6ebf5817075971a910906..0f6099c18a9415b9c58edc4acac470d4aed421eb 100644
--- a/drivers/thunderbolt/eeprom.c
+++ b/drivers/thunderbolt/eeprom.c
@@ -416,7 +416,7 @@ static int tb_drom_parse_entries(struct tb_switch *sw, size_t header_size)
 		if (pos + 1 == drom_size || pos + entry->len > drom_size
 				|| !entry->len) {
 			tb_sw_warn(sw, "DROM buffer overrun\n");
-			return -EILSEQ;
+			return -EIO;
 		}
 
 		switch (entry->type) {
@@ -471,14 +471,13 @@ static int tb_drom_copy_efi(struct tb_switch *sw, u16 *size)
 
 static int tb_drom_copy_nvm(struct tb_switch *sw, u16 *size)
 {
-	u32 drom_offset;
+	u16 drom_offset;
 	int ret;
 
 	if (!sw->dma_port)
 		return -ENODEV;
 
-	ret = tb_sw_read(sw, &drom_offset, TB_CFG_SWITCH,
-			 sw->cap_plug_events + 12, 1);
+	ret = tb_eeprom_get_drom_offset(sw, &drom_offset);
 	if (ret)
 		return ret;
 
@@ -513,7 +512,7 @@ static int tb_drom_copy_nvm(struct tb_switch *sw, u16 *size)
 	return ret;
 }
 
-static int usb4_copy_host_drom(struct tb_switch *sw, u16 *size)
+static int usb4_copy_drom(struct tb_switch *sw, u16 *size)
 {
 	int ret;
 
@@ -536,15 +535,40 @@ static int usb4_copy_host_drom(struct tb_switch *sw, u16 *size)
 	return ret;
 }
 
-static int tb_drom_read_n(struct tb_switch *sw, u16 offset, u8 *val,
-			  size_t count)
+static int tb_drom_bit_bang(struct tb_switch *sw, u16 *size)
 {
-	if (tb_switch_is_usb4(sw))
-		return usb4_switch_drom_read(sw, offset, val, count);
-	return tb_eeprom_read_n(sw, offset, val, count);
+	int ret;
+
+	ret = tb_eeprom_read_n(sw, 14, (u8 *)size, 2);
+	if (ret)
+		return ret;
+
+	*size &= 0x3ff;
+	*size += TB_DROM_DATA_START;
+
+	tb_sw_dbg(sw, "reading DROM (length: %#x)\n", *size);
+	if (*size < sizeof(struct tb_drom_header)) {
+		tb_sw_warn(sw, "DROM too small, aborting\n");
+		return -EIO;
+	}
+
+	sw->drom = kzalloc(*size, GFP_KERNEL);
+	if (!sw->drom)
+		return -ENOMEM;
+
+	ret = tb_eeprom_read_n(sw, 0, sw->drom, *size);
+	if (ret)
+		goto err;
+
+	return 0;
+
+err:
+	kfree(sw->drom);
+	sw->drom = NULL;
+	return ret;
 }
 
-static int tb_drom_parse(struct tb_switch *sw)
+static int tb_drom_parse_v1(struct tb_switch *sw)
 {
 	const struct tb_drom_header *header =
 		(const struct tb_drom_header *)sw->drom;
@@ -555,7 +579,7 @@ static int tb_drom_parse(struct tb_switch *sw)
 		tb_sw_warn(sw,
 			"DROM UID CRC8 mismatch (expected: %#x, got: %#x)\n",
 			header->uid_crc8, crc);
-		return -EILSEQ;
+		return -EIO;
 	}
 	if (!sw->uid)
 		sw->uid = header->uid;
@@ -589,85 +613,14 @@ static int usb4_drom_parse(struct tb_switch *sw)
 	return tb_drom_parse_entries(sw, USB4_DROM_HEADER_SIZE);
 }
 
-/**
- * tb_drom_read() - Copy DROM to sw->drom and parse it
- * @sw: Router whose DROM to read and parse
- *
- * This function reads router DROM and if successful parses the entries and
- * populates the fields in @sw accordingly. Can be called for any router
- * generation.
- *
- * Returns %0 in case of success and negative errno otherwise.
- */
-int tb_drom_read(struct tb_switch *sw)
+static int tb_drom_parse(struct tb_switch *sw, u16 size)
 {
-	u16 size;
-	struct tb_drom_header *header;
-	int res, retries = 1;
-
-	if (sw->drom)
-		return 0;
-
-	if (tb_route(sw) == 0) {
-		/*
-		 * Apple's NHI EFI driver supplies a DROM for the root switch
-		 * in a device property. Use it if available.
-		 */
-		if (tb_drom_copy_efi(sw, &size) == 0)
-			goto parse;
-
-		/* Non-Apple hardware has the DROM as part of NVM */
-		if (tb_drom_copy_nvm(sw, &size) == 0)
-			goto parse;
-
-		/*
-		 * USB4 hosts may support reading DROM through router
-		 * operations.
-		 */
-		if (tb_switch_is_usb4(sw)) {
-			usb4_switch_read_uid(sw, &sw->uid);
-			if (!usb4_copy_host_drom(sw, &size))
-				goto parse;
-		} else {
-			/*
-			 * The root switch contains only a dummy drom
-			 * (header only, no entries). Hardcode the
-			 * configuration here.
-			 */
-			tb_drom_read_uid_only(sw, &sw->uid);
-		}
-
-		return 0;
-	}
-
-	res = tb_drom_read_n(sw, 14, (u8 *) &size, 2);
-	if (res)
-		return res;
-	size &= 0x3ff;
-	size += TB_DROM_DATA_START;
-	tb_sw_dbg(sw, "reading drom (length: %#x)\n", size);
-	if (size < sizeof(*header)) {
-		tb_sw_warn(sw, "drom too small, aborting\n");
-		return -EIO;
-	}
-
-	sw->drom = kzalloc(size, GFP_KERNEL);
-	if (!sw->drom)
-		return -ENOMEM;
-read:
-	res = tb_drom_read_n(sw, 0, sw->drom, size);
-	if (res)
-		goto err;
-
-parse:
-	header = (void *) sw->drom;
+	const struct tb_drom_header *header = (const void *)sw->drom;
+	int ret;
 
 	if (header->data_len + TB_DROM_DATA_START != size) {
-		tb_sw_warn(sw, "drom size mismatch\n");
-		if (retries--) {
-			msleep(100);
-			goto read;
-		}
+		tb_sw_warn(sw, "DROM size mismatch\n");
+		ret = -EIO;
 		goto err;
 	}
 
@@ -675,29 +628,86 @@ int tb_drom_read(struct tb_switch *sw)
 
 	switch (header->device_rom_revision) {
 	case 3:
-		res = usb4_drom_parse(sw);
+		ret = usb4_drom_parse(sw);
 		break;
 	default:
 		tb_sw_warn(sw, "DROM device_rom_revision %#x unknown\n",
 			   header->device_rom_revision);
 		fallthrough;
 	case 1:
-		res = tb_drom_parse(sw);
+		ret = tb_drom_parse_v1(sw);
 		break;
 	}
 
-	/* If the DROM parsing fails, wait a moment and retry once */
-	if (res == -EILSEQ && retries--) {
+	if (ret) {
 		tb_sw_warn(sw, "parsing DROM failed\n");
-		msleep(100);
-		goto read;
+		goto err;
 	}
 
-	if (!res)
-		return 0;
+	return 0;
 
 err:
 	kfree(sw->drom);
 	sw->drom = NULL;
-	return -EIO;
+
+	return ret;
+}
+
+static int tb_drom_host_read(struct tb_switch *sw)
+{
+	u16 size;
+
+	if (tb_switch_is_usb4(sw)) {
+		usb4_switch_read_uid(sw, &sw->uid);
+		if (!usb4_copy_drom(sw, &size))
+			return tb_drom_parse(sw, size);
+	} else {
+		if (!tb_drom_copy_efi(sw, &size))
+			return tb_drom_parse(sw, size);
+
+		if (!tb_drom_copy_nvm(sw, &size))
+			return tb_drom_parse(sw, size);
+
+		tb_drom_read_uid_only(sw, &sw->uid);
+	}
+
+	return 0;
+}
+
+static int tb_drom_device_read(struct tb_switch *sw)
+{
+	u16 size;
+	int ret;
+
+	if (tb_switch_is_usb4(sw)) {
+		usb4_switch_read_uid(sw, &sw->uid);
+		ret = usb4_copy_drom(sw, &size);
+	} else {
+		ret = tb_drom_bit_bang(sw, &size);
+	}
+
+	if (ret)
+		return ret;
+
+	return tb_drom_parse(sw, size);
+}
+
+/**
+ * tb_drom_read() - Copy DROM to sw->drom and parse it
+ * @sw: Router whose DROM to read and parse
+ *
+ * This function reads router DROM and if successful parses the entries and
+ * populates the fields in @sw accordingly. Can be called for any router
+ * generation.
+ *
+ * Returns %0 in case of success and negative errno otherwise.
+ */
+int tb_drom_read(struct tb_switch *sw)
+{
+	if (sw->drom)
+		return 0;
+
+	if (!tb_route(sw))
+		return tb_drom_host_read(sw);
+	return tb_drom_device_read(sw);
 }
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index cfebec107f3fc8a437718c376045cd4d8d734171..d76e923fbc6a01fcc8ce93bb998d4231511ffa39 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -526,7 +526,8 @@ static int nhi_alloc_hop(struct tb_nhi *nhi, struct tb_ring *ring)
 			 ring->hop);
 		ret = -EBUSY;
 		goto err_unlock;
-	} else if (!ring->is_tx && nhi->rx_rings[ring->hop]) {
+	}
+	if (!ring->is_tx && nhi->rx_rings[ring->hop]) {
 		dev_warn(&nhi->pdev->dev, "RX hop %d already allocated\n",
 			 ring->hop);
 		ret = -EBUSY;
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index da373ac38285c6a1b35c8ed035689306fc9c045c..51e86b5171c77e9c37c07cf184364f01bc9f896e 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -271,9 +271,9 @@ static int nvm_authenticate(struct tb_switch *sw, bool auth_only)
 		}
 		sw->nvm->authenticating = true;
 		return usb4_switch_nvm_authenticate(sw);
-	} else if (auth_only) {
-		return -EOPNOTSUPP;
 	}
+	if (auth_only)
+		return -EOPNOTSUPP;
 
 	sw->nvm->authenticating = true;
 	if (!tb_route(sw)) {
diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c
index a0996cb2893c8693cfc08fd2e0bf71966b04a34a..485b6e43068634ed7b8ac628d508ce57876772bf 100644
--- a/drivers/thunderbolt/usb4.c
+++ b/drivers/thunderbolt/usb4.c
@@ -9,6 +9,7 @@
 
 #include <linux/delay.h>
 #include <linux/ktime.h>
+#include <linux/units.h>
 
 #include "sb_regs.h"
 #include "tb.h"
@@ -851,7 +852,7 @@ bool usb4_switch_query_dp_resource(struct tb_switch *sw, struct tb_port *in)
 	 */
 	if (ret == -EOPNOTSUPP)
 		return true;
-	else if (ret)
+	if (ret)
 		return false;
 
 	return !status;
@@ -877,7 +878,7 @@ int usb4_switch_alloc_dp_resource(struct tb_switch *sw, struct tb_port *in)
 			     &status);
 	if (ret == -EOPNOTSUPP)
 		return 0;
-	else if (ret)
+	if (ret)
 		return ret;
 
 	return status ? -EBUSY : 0;
@@ -900,7 +901,7 @@ int usb4_switch_dealloc_dp_resource(struct tb_switch *sw, struct tb_port *in)
 			     &status);
 	if (ret == -EOPNOTSUPP)
 		return 0;
-	else if (ret)
+	if (ret)
 		return ret;
 
 	return status ? -EIO : 0;
@@ -1302,6 +1303,20 @@ static int usb4_port_sb_write(struct tb_port *port, enum usb4_sb_target target,
 	return 0;
 }
 
+static int usb4_port_sb_opcode_err_to_errno(u32 val)
+{
+	switch (val) {
+	case 0:
+		return 0;
+	case USB4_SB_OPCODE_ERR:
+		return -EAGAIN;
+	case USB4_SB_OPCODE_ONS:
+		return -EOPNOTSUPP;
+	default:
+		return -EIO;
+	}
+}
+
 static int usb4_port_sb_op(struct tb_port *port, enum usb4_sb_target target,
 			   u8 index, enum usb4_sb_opcode opcode, int timeout_msec)
 {
@@ -1324,21 +1339,8 @@ static int usb4_port_sb_op(struct tb_port *port, enum usb4_sb_target target,
 		if (ret)
 			return ret;
 
-		switch (val) {
-		case 0:
-			return 0;
-
-		case USB4_SB_OPCODE_ERR:
-			return -EAGAIN;
-
-		case USB4_SB_OPCODE_ONS:
-			return -EOPNOTSUPP;
-
-		default:
-			if (val != opcode)
-				return -EIO;
-			break;
-		}
+		if (val != opcode)
+			return usb4_port_sb_opcode_err_to_errno(val);
 	} while (ktime_before(ktime_get(), timeout));
 
 	return -ETIMEDOUT;
@@ -1813,12 +1815,13 @@ int usb4_port_retimer_nvm_authenticate_status(struct tb_port *port, u8 index,
 	if (ret)
 		return ret;
 
-	switch (val) {
+	ret = usb4_port_sb_opcode_err_to_errno(val);
+	switch (ret) {
 	case 0:
 		*status = 0;
 		return 0;
 
-	case USB4_SB_OPCODE_ERR:
+	case -EAGAIN:
 		ret = usb4_port_retimer_read(port, index, USB4_SB_METADATA,
 					     &metadata, sizeof(metadata));
 		if (ret)
@@ -1827,11 +1830,8 @@ int usb4_port_retimer_nvm_authenticate_status(struct tb_port *port, u8 index,
 		*status = metadata & USB4_SB_METADATA_NVM_AUTH_WRITE_MASK;
 		return 0;
 
-	case USB4_SB_OPCODE_ONS:
-		return -EOPNOTSUPP;
-
 	default:
-		return -EIO;
+		return ret;
 	}
 }
 
@@ -1995,7 +1995,7 @@ static unsigned int usb3_bw_to_mbps(u32 bw, u8 scale)
 	unsigned long uframes;
 
 	uframes = bw * 512UL << scale;
-	return DIV_ROUND_CLOSEST(uframes * 8000, 1000 * 1000);
+	return DIV_ROUND_CLOSEST(uframes * 8000, MEGA);
 }
 
 static u32 mbps_to_usb3_bw(unsigned int mbps, u8 scale)
@@ -2003,7 +2003,7 @@ static u32 mbps_to_usb3_bw(unsigned int mbps, u8 scale)
 	unsigned long uframes;
 
 	/* 1 uframe is 1/8 ms (125 us) -> 1 / 8000 s */
-	uframes = ((unsigned long)mbps * 1000 *  1000) / 8000;
+	uframes = ((unsigned long)mbps * MEGA) / 8000;
 	return DIV_ROUND_UP(uframes, 512UL << scale);
 }
 
diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c
index a48335c95d39be5efca46eb6a2dbdae501044df1..e2b54887d3313e6a7adc6f9dc3e5bbf7a5946056 100644
--- a/drivers/thunderbolt/xdomain.c
+++ b/drivers/thunderbolt/xdomain.c
@@ -1178,9 +1178,8 @@ static int tb_xdomain_get_uuid(struct tb_xdomain *xd)
 		if (xd->state_retries-- > 0) {
 			dev_dbg(&xd->dev, "failed to request UUID, retrying\n");
 			return -EAGAIN;
-		} else {
-			dev_dbg(&xd->dev, "failed to read remote UUID\n");
 		}
+		dev_dbg(&xd->dev, "failed to read remote UUID\n");
 		return ret;
 	}
 
@@ -1367,12 +1366,10 @@ static int tb_xdomain_get_properties(struct tb_xdomain *xd)
 			dev_dbg(&xd->dev,
 				"failed to request remote properties, retrying\n");
 			return -EAGAIN;
-		} else {
-			/* Give up now */
-			dev_err(&xd->dev,
-				"failed read XDomain properties from %pUb\n",
-				xd->remote_uuid);
 		}
+		/* Give up now */
+		dev_err(&xd->dev, "failed read XDomain properties from %pUb\n",
+			xd->remote_uuid);
 
 		return ret;
 	}
@@ -2179,13 +2176,12 @@ static struct tb_xdomain *switch_find_xdomain(struct tb_switch *sw,
 				if (xd->remote_uuid &&
 				    uuid_equal(xd->remote_uuid, lookup->uuid))
 					return xd;
-			} else if (lookup->link &&
-				   lookup->link == xd->link &&
-				   lookup->depth == xd->depth) {
-				return xd;
-			} else if (lookup->route &&
-				   lookup->route == xd->route) {
-				return xd;
+			} else {
+				if (lookup->link && lookup->link == xd->link &&
+				    lookup->depth == xd->depth)
+					return xd;
+				if (lookup->route && lookup->route == xd->route)
+					return xd;
 			}
 		} else if (tb_port_has_remote(port)) {
 			xd = switch_find_xdomain(port->remote->sw, lookup);
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index a871a988829dbf0e91e3e1532163cf504b145810..7f33bcc315f27bf0cde170cb8f53fbc500e86754 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -133,35 +133,6 @@ comment "USB port drivers"
 
 if USB
 
-config USB_USS720
-	tristate "USS720 parport driver"
-	depends on PARPORT
-	select PARPORT_NOT_PC
-	help
-	  This driver is for USB parallel port adapters that use the Lucent
-	  Technologies USS-720 chip. These cables are plugged into your USB
-	  port and provide USB compatibility to peripherals designed with
-	  parallel port interfaces.
-
-	  The chip has two modes: automatic mode and manual mode. In automatic
-	  mode, it looks to the computer like a standard USB printer. Only
-	  printers may be connected to the USS-720 in this mode. The generic
-	  USB printer driver ("USB Printer support", above) may be used in
-	  that mode, and you can say N here if you want to use the chip only
-	  in this mode.
-
-	  Manual mode is not limited to printers, any parallel port
-	  device should work. This driver utilizes manual mode.
-	  Note however that some operations are three orders of magnitude
-	  slower than on a PCI/ISA Parallel Port, so timing critical
-	  applications might not work.
-
-	  Say Y here if you own an USS-720 USB->Parport cable and intend to
-	  connect anything other than a printer to it.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called uss720.
-
 source "drivers/usb/serial/Kconfig"
 
 source "drivers/usb/misc/Kconfig"
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index a81e6ef293af27723c73b3b44571fd5b2998f1f8..3a9a0dd4be706df102c768f0283bde6cc648ce91 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -31,7 +31,6 @@ obj-$(CONFIG_USB_FHCI_HCD)	+= host/
 obj-$(CONFIG_USB_XHCI_HCD)	+= host/
 obj-$(CONFIG_USB_SL811_HCD)	+= host/
 obj-$(CONFIG_USB_ISP1362_HCD)	+= host/
-obj-$(CONFIG_USB_U132_HCD)	+= host/
 obj-$(CONFIG_USB_R8A66597_HCD)	+= host/
 obj-$(CONFIG_USB_FSL_USB2)	+= host/
 obj-$(CONFIG_USB_FOTG210_HCD)	+= host/
diff --git a/drivers/usb/cdns3/cdns3-debug.h b/drivers/usb/cdns3/cdns3-debug.h
index a5c6a29e1340678c46c2a124fd4b4c7ec6538738..4618cfe85a4fb397eb00da3057cb941572701910 100644
--- a/drivers/usb/cdns3/cdns3-debug.h
+++ b/drivers/usb/cdns3/cdns3-debug.h
@@ -107,8 +107,7 @@ static inline char *cdns3_decode_ep0_irq(char *str,
  * Prints out all TRBs in the endpoint ring, even those after the Link TRB.
  *.
  */
-static inline char *cdns3_dbg_ring(struct cdns3_endpoint *priv_ep,
-				   struct cdns3_trb *ring, char *str)
+static inline char *cdns3_dbg_ring(struct cdns3_endpoint *priv_ep, char *str)
 {
 	dma_addr_t addr = priv_ep->trb_pool_dma;
 	struct cdns3_trb *trb;
@@ -136,9 +135,6 @@ static inline char *cdns3_dbg_ring(struct cdns3_endpoint *priv_ep,
 		       "\t\tfree trbs: %d, CCS=%d, PCS=%d\n",
 		       priv_ep->free_trbs, priv_ep->ccs, priv_ep->pcs);
 
-	if (trb_per_sector > TRBS_PER_SEGMENT)
-		trb_per_sector = TRBS_PER_SEGMENT;
-
 	if (trb_per_sector > TRBS_PER_SEGMENT) {
 		sprintf(str + ret, "\t\tTransfer ring %d too big\n",
 			trb_per_sector);
@@ -146,7 +142,7 @@ static inline char *cdns3_dbg_ring(struct cdns3_endpoint *priv_ep,
 	}
 
 	for (i = 0; i < trb_per_sector; ++i) {
-		trb = &ring[i];
+		trb = &priv_ep->trb_pool[i];
 		ret += sprintf(str + ret,
 			"\t\t@%pad %08x %08x %08x\n", &addr,
 			le32_to_cpu(trb->buffer),
diff --git a/drivers/usb/cdns3/cdns3-trace.h b/drivers/usb/cdns3/cdns3-trace.h
index 7574b4a6281320f635fa9156de6220d85bd5820a..40db89e3333cc4143778f6c2503fcf1a22b89be9 100644
--- a/drivers/usb/cdns3/cdns3-trace.h
+++ b/drivers/usb/cdns3/cdns3-trace.h
@@ -100,13 +100,12 @@ DECLARE_EVENT_CLASS(cdns3_log_usb_irq,
 	TP_STRUCT__entry(
 		__field(enum usb_device_speed, speed)
 		__field(u32, usb_ists)
-		__dynamic_array(char, str, CDNS3_MSG_MAX)
 	),
 	TP_fast_assign(
 		__entry->speed = cdns3_get_speed(priv_dev);
 		__entry->usb_ists = usb_ists;
 	),
-	TP_printk("%s", cdns3_decode_usb_irq(__get_str(str), __entry->speed,
+	TP_printk("%s", cdns3_decode_usb_irq(__get_buf(CDNS3_MSG_MAX), __entry->speed,
 					     __entry->usb_ists))
 );
 
@@ -124,7 +123,6 @@ DECLARE_EVENT_CLASS(cdns3_log_epx_irq,
 		__field(u32, ep_traddr)
 		__field(u32, ep_last_sid)
 		__field(u32, use_streams)
-		__dynamic_array(char, str, CDNS3_MSG_MAX)
 	),
 	TP_fast_assign(
 		__assign_str(ep_name, priv_ep->name);
@@ -134,7 +132,7 @@ DECLARE_EVENT_CLASS(cdns3_log_epx_irq,
 		__entry->use_streams = priv_ep->use_streams;
 	),
 	TP_printk("%s, ep_traddr: %08x ep_last_sid: %08x use_streams: %d",
-		  cdns3_decode_epx_irq(__get_str(str),
+		  cdns3_decode_epx_irq(__get_buf(CDNS3_MSG_MAX),
 				       __get_str(ep_name),
 				       __entry->ep_sts),
 		  __entry->ep_traddr,
@@ -153,13 +151,12 @@ DECLARE_EVENT_CLASS(cdns3_log_ep0_irq,
 	TP_STRUCT__entry(
 		__field(int, ep_dir)
 		__field(u32, ep_sts)
-		__dynamic_array(char, str, CDNS3_MSG_MAX)
 	),
 	TP_fast_assign(
 		__entry->ep_dir = priv_dev->selected_ep;
 		__entry->ep_sts = ep_sts;
 	),
-	TP_printk("%s", cdns3_decode_ep0_irq(__get_str(str),
+	TP_printk("%s", cdns3_decode_ep0_irq(__get_buf(CDNS3_MSG_MAX),
 					     __entry->ep_dir,
 					     __entry->ep_sts))
 );
@@ -178,7 +175,6 @@ DECLARE_EVENT_CLASS(cdns3_log_ctrl,
 		__field(u16, wValue)
 		__field(u16, wIndex)
 		__field(u16, wLength)
-		__dynamic_array(char, str, CDNS3_MSG_MAX)
 	),
 	TP_fast_assign(
 		__entry->bRequestType = ctrl->bRequestType;
@@ -187,7 +183,7 @@ DECLARE_EVENT_CLASS(cdns3_log_ctrl,
 		__entry->wIndex = le16_to_cpu(ctrl->wIndex);
 		__entry->wLength = le16_to_cpu(ctrl->wLength);
 	),
-	TP_printk("%s", usb_decode_ctrl(__get_str(str), CDNS3_MSG_MAX,
+	TP_printk("%s", usb_decode_ctrl(__get_buf(CDNS3_MSG_MAX), CDNS3_MSG_MAX,
 					__entry->bRequestType,
 					__entry->bRequest, __entry->wValue,
 					__entry->wIndex, __entry->wLength)
@@ -438,22 +434,16 @@ DECLARE_EVENT_CLASS(cdns3_log_ring,
 	TP_PROTO(struct cdns3_endpoint *priv_ep),
 	TP_ARGS(priv_ep),
 	TP_STRUCT__entry(
-		__dynamic_array(u8, ring, TRB_RING_SIZE)
-		__dynamic_array(u8, priv_ep, sizeof(struct cdns3_endpoint))
 		__dynamic_array(char, buffer,
-				(TRBS_PER_SEGMENT * 65) + CDNS3_MSG_MAX)
+				GET_TRBS_PER_SEGMENT(priv_ep->type) > TRBS_PER_SEGMENT ?
+				CDNS3_MSG_MAX :
+				(GET_TRBS_PER_SEGMENT(priv_ep->type) * 65) + CDNS3_MSG_MAX)
 	),
 	TP_fast_assign(
-		memcpy(__get_dynamic_array(priv_ep), priv_ep,
-		       sizeof(struct cdns3_endpoint));
-		memcpy(__get_dynamic_array(ring), priv_ep->trb_pool,
-		       TRB_RING_SIZE);
+		cdns3_dbg_ring(priv_ep, __get_str(buffer));
 	),
 
-	TP_printk("%s",
-		  cdns3_dbg_ring((struct cdns3_endpoint *)__get_str(priv_ep),
-				 (struct cdns3_trb *)__get_str(ring),
-				 __get_str(buffer)))
+	TP_printk("%s", __get_str(buffer))
 );
 
 DEFINE_EVENT(cdns3_log_ring, cdns3_ring,
diff --git a/drivers/usb/cdns3/cdnsp-trace.h b/drivers/usb/cdns3/cdnsp-trace.h
index 5983dfb996537ef344eb6bcb086d4a479ec48214..4b51011eb00b0ff9aedf14ae167c8c2ad4871a21 100644
--- a/drivers/usb/cdns3/cdnsp-trace.h
+++ b/drivers/usb/cdns3/cdnsp-trace.h
@@ -271,7 +271,6 @@ DECLARE_EVENT_CLASS(cdnsp_log_ctrl,
 		__field(u16, wValue)
 		__field(u16, wIndex)
 		__field(u16, wLength)
-		__dynamic_array(char, str, CDNSP_MSG_MAX)
 	),
 	TP_fast_assign(
 		__entry->bRequestType = ctrl->bRequestType;
@@ -280,7 +279,7 @@ DECLARE_EVENT_CLASS(cdnsp_log_ctrl,
 		__entry->wIndex = le16_to_cpu(ctrl->wIndex);
 		__entry->wLength = le16_to_cpu(ctrl->wLength);
 	),
-	TP_printk("%s", usb_decode_ctrl(__get_str(str), CDNSP_MSG_MAX,
+	TP_printk("%s", usb_decode_ctrl(__get_buf(CDNSP_MSG_MAX), CDNSP_MSG_MAX,
 					__entry->bRequestType,
 					__entry->bRequest, __entry->wValue,
 					__entry->wIndex, __entry->wLength)
@@ -345,7 +344,6 @@ DECLARE_EVENT_CLASS(cdnsp_log_trb,
 		__field(u32, field3)
 		__field(union cdnsp_trb *, trb)
 		__field(dma_addr_t, trb_dma)
-		__dynamic_array(char, str, CDNSP_MSG_MAX)
 	),
 	TP_fast_assign(
 		__entry->type = ring->type;
@@ -359,7 +357,7 @@ DECLARE_EVENT_CLASS(cdnsp_log_trb,
 
 	),
 	TP_printk("%s: %s trb: %p(%pad)", cdnsp_ring_type_string(__entry->type),
-		  cdnsp_decode_trb(__get_str(str), CDNSP_MSG_MAX,
+		  cdnsp_decode_trb(__get_buf(CDNSP_MSG_MAX), CDNSP_MSG_MAX,
 				   __entry->field0, __entry->field1,
 				   __entry->field2, __entry->field3),
 				   __entry->trb, &__entry->trb_dma
@@ -544,7 +542,6 @@ DECLARE_EVENT_CLASS(cdnsp_log_ep_ctx,
 		__field(u32, info2)
 		__field(u64, deq)
 		__field(u32, tx_info)
-		__dynamic_array(char, str, CDNSP_MSG_MAX)
 	),
 	TP_fast_assign(
 		__entry->info = le32_to_cpu(ctx->ep_info);
@@ -552,7 +549,7 @@ DECLARE_EVENT_CLASS(cdnsp_log_ep_ctx,
 		__entry->deq = le64_to_cpu(ctx->deq);
 		__entry->tx_info = le32_to_cpu(ctx->tx_info);
 	),
-	TP_printk("%s", cdnsp_decode_ep_context(__get_str(str), CDNSP_MSG_MAX,
+	TP_printk("%s", cdnsp_decode_ep_context(__get_buf(CDNSP_MSG_MAX), CDNSP_MSG_MAX,
 						__entry->info, __entry->info2,
 						__entry->deq, __entry->tx_info)
 	)
@@ -777,7 +774,6 @@ DECLARE_EVENT_CLASS(cdnsp_log_portsc,
 		TP_STRUCT__entry(
 				__field(u32, portnum)
 				__field(u32, portsc)
-				__dynamic_array(char, str, CDNSP_MSG_MAX)
 				),
 		TP_fast_assign(
 				__entry->portnum = portnum;
@@ -785,7 +781,7 @@ DECLARE_EVENT_CLASS(cdnsp_log_portsc,
 				),
 		TP_printk("port-%d: %s",
 			  __entry->portnum,
-			  cdnsp_decode_portsc(__get_str(str), CDNSP_MSG_MAX,
+			  cdnsp_decode_portsc(__get_buf(CDNSP_MSG_MAX), CDNSP_MSG_MAX,
 					      __entry->portsc)
 			)
 );
diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile
index 6f4a3deced359b53eadb0daddd717173fe03fb89..71afeab97e837741eedb3db7243dc0e281711c4c 100644
--- a/drivers/usb/chipidea/Makefile
+++ b/drivers/usb/chipidea/Makefile
@@ -14,5 +14,5 @@ ci_hdrc-$(CONFIG_USB_OTG_FSM)		+= otg_fsm.o
 obj-$(CONFIG_USB_CHIPIDEA_GENERIC)	+= ci_hdrc_usb2.o
 obj-$(CONFIG_USB_CHIPIDEA_MSM)		+= ci_hdrc_msm.o
 obj-$(CONFIG_USB_CHIPIDEA_PCI)		+= ci_hdrc_pci.o
-obj-$(CONFIG_USB_CHIPIDEA_IMX)		+= ci_hdrc_imx.o usbmisc_imx.o
+obj-$(CONFIG_USB_CHIPIDEA_IMX)		+= usbmisc_imx.o ci_hdrc_imx.o
 obj-$(CONFIG_USB_CHIPIDEA_TEGRA)	+= ci_hdrc_tegra.o
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 2eeccf4ec9d60e50800fb8fe435d9cc1cecb35ba..2855ac30300147aa69b32294fb24e2d6e95f8c4a 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -152,12 +152,12 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
 	 * Check the various over current related properties. If over current
 	 * detection is disabled we're not interested in the polarity.
 	 */
-	if (of_find_property(np, "disable-over-current", NULL)) {
+	if (of_property_read_bool(np, "disable-over-current")) {
 		data->disable_oc = 1;
-	} else if (of_find_property(np, "over-current-active-high", NULL)) {
+	} else if (of_property_read_bool(np, "over-current-active-high")) {
 		data->oc_pol_active_low = 0;
 		data->oc_pol_configured = 1;
-	} else if (of_find_property(np, "over-current-active-low", NULL)) {
+	} else if (of_property_read_bool(np, "over-current-active-low")) {
 		data->oc_pol_active_low = 1;
 		data->oc_pol_configured = 1;
 	} else {
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 281fc51720cea2ab9d0d63b486fb38c6c4f4ebfc..798cb077867abfee9dcdf00526105c4d1e20ee47 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -753,7 +753,7 @@ static int ci_get_platdata(struct device *dev,
 		return ret;
 	}
 
-	if (of_find_property(dev->of_node, "non-zero-ttctrl-ttha", NULL))
+	if (of_property_read_bool(dev->of_node, "non-zero-ttctrl-ttha"))
 		platdata->flags |= CI_HDRC_SET_NON_ZERO_TTHA;
 
 	ext_id = ERR_PTR(-ENODEV);
@@ -1108,7 +1108,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 	ret = ci_usb_phy_init(ci);
 	if (ret) {
 		dev_err(dev, "unable to init phy: %d\n", ret);
-		return ret;
+		goto ulpi_exit;
 	}
 
 	ci->hw_bank.phys = res->start;
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index bbc610e5bd69c43750015edead6f1f82a5220b96..e72c43615d777283eb0bff060a79378228fbd525 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -247,60 +247,6 @@ static int ci_otg_show(struct seq_file *s, void *unused)
 }
 DEFINE_SHOW_ATTRIBUTE(ci_otg);
 
-static int ci_role_show(struct seq_file *s, void *data)
-{
-	struct ci_hdrc *ci = s->private;
-
-	if (ci->role != CI_ROLE_END)
-		seq_printf(s, "%s\n", ci_role(ci)->name);
-
-	return 0;
-}
-
-static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
-			     size_t count, loff_t *ppos)
-{
-	struct seq_file *s = file->private_data;
-	struct ci_hdrc *ci = s->private;
-	enum ci_role role;
-	char buf[8];
-	int ret;
-
-	if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
-		return -EFAULT;
-
-	for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++)
-		if (ci->roles[role] &&
-		    !strncmp(buf, ci->roles[role]->name,
-			     strlen(ci->roles[role]->name)))
-			break;
-
-	if (role == CI_ROLE_END || role == ci->role)
-		return -EINVAL;
-
-	pm_runtime_get_sync(ci->dev);
-	disable_irq(ci->irq);
-	ci_role_stop(ci);
-	ret = ci_role_start(ci, role);
-	enable_irq(ci->irq);
-	pm_runtime_put_sync(ci->dev);
-
-	return ret ? ret : count;
-}
-
-static int ci_role_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ci_role_show, inode->i_private);
-}
-
-static const struct file_operations ci_role_fops = {
-	.open		= ci_role_open,
-	.write		= ci_role_write,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
 static int ci_registers_show(struct seq_file *s, void *unused)
 {
 	struct ci_hdrc *ci = s->private;
@@ -354,7 +300,6 @@ void dbg_create_files(struct ci_hdrc *ci)
 	if (ci_otg_is_fsm_mode(ci))
 		debugfs_create_file("otg", S_IRUGO, dir, ci, &ci_otg_fops);
 
-	debugfs_create_file("role", S_IRUGO | S_IWUSR, dir, ci, &ci_role_fops);
 	debugfs_create_file("registers", S_IRUGO, dir, ci, &ci_registers_fops);
 }
 
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c
index 533baa85083c2e6773f5b5b7483d20b05b782428..a34b22537d7ccfd4810708e756acbd17b8844e50 100644
--- a/drivers/usb/core/usb-acpi.c
+++ b/drivers/usb/core/usb-acpi.c
@@ -81,15 +81,11 @@ int usb_acpi_port_lpm_incapable(struct usb_device *hdev, int index)
 		return -ENODEV;
 	}
 
-	obj = acpi_evaluate_dsm(port_handle, &guid, 0,
-				USB_DSM_DISABLE_U1_U2_FOR_PORT, NULL);
-
-	if (!obj)
-		return -ENODEV;
-
-	if (obj->type != ACPI_TYPE_INTEGER) {
+	obj = acpi_evaluate_dsm_typed(port_handle, &guid, 0,
+				      USB_DSM_DISABLE_U1_U2_FOR_PORT, NULL,
+				      ACPI_TYPE_INTEGER);
+	if (!obj) {
 		dev_dbg(&hdev->dev, "evaluate port-%d _DSM failed\n", port1);
-		ACPI_FREE(obj);
 		return -EINVAL;
 	}
 
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 34742fbbd84d3d3fcdc1362befce683748d7999a..901ec732321c5eccd3133b9c5ee55579110a85e4 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -206,6 +206,82 @@ int usb_find_common_endpoints_reverse(struct usb_host_interface *alt,
 }
 EXPORT_SYMBOL_GPL(usb_find_common_endpoints_reverse);
 
+/**
+ * usb_find_endpoint() - Given an endpoint address, search for the endpoint's
+ * usb_host_endpoint structure in an interface's current altsetting.
+ * @intf: the interface whose current altsetting should be searched
+ * @ep_addr: the endpoint address (number and direction) to find
+ *
+ * Search the altsetting's list of endpoints for one with the specified address.
+ *
+ * Return: Pointer to the usb_host_endpoint if found, %NULL otherwise.
+ */
+static const struct usb_host_endpoint *usb_find_endpoint(
+		const struct usb_interface *intf, unsigned int ep_addr)
+{
+	int n;
+	const struct usb_host_endpoint *ep;
+
+	n = intf->cur_altsetting->desc.bNumEndpoints;
+	ep = intf->cur_altsetting->endpoint;
+	for (; n > 0; (--n, ++ep)) {
+		if (ep->desc.bEndpointAddress == ep_addr)
+			return ep;
+	}
+	return NULL;
+}
+
+/**
+ * usb_check_bulk_endpoints - Check whether an interface's current altsetting
+ * contains a set of bulk endpoints with the given addresses.
+ * @intf: the interface whose current altsetting should be searched
+ * @ep_addrs: 0-terminated array of the endpoint addresses (number and
+ * direction) to look for
+ *
+ * Search for endpoints with the specified addresses and check their types.
+ *
+ * Return: %true if all the endpoints are found and are bulk, %false otherwise.
+ */
+bool usb_check_bulk_endpoints(
+		const struct usb_interface *intf, const u8 *ep_addrs)
+{
+	const struct usb_host_endpoint *ep;
+
+	for (; *ep_addrs; ++ep_addrs) {
+		ep = usb_find_endpoint(intf, *ep_addrs);
+		if (!ep || !usb_endpoint_xfer_bulk(&ep->desc))
+			return false;
+	}
+	return true;
+}
+EXPORT_SYMBOL_GPL(usb_check_bulk_endpoints);
+
+/**
+ * usb_check_int_endpoints - Check whether an interface's current altsetting
+ * contains a set of interrupt endpoints with the given addresses.
+ * @intf: the interface whose current altsetting should be searched
+ * @ep_addrs: 0-terminated array of the endpoint addresses (number and
+ * direction) to look for
+ *
+ * Search for endpoints with the specified addresses and check their types.
+ *
+ * Return: %true if all the endpoints are found and are interrupt,
+ * %false otherwise.
+ */
+bool usb_check_int_endpoints(
+		const struct usb_interface *intf, const u8 *ep_addrs)
+{
+	const struct usb_host_endpoint *ep;
+
+	for (; *ep_addrs; ++ep_addrs) {
+		ep = usb_find_endpoint(intf, *ep_addrs);
+		if (!ep || !usb_endpoint_xfer_int(&ep->desc))
+			return false;
+	}
+	return true;
+}
+EXPORT_SYMBOL_GPL(usb_check_int_endpoints);
+
 /**
  * usb_find_alt_setting() - Given a configuration, find the alternate setting
  * for the given interface.
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 40cf2880d7e595354a25fafd056f6758f19d5ecc..0bb4c0c845bfa6d5ddde3228da328062bd4dd572 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1003,6 +1003,7 @@ struct dwc2_hregs_backup {
  * @ctrl_out_desc:	EP0 OUT data phase desc chain pointer
  * @irq:		Interrupt request line number
  * @clk:		Pointer to otg clock
+ * @utmi_clk:		Pointer to utmi_clk clock
  * @reset:		Pointer to dwc2 reset controller
  * @reset_ecc:          Pointer to dwc2 optional reset controller in Stratix10.
  * @regset:		A pointer to a struct debugfs_regset32, which contains
@@ -1065,6 +1066,7 @@ struct dwc2_hsotg {
 	void *priv;
 	int     irq;
 	struct clk *clk;
+	struct clk *utmi_clk;
 	struct reset_control *reset;
 	struct reset_control *reset_ecc;
 
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index 0a1145592fc766924dc0978d4caf6c66ca9e5a93..0d4495c6b9f7b4c5be0fca6f64c7dbbbaa16f1a5 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -1078,7 +1078,7 @@ static void dwc2_pick_first_frame(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
 	earliest_frame = dwc2_frame_num_inc(frame_number, 1);
 	next_active_frame = earliest_frame;
 
-	/* Get the "no microframe schduler" out of the way... */
+	/* Get the "no microframe scheduler" out of the way... */
 	if (!hsotg->params.uframe_sched) {
 		if (qh->do_split)
 			/* Splits are active at microframe 0 minus 1 */
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 9ed9fd9569404d692f5681139c2d70cf8efb0ebc..21d16533bd2f4f4720db2b82092ee04c5ea22372 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -508,8 +508,7 @@ static void dwc2_get_device_properties(struct dwc2_hsotg *hsotg)
 		of_usb_update_otg_caps(hsotg->dev->of_node, &p->otg_caps);
 	}
 
-	if (of_find_property(hsotg->dev->of_node, "disable-over-current", NULL))
-		p->oc_disable = true;
+	p->oc_disable = of_property_read_bool(hsotg->dev->of_node, "disable-over-current");
 }
 
 static void dwc2_check_param_otg_cap(struct dwc2_hsotg *hsotg)
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index d1589ba7d322dc6ccf8427ab29c131059c4ee80a..5aee284018c006b2114087e5dbbda974a00ea6da 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -101,10 +101,16 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
 	if (ret)
 		return ret;
 
+	if (hsotg->utmi_clk) {
+		ret = clk_prepare_enable(hsotg->utmi_clk);
+		if (ret)
+			goto err_dis_reg;
+	}
+
 	if (hsotg->clk) {
 		ret = clk_prepare_enable(hsotg->clk);
 		if (ret)
-			return ret;
+			goto err_dis_utmi_clk;
 	}
 
 	if (hsotg->uphy) {
@@ -113,10 +119,29 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
 		ret = hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
 	} else {
 		ret = phy_init(hsotg->phy);
-		if (ret == 0)
+		if (ret == 0) {
 			ret = phy_power_on(hsotg->phy);
+			if (ret)
+				phy_exit(hsotg->phy);
+		}
 	}
 
+	if (ret)
+		goto err_dis_clk;
+
+	return 0;
+
+err_dis_clk:
+	if (hsotg->clk)
+		clk_disable_unprepare(hsotg->clk);
+
+err_dis_utmi_clk:
+	if (hsotg->utmi_clk)
+		clk_disable_unprepare(hsotg->utmi_clk);
+
+err_dis_reg:
+	regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
+
 	return ret;
 }
 
@@ -156,6 +181,9 @@ static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
 	if (hsotg->clk)
 		clk_disable_unprepare(hsotg->clk);
 
+	if (hsotg->utmi_clk)
+		clk_disable_unprepare(hsotg->utmi_clk);
+
 	return regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 }
 
@@ -232,6 +260,11 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
 	if (IS_ERR(hsotg->clk))
 		return dev_err_probe(hsotg->dev, PTR_ERR(hsotg->clk), "cannot get otg clock\n");
 
+	hsotg->utmi_clk = devm_clk_get_optional(hsotg->dev, "utmi");
+	if (IS_ERR(hsotg->utmi_clk))
+		return dev_err_probe(hsotg->dev, PTR_ERR(hsotg->utmi_clk),
+				     "cannot get utmi clock\n");
+
 	/* Regulators */
 	for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++)
 		hsotg->supplies[i].supply = dwc2_hsotg_supply_names[i];
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 476b63618511665dc297e8b1ee6272356c9260ad..0beaab932e7db2122e05bf52ef84c0c4b538d434 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -534,90 +534,6 @@ void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
 	dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0);
 }
 
-static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
-{
-	if (!dwc->has_hibernation)
-		return 0;
-
-	if (!dwc->nr_scratch)
-		return 0;
-
-	dwc->scratchbuf = kmalloc_array(dwc->nr_scratch,
-			DWC3_SCRATCHBUF_SIZE, GFP_KERNEL);
-	if (!dwc->scratchbuf)
-		return -ENOMEM;
-
-	return 0;
-}
-
-static int dwc3_setup_scratch_buffers(struct dwc3 *dwc)
-{
-	dma_addr_t scratch_addr;
-	u32 param;
-	int ret;
-
-	if (!dwc->has_hibernation)
-		return 0;
-
-	if (!dwc->nr_scratch)
-		return 0;
-
-	 /* should never fall here */
-	if (!WARN_ON(dwc->scratchbuf))
-		return 0;
-
-	scratch_addr = dma_map_single(dwc->sysdev, dwc->scratchbuf,
-			dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
-			DMA_BIDIRECTIONAL);
-	if (dma_mapping_error(dwc->sysdev, scratch_addr)) {
-		dev_err(dwc->sysdev, "failed to map scratch buffer\n");
-		ret = -EFAULT;
-		goto err0;
-	}
-
-	dwc->scratch_addr = scratch_addr;
-
-	param = lower_32_bits(scratch_addr);
-
-	ret = dwc3_send_gadget_generic_command(dwc,
-			DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param);
-	if (ret < 0)
-		goto err1;
-
-	param = upper_32_bits(scratch_addr);
-
-	ret = dwc3_send_gadget_generic_command(dwc,
-			DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param);
-	if (ret < 0)
-		goto err1;
-
-	return 0;
-
-err1:
-	dma_unmap_single(dwc->sysdev, dwc->scratch_addr, dwc->nr_scratch *
-			DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
-
-err0:
-	return ret;
-}
-
-static void dwc3_free_scratch_buffers(struct dwc3 *dwc)
-{
-	if (!dwc->has_hibernation)
-		return;
-
-	if (!dwc->nr_scratch)
-		return;
-
-	 /* should never fall here */
-	if (!WARN_ON(dwc->scratchbuf))
-		return;
-
-	dma_unmap_single(dwc->sysdev, dwc->scratch_addr, dwc->nr_scratch *
-			DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
-	kfree(dwc->scratchbuf);
-}
-
 static void dwc3_core_num_eps(struct dwc3 *dwc)
 {
 	struct dwc3_hwparams	*parms = &dwc->hwparams;
@@ -800,11 +716,91 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
 	if (dwc->dis_u2_freeclk_exists_quirk || dwc->gfladj_refclk_lpm_sel)
 		reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS;
 
+	/*
+	 * Some ULPI USB PHY does not support internal VBUS supply, to drive
+	 * the CPEN pin requires the configuration of the ULPI DRVVBUSEXTERNAL
+	 * bit of OTG_CTRL register. Controller configures the USB2 PHY
+	 * ULPIEXTVBUSDRV bit[17] of the GUSB2PHYCFG register to drive vBus
+	 * with an external supply.
+	 */
+	if (dwc->ulpi_ext_vbus_drv)
+		reg |= DWC3_GUSB2PHYCFG_ULPIEXTVBUSDRV;
+
 	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 
 	return 0;
 }
 
+static int dwc3_phy_init(struct dwc3 *dwc)
+{
+	int ret;
+
+	usb_phy_init(dwc->usb2_phy);
+	usb_phy_init(dwc->usb3_phy);
+
+	ret = phy_init(dwc->usb2_generic_phy);
+	if (ret < 0)
+		goto err_shutdown_usb3_phy;
+
+	ret = phy_init(dwc->usb3_generic_phy);
+	if (ret < 0)
+		goto err_exit_usb2_phy;
+
+	return 0;
+
+err_exit_usb2_phy:
+	phy_exit(dwc->usb2_generic_phy);
+err_shutdown_usb3_phy:
+	usb_phy_shutdown(dwc->usb3_phy);
+	usb_phy_shutdown(dwc->usb2_phy);
+
+	return ret;
+}
+
+static void dwc3_phy_exit(struct dwc3 *dwc)
+{
+	phy_exit(dwc->usb3_generic_phy);
+	phy_exit(dwc->usb2_generic_phy);
+
+	usb_phy_shutdown(dwc->usb3_phy);
+	usb_phy_shutdown(dwc->usb2_phy);
+}
+
+static int dwc3_phy_power_on(struct dwc3 *dwc)
+{
+	int ret;
+
+	usb_phy_set_suspend(dwc->usb2_phy, 0);
+	usb_phy_set_suspend(dwc->usb3_phy, 0);
+
+	ret = phy_power_on(dwc->usb2_generic_phy);
+	if (ret < 0)
+		goto err_suspend_usb3_phy;
+
+	ret = phy_power_on(dwc->usb3_generic_phy);
+	if (ret < 0)
+		goto err_power_off_usb2_phy;
+
+	return 0;
+
+err_power_off_usb2_phy:
+	phy_power_off(dwc->usb2_generic_phy);
+err_suspend_usb3_phy:
+	usb_phy_set_suspend(dwc->usb3_phy, 1);
+	usb_phy_set_suspend(dwc->usb2_phy, 1);
+
+	return ret;
+}
+
+static void dwc3_phy_power_off(struct dwc3 *dwc)
+{
+	phy_power_off(dwc->usb3_generic_phy);
+	phy_power_off(dwc->usb2_generic_phy);
+
+	usb_phy_set_suspend(dwc->usb3_phy, 1);
+	usb_phy_set_suspend(dwc->usb2_phy, 1);
+}
+
 static int dwc3_clk_enable(struct dwc3 *dwc)
 {
 	int ret;
@@ -840,17 +836,8 @@ static void dwc3_clk_disable(struct dwc3 *dwc)
 static void dwc3_core_exit(struct dwc3 *dwc)
 {
 	dwc3_event_buffers_cleanup(dwc);
-
-	usb_phy_set_suspend(dwc->usb2_phy, 1);
-	usb_phy_set_suspend(dwc->usb3_phy, 1);
-	phy_power_off(dwc->usb2_generic_phy);
-	phy_power_off(dwc->usb3_generic_phy);
-
-	usb_phy_shutdown(dwc->usb2_phy);
-	usb_phy_shutdown(dwc->usb3_phy);
-	phy_exit(dwc->usb2_generic_phy);
-	phy_exit(dwc->usb3_generic_phy);
-
+	dwc3_phy_power_off(dwc);
+	dwc3_phy_exit(dwc);
 	dwc3_clk_disable(dwc);
 	reset_control_assert(dwc->reset);
 }
@@ -877,7 +864,6 @@ static bool dwc3_core_is_valid(struct dwc3 *dwc)
 
 static void dwc3_core_setup_global_control(struct dwc3 *dwc)
 {
-	u32 hwparams4 = dwc->hwparams.hwparams4;
 	u32 reg;
 
 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
@@ -905,9 +891,6 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc)
 			reg &= ~DWC3_GCTL_DSBLCLKGTNG;
 		break;
 	case DWC3_GHWPARAMS1_EN_PWROPT_HIB:
-		/* enable hibernation here */
-		dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4);
-
 		/*
 		 * REVISIT Enabling this bit so that host-mode hibernation
 		 * will work. Device-mode hibernation is not yet implemented.
@@ -1096,7 +1079,7 @@ static int dwc3_core_init(struct dwc3 *dwc)
 
 	ret = dwc3_phy_setup(dwc);
 	if (ret)
-		goto err0;
+		return ret;
 
 	if (!dwc->ulpi_ready) {
 		ret = dwc3_core_ulpi_init(dwc);
@@ -1105,7 +1088,7 @@ static int dwc3_core_init(struct dwc3 *dwc)
 				dwc3_core_soft_reset(dwc);
 				ret = -EPROBE_DEFER;
 			}
-			goto err0;
+			return ret;
 		}
 		dwc->ulpi_ready = true;
 	}
@@ -1113,25 +1096,17 @@ static int dwc3_core_init(struct dwc3 *dwc)
 	if (!dwc->phys_ready) {
 		ret = dwc3_core_get_phy(dwc);
 		if (ret)
-			goto err0a;
+			goto err_exit_ulpi;
 		dwc->phys_ready = true;
 	}
 
-	usb_phy_init(dwc->usb2_phy);
-	usb_phy_init(dwc->usb3_phy);
-	ret = phy_init(dwc->usb2_generic_phy);
-	if (ret < 0)
-		goto err0a;
-
-	ret = phy_init(dwc->usb3_generic_phy);
-	if (ret < 0) {
-		phy_exit(dwc->usb2_generic_phy);
-		goto err0a;
-	}
+	ret = dwc3_phy_init(dwc);
+	if (ret)
+		goto err_exit_ulpi;
 
 	ret = dwc3_core_soft_reset(dwc);
 	if (ret)
-		goto err1;
+		goto err_exit_phy;
 
 	if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD &&
 	    !DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) {
@@ -1151,10 +1126,6 @@ static int dwc3_core_init(struct dwc3 *dwc)
 	dwc3_core_setup_global_control(dwc);
 	dwc3_core_num_eps(dwc);
 
-	ret = dwc3_setup_scratch_buffers(dwc);
-	if (ret)
-		goto err1;
-
 	/* Set power down scale of suspend_clk */
 	dwc3_set_power_down_clk_scale(dwc);
 
@@ -1166,20 +1137,14 @@ static int dwc3_core_init(struct dwc3 *dwc)
 
 	dwc3_set_incr_burst_type(dwc);
 
-	usb_phy_set_suspend(dwc->usb2_phy, 0);
-	usb_phy_set_suspend(dwc->usb3_phy, 0);
-	ret = phy_power_on(dwc->usb2_generic_phy);
-	if (ret < 0)
-		goto err2;
-
-	ret = phy_power_on(dwc->usb3_generic_phy);
-	if (ret < 0)
-		goto err3;
+	dwc3_phy_power_on(dwc);
+	if (ret)
+		goto err_exit_phy;
 
 	ret = dwc3_event_buffers_setup(dwc);
 	if (ret) {
 		dev_err(dwc->dev, "failed to setup event buffers\n");
-		goto err4;
+		goto err_power_off_phy;
 	}
 
 	/*
@@ -1233,6 +1198,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
 		if (dwc->parkmode_disable_ss_quirk)
 			reg |= DWC3_GUCTL1_PARKMODE_DISABLE_SS;
 
+		if (dwc->parkmode_disable_hs_quirk)
+			reg |= DWC3_GUCTL1_PARKMODE_DISABLE_HS;
+
 		if (DWC3_VER_IS_WITHIN(DWC3, 290A, ANY) &&
 		    (dwc->maximum_speed == USB_SPEED_HIGH ||
 		     dwc->maximum_speed == USB_SPEED_FULL))
@@ -1296,26 +1264,13 @@ static int dwc3_core_init(struct dwc3 *dwc)
 
 	return 0;
 
-err4:
-	phy_power_off(dwc->usb3_generic_phy);
-
-err3:
-	phy_power_off(dwc->usb2_generic_phy);
-
-err2:
-	usb_phy_set_suspend(dwc->usb2_phy, 1);
-	usb_phy_set_suspend(dwc->usb3_phy, 1);
-
-err1:
-	usb_phy_shutdown(dwc->usb2_phy);
-	usb_phy_shutdown(dwc->usb3_phy);
-	phy_exit(dwc->usb2_generic_phy);
-	phy_exit(dwc->usb3_generic_phy);
-
-err0a:
+err_power_off_phy:
+	dwc3_phy_power_off(dwc);
+err_exit_phy:
+	dwc3_phy_exit(dwc);
+err_exit_ulpi:
 	dwc3_ulpi_exit(dwc);
 
-err0:
 	return ret;
 }
 
@@ -1553,8 +1508,12 @@ static void dwc3_get_properties(struct dwc3 *dwc)
 				"snps,dis-tx-ipgap-linecheck-quirk");
 	dwc->resume_hs_terminations = device_property_read_bool(dev,
 				"snps,resume-hs-terminations");
+	dwc->ulpi_ext_vbus_drv = device_property_read_bool(dev,
+				"snps,ulpi-ext-vbus-drv");
 	dwc->parkmode_disable_ss_quirk = device_property_read_bool(dev,
 				"snps,parkmode-disable-ss-quirk");
+	dwc->parkmode_disable_hs_quirk = device_property_read_bool(dev,
+				"snps,parkmode-disable-hs-quirk");
 	dwc->gfladj_refclk_lpm_sel = device_property_read_bool(dev,
 				"snps,gfladj-refclk-lpm-sel-quirk");
 
@@ -1750,16 +1709,72 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
 	return edev;
 }
 
+static int dwc3_get_clocks(struct dwc3 *dwc)
+{
+	struct device *dev = dwc->dev;
+
+	if (!dev->of_node)
+		return 0;
+
+	/*
+	 * Clocks are optional, but new DT platforms should support all clocks
+	 * as required by the DT-binding.
+	 * Some devices have different clock names in legacy device trees,
+	 * check for them to retain backwards compatibility.
+	 */
+	dwc->bus_clk = devm_clk_get_optional(dev, "bus_early");
+	if (IS_ERR(dwc->bus_clk)) {
+		return dev_err_probe(dev, PTR_ERR(dwc->bus_clk),
+				"could not get bus clock\n");
+	}
+
+	if (dwc->bus_clk == NULL) {
+		dwc->bus_clk = devm_clk_get_optional(dev, "bus_clk");
+		if (IS_ERR(dwc->bus_clk)) {
+			return dev_err_probe(dev, PTR_ERR(dwc->bus_clk),
+					"could not get bus clock\n");
+		}
+	}
+
+	dwc->ref_clk = devm_clk_get_optional(dev, "ref");
+	if (IS_ERR(dwc->ref_clk)) {
+		return dev_err_probe(dev, PTR_ERR(dwc->ref_clk),
+				"could not get ref clock\n");
+	}
+
+	if (dwc->ref_clk == NULL) {
+		dwc->ref_clk = devm_clk_get_optional(dev, "ref_clk");
+		if (IS_ERR(dwc->ref_clk)) {
+			return dev_err_probe(dev, PTR_ERR(dwc->ref_clk),
+					"could not get ref clock\n");
+		}
+	}
+
+	dwc->susp_clk = devm_clk_get_optional(dev, "suspend");
+	if (IS_ERR(dwc->susp_clk)) {
+		return dev_err_probe(dev, PTR_ERR(dwc->susp_clk),
+				"could not get suspend clock\n");
+	}
+
+	if (dwc->susp_clk == NULL) {
+		dwc->susp_clk = devm_clk_get_optional(dev, "suspend_clk");
+		if (IS_ERR(dwc->susp_clk)) {
+			return dev_err_probe(dev, PTR_ERR(dwc->susp_clk),
+					"could not get suspend clock\n");
+		}
+	}
+
+	return 0;
+}
+
 static int dwc3_probe(struct platform_device *pdev)
 {
 	struct device		*dev = &pdev->dev;
 	struct resource		*res, dwc_res;
+	void __iomem		*regs;
 	struct dwc3		*dwc;
-
 	int			ret;
 
-	void __iomem		*regs;
-
 	dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL);
 	if (!dwc)
 		return -ENOMEM;
@@ -1797,77 +1812,25 @@ static int dwc3_probe(struct platform_device *pdev)
 	dwc->reset = devm_reset_control_array_get_optional_shared(dev);
 	if (IS_ERR(dwc->reset)) {
 		ret = PTR_ERR(dwc->reset);
-		goto put_usb_psy;
+		goto err_put_psy;
 	}
 
-	if (dev->of_node) {
-		/*
-		 * Clocks are optional, but new DT platforms should support all
-		 * clocks as required by the DT-binding.
-		 * Some devices have different clock names in legacy device trees,
-		 * check for them to retain backwards compatibility.
-		 */
-		dwc->bus_clk = devm_clk_get_optional(dev, "bus_early");
-		if (IS_ERR(dwc->bus_clk)) {
-			ret = dev_err_probe(dev, PTR_ERR(dwc->bus_clk),
-					    "could not get bus clock\n");
-			goto put_usb_psy;
-		}
-
-		if (dwc->bus_clk == NULL) {
-			dwc->bus_clk = devm_clk_get_optional(dev, "bus_clk");
-			if (IS_ERR(dwc->bus_clk)) {
-				ret = dev_err_probe(dev, PTR_ERR(dwc->bus_clk),
-						    "could not get bus clock\n");
-				goto put_usb_psy;
-			}
-		}
-
-		dwc->ref_clk = devm_clk_get_optional(dev, "ref");
-		if (IS_ERR(dwc->ref_clk)) {
-			ret = dev_err_probe(dev, PTR_ERR(dwc->ref_clk),
-					    "could not get ref clock\n");
-			goto put_usb_psy;
-		}
-
-		if (dwc->ref_clk == NULL) {
-			dwc->ref_clk = devm_clk_get_optional(dev, "ref_clk");
-			if (IS_ERR(dwc->ref_clk)) {
-				ret = dev_err_probe(dev, PTR_ERR(dwc->ref_clk),
-						    "could not get ref clock\n");
-				goto put_usb_psy;
-			}
-		}
-
-		dwc->susp_clk = devm_clk_get_optional(dev, "suspend");
-		if (IS_ERR(dwc->susp_clk)) {
-			ret = dev_err_probe(dev, PTR_ERR(dwc->susp_clk),
-					    "could not get suspend clock\n");
-			goto put_usb_psy;
-		}
-
-		if (dwc->susp_clk == NULL) {
-			dwc->susp_clk = devm_clk_get_optional(dev, "suspend_clk");
-			if (IS_ERR(dwc->susp_clk)) {
-				ret = dev_err_probe(dev, PTR_ERR(dwc->susp_clk),
-						    "could not get suspend clock\n");
-				goto put_usb_psy;
-			}
-		}
-	}
+	ret = dwc3_get_clocks(dwc);
+	if (ret)
+		goto err_put_psy;
 
 	ret = reset_control_deassert(dwc->reset);
 	if (ret)
-		goto put_usb_psy;
+		goto err_put_psy;
 
 	ret = dwc3_clk_enable(dwc);
 	if (ret)
-		goto assert_reset;
+		goto err_assert_reset;
 
 	if (!dwc3_core_is_valid(dwc)) {
 		dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
 		ret = -ENODEV;
-		goto disable_clks;
+		goto err_disable_clks;
 	}
 
 	platform_set_drvdata(pdev, dwc);
@@ -1877,19 +1840,17 @@ static int dwc3_probe(struct platform_device *pdev)
 	    DWC3_GHWPARAMS0_AWIDTH(dwc->hwparams.hwparams0) == 64) {
 		ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64));
 		if (ret)
-			goto disable_clks;
+			goto err_disable_clks;
 	}
 
 	spin_lock_init(&dwc->lock);
 	mutex_init(&dwc->mutex);
 
+	pm_runtime_get_noresume(dev);
 	pm_runtime_set_active(dev);
 	pm_runtime_use_autosuspend(dev);
 	pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
 	pm_runtime_enable(dev);
-	ret = pm_runtime_get_sync(dev);
-	if (ret < 0)
-		goto err1;
 
 	pm_runtime_forbid(dev);
 
@@ -1897,27 +1858,23 @@ static int dwc3_probe(struct platform_device *pdev)
 	if (ret) {
 		dev_err(dwc->dev, "failed to allocate event buffers\n");
 		ret = -ENOMEM;
-		goto err2;
+		goto err_allow_rpm;
 	}
 
 	dwc->edev = dwc3_get_extcon(dwc);
 	if (IS_ERR(dwc->edev)) {
 		ret = dev_err_probe(dwc->dev, PTR_ERR(dwc->edev), "failed to get extcon\n");
-		goto err3;
+		goto err_free_event_buffers;
 	}
 
 	ret = dwc3_get_dr_mode(dwc);
 	if (ret)
-		goto err3;
-
-	ret = dwc3_alloc_scratch_buffers(dwc);
-	if (ret)
-		goto err3;
+		goto err_free_event_buffers;
 
 	ret = dwc3_core_init(dwc);
 	if (ret) {
 		dev_err_probe(dev, ret, "failed to initialize core\n");
-		goto err4;
+		goto err_free_event_buffers;
 	}
 
 	dwc3_check_params(dwc);
@@ -1925,46 +1882,31 @@ static int dwc3_probe(struct platform_device *pdev)
 
 	ret = dwc3_core_init_mode(dwc);
 	if (ret)
-		goto err5;
+		goto err_exit_debugfs;
 
 	pm_runtime_put(dev);
 
 	return 0;
 
-err5:
+err_exit_debugfs:
 	dwc3_debugfs_exit(dwc);
 	dwc3_event_buffers_cleanup(dwc);
-
-	usb_phy_set_suspend(dwc->usb2_phy, 1);
-	usb_phy_set_suspend(dwc->usb3_phy, 1);
-	phy_power_off(dwc->usb2_generic_phy);
-	phy_power_off(dwc->usb3_generic_phy);
-
-	usb_phy_shutdown(dwc->usb2_phy);
-	usb_phy_shutdown(dwc->usb3_phy);
-	phy_exit(dwc->usb2_generic_phy);
-	phy_exit(dwc->usb3_generic_phy);
-
+	dwc3_phy_power_off(dwc);
+	dwc3_phy_exit(dwc);
 	dwc3_ulpi_exit(dwc);
-
-err4:
-	dwc3_free_scratch_buffers(dwc);
-
-err3:
+err_free_event_buffers:
 	dwc3_free_event_buffers(dwc);
-
-err2:
-	pm_runtime_allow(&pdev->dev);
-
-err1:
-	pm_runtime_put_sync(&pdev->dev);
-	pm_runtime_disable(&pdev->dev);
-
-disable_clks:
+err_allow_rpm:
+	pm_runtime_allow(dev);
+	pm_runtime_disable(dev);
+	pm_runtime_dont_use_autosuspend(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
+err_disable_clks:
 	dwc3_clk_disable(dwc);
-assert_reset:
+err_assert_reset:
 	reset_control_assert(dwc->reset);
-put_usb_psy:
+err_put_psy:
 	if (dwc->usb_psy)
 		power_supply_put(dwc->usb_psy);
 
@@ -1983,12 +1925,13 @@ static int dwc3_remove(struct platform_device *pdev)
 	dwc3_core_exit(dwc);
 	dwc3_ulpi_exit(dwc);
 
+	pm_runtime_allow(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 
 	dwc3_free_event_buffers(dwc);
-	dwc3_free_scratch_buffers(dwc);
 
 	if (dwc->usb_psy)
 		power_supply_put(dwc->usb_psy);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 4743e918dcafa96aea30b238ca24d44c36745448..d56457c02996b669c60a096533a506c324ad4a98 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -263,6 +263,7 @@
 #define DWC3_GUCTL1_DEV_FORCE_20_CLK_FOR_30_CLK	BIT(26)
 #define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW		BIT(24)
 #define DWC3_GUCTL1_PARKMODE_DISABLE_SS		BIT(17)
+#define DWC3_GUCTL1_PARKMODE_DISABLE_HS		BIT(16)
 #define DWC3_GUCTL1_RESUME_OPMODE_HS_HOST	BIT(10)
 
 /* Global Status Register */
@@ -280,6 +281,7 @@
 /* Global USB2 PHY Configuration Register */
 #define DWC3_GUSB2PHYCFG_PHYSOFTRST	BIT(31)
 #define DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS	BIT(30)
+#define DWC3_GUSB2PHYCFG_ULPIEXTVBUSDRV	BIT(17)
 #define DWC3_GUSB2PHYCFG_SUSPHY		BIT(6)
 #define DWC3_GUSB2PHYCFG_ULPI_UTMI	BIT(4)
 #define DWC3_GUSB2PHYCFG_ENBLSLPM	BIT(8)
@@ -526,6 +528,7 @@
 #define DWC3_DGCMD_SET_ENDPOINT_NRDY	0x0c
 #define DWC3_DGCMD_SET_ENDPOINT_PRIME	0x0d
 #define DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK	0x10
+#define DWC3_DGCMD_DEV_NOTIFICATION	0x07
 
 #define DWC3_DGCMD_STATUS(n)		(((n) >> 12) & 0x0F)
 #define DWC3_DGCMD_CMDACT		BIT(10)
@@ -538,6 +541,8 @@
 #define DWC3_DGCMDPAR_TX_FIFO			BIT(5)
 #define DWC3_DGCMDPAR_LOOPBACK_DIS		(0 << 0)
 #define DWC3_DGCMDPAR_LOOPBACK_ENA		BIT(0)
+#define DWC3_DGCMDPAR_DN_FUNC_WAKE		BIT(0)
+#define DWC3_DGCMDPAR_INTF_SEL(n)		((n) << 4)
 
 /* Device Endpoint Command Register */
 #define DWC3_DEPCMD_PARAM_SHIFT		16
@@ -969,12 +974,10 @@ struct dwc3_scratchpad_array {
  * @drd_work: workqueue used for role swapping
  * @ep0_trb: trb which is used for the ctrl_req
  * @bounce: address of bounce buffer
- * @scratchbuf: address of scratch buffer
  * @setup_buf: used while precessing STD USB requests
  * @ep0_trb_addr: dma address of @ep0_trb
  * @bounce_addr: dma address of @bounce
  * @ep0_usb_req: dummy req used while handling STD USB requests
- * @scratch_addr: dma address of scratchbuf
  * @ep0_in_setup: one control transfer is completed and enter setup phase
  * @lock: for synchronizing
  * @mutex: for mode switching
@@ -999,7 +1002,6 @@ struct dwc3_scratchpad_array {
  * @current_otg_role: current role of operation while using the OTG block
  * @desired_otg_role: desired role of operation while using the OTG block
  * @otg_restart_host: flag that OTG controller needs to restart host
- * @nr_scratch: number of scratch buffers
  * @u1u2: only used on revisions <1.83a for workaround
  * @maximum_speed: maximum speed requested (mainly for testing purposes)
  * @max_ssp_rate: SuperSpeed Plus maximum signaling rate and lane count
@@ -1056,7 +1058,6 @@ struct dwc3_scratchpad_array {
  * @delayed_status: true when gadget driver asks for delayed status
  * @ep0_bounced: true when we used bounce buffer
  * @ep0_expect_in: true when we expect a DATA IN transfer
- * @has_hibernation: true when dwc3 was configured with Hibernation
  * @sysdev_is_parent: true when dwc3 device has a parent driver
  * @has_lpm_erratum: true when core was configured with LPM Erratum. Note that
  *			there's now way for software to detect this in runtime.
@@ -1100,8 +1101,12 @@ struct dwc3_scratchpad_array {
  *			check during HS transmit.
  * @resume_hs_terminations: Set if we enable quirk for fixing improper crc
  *			generation after resume from suspend.
+ * @ulpi_ext_vbus_drv: Set to confiure the upli chip to drives CPEN pin
+ *			VBUS with an external supply.
  * @parkmode_disable_ss_quirk: set if we need to disable all SuperSpeed
  *			instances in park mode.
+ * @parkmode_disable_hs_quirk: set if we need to disable all HishSpeed
+ *			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
@@ -1110,6 +1115,7 @@ struct dwc3_scratchpad_array {
  *	3	- Reserved
  * @dis_metastability_quirk: set to disable metastability quirk.
  * @dis_split_quirk: set to disable split boundary.
+ * @wakeup_configured: set if the device is configured for remote wakeup.
  * @imod_interval: set the interrupt moderation interval in 250ns
  *			increments or 0 to disable.
  * @max_cfg_eps: current max number of IN eps used across all USB configs.
@@ -1123,11 +1129,9 @@ struct dwc3 {
 	struct work_struct	drd_work;
 	struct dwc3_trb		*ep0_trb;
 	void			*bounce;
-	void			*scratchbuf;
 	u8			*setup_buf;
 	dma_addr_t		ep0_trb_addr;
 	dma_addr_t		bounce_addr;
-	dma_addr_t		scratch_addr;
 	struct dwc3_request	ep0_usb_req;
 	struct completion	ep0_in_setup;
 
@@ -1187,7 +1191,6 @@ struct dwc3 {
 	u32			current_otg_role;
 	u32			desired_otg_role;
 	bool			otg_restart_host;
-	u32			nr_scratch;
 	u32			u1u2;
 	u32			maximum_speed;
 	u32			gadget_max_speed;
@@ -1284,7 +1287,6 @@ struct dwc3 {
 	unsigned		delayed_status:1;
 	unsigned		ep0_bounced:1;
 	unsigned		ep0_expect_in:1;
-	unsigned		has_hibernation:1;
 	unsigned		sysdev_is_parent:1;
 	unsigned		has_lpm_erratum:1;
 	unsigned		is_utmi_l1_suspend:1;
@@ -1317,7 +1319,9 @@ struct dwc3 {
 	unsigned		dis_del_phy_power_chg_quirk:1;
 	unsigned		dis_tx_ipgap_linecheck_quirk:1;
 	unsigned		resume_hs_terminations:1;
+	unsigned		ulpi_ext_vbus_drv:1;
 	unsigned		parkmode_disable_ss_quirk:1;
+	unsigned		parkmode_disable_hs_quirk:1;
 	unsigned		gfladj_refclk_lpm_sel:1;
 
 	unsigned		tx_de_emphasis_quirk:1;
@@ -1327,6 +1331,7 @@ struct dwc3 {
 
 	unsigned		dis_split_quirk:1;
 	unsigned		async_callbacks:1;
+	unsigned		wakeup_configured:1;
 
 	u16			imod_interval;
 
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h
index 8bb2c9e3b9ac669d0338c45d136a967660ec0fb8..09d703852a92bd9b86fde2262c45068af6aa8c9b 100644
--- a/drivers/usb/dwc3/debug.h
+++ b/drivers/usb/dwc3/debug.h
@@ -72,6 +72,8 @@ dwc3_gadget_generic_cmd_string(u8 cmd)
 		return "Set Endpoint Prime";
 	case DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK:
 		return "Run SoC Bus Loopback Test";
+	case DWC3_DGCMD_DEV_NOTIFICATION:
+		return "Device Notification";
 	default:
 		return "UNKNOWN";
 	}
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index 850df0e6bcabf657a0cceba2e0f607e772bb40cc..e4a2560b9dc0c670d9a5c775a73d17c340b5a992 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -88,6 +88,9 @@ static const struct debugfs_reg32 dwc3_regs[] = {
 	dump_register(GPRTBIMAP_HS1),
 	dump_register(GPRTBIMAP_FS0),
 	dump_register(GPRTBIMAP_FS1),
+	dump_register(GUCTL2),
+	dump_register(VER_NUMBER),
+	dump_register(VER_TYPE),
 
 	dump_register(GUSB2PHYCFG(0)),
 	dump_register(GUSB2PHYCFG(1)),
@@ -229,6 +232,8 @@ static const struct debugfs_reg32 dwc3_regs[] = {
 	dump_register(GEVNTCOUNT(0)),
 
 	dump_register(GHWPARAMS8),
+	dump_register(GUCTL3),
+	dump_register(GFLADJ),
 	dump_register(DCFG),
 	dump_register(DCTL),
 	dump_register(DEVTEN),
diff --git a/drivers/usb/dwc3/dwc3-am62.c b/drivers/usb/dwc3/dwc3-am62.c
index 173cf3579c55d8098f89f1c5a1615cdc5eb98611..cda9458c809b3b418ae1abe96372fac80a040dce 100644
--- a/drivers/usb/dwc3/dwc3-am62.c
+++ b/drivers/usb/dwc3/dwc3-am62.c
@@ -11,12 +11,14 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/syscon.h>
 #include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
 #include <linux/clk.h>
 #include <linux/regmap.h>
 #include <linux/pinctrl/consumer.h>
 
+#include "core.h"
+
 /* USB WRAPPER register offsets */
 #define USBSS_PID			0x0
 #define USBSS_OVERCURRENT_CTRL		0x4
@@ -45,6 +47,10 @@
 #define USBSS_PHY_VBUS_SEL_SHIFT	1
 #define USBSS_PHY_LANE_REVERSE		BIT(0)
 
+/* CORE STAT register bits */
+#define USBSS_CORE_OPERATIONAL_MODE_MASK	GENMASK(13, 12)
+#define USBSS_CORE_OPERATIONAL_MODE_SHIFT	12
+
 /* MODE CONTROL register bits */
 #define USBSS_MODE_VALID	BIT(0)
 
@@ -54,6 +60,13 @@
 #define USBSS_WAKEUP_CFG_SESSVALID_EN	BIT(1)
 #define USBSS_WAKEUP_CFG_VBUSVALID_EN	BIT(0)
 
+#define USBSS_WAKEUP_CFG_ALL	(USBSS_WAKEUP_CFG_VBUSVALID_EN | \
+				 USBSS_WAKEUP_CFG_SESSVALID_EN | \
+				 USBSS_WAKEUP_CFG_LINESTATE_EN | \
+				 USBSS_WAKEUP_CFG_OVERCURRENT_EN)
+
+#define USBSS_WAKEUP_CFG_NONE	0
+
 /* WAKEUP STAT register bits */
 #define USBSS_WAKEUP_STAT_OVERCURRENT	BIT(4)
 #define USBSS_WAKEUP_STAT_LINESTATE	BIT(3)
@@ -97,6 +110,7 @@ struct dwc3_data {
 	struct regmap *syscon;
 	unsigned int offset;
 	unsigned int vbus_divider;
+	u32 wakeup_stat;
 };
 
 static const int dwc3_ti_rate_table[] = {	/* in KHZ */
@@ -233,6 +247,12 @@ static int dwc3_ti_probe(struct platform_device *pdev)
 	reg |= USBSS_MODE_VALID;
 	dwc3_ti_writel(data, USBSS_MODE_CONTROL, reg);
 
+	/* Device has capability to wakeup system from sleep */
+	device_set_wakeup_capable(dev, true);
+	ret = device_wakeup_enable(dev);
+	if (ret)
+		dev_err(dev, "couldn't enable device as a wakeup source: %d\n", ret);
+
 	/* Setting up autosuspend */
 	pm_runtime_set_autosuspend_delay(dev, DWC3_AM62_AUTOSUSPEND_DELAY);
 	pm_runtime_use_autosuspend(dev);
@@ -281,6 +301,27 @@ static int dwc3_ti_remove(struct platform_device *pdev)
 static int dwc3_ti_suspend_common(struct device *dev)
 {
 	struct dwc3_data *data = dev_get_drvdata(dev);
+	u32 reg, current_prtcap_dir;
+
+	if (device_may_wakeup(dev)) {
+		reg = dwc3_ti_readl(data, USBSS_CORE_STAT);
+		current_prtcap_dir = (reg & USBSS_CORE_OPERATIONAL_MODE_MASK)
+				     >> USBSS_CORE_OPERATIONAL_MODE_SHIFT;
+		/* Set wakeup config enable bits */
+		reg = dwc3_ti_readl(data, USBSS_WAKEUP_CONFIG);
+		if (current_prtcap_dir == DWC3_GCTL_PRTCAP_HOST) {
+			reg = USBSS_WAKEUP_CFG_LINESTATE_EN | USBSS_WAKEUP_CFG_OVERCURRENT_EN;
+		} else {
+			reg = USBSS_WAKEUP_CFG_VBUSVALID_EN | USBSS_WAKEUP_CFG_SESSVALID_EN;
+			/*
+			 * Enable LINESTATE wake up only if connected to bus
+			 * and in U2/L3 state else it causes spurious wake-up.
+			 */
+		}
+		dwc3_ti_writel(data, USBSS_WAKEUP_CONFIG, reg);
+		/* clear wakeup status so we know what caused the wake up */
+		dwc3_ti_writel(data, USBSS_WAKEUP_STAT, USBSS_WAKEUP_STAT_CLR);
+	}
 
 	clk_disable_unprepare(data->usb2_refclk);
 
@@ -290,9 +331,18 @@ static int dwc3_ti_suspend_common(struct device *dev)
 static int dwc3_ti_resume_common(struct device *dev)
 {
 	struct dwc3_data *data = dev_get_drvdata(dev);
+	u32 reg;
 
 	clk_prepare_enable(data->usb2_refclk);
 
+	if (device_may_wakeup(dev)) {
+		/* Clear wakeup config enable bits */
+		dwc3_ti_writel(data, USBSS_WAKEUP_CONFIG, USBSS_WAKEUP_CFG_NONE);
+	}
+
+	reg = dwc3_ti_readl(data, USBSS_WAKEUP_STAT);
+	data->wakeup_stat = reg;
+
 	return 0;
 }
 
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index 560793545362afc0ee105f54a086a87b003fbe46..44a04c9b20735014df5e90920e1ef50e2830c138 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -388,107 +388,41 @@ static void dwc3_pci_remove(struct pci_dev *pci)
 }
 
 static const struct pci_device_id dwc3_pci_id_table[] = {
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BSW),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BYT),
-	  (kernel_ulong_t) &dwc3_pci_intel_byt_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MRFLD),
-	  (kernel_ulong_t) &dwc3_pci_intel_mrfld_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CMLLP),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CMLH),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SPTLP),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SPTH),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BXT),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BXT_M),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_APL),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_KBP),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_GLK),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CNPLP),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CNPH),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CNPV),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICLLP),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_EHL),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGPLP),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGPH),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_JSP),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADL),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADL_PCH),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADLN),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADLN_PCH),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADLS),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPL),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPLS),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTLM),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTLP),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTLS),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL),
-	  (kernel_ulong_t) &dwc3_pci_intel_swnode, },
-
-	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_NL_USB),
-	  (kernel_ulong_t) &dwc3_pci_amd_swnode, },
-
-	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MR),
-	  (kernel_ulong_t)&dwc3_pci_amd_mr_swnode, },
+	{ PCI_DEVICE_DATA(INTEL, BSW, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, BYT, &dwc3_pci_intel_byt_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, MRFLD, &dwc3_pci_intel_mrfld_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, CMLLP, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, CMLH, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, SPTLP, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, SPTH, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, BXT, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, BXT_M, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, APL, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, KBP, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, GLK, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, CNPLP, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, CNPH, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, CNPV, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, ICLLP, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, EHL, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, TGPLP, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, TGPH, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, JSP, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, ADL, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, ADL_PCH, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, ADLN, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, ADLN_PCH, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, ADLS, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, RPL, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, RPLS, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, MTLM, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, MTLP, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, MTL, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) },
+	{ PCI_DEVICE_DATA(INTEL, TGL, &dwc3_pci_intel_swnode) },
+
+	{ PCI_DEVICE_DATA(AMD, NL_USB, &dwc3_pci_amd_swnode) },
+	{ PCI_DEVICE_DATA(AMD, MR, &dwc3_pci_amd_mr_swnode) },
 
 	{  }	/* Terminating Entry */
 };
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 61de693461da4780bb9017b67a0d37e823b1b7ee..953b752a50526dd37c0968258d972df4cef2b645 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -30,6 +30,8 @@
 static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep);
 static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
 		struct dwc3_ep *dep, struct dwc3_request *req);
+static int dwc3_ep0_delegate_req(struct dwc3 *dwc,
+				 struct usb_ctrlrequest *ctrl);
 
 static void dwc3_ep0_prepare_one_trb(struct dwc3_ep *dep,
 		dma_addr_t buf_dma, u32 len, u32 type, bool chain)
@@ -356,6 +358,9 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
 				usb_status |= 1 << USB_DEV_STAT_U1_ENABLED;
 			if (reg & DWC3_DCTL_INITU2ENA)
 				usb_status |= 1 << USB_DEV_STAT_U2_ENABLED;
+		} else {
+			usb_status |= dwc->gadget->wakeup_armed <<
+					USB_DEVICE_REMOTE_WAKEUP;
 		}
 
 		break;
@@ -365,7 +370,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
 		 * Function Remote Wake Capable	D0
 		 * Function Remote Wakeup	D1
 		 */
-		break;
+		return dwc3_ep0_delegate_req(dwc, ctrl);
 
 	case USB_RECIP_ENDPOINT:
 		dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex);
@@ -476,6 +481,10 @@ static int dwc3_ep0_handle_device(struct dwc3 *dwc,
 
 	switch (wValue) {
 	case USB_DEVICE_REMOTE_WAKEUP:
+		if (dwc->wakeup_configured)
+			dwc->gadget->wakeup_armed = set;
+		else
+			ret = -EINVAL;
 		break;
 	/*
 	 * 9.4.1 says only for SS, in AddressState only for
@@ -510,13 +519,7 @@ static int dwc3_ep0_handle_intf(struct dwc3 *dwc,
 
 	switch (wValue) {
 	case USB_INTRF_FUNC_SUSPEND:
-		/*
-		 * REVISIT: Ideally we would enable some low power mode here,
-		 * however it's unclear what we should be doing here.
-		 *
-		 * For now, we're not doing anything, just making sure we return
-		 * 0 so USB Command Verifier tests pass without any errors.
-		 */
+		ret = dwc3_ep0_delegate_req(dwc, ctrl);
 		break;
 	default:
 		ret = -EINVAL;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index cf5b4f49c3ed8241fdf34d5ebd9ae15d78c14e89..c0ca4d12f95d96b189128456d1b7c33455c02723 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -139,6 +139,24 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state)
 	return -ETIMEDOUT;
 }
 
+static void dwc3_ep0_reset_state(struct dwc3 *dwc)
+{
+	unsigned int	dir;
+
+	if (dwc->ep0state != EP0_SETUP_PHASE) {
+		dir = !!dwc->ep0_expect_in;
+		if (dwc->ep0state == EP0_DATA_PHASE)
+			dwc3_ep0_end_control_data(dwc, dwc->eps[dir]);
+		else
+			dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]);
+
+		dwc->eps[0]->trb_enqueue = 0;
+		dwc->eps[1]->trb_enqueue = 0;
+
+		dwc3_ep0_stall_and_restart(dwc);
+	}
+}
+
 /**
  * dwc3_ep_inc_trb - increment a trb index.
  * @index: Pointer to the TRB index to increment.
@@ -258,7 +276,7 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd,
 	return ret;
 }
 
-static int __dwc3_gadget_wakeup(struct dwc3 *dwc);
+static int __dwc3_gadget_wakeup(struct dwc3 *dwc, bool async);
 
 /**
  * dwc3_send_gadget_ep_cmd - issue an endpoint command
@@ -325,7 +343,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
 
 			fallthrough;
 		case DWC3_LINK_STATE_U3:
-			ret = __dwc3_gadget_wakeup(dwc);
+			ret = __dwc3_gadget_wakeup(dwc, false);
 			dev_WARN_ONCE(dwc->dev, ret, "wakeup failed --> %d\n",
 					ret);
 			break;
@@ -2273,6 +2291,22 @@ static const struct usb_ep_ops dwc3_gadget_ep_ops = {
 
 /* -------------------------------------------------------------------------- */
 
+static void dwc3_gadget_enable_linksts_evts(struct dwc3 *dwc, bool set)
+{
+	u32 reg;
+
+	if (DWC3_VER_IS_PRIOR(DWC3, 250A))
+		return;
+
+	reg = dwc3_readl(dwc->regs, DWC3_DEVTEN);
+	if (set)
+		reg |= DWC3_DEVTEN_ULSTCNGEN;
+	else
+		reg &= ~DWC3_DEVTEN_ULSTCNGEN;
+
+	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
+}
+
 static int dwc3_gadget_get_frame(struct usb_gadget *g)
 {
 	struct dwc3		*dwc = gadget_to_dwc(g);
@@ -2280,7 +2314,7 @@ static int dwc3_gadget_get_frame(struct usb_gadget *g)
 	return __dwc3_gadget_get_frame(dwc);
 }
 
-static int __dwc3_gadget_wakeup(struct dwc3 *dwc)
+static int __dwc3_gadget_wakeup(struct dwc3 *dwc, bool async)
 {
 	int			retries;
 
@@ -2311,9 +2345,13 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc)
 		return -EINVAL;
 	}
 
+	if (async)
+		dwc3_gadget_enable_linksts_evts(dwc, true);
+
 	ret = dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RECOV);
 	if (ret < 0) {
 		dev_err(dwc->dev, "failed to put link in Recovery\n");
+		dwc3_gadget_enable_linksts_evts(dwc, false);
 		return ret;
 	}
 
@@ -2325,6 +2363,13 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc)
 		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 	}
 
+	/*
+	 * Since link status change events are enabled we will receive
+	 * an U0 event when wakeup is successful. So bail out.
+	 */
+	if (async)
+		return 0;
+
 	/* poll until Link State changes to ON */
 	retries = 20000;
 
@@ -2350,13 +2395,77 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g)
 	unsigned long		flags;
 	int			ret;
 
+	if (!dwc->wakeup_configured) {
+		dev_err(dwc->dev, "remote wakeup not configured\n");
+		return -EINVAL;
+	}
+
 	spin_lock_irqsave(&dwc->lock, flags);
-	ret = __dwc3_gadget_wakeup(dwc);
+	if (!dwc->gadget->wakeup_armed) {
+		dev_err(dwc->dev, "not armed for remote wakeup\n");
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		return -EINVAL;
+	}
+	ret = __dwc3_gadget_wakeup(dwc, true);
+
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
 	return ret;
 }
 
+static void dwc3_resume_gadget(struct dwc3 *dwc);
+
+static int dwc3_gadget_func_wakeup(struct usb_gadget *g, int intf_id)
+{
+	struct  dwc3		*dwc = gadget_to_dwc(g);
+	unsigned long		flags;
+	int			ret;
+	int			link_state;
+
+	if (!dwc->wakeup_configured) {
+		dev_err(dwc->dev, "remote wakeup not configured\n");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&dwc->lock, flags);
+	/*
+	 * If the link is in U3, signal for remote wakeup and wait for the
+	 * link to transition to U0 before sending device notification.
+	 */
+	link_state = dwc3_gadget_get_link_state(dwc);
+	if (link_state == DWC3_LINK_STATE_U3) {
+		ret = __dwc3_gadget_wakeup(dwc, false);
+		if (ret) {
+			spin_unlock_irqrestore(&dwc->lock, flags);
+			return -EINVAL;
+		}
+		dwc3_resume_gadget(dwc);
+		dwc->link_state = DWC3_LINK_STATE_U0;
+	}
+
+	ret = dwc3_send_gadget_generic_command(dwc, DWC3_DGCMD_DEV_NOTIFICATION,
+					       DWC3_DGCMDPAR_DN_FUNC_WAKE |
+					       DWC3_DGCMDPAR_INTF_SEL(intf_id));
+	if (ret)
+		dev_err(dwc->dev, "function remote wakeup failed, ret:%d\n", ret);
+
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	return ret;
+}
+
+static int dwc3_gadget_set_remote_wakeup(struct usb_gadget *g, int set)
+{
+	struct dwc3		*dwc = gadget_to_dwc(g);
+	unsigned long		flags;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+	dwc->wakeup_configured = !!set;
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	return 0;
+}
+
 static int dwc3_gadget_set_selfpowered(struct usb_gadget *g,
 		int is_selfpowered)
 {
@@ -2478,7 +2587,7 @@ static void __dwc3_gadget_set_speed(struct dwc3 *dwc)
 	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 }
 
-static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
+static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
 {
 	u32			reg;
 	u32			timeout = 2000;
@@ -2497,17 +2606,11 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
 			reg &= ~DWC3_DCTL_KEEP_CONNECT;
 		reg |= DWC3_DCTL_RUN_STOP;
 
-		if (dwc->has_hibernation)
-			reg |= DWC3_DCTL_KEEP_CONNECT;
-
 		__dwc3_gadget_set_speed(dwc);
 		dwc->pullups_connected = true;
 	} else {
 		reg &= ~DWC3_DCTL_RUN_STOP;
 
-		if (dwc->has_hibernation && !suspend)
-			reg &= ~DWC3_DCTL_KEEP_CONNECT;
-
 		dwc->pullups_connected = false;
 	}
 
@@ -2532,29 +2635,17 @@ static int __dwc3_gadget_start(struct dwc3 *dwc);
 static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc)
 {
 	unsigned long flags;
+	int ret;
 
 	spin_lock_irqsave(&dwc->lock, flags);
 	dwc->connected = false;
 
 	/*
-	 * Per databook, when we want to stop the gadget, if a control transfer
-	 * is still in process, complete it and get the core into setup phase.
+	 * Attempt to end pending SETUP status phase, and not wait for the
+	 * function to do so.
 	 */
-	if (dwc->ep0state != EP0_SETUP_PHASE) {
-		int ret;
-
-		if (dwc->delayed_status)
-			dwc3_ep0_send_delayed_status(dwc);
-
-		reinit_completion(&dwc->ep0_in_setup);
-
-		spin_unlock_irqrestore(&dwc->lock, flags);
-		ret = wait_for_completion_timeout(&dwc->ep0_in_setup,
-				msecs_to_jiffies(DWC3_PULL_UP_TIMEOUT));
-		spin_lock_irqsave(&dwc->lock, flags);
-		if (ret == 0)
-			dev_warn(dwc->dev, "timed out waiting for SETUP phase\n");
-	}
+	if (dwc->delayed_status)
+		dwc3_ep0_send_delayed_status(dwc);
 
 	/*
 	 * In the Synopsys DesignWare Cores USB3 Databook Rev. 3.30a
@@ -2564,9 +2655,28 @@ static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc)
 	 * bit.
 	 */
 	dwc3_stop_active_transfers(dwc);
-	__dwc3_gadget_stop(dwc);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
+	/*
+	 * Per databook, when we want to stop the gadget, if a control transfer
+	 * is still in process, complete it and get the core into setup phase.
+	 * In case the host is unresponsive to a SETUP transaction, forcefully
+	 * stall the transfer, and move back to the SETUP phase, so that any
+	 * pending endxfers can be executed.
+	 */
+	if (dwc->ep0state != EP0_SETUP_PHASE) {
+		reinit_completion(&dwc->ep0_in_setup);
+
+		ret = wait_for_completion_timeout(&dwc->ep0_in_setup,
+				msecs_to_jiffies(DWC3_PULL_UP_TIMEOUT));
+		if (ret == 0) {
+			dev_warn(dwc->dev, "wait for SETUP phase timed out\n");
+			spin_lock_irqsave(&dwc->lock, flags);
+			dwc3_ep0_reset_state(dwc);
+			spin_unlock_irqrestore(&dwc->lock, flags);
+		}
+	}
+
 	/*
 	 * Note: if the GEVNTCOUNT indicates events in the event buffer, the
 	 * driver needs to acknowledge them before the controller can halt.
@@ -2574,7 +2684,19 @@ static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc)
 	 * remaining event generated by the controller while polling for
 	 * DSTS.DEVCTLHLT.
 	 */
-	return dwc3_gadget_run_stop(dwc, false, false);
+	ret = dwc3_gadget_run_stop(dwc, false);
+
+	/*
+	 * Stop the gadget after controller is halted, so that if needed, the
+	 * events to update EP0 state can still occur while the run/stop
+	 * routine polls for the halted state.  DEVTEN is cleared as part of
+	 * gadget stop.
+	 */
+	spin_lock_irqsave(&dwc->lock, flags);
+	__dwc3_gadget_stop(dwc);
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	return ret;
 }
 
 static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
@@ -2628,7 +2750,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 
 		dwc3_event_buffers_setup(dwc);
 		__dwc3_gadget_start(dwc);
-		ret = dwc3_gadget_run_stop(dwc, true, false);
+		ret = dwc3_gadget_run_stop(dwc, true);
 	}
 
 	pm_runtime_put(dwc->dev);
@@ -2982,6 +3104,8 @@ static void dwc3_gadget_async_callbacks(struct usb_gadget *g, bool enable)
 static const struct usb_gadget_ops dwc3_gadget_ops = {
 	.get_frame		= dwc3_gadget_get_frame,
 	.wakeup			= dwc3_gadget_wakeup,
+	.func_wakeup		= dwc3_gadget_func_wakeup,
+	.set_remote_wakeup	= dwc3_gadget_set_remote_wakeup,
 	.set_selfpowered	= dwc3_gadget_set_selfpowered,
 	.pullup			= dwc3_gadget_pullup,
 	.udc_start		= dwc3_gadget_start,
@@ -3827,18 +3951,11 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
 
 	dwc->gadget->speed = USB_SPEED_UNKNOWN;
 	dwc->setup_packet_pending = false;
+	dwc->gadget->wakeup_armed = false;
+	dwc3_gadget_enable_linksts_evts(dwc, false);
 	usb_gadget_set_state(dwc->gadget, USB_STATE_NOTATTACHED);
 
-	if (dwc->ep0state != EP0_SETUP_PHASE) {
-		unsigned int    dir;
-
-		dir = !!dwc->ep0_expect_in;
-		if (dwc->ep0state == EP0_DATA_PHASE)
-			dwc3_ep0_end_control_data(dwc, dwc->eps[dir]);
-		else
-			dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]);
-		dwc3_ep0_stall_and_restart(dwc);
-	}
+	dwc3_ep0_reset_state(dwc);
 }
 
 static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
@@ -3892,20 +4009,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 	 * phase. So ensure that EP0 is in setup phase by issuing a stall
 	 * and restart if EP0 is not in setup phase.
 	 */
-	if (dwc->ep0state != EP0_SETUP_PHASE) {
-		unsigned int	dir;
-
-		dir = !!dwc->ep0_expect_in;
-		if (dwc->ep0state == EP0_DATA_PHASE)
-			dwc3_ep0_end_control_data(dwc, dwc->eps[dir]);
-		else
-			dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]);
-
-		dwc->eps[0]->trb_enqueue = 0;
-		dwc->eps[1]->trb_enqueue = 0;
-
-		dwc3_ep0_stall_and_restart(dwc);
-	}
+	dwc3_ep0_reset_state(dwc);
 
 	/*
 	 * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
@@ -3920,6 +4024,8 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 	reg &= ~DWC3_DCTL_TSTCTRL_MASK;
 	dwc3_gadget_dctl_write_safe(dwc, reg);
 	dwc->test_mode = false;
+	dwc->gadget->wakeup_armed = false;
+	dwc3_gadget_enable_linksts_evts(dwc, false);
 	dwc3_clear_stall_all_ep(dwc);
 
 	/* Reset device address to zero */
@@ -4072,7 +4178,7 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 	 */
 }
 
-static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc)
+static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, unsigned int evtinfo)
 {
 	/*
 	 * TODO take core out of low power mode when that's
@@ -4084,6 +4190,8 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc)
 		dwc->gadget_driver->resume(dwc->gadget);
 		spin_lock(&dwc->lock);
 	}
+
+	dwc->link_state = evtinfo & DWC3_LINK_STATE_MASK;
 }
 
 static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
@@ -4165,6 +4273,12 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
 	}
 
 	switch (next) {
+	case DWC3_LINK_STATE_U0:
+		if (dwc->gadget->wakeup_armed) {
+			dwc3_gadget_enable_linksts_evts(dwc, false);
+			dwc3_resume_gadget(dwc);
+		}
+		break;
 	case DWC3_LINK_STATE_U1:
 		if (dwc->speed == USB_SPEED_SUPER)
 			dwc3_suspend_gadget(dwc);
@@ -4195,30 +4309,6 @@ static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc,
 	dwc->link_state = next;
 }
 
-static void dwc3_gadget_hibernation_interrupt(struct dwc3 *dwc,
-		unsigned int evtinfo)
-{
-	unsigned int is_ss = evtinfo & BIT(4);
-
-	/*
-	 * WORKAROUND: DWC3 revision 2.20a with hibernation support
-	 * have a known issue which can cause USB CV TD.9.23 to fail
-	 * randomly.
-	 *
-	 * Because of this issue, core could generate bogus hibernation
-	 * events which SW needs to ignore.
-	 *
-	 * Refers to:
-	 *
-	 * STAR#9000546576: Device Mode Hibernation: Issue in USB 2.0
-	 * Device Fallback from SuperSpeed
-	 */
-	if (is_ss ^ (dwc->speed == USB_SPEED_SUPER))
-		return;
-
-	/* enter hibernation here */
-}
-
 static void dwc3_gadget_interrupt(struct dwc3 *dwc,
 		const struct dwc3_event_devt *event)
 {
@@ -4233,29 +4323,18 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc,
 		dwc3_gadget_conndone_interrupt(dwc);
 		break;
 	case DWC3_DEVICE_EVENT_WAKEUP:
-		dwc3_gadget_wakeup_interrupt(dwc);
+		dwc3_gadget_wakeup_interrupt(dwc, event->event_info);
 		break;
 	case DWC3_DEVICE_EVENT_HIBER_REQ:
-		if (dev_WARN_ONCE(dwc->dev, !dwc->has_hibernation,
-					"unexpected hibernation event\n"))
-			break;
-
-		dwc3_gadget_hibernation_interrupt(dwc, event->event_info);
+		dev_WARN_ONCE(dwc->dev, true, "unexpected hibernation event\n");
 		break;
 	case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
 		dwc3_gadget_linksts_change_interrupt(dwc, event->event_info);
 		break;
 	case DWC3_DEVICE_EVENT_SUSPEND:
 		/* It changed to be suspend event for version 2.30a and above */
-		if (!DWC3_VER_IS_PRIOR(DWC3, 230A)) {
-			/*
-			 * Ignore suspend event until the gadget enters into
-			 * USB_STATE_CONFIGURED state.
-			 */
-			if (dwc->gadget->state >= USB_STATE_CONFIGURED)
-				dwc3_gadget_suspend_interrupt(dwc,
-						event->event_info);
-		}
+		if (!DWC3_VER_IS_PRIOR(DWC3, 230A))
+			dwc3_gadget_suspend_interrupt(dwc, event->event_info);
 		break;
 	case DWC3_DEVICE_EVENT_SOF:
 	case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
@@ -4417,11 +4496,6 @@ static int dwc3_gadget_get_irq(struct dwc3 *dwc)
 		goto out;
 
 	irq = platform_get_irq(dwc3_pdev, 0);
-	if (irq > 0)
-		goto out;
-
-	if (!irq)
-		irq = -EINVAL;
 
 out:
 	return irq;
@@ -4493,6 +4567,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 	dwc->gadget->sg_supported	= true;
 	dwc->gadget->name		= "dwc3-gadget";
 	dwc->gadget->lpm_capable	= !dwc->usb2_gadget_lpm_disable;
+	dwc->gadget->wakeup_capable	= true;
 
 	/*
 	 * FIXME We might be setting max_speed to <SUPER, however versions
@@ -4584,7 +4659,7 @@ int dwc3_gadget_suspend(struct dwc3 *dwc)
 	if (!dwc->gadget_driver)
 		return 0;
 
-	dwc3_gadget_run_stop(dwc, false, false);
+	dwc3_gadget_run_stop(dwc, false);
 
 	spin_lock_irqsave(&dwc->lock, flags);
 	dwc3_disconnect_gadget(dwc);
@@ -4605,7 +4680,7 @@ int dwc3_gadget_resume(struct dwc3 *dwc)
 	if (ret < 0)
 		goto err0;
 
-	ret = dwc3_gadget_run_stop(dwc, true, false);
+	ret = dwc3_gadget_run_stop(dwc, true);
 	if (ret < 0)
 		goto err1;
 
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index f6f13e7f1ba14a8457f32d03627ae183351cdf6b..61f57fe5bb783bcf676cdb47177c66bb2a2e81be 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -52,13 +52,8 @@ static int dwc3_host_get_irq(struct dwc3 *dwc)
 		goto out;
 
 	irq = platform_get_irq(dwc3_pdev, 0);
-	if (irq > 0) {
+	if (irq > 0)
 		dwc3_host_fill_xhci_irq_res(dwc, irq, NULL);
-		goto out;
-	}
-
-	if (!irq)
-		irq = -EINVAL;
 
 out:
 	return irq;
diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h
index 1975aec8d36d853261733ed9e189f8c29d7ad621..d2997d17cfbe0bca96ac06b5d92e3234a1608d75 100644
--- a/drivers/usb/dwc3/trace.h
+++ b/drivers/usb/dwc3/trace.h
@@ -54,14 +54,13 @@ DECLARE_EVENT_CLASS(dwc3_log_event,
 	TP_STRUCT__entry(
 		__field(u32, event)
 		__field(u32, ep0state)
-		__dynamic_array(char, str, DWC3_MSG_MAX)
 	),
 	TP_fast_assign(
 		__entry->event = event;
 		__entry->ep0state = dwc->ep0state;
 	),
 	TP_printk("event (%08x): %s", __entry->event,
-			dwc3_decode_event(__get_str(str), DWC3_MSG_MAX,
+			dwc3_decode_event(__get_buf(DWC3_MSG_MAX), DWC3_MSG_MAX,
 					__entry->event, __entry->ep0state))
 );
 
@@ -79,7 +78,6 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
 		__field(__u16, wValue)
 		__field(__u16, wIndex)
 		__field(__u16, wLength)
-		__dynamic_array(char, str, DWC3_MSG_MAX)
 	),
 	TP_fast_assign(
 		__entry->bRequestType = ctrl->bRequestType;
@@ -88,7 +86,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
 		__entry->wIndex = le16_to_cpu(ctrl->wIndex);
 		__entry->wLength = le16_to_cpu(ctrl->wLength);
 	),
-	TP_printk("%s", usb_decode_ctrl(__get_str(str), DWC3_MSG_MAX,
+	TP_printk("%s", usb_decode_ctrl(__get_buf(DWC3_MSG_MAX), DWC3_MSG_MAX,
 					__entry->bRequestType,
 					__entry->bRequest, __entry->wValue,
 					__entry->wIndex, __entry->wLength)
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 5377d873c08eb6fb57895e1fe127f8b0fa16b68e..1b3489149e5ea5f37b317bdcba1e26cbcdbeab92 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -492,6 +492,46 @@ int usb_interface_id(struct usb_configuration *config,
 }
 EXPORT_SYMBOL_GPL(usb_interface_id);
 
+/**
+ * usb_func_wakeup - sends function wake notification to the host.
+ * @func: function that sends the remote wakeup notification.
+ *
+ * Applicable to devices operating at enhanced superspeed when usb
+ * functions are put in function suspend state and armed for function
+ * remote wakeup. On completion, function wake notification is sent. If
+ * the device is in low power state it tries to bring the device to active
+ * state before sending the wake notification. Since it is a synchronous
+ * call, caller must take care of not calling it in interrupt context.
+ * For devices operating at lower speeds  returns negative errno.
+ *
+ * Returns zero on success, else negative errno.
+ */
+int usb_func_wakeup(struct usb_function *func)
+{
+	struct usb_gadget	*gadget = func->config->cdev->gadget;
+	int			id;
+
+	if (!gadget->ops->func_wakeup)
+		return -EOPNOTSUPP;
+
+	if (!func->func_wakeup_armed) {
+		ERROR(func->config->cdev, "not armed for func remote wakeup\n");
+		return -EINVAL;
+	}
+
+	for (id = 0; id < MAX_CONFIG_INTERFACES; id++)
+		if (func->config->interface[id] == func)
+			break;
+
+	if (id == MAX_CONFIG_INTERFACES) {
+		ERROR(func->config->cdev, "Invalid function\n");
+		return -EINVAL;
+	}
+
+	return gadget->ops->func_wakeup(gadget, id);
+}
+EXPORT_SYMBOL_GPL(usb_func_wakeup);
+
 static u8 encode_bMaxPower(enum usb_device_speed speed,
 		struct usb_configuration *c)
 {
@@ -513,6 +553,19 @@ static u8 encode_bMaxPower(enum usb_device_speed speed,
 		return min(val, 900U) / 8;
 }
 
+void check_remote_wakeup_config(struct usb_gadget *g,
+				struct usb_configuration *c)
+{
+	if (USB_CONFIG_ATT_WAKEUP & c->bmAttributes) {
+		/* Reset the rw bit if gadget is not capable of it */
+		if (!g->wakeup_capable && g->ops->set_remote_wakeup) {
+			WARN(c->cdev, "Clearing wakeup bit for config c.%d\n",
+			     c->bConfigurationValue);
+			c->bmAttributes &= ~USB_CONFIG_ATT_WAKEUP;
+		}
+	}
+}
+
 static int config_buf(struct usb_configuration *config,
 		enum usb_device_speed speed, void *buf, u8 type)
 {
@@ -888,6 +941,9 @@ static void reset_config(struct usb_composite_dev *cdev)
 		if (f->disable)
 			f->disable(f);
 
+		/* Section 9.1.1.6, disable remote wakeup when device is reset */
+		f->func_wakeup_armed = false;
+
 		bitmap_zero(f->endpoints, 32);
 	}
 	cdev->config = NULL;
@@ -994,6 +1050,11 @@ static int set_config(struct usb_composite_dev *cdev,
 		power = min(power, 500U);
 	else
 		power = min(power, 900U);
+
+	if (USB_CONFIG_ATT_WAKEUP & c->bmAttributes)
+		usb_gadget_set_remote_wakeup(gadget, 1);
+	else
+		usb_gadget_set_remote_wakeup(gadget, 0);
 done:
 	if (power <= USB_SELF_POWER_VBUS_MAX_DRAW)
 		usb_gadget_set_selfpowered(gadget);
@@ -1948,9 +2009,20 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 		f = cdev->config->interface[intf];
 		if (!f)
 			break;
-		status = f->get_status ? f->get_status(f) : 0;
-		if (status < 0)
-			break;
+
+		if (f->get_status) {
+			status = f->get_status(f);
+			if (status < 0)
+				break;
+		} else {
+			/* Set D0 and D1 bits based on func wakeup capability */
+			if (f->config->bmAttributes & USB_CONFIG_ATT_WAKEUP) {
+				status |= USB_INTRF_STAT_FUNC_RW_CAP;
+				if (f->func_wakeup_armed)
+					status |= USB_INTRF_STAT_FUNC_RW;
+			}
+		}
+
 		put_unaligned_le16(status & 0x0000ffff, req->buf);
 		break;
 	/*
@@ -1972,8 +2044,44 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 			if (!f)
 				break;
 			value = 0;
-			if (f->func_suspend)
+			if (f->func_suspend) {
 				value = f->func_suspend(f, w_index >> 8);
+			/* SetFeature(FUNCTION_SUSPEND) */
+			} else if (ctrl->bRequest == USB_REQ_SET_FEATURE) {
+				if (!(f->config->bmAttributes &
+				      USB_CONFIG_ATT_WAKEUP) &&
+				     (w_index & USB_INTRF_FUNC_SUSPEND_RW))
+					break;
+
+				f->func_wakeup_armed = !!(w_index &
+							  USB_INTRF_FUNC_SUSPEND_RW);
+
+				if (w_index & USB_INTRF_FUNC_SUSPEND_LP) {
+					if (f->suspend && !f->func_suspended) {
+						f->suspend(f);
+						f->func_suspended = true;
+					}
+				/*
+				 * Handle cases where host sends function resume
+				 * through SetFeature(FUNCTION_SUSPEND) but low power
+				 * bit reset
+				 */
+				} else {
+					if (f->resume && f->func_suspended) {
+						f->resume(f);
+						f->func_suspended = false;
+					}
+				}
+			/* ClearFeature(FUNCTION_SUSPEND) */
+			} else if (ctrl->bRequest == USB_REQ_CLEAR_FEATURE) {
+				f->func_wakeup_armed = false;
+
+				if (f->resume && f->func_suspended) {
+					f->resume(f);
+					f->func_suspended = false;
+				}
+			}
+
 			if (value < 0) {
 				ERROR(cdev,
 				      "func_suspend() returned error %d\n",
@@ -2515,7 +2623,12 @@ void composite_resume(struct usb_gadget *gadget)
 		cdev->driver->resume(cdev);
 	if (cdev->config) {
 		list_for_each_entry(f, &cdev->config->functions, list) {
-			if (f->resume)
+			/*
+			 * Check for func_suspended flag to see if the function is
+			 * in USB3 FUNCTION_SUSPEND state. In this case resume is
+			 * done via FUNCTION_SUSPEND feature selector.
+			 */
+			if (f->resume && !f->func_suspended)
 				f->resume(f);
 		}
 
@@ -2530,6 +2643,10 @@ void composite_resume(struct usb_gadget *gadget)
 			usb_gadget_clear_selfpowered(gadget);
 
 		usb_gadget_vbus_draw(gadget, maxpower);
+	} else {
+		maxpower = CONFIG_USB_GADGET_VBUS_DRAW;
+		maxpower = min(maxpower, 100U);
+		usb_gadget_vbus_draw(gadget, maxpower);
 	}
 
 	cdev->suspended = 0;
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index b9f1136aa0a268a7c526e59f450b2126b719f5d7..4c639e9ddedc0a0bc226795cd8fbd2e0dadbf70b 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1761,6 +1761,9 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
 		if (gadget_is_otg(gadget))
 			c->descriptors = otg_desc;
 
+		/* Properly configure the bmAttributes wakeup bit */
+		check_remote_wakeup_config(gadget, c);
+
 		cfg = container_of(c, struct config_usb_cfg, c);
 		if (!list_empty(&cfg->string_list)) {
 			i = 0;
diff --git a/drivers/usb/gadget/function/f_ecm.c b/drivers/usb/gadget/function/f_ecm.c
index a7ab30e603e20c2b72a54f550838ed6332ef6da7..c6e63ad77a404067644a118b05eb824ea1dad71f 100644
--- a/drivers/usb/gadget/function/f_ecm.c
+++ b/drivers/usb/gadget/function/f_ecm.c
@@ -885,6 +885,26 @@ static struct usb_function_instance *ecm_alloc_inst(void)
 	return &opts->func_inst;
 }
 
+static void ecm_suspend(struct usb_function *f)
+{
+	struct f_ecm *ecm = func_to_ecm(f);
+	struct usb_composite_dev *cdev = ecm->port.func.config->cdev;
+
+	DBG(cdev, "ECM Suspend\n");
+
+	gether_suspend(&ecm->port);
+}
+
+static void ecm_resume(struct usb_function *f)
+{
+	struct f_ecm *ecm = func_to_ecm(f);
+	struct usb_composite_dev *cdev = ecm->port.func.config->cdev;
+
+	DBG(cdev, "ECM Resume\n");
+
+	gether_resume(&ecm->port);
+}
+
 static void ecm_free(struct usb_function *f)
 {
 	struct f_ecm *ecm;
@@ -952,6 +972,8 @@ static struct usb_function *ecm_alloc(struct usb_function_instance *fi)
 	ecm->port.func.setup = ecm_setup;
 	ecm->port.func.disable = ecm_disable;
 	ecm->port.func.free_func = ecm_free;
+	ecm->port.func.suspend = ecm_suspend;
+	ecm->port.func.resume = ecm_resume;
 
 	return &ecm->port.func;
 }
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 56cdfb2e42113eb27b29e2f675a104d84503c737..a13c946e0663c2c41736bc04f0dcfae44895a93b 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -335,8 +335,6 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
 	ssize_t ret;
 	char *data;
 
-	ENTER();
-
 	/* Fast check if setup was canceled */
 	if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED)
 		return -EIDRM;
@@ -512,8 +510,6 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
 	size_t n;
 	int ret;
 
-	ENTER();
-
 	/* Fast check if setup was canceled */
 	if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED)
 		return -EIDRM;
@@ -612,8 +608,6 @@ static int ffs_ep0_open(struct inode *inode, struct file *file)
 {
 	struct ffs_data *ffs = inode->i_private;
 
-	ENTER();
-
 	if (ffs->state == FFS_CLOSING)
 		return -EBUSY;
 
@@ -627,8 +621,6 @@ static int ffs_ep0_release(struct inode *inode, struct file *file)
 {
 	struct ffs_data *ffs = file->private_data;
 
-	ENTER();
-
 	ffs_data_closed(ffs);
 
 	return 0;
@@ -640,8 +632,6 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value)
 	struct usb_gadget *gadget = ffs->gadget;
 	long ret;
 
-	ENTER();
-
 	if (code == FUNCTIONFS_INTERFACE_REVMAP) {
 		struct ffs_function *func = ffs->func;
 		ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV;
@@ -715,7 +705,6 @@ static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
 {
 	struct ffs_io_data *io_data = req->context;
 
-	ENTER();
 	if (req->status)
 		io_data->status = req->status;
 	else
@@ -856,8 +845,6 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
 	struct ffs_io_data *io_data = req->context;
 	struct ffs_data *ffs = io_data->ffs;
 
-	ENTER();
-
 	io_data->status = req->status ? req->status : req->actual;
 	usb_ep_free_request(_ep, req);
 
@@ -1161,8 +1148,6 @@ ffs_epfile_open(struct inode *inode, struct file *file)
 {
 	struct ffs_epfile *epfile = inode->i_private;
 
-	ENTER();
-
 	if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
 		return -ENODEV;
 
@@ -1179,8 +1164,6 @@ static int ffs_aio_cancel(struct kiocb *kiocb)
 	unsigned long flags;
 	int value;
 
-	ENTER();
-
 	spin_lock_irqsave(&epfile->ffs->eps_lock, flags);
 
 	if (io_data && io_data->ep && io_data->req)
@@ -1198,8 +1181,6 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from)
 	struct ffs_io_data io_data, *p = &io_data;
 	ssize_t res;
 
-	ENTER();
-
 	if (!is_sync_kiocb(kiocb)) {
 		p = kzalloc(sizeof(io_data), GFP_KERNEL);
 		if (!p)
@@ -1235,8 +1216,6 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to)
 	struct ffs_io_data io_data, *p = &io_data;
 	ssize_t res;
 
-	ENTER();
-
 	if (!is_sync_kiocb(kiocb)) {
 		p = kzalloc(sizeof(io_data), GFP_KERNEL);
 		if (!p)
@@ -1284,8 +1263,6 @@ ffs_epfile_release(struct inode *inode, struct file *file)
 {
 	struct ffs_epfile *epfile = inode->i_private;
 
-	ENTER();
-
 	__ffs_epfile_read_buffer_free(epfile);
 	ffs_data_closed(epfile->ffs);
 
@@ -1299,8 +1276,6 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
 	struct ffs_ep *ep;
 	int ret;
 
-	ENTER();
-
 	if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
 		return -ENODEV;
 
@@ -1399,8 +1374,6 @@ ffs_sb_make_inode(struct super_block *sb, void *data,
 {
 	struct inode *inode;
 
-	ENTER();
-
 	inode = new_inode(sb);
 
 	if (inode) {
@@ -1432,8 +1405,6 @@ static struct dentry *ffs_sb_create_file(struct super_block *sb,
 	struct dentry	*dentry;
 	struct inode	*inode;
 
-	ENTER();
-
 	dentry = d_alloc_name(sb->s_root, name);
 	if (!dentry)
 		return NULL;
@@ -1468,8 +1439,6 @@ static int ffs_sb_fill(struct super_block *sb, struct fs_context *fc)
 	struct inode	*inode;
 	struct ffs_data	*ffs = data->ffs_data;
 
-	ENTER();
-
 	ffs->sb              = sb;
 	data->ffs_data       = NULL;
 	sb->s_fs_info        = ffs;
@@ -1521,8 +1490,6 @@ static int ffs_fs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 	struct fs_parse_result result;
 	int opt;
 
-	ENTER();
-
 	opt = fs_parse(fc, ffs_fs_fs_parameters, param, &result);
 	if (opt < 0)
 		return opt;
@@ -1572,8 +1539,6 @@ static int ffs_fs_get_tree(struct fs_context *fc)
 	struct ffs_data	*ffs;
 	int ret;
 
-	ENTER();
-
 	if (!fc->source)
 		return invalf(fc, "No source specified");
 
@@ -1640,8 +1605,6 @@ static int ffs_fs_init_fs_context(struct fs_context *fc)
 static void
 ffs_fs_kill_sb(struct super_block *sb)
 {
-	ENTER();
-
 	kill_litter_super(sb);
 	if (sb->s_fs_info)
 		ffs_data_closed(sb->s_fs_info);
@@ -1663,8 +1626,6 @@ static int functionfs_init(void)
 {
 	int ret;
 
-	ENTER();
-
 	ret = register_filesystem(&ffs_fs_type);
 	if (!ret)
 		pr_info("file system registered\n");
@@ -1676,8 +1637,6 @@ static int functionfs_init(void)
 
 static void functionfs_cleanup(void)
 {
-	ENTER();
-
 	pr_info("unloading\n");
 	unregister_filesystem(&ffs_fs_type);
 }
@@ -1690,15 +1649,11 @@ static void ffs_data_reset(struct ffs_data *ffs);
 
 static void ffs_data_get(struct ffs_data *ffs)
 {
-	ENTER();
-
 	refcount_inc(&ffs->ref);
 }
 
 static void ffs_data_opened(struct ffs_data *ffs)
 {
-	ENTER();
-
 	refcount_inc(&ffs->ref);
 	if (atomic_add_return(1, &ffs->opened) == 1 &&
 			ffs->state == FFS_DEACTIVATED) {
@@ -1709,8 +1664,6 @@ static void ffs_data_opened(struct ffs_data *ffs)
 
 static void ffs_data_put(struct ffs_data *ffs)
 {
-	ENTER();
-
 	if (refcount_dec_and_test(&ffs->ref)) {
 		pr_info("%s(): freeing\n", __func__);
 		ffs_data_clear(ffs);
@@ -1729,8 +1682,6 @@ static void ffs_data_closed(struct ffs_data *ffs)
 	struct ffs_epfile *epfiles;
 	unsigned long flags;
 
-	ENTER();
-
 	if (atomic_dec_and_test(&ffs->opened)) {
 		if (ffs->no_disconnect) {
 			ffs->state = FFS_DEACTIVATED;
@@ -1765,8 +1716,6 @@ static struct ffs_data *ffs_data_new(const char *dev_name)
 	if (!ffs)
 		return NULL;
 
-	ENTER();
-
 	ffs->io_completion_wq = alloc_ordered_workqueue("%s", 0, dev_name);
 	if (!ffs->io_completion_wq) {
 		kfree(ffs);
@@ -1793,8 +1742,6 @@ static void ffs_data_clear(struct ffs_data *ffs)
 	struct ffs_epfile *epfiles;
 	unsigned long flags;
 
-	ENTER();
-
 	ffs_closed(ffs);
 
 	BUG_ON(ffs->gadget);
@@ -1826,8 +1773,6 @@ static void ffs_data_clear(struct ffs_data *ffs)
 
 static void ffs_data_reset(struct ffs_data *ffs)
 {
-	ENTER();
-
 	ffs_data_clear(ffs);
 
 	ffs->raw_descs_data = NULL;
@@ -1861,8 +1806,6 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
 	struct usb_gadget_strings **lang;
 	int first_id;
 
-	ENTER();
-
 	if (WARN_ON(ffs->state != FFS_ACTIVE
 		 || test_and_set_bit(FFS_FL_BOUND, &ffs->flags)))
 		return -EBADFD;
@@ -1894,8 +1837,6 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
 
 static void functionfs_unbind(struct ffs_data *ffs)
 {
-	ENTER();
-
 	if (!WARN_ON(!ffs->gadget)) {
 		/* dequeue before freeing ep0req */
 		usb_ep_dequeue(ffs->gadget->ep0, ffs->ep0req);
@@ -1914,8 +1855,6 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
 	struct ffs_epfile *epfile, *epfiles;
 	unsigned i, count;
 
-	ENTER();
-
 	count = ffs->eps_count;
 	epfiles = kcalloc(count, sizeof(*epfiles), GFP_KERNEL);
 	if (!epfiles)
@@ -1946,8 +1885,6 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
 {
 	struct ffs_epfile *epfile = epfiles;
 
-	ENTER();
-
 	for (; count; --count, ++epfile) {
 		BUG_ON(mutex_is_locked(&epfile->mutex));
 		if (epfile->dentry) {
@@ -2064,8 +2001,6 @@ static int __must_check ffs_do_single_desc(char *data, unsigned len,
 	u8 length;
 	int ret;
 
-	ENTER();
-
 	/* At least two bytes are required: length and type */
 	if (len < 2) {
 		pr_vdebug("descriptor too short\n");
@@ -2204,8 +2139,6 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len,
 	unsigned long num = 0;
 	int current_class = -1;
 
-	ENTER();
-
 	for (;;) {
 		int ret;
 
@@ -2243,8 +2176,6 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
 	struct ffs_desc_helper *helper = priv;
 	struct usb_endpoint_descriptor *d;
 
-	ENTER();
-
 	switch (type) {
 	case FFS_DESCRIPTOR:
 		break;
@@ -2292,8 +2223,11 @@ static int __ffs_do_os_desc_header(enum ffs_os_desc_type *next_type,
 	u16 bcd_version = le16_to_cpu(desc->bcdVersion);
 	u16 w_index = le16_to_cpu(desc->wIndex);
 
-	if (bcd_version != 1) {
-		pr_vdebug("unsupported os descriptors version: %d",
+	if (bcd_version == 0x1) {
+		pr_warn("bcdVersion must be 0x0100, stored in Little Endian order. "
+			"Userspace driver should be fixed, accepting 0x0001 for compatibility.\n");
+	} else if (bcd_version != 0x100) {
+		pr_vdebug("unsupported os descriptors version: 0x%x\n",
 			  bcd_version);
 		return -EINVAL;
 	}
@@ -2326,8 +2260,6 @@ static int __must_check ffs_do_single_os_desc(char *data, unsigned len,
 	int ret;
 	const unsigned _len = len;
 
-	ENTER();
-
 	/* loop over all ext compat/ext prop descriptors */
 	while (feature_count--) {
 		ret = entity(type, h, data, len, priv);
@@ -2349,8 +2281,6 @@ static int __must_check ffs_do_os_descs(unsigned count,
 	const unsigned _len = len;
 	unsigned long num = 0;
 
-	ENTER();
-
 	for (num = 0; num < count; ++num) {
 		int ret;
 		enum ffs_os_desc_type type;
@@ -2413,8 +2343,6 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
 	struct ffs_data *ffs = priv;
 	u8 length;
 
-	ENTER();
-
 	switch (type) {
 	case FFS_OS_DESC_EXT_COMPAT: {
 		struct usb_ext_compat_desc *d = data;
@@ -2490,8 +2418,6 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
 	int ret = -EINVAL, i;
 	struct ffs_desc_helper helper;
 
-	ENTER();
-
 	if (get_unaligned_le32(data + 4) != len)
 		goto error;
 
@@ -2622,8 +2548,6 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
 	const char *data = _data;
 	struct usb_string *s;
 
-	ENTER();
-
 	if (len < 16 ||
 	    get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
 	    get_unaligned_le32(data + 4) != len)
@@ -3082,8 +3006,6 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
 	struct ffs_data *ffs_data;
 	int ret;
 
-	ENTER();
-
 	/*
 	 * Legacy gadget triggers binding in functionfs_ready_callback,
 	 * which already uses locking; taking the same lock here would
@@ -3160,8 +3082,6 @@ static int _ffs_func_bind(struct usb_configuration *c,
 	vla_item_with_sz(d, char, raw_descs, ffs->raw_descs_length);
 	char *vlabuf;
 
-	ENTER();
-
 	/* Has descriptors only for speeds gadget does not support */
 	if (!(full | high | super))
 		return -ENOTSUPP;
@@ -3365,8 +3285,6 @@ static int ffs_func_setup(struct usb_function *f,
 	unsigned long flags;
 	int ret;
 
-	ENTER();
-
 	pr_vdebug("creq->bRequestType = %02x\n", creq->bRequestType);
 	pr_vdebug("creq->bRequest     = %02x\n", creq->bRequest);
 	pr_vdebug("creq->wValue       = %04x\n", le16_to_cpu(creq->wValue));
@@ -3441,13 +3359,11 @@ static bool ffs_func_req_match(struct usb_function *f,
 
 static void ffs_func_suspend(struct usb_function *f)
 {
-	ENTER();
 	ffs_event_add(ffs_func_from_usb(f)->ffs, FUNCTIONFS_SUSPEND);
 }
 
 static void ffs_func_resume(struct usb_function *f)
 {
-	ENTER();
 	ffs_event_add(ffs_func_from_usb(f)->ffs, FUNCTIONFS_RESUME);
 }
 
@@ -3611,7 +3527,6 @@ static void ffs_func_unbind(struct usb_configuration *c,
 	unsigned count = ffs->eps_count;
 	unsigned long flags;
 
-	ENTER();
 	if (ffs->func == func) {
 		ffs_func_eps_disable(func);
 		ffs->func = NULL;
@@ -3651,8 +3566,6 @@ static struct usb_function *ffs_alloc(struct usb_function_instance *fi)
 {
 	struct ffs_function *func;
 
-	ENTER();
-
 	func = kzalloc(sizeof(*func), GFP_KERNEL);
 	if (!func)
 		return ERR_PTR(-ENOMEM);
@@ -3753,7 +3666,6 @@ static int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data)
 	int ret = 0;
 	struct ffs_dev *ffs_dev;
 
-	ENTER();
 	ffs_dev_lock();
 
 	ffs_dev = _ffs_find_dev(dev_name);
@@ -3776,7 +3688,6 @@ static int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data)
 
 static void ffs_release_dev(struct ffs_dev *ffs_dev)
 {
-	ENTER();
 	ffs_dev_lock();
 
 	if (ffs_dev && ffs_dev->mounted) {
@@ -3798,7 +3709,6 @@ static int ffs_ready(struct ffs_data *ffs)
 	struct ffs_dev *ffs_obj;
 	int ret = 0;
 
-	ENTER();
 	ffs_dev_lock();
 
 	ffs_obj = ffs->private_data;
@@ -3831,7 +3741,6 @@ static void ffs_closed(struct ffs_data *ffs)
 	struct f_fs_opts *opts;
 	struct config_item *ci;
 
-	ENTER();
 	ffs_dev_lock();
 
 	ffs_obj = ffs->private_data;
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index f259975dfba433ea55f0b4598ba364c671f41dd9..6956ad8ba8dd86e5c1a3fd6e10bc25adc8a734f2 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -437,6 +437,20 @@ static inline int is_promisc(u16 cdc_filter)
 	return cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
 }
 
+static int ether_wakeup_host(struct gether *port)
+{
+	int			ret;
+	struct usb_function	*func = &port->func;
+	struct usb_gadget	*gadget = func->config->cdev->gadget;
+
+	if (func->func_suspended)
+		ret = usb_func_wakeup(func);
+	else
+		ret = usb_gadget_wakeup(gadget);
+
+	return ret;
+}
+
 static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
 					struct net_device *net)
 {
@@ -456,6 +470,15 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
 		in = NULL;
 		cdc_filter = 0;
 	}
+
+	if (dev->port_usb && dev->port_usb->is_suspend) {
+		DBG(dev, "Port suspended. Triggering wakeup\n");
+		netif_stop_queue(net);
+		spin_unlock_irqrestore(&dev->lock, flags);
+		ether_wakeup_host(dev->port_usb);
+		return NETDEV_TX_BUSY;
+	}
+
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 	if (!in) {
@@ -1014,6 +1037,45 @@ int gether_set_ifname(struct net_device *net, const char *name, int len)
 }
 EXPORT_SYMBOL_GPL(gether_set_ifname);
 
+void gether_suspend(struct gether *link)
+{
+	struct eth_dev *dev = link->ioport;
+	unsigned long flags;
+
+	if (!dev)
+		return;
+
+	if (atomic_read(&dev->tx_qlen)) {
+		/*
+		 * There is a transfer in progress. So we trigger a remote
+		 * wakeup to inform the host.
+		 */
+		ether_wakeup_host(dev->port_usb);
+		return;
+	}
+	spin_lock_irqsave(&dev->lock, flags);
+	link->is_suspend = true;
+	spin_unlock_irqrestore(&dev->lock, flags);
+}
+EXPORT_SYMBOL_GPL(gether_suspend);
+
+void gether_resume(struct gether *link)
+{
+	struct eth_dev *dev = link->ioport;
+	unsigned long flags;
+
+	if (!dev)
+		return;
+
+	if (netif_queue_stopped(dev->net))
+		netif_start_queue(dev->net);
+
+	spin_lock_irqsave(&dev->lock, flags);
+	link->is_suspend = false;
+	spin_unlock_irqrestore(&dev->lock, flags);
+}
+EXPORT_SYMBOL_GPL(gether_resume);
+
 /*
  * gether_cleanup - remove Ethernet-over-USB device
  * Context: may sleep
@@ -1176,6 +1238,7 @@ void gether_disconnect(struct gether *link)
 
 	spin_lock(&dev->lock);
 	dev->port_usb = NULL;
+	link->is_suspend = false;
 	spin_unlock(&dev->lock);
 }
 EXPORT_SYMBOL_GPL(gether_disconnect);
diff --git a/drivers/usb/gadget/function/u_ether.h b/drivers/usb/gadget/function/u_ether.h
index 40144546d1b07f4f1787db0753df9213e81bc742..851ee10d6e6383ed3f134c1193028c30501bbf43 100644
--- a/drivers/usb/gadget/function/u_ether.h
+++ b/drivers/usb/gadget/function/u_ether.h
@@ -79,6 +79,7 @@ struct gether {
 	/* called on network open/close */
 	void				(*open)(struct gether *);
 	void				(*close)(struct gether *);
+	bool				is_suspend;
 };
 
 #define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
@@ -258,6 +259,9 @@ int gether_set_ifname(struct net_device *net, const char *name, int len);
 
 void gether_cleanup(struct eth_dev *dev);
 
+void gether_suspend(struct gether *link);
+void gether_resume(struct gether *link);
+
 /* connect/disconnect is handled by individual functions */
 struct net_device *gether_connect(struct gether *);
 void gether_disconnect(struct gether *);
diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h
index f102ec23f3afd246b7dabd475a9cc138e802c6fe..4b3365f23fd7508f0ef363a2374b738ce69f0cac 100644
--- a/drivers/usb/gadget/function/u_fs.h
+++ b/drivers/usb/gadget/function/u_fs.h
@@ -32,8 +32,6 @@
 #  define ffs_dump_mem(prefix, ptr, len) do { } while (0)
 #endif /* VERBOSE_DEBUG */
 
-#define ENTER()    pr_vdebug("%s()\n", __func__)
-
 struct f_fs_opts;
 
 struct ffs_dev {
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 62b759bb7613c0bf2089910886c8612f5994ae36..9bf0e985acfab531dfe70989a7000c1a0fe09caf 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -334,6 +334,64 @@ UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, 8);
 
 #undef UVCG_DEFAULT_PROCESSING_ATTR
 
+static ssize_t uvcg_default_processing_bm_controls_store(
+	struct config_item *item, const char *page, size_t len)
+{
+	struct config_group *group = to_config_group(item);
+	struct mutex *su_mutex = &group->cg_subsys->su_mutex;
+	struct uvc_processing_unit_descriptor *pd;
+	struct config_item *opts_item;
+	struct f_uvc_opts *opts;
+	u8 *bm_controls, *tmp;
+	unsigned int i;
+	int ret, n = 0;
+
+	mutex_lock(su_mutex);
+
+	opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
+	opts = to_f_uvc_opts(opts_item);
+	pd = &opts->uvc_processing;
+
+	mutex_lock(&opts->lock);
+	if (opts->refcnt) {
+		ret = -EBUSY;
+		goto unlock;
+	}
+
+	ret = __uvcg_iter_item_entries(page, len, __uvcg_count_item_entries, &n,
+				       sizeof(u8));
+	if (ret)
+		goto unlock;
+
+	if (n > pd->bControlSize) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	tmp = bm_controls = kcalloc(n, sizeof(u8), GFP_KERNEL);
+	if (!bm_controls) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
+	ret = __uvcg_iter_item_entries(page, len, __uvcg_fill_item_entries, &tmp,
+				       sizeof(u8));
+	if (ret)
+		goto free_mem;
+
+	for (i = 0; i < n; i++)
+		pd->bmControls[i] = bm_controls[i];
+
+	ret = len;
+
+free_mem:
+	kfree(bm_controls);
+unlock:
+	mutex_unlock(&opts->lock);
+	mutex_unlock(su_mutex);
+	return ret;
+}
+
 static ssize_t uvcg_default_processing_bm_controls_show(
 	struct config_item *item, char *page)
 {
@@ -363,7 +421,7 @@ static ssize_t uvcg_default_processing_bm_controls_show(
 	return result;
 }
 
-UVC_ATTR_RO(uvcg_default_processing_, bm_controls, bmControls);
+UVC_ATTR(uvcg_default_processing_, bm_controls, bmControls);
 
 static struct configfs_attribute *uvcg_default_processing_attrs[] = {
 	&uvcg_default_processing_attr_b_unit_id,
@@ -445,6 +503,65 @@ UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength,
 
 #undef UVCG_DEFAULT_CAMERA_ATTR
 
+static ssize_t uvcg_default_camera_bm_controls_store(
+	struct config_item *item, const char *page, size_t len)
+{
+	struct config_group *group = to_config_group(item);
+	struct mutex *su_mutex = &group->cg_subsys->su_mutex;
+	struct uvc_camera_terminal_descriptor *cd;
+	struct config_item *opts_item;
+	struct f_uvc_opts *opts;
+	u8 *bm_controls, *tmp;
+	unsigned int i;
+	int ret, n = 0;
+
+	mutex_lock(su_mutex);
+
+	opts_item = group->cg_item.ci_parent->ci_parent->ci_parent->
+			ci_parent;
+	opts = to_f_uvc_opts(opts_item);
+	cd = &opts->uvc_camera_terminal;
+
+	mutex_lock(&opts->lock);
+	if (opts->refcnt) {
+		ret = -EBUSY;
+		goto unlock;
+	}
+
+	ret = __uvcg_iter_item_entries(page, len, __uvcg_count_item_entries, &n,
+				       sizeof(u8));
+	if (ret)
+		goto unlock;
+
+	if (n > cd->bControlSize) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	tmp = bm_controls = kcalloc(n, sizeof(u8), GFP_KERNEL);
+	if (!bm_controls) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
+	ret = __uvcg_iter_item_entries(page, len, __uvcg_fill_item_entries, &tmp,
+				       sizeof(u8));
+	if (ret)
+		goto free_mem;
+
+	for (i = 0; i < n; i++)
+		cd->bmControls[i] = bm_controls[i];
+
+	ret = len;
+
+free_mem:
+	kfree(bm_controls);
+unlock:
+	mutex_unlock(&opts->lock);
+	mutex_unlock(su_mutex);
+	return ret;
+}
+
 static ssize_t uvcg_default_camera_bm_controls_show(
 	struct config_item *item, char *page)
 {
@@ -474,7 +591,7 @@ static ssize_t uvcg_default_camera_bm_controls_show(
 	return result;
 }
 
-UVC_ATTR_RO(uvcg_default_camera_, bm_controls, bmControls);
+UVC_ATTR(uvcg_default_camera_, bm_controls, bmControls);
 
 static struct configfs_attribute *uvcg_default_camera_attrs[] = {
 	&uvcg_default_camera_attr_b_terminal_id,
diff --git a/drivers/usb/gadget/legacy/g_ffs.c b/drivers/usb/gadget/legacy/g_ffs.c
index ae6d8f7092b8e97a0153bfc7758cca99348397a6..097854683e5b37b1ef88b839a80aa12faadb8057 100644
--- a/drivers/usb/gadget/legacy/g_ffs.c
+++ b/drivers/usb/gadget/legacy/g_ffs.c
@@ -180,8 +180,6 @@ static int __init gfs_init(void)
 	int i;
 	int ret = 0;
 
-	ENTER();
-
 	if (func_num < 2) {
 		gfs_single_func = true;
 		func_num = 1;
@@ -242,8 +240,6 @@ static void __exit gfs_exit(void)
 {
 	int i;
 
-	ENTER();
-
 	if (gfs_registered)
 		usb_composite_unregister(&gfs_driver);
 	gfs_registered = false;
@@ -316,8 +312,6 @@ static int gfs_bind(struct usb_composite_dev *cdev)
 #endif
 	int ret, i;
 
-	ENTER();
-
 	if (missing_funcs)
 		return -ENODEV;
 #if defined CONFIG_USB_FUNCTIONFS_ETH
@@ -445,9 +439,6 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
 {
 	int i;
 
-	ENTER();
-
-
 #ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 	usb_put_function(f_rndis);
 	usb_put_function_instance(fi_rndis);
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/core.c b/drivers/usb/gadget/udc/aspeed-vhub/core.c
index ac3ca24f8b0454dfa2ac547e517cad005a21664e..86398a04a012d5e31a2a6fe7429c1837f4b799ff 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/core.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/core.c
@@ -21,7 +21,6 @@
 #include <linux/clk.h>
 #include <linux/usb/gadget.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
 #include <linux/regmap.h>
 #include <linux/dma-mapping.h>
 
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
index 4f3bc27c1c628da63d0c38658ad471c190720fc5..573109ca5b79902c5b396f98f58c3e87f41cc6bd 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
@@ -21,7 +21,6 @@
 #include <linux/clk.h>
 #include <linux/usb/gadget.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
 #include <linux/regmap.h>
 #include <linux/dma-mapping.h>
 #include <linux/usb.h>
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/ep0.c b/drivers/usb/gadget/udc/aspeed-vhub/ep0.c
index b4cf46249fea35ea3f886fc29bfcf8a2115e736b..e9aa74231760c3ee98b8d4c5b28bc5bcacd1d7e4 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/ep0.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/ep0.c
@@ -21,7 +21,6 @@
 #include <linux/clk.h>
 #include <linux/usb/gadget.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
 #include <linux/regmap.h>
 #include <linux/dma-mapping.h>
 
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/epn.c b/drivers/usb/gadget/udc/aspeed-vhub/epn.c
index 56e55472daa136cc8ea474d6dc5fb25367a888bc..148d7ec3ebf48f94d1cc040a8ac17ec5b80eda7d 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/epn.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/epn.c
@@ -21,7 +21,6 @@
 #include <linux/clk.h>
 #include <linux/usb/gadget.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
 #include <linux/regmap.h>
 #include <linux/dma-mapping.h>
 
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/hub.c b/drivers/usb/gadget/udc/aspeed-vhub/hub.c
index e2207d0146204df5f9f2113bcd885f147de90e87..a63e4af60a56a9a0b00c2828c4de14f31b13e033 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/hub.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/hub.c
@@ -21,7 +21,6 @@
 #include <linux/clk.h>
 #include <linux/usb/gadget.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
 #include <linux/regmap.h>
 #include <linux/dma-mapping.h>
 #include <linux/bcd.h>
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 23b0629a877431325c3f2f35f900388d9494d2cb..1c5403ce9e7c0359db296d7841e0b93cc7c68dfc 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -37,6 +37,10 @@ static struct bus_type gadget_bus_type;
  * @vbus: for udcs who care about vbus status, this value is real vbus status;
  * for udcs who do not care about vbus status, this value is always true
  * @started: the UDC's started state. True if the UDC had started.
+ * @connect_lock: protects udc->vbus, udc->started, gadget->connect, gadget->deactivate related
+ * functions. usb_gadget_connect_locked, usb_gadget_disconnect_locked,
+ * usb_udc_connect_control_locked, usb_gadget_udc_start_locked, usb_gadget_udc_stop_locked are
+ * called with this lock held.
  *
  * This represents the internal data structure which is used by the UDC-class
  * to hold information about udc driver and gadget together.
@@ -48,6 +52,7 @@ struct usb_udc {
 	struct list_head		list;
 	bool				vbus;
 	bool				started;
+	struct mutex			connect_lock;
 };
 
 static struct class *udc_class;
@@ -513,6 +518,33 @@ int usb_gadget_wakeup(struct usb_gadget *gadget)
 }
 EXPORT_SYMBOL_GPL(usb_gadget_wakeup);
 
+/**
+ * usb_gadget_set_remote_wakeup - configures the device remote wakeup feature.
+ * @gadget:the device being configured for remote wakeup
+ * @set:value to be configured.
+ *
+ * set to one to enable remote wakeup feature and zero to disable it.
+ *
+ * returns zero on success, else negative errno.
+ */
+int usb_gadget_set_remote_wakeup(struct usb_gadget *gadget, int set)
+{
+	int ret = 0;
+
+	if (!gadget->ops->set_remote_wakeup) {
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	ret = gadget->ops->set_remote_wakeup(gadget, set);
+
+out:
+	trace_usb_gadget_set_remote_wakeup(gadget, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_set_remote_wakeup);
+
 /**
  * usb_gadget_set_selfpowered - sets the device selfpowered feature.
  * @gadget:the device being declared as self-powered
@@ -660,17 +692,9 @@ int usb_gadget_vbus_disconnect(struct usb_gadget *gadget)
 }
 EXPORT_SYMBOL_GPL(usb_gadget_vbus_disconnect);
 
-/**
- * usb_gadget_connect - software-controlled connect to USB host
- * @gadget:the peripheral being connected
- *
- * Enables the D+ (or potentially D-) pullup.  The host will start
- * enumerating this gadget when the pullup is active and a VBUS session
- * is active (the link is powered).
- *
- * Returns zero on success, else negative errno.
- */
-int usb_gadget_connect(struct usb_gadget *gadget)
+/* Internal version of usb_gadget_connect needs to be called with connect_lock held. */
+static int usb_gadget_connect_locked(struct usb_gadget *gadget)
+	__must_hold(&gadget->udc->connect_lock)
 {
 	int ret = 0;
 
@@ -679,10 +703,15 @@ int usb_gadget_connect(struct usb_gadget *gadget)
 		goto out;
 	}
 
-	if (gadget->deactivated) {
+	if (gadget->connected)
+		goto out;
+
+	if (gadget->deactivated || !gadget->udc->started) {
 		/*
 		 * If gadget is deactivated we only save new state.
 		 * Gadget will be connected automatically after activation.
+		 *
+		 * udc first needs to be started before gadget can be pulled up.
 		 */
 		gadget->connected = true;
 		goto out;
@@ -697,22 +726,32 @@ int usb_gadget_connect(struct usb_gadget *gadget)
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(usb_gadget_connect);
 
 /**
- * usb_gadget_disconnect - software-controlled disconnect from USB host
- * @gadget:the peripheral being disconnected
- *
- * Disables the D+ (or potentially D-) pullup, which the host may see
- * as a disconnect (when a VBUS session is active).  Not all systems
- * support software pullup controls.
+ * usb_gadget_connect - software-controlled connect to USB host
+ * @gadget:the peripheral being connected
  *
- * Following a successful disconnect, invoke the ->disconnect() callback
- * for the current gadget driver so that UDC drivers don't need to.
+ * Enables the D+ (or potentially D-) pullup.  The host will start
+ * enumerating this gadget when the pullup is active and a VBUS session
+ * is active (the link is powered).
  *
  * Returns zero on success, else negative errno.
  */
-int usb_gadget_disconnect(struct usb_gadget *gadget)
+int usb_gadget_connect(struct usb_gadget *gadget)
+{
+	int ret;
+
+	mutex_lock(&gadget->udc->connect_lock);
+	ret = usb_gadget_connect_locked(gadget);
+	mutex_unlock(&gadget->udc->connect_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_connect);
+
+/* Internal version of usb_gadget_disconnect needs to be called with connect_lock held. */
+static int usb_gadget_disconnect_locked(struct usb_gadget *gadget)
+	__must_hold(&gadget->udc->connect_lock)
 {
 	int ret = 0;
 
@@ -724,10 +763,12 @@ int usb_gadget_disconnect(struct usb_gadget *gadget)
 	if (!gadget->connected)
 		goto out;
 
-	if (gadget->deactivated) {
+	if (gadget->deactivated || !gadget->udc->started) {
 		/*
 		 * If gadget is deactivated we only save new state.
 		 * Gadget will stay disconnected after activation.
+		 *
+		 * udc should have been started before gadget being pulled down.
 		 */
 		gadget->connected = false;
 		goto out;
@@ -747,6 +788,30 @@ int usb_gadget_disconnect(struct usb_gadget *gadget)
 
 	return ret;
 }
+
+/**
+ * usb_gadget_disconnect - software-controlled disconnect from USB host
+ * @gadget:the peripheral being disconnected
+ *
+ * Disables the D+ (or potentially D-) pullup, which the host may see
+ * as a disconnect (when a VBUS session is active).  Not all systems
+ * support software pullup controls.
+ *
+ * Following a successful disconnect, invoke the ->disconnect() callback
+ * for the current gadget driver so that UDC drivers don't need to.
+ *
+ * Returns zero on success, else negative errno.
+ */
+int usb_gadget_disconnect(struct usb_gadget *gadget)
+{
+	int ret;
+
+	mutex_lock(&gadget->udc->connect_lock);
+	ret = usb_gadget_disconnect_locked(gadget);
+	mutex_unlock(&gadget->udc->connect_lock);
+
+	return ret;
+}
 EXPORT_SYMBOL_GPL(usb_gadget_disconnect);
 
 /**
@@ -767,10 +832,11 @@ int usb_gadget_deactivate(struct usb_gadget *gadget)
 	if (gadget->deactivated)
 		goto out;
 
+	mutex_lock(&gadget->udc->connect_lock);
 	if (gadget->connected) {
-		ret = usb_gadget_disconnect(gadget);
+		ret = usb_gadget_disconnect_locked(gadget);
 		if (ret)
-			goto out;
+			goto unlock;
 
 		/*
 		 * If gadget was being connected before deactivation, we want
@@ -780,6 +846,8 @@ int usb_gadget_deactivate(struct usb_gadget *gadget)
 	}
 	gadget->deactivated = true;
 
+unlock:
+	mutex_unlock(&gadget->udc->connect_lock);
 out:
 	trace_usb_gadget_deactivate(gadget, ret);
 
@@ -803,6 +871,7 @@ int usb_gadget_activate(struct usb_gadget *gadget)
 	if (!gadget->deactivated)
 		goto out;
 
+	mutex_lock(&gadget->udc->connect_lock);
 	gadget->deactivated = false;
 
 	/*
@@ -810,7 +879,8 @@ int usb_gadget_activate(struct usb_gadget *gadget)
 	 * while it was being deactivated, we call usb_gadget_connect().
 	 */
 	if (gadget->connected)
-		ret = usb_gadget_connect(gadget);
+		ret = usb_gadget_connect_locked(gadget);
+	mutex_unlock(&gadget->udc->connect_lock);
 
 out:
 	trace_usb_gadget_activate(gadget, ret);
@@ -1051,12 +1121,13 @@ EXPORT_SYMBOL_GPL(usb_gadget_set_state);
 
 /* ------------------------------------------------------------------------- */
 
-static void usb_udc_connect_control(struct usb_udc *udc)
+/* Acquire connect_lock before calling this function. */
+static void usb_udc_connect_control_locked(struct usb_udc *udc) __must_hold(&udc->connect_lock)
 {
-	if (udc->vbus)
-		usb_gadget_connect(udc->gadget);
+	if (udc->vbus && udc->started)
+		usb_gadget_connect_locked(udc->gadget);
 	else
-		usb_gadget_disconnect(udc->gadget);
+		usb_gadget_disconnect_locked(udc->gadget);
 }
 
 /**
@@ -1072,10 +1143,12 @@ void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status)
 {
 	struct usb_udc *udc = gadget->udc;
 
+	mutex_lock(&udc->connect_lock);
 	if (udc) {
 		udc->vbus = status;
-		usb_udc_connect_control(udc);
+		usb_udc_connect_control_locked(udc);
 	}
+	mutex_unlock(&udc->connect_lock);
 }
 EXPORT_SYMBOL_GPL(usb_udc_vbus_handler);
 
@@ -1097,7 +1170,7 @@ void usb_gadget_udc_reset(struct usb_gadget *gadget,
 EXPORT_SYMBOL_GPL(usb_gadget_udc_reset);
 
 /**
- * usb_gadget_udc_start - tells usb device controller to start up
+ * usb_gadget_udc_start_locked - tells usb device controller to start up
  * @udc: The UDC to be started
  *
  * This call is issued by the UDC Class driver when it's about
@@ -1108,8 +1181,11 @@ EXPORT_SYMBOL_GPL(usb_gadget_udc_reset);
  * necessary to have it powered on.
  *
  * Returns zero on success, else negative errno.
+ *
+ * Caller should acquire connect_lock before invoking this function.
  */
-static inline int usb_gadget_udc_start(struct usb_udc *udc)
+static inline int usb_gadget_udc_start_locked(struct usb_udc *udc)
+	__must_hold(&udc->connect_lock)
 {
 	int ret;
 
@@ -1126,7 +1202,7 @@ static inline int usb_gadget_udc_start(struct usb_udc *udc)
 }
 
 /**
- * usb_gadget_udc_stop - tells usb device controller we don't need it anymore
+ * usb_gadget_udc_stop_locked - tells usb device controller we don't need it anymore
  * @udc: The UDC to be stopped
  *
  * This call is issued by the UDC Class driver after calling
@@ -1135,8 +1211,11 @@ static inline int usb_gadget_udc_start(struct usb_udc *udc)
  * The details are implementation specific, but it can go as
  * far as powering off UDC completely and disable its data
  * line pullups.
+ *
+ * Caller should acquire connect lock before invoking this function.
  */
-static inline void usb_gadget_udc_stop(struct usb_udc *udc)
+static inline void usb_gadget_udc_stop_locked(struct usb_udc *udc)
+	__must_hold(&udc->connect_lock)
 {
 	if (!udc->started) {
 		dev_err(&udc->dev, "UDC had already stopped\n");
@@ -1295,6 +1374,7 @@ int usb_add_gadget(struct usb_gadget *gadget)
 
 	udc->gadget = gadget;
 	gadget->udc = udc;
+	mutex_init(&udc->connect_lock);
 
 	udc->started = false;
 
@@ -1496,11 +1576,15 @@ static int gadget_bind_driver(struct device *dev)
 	if (ret)
 		goto err_bind;
 
-	ret = usb_gadget_udc_start(udc);
-	if (ret)
+	mutex_lock(&udc->connect_lock);
+	ret = usb_gadget_udc_start_locked(udc);
+	if (ret) {
+		mutex_unlock(&udc->connect_lock);
 		goto err_start;
+	}
 	usb_gadget_enable_async_callbacks(udc);
-	usb_udc_connect_control(udc);
+	usb_udc_connect_control_locked(udc);
+	mutex_unlock(&udc->connect_lock);
 
 	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
 	return 0;
@@ -1531,12 +1615,14 @@ static void gadget_unbind_driver(struct device *dev)
 
 	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
 
-	usb_gadget_disconnect(gadget);
+	mutex_lock(&udc->connect_lock);
+	usb_gadget_disconnect_locked(gadget);
 	usb_gadget_disable_async_callbacks(udc);
 	if (gadget->irq)
 		synchronize_irq(gadget->irq);
 	udc->driver->unbind(gadget);
-	usb_gadget_udc_stop(udc);
+	usb_gadget_udc_stop_locked(udc);
+	mutex_unlock(&udc->connect_lock);
 
 	mutex_lock(&udc_lock);
 	driver->is_bound = false;
@@ -1622,11 +1708,15 @@ static ssize_t soft_connect_store(struct device *dev,
 	}
 
 	if (sysfs_streq(buf, "connect")) {
-		usb_gadget_udc_start(udc);
-		usb_gadget_connect(udc->gadget);
+		mutex_lock(&udc->connect_lock);
+		usb_gadget_udc_start_locked(udc);
+		usb_gadget_connect_locked(udc->gadget);
+		mutex_unlock(&udc->connect_lock);
 	} else if (sysfs_streq(buf, "disconnect")) {
-		usb_gadget_disconnect(udc->gadget);
-		usb_gadget_udc_stop(udc);
+		mutex_lock(&udc->connect_lock);
+		usb_gadget_disconnect_locked(udc->gadget);
+		usb_gadget_udc_stop_locked(udc);
+		mutex_unlock(&udc->connect_lock);
 	} else {
 		dev_err(dev, "unsupported command '%s'\n", buf);
 		ret = -EINVAL;
diff --git a/drivers/usb/gadget/udc/max3420_udc.c b/drivers/usb/gadget/udc/max3420_udc.c
index ddf0ed3eb4f2616fe6c4a5cbe235a66a50210ea7..12c519f32bf7f77eb48b7dd6bb00f2dc44418461 100644
--- a/drivers/usb/gadget/udc/max3420_udc.c
+++ b/drivers/usb/gadget/udc/max3420_udc.c
@@ -1319,7 +1319,7 @@ MODULE_DEVICE_TABLE(of, max3420_udc_of_match);
 static struct spi_driver max3420_driver = {
 	.driver = {
 		.name = "max3420-udc",
-		.of_match_table = of_match_ptr(max3420_udc_of_match),
+		.of_match_table = max3420_udc_of_match,
 	},
 	.probe = max3420_probe,
 	.remove = max3420_remove,
diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c
index b397f3a848cf7ac082dc4296b692bb4df81bd098..08474c08d8747065c782f8497333d50539516b29 100644
--- a/drivers/usb/gadget/udc/mv_udc_core.c
+++ b/drivers/usb/gadget/udc/mv_udc_core.c
@@ -2229,7 +2229,11 @@ static int mv_udc_probe(struct platform_device *pdev)
 	INIT_LIST_HEAD(&udc->status_req->queue);
 
 	/* allocate a small amount of memory to get valid address */
-	udc->status_req->req.buf = kzalloc(8, GFP_KERNEL);
+	udc->status_req->req.buf = devm_kzalloc(&pdev->dev, 8, GFP_KERNEL);
+	if (!udc->status_req->req.buf) {
+		retval = -ENOMEM;
+		goto err_destroy_dma;
+	}
 	udc->status_req->req.dma = DMA_ADDR_INVALID;
 
 	udc->resume_state = USB_STATE_NOTATTACHED;
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
index bee6bceafc4fa5b727521921b8d666acf00ad664..aac8bc185afa906eb0fa9891a59675478ec9b2e9 100644
--- a/drivers/usb/gadget/udc/renesas_usb3.c
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
@@ -22,7 +22,6 @@
 #include <linux/sizes.h>
 #include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/sys_soc.h>
 #include <linux/uaccess.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
@@ -2661,6 +2660,7 @@ static int renesas_usb3_remove(struct platform_device *pdev)
 	debugfs_remove_recursive(usb3->dentry);
 	device_remove_file(&pdev->dev, &dev_attr_role);
 
+	cancel_work_sync(&usb3->role_work);
 	usb_role_switch_unregister(usb3->role_sw);
 
 	usb_del_gadget_udc(&usb3->gadget);
@@ -2781,13 +2781,6 @@ static void renesas_usb3_init_ram(struct renesas_usb3 *usb3, struct device *dev,
 	}
 }
 
-static const struct renesas_usb3_priv renesas_usb3_priv_r8a7795_es1 = {
-	.ramsize_per_ramif = SZ_16K,
-	.num_ramif = 2,
-	.ramsize_per_pipe = SZ_4K,
-	.workaround_for_vbus = true,
-};
-
 static const struct renesas_usb3_priv renesas_usb3_priv_gen3 = {
 	.ramsize_per_ramif = SZ_16K,
 	.num_ramif = 4,
@@ -2829,14 +2822,6 @@ static const struct of_device_id usb3_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, usb3_of_match);
 
-static const struct soc_device_attribute renesas_usb3_quirks_match[] = {
-	{
-		.soc_id = "r8a7795", .revision = "ES1.*",
-		.data = &renesas_usb3_priv_r8a7795_es1,
-	},
-	{ /* sentinel */ }
-};
-
 static const unsigned int renesas_usb3_cable[] = {
 	EXTCON_USB,
 	EXTCON_USB_HOST,
@@ -2854,13 +2839,8 @@ static int renesas_usb3_probe(struct platform_device *pdev)
 	struct renesas_usb3 *usb3;
 	int irq, ret;
 	const struct renesas_usb3_priv *priv;
-	const struct soc_device_attribute *attr;
 
-	attr = soc_device_match(renesas_usb3_quirks_match);
-	if (attr)
-		priv = attr->data;
-	else
-		priv = of_device_get_match_data(&pdev->dev);
+	priv = of_device_get_match_data(&pdev->dev);
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
@@ -3039,7 +3019,7 @@ static struct platform_driver renesas_usb3_driver = {
 	.driver		= {
 		.name =	udc_name,
 		.pm		= &renesas_usb3_pm_ops,
-		.of_match_table = of_match_ptr(usb3_of_match),
+		.of_match_table = usb3_of_match,
 	},
 };
 module_platform_driver(renesas_usb3_driver);
diff --git a/drivers/usb/gadget/udc/renesas_usbf.c b/drivers/usb/gadget/udc/renesas_usbf.c
index cb23e62e8a8765e0fe382ad714687bd5be462af2..84ac9fe4ce7f138c8bf54275df9ceeb1c7aa90d3 100644
--- a/drivers/usb/gadget/udc/renesas_usbf.c
+++ b/drivers/usb/gadget/udc/renesas_usbf.c
@@ -545,17 +545,6 @@ static inline void usbf_ep_dma_reg_bitclr(struct usbf_ep *ep, uint offset,
 	usbf_ep_dma_reg_writel(ep, offset, tmp);
 }
 
-static inline void usbf_ep_dma_reg_clrset(struct usbf_ep *ep, uint offset,
-					  u32 clr, u32 set)
-{
-	u32 tmp;
-
-	tmp = usbf_ep_dma_reg_readl(ep, offset);
-	tmp &= ~clr;
-	tmp |= set;
-	usbf_ep_dma_reg_writel(ep, offset, tmp);
-}
-
 static void usbf_ep0_send_null(struct usbf_ep *ep0, bool is_data1)
 {
 	u32 set;
diff --git a/drivers/usb/gadget/udc/rzv2m_usb3drd.c b/drivers/usb/gadget/udc/rzv2m_usb3drd.c
index 3c8bbf84303804b49c4f3b449974aef8a984a80d..589c7252e0147f1c26335ab271bde08ae0b49212 100644
--- a/drivers/usb/gadget/udc/rzv2m_usb3drd.c
+++ b/drivers/usb/gadget/udc/rzv2m_usb3drd.c
@@ -6,7 +6,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/of_device.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/reset.h>
@@ -126,7 +126,7 @@ MODULE_DEVICE_TABLE(of, rzv2m_usb3drd_of_match);
 static struct platform_driver rzv2m_usb3drd_driver = {
 	.driver = {
 		.name = "rzv2m-usb3drd",
-		.of_match_table = of_match_ptr(rzv2m_usb3drd_of_match),
+		.of_match_table = rzv2m_usb3drd_of_match,
 	},
 	.probe = rzv2m_usb3drd_probe,
 	.remove = rzv2m_usb3drd_remove,
diff --git a/drivers/usb/gadget/udc/snps_udc_plat.c b/drivers/usb/gadget/udc/snps_udc_plat.c
index 8bbb89c8034876c98a09b6b35c299c7b07f0dbd3..0d3e705655b978983c44431ae047b50f9ca47ade 100644
--- a/drivers/usb/gadget/udc/snps_udc_plat.c
+++ b/drivers/usb/gadget/udc/snps_udc_plat.c
@@ -158,7 +158,7 @@ static int udc_plat_probe(struct platform_device *pdev)
 	}
 
 	/* Register for extcon if supported */
-	if (of_get_property(dev->of_node, "extcon", NULL)) {
+	if (of_property_present(dev->of_node, "extcon")) {
 		udc->edev = extcon_get_edev_by_phandle(dev, 0);
 		if (IS_ERR(udc->edev)) {
 			if (PTR_ERR(udc->edev) == -EPROBE_DEFER)
diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c
index 2b71b33725f1703a8180a5a7a7bf3c0587a4c18f..34e9c1df54c79499ac86452c210ab3b096d6b085 100644
--- a/drivers/usb/gadget/udc/tegra-xudc.c
+++ b/drivers/usb/gadget/udc/tegra-xudc.c
@@ -2162,15 +2162,14 @@ static int tegra_xudc_gadget_stop(struct usb_gadget *gadget)
 static int tegra_xudc_gadget_vbus_draw(struct usb_gadget *gadget,
 						unsigned int m_a)
 {
-	int ret = 0;
 	struct tegra_xudc *xudc = to_xudc(gadget);
 
 	dev_dbg(xudc->dev, "%s: %u mA\n", __func__, m_a);
 
-	if (xudc->curr_usbphy->chg_type == SDP_TYPE)
-		ret = usb_phy_set_power(xudc->curr_usbphy, m_a);
+	if (xudc->curr_usbphy && xudc->curr_usbphy->chg_type == SDP_TYPE)
+		return usb_phy_set_power(xudc->curr_usbphy, m_a);
 
-	return ret;
+	return 0;
 }
 
 static int tegra_xudc_set_selfpowered(struct usb_gadget *gadget, int is_on)
diff --git a/drivers/usb/gadget/udc/trace.h b/drivers/usb/gadget/udc/trace.h
index abdbcb1bacb0bb01625e47e5ddc91b758b06f57b..a5ed26fbc2dad698c896e817fb8266bbaa6d29a9 100644
--- a/drivers/usb/gadget/udc/trace.h
+++ b/drivers/usb/gadget/udc/trace.h
@@ -91,6 +91,11 @@ DEFINE_EVENT(udc_log_gadget, usb_gadget_wakeup,
 	TP_ARGS(g, ret)
 );
 
+DEFINE_EVENT(udc_log_gadget, usb_gadget_set_remote_wakeup,
+	TP_PROTO(struct usb_gadget *g, int ret),
+	TP_ARGS(g, ret)
+);
+
 DEFINE_EVENT(udc_log_gadget, usb_gadget_set_selfpowered,
 	TP_PROTO(struct usb_gadget *g, int ret),
 	TP_ARGS(g, ret)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index eacb603ad1b2144747d38e7cc8b312df02f94c17..c170672f847ec8256397f5dd5e62682d8875ca07 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -622,33 +622,6 @@ config FHCI_DEBUG
 	  Say "y" to see some FHCI debug information and statistics
 	  through debugfs.
 
-config USB_U132_HCD
-	tristate "Elan U132 Adapter Host Controller"
-	depends on USB_FTDI_ELAN
-	help
-	  The U132 adapter is a USB to CardBus adapter specifically designed
-	  for PC cards that contain an OHCI host controller. Typical PC cards
-	  are the Orange Mobile 3G Option GlobeTrotter Fusion card. The U132
-	  adapter will *NOT* work with PC cards that do not contain an OHCI
-	  controller.
-
-	  For those PC cards that contain multiple OHCI controllers only the
-	  first one is used.
-
-	  The driver consists of two modules, the "ftdi-elan" module is a
-	  USB client driver that interfaces to the FTDI chip within ELAN's
-	  USB-to-PCMCIA adapter, and this "u132-hcd" module is a USB host
-	  controller driver that talks to the OHCI controller within the
-	  CardBus cards that are inserted in the U132 adapter.
-
-	  This driver has been tested with a CardBus OHCI USB adapter, and
-	  worked with a USB PEN Drive inserted into the first USB port of
-	  the PCCARD. A rather pointless thing to do, but useful for testing.
-
-	  It is safe to say M here.
-
-	  See also <http://www.elandigitalsystems.com/support/ufaq/u132linux.php>
-
 config USB_SL811_HCD
 	tristate "SL811HS HCD support"
 	depends on HAS_IOMEM
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 5a13712f367da4146f711172b0833bd29e4ffc68..be4e5245c52fe903dd612447f111c24aeb818ad2 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -76,7 +76,6 @@ obj-$(CONFIG_USB_XHCI_MTK)	+= xhci-mtk-hcd.o
 obj-$(CONFIG_USB_XHCI_TEGRA)	+= xhci-tegra.o
 obj-$(CONFIG_USB_SL811_HCD)	+= sl811-hcd.o
 obj-$(CONFIG_USB_SL811_CS)	+= sl811_cs.o
-obj-$(CONFIG_USB_U132_HCD)	+= u132-hcd.o
 obj-$(CONFIG_USB_R8A66597_HCD)	+= r8a66597-hcd.o
 obj-$(CONFIG_USB_FSL_USB2)	+= fsl-mph-dr-of.o
 obj-$(CONFIG_USB_EHCI_FSL)	+= fsl-mph-dr-of.o
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
index 62a0a193798c2daf69b0c5921506d776b080caba..b3aa464e9d2c997ef9749664d93b37d022f42292 100644
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -151,13 +151,13 @@ static int ehci_hcd_ppc_of_probe(struct platform_device *op)
 		of_node_put(np);
 	}
 
-	if (of_get_property(dn, "big-endian", NULL)) {
+	if (of_property_read_bool(dn, "big-endian")) {
 		ehci->big_endian_mmio = 1;
 		ehci->big_endian_desc = 1;
 	}
-	if (of_get_property(dn, "big-endian-regs", NULL))
+	if (of_property_read_bool(dn, "big-endian-regs"))
 		ehci->big_endian_mmio = 1;
-	if (of_get_property(dn, "big-endian-desc", NULL))
+	if (of_property_read_bool(dn, "big-endian-desc"))
 		ehci->big_endian_desc = 1;
 
 	ehci->caps = hcd->regs;
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 46c6a152b86554161886c0130dab12f7749a1406..9db909d12354b074152dd49901b5d78caae92f4a 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -200,19 +200,16 @@ static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
 	dev_data = get_dr_mode_data(np);
 
 	if (of_device_is_compatible(np, "fsl-usb2-mph")) {
-		if (of_get_property(np, "port0", NULL))
+		if (of_property_present(np, "port0"))
 			pdata->port_enables |= FSL_USB2_PORT0_ENABLED;
 
-		if (of_get_property(np, "port1", NULL))
+		if (of_property_present(np, "port1"))
 			pdata->port_enables |= FSL_USB2_PORT1_ENABLED;
 
 		pdata->operating_mode = FSL_USB2_MPH_HOST;
 	} else {
-		if (of_get_property(np, "fsl,invert-drvvbus", NULL))
-			pdata->invert_drvvbus = 1;
-
-		if (of_get_property(np, "fsl,invert-pwr-fault", NULL))
-			pdata->invert_pwr_fault = 1;
+		pdata->invert_drvvbus = of_property_read_bool(np, "fsl,invert-drvvbus");
+		pdata->invert_pwr_fault = of_property_read_bool(np, "fsl,invert-pwr-fault");
 
 		/* setup mode selected in the device tree */
 		pdata->operating_mode = dev_data->op_mode;
diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c
index 28d1524ee2fa93c7ffe38eec88da12aa63b4109d..d152d72de1269e09d22c0d0bc98bd4e9eb0c1e60 100644
--- a/drivers/usb/host/max3421-hcd.c
+++ b/drivers/usb/host/max3421-hcd.c
@@ -1951,7 +1951,7 @@ static struct spi_driver max3421_driver = {
 	.remove		= max3421_remove,
 	.driver		= {
 		.name	= "max3421-hcd",
-		.of_match_table = of_match_ptr(max3421_of_match_table),
+		.of_match_table = max3421_of_match_table,
 	},
 };
 
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index 3a441310c713280b7158af165adf9de765007216..f998d3f1a78a1826db79c29b3bfbd08f1eab1c3d 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -169,7 +169,7 @@ struct ehci_regs {
 #define FLAG_CF		(1<<0)		/* true: we'll support "high speed" */
 
 	/* PORTSC: offset 0x44 */
-	u32		port_status[0];	/* up to N_PORTS */
+	u32		port_status[];	/* up to N_PORTS */
 /* 31:23 reserved */
 #define PORT_WKOC_E	(1<<22)		/* wake on overcurrent (enable) */
 #define PORT_WKDISC_E	(1<<21)		/* wake on disconnect (enable) */
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index ef08d68b9714924513a3e5b47d467f4793e18f73..2665832f9addff97c4ec520cb7f7bb66de82dac0 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -207,8 +207,7 @@ EXPORT_SYMBOL_GPL(sb800_prefetch);
 static void usb_amd_find_chipset_info(void)
 {
 	unsigned long flags;
-	struct amd_chipset_info info;
-	info.need_pll_quirk = false;
+	struct amd_chipset_info info = { };
 
 	spin_lock_irqsave(&amd_lock, flags);
 
@@ -218,7 +217,6 @@ static void usb_amd_find_chipset_info(void)
 		spin_unlock_irqrestore(&amd_lock, flags);
 		return;
 	}
-	memset(&info, 0, sizeof(info));
 	spin_unlock_irqrestore(&amd_lock, flags);
 
 	if (!amd_chipset_sb_type_init(&info)) {
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
deleted file mode 100644
index 95240c9c45bdbb2772cf12df6ff51d2102e554ff..0000000000000000000000000000000000000000
--- a/drivers/usb/host/u132-hcd.c
+++ /dev/null
@@ -1,3219 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
-* Host Controller Driver for the Elan Digital Systems U132 adapter
-*
-* Copyright(C) 2006 Elan Digital Systems Limited
-* http://www.elandigitalsystems.com
-*
-* Author and Maintainer - Tony Olech - Elan Digital Systems
-* tony.olech@elandigitalsystems.com
-*
-* This driver was written by Tony Olech(tony.olech@elandigitalsystems.com)
-* based on various USB host drivers in the 2.6.15 linux kernel
-* with constant reference to the 3rd Edition of Linux Device Drivers
-* published by O'Reilly
-*
-* The U132 adapter is a USB to CardBus adapter specifically designed
-* for PC cards that contain an OHCI host controller. Typical PC cards
-* are the Orange Mobile 3G Option GlobeTrotter Fusion card.
-*
-* The U132 adapter will *NOT *work with PC cards that do not contain
-* an OHCI controller. A simple way to test whether a PC card has an
-* OHCI controller as an interface is to insert the PC card directly
-* into a laptop(or desktop) with a CardBus slot and if "lspci" shows
-* a new USB controller and "lsusb -v" shows a new OHCI Host Controller
-* then there is a good chance that the U132 adapter will support the
-* PC card.(you also need the specific client driver for the PC card)
-*
-* Please inform the Author and Maintainer about any PC cards that
-* contain OHCI Host Controller and work when directly connected to
-* an embedded CardBus slot but do not work when they are connected
-* via an ELAN U132 adapter.
-*
-*/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/pci_ids.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/usb.h>
-#include <linux/usb/hcd.h>
-#include <linux/workqueue.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/byteorder.h>
-
-	/* FIXME ohci.h is ONLY for internal use by the OHCI driver.
-	 * If you're going to try stuff like this, you need to split
-	 * out shareable stuff (register declarations?) into its own
-	 * file, maybe name <linux/usb/ohci.h>
-	 */
-
-#include "ohci.h"
-#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
-#define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
-	OHCI_INTR_WDH)
-MODULE_AUTHOR("Tony Olech - Elan Digital Systems Limited");
-MODULE_DESCRIPTION("U132 USB Host Controller Driver");
-MODULE_LICENSE("GPL");
-#define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
-INT_MODULE_PARM(testing, 0);
-/* Some boards misreport power switching/overcurrent*/
-static bool distrust_firmware = true;
-module_param(distrust_firmware, bool, 0);
-MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurrent"
-	"t setup");
-static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
-/*
-* u132_module_lock exists to protect access to global variables
-*
-*/
-static DEFINE_MUTEX(u132_module_lock);
-static int u132_exiting;
-static int u132_instances;
-/*
-* end of the global variables protected by u132_module_lock
-*/
-static struct workqueue_struct *workqueue;
-#define MAX_U132_PORTS 7
-#define MAX_U132_ADDRS 128
-#define MAX_U132_UDEVS 4
-#define MAX_U132_ENDPS 100
-#define MAX_U132_RINGS 4
-static const char *cc_to_text[16] = {
-	"No Error ",
-	"CRC Error ",
-	"Bit Stuff ",
-	"Data Togg ",
-	"Stall ",
-	"DevNotResp ",
-	"PIDCheck ",
-	"UnExpPID ",
-	"DataOver ",
-	"DataUnder ",
-	"(for hw) ",
-	"(for hw) ",
-	"BufferOver ",
-	"BuffUnder ",
-	"(for HCD) ",
-	"(for HCD) "
-};
-struct u132_port {
-	struct u132 *u132;
-	int reset;
-	int enable;
-	int power;
-	int Status;
-};
-struct u132_addr {
-	u8 address;
-};
-struct u132_udev {
-	struct kref kref;
-	struct usb_device *usb_device;
-	u8 enumeration;
-	u8 udev_number;
-	u8 usb_addr;
-	u8 portnumber;
-	u8 endp_number_in[16];
-	u8 endp_number_out[16];
-};
-#define ENDP_QUEUE_SHIFT 3
-#define ENDP_QUEUE_SIZE (1<<ENDP_QUEUE_SHIFT)
-#define ENDP_QUEUE_MASK (ENDP_QUEUE_SIZE-1)
-struct u132_urbq {
-	struct list_head urb_more;
-	struct urb *urb;
-};
-struct u132_spin {
-	spinlock_t slock;
-};
-struct u132_endp {
-	struct kref kref;
-	u8 udev_number;
-	u8 endp_number;
-	u8 usb_addr;
-	u8 usb_endp;
-	struct u132 *u132;
-	struct list_head endp_ring;
-	struct u132_ring *ring;
-	unsigned toggle_bits:2;
-	unsigned active:1;
-	unsigned delayed:1;
-	unsigned input:1;
-	unsigned output:1;
-	unsigned pipetype:2;
-	unsigned dequeueing:1;
-	unsigned edset_flush:1;
-	unsigned spare_bits:14;
-	unsigned long jiffies;
-	struct usb_host_endpoint *hep;
-	struct u132_spin queue_lock;
-	u16 queue_size;
-	u16 queue_last;
-	u16 queue_next;
-	struct urb *urb_list[ENDP_QUEUE_SIZE];
-	struct list_head urb_more;
-	struct delayed_work scheduler;
-};
-struct u132_ring {
-	unsigned in_use:1;
-	unsigned length:7;
-	u8 number;
-	struct u132 *u132;
-	struct u132_endp *curr_endp;
-	struct delayed_work scheduler;
-};
-struct u132 {
-	struct kref kref;
-	struct mutex sw_lock;
-	struct mutex scheduler_lock;
-	struct u132_platform_data *board;
-	struct platform_device *platform_dev;
-	struct u132_ring ring[MAX_U132_RINGS];
-	int sequence_num;
-	int going;
-	int power;
-	int reset;
-	int num_ports;
-	u32 hc_control;
-	u32 hc_fminterval;
-	u32 hc_roothub_status;
-	u32 hc_roothub_a;
-	u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
-	int flags;
-	unsigned long next_statechange;
-	struct delayed_work monitor;
-	int num_endpoints;
-	struct u132_addr addr[MAX_U132_ADDRS];
-	struct u132_udev udev[MAX_U132_UDEVS];
-	struct u132_port port[MAX_U132_PORTS];
-	struct u132_endp *endp[MAX_U132_ENDPS];
-};
-
-/*
-* these cannot be inlines because we need the structure offset!!
-* Does anyone have a better way?????
-*/
-#define ftdi_read_pcimem(pdev, member, data) usb_ftdi_elan_read_pcimem(pdev, \
-	offsetof(struct ohci_regs, member), 0, data);
-#define ftdi_write_pcimem(pdev, member, data) usb_ftdi_elan_write_pcimem(pdev, \
-	offsetof(struct ohci_regs, member), 0, data)
-#define u132_read_pcimem(u132, member, data) \
-	usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
-	ohci_regs, member), 0, data)
-#define u132_write_pcimem(u132, member, data) \
-	usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
-	ohci_regs, member), 0, data)
-static inline struct u132 *udev_to_u132(struct u132_udev *udev)
-{
-	u8 udev_number = udev->udev_number;
-	return container_of(udev, struct u132, udev[udev_number]);
-}
-
-static inline struct u132 *hcd_to_u132(struct usb_hcd *hcd)
-{
-	return (struct u132 *)(hcd->hcd_priv);
-}
-
-static inline struct usb_hcd *u132_to_hcd(struct u132 *u132)
-{
-	return container_of((void *)u132, struct usb_hcd, hcd_priv);
-}
-
-static inline void u132_disable(struct u132 *u132)
-{
-	u132_to_hcd(u132)->state = HC_STATE_HALT;
-}
-
-
-#define kref_to_u132(d) container_of(d, struct u132, kref)
-#define kref_to_u132_endp(d) container_of(d, struct u132_endp, kref)
-#define kref_to_u132_udev(d) container_of(d, struct u132_udev, kref)
-#include "../misc/usb_u132.h"
-static const char hcd_name[] = "u132_hcd";
-#define PORT_C_MASK ((USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | \
-	USB_PORT_STAT_C_SUSPEND | USB_PORT_STAT_C_OVERCURRENT | \
-	USB_PORT_STAT_C_RESET) << 16)
-static void u132_hcd_delete(struct kref *kref)
-{
-	struct u132 *u132 = kref_to_u132(kref);
-	struct platform_device *pdev = u132->platform_dev;
-	struct usb_hcd *hcd = u132_to_hcd(u132);
-	u132->going += 1;
-	mutex_lock(&u132_module_lock);
-	u132_instances -= 1;
-	mutex_unlock(&u132_module_lock);
-	dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13"
-		"2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev);
-	usb_put_hcd(hcd);
-}
-
-static inline void u132_u132_put_kref(struct u132 *u132)
-{
-	kref_put(&u132->kref, u132_hcd_delete);
-}
-
-static inline void u132_u132_init_kref(struct u132 *u132)
-{
-	kref_init(&u132->kref);
-}
-
-static void u132_udev_delete(struct kref *kref)
-{
-	struct u132_udev *udev = kref_to_u132_udev(kref);
-	udev->udev_number = 0;
-	udev->usb_device = NULL;
-	udev->usb_addr = 0;
-	udev->enumeration = 0;
-}
-
-static inline void u132_udev_put_kref(struct u132 *u132, struct u132_udev *udev)
-{
-	kref_put(&udev->kref, u132_udev_delete);
-}
-
-static inline void u132_udev_get_kref(struct u132 *u132, struct u132_udev *udev)
-{
-	kref_get(&udev->kref);
-}
-
-static inline void u132_udev_init_kref(struct u132 *u132,
-	struct u132_udev *udev)
-{
-	kref_init(&udev->kref);
-}
-
-static inline void u132_ring_put_kref(struct u132 *u132, struct u132_ring *ring)
-{
-	kref_put(&u132->kref, u132_hcd_delete);
-}
-
-static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring,
-	unsigned int delta)
-{
-	if (delta > 0) {
-		if (queue_delayed_work(workqueue, &ring->scheduler, delta))
-			return;
-	} else if (queue_delayed_work(workqueue, &ring->scheduler, 0))
-		return;
-	kref_put(&u132->kref, u132_hcd_delete);
-}
-
-static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring,
-	unsigned int delta)
-{
-	kref_get(&u132->kref);
-	u132_ring_requeue_work(u132, ring, delta);
-}
-
-static void u132_ring_cancel_work(struct u132 *u132, struct u132_ring *ring)
-{
-	if (cancel_delayed_work(&ring->scheduler))
-		kref_put(&u132->kref, u132_hcd_delete);
-}
-
-static void u132_endp_delete(struct kref *kref)
-{
-	struct u132_endp *endp = kref_to_u132_endp(kref);
-	struct u132 *u132 = endp->u132;
-	u8 usb_addr = endp->usb_addr;
-	u8 usb_endp = endp->usb_endp;
-	u8 address = u132->addr[usb_addr].address;
-	struct u132_udev *udev = &u132->udev[address];
-	u8 endp_number = endp->endp_number;
-	struct usb_host_endpoint *hep = endp->hep;
-	struct u132_ring *ring = endp->ring;
-	struct list_head *head = &endp->endp_ring;
-	ring->length -= 1;
-	if (endp == ring->curr_endp) {
-		if (list_empty(head)) {
-			ring->curr_endp = NULL;
-			list_del(head);
-		} else {
-			struct u132_endp *next_endp = list_entry(head->next,
-				struct u132_endp, endp_ring);
-			ring->curr_endp = next_endp;
-			list_del(head);
-		}
-	} else
-		list_del(head);
-	if (endp->input) {
-		udev->endp_number_in[usb_endp] = 0;
-		u132_udev_put_kref(u132, udev);
-	}
-	if (endp->output) {
-		udev->endp_number_out[usb_endp] = 0;
-		u132_udev_put_kref(u132, udev);
-	}
-	u132->endp[endp_number - 1] = NULL;
-	hep->hcpriv = NULL;
-	kfree(endp);
-	u132_u132_put_kref(u132);
-}
-
-static inline void u132_endp_put_kref(struct u132 *u132, struct u132_endp *endp)
-{
-	kref_put(&endp->kref, u132_endp_delete);
-}
-
-static inline void u132_endp_get_kref(struct u132 *u132, struct u132_endp *endp)
-{
-	kref_get(&endp->kref);
-}
-
-static inline void u132_endp_init_kref(struct u132 *u132,
-	struct u132_endp *endp)
-{
-	kref_init(&endp->kref);
-	kref_get(&u132->kref);
-}
-
-static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp,
-	unsigned int delta)
-{
-	if (queue_delayed_work(workqueue, &endp->scheduler, delta))
-		kref_get(&endp->kref);
-}
-
-static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp)
-{
-	if (cancel_delayed_work(&endp->scheduler))
-		kref_put(&endp->kref, u132_endp_delete);
-}
-
-static inline void u132_monitor_put_kref(struct u132 *u132)
-{
-	kref_put(&u132->kref, u132_hcd_delete);
-}
-
-static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta)
-{
-	if (queue_delayed_work(workqueue, &u132->monitor, delta))
-		kref_get(&u132->kref);
-}
-
-static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta)
-{
-	if (!queue_delayed_work(workqueue, &u132->monitor, delta))
-		kref_put(&u132->kref, u132_hcd_delete);
-}
-
-static void u132_monitor_cancel_work(struct u132 *u132)
-{
-	if (cancel_delayed_work(&u132->monitor))
-		kref_put(&u132->kref, u132_hcd_delete);
-}
-
-static int read_roothub_info(struct u132 *u132)
-{
-	u32 revision;
-	int retval;
-	retval = u132_read_pcimem(u132, revision, &revision);
-	if (retval) {
-		dev_err(&u132->platform_dev->dev, "error %d accessing device co"
-			"ntrol\n", retval);
-		return retval;
-	} else if ((revision & 0xFF) == 0x10) {
-	} else if ((revision & 0xFF) == 0x11) {
-	} else {
-		dev_err(&u132->platform_dev->dev, "device revision is not valid"
-			" %08X\n", revision);
-		return -ENODEV;
-	}
-	retval = u132_read_pcimem(u132, control, &u132->hc_control);
-	if (retval) {
-		dev_err(&u132->platform_dev->dev, "error %d accessing device co"
-			"ntrol\n", retval);
-		return retval;
-	}
-	retval = u132_read_pcimem(u132, roothub.status,
-		&u132->hc_roothub_status);
-	if (retval) {
-		dev_err(&u132->platform_dev->dev, "error %d accessing device re"
-			"g roothub.status\n", retval);
-		return retval;
-	}
-	retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a);
-	if (retval) {
-		dev_err(&u132->platform_dev->dev, "error %d accessing device re"
-			"g roothub.a\n", retval);
-		return retval;
-	}
-	{
-		int I = u132->num_ports;
-		int i = 0;
-		while (I-- > 0) {
-			retval = u132_read_pcimem(u132, roothub.portstatus[i],
-				&u132->hc_roothub_portstatus[i]);
-			if (retval) {
-				dev_err(&u132->platform_dev->dev, "error %d acc"
-					"essing device roothub.portstatus[%d]\n"
-					, retval, i);
-				return retval;
-			} else
-				i += 1;
-		}
-	}
-	return 0;
-}
-
-static void u132_hcd_monitor_work(struct work_struct *work)
-{
-	struct u132 *u132 = container_of(work, struct u132, monitor.work);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		u132_monitor_put_kref(u132);
-		return;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
-		u132_monitor_put_kref(u132);
-		return;
-	} else {
-		int retval;
-		mutex_lock(&u132->sw_lock);
-		retval = read_roothub_info(u132);
-		if (retval) {
-			struct usb_hcd *hcd = u132_to_hcd(u132);
-			u132_disable(u132);
-			u132->going = 1;
-			mutex_unlock(&u132->sw_lock);
-			usb_hc_died(hcd);
-			ftdi_elan_gone_away(u132->platform_dev);
-			u132_monitor_put_kref(u132);
-			return;
-		} else {
-			u132_monitor_requeue_work(u132, 500);
-			mutex_unlock(&u132->sw_lock);
-			return;
-		}
-	}
-}
-
-static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
-	struct urb *urb, int status)
-{
-	struct u132_ring *ring;
-	unsigned long irqs;
-	struct usb_hcd *hcd = u132_to_hcd(u132);
-	urb->error_count = 0;
-	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
-	usb_hcd_unlink_urb_from_ep(hcd, urb);
-	endp->queue_next += 1;
-	if (ENDP_QUEUE_SIZE > --endp->queue_size) {
-		endp->active = 0;
-		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-	} else {
-		struct list_head *next = endp->urb_more.next;
-		struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
-			urb_more);
-		list_del(next);
-		endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
-			urbq->urb;
-		endp->active = 0;
-		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-		kfree(urbq);
-	}
-	mutex_lock(&u132->scheduler_lock);
-	ring = endp->ring;
-	ring->in_use = 0;
-	u132_ring_cancel_work(u132, ring);
-	u132_ring_queue_work(u132, ring, 0);
-	mutex_unlock(&u132->scheduler_lock);
-	u132_endp_put_kref(u132, endp);
-	usb_hcd_giveback_urb(hcd, urb, status);
-}
-
-static void u132_hcd_forget_urb(struct u132 *u132, struct u132_endp *endp,
-	struct urb *urb, int status)
-{
-	u132_endp_put_kref(u132, endp);
-}
-
-static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
-	struct urb *urb, int status)
-{
-	unsigned long irqs;
-	struct usb_hcd *hcd = u132_to_hcd(u132);
-	urb->error_count = 0;
-	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
-	usb_hcd_unlink_urb_from_ep(hcd, urb);
-	endp->queue_next += 1;
-	if (ENDP_QUEUE_SIZE > --endp->queue_size) {
-		endp->active = 0;
-		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-	} else {
-		struct list_head *next = endp->urb_more.next;
-		struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
-			urb_more);
-		list_del(next);
-		endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
-			urbq->urb;
-		endp->active = 0;
-		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-		kfree(urbq);
-	}
-	usb_hcd_giveback_urb(hcd, urb, status);
-}
-
-static inline int edset_input(struct u132 *u132, struct u132_ring *ring,
-	struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
-	void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-	int toggle_bits, int error_count, int condition_code, int repeat_number,
-	 int halted, int skipped, int actual, int non_null))
-{
-	return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp,
-		 urb, address, endp->usb_endp, toggle_bits, callback);
-}
-
-static inline int edset_setup(struct u132 *u132, struct u132_ring *ring,
-	struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
-	void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-	int toggle_bits, int error_count, int condition_code, int repeat_number,
-	 int halted, int skipped, int actual, int non_null))
-{
-	return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp,
-		 urb, address, endp->usb_endp, toggle_bits, callback);
-}
-
-static inline int edset_single(struct u132 *u132, struct u132_ring *ring,
-	struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
-	void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-	int toggle_bits, int error_count, int condition_code, int repeat_number,
-	 int halted, int skipped, int actual, int non_null))
-{
-	return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number,
-		endp, urb, address, endp->usb_endp, toggle_bits, callback);
-}
-
-static inline int edset_output(struct u132 *u132, struct u132_ring *ring,
-	struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
-	void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-	int toggle_bits, int error_count, int condition_code, int repeat_number,
-	 int halted, int skipped, int actual, int non_null))
-{
-	return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number,
-		endp, urb, address, endp->usb_endp, toggle_bits, callback);
-}
-
-
-/*
-* must not LOCK sw_lock
-*
-*/
-static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,
-	int len, int toggle_bits, int error_count, int condition_code,
-	int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-	struct u132_endp *endp = data;
-	struct u132 *u132 = endp->u132;
-	u8 address = u132->addr[endp->usb_addr].address;
-	struct u132_udev *udev = &u132->udev[address];
-	mutex_lock(&u132->scheduler_lock);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (endp->dequeueing) {
-		endp->dequeueing = 0;
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-		return;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed "
-				"urb=%p\n", urb);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (!urb->unlinked) {
-		struct u132_ring *ring = endp->ring;
-		u8 *u = urb->transfer_buffer + urb->actual_length;
-		u8 *b = buf;
-		int L = len;
-
-		while (L-- > 0)
-			*u++ = *b++;
-
-		urb->actual_length += len;
-		if ((condition_code == TD_CC_NOERROR) &&
-			(urb->transfer_buffer_length > urb->actual_length)) {
-			endp->toggle_bits = toggle_bits;
-			usb_settoggle(udev->usb_device, endp->usb_endp, 0,
-				1 & toggle_bits);
-			if (urb->actual_length > 0) {
-				int retval;
-				mutex_unlock(&u132->scheduler_lock);
-				retval = edset_single(u132, ring, endp, urb,
-					address, endp->toggle_bits,
-					u132_hcd_interrupt_recv);
-				if (retval != 0)
-					u132_hcd_giveback_urb(u132, endp, urb,
-						retval);
-			} else {
-				ring->in_use = 0;
-				endp->active = 0;
-				endp->jiffies = jiffies +
-					msecs_to_jiffies(urb->interval);
-				u132_ring_cancel_work(u132, ring);
-				u132_ring_queue_work(u132, ring, 0);
-				mutex_unlock(&u132->scheduler_lock);
-				u132_endp_put_kref(u132, endp);
-			}
-			return;
-		} else if ((condition_code == TD_DATAUNDERRUN) &&
-			((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
-			endp->toggle_bits = toggle_bits;
-			usb_settoggle(udev->usb_device, endp->usb_endp, 0,
-				1 & toggle_bits);
-			mutex_unlock(&u132->scheduler_lock);
-			u132_hcd_giveback_urb(u132, endp, urb, 0);
-			return;
-		} else {
-			if (condition_code == TD_CC_NOERROR) {
-				endp->toggle_bits = toggle_bits;
-				usb_settoggle(udev->usb_device, endp->usb_endp,
-					0, 1 & toggle_bits);
-			} else if (condition_code == TD_CC_STALL) {
-				endp->toggle_bits = 0x2;
-				usb_settoggle(udev->usb_device, endp->usb_endp,
-					0, 0);
-			} else {
-				endp->toggle_bits = 0x2;
-				usb_settoggle(udev->usb_device, endp->usb_endp,
-					0, 0);
-				dev_err(&u132->platform_dev->dev, "urb=%p givin"
-					"g back INTERRUPT %s\n", urb,
-					cc_to_text[condition_code]);
-			}
-			mutex_unlock(&u132->scheduler_lock);
-			u132_hcd_giveback_urb(u132, endp, urb,
-				cc_to_error[condition_code]);
-			return;
-		}
-	} else {
-		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
-				"unlinked=%d\n", urb, urb->unlinked);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	}
-}
-
-static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf,
-	int len, int toggle_bits, int error_count, int condition_code,
-	int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-	struct u132_endp *endp = data;
-	struct u132 *u132 = endp->u132;
-	u8 address = u132->addr[endp->usb_addr].address;
-	mutex_lock(&u132->scheduler_lock);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (endp->dequeueing) {
-		endp->dequeueing = 0;
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-		return;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed "
-				"urb=%p\n", urb);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (!urb->unlinked) {
-		struct u132_ring *ring = endp->ring;
-		urb->actual_length += len;
-		endp->toggle_bits = toggle_bits;
-		if (urb->transfer_buffer_length > urb->actual_length) {
-			int retval;
-			mutex_unlock(&u132->scheduler_lock);
-			retval = edset_output(u132, ring, endp, urb, address,
-				endp->toggle_bits, u132_hcd_bulk_output_sent);
-			if (retval != 0)
-				u132_hcd_giveback_urb(u132, endp, urb, retval);
-			return;
-		} else {
-			mutex_unlock(&u132->scheduler_lock);
-			u132_hcd_giveback_urb(u132, endp, urb, 0);
-			return;
-		}
-	} else {
-		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
-				"unlinked=%d\n", urb, urb->unlinked);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	}
-}
-
-static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf,
-	int len, int toggle_bits, int error_count, int condition_code,
-	int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-	struct u132_endp *endp = data;
-	struct u132 *u132 = endp->u132;
-	u8 address = u132->addr[endp->usb_addr].address;
-	struct u132_udev *udev = &u132->udev[address];
-	mutex_lock(&u132->scheduler_lock);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (endp->dequeueing) {
-		endp->dequeueing = 0;
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-		return;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed "
-				"urb=%p\n", urb);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (!urb->unlinked) {
-		struct u132_ring *ring = endp->ring;
-		u8 *u = urb->transfer_buffer + urb->actual_length;
-		u8 *b = buf;
-		int L = len;
-
-		while (L-- > 0)
-			*u++ = *b++;
-
-		urb->actual_length += len;
-		if ((condition_code == TD_CC_NOERROR) &&
-			(urb->transfer_buffer_length > urb->actual_length)) {
-			int retval;
-			endp->toggle_bits = toggle_bits;
-			usb_settoggle(udev->usb_device, endp->usb_endp, 0,
-				1 & toggle_bits);
-			mutex_unlock(&u132->scheduler_lock);
-			retval = usb_ftdi_elan_edset_input(u132->platform_dev,
-				ring->number, endp, urb, address,
-				endp->usb_endp, endp->toggle_bits,
-				u132_hcd_bulk_input_recv);
-			if (retval != 0)
-				u132_hcd_giveback_urb(u132, endp, urb, retval);
-			return;
-		} else if (condition_code == TD_CC_NOERROR) {
-			endp->toggle_bits = toggle_bits;
-			usb_settoggle(udev->usb_device, endp->usb_endp, 0,
-				1 & toggle_bits);
-			mutex_unlock(&u132->scheduler_lock);
-			u132_hcd_giveback_urb(u132, endp, urb,
-				cc_to_error[condition_code]);
-			return;
-		} else if ((condition_code == TD_DATAUNDERRUN) &&
-			((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
-			endp->toggle_bits = toggle_bits;
-			usb_settoggle(udev->usb_device, endp->usb_endp, 0,
-				1 & toggle_bits);
-			mutex_unlock(&u132->scheduler_lock);
-			u132_hcd_giveback_urb(u132, endp, urb, 0);
-			return;
-		} else if (condition_code == TD_DATAUNDERRUN) {
-			endp->toggle_bits = toggle_bits;
-			usb_settoggle(udev->usb_device, endp->usb_endp, 0,
-				1 & toggle_bits);
-			dev_warn(&u132->platform_dev->dev, "urb=%p(SHORT NOT OK"
-				") giving back BULK IN %s\n", urb,
-				cc_to_text[condition_code]);
-			mutex_unlock(&u132->scheduler_lock);
-			u132_hcd_giveback_urb(u132, endp, urb, 0);
-			return;
-		} else if (condition_code == TD_CC_STALL) {
-			endp->toggle_bits = 0x2;
-			usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
-			mutex_unlock(&u132->scheduler_lock);
-			u132_hcd_giveback_urb(u132, endp, urb,
-				cc_to_error[condition_code]);
-			return;
-		} else {
-			endp->toggle_bits = 0x2;
-			usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
-			dev_err(&u132->platform_dev->dev, "urb=%p giving back B"
-				"ULK IN code=%d %s\n", urb, condition_code,
-				cc_to_text[condition_code]);
-			mutex_unlock(&u132->scheduler_lock);
-			u132_hcd_giveback_urb(u132, endp, urb,
-				cc_to_error[condition_code]);
-			return;
-		}
-	} else {
-		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
-				"unlinked=%d\n", urb, urb->unlinked);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	}
-}
-
-static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf,
-	int len, int toggle_bits, int error_count, int condition_code,
-	int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-	struct u132_endp *endp = data;
-	struct u132 *u132 = endp->u132;
-	mutex_lock(&u132->scheduler_lock);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (endp->dequeueing) {
-		endp->dequeueing = 0;
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-		return;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed "
-				"urb=%p\n", urb);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (!urb->unlinked) {
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	} else {
-		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
-				"unlinked=%d\n", urb, urb->unlinked);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	}
-}
-
-static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf,
-	int len, int toggle_bits, int error_count, int condition_code,
-	int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-	struct u132_endp *endp = data;
-	struct u132 *u132 = endp->u132;
-	u8 address = u132->addr[endp->usb_addr].address;
-	mutex_lock(&u132->scheduler_lock);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (endp->dequeueing) {
-		endp->dequeueing = 0;
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-		return;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed "
-				"urb=%p\n", urb);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (!urb->unlinked) {
-		struct u132_ring *ring = endp->ring;
-		u8 *u = urb->transfer_buffer;
-		u8 *b = buf;
-		int L = len;
-
-		while (L-- > 0)
-			*u++ = *b++;
-
-		urb->actual_length = len;
-		if ((condition_code == TD_CC_NOERROR) || ((condition_code ==
-			TD_DATAUNDERRUN) && ((urb->transfer_flags &
-			URB_SHORT_NOT_OK) == 0))) {
-			int retval;
-			mutex_unlock(&u132->scheduler_lock);
-			retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
-				ring->number, endp, urb, address,
-				endp->usb_endp, 0x3,
-				u132_hcd_configure_empty_sent);
-			if (retval != 0)
-				u132_hcd_giveback_urb(u132, endp, urb, retval);
-			return;
-		} else if (condition_code == TD_CC_STALL) {
-			mutex_unlock(&u132->scheduler_lock);
-			dev_warn(&u132->platform_dev->dev, "giving back SETUP I"
-				"NPUT STALL urb %p\n", urb);
-			u132_hcd_giveback_urb(u132, endp, urb,
-				cc_to_error[condition_code]);
-			return;
-		} else {
-			mutex_unlock(&u132->scheduler_lock);
-			dev_err(&u132->platform_dev->dev, "giving back SETUP IN"
-				"PUT %s urb %p\n", cc_to_text[condition_code],
-				urb);
-			u132_hcd_giveback_urb(u132, endp, urb,
-				cc_to_error[condition_code]);
-			return;
-		}
-	} else {
-		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
-				"unlinked=%d\n", urb, urb->unlinked);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	}
-}
-
-static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf,
-	int len, int toggle_bits, int error_count, int condition_code,
-	int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-	struct u132_endp *endp = data;
-	struct u132 *u132 = endp->u132;
-	mutex_lock(&u132->scheduler_lock);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (endp->dequeueing) {
-		endp->dequeueing = 0;
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-		return;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed "
-				"urb=%p\n", urb);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (!urb->unlinked) {
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	} else {
-		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
-				"unlinked=%d\n", urb, urb->unlinked);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	}
-}
-
-static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf,
-	int len, int toggle_bits, int error_count, int condition_code,
-	int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-	struct u132_endp *endp = data;
-	struct u132 *u132 = endp->u132;
-	u8 address = u132->addr[endp->usb_addr].address;
-	mutex_lock(&u132->scheduler_lock);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (endp->dequeueing) {
-		endp->dequeueing = 0;
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-		return;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed "
-				"urb=%p\n", urb);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (!urb->unlinked) {
-		if (usb_pipein(urb->pipe)) {
-			int retval;
-			struct u132_ring *ring = endp->ring;
-			mutex_unlock(&u132->scheduler_lock);
-			retval = usb_ftdi_elan_edset_input(u132->platform_dev,
-				ring->number, endp, urb, address,
-				endp->usb_endp, 0,
-				u132_hcd_configure_input_recv);
-			if (retval != 0)
-				u132_hcd_giveback_urb(u132, endp, urb, retval);
-			return;
-		} else {
-			int retval;
-			struct u132_ring *ring = endp->ring;
-			mutex_unlock(&u132->scheduler_lock);
-			retval = usb_ftdi_elan_edset_input(u132->platform_dev,
-				ring->number, endp, urb, address,
-				endp->usb_endp, 0,
-				u132_hcd_configure_empty_recv);
-			if (retval != 0)
-				u132_hcd_giveback_urb(u132, endp, urb, retval);
-			return;
-		}
-	} else {
-		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
-				"unlinked=%d\n", urb, urb->unlinked);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	}
-}
-
-static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb,
-	u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
-	int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-	struct u132_endp *endp = data;
-	struct u132 *u132 = endp->u132;
-	u8 address = u132->addr[endp->usb_addr].address;
-	struct u132_udev *udev = &u132->udev[address];
-	mutex_lock(&u132->scheduler_lock);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (endp->dequeueing) {
-		endp->dequeueing = 0;
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-		return;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed "
-				"urb=%p\n", urb);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (!urb->unlinked) {
-		u132->addr[0].address = 0;
-		endp->usb_addr = udev->usb_addr;
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	} else {
-		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
-				"unlinked=%d\n", urb, urb->unlinked);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	}
-}
-
-static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb,
-	u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
-	int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-	struct u132_endp *endp = data;
-	struct u132 *u132 = endp->u132;
-	mutex_lock(&u132->scheduler_lock);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (endp->dequeueing) {
-		endp->dequeueing = 0;
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-		return;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed "
-				"urb=%p\n", urb);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (!urb->unlinked) {
-		int retval;
-		struct u132_ring *ring = endp->ring;
-		mutex_unlock(&u132->scheduler_lock);
-		retval = usb_ftdi_elan_edset_input(u132->platform_dev,
-			ring->number, endp, urb, 0, endp->usb_endp, 0,
-			u132_hcd_enumeration_empty_recv);
-		if (retval != 0)
-			u132_hcd_giveback_urb(u132, endp, urb, retval);
-		return;
-	} else {
-		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
-				"unlinked=%d\n", urb, urb->unlinked);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	}
-}
-
-static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf,
-	int len, int toggle_bits, int error_count, int condition_code,
-	int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-	struct u132_endp *endp = data;
-	struct u132 *u132 = endp->u132;
-	mutex_lock(&u132->scheduler_lock);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (endp->dequeueing) {
-		endp->dequeueing = 0;
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-		return;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed "
-				"urb=%p\n", urb);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (!urb->unlinked) {
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	} else {
-		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
-				"unlinked=%d\n", urb, urb->unlinked);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	}
-}
-
-static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf,
-	int len, int toggle_bits, int error_count, int condition_code,
-	int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-	struct u132_endp *endp = data;
-	struct u132 *u132 = endp->u132;
-	u8 address = u132->addr[endp->usb_addr].address;
-	mutex_lock(&u132->scheduler_lock);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (endp->dequeueing) {
-		endp->dequeueing = 0;
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-		return;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed "
-				"urb=%p\n", urb);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (!urb->unlinked) {
-		int retval;
-		struct u132_ring *ring = endp->ring;
-		u8 *u = urb->transfer_buffer;
-		u8 *b = buf;
-		int L = len;
-
-		while (L-- > 0)
-			*u++ = *b++;
-
-		urb->actual_length = len;
-		mutex_unlock(&u132->scheduler_lock);
-		retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
-			ring->number, endp, urb, address, endp->usb_endp, 0x3,
-			u132_hcd_initial_empty_sent);
-		if (retval != 0)
-			u132_hcd_giveback_urb(u132, endp, urb, retval);
-		return;
-	} else {
-		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
-				"unlinked=%d\n", urb, urb->unlinked);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	}
-}
-
-static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
-	int len, int toggle_bits, int error_count, int condition_code,
-	int repeat_number, int halted, int skipped, int actual, int non_null)
-{
-	struct u132_endp *endp = data;
-	struct u132 *u132 = endp->u132;
-	u8 address = u132->addr[endp->usb_addr].address;
-	mutex_lock(&u132->scheduler_lock);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (endp->dequeueing) {
-		endp->dequeueing = 0;
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
-		return;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed "
-				"urb=%p\n", urb);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
-		return;
-	} else if (!urb->unlinked) {
-		int retval;
-		struct u132_ring *ring = endp->ring;
-		mutex_unlock(&u132->scheduler_lock);
-		retval = usb_ftdi_elan_edset_input(u132->platform_dev,
-			ring->number, endp, urb, address, endp->usb_endp, 0,
-			u132_hcd_initial_input_recv);
-		if (retval != 0)
-			u132_hcd_giveback_urb(u132, endp, urb, retval);
-		return;
-	} else {
-		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
-				"unlinked=%d\n", urb, urb->unlinked);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_hcd_giveback_urb(u132, endp, urb, 0);
-		return;
-	}
-}
-
-/*
-* this work function is only executed from the work queue
-*
-*/
-static void u132_hcd_ring_work_scheduler(struct work_struct *work)
-{
-	struct u132_ring *ring =
-		container_of(work, struct u132_ring, scheduler.work);
-	struct u132 *u132 = ring->u132;
-	mutex_lock(&u132->scheduler_lock);
-	if (ring->in_use) {
-		mutex_unlock(&u132->scheduler_lock);
-		u132_ring_put_kref(u132, ring);
-		return;
-	} else if (ring->curr_endp) {
-		struct u132_endp *endp, *last_endp = ring->curr_endp;
-		unsigned long wakeup = 0;
-		list_for_each_entry(endp, &last_endp->endp_ring, endp_ring) {
-			if (endp->queue_next == endp->queue_last) {
-			} else if ((endp->delayed == 0)
-				|| time_after_eq(jiffies, endp->jiffies)) {
-				ring->curr_endp = endp;
-				u132_endp_cancel_work(u132, last_endp);
-				u132_endp_queue_work(u132, last_endp, 0);
-				mutex_unlock(&u132->scheduler_lock);
-				u132_ring_put_kref(u132, ring);
-				return;
-			} else {
-				unsigned long delta = endp->jiffies - jiffies;
-				if (delta > wakeup)
-					wakeup = delta;
-			}
-		}
-		if (last_endp->queue_next == last_endp->queue_last) {
-		} else if ((last_endp->delayed == 0) || time_after_eq(jiffies,
-			last_endp->jiffies)) {
-			u132_endp_cancel_work(u132, last_endp);
-			u132_endp_queue_work(u132, last_endp, 0);
-			mutex_unlock(&u132->scheduler_lock);
-			u132_ring_put_kref(u132, ring);
-			return;
-		} else {
-			unsigned long delta = last_endp->jiffies - jiffies;
-			if (delta > wakeup)
-				wakeup = delta;
-		}
-		if (wakeup > 0) {
-			u132_ring_requeue_work(u132, ring, wakeup);
-			mutex_unlock(&u132->scheduler_lock);
-			return;
-		} else {
-			mutex_unlock(&u132->scheduler_lock);
-			u132_ring_put_kref(u132, ring);
-			return;
-		}
-	} else {
-		mutex_unlock(&u132->scheduler_lock);
-		u132_ring_put_kref(u132, ring);
-		return;
-	}
-}
-
-static void u132_hcd_endp_work_scheduler(struct work_struct *work)
-{
-	struct u132_ring *ring;
-	struct u132_endp *endp =
-		container_of(work, struct u132_endp, scheduler.work);
-	struct u132 *u132 = endp->u132;
-	mutex_lock(&u132->scheduler_lock);
-	ring = endp->ring;
-	if (endp->edset_flush) {
-		endp->edset_flush = 0;
-		if (endp->dequeueing)
-			usb_ftdi_elan_edset_flush(u132->platform_dev,
-				ring->number, endp);
-		mutex_unlock(&u132->scheduler_lock);
-		u132_endp_put_kref(u132, endp);
-		return;
-	} else if (endp->active) {
-		mutex_unlock(&u132->scheduler_lock);
-		u132_endp_put_kref(u132, endp);
-		return;
-	} else if (ring->in_use) {
-		mutex_unlock(&u132->scheduler_lock);
-		u132_endp_put_kref(u132, endp);
-		return;
-	} else if (endp->queue_next == endp->queue_last) {
-		mutex_unlock(&u132->scheduler_lock);
-		u132_endp_put_kref(u132, endp);
-		return;
-	} else if (endp->pipetype == PIPE_INTERRUPT) {
-		u8 address = u132->addr[endp->usb_addr].address;
-		if (ring->in_use) {
-			mutex_unlock(&u132->scheduler_lock);
-			u132_endp_put_kref(u132, endp);
-			return;
-		} else {
-			int retval;
-			struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
-				endp->queue_next];
-			endp->active = 1;
-			ring->curr_endp = endp;
-			ring->in_use = 1;
-			mutex_unlock(&u132->scheduler_lock);
-			retval = edset_single(u132, ring, endp, urb, address,
-				endp->toggle_bits, u132_hcd_interrupt_recv);
-			if (retval != 0)
-				u132_hcd_giveback_urb(u132, endp, urb, retval);
-			return;
-		}
-	} else if (endp->pipetype == PIPE_CONTROL) {
-		u8 address = u132->addr[endp->usb_addr].address;
-		if (ring->in_use) {
-			mutex_unlock(&u132->scheduler_lock);
-			u132_endp_put_kref(u132, endp);
-			return;
-		} else if (address == 0) {
-			int retval;
-			struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
-				endp->queue_next];
-			endp->active = 1;
-			ring->curr_endp = endp;
-			ring->in_use = 1;
-			mutex_unlock(&u132->scheduler_lock);
-			retval = edset_setup(u132, ring, endp, urb, address,
-				0x2, u132_hcd_initial_setup_sent);
-			if (retval != 0)
-				u132_hcd_giveback_urb(u132, endp, urb, retval);
-			return;
-		} else if (endp->usb_addr == 0) {
-			int retval;
-			struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
-				endp->queue_next];
-			endp->active = 1;
-			ring->curr_endp = endp;
-			ring->in_use = 1;
-			mutex_unlock(&u132->scheduler_lock);
-			retval = edset_setup(u132, ring, endp, urb, 0, 0x2,
-				u132_hcd_enumeration_address_sent);
-			if (retval != 0)
-				u132_hcd_giveback_urb(u132, endp, urb, retval);
-			return;
-		} else {
-			int retval;
-			struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
-				endp->queue_next];
-			address = u132->addr[endp->usb_addr].address;
-			endp->active = 1;
-			ring->curr_endp = endp;
-			ring->in_use = 1;
-			mutex_unlock(&u132->scheduler_lock);
-			retval = edset_setup(u132, ring, endp, urb, address,
-				0x2, u132_hcd_configure_setup_sent);
-			if (retval != 0)
-				u132_hcd_giveback_urb(u132, endp, urb, retval);
-			return;
-		}
-	} else {
-		if (endp->input) {
-			u8 address = u132->addr[endp->usb_addr].address;
-			if (ring->in_use) {
-				mutex_unlock(&u132->scheduler_lock);
-				u132_endp_put_kref(u132, endp);
-				return;
-			} else {
-				int retval;
-				struct urb *urb = endp->urb_list[
-					ENDP_QUEUE_MASK & endp->queue_next];
-				endp->active = 1;
-				ring->curr_endp = endp;
-				ring->in_use = 1;
-				mutex_unlock(&u132->scheduler_lock);
-				retval = edset_input(u132, ring, endp, urb,
-					address, endp->toggle_bits,
-					u132_hcd_bulk_input_recv);
-				if (retval == 0) {
-				} else
-					u132_hcd_giveback_urb(u132, endp, urb,
-						retval);
-				return;
-			}
-		} else {	/* output pipe */
-			u8 address = u132->addr[endp->usb_addr].address;
-			if (ring->in_use) {
-				mutex_unlock(&u132->scheduler_lock);
-				u132_endp_put_kref(u132, endp);
-				return;
-			} else {
-				int retval;
-				struct urb *urb = endp->urb_list[
-					ENDP_QUEUE_MASK & endp->queue_next];
-				endp->active = 1;
-				ring->curr_endp = endp;
-				ring->in_use = 1;
-				mutex_unlock(&u132->scheduler_lock);
-				retval = edset_output(u132, ring, endp, urb,
-					address, endp->toggle_bits,
-					u132_hcd_bulk_output_sent);
-				if (retval == 0) {
-				} else
-					u132_hcd_giveback_urb(u132, endp, urb,
-						retval);
-				return;
-			}
-		}
-	}
-}
-#ifdef CONFIG_PM
-
-static void port_power(struct u132 *u132, int pn, int is_on)
-{
-	u132->port[pn].power = is_on;
-}
-
-#endif
-
-static void u132_power(struct u132 *u132, int is_on)
-{
-	struct usb_hcd *hcd = u132_to_hcd(u132)
-		;	/* hub is inactive unless the port is powered */
-	if (is_on) {
-		if (u132->power)
-			return;
-		u132->power = 1;
-	} else {
-		u132->power = 0;
-		hcd->state = HC_STATE_HALT;
-	}
-}
-
-static int u132_periodic_reinit(struct u132 *u132)
-{
-	int retval;
-	u32 fi = u132->hc_fminterval & 0x03fff;
-	u32 fit;
-	u32 fminterval;
-	retval = u132_read_pcimem(u132, fminterval, &fminterval);
-	if (retval)
-		return retval;
-	fit = fminterval & FIT;
-	retval = u132_write_pcimem(u132, fminterval,
-		(fit ^ FIT) | u132->hc_fminterval);
-	if (retval)
-		return retval;
-	return u132_write_pcimem(u132, periodicstart,
-	       ((9 * fi) / 10) & 0x3fff);
-}
-
-static char *hcfs2string(int state)
-{
-	switch (state) {
-	case OHCI_USB_RESET:
-		return "reset";
-	case OHCI_USB_RESUME:
-		return "resume";
-	case OHCI_USB_OPER:
-		return "operational";
-	case OHCI_USB_SUSPEND:
-		return "suspend";
-	}
-	return "?";
-}
-
-static int u132_init(struct u132 *u132)
-{
-	int retval;
-	u32 control;
-	u132_disable(u132);
-	u132->next_statechange = jiffies;
-	retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
-	if (retval)
-		return retval;
-	retval = u132_read_pcimem(u132, control, &control);
-	if (retval)
-		return retval;
-	if (u132->num_ports == 0) {
-		u32 rh_a = -1;
-		retval = u132_read_pcimem(u132, roothub.a, &rh_a);
-		if (retval)
-			return retval;
-		u132->num_ports = rh_a & RH_A_NDP;
-		retval = read_roothub_info(u132);
-		if (retval)
-			return retval;
-	}
-	if (u132->num_ports > MAX_U132_PORTS)
-		return -EINVAL;
-
-	return 0;
-}
-
-
-/* Start an OHCI controller, set the BUS operational
-* resets USB and controller
-* enable interrupts
-*/
-static int u132_run(struct u132 *u132)
-{
-	int retval;
-	u32 control;
-	u32 status;
-	u32 fminterval;
-	u32 periodicstart;
-	u32 cmdstatus;
-	u32 roothub_a;
-	int mask = OHCI_INTR_INIT;
-	int first = u132->hc_fminterval == 0;
-	int sleep_time = 0;
-	int reset_timeout = 30;	/* ... allow extra time */
-	u132_disable(u132);
-	if (first) {
-		u32 temp;
-		retval = u132_read_pcimem(u132, fminterval, &temp);
-		if (retval)
-			return retval;
-		u132->hc_fminterval = temp & 0x3fff;
-		u132->hc_fminterval |= FSMP(u132->hc_fminterval) << 16;
-	}
-	retval = u132_read_pcimem(u132, control, &u132->hc_control);
-	if (retval)
-		return retval;
-	dev_info(&u132->platform_dev->dev, "resetting from state '%s', control "
-		"= %08X\n", hcfs2string(u132->hc_control & OHCI_CTRL_HCFS),
-		u132->hc_control);
-	switch (u132->hc_control & OHCI_CTRL_HCFS) {
-	case OHCI_USB_OPER:
-		sleep_time = 0;
-		break;
-	case OHCI_USB_SUSPEND:
-	case OHCI_USB_RESUME:
-		u132->hc_control &= OHCI_CTRL_RWC;
-		u132->hc_control |= OHCI_USB_RESUME;
-		sleep_time = 10;
-		break;
-	default:
-		u132->hc_control &= OHCI_CTRL_RWC;
-		u132->hc_control |= OHCI_USB_RESET;
-		sleep_time = 50;
-		break;
-	}
-	retval = u132_write_pcimem(u132, control, u132->hc_control);
-	if (retval)
-		return retval;
-	retval = u132_read_pcimem(u132, control, &control);
-	if (retval)
-		return retval;
-	msleep(sleep_time);
-	retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
-	if (retval)
-		return retval;
-	if (!(roothub_a & RH_A_NPS)) {
-		int temp;	/* power down each port */
-		for (temp = 0; temp < u132->num_ports; temp++) {
-			retval = u132_write_pcimem(u132,
-				roothub.portstatus[temp], RH_PS_LSDA);
-			if (retval)
-				return retval;
-		}
-	}
-	retval = u132_read_pcimem(u132, control, &control);
-	if (retval)
-		return retval;
-retry:
-	retval = u132_read_pcimem(u132, cmdstatus, &status);
-	if (retval)
-		return retval;
-	retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR);
-	if (retval)
-		return retval;
-extra:	{
-		retval = u132_read_pcimem(u132, cmdstatus, &status);
-		if (retval)
-			return retval;
-		if (0 != (status & OHCI_HCR)) {
-			if (--reset_timeout == 0) {
-				dev_err(&u132->platform_dev->dev, "USB HC reset"
-					" timed out!\n");
-				return -ENODEV;
-			} else {
-				msleep(5);
-				goto extra;
-			}
-		}
-	}
-	if (u132->flags & OHCI_QUIRK_INITRESET) {
-		retval = u132_write_pcimem(u132, control, u132->hc_control);
-		if (retval)
-			return retval;
-		retval = u132_read_pcimem(u132, control, &control);
-		if (retval)
-			return retval;
-	}
-	retval = u132_write_pcimem(u132, ed_controlhead, 0x00000000);
-	if (retval)
-		return retval;
-	retval = u132_write_pcimem(u132, ed_bulkhead, 0x11000000);
-	if (retval)
-		return retval;
-	retval = u132_write_pcimem(u132, hcca, 0x00000000);
-	if (retval)
-		return retval;
-	retval = u132_periodic_reinit(u132);
-	if (retval)
-		return retval;
-	retval = u132_read_pcimem(u132, fminterval, &fminterval);
-	if (retval)
-		return retval;
-	retval = u132_read_pcimem(u132, periodicstart, &periodicstart);
-	if (retval)
-		return retval;
-	if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
-		if (!(u132->flags & OHCI_QUIRK_INITRESET)) {
-			u132->flags |= OHCI_QUIRK_INITRESET;
-			goto retry;
-		} else
-			dev_err(&u132->platform_dev->dev, "init err(%08x %04x)"
-				"\n", fminterval, periodicstart);
-	}			/* start controller operations */
-	u132->hc_control &= OHCI_CTRL_RWC;
-	u132->hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
-	retval = u132_write_pcimem(u132, control, u132->hc_control);
-	if (retval)
-		return retval;
-	retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF);
-	if (retval)
-		return retval;
-	retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
-	if (retval)
-		return retval;
-	retval = u132_read_pcimem(u132, control, &control);
-	if (retval)
-		return retval;
-	u132_to_hcd(u132)->state = HC_STATE_RUNNING;
-	retval = u132_write_pcimem(u132, roothub.status, RH_HS_DRWE);
-	if (retval)
-		return retval;
-	retval = u132_write_pcimem(u132, intrstatus, mask);
-	if (retval)
-		return retval;
-	retval = u132_write_pcimem(u132, intrdisable,
-		OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
-		OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
-		OHCI_INTR_SO);
-	if (retval)
-		return retval;	/* handle root hub init quirks ... */
-	retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
-	if (retval)
-		return retval;
-	roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
-	if (u132->flags & OHCI_QUIRK_SUPERIO) {
-		roothub_a |= RH_A_NOCP;
-		roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
-		retval = u132_write_pcimem(u132, roothub.a, roothub_a);
-		if (retval)
-			return retval;
-	} else if ((u132->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
-		roothub_a |= RH_A_NPS;
-		retval = u132_write_pcimem(u132, roothub.a, roothub_a);
-		if (retval)
-			return retval;
-	}
-	retval = u132_write_pcimem(u132, roothub.status, RH_HS_LPSC);
-	if (retval)
-		return retval;
-	retval = u132_write_pcimem(u132, roothub.b,
-		(roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
-	if (retval)
-		return retval;
-	retval = u132_read_pcimem(u132, control, &control);
-	if (retval)
-		return retval;
-	mdelay((roothub_a >> 23) & 0x1fe);
-	u132_to_hcd(u132)->state = HC_STATE_RUNNING;
-	return 0;
-}
-
-static void u132_hcd_stop(struct usb_hcd *hcd)
-{
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b"
-			"een removed %d\n", u132, hcd, u132->going);
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
-			"ed\n", hcd);
-	} else {
-		mutex_lock(&u132->sw_lock);
-		msleep(100);
-		u132_power(u132, 0);
-		mutex_unlock(&u132->sw_lock);
-	}
-}
-
-static int u132_hcd_start(struct usb_hcd *hcd)
-{
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		return -ENODEV;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
-		return -ESHUTDOWN;
-	} else if (hcd->self.controller) {
-		int retval;
-		struct platform_device *pdev =
-			to_platform_device(hcd->self.controller);
-		u16 vendor = ((struct u132_platform_data *)
-			dev_get_platdata(&pdev->dev))->vendor;
-		u16 device = ((struct u132_platform_data *)
-			dev_get_platdata(&pdev->dev))->device;
-		mutex_lock(&u132->sw_lock);
-		msleep(10);
-		if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) {
-			u132->flags = OHCI_QUIRK_AMD756;
-		} else if (vendor == PCI_VENDOR_ID_OPTI && device == 0xc861) {
-			dev_err(&u132->platform_dev->dev, "WARNING: OPTi workar"
-				"ounds unavailable\n");
-		} else if (vendor == PCI_VENDOR_ID_COMPAQ && device == 0xa0f8)
-			u132->flags |= OHCI_QUIRK_ZFMICRO;
-		retval = u132_run(u132);
-		if (retval) {
-			u132_disable(u132);
-			u132->going = 1;
-		}
-		msleep(100);
-		mutex_unlock(&u132->sw_lock);
-		return retval;
-	} else {
-		dev_err(&u132->platform_dev->dev, "platform_device missing\n");
-		return -ENODEV;
-	}
-}
-
-static int u132_hcd_reset(struct usb_hcd *hcd)
-{
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		return -ENODEV;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
-		return -ESHUTDOWN;
-	} else {
-		int retval;
-		mutex_lock(&u132->sw_lock);
-		retval = u132_init(u132);
-		if (retval) {
-			u132_disable(u132);
-			u132->going = 1;
-		}
-		mutex_unlock(&u132->sw_lock);
-		return retval;
-	}
-}
-
-static int create_endpoint_and_queue_int(struct u132 *u132,
-	struct u132_udev *udev, struct urb *urb,
-	struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
-	gfp_t mem_flags)
-{
-	struct u132_ring *ring;
-	unsigned long irqs;
-	int rc;
-	u8 endp_number;
-	struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
-
-	if (!endp)
-		return -ENOMEM;
-
-	spin_lock_init(&endp->queue_lock.slock);
-	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
-	rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb);
-	if (rc) {
-		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-		kfree(endp);
-		return rc;
-	}
-
-	endp_number = ++u132->num_endpoints;
-	urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
-	INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
-	INIT_LIST_HEAD(&endp->urb_more);
-	ring = endp->ring = &u132->ring[0];
-	if (ring->curr_endp) {
-		list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
-	} else {
-		INIT_LIST_HEAD(&endp->endp_ring);
-		ring->curr_endp = endp;
-	}
-	ring->length += 1;
-	endp->dequeueing = 0;
-	endp->edset_flush = 0;
-	endp->active = 0;
-	endp->delayed = 0;
-	endp->endp_number = endp_number;
-	endp->u132 = u132;
-	endp->hep = urb->ep;
-	endp->pipetype = usb_pipetype(urb->pipe);
-	u132_endp_init_kref(u132, endp);
-	if (usb_pipein(urb->pipe)) {
-		endp->toggle_bits = 0x2;
-		usb_settoggle(udev->usb_device, usb_endp, 0, 0);
-		endp->input = 1;
-		endp->output = 0;
-		udev->endp_number_in[usb_endp] = endp_number;
-		u132_udev_get_kref(u132, udev);
-	} else {
-		endp->toggle_bits = 0x2;
-		usb_settoggle(udev->usb_device, usb_endp, 1, 0);
-		endp->input = 0;
-		endp->output = 1;
-		udev->endp_number_out[usb_endp] = endp_number;
-		u132_udev_get_kref(u132, udev);
-	}
-	urb->hcpriv = u132;
-	endp->delayed = 1;
-	endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
-	endp->udev_number = address;
-	endp->usb_addr = usb_addr;
-	endp->usb_endp = usb_endp;
-	endp->queue_size = 1;
-	endp->queue_last = 0;
-	endp->queue_next = 0;
-	endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
-	spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-	u132_endp_queue_work(u132, endp, msecs_to_jiffies(urb->interval));
-	return 0;
-}
-
-static int queue_int_on_old_endpoint(struct u132 *u132,
-	struct u132_udev *udev, struct urb *urb,
-	struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
-	u8 usb_endp, u8 address)
-{
-	urb->hcpriv = u132;
-	endp->delayed = 1;
-	endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
-	if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
-		endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
-	} else {
-		struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
-			GFP_ATOMIC);
-		if (urbq == NULL) {
-			endp->queue_size -= 1;
-			return -ENOMEM;
-		} else {
-			list_add_tail(&urbq->urb_more, &endp->urb_more);
-			urbq->urb = urb;
-		}
-	}
-	return 0;
-}
-
-static int create_endpoint_and_queue_bulk(struct u132 *u132,
-	struct u132_udev *udev, struct urb *urb,
-	struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
-	gfp_t mem_flags)
-{
-	int ring_number;
-	struct u132_ring *ring;
-	unsigned long irqs;
-	int rc;
-	u8 endp_number;
-	struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
-
-	if (!endp)
-		return -ENOMEM;
-
-	spin_lock_init(&endp->queue_lock.slock);
-	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
-	rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb);
-	if (rc) {
-		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-		kfree(endp);
-		return rc;
-	}
-
-	endp_number = ++u132->num_endpoints;
-	urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
-	INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
-	INIT_LIST_HEAD(&endp->urb_more);
-	endp->dequeueing = 0;
-	endp->edset_flush = 0;
-	endp->active = 0;
-	endp->delayed = 0;
-	endp->endp_number = endp_number;
-	endp->u132 = u132;
-	endp->hep = urb->ep;
-	endp->pipetype = usb_pipetype(urb->pipe);
-	u132_endp_init_kref(u132, endp);
-	if (usb_pipein(urb->pipe)) {
-		endp->toggle_bits = 0x2;
-		usb_settoggle(udev->usb_device, usb_endp, 0, 0);
-		ring_number = 3;
-		endp->input = 1;
-		endp->output = 0;
-		udev->endp_number_in[usb_endp] = endp_number;
-		u132_udev_get_kref(u132, udev);
-	} else {
-		endp->toggle_bits = 0x2;
-		usb_settoggle(udev->usb_device, usb_endp, 1, 0);
-		ring_number = 2;
-		endp->input = 0;
-		endp->output = 1;
-		udev->endp_number_out[usb_endp] = endp_number;
-		u132_udev_get_kref(u132, udev);
-	}
-	ring = endp->ring = &u132->ring[ring_number - 1];
-	if (ring->curr_endp) {
-		list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
-	} else {
-		INIT_LIST_HEAD(&endp->endp_ring);
-		ring->curr_endp = endp;
-	}
-	ring->length += 1;
-	urb->hcpriv = u132;
-	endp->udev_number = address;
-	endp->usb_addr = usb_addr;
-	endp->usb_endp = usb_endp;
-	endp->queue_size = 1;
-	endp->queue_last = 0;
-	endp->queue_next = 0;
-	endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
-	spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-	u132_endp_queue_work(u132, endp, 0);
-	return 0;
-}
-
-static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
-	struct urb *urb,
-	struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
-	u8 usb_endp, u8 address)
-{
-	urb->hcpriv = u132;
-	if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
-		endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
-	} else {
-		struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
-			GFP_ATOMIC);
-		if (urbq == NULL) {
-			endp->queue_size -= 1;
-			return -ENOMEM;
-		} else {
-			list_add_tail(&urbq->urb_more, &endp->urb_more);
-			urbq->urb = urb;
-		}
-	}
-	return 0;
-}
-
-static int create_endpoint_and_queue_control(struct u132 *u132,
-	struct urb *urb,
-	struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp,
-	gfp_t mem_flags)
-{
-	struct u132_ring *ring;
-	unsigned long irqs;
-	int rc;
-	u8 endp_number;
-	struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
-
-	if (!endp)
-		return -ENOMEM;
-
-	spin_lock_init(&endp->queue_lock.slock);
-	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
-	rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb);
-	if (rc) {
-		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-		kfree(endp);
-		return rc;
-	}
-
-	endp_number = ++u132->num_endpoints;
-	urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
-	INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
-	INIT_LIST_HEAD(&endp->urb_more);
-	ring = endp->ring = &u132->ring[0];
-	if (ring->curr_endp) {
-		list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
-	} else {
-		INIT_LIST_HEAD(&endp->endp_ring);
-		ring->curr_endp = endp;
-	}
-	ring->length += 1;
-	endp->dequeueing = 0;
-	endp->edset_flush = 0;
-	endp->active = 0;
-	endp->delayed = 0;
-	endp->endp_number = endp_number;
-	endp->u132 = u132;
-	endp->hep = urb->ep;
-	u132_endp_init_kref(u132, endp);
-	u132_endp_get_kref(u132, endp);
-	if (usb_addr == 0) {
-		u8 address = u132->addr[usb_addr].address;
-		struct u132_udev *udev = &u132->udev[address];
-		endp->udev_number = address;
-		endp->usb_addr = usb_addr;
-		endp->usb_endp = usb_endp;
-		endp->input = 1;
-		endp->output = 1;
-		endp->pipetype = usb_pipetype(urb->pipe);
-		u132_udev_init_kref(u132, udev);
-		u132_udev_get_kref(u132, udev);
-		udev->endp_number_in[usb_endp] = endp_number;
-		udev->endp_number_out[usb_endp] = endp_number;
-		urb->hcpriv = u132;
-		endp->queue_size = 1;
-		endp->queue_last = 0;
-		endp->queue_next = 0;
-		endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
-		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-		u132_endp_queue_work(u132, endp, 0);
-		return 0;
-	} else {		/*(usb_addr > 0) */
-		u8 address = u132->addr[usb_addr].address;
-		struct u132_udev *udev = &u132->udev[address];
-		endp->udev_number = address;
-		endp->usb_addr = usb_addr;
-		endp->usb_endp = usb_endp;
-		endp->input = 1;
-		endp->output = 1;
-		endp->pipetype = usb_pipetype(urb->pipe);
-		u132_udev_get_kref(u132, udev);
-		udev->enumeration = 2;
-		udev->endp_number_in[usb_endp] = endp_number;
-		udev->endp_number_out[usb_endp] = endp_number;
-		urb->hcpriv = u132;
-		endp->queue_size = 1;
-		endp->queue_last = 0;
-		endp->queue_next = 0;
-		endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
-		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-		u132_endp_queue_work(u132, endp, 0);
-		return 0;
-	}
-}
-
-static int queue_control_on_old_endpoint(struct u132 *u132,
-	struct urb *urb,
-	struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
-	u8 usb_endp)
-{
-	if (usb_addr == 0) {
-		if (usb_pipein(urb->pipe)) {
-			urb->hcpriv = u132;
-			if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
-				endp->urb_list[ENDP_QUEUE_MASK &
-					endp->queue_last++] = urb;
-			} else {
-				struct u132_urbq *urbq =
-					kmalloc(sizeof(struct u132_urbq),
-					GFP_ATOMIC);
-				if (urbq == NULL) {
-					endp->queue_size -= 1;
-					return -ENOMEM;
-				} else {
-					list_add_tail(&urbq->urb_more,
-						&endp->urb_more);
-					urbq->urb = urb;
-				}
-			}
-			return 0;
-		} else {	/* usb_pipeout(urb->pipe) */
-			struct u132_addr *addr = &u132->addr[usb_dev->devnum];
-			int I = MAX_U132_UDEVS;
-			int i = 0;
-			while (--I > 0) {
-				struct u132_udev *udev = &u132->udev[++i];
-				if (udev->usb_device) {
-					continue;
-				} else {
-					udev->enumeration = 1;
-					u132->addr[0].address = i;
-					endp->udev_number = i;
-					udev->udev_number = i;
-					udev->usb_addr = usb_dev->devnum;
-					u132_udev_init_kref(u132, udev);
-					udev->endp_number_in[usb_endp] =
-						endp->endp_number;
-					u132_udev_get_kref(u132, udev);
-					udev->endp_number_out[usb_endp] =
-						endp->endp_number;
-					udev->usb_device = usb_dev;
-					((u8 *) (urb->setup_packet))[2] =
-						addr->address = i;
-					u132_udev_get_kref(u132, udev);
-					break;
-				}
-			}
-			if (I == 0) {
-				dev_err(&u132->platform_dev->dev, "run out of d"
-					"evice space\n");
-				return -EINVAL;
-			}
-			urb->hcpriv = u132;
-			if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
-				endp->urb_list[ENDP_QUEUE_MASK &
-					endp->queue_last++] = urb;
-			} else {
-				struct u132_urbq *urbq =
-					kmalloc(sizeof(struct u132_urbq),
-					GFP_ATOMIC);
-				if (urbq == NULL) {
-					endp->queue_size -= 1;
-					return -ENOMEM;
-				} else {
-					list_add_tail(&urbq->urb_more,
-						&endp->urb_more);
-					urbq->urb = urb;
-				}
-			}
-			return 0;
-		}
-	} else {		/*(usb_addr > 0) */
-		u8 address = u132->addr[usb_addr].address;
-		struct u132_udev *udev = &u132->udev[address];
-		urb->hcpriv = u132;
-		if (udev->enumeration != 2)
-			udev->enumeration = 2;
-		if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
-			endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
-				urb;
-		} else {
-			struct u132_urbq *urbq =
-				kmalloc(sizeof(struct u132_urbq), GFP_ATOMIC);
-			if (urbq == NULL) {
-				endp->queue_size -= 1;
-				return -ENOMEM;
-			} else {
-				list_add_tail(&urbq->urb_more, &endp->urb_more);
-				urbq->urb = urb;
-			}
-		}
-		return 0;
-	}
-}
-
-static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
-		gfp_t mem_flags)
-{
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (irqs_disabled()) {
-		if (gfpflags_allow_blocking(mem_flags)) {
-			printk(KERN_ERR "invalid context for function that might sleep\n");
-			return -EINVAL;
-		}
-	}
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		return -ENODEV;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed "
-				"urb=%p\n", urb);
-		return -ESHUTDOWN;
-	} else {
-		u8 usb_addr = usb_pipedevice(urb->pipe);
-		u8 usb_endp = usb_pipeendpoint(urb->pipe);
-		struct usb_device *usb_dev = urb->dev;
-		if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
-			u8 address = u132->addr[usb_addr].address;
-			struct u132_udev *udev = &u132->udev[address];
-			struct u132_endp *endp = urb->ep->hcpriv;
-			urb->actual_length = 0;
-			if (endp) {
-				unsigned long irqs;
-				int retval;
-				spin_lock_irqsave(&endp->queue_lock.slock,
-					irqs);
-				retval = usb_hcd_link_urb_to_ep(hcd, urb);
-				if (retval == 0) {
-					retval = queue_int_on_old_endpoint(
-							u132, udev, urb,
-							usb_dev, endp,
-							usb_addr, usb_endp,
-							address);
-					if (retval)
-						usb_hcd_unlink_urb_from_ep(
-	hcd, urb);
-				}
-				spin_unlock_irqrestore(&endp->queue_lock.slock,
-					irqs);
-				if (retval) {
-					return retval;
-				} else {
-					u132_endp_queue_work(u132, endp,
-						msecs_to_jiffies(urb->interval))
-						;
-					return 0;
-				}
-			} else if (u132->num_endpoints == MAX_U132_ENDPS) {
-				return -EINVAL;
-			} else {	/*(endp == NULL) */
-				return create_endpoint_and_queue_int(u132, udev,
-						urb, usb_dev, usb_addr,
-						usb_endp, address, mem_flags);
-			}
-		} else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-			dev_err(&u132->platform_dev->dev, "the hardware does no"
-				"t support PIPE_ISOCHRONOUS\n");
-			return -EINVAL;
-		} else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
-			u8 address = u132->addr[usb_addr].address;
-			struct u132_udev *udev = &u132->udev[address];
-			struct u132_endp *endp = urb->ep->hcpriv;
-			urb->actual_length = 0;
-			if (endp) {
-				unsigned long irqs;
-				int retval;
-				spin_lock_irqsave(&endp->queue_lock.slock,
-					irqs);
-				retval = usb_hcd_link_urb_to_ep(hcd, urb);
-				if (retval == 0) {
-					retval = queue_bulk_on_old_endpoint(
-							u132, udev, urb,
-							usb_dev, endp,
-							usb_addr, usb_endp,
-							address);
-					if (retval)
-						usb_hcd_unlink_urb_from_ep(
-	hcd, urb);
-				}
-				spin_unlock_irqrestore(&endp->queue_lock.slock,
-					irqs);
-				if (retval) {
-					return retval;
-				} else {
-					u132_endp_queue_work(u132, endp, 0);
-					return 0;
-				}
-			} else if (u132->num_endpoints == MAX_U132_ENDPS) {
-				return -EINVAL;
-			} else
-				return create_endpoint_and_queue_bulk(u132,
-					udev, urb, usb_dev, usb_addr,
-					usb_endp, address, mem_flags);
-		} else {
-			struct u132_endp *endp = urb->ep->hcpriv;
-			u16 urb_size = 8;
-			u8 *b = urb->setup_packet;
-			int i = 0;
-			char data[30 * 3 + 4];
-			char *d = data;
-			int m = (sizeof(data) - 1) / 3;
-			int l = 0;
-			data[0] = 0;
-			while (urb_size-- > 0) {
-				if (i > m) {
-				} else if (i++ < m) {
-					int w = sprintf(d, " %02X", *b++);
-					d += w;
-					l += w;
-				} else
-					d += sprintf(d, " ..");
-			}
-			if (endp) {
-				unsigned long irqs;
-				int retval;
-				spin_lock_irqsave(&endp->queue_lock.slock,
-					irqs);
-				retval = usb_hcd_link_urb_to_ep(hcd, urb);
-				if (retval == 0) {
-					retval = queue_control_on_old_endpoint(
-							u132, urb, usb_dev,
-							endp, usb_addr,
-							usb_endp);
-					if (retval)
-						usb_hcd_unlink_urb_from_ep(
-								hcd, urb);
-				}
-				spin_unlock_irqrestore(&endp->queue_lock.slock,
-					irqs);
-				if (retval) {
-					return retval;
-				} else {
-					u132_endp_queue_work(u132, endp, 0);
-					return 0;
-				}
-			} else if (u132->num_endpoints == MAX_U132_ENDPS) {
-				return -EINVAL;
-			} else
-				return create_endpoint_and_queue_control(u132,
-					urb, usb_dev, usb_addr, usb_endp,
-					mem_flags);
-		}
-	}
-}
-
-static int dequeue_from_overflow_chain(struct u132 *u132,
-	struct u132_endp *endp, struct urb *urb)
-{
-	struct u132_urbq *urbq;
-
-	list_for_each_entry(urbq, &endp->urb_more, urb_more) {
-		if (urbq->urb == urb) {
-			struct usb_hcd *hcd = u132_to_hcd(u132);
-			list_del(&urbq->urb_more);
-			endp->queue_size -= 1;
-			urb->error_count = 0;
-			usb_hcd_giveback_urb(hcd, urb, 0);
-			return 0;
-		}
-	}
-	dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring"
-		"[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X"
-		"\n", urb, endp->endp_number, endp, endp->ring->number,
-		endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
-		endp->usb_endp, endp->usb_addr, endp->queue_size,
-		endp->queue_next, endp->queue_last);
-	return -EINVAL;
-}
-
-static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
-		struct urb *urb, int status)
-{
-	unsigned long irqs;
-	int rc;
-
-	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
-	rc = usb_hcd_check_unlink_urb(u132_to_hcd(u132), urb, status);
-	if (rc) {
-		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-		return rc;
-	}
-	if (endp->queue_size == 0) {
-		dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]"
-			"=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb,
-			endp->endp_number, endp, endp->ring->number,
-			endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
-			endp->usb_endp, endp->usb_addr);
-		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-		return -EINVAL;
-	}
-	if (urb == endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]) {
-		if (endp->active) {
-			endp->dequeueing = 1;
-			endp->edset_flush = 1;
-			u132_endp_queue_work(u132, endp, 0);
-			spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-			return 0;
-		} else {
-			spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-			u132_hcd_abandon_urb(u132, endp, urb, status);
-			return 0;
-		}
-	} else {
-		u16 queue_list = 0;
-		u16 queue_size = endp->queue_size;
-		u16 queue_scan = endp->queue_next;
-		struct urb **urb_slot = NULL;
-		while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
-			if (urb == endp->urb_list[ENDP_QUEUE_MASK &
-				++queue_scan]) {
-				urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
-					queue_scan];
-				break;
-			}
-		}
-		while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
-			*urb_slot = endp->urb_list[ENDP_QUEUE_MASK &
-				++queue_scan];
-			urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
-				queue_scan];
-		}
-		if (urb_slot) {
-			struct usb_hcd *hcd = u132_to_hcd(u132);
-
-			usb_hcd_unlink_urb_from_ep(hcd, urb);
-			endp->queue_size -= 1;
-			if (list_empty(&endp->urb_more)) {
-				spin_unlock_irqrestore(&endp->queue_lock.slock,
-					irqs);
-			} else {
-				struct list_head *next = endp->urb_more.next;
-				struct u132_urbq *urbq = list_entry(next,
-					struct u132_urbq, urb_more);
-				list_del(next);
-				*urb_slot = urbq->urb;
-				spin_unlock_irqrestore(&endp->queue_lock.slock,
-					irqs);
-				kfree(urbq);
-			}
-			urb->error_count = 0;
-			usb_hcd_giveback_urb(hcd, urb, status);
-			return 0;
-		} else if (list_empty(&endp->urb_more)) {
-			dev_err(&u132->platform_dev->dev, "urb=%p not found in "
-				"endp[%d]=%p ring[%d] %c%c usb_endp=%d usb_addr"
-				"=%d size=%d next=%04X last=%04X\n", urb,
-				endp->endp_number, endp, endp->ring->number,
-				endp->input ? 'I' : ' ',
-				endp->output ? 'O' : ' ', endp->usb_endp,
-				endp->usb_addr, endp->queue_size,
-				endp->queue_next, endp->queue_last);
-			spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-			return -EINVAL;
-		} else {
-			int retval;
-
-			usb_hcd_unlink_urb_from_ep(u132_to_hcd(u132), urb);
-			retval = dequeue_from_overflow_chain(u132, endp,
-				urb);
-			spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-			return retval;
-		}
-	}
-}
-
-static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
-{
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (u132->going > 2) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		return -ENODEV;
-	} else {
-		u8 usb_addr = usb_pipedevice(urb->pipe);
-		u8 usb_endp = usb_pipeendpoint(urb->pipe);
-		u8 address = u132->addr[usb_addr].address;
-		struct u132_udev *udev = &u132->udev[address];
-		if (usb_pipein(urb->pipe)) {
-			u8 endp_number = udev->endp_number_in[usb_endp];
-			struct u132_endp *endp = u132->endp[endp_number - 1];
-			return u132_endp_urb_dequeue(u132, endp, urb, status);
-		} else {
-			u8 endp_number = udev->endp_number_out[usb_endp];
-			struct u132_endp *endp = u132->endp[endp_number - 1];
-			return u132_endp_urb_dequeue(u132, endp, urb, status);
-		}
-	}
-}
-
-static void u132_endpoint_disable(struct usb_hcd *hcd,
-	struct usb_host_endpoint *hep)
-{
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (u132->going > 2) {
-		dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p"
-			") has been removed %d\n", u132, hcd, hep,
-			u132->going);
-	} else {
-		struct u132_endp *endp = hep->hcpriv;
-		if (endp)
-			u132_endp_put_kref(u132, endp);
-	}
-}
-
-static int u132_get_frame(struct usb_hcd *hcd)
-{
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		return -ENODEV;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
-		return -ESHUTDOWN;
-	} else {
-		dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n");
-		mdelay(100);
-		return 0;
-	}
-}
-
-static int u132_roothub_descriptor(struct u132 *u132,
-	struct usb_hub_descriptor *desc)
-{
-	int retval;
-	u16 temp;
-	u32 rh_a = -1;
-	u32 rh_b = -1;
-	retval = u132_read_pcimem(u132, roothub.a, &rh_a);
-	if (retval)
-		return retval;
-	desc->bDescriptorType = USB_DT_HUB;
-	desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24;
-	desc->bHubContrCurrent = 0;
-	desc->bNbrPorts = u132->num_ports;
-	temp = 1 + (u132->num_ports / 8);
-	desc->bDescLength = 7 + 2 * temp;
-	temp = HUB_CHAR_COMMON_LPSM | HUB_CHAR_COMMON_OCPM;
-	if (rh_a & RH_A_NPS)
-		temp |= HUB_CHAR_NO_LPSM;
-	if (rh_a & RH_A_PSM)
-		temp |= HUB_CHAR_INDV_PORT_LPSM;
-	if (rh_a & RH_A_NOCP)
-		temp |= HUB_CHAR_NO_OCPM;
-	else if (rh_a & RH_A_OCPM)
-		temp |= HUB_CHAR_INDV_PORT_OCPM;
-	desc->wHubCharacteristics = cpu_to_le16(temp);
-	retval = u132_read_pcimem(u132, roothub.b, &rh_b);
-	if (retval)
-		return retval;
-	memset(desc->u.hs.DeviceRemovable, 0xff,
-			sizeof(desc->u.hs.DeviceRemovable));
-	desc->u.hs.DeviceRemovable[0] = rh_b & RH_B_DR;
-	if (u132->num_ports > 7) {
-		desc->u.hs.DeviceRemovable[1] = (rh_b & RH_B_DR) >> 8;
-		desc->u.hs.DeviceRemovable[2] = 0xff;
-	} else
-		desc->u.hs.DeviceRemovable[1] = 0xff;
-	return 0;
-}
-
-static int u132_roothub_status(struct u132 *u132, __le32 *desc)
-{
-	u32 rh_status = -1;
-	int ret_status = u132_read_pcimem(u132, roothub.status, &rh_status);
-	*desc = cpu_to_le32(rh_status);
-	return ret_status;
-}
-
-static int u132_roothub_portstatus(struct u132 *u132, __le32 *desc, u16 wIndex)
-{
-	if (wIndex == 0 || wIndex > u132->num_ports) {
-		return -EINVAL;
-	} else {
-		int port = wIndex - 1;
-		u32 rh_portstatus = -1;
-		int ret_portstatus = u132_read_pcimem(u132,
-			roothub.portstatus[port], &rh_portstatus);
-		*desc = cpu_to_le32(rh_portstatus);
-		if (*(u16 *) (desc + 2)) {
-			dev_info(&u132->platform_dev->dev, "Port %d Status Chan"
-				"ge = %08X\n", port, *desc);
-		}
-		return ret_portstatus;
-	}
-}
-
-
-/* this timer value might be vendor-specific ... */
-#define PORT_RESET_HW_MSEC 10
-#define PORT_RESET_MSEC 10
-/* wrap-aware logic morphed from <linux/jiffies.h> */
-#define tick_before(t1, t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
-static int u132_roothub_portreset(struct u132 *u132, int port_index)
-{
-	int retval;
-	u32 fmnumber;
-	u16 now;
-	u16 reset_done;
-	retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
-	if (retval)
-		return retval;
-	now = fmnumber;
-	reset_done = now + PORT_RESET_MSEC;
-	do {
-		u32 portstat;
-		do {
-			retval = u132_read_pcimem(u132,
-				roothub.portstatus[port_index], &portstat);
-			if (retval)
-				return retval;
-			if (RH_PS_PRS & portstat)
-				continue;
-			else
-				break;
-		} while (tick_before(now, reset_done));
-		if (RH_PS_PRS & portstat)
-			return -ENODEV;
-		if (RH_PS_CCS & portstat) {
-			if (RH_PS_PRSC & portstat) {
-				retval = u132_write_pcimem(u132,
-					roothub.portstatus[port_index],
-					RH_PS_PRSC);
-				if (retval)
-					return retval;
-			}
-		} else
-			break;	/* start the next reset,
-				sleep till it's probably done */
-		retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
-			 RH_PS_PRS);
-		if (retval)
-			return retval;
-		msleep(PORT_RESET_HW_MSEC);
-		retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
-		if (retval)
-			return retval;
-		now = fmnumber;
-	} while (tick_before(now, reset_done));
-	return 0;
-}
-
-static int u132_roothub_setportfeature(struct u132 *u132, u16 wValue,
-	u16 wIndex)
-{
-	if (wIndex == 0 || wIndex > u132->num_ports) {
-		return -EINVAL;
-	} else {
-		int port_index = wIndex - 1;
-		struct u132_port *port = &u132->port[port_index];
-		port->Status &= ~(1 << wValue);
-		switch (wValue) {
-		case USB_PORT_FEAT_SUSPEND:
-			return u132_write_pcimem(u132,
-			       roothub.portstatus[port_index], RH_PS_PSS);
-		case USB_PORT_FEAT_POWER:
-			return u132_write_pcimem(u132,
-			       roothub.portstatus[port_index], RH_PS_PPS);
-		case USB_PORT_FEAT_RESET:
-			return u132_roothub_portreset(u132, port_index);
-		default:
-			return -EPIPE;
-		}
-	}
-}
-
-static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue,
-	u16 wIndex)
-{
-	if (wIndex == 0 || wIndex > u132->num_ports) {
-		return -EINVAL;
-	} else {
-		int port_index = wIndex - 1;
-		u32 temp;
-		struct u132_port *port = &u132->port[port_index];
-		port->Status &= ~(1 << wValue);
-		switch (wValue) {
-		case USB_PORT_FEAT_ENABLE:
-			temp = RH_PS_CCS;
-			break;
-		case USB_PORT_FEAT_C_ENABLE:
-			temp = RH_PS_PESC;
-			break;
-		case USB_PORT_FEAT_SUSPEND:
-			temp = RH_PS_POCI;
-			if ((u132->hc_control & OHCI_CTRL_HCFS)
-				!= OHCI_USB_OPER) {
-				dev_err(&u132->platform_dev->dev, "TODO resume_"
-					"root_hub\n");
-			}
-			break;
-		case USB_PORT_FEAT_C_SUSPEND:
-			temp = RH_PS_PSSC;
-			break;
-		case USB_PORT_FEAT_POWER:
-			temp = RH_PS_LSDA;
-			break;
-		case USB_PORT_FEAT_C_CONNECTION:
-			temp = RH_PS_CSC;
-			break;
-		case USB_PORT_FEAT_C_OVER_CURRENT:
-			temp = RH_PS_OCIC;
-			break;
-		case USB_PORT_FEAT_C_RESET:
-			temp = RH_PS_PRSC;
-			break;
-		default:
-			return -EPIPE;
-		}
-		return u132_write_pcimem(u132, roothub.portstatus[port_index],
-		       temp);
-	}
-}
-
-
-/* the virtual root hub timer IRQ checks for hub status*/
-static int u132_hub_status_data(struct usb_hcd *hcd, char *buf)
-{
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device hcd=%p has been remov"
-			"ed %d\n", hcd, u132->going);
-		return -ENODEV;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
-			"ed\n", hcd);
-		return -ESHUTDOWN;
-	} else {
-		int i, changed = 0, length = 1;
-		if (u132->flags & OHCI_QUIRK_AMD756) {
-			if ((u132->hc_roothub_a & RH_A_NDP) > MAX_ROOT_PORTS) {
-				dev_err(&u132->platform_dev->dev, "bogus NDP, r"
-					"ereads as NDP=%d\n",
-					u132->hc_roothub_a & RH_A_NDP);
-				goto done;
-			}
-		}
-		if (u132->hc_roothub_status & (RH_HS_LPSC | RH_HS_OCIC))
-			buf[0] = changed = 1;
-		else
-			buf[0] = 0;
-		if (u132->num_ports > 7) {
-			buf[1] = 0;
-			length++;
-		}
-		for (i = 0; i < u132->num_ports; i++) {
-			if (u132->hc_roothub_portstatus[i] & (RH_PS_CSC |
-				RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC |
-				RH_PS_PRSC)) {
-				changed = 1;
-				if (i < 7)
-					buf[0] |= 1 << (i + 1);
-				else
-					buf[1] |= 1 << (i - 7);
-				continue;
-			}
-			if (!(u132->hc_roothub_portstatus[i] & RH_PS_CCS))
-				continue;
-
-			if ((u132->hc_roothub_portstatus[i] & RH_PS_PSS))
-				continue;
-		}
-done:
-		return changed ? length : 0;
-	}
-}
-
-static int u132_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
-	u16 wIndex, char *buf, u16 wLength)
-{
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		return -ENODEV;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
-		return -ESHUTDOWN;
-	} else {
-		int retval = 0;
-		mutex_lock(&u132->sw_lock);
-		switch (typeReq) {
-		case ClearHubFeature:
-			switch (wValue) {
-			case C_HUB_OVER_CURRENT:
-			case C_HUB_LOCAL_POWER:
-				break;
-			default:
-				goto stall;
-			}
-			break;
-		case SetHubFeature:
-			switch (wValue) {
-			case C_HUB_OVER_CURRENT:
-			case C_HUB_LOCAL_POWER:
-				break;
-			default:
-				goto stall;
-			}
-			break;
-		case ClearPortFeature:{
-				retval = u132_roothub_clearportfeature(u132,
-					wValue, wIndex);
-				if (retval)
-					goto error;
-				break;
-			}
-		case GetHubDescriptor:{
-				retval = u132_roothub_descriptor(u132,
-					(struct usb_hub_descriptor *)buf);
-				if (retval)
-					goto error;
-				break;
-			}
-		case GetHubStatus:{
-				retval = u132_roothub_status(u132,
-					(__le32 *) buf);
-				if (retval)
-					goto error;
-				break;
-			}
-		case GetPortStatus:{
-				retval = u132_roothub_portstatus(u132,
-					(__le32 *) buf, wIndex);
-				if (retval)
-					goto error;
-				break;
-			}
-		case SetPortFeature:{
-				retval = u132_roothub_setportfeature(u132,
-					wValue, wIndex);
-				if (retval)
-					goto error;
-				break;
-			}
-		default:
-			goto stall;
-		error:
-			u132_disable(u132);
-			u132->going = 1;
-			break;
-		stall:
-			retval = -EPIPE;
-			break;
-		}
-		mutex_unlock(&u132->sw_lock);
-		return retval;
-	}
-}
-
-static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
-{
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		return -ENODEV;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
-		return -ESHUTDOWN;
-	} else
-		return 0;
-}
-
-
-#ifdef CONFIG_PM
-static int u132_bus_suspend(struct usb_hcd *hcd)
-{
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		return -ENODEV;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
-		return -ESHUTDOWN;
-	} else
-		return 0;
-}
-
-static int u132_bus_resume(struct usb_hcd *hcd)
-{
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		return -ENODEV;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
-		return -ESHUTDOWN;
-	} else
-		return 0;
-}
-
-#else
-#define u132_bus_suspend NULL
-#define u132_bus_resume NULL
-#endif
-static const struct hc_driver u132_hc_driver = {
-	.description = hcd_name,
-	.hcd_priv_size = sizeof(struct u132),
-	.irq = NULL,
-	.flags = HCD_USB11 | HCD_MEMORY,
-	.reset = u132_hcd_reset,
-	.start = u132_hcd_start,
-	.stop = u132_hcd_stop,
-	.urb_enqueue = u132_urb_enqueue,
-	.urb_dequeue = u132_urb_dequeue,
-	.endpoint_disable = u132_endpoint_disable,
-	.get_frame_number = u132_get_frame,
-	.hub_status_data = u132_hub_status_data,
-	.hub_control = u132_hub_control,
-	.bus_suspend = u132_bus_suspend,
-	.bus_resume = u132_bus_resume,
-	.start_port_reset = u132_start_port_reset,
-};
-
-/*
-* This function may be called by the USB core whilst the "usb_all_devices_rwsem"
-* is held for writing, thus this module must not call usb_remove_hcd()
-* synchronously - but instead should immediately stop activity to the
-* device and asynchronously call usb_remove_hcd()
-*/
-static int u132_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-	if (hcd) {
-		struct u132 *u132 = hcd_to_u132(hcd);
-		if (u132->going++ > 1) {
-			dev_err(&u132->platform_dev->dev, "already being remove"
-				"d\n");
-			return -ENODEV;
-		} else {
-			int rings = MAX_U132_RINGS;
-			int endps = MAX_U132_ENDPS;
-			dev_err(&u132->platform_dev->dev, "removing device u132"
-				".%d\n", u132->sequence_num);
-			msleep(100);
-			mutex_lock(&u132->sw_lock);
-			u132_monitor_cancel_work(u132);
-			while (rings-- > 0) {
-				struct u132_ring *ring = &u132->ring[rings];
-				u132_ring_cancel_work(u132, ring);
-			}
-			while (endps-- > 0) {
-				struct u132_endp *endp = u132->endp[endps];
-				if (endp)
-					u132_endp_cancel_work(u132, endp);
-			}
-			u132->going += 1;
-			printk(KERN_INFO "removing device u132.%d\n",
-				u132->sequence_num);
-			mutex_unlock(&u132->sw_lock);
-			usb_remove_hcd(hcd);
-			u132_u132_put_kref(u132);
-			return 0;
-		}
-	} else
-		return 0;
-}
-
-static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
-{
-	int rings = MAX_U132_RINGS;
-	int ports = MAX_U132_PORTS;
-	int addrs = MAX_U132_ADDRS;
-	int udevs = MAX_U132_UDEVS;
-	int endps = MAX_U132_ENDPS;
-	u132->board = dev_get_platdata(&pdev->dev);
-	u132->platform_dev = pdev;
-	u132->power = 0;
-	u132->reset = 0;
-	mutex_init(&u132->sw_lock);
-	mutex_init(&u132->scheduler_lock);
-	while (rings-- > 0) {
-		struct u132_ring *ring = &u132->ring[rings];
-		ring->u132 = u132;
-		ring->number = rings + 1;
-		ring->length = 0;
-		ring->curr_endp = NULL;
-		INIT_DELAYED_WORK(&ring->scheduler,
-				  u132_hcd_ring_work_scheduler);
-	}
-	mutex_lock(&u132->sw_lock);
-	INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work);
-	while (ports-- > 0) {
-		struct u132_port *port = &u132->port[ports];
-		port->u132 = u132;
-		port->reset = 0;
-		port->enable = 0;
-		port->power = 0;
-		port->Status = 0;
-	}
-	while (addrs-- > 0) {
-		struct u132_addr *addr = &u132->addr[addrs];
-		addr->address = 0;
-	}
-	while (udevs-- > 0) {
-		struct u132_udev *udev = &u132->udev[udevs];
-		int i = ARRAY_SIZE(udev->endp_number_in);
-		int o = ARRAY_SIZE(udev->endp_number_out);
-		udev->usb_device = NULL;
-		udev->udev_number = 0;
-		udev->usb_addr = 0;
-		udev->portnumber = 0;
-		while (i-- > 0)
-			udev->endp_number_in[i] = 0;
-
-		while (o-- > 0)
-			udev->endp_number_out[o] = 0;
-
-	}
-	while (endps-- > 0)
-		u132->endp[endps] = NULL;
-
-	mutex_unlock(&u132->sw_lock);
-}
-
-static int u132_probe(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd;
-	int retval;
-	u32 control;
-	u32 rh_a = -1;
-
-	msleep(100);
-	if (u132_exiting > 0)
-		return -ENODEV;
-
-	retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE);
-	if (retval)
-		return retval;
-	retval = ftdi_read_pcimem(pdev, control, &control);
-	if (retval)
-		return retval;
-	retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a);
-	if (retval)
-		return retval;
-
-	hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, dev_name(&pdev->dev));
-	if (!hcd) {
-		printk(KERN_ERR "failed to create the usb hcd struct for U132\n"
-			);
-		ftdi_elan_gone_away(pdev);
-		return -ENOMEM;
-	} else {
-		struct u132 *u132 = hcd_to_u132(hcd);
-		retval = 0;
-		hcd->rsrc_start = 0;
-		mutex_lock(&u132_module_lock);
-		u132->sequence_num = ++u132_instances;
-		mutex_unlock(&u132_module_lock);
-		u132_u132_init_kref(u132);
-		u132_initialise(u132, pdev);
-		hcd->product_desc = "ELAN U132 Host Controller";
-		retval = usb_add_hcd(hcd, 0, 0);
-		if (retval != 0) {
-			dev_err(&u132->platform_dev->dev, "init error %d\n",
-				retval);
-			u132_u132_put_kref(u132);
-			return retval;
-		} else {
-			device_wakeup_enable(hcd->self.controller);
-			u132_monitor_queue_work(u132, 100);
-			return 0;
-		}
-	}
-}
-
-
-#ifdef CONFIG_PM
-/*
- * for this device there's no useful distinction between the controller
- * and its root hub.
- */
-static int u132_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		return -ENODEV;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
-		return -ESHUTDOWN;
-	} else {
-		int retval = 0, ports;
-
-		switch (state.event) {
-		case PM_EVENT_FREEZE:
-			retval = u132_bus_suspend(hcd);
-			break;
-		case PM_EVENT_SUSPEND:
-		case PM_EVENT_HIBERNATE:
-			ports = MAX_U132_PORTS;
-			while (ports-- > 0) {
-				port_power(u132, ports, 0);
-			}
-			break;
-		}
-		return retval;
-	}
-}
-
-static int u132_resume(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-		return -ENODEV;
-	} else if (u132->going > 0) {
-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
-		return -ESHUTDOWN;
-	} else {
-		int retval = 0;
-		if (!u132->port[0].power) {
-			int ports = MAX_U132_PORTS;
-			while (ports-- > 0) {
-				port_power(u132, ports, 1);
-			}
-			retval = 0;
-		} else {
-			retval = u132_bus_resume(hcd);
-		}
-		return retval;
-	}
-}
-
-#else
-#define u132_suspend NULL
-#define u132_resume NULL
-#endif
-/*
-* this driver is loaded explicitly by ftdi_u132
-*
-* the platform_driver struct is static because it is per type of module
-*/
-static struct platform_driver u132_platform_driver = {
-	.probe = u132_probe,
-	.remove = u132_remove,
-	.suspend = u132_suspend,
-	.resume = u132_resume,
-	.driver = {
-		   .name = hcd_name,
-		   },
-};
-static int __init u132_hcd_init(void)
-{
-	int retval;
-	u132_instances = 0;
-	u132_exiting = 0;
-	if (usb_disabled())
-		return -ENODEV;
-	workqueue = create_singlethread_workqueue("u132");
-	if (!workqueue)
-		return -ENOMEM;
-	retval = platform_driver_register(&u132_platform_driver);
-	if (retval)
-		destroy_workqueue(workqueue);
-
-	return retval;
-}
-
-
-module_init(u132_hcd_init);
-static void __exit u132_hcd_exit(void)
-{
-	mutex_lock(&u132_module_lock);
-	u132_exiting += 1;
-	mutex_unlock(&u132_module_lock);
-	platform_driver_unregister(&u132_platform_driver);
-	printk(KERN_INFO "u132-hcd driver deregistered\n");
-	wait_event(u132_hcd_wait, u132_instances == 0);
-	destroy_workqueue(workqueue);
-}
-
-
-module_exit(u132_hcd_exit);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:u132_hcd");
diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c
index f1367b53b2600934d922d5127e0268547eee269b..b40d9238d4471494bf47249bff907bbcf8e2f209 100644
--- a/drivers/usb/host/xhci-dbgcap.c
+++ b/drivers/usb/host/xhci-dbgcap.c
@@ -124,10 +124,10 @@ static void xhci_dbc_init_contexts(struct xhci_dbc *dbc, u32 string_length)
 	/* Set DbC context and info registers: */
 	lo_hi_writeq(dbc->ctx->dma, &dbc->regs->dccp);
 
-	dev_info = cpu_to_le32((DBC_VENDOR_ID << 16) | DBC_PROTOCOL);
+	dev_info = (dbc->idVendor << 16) | dbc->bInterfaceProtocol;
 	writel(dev_info, &dbc->regs->devinfo1);
 
-	dev_info = cpu_to_le32((DBC_DEVICE_REV << 16) | DBC_PRODUCT_ID);
+	dev_info = (dbc->bcdDevice << 16) | dbc->idProduct;
 	writel(dev_info, &dbc->regs->devinfo2);
 }
 
@@ -971,7 +971,186 @@ static ssize_t dbc_store(struct device *dev,
 	return count;
 }
 
+static ssize_t dbc_idVendor_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	struct xhci_dbc		*dbc;
+	struct xhci_hcd		*xhci;
+
+	xhci = hcd_to_xhci(dev_get_drvdata(dev));
+	dbc = xhci->dbc;
+
+	return sprintf(buf, "%04x\n", dbc->idVendor);
+}
+
+static ssize_t dbc_idVendor_store(struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buf, size_t size)
+{
+	struct xhci_dbc		*dbc;
+	struct xhci_hcd		*xhci;
+	void __iomem		*ptr;
+	u16			value;
+	u32			dev_info;
+
+	if (kstrtou16(buf, 0, &value))
+		return -EINVAL;
+
+	xhci = hcd_to_xhci(dev_get_drvdata(dev));
+	dbc = xhci->dbc;
+	if (dbc->state != DS_DISABLED)
+		return -EBUSY;
+
+	dbc->idVendor = value;
+	ptr = &dbc->regs->devinfo1;
+	dev_info = readl(ptr);
+	dev_info = (dev_info & ~(0xffffu << 16)) | (value << 16);
+	writel(dev_info, ptr);
+
+	return size;
+}
+
+static ssize_t dbc_idProduct_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	struct xhci_dbc         *dbc;
+	struct xhci_hcd         *xhci;
+
+	xhci = hcd_to_xhci(dev_get_drvdata(dev));
+	dbc = xhci->dbc;
+
+	return sprintf(buf, "%04x\n", dbc->idProduct);
+}
+
+static ssize_t dbc_idProduct_store(struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buf, size_t size)
+{
+	struct xhci_dbc         *dbc;
+	struct xhci_hcd         *xhci;
+	void __iomem		*ptr;
+	u32			dev_info;
+	u16			value;
+
+	if (kstrtou16(buf, 0, &value))
+		return -EINVAL;
+
+	xhci = hcd_to_xhci(dev_get_drvdata(dev));
+	dbc = xhci->dbc;
+	if (dbc->state != DS_DISABLED)
+		return -EBUSY;
+
+	dbc->idProduct = value;
+	ptr = &dbc->regs->devinfo2;
+	dev_info = readl(ptr);
+	dev_info = (dev_info & ~(0xffffu)) | value;
+	writel(dev_info, ptr);
+	return size;
+}
+
+static ssize_t dbc_bcdDevice_show(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf)
+{
+	struct xhci_dbc	*dbc;
+	struct xhci_hcd	*xhci;
+
+	xhci = hcd_to_xhci(dev_get_drvdata(dev));
+	dbc = xhci->dbc;
+
+	return sprintf(buf, "%04x\n", dbc->bcdDevice);
+}
+
+static ssize_t dbc_bcdDevice_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t size)
+{
+	struct xhci_dbc	*dbc;
+	struct xhci_hcd	*xhci;
+	void __iomem *ptr;
+	u32 dev_info;
+	u16 value;
+
+	if (kstrtou16(buf, 0, &value))
+		return -EINVAL;
+
+	xhci = hcd_to_xhci(dev_get_drvdata(dev));
+	dbc = xhci->dbc;
+	if (dbc->state != DS_DISABLED)
+		return -EBUSY;
+
+	dbc->bcdDevice = value;
+	ptr = &dbc->regs->devinfo2;
+	dev_info = readl(ptr);
+	dev_info = (dev_info & ~(0xffffu << 16)) | (value << 16);
+	writel(dev_info, ptr);
+
+	return size;
+}
+
+static ssize_t dbc_bInterfaceProtocol_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct xhci_dbc	*dbc;
+	struct xhci_hcd	*xhci;
+
+	xhci = hcd_to_xhci(dev_get_drvdata(dev));
+	dbc = xhci->dbc;
+
+	return sprintf(buf, "%02x\n", dbc->bInterfaceProtocol);
+}
+
+static ssize_t dbc_bInterfaceProtocol_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t size)
+{
+	struct xhci_dbc *dbc;
+	struct xhci_hcd *xhci;
+	void __iomem *ptr;
+	u32 dev_info;
+	u8 value;
+	int ret;
+
+	/* bInterfaceProtocol is 8 bit, but xhci only supports values 0 and 1 */
+	ret = kstrtou8(buf, 0, &value);
+	if (ret || value > 1)
+		return -EINVAL;
+
+	xhci = hcd_to_xhci(dev_get_drvdata(dev));
+	dbc = xhci->dbc;
+	if (dbc->state != DS_DISABLED)
+		return -EBUSY;
+
+	dbc->bInterfaceProtocol = value;
+	ptr = &dbc->regs->devinfo1;
+	dev_info = readl(ptr);
+	dev_info = (dev_info & ~(0xffu)) | value;
+	writel(dev_info, ptr);
+
+	return size;
+}
+
 static DEVICE_ATTR_RW(dbc);
+static DEVICE_ATTR_RW(dbc_idVendor);
+static DEVICE_ATTR_RW(dbc_idProduct);
+static DEVICE_ATTR_RW(dbc_bcdDevice);
+static DEVICE_ATTR_RW(dbc_bInterfaceProtocol);
+
+static struct attribute *dbc_dev_attributes[] = {
+	&dev_attr_dbc.attr,
+	&dev_attr_dbc_idVendor.attr,
+	&dev_attr_dbc_idProduct.attr,
+	&dev_attr_dbc_bcdDevice.attr,
+	&dev_attr_dbc_bInterfaceProtocol.attr,
+	NULL
+};
+
+static const struct attribute_group dbc_dev_attrib_grp = {
+	.attrs = dbc_dev_attributes,
+};
 
 struct xhci_dbc *
 xhci_alloc_dbc(struct device *dev, void __iomem *base, const struct dbc_driver *driver)
@@ -986,6 +1165,10 @@ xhci_alloc_dbc(struct device *dev, void __iomem *base, const struct dbc_driver *
 	dbc->regs = base;
 	dbc->dev = dev;
 	dbc->driver = driver;
+	dbc->idProduct = DBC_PRODUCT_ID;
+	dbc->idVendor = DBC_VENDOR_ID;
+	dbc->bcdDevice = DBC_DEVICE_REV;
+	dbc->bInterfaceProtocol = DBC_PROTOCOL;
 
 	if (readl(&dbc->regs->control) & DBC_CTRL_DBC_ENABLE)
 		goto err;
@@ -993,7 +1176,7 @@ xhci_alloc_dbc(struct device *dev, void __iomem *base, const struct dbc_driver *
 	INIT_DELAYED_WORK(&dbc->event_work, xhci_dbc_handle_events);
 	spin_lock_init(&dbc->lock);
 
-	ret = device_create_file(dev, &dev_attr_dbc);
+	ret = sysfs_create_group(&dev->kobj, &dbc_dev_attrib_grp);
 	if (ret)
 		goto err;
 
@@ -1012,7 +1195,7 @@ void xhci_dbc_remove(struct xhci_dbc *dbc)
 	xhci_dbc_stop(dbc);
 
 	/* remove sysfs files */
-	device_remove_file(dbc->dev, &dev_attr_dbc);
+	sysfs_remove_group(&dbc->dev->kobj, &dbc_dev_attrib_grp);
 
 	kfree(dbc);
 }
diff --git a/drivers/usb/host/xhci-dbgcap.h b/drivers/usb/host/xhci-dbgcap.h
index ca04192fdab1d94a703e5d9fbd3d996aa95ee9a4..51a7ab3ba0cac0297c4576d295b6c49551dd2d6c 100644
--- a/drivers/usb/host/xhci-dbgcap.h
+++ b/drivers/usb/host/xhci-dbgcap.h
@@ -132,6 +132,10 @@ struct xhci_dbc {
 	struct dbc_str_descs		*string;
 	dma_addr_t			string_dma;
 	size_t				string_size;
+	u16				idVendor;
+	u16				idProduct;
+	u16				bcdDevice;
+	u8				bInterfaceProtocol;
 
 	enum dbc_state			state;
 	struct delayed_work		event_work;
diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c
index 0bc7fe11f749edd0f2eb15cfd59aad765f47bdfe..99baa60ef50fe954ede2dd593b7a66004b6647e6 100644
--- a/drivers/usb/host/xhci-debugfs.c
+++ b/drivers/usb/host/xhci-debugfs.c
@@ -133,6 +133,7 @@ static void xhci_debugfs_regset(struct xhci_hcd *xhci, u32 base,
 	regset->regs = regs;
 	regset->nregs = nregs;
 	regset->base = hcd->regs + base;
+	regset->dev = hcd->self.controller;
 
 	debugfs_create_regset32((const char *)rgs->name, 0444, parent, regset);
 }
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index d0a9467aa5fc400d41fd7f1761d49142f5925563..7e106bd804ca1a43c2fb489da4e2e634ffc66a90 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/usb.h>
+#include <linux/overflow.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/dmapool.h>
@@ -543,14 +544,11 @@ static void xhci_free_stream_ctx(struct xhci_hcd *xhci,
 	size_t size = sizeof(struct xhci_stream_ctx) * num_stream_ctxs;
 
 	if (size > MEDIUM_STREAM_ARRAY_SIZE)
-		dma_free_coherent(dev, size,
-				stream_ctx, dma);
-	else if (size <= SMALL_STREAM_ARRAY_SIZE)
-		return dma_pool_free(xhci->small_streams_pool,
-				stream_ctx, dma);
+		dma_free_coherent(dev, size, stream_ctx, dma);
+	else if (size > SMALL_STREAM_ARRAY_SIZE)
+		dma_pool_free(xhci->medium_streams_pool, stream_ctx, dma);
 	else
-		return dma_pool_free(xhci->medium_streams_pool,
-				stream_ctx, dma);
+		dma_pool_free(xhci->small_streams_pool, stream_ctx, dma);
 }
 
 /*
@@ -568,17 +566,14 @@ static struct xhci_stream_ctx *xhci_alloc_stream_ctx(struct xhci_hcd *xhci,
 		gfp_t mem_flags)
 {
 	struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
-	size_t size = sizeof(struct xhci_stream_ctx) * num_stream_ctxs;
+	size_t size = size_mul(sizeof(struct xhci_stream_ctx), num_stream_ctxs);
 
 	if (size > MEDIUM_STREAM_ARRAY_SIZE)
-		return dma_alloc_coherent(dev, size,
-				dma, mem_flags);
-	else if (size <= SMALL_STREAM_ARRAY_SIZE)
-		return dma_pool_alloc(xhci->small_streams_pool,
-				mem_flags, dma);
+		return dma_alloc_coherent(dev, size, dma, mem_flags);
+	if (size > SMALL_STREAM_ARRAY_SIZE)
+		return dma_pool_zalloc(xhci->medium_streams_pool, mem_flags, dma);
 	else
-		return dma_pool_alloc(xhci->medium_streams_pool,
-				mem_flags, dma);
+		return dma_pool_zalloc(xhci->small_streams_pool, mem_flags, dma);
 }
 
 struct xhci_ring *xhci_dma_to_transfer_ring(
@@ -612,8 +607,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
 	int ret;
 	struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
 
-	xhci_dbg(xhci, "Allocating %u streams and %u "
-			"stream context array entries.\n",
+	xhci_dbg(xhci, "Allocating %u streams and %u stream context array entries.\n",
 			num_streams, num_stream_ctxs);
 	if (xhci->cmd_ring_reserved_trbs == MAX_RSVD_CMD_TRBS) {
 		xhci_dbg(xhci, "Command ring has no reserved TRBs available\n");
@@ -642,8 +636,6 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
 			mem_flags);
 	if (!stream_info->stream_ctx_array)
 		goto cleanup_ring_array;
-	memset(stream_info->stream_ctx_array, 0,
-			sizeof(struct xhci_stream_ctx)*num_stream_ctxs);
 
 	/* Allocate everything needed to free the stream rings later */
 	stream_info->free_streams_command =
@@ -673,8 +665,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
 			cur_ring->cycle_state;
 		stream_info->stream_ctx_array[cur_stream].stream_ring =
 			cpu_to_le64(addr);
-		xhci_dbg(xhci, "Setting stream %d ring ptr to 0x%08llx\n",
-				cur_stream, (unsigned long long) addr);
+		xhci_dbg(xhci, "Setting stream %d ring ptr to 0x%08llx\n", cur_stream, addr);
 
 		ret = xhci_update_stream_mapping(cur_ring, mem_flags);
 		if (ret) {
@@ -984,16 +975,14 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
 	if (!dev->out_ctx)
 		goto fail;
 
-	xhci_dbg(xhci, "Slot %d output ctx = 0x%llx (dma)\n", slot_id,
-			(unsigned long long)dev->out_ctx->dma);
+	xhci_dbg(xhci, "Slot %d output ctx = 0x%pad (dma)\n", slot_id, &dev->out_ctx->dma);
 
 	/* Allocate the (input) device context for address device command */
 	dev->in_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_INPUT, flags);
 	if (!dev->in_ctx)
 		goto fail;
 
-	xhci_dbg(xhci, "Slot %d input ctx = 0x%llx (dma)\n", slot_id,
-			(unsigned long long)dev->in_ctx->dma);
+	xhci_dbg(xhci, "Slot %d input ctx = 0x%pad (dma)\n", slot_id, &dev->in_ctx->dma);
 
 	/* Initialize the cancellation and bandwidth list for each ep */
 	for (i = 0; i < 31; i++) {
@@ -1400,8 +1389,9 @@ static u32 xhci_get_max_esit_payload(struct usb_device *udev,
 	if ((udev->speed >= USB_SPEED_SUPER_PLUS) &&
 	    USB_SS_SSP_ISOC_COMP(ep->ss_ep_comp.bmAttributes))
 		return le32_to_cpu(ep->ssp_isoc_ep_comp.dwBytesPerInterval);
+
 	/* SuperSpeed or SuperSpeedPlus Isoc ep with less than 48k per esit */
-	else if (udev->speed >= USB_SPEED_SUPER)
+	if (udev->speed >= USB_SPEED_SUPER)
 		return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
 
 	max_packet = usb_endpoint_maxp(&ep->desc);
@@ -1660,7 +1650,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
 		goto fail_sp;
 
 	xhci->scratchpad->sp_array = dma_alloc_coherent(dev,
-				     num_sp * sizeof(u64),
+				     size_mul(sizeof(u64), num_sp),
 				     &xhci->scratchpad->sp_dma, flags);
 	if (!xhci->scratchpad->sp_array)
 		goto fail_sp2;
@@ -1685,11 +1675,10 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
 	return 0;
 
  fail_sp4:
-	for (i = i - 1; i >= 0; i--) {
+	while (i--)
 		dma_free_coherent(dev, xhci->page_size,
 				    xhci->scratchpad->sp_buffers[i],
 				    xhci->scratchpad->sp_array[i]);
-	}
 
 	kfree(xhci->scratchpad->sp_buffers);
 
@@ -1799,7 +1788,7 @@ int xhci_alloc_erst(struct xhci_hcd *xhci,
 	struct xhci_segment *seg;
 	struct xhci_erst_entry *entry;
 
-	size = sizeof(struct xhci_erst_entry) * evt_ring->num_segs;
+	size = size_mul(sizeof(struct xhci_erst_entry), evt_ring->num_segs);
 	erst->entries = dma_alloc_coherent(xhci_to_hcd(xhci)->self.sysdev,
 					   size, &erst->erst_dma_addr, flags);
 	if (!erst->entries)
@@ -1830,7 +1819,7 @@ xhci_free_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
 	if (!ir)
 		return;
 
-	erst_size = sizeof(struct xhci_erst_entry) * (ir->erst.num_entries);
+	erst_size = sizeof(struct xhci_erst_entry) * ir->erst.num_entries;
 	if (ir->erst.entries)
 		dma_free_coherent(dev, erst_size,
 				  ir->erst.entries,
@@ -1960,8 +1949,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci, struct xhci_interrupter
 	deq = xhci_trb_virt_to_dma(ir->event_ring->deq_seg,
 			ir->event_ring->dequeue);
 	if (!deq)
-		xhci_warn(xhci, "WARN something wrong with SW event ring "
-				"dequeue ptr.\n");
+		xhci_warn(xhci, "WARN something wrong with SW event ring dequeue ptr.\n");
 	/* Update HC event ring dequeue pointer */
 	temp = xhci_read_64(xhci, &ir->ir_set->erst_dequeue);
 	temp &= ERST_PTR_MASK;
@@ -1970,8 +1958,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci, struct xhci_interrupter
 	 */
 	temp &= ~ERST_EHB;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-			"// Write event ring dequeue pointer, "
-			"preserving EHB bit");
+		       "// Write event ring dequeue pointer, preserving EHB bit");
 	xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
 			&ir->ir_set->erst_dequeue);
 }
@@ -2004,8 +1991,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
 	} else if (major_revision <= 0x02) {
 		rhub = &xhci->usb2_rhub;
 	} else {
-		xhci_warn(xhci, "Ignoring unknown port speed, "
-				"Ext Cap %p, revision = 0x%x\n",
+		xhci_warn(xhci, "Ignoring unknown port speed, Ext Cap %p, revision = 0x%x\n",
 				addr, major_revision);
 		/* Ignoring port protocol we can't understand. FIXME */
 		return;
@@ -2020,9 +2006,8 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
 	port_offset = XHCI_EXT_PORT_OFF(temp);
 	port_count = XHCI_EXT_PORT_COUNT(temp);
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-			"Ext Cap %p, port offset = %u, "
-			"count = %u, revision = 0x%x",
-			addr, port_offset, port_count, major_revision);
+		       "Ext Cap %p, port offset = %u, count = %u, revision = 0x%x",
+		       addr, port_offset, port_count, major_revision);
 	/* Port count includes the current port offset */
 	if (port_offset == 0 || (port_offset + port_count - 1) > num_ports)
 		/* WTF? "Valid values are ‘1’ to MaxPorts" */
@@ -2079,10 +2064,8 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
 		struct xhci_port *hw_port = &xhci->hw_ports[i];
 		/* Duplicate entry.  Ignore the port if the revisions differ. */
 		if (hw_port->rhub) {
-			xhci_warn(xhci, "Duplicate port entry, Ext Cap %p,"
-					" port %u\n", addr, i);
-			xhci_warn(xhci, "Port was marked as USB %u, "
-					"duplicated as USB %u\n",
+			xhci_warn(xhci, "Duplicate port entry, Ext Cap %p, port %u\n", addr, i);
+			xhci_warn(xhci, "Port was marked as USB %u, duplicated as USB %u\n",
 					hw_port->rhub->maj_rev, major_revision);
 			/* Only adjust the roothub port counts if we haven't
 			 * found a similar duplicate.
@@ -2358,8 +2341,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 		goto fail;
 	xhci->dcbaa->dma = dma;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-			"// Device context base array address = 0x%llx (DMA), %p (virt)",
-			(unsigned long long)xhci->dcbaa->dma, xhci->dcbaa);
+			"// Device context base array address = 0x%pad (DMA), %p (virt)",
+			&xhci->dcbaa->dma, xhci->dcbaa);
 	xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr);
 
 	/*
@@ -2400,8 +2383,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 		goto fail;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
 			"Allocated command ring at %p", xhci->cmd_ring);
-	xhci_dbg_trace(xhci, trace_xhci_dbg_init, "First segment DMA is 0x%llx",
-			(unsigned long long)xhci->cmd_ring->first_seg->dma);
+	xhci_dbg_trace(xhci, trace_xhci_dbg_init, "First segment DMA is 0x%pad",
+			&xhci->cmd_ring->first_seg->dma);
 
 	/* Set the address in the Command Ring Control register */
 	val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
@@ -2421,8 +2404,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 	val = readl(&xhci->cap_regs->db_off);
 	val &= DBOFF_MASK;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-			"// Doorbell array is located at offset 0x%x"
-			" from cap regs base addr", val);
+		       "// Doorbell array is located at offset 0x%x from cap regs base addr",
+		       val);
 	xhci->dba = (void __iomem *) xhci->cap_regs + val;
 	/* Set ir_set to interrupt register set 0 */
 
diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index f7cbb08fc5068da5f932885c138781b7e88c1bc0..90cf40d6d0c3170df180dc44d7522821aa04a0e7 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -398,6 +398,7 @@ static int xhci_mtk_clks_get(struct xhci_hcd_mtk *mtk)
 	clks[2].id = "ref_ck";
 	clks[3].id = "mcu_ck";
 	clks[4].id = "dma_ck";
+	clks[5].id = "frmcnt_ck";
 
 	return devm_clk_bulk_get_optional(mtk->dev, BULK_CLKS_NUM, clks);
 }
diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h
index 1174a510dd38810fd7403a909024d21cfc8b8713..faaaf05e36ce0963a5108b2d0a997024464f023c 100644
--- a/drivers/usb/host/xhci-mtk.h
+++ b/drivers/usb/host/xhci-mtk.h
@@ -15,7 +15,7 @@
 
 #include "xhci.h"
 
-#define BULK_CLKS_NUM	5
+#define BULK_CLKS_NUM	6
 #define BULK_VREGS_NUM	2
 
 /* support at most 64 ep, use 32 size hash table */
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 6db07ca419c317488e4c0918a39d2d3e6f6a5865..ddb79f23fb3b7ce0a54b93f388e46db6508aecff 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -78,14 +78,207 @@ static const char hcd_name[] = "xhci_hcd";
 static struct hc_driver __read_mostly xhci_pci_hc_driver;
 
 static int xhci_pci_setup(struct usb_hcd *hcd);
+static int xhci_pci_run(struct usb_hcd *hcd);
 static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
 				      struct usb_tt *tt, gfp_t mem_flags);
 
 static const struct xhci_driver_overrides xhci_pci_overrides __initconst = {
 	.reset = xhci_pci_setup,
+	.start = xhci_pci_run,
 	.update_hub_device = xhci_pci_update_hub_device,
 };
 
+static void xhci_msix_sync_irqs(struct xhci_hcd *xhci)
+{
+	struct usb_hcd *hcd = xhci_to_hcd(xhci);
+
+	if (hcd->msix_enabled) {
+		struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+		int i;
+
+		for (i = 0; i < xhci->msix_count; i++)
+			synchronize_irq(pci_irq_vector(pdev, i));
+	}
+}
+
+/* Free any IRQs and disable MSI-X */
+static void xhci_cleanup_msix(struct xhci_hcd *xhci)
+{
+	struct usb_hcd *hcd = xhci_to_hcd(xhci);
+	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+
+	if (xhci->quirks & XHCI_PLAT)
+		return;
+
+	/* return if using legacy interrupt */
+	if (hcd->irq > 0)
+		return;
+
+	if (hcd->msix_enabled) {
+		int i;
+
+		for (i = 0; i < xhci->msix_count; i++)
+			free_irq(pci_irq_vector(pdev, i), xhci_to_hcd(xhci));
+	} else {
+		free_irq(pci_irq_vector(pdev, 0), xhci_to_hcd(xhci));
+	}
+
+	pci_free_irq_vectors(pdev);
+	hcd->msix_enabled = 0;
+}
+
+/*
+ * Set up MSI
+ */
+static int xhci_setup_msi(struct xhci_hcd *xhci)
+{
+	int ret;
+	/*
+	 * TODO:Check with MSI Soc for sysdev
+	 */
+	struct pci_dev  *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
+
+	ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
+	if (ret < 0) {
+		xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+				"failed to allocate MSI entry");
+		return ret;
+	}
+
+	ret = request_irq(pdev->irq, xhci_msi_irq,
+				0, "xhci_hcd", xhci_to_hcd(xhci));
+	if (ret) {
+		xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+				"disable MSI interrupt");
+		pci_free_irq_vectors(pdev);
+	}
+
+	return ret;
+}
+
+/*
+ * Set up MSI-X
+ */
+static int xhci_setup_msix(struct xhci_hcd *xhci)
+{
+	int i, ret;
+	struct usb_hcd *hcd = xhci_to_hcd(xhci);
+	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+
+	/*
+	 * calculate number of msi-x vectors supported.
+	 * - HCS_MAX_INTRS: the max number of interrupts the host can handle,
+	 *   with max number of interrupters based on the xhci HCSPARAMS1.
+	 * - num_online_cpus: maximum msi-x vectors per CPUs core.
+	 *   Add additional 1 vector to ensure always available interrupt.
+	 */
+	xhci->msix_count = min(num_online_cpus() + 1,
+				HCS_MAX_INTRS(xhci->hcs_params1));
+
+	ret = pci_alloc_irq_vectors(pdev, xhci->msix_count, xhci->msix_count,
+			PCI_IRQ_MSIX);
+	if (ret < 0) {
+		xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+				"Failed to enable MSI-X");
+		return ret;
+	}
+
+	for (i = 0; i < xhci->msix_count; i++) {
+		ret = request_irq(pci_irq_vector(pdev, i), xhci_msi_irq, 0,
+				"xhci_hcd", xhci_to_hcd(xhci));
+		if (ret)
+			goto disable_msix;
+	}
+
+	hcd->msix_enabled = 1;
+	return ret;
+
+disable_msix:
+	xhci_dbg_trace(xhci, trace_xhci_dbg_init, "disable MSI-X interrupt");
+	while (--i >= 0)
+		free_irq(pci_irq_vector(pdev, i), xhci_to_hcd(xhci));
+	pci_free_irq_vectors(pdev);
+	return ret;
+}
+
+static int xhci_try_enable_msi(struct usb_hcd *hcd)
+{
+	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+	struct pci_dev  *pdev;
+	int ret;
+
+	/* The xhci platform device has set up IRQs through usb_add_hcd. */
+	if (xhci->quirks & XHCI_PLAT)
+		return 0;
+
+	pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
+	/*
+	 * Some Fresco Logic host controllers advertise MSI, but fail to
+	 * generate interrupts.  Don't even try to enable MSI.
+	 */
+	if (xhci->quirks & XHCI_BROKEN_MSI)
+		goto legacy_irq;
+
+	/* unregister the legacy interrupt */
+	if (hcd->irq)
+		free_irq(hcd->irq, hcd);
+	hcd->irq = 0;
+
+	ret = xhci_setup_msix(xhci);
+	if (ret)
+		/* fall back to msi*/
+		ret = xhci_setup_msi(xhci);
+
+	if (!ret) {
+		hcd->msi_enabled = 1;
+		return 0;
+	}
+
+	if (!pdev->irq) {
+		xhci_err(xhci, "No msi-x/msi found and no IRQ in BIOS\n");
+		return -EINVAL;
+	}
+
+ legacy_irq:
+	if (!strlen(hcd->irq_descr))
+		snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
+			 hcd->driver->description, hcd->self.busnum);
+
+	/* fall back to legacy interrupt*/
+	ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
+			hcd->irq_descr, hcd);
+	if (ret) {
+		xhci_err(xhci, "request interrupt %d failed\n",
+				pdev->irq);
+		return ret;
+	}
+	hcd->irq = pdev->irq;
+	return 0;
+}
+
+static int xhci_pci_run(struct usb_hcd *hcd)
+{
+	int ret;
+
+	if (usb_hcd_is_primary_hcd(hcd)) {
+		ret = xhci_try_enable_msi(hcd);
+		if (ret)
+			return ret;
+	}
+
+	return xhci_run(hcd);
+}
+
+static void xhci_pci_stop(struct usb_hcd *hcd)
+{
+	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+	xhci_stop(hcd);
+
+	if (usb_hcd_is_primary_hcd(hcd))
+		xhci_cleanup_msix(xhci);
+}
+
 /* called after powerup, by probe or system-pm "wakeup" */
 static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev)
 {
@@ -535,7 +728,6 @@ static void xhci_pci_remove(struct pci_dev *dev)
 	usb_hcd_pci_remove(dev);
 }
 
-#ifdef CONFIG_PM
 /*
  * In some Intel xHCI controllers, in order to get D3 working,
  * through a vendor specific SSIC CONFIG register at offset 0x883c,
@@ -622,6 +814,10 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 		xhci_sparse_control_quirk(hcd);
 
 	ret = xhci_suspend(xhci, do_wakeup);
+
+	/* synchronize irq when using MSI-X */
+	xhci_msix_sync_irqs(xhci);
+
 	if (ret && (xhci->quirks & XHCI_SSIC_PORT_UNUSED))
 		xhci_ssic_port_unused_quirk(hcd, false);
 
@@ -724,12 +920,12 @@ static void xhci_pci_shutdown(struct usb_hcd *hcd)
 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
 
 	xhci_shutdown(hcd);
+	xhci_cleanup_msix(xhci);
 
 	/* Yet another workaround for spurious wakeups at shutdown with HSW */
 	if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
 		pci_set_power_state(pdev, PCI_D3hot);
 }
-#endif /* CONFIG_PM */
 
 /*-------------------------------------------------------------------------*/
 
@@ -771,22 +967,19 @@ static struct pci_driver xhci_pci_driver = {
 	/* suspend and resume implemented later */
 
 	.shutdown = 	usb_hcd_pci_shutdown,
-#ifdef CONFIG_PM
 	.driver = {
-		.pm = &usb_hcd_pci_pm_ops
+		.pm = pm_ptr(&usb_hcd_pci_pm_ops),
 	},
-#endif
 };
 
 static int __init xhci_pci_init(void)
 {
 	xhci_init_driver(&xhci_pci_hc_driver, &xhci_pci_overrides);
-#ifdef CONFIG_PM
-	xhci_pci_hc_driver.pci_suspend = xhci_pci_suspend;
-	xhci_pci_hc_driver.pci_resume = xhci_pci_resume;
-	xhci_pci_hc_driver.pci_poweroff_late = xhci_pci_poweroff_late;
-	xhci_pci_hc_driver.shutdown = xhci_pci_shutdown;
-#endif
+	xhci_pci_hc_driver.pci_suspend = pm_ptr(xhci_pci_suspend);
+	xhci_pci_hc_driver.pci_resume = pm_ptr(xhci_pci_resume);
+	xhci_pci_hc_driver.pci_poweroff_late = pm_ptr(xhci_pci_poweroff_late);
+	xhci_pci_hc_driver.shutdown = pm_ptr(xhci_pci_shutdown);
+	xhci_pci_hc_driver.stop = xhci_pci_stop;
 	return pci_register_driver(&xhci_pci_driver);
 }
 module_init(xhci_pci_init);
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index b9f9625467d61e51010f70e85a33d9acf2f0b546..b0c8e8efc43b6f04222d9376b2fb582b2a530292 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -291,6 +291,21 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
 			goto dealloc_usb2_hcd;
 		}
 
+		xhci->shared_hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev,
+			    "usb-phy", 1);
+		if (IS_ERR(xhci->shared_hcd->usb_phy)) {
+			if (PTR_ERR(xhci->shared_hcd->usb_phy) != -ENODEV)
+				dev_err(sysdev, "%s get usb3phy fail (ret=%d)\n",
+					     __func__,
+					    (int)PTR_ERR(xhci->shared_hcd->usb_phy));
+			xhci->shared_hcd->usb_phy = NULL;
+		} else {
+			ret = usb_phy_init(xhci->shared_hcd->usb_phy);
+			if (ret)
+				dev_err(sysdev, "%s init usb3phy fail (ret=%d)\n",
+					    __func__, ret);
+		}
+
 		xhci->shared_hcd->tpl_support = hcd->tpl_support;
 	}
 
@@ -362,10 +377,8 @@ static int xhci_generic_plat_probe(struct platform_device *pdev)
 		if (is_of_node(sysdev->fwnode) ||
 			is_acpi_device_node(sysdev->fwnode))
 			break;
-#ifdef CONFIG_PCI
-		else if (sysdev->bus == &pci_bus_type)
+		else if (dev_is_pci(sysdev))
 			break;
-#endif
 	}
 
 	if (!sysdev)
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
index 7f18509a1d397dcb6965ae7666ad60ec89fcc2ce..ad966b797b892afb799d6c640a33cd504e56ac9a 100644
--- a/drivers/usb/host/xhci-rcar.c
+++ b/drivers/usb/host/xhci-rcar.c
@@ -12,26 +12,22 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/usb/phy.h>
-#include <linux/sys_soc.h>
 
 #include "xhci.h"
 #include "xhci-plat.h"
 #include "xhci-rzv2m.h"
 
 #define XHCI_RCAR_FIRMWARE_NAME_V1	"r8a779x_usb3_v1.dlmem"
-#define XHCI_RCAR_FIRMWARE_NAME_V2	"r8a779x_usb3_v2.dlmem"
 #define XHCI_RCAR_FIRMWARE_NAME_V3	"r8a779x_usb3_v3.dlmem"
 
 /*
-* - The V3 firmware is for almost all R-Car Gen3 (except r8a7795 ES1.x)
-* - The V2 firmware is for r8a7795 ES1.x.
+* - The V3 firmware is for all R-Car Gen3
 * - The V2 firmware is possible to use on R-Car Gen2. However, the V2 causes
 *   performance degradation. So, this driver continues to use the V1 if R-Car
 *   Gen2.
 * - The V1 firmware is impossible to use on R-Car Gen3.
 */
 MODULE_FIRMWARE(XHCI_RCAR_FIRMWARE_NAME_V1);
-MODULE_FIRMWARE(XHCI_RCAR_FIRMWARE_NAME_V2);
 MODULE_FIRMWARE(XHCI_RCAR_FIRMWARE_NAME_V3);
 
 /*** Register Offset ***/
@@ -78,18 +74,6 @@ MODULE_FIRMWARE(XHCI_RCAR_FIRMWARE_NAME_V3);
 #define RCAR_USB3_RX_POL_VAL	BIT(21)
 #define RCAR_USB3_TX_POL_VAL	BIT(4)
 
-/* For soc_device_attribute */
-#define RCAR_XHCI_FIRMWARE_V2   BIT(0) /* FIRMWARE V2 */
-#define RCAR_XHCI_FIRMWARE_V3   BIT(1) /* FIRMWARE V3 */
-
-static const struct soc_device_attribute rcar_quirks_match[]  = {
-	{
-		.soc_id = "r8a7795", .revision = "ES1.*",
-		.data = (void *)RCAR_XHCI_FIRMWARE_V2,
-	},
-	{ /* sentinel */ }
-};
-
 static void xhci_rcar_start_gen2(struct usb_hcd *hcd)
 {
 	/* LCLK Select */
@@ -135,9 +119,6 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)
 	const struct firmware *fw;
 	int retval, index, j;
 	u32 data, val, temp;
-	u32 quirks = 0;
-	const struct soc_device_attribute *attr;
-	const char *firmware_name;
 
 	/*
 	 * According to the datasheet, "Upon the completion of FW Download,
@@ -146,19 +127,8 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)
 	if (readl(regs + RCAR_USB3_DL_CTRL) & RCAR_USB3_DL_CTRL_FW_SUCCESS)
 		return 0;
 
-	attr = soc_device_match(rcar_quirks_match);
-	if (attr)
-		quirks = (uintptr_t)attr->data;
-
-	if (quirks & RCAR_XHCI_FIRMWARE_V2)
-		firmware_name = XHCI_RCAR_FIRMWARE_NAME_V2;
-	else if (quirks & RCAR_XHCI_FIRMWARE_V3)
-		firmware_name = XHCI_RCAR_FIRMWARE_NAME_V3;
-	else
-		firmware_name = priv->firmware_name;
-
 	/* request R-Car USB3.0 firmware */
-	retval = request_firmware(&fw, firmware_name, dev);
+	retval = request_firmware(&fw, priv->firmware_name, dev);
 	if (retval)
 		return retval;
 
@@ -312,7 +282,7 @@ static struct platform_driver usb_xhci_renesas_driver = {
 	.driver	= {
 		.name = "xhci-renesas-hcd",
 		.pm = &xhci_plat_pm_ops,
-		.of_match_table = of_match_ptr(usb_xhci_of_match),
+		.of_match_table = usb_xhci_of_match,
 	},
 };
 module_platform_driver(usb_xhci_renesas_driver);
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index eb788c60c1c09ded98b2ed8f9b50579ed981bf93..1ad12d5a48572b15e3d877df43dd80cf480ccc00 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3106,6 +3106,7 @@ irqreturn_t xhci_msi_irq(int irq, void *hcd)
 {
 	return xhci_irq(hcd);
 }
+EXPORT_SYMBOL_GPL(xhci_msi_irq);
 
 /****		Endpoint Ring Operations	****/
 
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index a88c39e525c235521d1583ca2807aced1bc96259..c75d9324414366c993a9d9729c0c0d7066381dbb 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -1535,7 +1535,6 @@ static void tegra_xusb_deinit_usb_phy(struct tegra_xusb *tegra)
 
 static int tegra_xusb_probe(struct platform_device *pdev)
 {
-	struct of_phandle_args args;
 	struct tegra_xusb *tegra;
 	struct device_node *np;
 	struct resource *regs;
@@ -1594,15 +1593,13 @@ static int tegra_xusb_probe(struct platform_device *pdev)
 		goto put_padctl;
 	}
 
-	/* Older device-trees don't have padctrl interrupt */
-	err = of_irq_parse_one(np, 0, &args);
-	if (!err) {
-		tegra->padctl_irq = of_irq_get(np, 0);
-		if (tegra->padctl_irq <= 0) {
-			err = (tegra->padctl_irq == 0) ? -ENODEV : tegra->padctl_irq;
-			goto put_padctl;
-		}
-	} else {
+	tegra->padctl_irq = of_irq_get(np, 0);
+	if (tegra->padctl_irq == -EPROBE_DEFER) {
+		err = tegra->padctl_irq;
+		goto put_padctl;
+	} else if (tegra->padctl_irq <= 0) {
+		/* Older device-trees don't have padctrl interrupt */
+		tegra->padctl_irq = 0;
 		dev_dbg(&pdev->dev,
 			"%pOF is missing an interrupt, disabling PM support\n", np);
 	}
diff --git a/drivers/usb/host/xhci-trace.c b/drivers/usb/host/xhci-trace.c
index d0070814d1eaf75f2d14583d2a11c921c2110ddc..062662d23241e4ffe4975ec6fe3bf95ebad1d488 100644
--- a/drivers/usb/host/xhci-trace.c
+++ b/drivers/usb/host/xhci-trace.c
@@ -12,3 +12,4 @@
 #include "xhci-trace.h"
 
 EXPORT_TRACEPOINT_SYMBOL_GPL(xhci_dbg_quirks);
+EXPORT_TRACEPOINT_SYMBOL_GPL(xhci_dbg_init);
diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h
index 61e93a3540a7cc299ca783ddd2cf1f971eb5b856..4286dba5b1574fd79c38c574d69b51a8e58e83ca 100644
--- a/drivers/usb/host/xhci-trace.h
+++ b/drivers/usb/host/xhci-trace.h
@@ -120,7 +120,6 @@ DECLARE_EVENT_CLASS(xhci_log_trb,
 		__field(u32, field1)
 		__field(u32, field2)
 		__field(u32, field3)
-		__dynamic_array(char, str, XHCI_MSG_MAX)
 	),
 	TP_fast_assign(
 		__entry->type = ring->type;
@@ -130,8 +129,8 @@ DECLARE_EVENT_CLASS(xhci_log_trb,
 		__entry->field3 = le32_to_cpu(trb->field[3]);
 	),
 	TP_printk("%s: %s", xhci_ring_type_string(__entry->type),
-		  xhci_decode_trb(__get_str(str), XHCI_MSG_MAX, __entry->field0, __entry->field1,
-					__entry->field2, __entry->field3)
+		  xhci_decode_trb(__get_buf(XHCI_MSG_MAX), XHCI_MSG_MAX, __entry->field0,
+				  __entry->field1, __entry->field2, __entry->field3)
 	)
 );
 
@@ -322,7 +321,6 @@ DECLARE_EVENT_CLASS(xhci_log_ep_ctx,
 		__field(u32, info2)
 		__field(u64, deq)
 		__field(u32, tx_info)
-		__dynamic_array(char, str, XHCI_MSG_MAX)
 	),
 	TP_fast_assign(
 		__entry->info = le32_to_cpu(ctx->ep_info);
@@ -330,7 +328,7 @@ DECLARE_EVENT_CLASS(xhci_log_ep_ctx,
 		__entry->deq = le64_to_cpu(ctx->deq);
 		__entry->tx_info = le32_to_cpu(ctx->tx_info);
 	),
-	TP_printk("%s", xhci_decode_ep_context(__get_str(str),
+	TP_printk("%s", xhci_decode_ep_context(__get_buf(XHCI_MSG_MAX),
 		__entry->info, __entry->info2, __entry->deq, __entry->tx_info)
 	)
 );
@@ -368,7 +366,6 @@ DECLARE_EVENT_CLASS(xhci_log_slot_ctx,
 		__field(u32, info2)
 		__field(u32, tt_info)
 		__field(u32, state)
-		__dynamic_array(char, str, XHCI_MSG_MAX)
 	),
 	TP_fast_assign(
 		__entry->info = le32_to_cpu(ctx->dev_info);
@@ -376,7 +373,7 @@ DECLARE_EVENT_CLASS(xhci_log_slot_ctx,
 		__entry->tt_info = le64_to_cpu(ctx->tt_info);
 		__entry->state = le32_to_cpu(ctx->dev_state);
 	),
-	TP_printk("%s", xhci_decode_slot_context(__get_str(str),
+	TP_printk("%s", xhci_decode_slot_context(__get_buf(XHCI_MSG_MAX),
 			__entry->info, __entry->info2,
 			__entry->tt_info, __entry->state)
 	)
@@ -433,13 +430,12 @@ DECLARE_EVENT_CLASS(xhci_log_ctrl_ctx,
 	TP_STRUCT__entry(
 		__field(u32, drop)
 		__field(u32, add)
-		__dynamic_array(char, str, XHCI_MSG_MAX)
 	),
 	TP_fast_assign(
 		__entry->drop = le32_to_cpu(ctrl_ctx->drop_flags);
 		__entry->add = le32_to_cpu(ctrl_ctx->add_flags);
 	),
-	TP_printk("%s", xhci_decode_ctrl_ctx(__get_str(str), __entry->drop, __entry->add)
+	TP_printk("%s", xhci_decode_ctrl_ctx(__get_buf(XHCI_MSG_MAX), __entry->drop, __entry->add)
 	)
 );
 
@@ -525,7 +521,6 @@ DECLARE_EVENT_CLASS(xhci_log_portsc,
 		    TP_STRUCT__entry(
 				     __field(u32, portnum)
 				     __field(u32, portsc)
-				     __dynamic_array(char, str, XHCI_MSG_MAX)
 				     ),
 		    TP_fast_assign(
 				   __entry->portnum = portnum;
@@ -533,7 +528,7 @@ DECLARE_EVENT_CLASS(xhci_log_portsc,
 				   ),
 		    TP_printk("port-%d: %s",
 			      __entry->portnum,
-			      xhci_decode_portsc(__get_str(str), __entry->portsc)
+			      xhci_decode_portsc(__get_buf(XHCI_MSG_MAX), __entry->portsc)
 			      )
 );
 
@@ -558,14 +553,13 @@ DECLARE_EVENT_CLASS(xhci_log_doorbell,
 	TP_STRUCT__entry(
 		__field(u32, slot)
 		__field(u32, doorbell)
-		__dynamic_array(char, str, XHCI_MSG_MAX)
 	),
 	TP_fast_assign(
 		__entry->slot = slot;
 		__entry->doorbell = doorbell;
 	),
 	TP_printk("Ring doorbell for %s",
-		  xhci_decode_doorbell(__get_str(str), __entry->slot, __entry->doorbell)
+		  xhci_decode_doorbell(__get_buf(XHCI_MSG_MAX), __entry->slot, __entry->doorbell)
 	)
 );
 
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 6307bae9cddffdf775786d976b28b7eadd8d0078..78790dc13c5f143f1262e4dd171402d8ed9a15ba 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -322,192 +322,6 @@ static int xhci_disable_interrupter(struct xhci_interrupter *ir)
 	return 0;
 }
 
-#ifdef CONFIG_USB_PCI
-/*
- * Set up MSI
- */
-static int xhci_setup_msi(struct xhci_hcd *xhci)
-{
-	int ret;
-	/*
-	 * TODO:Check with MSI Soc for sysdev
-	 */
-	struct pci_dev  *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
-
-	ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
-	if (ret < 0) {
-		xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-				"failed to allocate MSI entry");
-		return ret;
-	}
-
-	ret = request_irq(pdev->irq, xhci_msi_irq,
-				0, "xhci_hcd", xhci_to_hcd(xhci));
-	if (ret) {
-		xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-				"disable MSI interrupt");
-		pci_free_irq_vectors(pdev);
-	}
-
-	return ret;
-}
-
-/*
- * Set up MSI-X
- */
-static int xhci_setup_msix(struct xhci_hcd *xhci)
-{
-	int i, ret;
-	struct usb_hcd *hcd = xhci_to_hcd(xhci);
-	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
-
-	/*
-	 * calculate number of msi-x vectors supported.
-	 * - HCS_MAX_INTRS: the max number of interrupts the host can handle,
-	 *   with max number of interrupters based on the xhci HCSPARAMS1.
-	 * - num_online_cpus: maximum msi-x vectors per CPUs core.
-	 *   Add additional 1 vector to ensure always available interrupt.
-	 */
-	xhci->msix_count = min(num_online_cpus() + 1,
-				HCS_MAX_INTRS(xhci->hcs_params1));
-
-	ret = pci_alloc_irq_vectors(pdev, xhci->msix_count, xhci->msix_count,
-			PCI_IRQ_MSIX);
-	if (ret < 0) {
-		xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-				"Failed to enable MSI-X");
-		return ret;
-	}
-
-	for (i = 0; i < xhci->msix_count; i++) {
-		ret = request_irq(pci_irq_vector(pdev, i), xhci_msi_irq, 0,
-				"xhci_hcd", xhci_to_hcd(xhci));
-		if (ret)
-			goto disable_msix;
-	}
-
-	hcd->msix_enabled = 1;
-	return ret;
-
-disable_msix:
-	xhci_dbg_trace(xhci, trace_xhci_dbg_init, "disable MSI-X interrupt");
-	while (--i >= 0)
-		free_irq(pci_irq_vector(pdev, i), xhci_to_hcd(xhci));
-	pci_free_irq_vectors(pdev);
-	return ret;
-}
-
-/* Free any IRQs and disable MSI-X */
-static void xhci_cleanup_msix(struct xhci_hcd *xhci)
-{
-	struct usb_hcd *hcd = xhci_to_hcd(xhci);
-	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
-
-	if (xhci->quirks & XHCI_PLAT)
-		return;
-
-	/* return if using legacy interrupt */
-	if (hcd->irq > 0)
-		return;
-
-	if (hcd->msix_enabled) {
-		int i;
-
-		for (i = 0; i < xhci->msix_count; i++)
-			free_irq(pci_irq_vector(pdev, i), xhci_to_hcd(xhci));
-	} else {
-		free_irq(pci_irq_vector(pdev, 0), xhci_to_hcd(xhci));
-	}
-
-	pci_free_irq_vectors(pdev);
-	hcd->msix_enabled = 0;
-}
-
-static void __maybe_unused xhci_msix_sync_irqs(struct xhci_hcd *xhci)
-{
-	struct usb_hcd *hcd = xhci_to_hcd(xhci);
-
-	if (hcd->msix_enabled) {
-		struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
-		int i;
-
-		for (i = 0; i < xhci->msix_count; i++)
-			synchronize_irq(pci_irq_vector(pdev, i));
-	}
-}
-
-static int xhci_try_enable_msi(struct usb_hcd *hcd)
-{
-	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-	struct pci_dev  *pdev;
-	int ret;
-
-	/* The xhci platform device has set up IRQs through usb_add_hcd. */
-	if (xhci->quirks & XHCI_PLAT)
-		return 0;
-
-	pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
-	/*
-	 * Some Fresco Logic host controllers advertise MSI, but fail to
-	 * generate interrupts.  Don't even try to enable MSI.
-	 */
-	if (xhci->quirks & XHCI_BROKEN_MSI)
-		goto legacy_irq;
-
-	/* unregister the legacy interrupt */
-	if (hcd->irq)
-		free_irq(hcd->irq, hcd);
-	hcd->irq = 0;
-
-	ret = xhci_setup_msix(xhci);
-	if (ret)
-		/* fall back to msi*/
-		ret = xhci_setup_msi(xhci);
-
-	if (!ret) {
-		hcd->msi_enabled = 1;
-		return 0;
-	}
-
-	if (!pdev->irq) {
-		xhci_err(xhci, "No msi-x/msi found and no IRQ in BIOS\n");
-		return -EINVAL;
-	}
-
- legacy_irq:
-	if (!strlen(hcd->irq_descr))
-		snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
-			 hcd->driver->description, hcd->self.busnum);
-
-	/* fall back to legacy interrupt*/
-	ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
-			hcd->irq_descr, hcd);
-	if (ret) {
-		xhci_err(xhci, "request interrupt %d failed\n",
-				pdev->irq);
-		return ret;
-	}
-	hcd->irq = pdev->irq;
-	return 0;
-}
-
-#else
-
-static inline int xhci_try_enable_msi(struct usb_hcd *hcd)
-{
-	return 0;
-}
-
-static inline void xhci_cleanup_msix(struct xhci_hcd *xhci)
-{
-}
-
-static inline void xhci_msix_sync_irqs(struct xhci_hcd *xhci)
-{
-}
-
-#endif
-
 static void compliance_mode_recovery(struct timer_list *t)
 {
 	struct xhci_hcd *xhci;
@@ -705,10 +519,6 @@ int xhci_run(struct usb_hcd *hcd)
 
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init, "xhci_run");
 
-	ret = xhci_try_enable_msi(hcd);
-	if (ret)
-		return ret;
-
 	temp_64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue);
 	temp_64 &= ~ERST_PTR_MASK;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
@@ -758,7 +568,7 @@ EXPORT_SYMBOL_GPL(xhci_run);
  * Disable device contexts, disable IRQs, and quiesce the HC.
  * Reset the HC, finish any completed transactions, and cleanup memory.
  */
-static void xhci_stop(struct usb_hcd *hcd)
+void xhci_stop(struct usb_hcd *hcd)
 {
 	u32 temp;
 	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -781,8 +591,6 @@ static void xhci_stop(struct usb_hcd *hcd)
 	xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
 	spin_unlock_irq(&xhci->lock);
 
-	xhci_cleanup_msix(xhci);
-
 	/* Deleting Compliance Mode Recovery Timer */
 	if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
 			(!(xhci_all_ports_seen_u0(xhci)))) {
@@ -809,6 +617,7 @@ static void xhci_stop(struct usb_hcd *hcd)
 			readl(&xhci->op_regs->status));
 	mutex_unlock(&xhci->mutex);
 }
+EXPORT_SYMBOL_GPL(xhci_stop);
 
 /*
  * Shutdown HC (not bus-specific)
@@ -850,8 +659,6 @@ void xhci_shutdown(struct usb_hcd *hcd)
 
 	spin_unlock_irq(&xhci->lock);
 
-	xhci_cleanup_msix(xhci);
-
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
 			"xhci_shutdown completed - status = %x",
 			readl(&xhci->op_regs->status));
@@ -1143,10 +950,6 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
 				__func__);
 	}
 
-	/* step 5: remove core well power */
-	/* synchronize irq when using MSI-X */
-	xhci_msix_sync_irqs(xhci);
-
 	return rc;
 }
 EXPORT_SYMBOL_GPL(xhci_suspend);
@@ -1250,7 +1053,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 		spin_unlock_irq(&xhci->lock);
 		if (retval)
 			return retval;
-		xhci_cleanup_msix(xhci);
 
 		xhci_dbg(xhci, "// Disabling event ring interrupts\n");
 		temp = readl(&xhci->op_regs->status);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 786002bb35db0f62b6ebe42527c8887bb0b7428d..08d721921b7bb22606d82cea5b4736208beb0a9c 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -2125,6 +2125,7 @@ int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us);
 int xhci_run(struct usb_hcd *hcd);
 int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks);
 void xhci_shutdown(struct usb_hcd *hcd);
+void xhci_stop(struct usb_hcd *hcd);
 void xhci_init_driver(struct hc_driver *drv,
 		      const struct xhci_driver_overrides *over);
 int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index a5f7652db7da1b4810d2c83a1bd2b8a4362f2f24..99b15b77dfd576dace539b7166dd574fe134fcdf 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -4,6 +4,35 @@
 #
 comment "USB Miscellaneous drivers"
 
+config USB_USS720
+	tristate "USS720 parport driver"
+	depends on PARPORT
+	select PARPORT_NOT_PC
+	help
+	  This driver is for USB parallel port adapters that use the Lucent
+	  Technologies USS-720 chip. These cables are plugged into your USB
+	  port and provide USB compatibility to peripherals designed with
+	  parallel port interfaces.
+
+	  The chip has two modes: automatic mode and manual mode. In automatic
+	  mode, it looks to the computer like a standard USB printer. Only
+	  printers may be connected to the USS-720 in this mode. The generic
+	  USB printer driver ("USB Printer support", above) may be used in
+	  that mode, and you can say N here if you want to use the chip only
+	  in this mode.
+
+	  Manual mode is not limited to printers, any parallel port
+	  device should work. This driver utilizes manual mode.
+	  Note however that some operations are three orders of magnitude
+	  slower than on a PCI/ISA Parallel Port, so timing critical
+	  applications might not work.
+
+	  Say Y here if you own an USS-720 USB->Parport cable and intend to
+	  connect anything other than a printer to it.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called uss720.
+
 config USB_EMI62
 	tristate "EMI 6|2m USB Audio interface support"
 	help
@@ -108,28 +137,6 @@ config USB_IDMOUSE
 
 	  See also <https://www.fs.tum.de/~echtler/idmouse/>.
 
-config USB_FTDI_ELAN
-	tristate "Elan PCMCIA CardBus Adapter USB Client"
-	help
-	  ELAN's Uxxx series of adapters are USB to PCMCIA CardBus adapters.
-	  Currently only the U132 adapter is available.
-
-	  The U132 is specifically designed for CardBus PC cards that contain
-	  an OHCI host controller. Typical PC cards are the Orange Mobile 3G
-	  Option GlobeTrotter Fusion card. The U132 adapter will *NOT* work
-	  with PC cards that do not contain an OHCI controller. To use a U132
-	  adapter you will need this "ftdi-elan" module as well as the "u132-hcd"
-	  module which is a USB host controller driver that talks to the OHCI
-	  controller within CardBus card that are inserted in the U132 adapter.
-
-	  This driver has been tested with a CardBus OHCI USB adapter, and
-	  worked with a USB PEN Drive inserted into the first USB port of
-	  the PCCARD. A rather pointless thing to do, but useful for testing.
-
-	  See also the USB_U132_HCD entry "Elan U132 Adapter Host Controller"
-
-	  It is safe to say M here.
-
 config USB_APPLEDISPLAY
 	tristate "Apple Cinema Display support"
 	select BACKLIGHT_CLASS_DEVICE
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 93581baec3a83b0501fb8e52db81a6732bfa1bad..1992cc284d8aba91f2229810d6b1d9e3b663ef2e 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -10,7 +10,6 @@ obj-$(CONFIG_USB_CYTHERM)		+= cytherm.o
 obj-$(CONFIG_USB_EMI26)			+= emi26.o
 obj-$(CONFIG_USB_EMI62)			+= emi62.o
 obj-$(CONFIG_USB_EZUSB_FX2)		+= ezusb.o
-obj-$(CONFIG_USB_FTDI_ELAN)		+= ftdi-elan.o
 obj-$(CONFIG_APPLE_MFI_FASTCHARGE)	+= apple-mfi-fastcharge.o
 obj-$(CONFIG_USB_IDMOUSE)		+= idmouse.o
 obj-$(CONFIG_USB_IOWARRIOR)		+= iowarrior.o
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
deleted file mode 100644
index 8ce191e3a4c069e47530404bca7895a264cb6b50..0000000000000000000000000000000000000000
--- a/drivers/usb/misc/ftdi-elan.c
+++ /dev/null
@@ -1,2780 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * USB FTDI client driver for Elan Digital Systems's Uxxx adapters
- *
- * Copyright(C) 2006 Elan Digital Systems Limited
- * http://www.elandigitalsystems.com
- *
- * Author and Maintainer - Tony Olech - Elan Digital Systems
- * tony.olech@elandigitalsystems.com
- *
- * This driver was written by Tony Olech(tony.olech@elandigitalsystems.com)
- * based on various USB client drivers in the 2.6.15 linux kernel
- * with constant reference to the 3rd Edition of Linux Device Drivers
- * published by O'Reilly
- *
- * The U132 adapter is a USB to CardBus adapter specifically designed
- * for PC cards that contain an OHCI host controller. Typical PC cards
- * are the Orange Mobile 3G Option GlobeTrotter Fusion card.
- *
- * The U132 adapter will *NOT *work with PC cards that do not contain
- * an OHCI controller. A simple way to test whether a PC card has an
- * OHCI controller as an interface is to insert the PC card directly
- * into a laptop(or desktop) with a CardBus slot and if "lspci" shows
- * a new USB controller and "lsusb -v" shows a new OHCI Host Controller
- * then there is a good chance that the U132 adapter will support the
- * PC card.(you also need the specific client driver for the PC card)
- *
- * Please inform the Author and Maintainer about any PC cards that
- * contain OHCI Host Controller and work when directly connected to
- * an embedded CardBus slot but do not work when they are connected
- * via an ELAN U132 adapter.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/ioctl.h>
-#include <linux/pci_ids.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/mutex.h>
-#include <linux/uaccess.h>
-#include <linux/usb.h>
-#include <linux/workqueue.h>
-#include <linux/platform_device.h>
-MODULE_AUTHOR("Tony Olech");
-MODULE_DESCRIPTION("FTDI ELAN driver");
-MODULE_LICENSE("GPL");
-#define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
-static bool distrust_firmware = 1;
-module_param(distrust_firmware, bool, 0);
-MODULE_PARM_DESC(distrust_firmware,
-		 "true to distrust firmware power/overcurrent setup");
-extern struct platform_driver u132_platform_driver;
-/*
- * ftdi_module_lock exists to protect access to global variables
- *
- */
-static struct mutex ftdi_module_lock;
-static int ftdi_instances = 0;
-static struct list_head ftdi_static_list;
-/*
- * end of the global variables protected by ftdi_module_lock
- */
-#include "usb_u132.h"
-#include <asm/io.h>
-#include <linux/usb/hcd.h>
-
-/* FIXME ohci.h is ONLY for internal use by the OHCI driver.
- * If you're going to try stuff like this, you need to split
- * out shareable stuff (register declarations?) into its own
- * file, maybe name <linux/usb/ohci.h>
- */
-
-#include "../host/ohci.h"
-/* Define these values to match your devices*/
-#define USB_FTDI_ELAN_VENDOR_ID 0x0403
-#define USB_FTDI_ELAN_PRODUCT_ID 0xd6ea
-/* table of devices that work with this driver*/
-static const struct usb_device_id ftdi_elan_table[] = {
-	{USB_DEVICE(USB_FTDI_ELAN_VENDOR_ID, USB_FTDI_ELAN_PRODUCT_ID)},
-	{ /* Terminating entry */ }
-};
-
-MODULE_DEVICE_TABLE(usb, ftdi_elan_table);
-/* only the jtag(firmware upgrade device) interface requires
- * a device file and corresponding minor number, but the
- * interface is created unconditionally - I suppose it could
- * be configured or not according to a module parameter.
- * But since we(now) require one interface per device,
- * and since it unlikely that a normal installation would
- * require more than a couple of elan-ftdi devices, 8 seems
- * like a reasonable limit to have here, and if someone
- * really requires more than 8 devices, then they can frig the
- * code and recompile
- */
-#define USB_FTDI_ELAN_MINOR_BASE 192
-#define COMMAND_BITS 5
-#define COMMAND_SIZE (1<<COMMAND_BITS)
-#define COMMAND_MASK (COMMAND_SIZE-1)
-struct u132_command {
-	u8 header;
-	u16 length;
-	u8 address;
-	u8 width;
-	u32 value;
-	int follows;
-	void *buffer;
-};
-#define RESPOND_BITS 5
-#define RESPOND_SIZE (1<<RESPOND_BITS)
-#define RESPOND_MASK (RESPOND_SIZE-1)
-struct u132_respond {
-	u8 header;
-	u8 address;
-	u32 *value;
-	int *result;
-	struct completion wait_completion;
-};
-struct u132_target {
-	void *endp;
-	struct urb *urb;
-	int toggle_bits;
-	int error_count;
-	int condition_code;
-	int repeat_number;
-	int halted;
-	int skipped;
-	int actual;
-	int non_null;
-	int active;
-	int abandoning;
-	void (*callback)(void *endp, struct urb *urb, u8 *buf, int len,
-			 int toggle_bits, int error_count, int condition_code,
-			 int repeat_number, int halted, int skipped, int actual,
-			 int non_null);
-};
-/* Structure to hold all of our device specific stuff*/
-struct usb_ftdi {
-	struct list_head ftdi_list;
-	struct mutex u132_lock;
-	int command_next;
-	int command_head;
-	struct u132_command command[COMMAND_SIZE];
-	int respond_next;
-	int respond_head;
-	struct u132_respond respond[RESPOND_SIZE];
-	struct u132_target target[4];
-	char device_name[16];
-	unsigned synchronized:1;
-	unsigned enumerated:1;
-	unsigned registered:1;
-	unsigned initialized:1;
-	unsigned card_ejected:1;
-	int function;
-	int sequence_num;
-	int disconnected;
-	int gone_away;
-	int stuck_status;
-	int status_queue_delay;
-	struct semaphore sw_lock;
-	struct usb_device *udev;
-	struct usb_interface *interface;
-	struct usb_class_driver *class;
-	struct delayed_work status_work;
-	struct delayed_work command_work;
-	struct delayed_work respond_work;
-	struct u132_platform_data platform_data;
-	struct resource resources[0];
-	struct platform_device platform_dev;
-	unsigned char *bulk_in_buffer;
-	size_t bulk_in_size;
-	size_t bulk_in_last;
-	size_t bulk_in_left;
-	__u8 bulk_in_endpointAddr;
-	__u8 bulk_out_endpointAddr;
-	struct kref kref;
-	u32 controlreg;
-	u8 response[4 + 1024];
-	int expected;
-	int received;
-	int ed_found;
-};
-#define kref_to_usb_ftdi(d) container_of(d, struct usb_ftdi, kref)
-#define platform_device_to_usb_ftdi(d) container_of(d, struct usb_ftdi, \
-						    platform_dev)
-static struct usb_driver ftdi_elan_driver;
-static void ftdi_elan_delete(struct kref *kref)
-{
-	struct usb_ftdi *ftdi = kref_to_usb_ftdi(kref);
-	dev_warn(&ftdi->udev->dev, "FREEING ftdi=%p\n", ftdi);
-	usb_put_dev(ftdi->udev);
-	ftdi->disconnected += 1;
-	mutex_lock(&ftdi_module_lock);
-	list_del_init(&ftdi->ftdi_list);
-	ftdi_instances -= 1;
-	mutex_unlock(&ftdi_module_lock);
-	kfree(ftdi->bulk_in_buffer);
-	ftdi->bulk_in_buffer = NULL;
-	kfree(ftdi);
-}
-
-static void ftdi_elan_put_kref(struct usb_ftdi *ftdi)
-{
-	kref_put(&ftdi->kref, ftdi_elan_delete);
-}
-
-static void ftdi_elan_get_kref(struct usb_ftdi *ftdi)
-{
-	kref_get(&ftdi->kref);
-}
-
-static void ftdi_elan_init_kref(struct usb_ftdi *ftdi)
-{
-	kref_init(&ftdi->kref);
-}
-
-static void ftdi_status_requeue_work(struct usb_ftdi *ftdi, unsigned int delta)
-{
-	if (!schedule_delayed_work(&ftdi->status_work, delta))
-		kref_put(&ftdi->kref, ftdi_elan_delete);
-}
-
-static void ftdi_status_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
-{
-	if (schedule_delayed_work(&ftdi->status_work, delta))
-		kref_get(&ftdi->kref);
-}
-
-static void ftdi_status_cancel_work(struct usb_ftdi *ftdi)
-{
-	if (cancel_delayed_work_sync(&ftdi->status_work))
-		kref_put(&ftdi->kref, ftdi_elan_delete);
-}
-
-static void ftdi_command_requeue_work(struct usb_ftdi *ftdi, unsigned int delta)
-{
-	if (!schedule_delayed_work(&ftdi->command_work, delta))
-		kref_put(&ftdi->kref, ftdi_elan_delete);
-}
-
-static void ftdi_command_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
-{
-	if (schedule_delayed_work(&ftdi->command_work, delta))
-		kref_get(&ftdi->kref);
-}
-
-static void ftdi_command_cancel_work(struct usb_ftdi *ftdi)
-{
-	if (cancel_delayed_work_sync(&ftdi->command_work))
-		kref_put(&ftdi->kref, ftdi_elan_delete);
-}
-
-static void ftdi_response_requeue_work(struct usb_ftdi *ftdi,
-				       unsigned int delta)
-{
-	if (!schedule_delayed_work(&ftdi->respond_work, delta))
-		kref_put(&ftdi->kref, ftdi_elan_delete);
-}
-
-static void ftdi_respond_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
-{
-	if (schedule_delayed_work(&ftdi->respond_work, delta))
-		kref_get(&ftdi->kref);
-}
-
-static void ftdi_response_cancel_work(struct usb_ftdi *ftdi)
-{
-	if (cancel_delayed_work_sync(&ftdi->respond_work))
-		kref_put(&ftdi->kref, ftdi_elan_delete);
-}
-
-void ftdi_elan_gone_away(struct platform_device *pdev)
-{
-	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
-	ftdi->gone_away += 1;
-	ftdi_elan_put_kref(ftdi);
-}
-
-
-EXPORT_SYMBOL_GPL(ftdi_elan_gone_away);
-static void ftdi_release_platform_dev(struct device *dev)
-{
-	dev->parent = NULL;
-}
-
-static void ftdi_elan_do_callback(struct usb_ftdi *ftdi,
-				  struct u132_target *target, u8 *buffer, int length);
-static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi);
-static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi);
-static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi);
-static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi);
-static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi);
-static int ftdi_elan_synchronize(struct usb_ftdi *ftdi);
-static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi);
-static int ftdi_elan_command_engine(struct usb_ftdi *ftdi);
-static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi);
-static int ftdi_elan_hcd_init(struct usb_ftdi *ftdi)
-{
-	if (ftdi->platform_dev.dev.parent)
-		return -EBUSY;
-
-	ftdi_elan_get_kref(ftdi);
-	ftdi->platform_data.potpg = 100;
-	ftdi->platform_data.reset = NULL;
-	ftdi->platform_dev.id = ftdi->sequence_num;
-	ftdi->platform_dev.resource = ftdi->resources;
-	ftdi->platform_dev.num_resources = ARRAY_SIZE(ftdi->resources);
-	ftdi->platform_dev.dev.platform_data = &ftdi->platform_data;
-	ftdi->platform_dev.dev.parent = NULL;
-	ftdi->platform_dev.dev.release = ftdi_release_platform_dev;
-	ftdi->platform_dev.dev.dma_mask = NULL;
-	snprintf(ftdi->device_name, sizeof(ftdi->device_name), "u132_hcd");
-	ftdi->platform_dev.name = ftdi->device_name;
-	dev_info(&ftdi->udev->dev, "requesting module '%s'\n", "u132_hcd");
-	request_module("u132_hcd");
-	dev_info(&ftdi->udev->dev, "registering '%s'\n",
-		 ftdi->platform_dev.name);
-
-	return platform_device_register(&ftdi->platform_dev);
-}
-
-static void ftdi_elan_abandon_completions(struct usb_ftdi *ftdi)
-{
-	mutex_lock(&ftdi->u132_lock);
-	while (ftdi->respond_next > ftdi->respond_head) {
-		struct u132_respond *respond = &ftdi->respond[RESPOND_MASK &
-							      ftdi->respond_head++];
-		*respond->result = -ESHUTDOWN;
-		*respond->value = 0;
-		complete(&respond->wait_completion);
-	}
-	mutex_unlock(&ftdi->u132_lock);
-}
-
-static void ftdi_elan_abandon_targets(struct usb_ftdi *ftdi)
-{
-	int ed_number = 4;
-	mutex_lock(&ftdi->u132_lock);
-	while (ed_number-- > 0) {
-		struct u132_target *target = &ftdi->target[ed_number];
-		if (target->active == 1) {
-			target->condition_code = TD_DEVNOTRESP;
-			mutex_unlock(&ftdi->u132_lock);
-			ftdi_elan_do_callback(ftdi, target, NULL, 0);
-			mutex_lock(&ftdi->u132_lock);
-		}
-	}
-	ftdi->received = 0;
-	ftdi->expected = 4;
-	ftdi->ed_found = 0;
-	mutex_unlock(&ftdi->u132_lock);
-}
-
-static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi)
-{
-	int ed_number = 4;
-	mutex_lock(&ftdi->u132_lock);
-	while (ed_number-- > 0) {
-		struct u132_target *target = &ftdi->target[ed_number];
-		target->abandoning = 1;
-	wait_1:if (target->active == 1) {
-			int command_size = ftdi->command_next -
-				ftdi->command_head;
-			if (command_size < COMMAND_SIZE) {
-				struct u132_command *command = &ftdi->command[
-					COMMAND_MASK & ftdi->command_next];
-				command->header = 0x80 | (ed_number << 5) | 0x4;
-				command->length = 0x00;
-				command->address = 0x00;
-				command->width = 0x00;
-				command->follows = 0;
-				command->value = 0;
-				command->buffer = &command->value;
-				ftdi->command_next += 1;
-				ftdi_elan_kick_command_queue(ftdi);
-			} else {
-				mutex_unlock(&ftdi->u132_lock);
-				msleep(100);
-				mutex_lock(&ftdi->u132_lock);
-				goto wait_1;
-			}
-		}
-	wait_2:if (target->active == 1) {
-			int command_size = ftdi->command_next -
-				ftdi->command_head;
-			if (command_size < COMMAND_SIZE) {
-				struct u132_command *command = &ftdi->command[
-					COMMAND_MASK & ftdi->command_next];
-				command->header = 0x90 | (ed_number << 5);
-				command->length = 0x00;
-				command->address = 0x00;
-				command->width = 0x00;
-				command->follows = 0;
-				command->value = 0;
-				command->buffer = &command->value;
-				ftdi->command_next += 1;
-				ftdi_elan_kick_command_queue(ftdi);
-			} else {
-				mutex_unlock(&ftdi->u132_lock);
-				msleep(100);
-				mutex_lock(&ftdi->u132_lock);
-				goto wait_2;
-			}
-		}
-	}
-	ftdi->received = 0;
-	ftdi->expected = 4;
-	ftdi->ed_found = 0;
-	mutex_unlock(&ftdi->u132_lock);
-}
-
-static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi)
-{
-	int ed_number = 4;
-	mutex_lock(&ftdi->u132_lock);
-	while (ed_number-- > 0) {
-		struct u132_target *target = &ftdi->target[ed_number];
-		target->abandoning = 1;
-	wait:if (target->active == 1) {
-			int command_size = ftdi->command_next -
-				ftdi->command_head;
-			if (command_size < COMMAND_SIZE) {
-				struct u132_command *command = &ftdi->command[
-					COMMAND_MASK & ftdi->command_next];
-				command->header = 0x80 | (ed_number << 5) | 0x4;
-				command->length = 0x00;
-				command->address = 0x00;
-				command->width = 0x00;
-				command->follows = 0;
-				command->value = 0;
-				command->buffer = &command->value;
-				ftdi->command_next += 1;
-				ftdi_elan_kick_command_queue(ftdi);
-			} else {
-				mutex_unlock(&ftdi->u132_lock);
-				msleep(100);
-				mutex_lock(&ftdi->u132_lock);
-				goto wait;
-			}
-		}
-	}
-	ftdi->received = 0;
-	ftdi->expected = 4;
-	ftdi->ed_found = 0;
-	mutex_unlock(&ftdi->u132_lock);
-}
-
-static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi)
-{
-	ftdi_command_queue_work(ftdi, 0);
-}
-
-static void ftdi_elan_command_work(struct work_struct *work)
-{
-	struct usb_ftdi *ftdi =
-		container_of(work, struct usb_ftdi, command_work.work);
-
-	if (ftdi->disconnected > 0) {
-		ftdi_elan_put_kref(ftdi);
-		return;
-	} else {
-		int retval = ftdi_elan_command_engine(ftdi);
-		if (retval == -ESHUTDOWN) {
-			ftdi->disconnected += 1;
-		} else if (retval == -ENODEV) {
-			ftdi->disconnected += 1;
-		} else if (retval)
-			dev_err(&ftdi->udev->dev, "command error %d\n", retval);
-		ftdi_command_requeue_work(ftdi, msecs_to_jiffies(10));
-		return;
-	}
-}
-
-static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi)
-{
-	ftdi_respond_queue_work(ftdi, 0);
-}
-
-static void ftdi_elan_respond_work(struct work_struct *work)
-{
-	struct usb_ftdi *ftdi =
-		container_of(work, struct usb_ftdi, respond_work.work);
-	if (ftdi->disconnected > 0) {
-		ftdi_elan_put_kref(ftdi);
-		return;
-	} else {
-		int retval = ftdi_elan_respond_engine(ftdi);
-		if (retval == 0) {
-		} else if (retval == -ESHUTDOWN) {
-			ftdi->disconnected += 1;
-		} else if (retval == -ENODEV) {
-			ftdi->disconnected += 1;
-		} else if (retval == -EILSEQ) {
-			ftdi->disconnected += 1;
-		} else {
-			ftdi->disconnected += 1;
-			dev_err(&ftdi->udev->dev, "respond error %d\n", retval);
-		}
-		if (ftdi->disconnected > 0) {
-			ftdi_elan_abandon_completions(ftdi);
-			ftdi_elan_abandon_targets(ftdi);
-		}
-		ftdi_response_requeue_work(ftdi, msecs_to_jiffies(10));
-		return;
-	}
-}
-
-
-/*
- * the sw_lock is initially held and will be freed
- * after the FTDI has been synchronized
- *
- */
-static void ftdi_elan_status_work(struct work_struct *work)
-{
-	struct usb_ftdi *ftdi =
-		container_of(work, struct usb_ftdi, status_work.work);
-	int work_delay_in_msec = 0;
-	if (ftdi->disconnected > 0) {
-		ftdi_elan_put_kref(ftdi);
-		return;
-	} else if (ftdi->synchronized == 0) {
-		down(&ftdi->sw_lock);
-		if (ftdi_elan_synchronize(ftdi) == 0) {
-			ftdi->synchronized = 1;
-			ftdi_command_queue_work(ftdi, 1);
-			ftdi_respond_queue_work(ftdi, 1);
-			up(&ftdi->sw_lock);
-			work_delay_in_msec = 100;
-		} else {
-			dev_err(&ftdi->udev->dev, "synchronize failed\n");
-			up(&ftdi->sw_lock);
-			work_delay_in_msec = 10 *1000;
-		}
-	} else if (ftdi->stuck_status > 0) {
-		if (ftdi_elan_stuck_waiting(ftdi) == 0) {
-			ftdi->stuck_status = 0;
-			ftdi->synchronized = 0;
-		} else if ((ftdi->stuck_status++ % 60) == 1) {
-			dev_err(&ftdi->udev->dev, "WRONG type of card inserted - please remove\n");
-		} else
-			dev_err(&ftdi->udev->dev, "WRONG type of card inserted - checked %d times\n",
-				ftdi->stuck_status);
-		work_delay_in_msec = 100;
-	} else if (ftdi->enumerated == 0) {
-		if (ftdi_elan_enumeratePCI(ftdi) == 0) {
-			ftdi->enumerated = 1;
-			work_delay_in_msec = 250;
-		} else
-			work_delay_in_msec = 1000;
-	} else if (ftdi->initialized == 0) {
-		if (ftdi_elan_setupOHCI(ftdi) == 0) {
-			ftdi->initialized = 1;
-			work_delay_in_msec = 500;
-		} else {
-			dev_err(&ftdi->udev->dev, "initialized failed - trying again in 10 seconds\n");
-			work_delay_in_msec = 1 *1000;
-		}
-	} else if (ftdi->registered == 0) {
-		work_delay_in_msec = 10;
-		if (ftdi_elan_hcd_init(ftdi) == 0) {
-			ftdi->registered = 1;
-		} else
-			dev_err(&ftdi->udev->dev, "register failed\n");
-		work_delay_in_msec = 250;
-	} else {
-		if (ftdi_elan_checkingPCI(ftdi) == 0) {
-			work_delay_in_msec = 250;
-		} else if (ftdi->controlreg & 0x00400000) {
-			if (ftdi->gone_away > 0) {
-				dev_err(&ftdi->udev->dev, "PCI device eject confirmed platform_dev.dev.parent=%p platform_dev.dev=%p\n",
-					ftdi->platform_dev.dev.parent,
-					&ftdi->platform_dev.dev);
-				platform_device_unregister(&ftdi->platform_dev);
-				ftdi->platform_dev.dev.parent = NULL;
-				ftdi->registered = 0;
-				ftdi->enumerated = 0;
-				ftdi->card_ejected = 0;
-				ftdi->initialized = 0;
-				ftdi->gone_away = 0;
-			} else
-				ftdi_elan_flush_targets(ftdi);
-			work_delay_in_msec = 250;
-		} else {
-			dev_err(&ftdi->udev->dev, "PCI device has disappeared\n");
-			ftdi_elan_cancel_targets(ftdi);
-			work_delay_in_msec = 500;
-			ftdi->enumerated = 0;
-			ftdi->initialized = 0;
-		}
-	}
-	if (ftdi->disconnected > 0) {
-		ftdi_elan_put_kref(ftdi);
-		return;
-	} else {
-		ftdi_status_requeue_work(ftdi,
-					 msecs_to_jiffies(work_delay_in_msec));
-		return;
-	}
-}
-
-
-/*
- * file_operations for the jtag interface
- *
- * the usage count for the device is incremented on open()
- * and decremented on release()
- */
-static int ftdi_elan_open(struct inode *inode, struct file *file)
-{
-	int subminor;
-	struct usb_interface *interface;
-
-	subminor = iminor(inode);
-	interface = usb_find_interface(&ftdi_elan_driver, subminor);
-
-	if (!interface) {
-		pr_err("can't find device for minor %d\n", subminor);
-		return -ENODEV;
-	} else {
-		struct usb_ftdi *ftdi = usb_get_intfdata(interface);
-		if (!ftdi) {
-			return -ENODEV;
-		} else {
-			if (down_interruptible(&ftdi->sw_lock)) {
-				return -EINTR;
-			} else {
-				ftdi_elan_get_kref(ftdi);
-				file->private_data = ftdi;
-				return 0;
-			}
-		}
-	}
-}
-
-static int ftdi_elan_release(struct inode *inode, struct file *file)
-{
-	struct usb_ftdi *ftdi = file->private_data;
-	if (ftdi == NULL)
-		return -ENODEV;
-	up(&ftdi->sw_lock);        /* decrement the count on our device */
-	ftdi_elan_put_kref(ftdi);
-	return 0;
-}
-
-
-/*
- *
- * blocking bulk reads are used to get data from the device
- *
- */
-static ssize_t ftdi_elan_read(struct file *file, char __user *buffer,
-			      size_t count, loff_t *ppos)
-{
-	char data[30 *3 + 4];
-	char *d = data;
-	int m = (sizeof(data) - 1) / 3 - 1;
-	int bytes_read = 0;
-	int retry_on_empty = 10;
-	int retry_on_timeout = 5;
-	struct usb_ftdi *ftdi = file->private_data;
-	if (ftdi->disconnected > 0) {
-		return -ENODEV;
-	}
-	data[0] = 0;
-have:if (ftdi->bulk_in_left > 0) {
-		if (count-- > 0) {
-			char *p = ++ftdi->bulk_in_last + ftdi->bulk_in_buffer;
-			ftdi->bulk_in_left -= 1;
-			if (bytes_read < m) {
-				d += sprintf(d, " %02X", 0x000000FF & *p);
-			} else if (bytes_read > m) {
-			} else
-				d += sprintf(d, " ..");
-			if (copy_to_user(buffer++, p, 1)) {
-				return -EFAULT;
-			} else {
-				bytes_read += 1;
-				goto have;
-			}
-		} else
-			return bytes_read;
-	}
-more:if (count > 0) {
-		int packet_bytes = 0;
-		int retval = usb_bulk_msg(ftdi->udev,
-					  usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
-					  ftdi->bulk_in_buffer, ftdi->bulk_in_size,
-					  &packet_bytes, 50);
-		if (packet_bytes > 2) {
-			ftdi->bulk_in_left = packet_bytes - 2;
-			ftdi->bulk_in_last = 1;
-			goto have;
-		} else if (retval == -ETIMEDOUT) {
-			if (retry_on_timeout-- > 0) {
-				goto more;
-			} else if (bytes_read > 0) {
-				return bytes_read;
-			} else
-				return retval;
-		} else if (retval == 0) {
-			if (retry_on_empty-- > 0) {
-				goto more;
-			} else
-				return bytes_read;
-		} else
-			return retval;
-	} else
-		return bytes_read;
-}
-
-static void ftdi_elan_write_bulk_callback(struct urb *urb)
-{
-	struct usb_ftdi *ftdi = urb->context;
-	int status = urb->status;
-
-	if (status && !(status == -ENOENT || status == -ECONNRESET ||
-			status == -ESHUTDOWN)) {
-		dev_err(&ftdi->udev->dev,
-			"urb=%p write bulk status received: %d\n", urb, status);
-	}
-	usb_free_coherent(urb->dev, urb->transfer_buffer_length,
-			  urb->transfer_buffer, urb->transfer_dma);
-}
-
-static int fill_buffer_with_all_queued_commands(struct usb_ftdi *ftdi,
-						char *buf, int command_size, int total_size)
-{
-	int ed_commands = 0;
-	int b = 0;
-	int I = command_size;
-	int i = ftdi->command_head;
-	while (I-- > 0) {
-		struct u132_command *command = &ftdi->command[COMMAND_MASK &
-							      i++];
-		int F = command->follows;
-		u8 *f = command->buffer;
-		if (command->header & 0x80) {
-			ed_commands |= 1 << (0x3 & (command->header >> 5));
-		}
-		buf[b++] = command->header;
-		buf[b++] = (command->length >> 0) & 0x00FF;
-		buf[b++] = (command->length >> 8) & 0x00FF;
-		buf[b++] = command->address;
-		buf[b++] = command->width;
-		while (F-- > 0) {
-			buf[b++] = *f++;
-		}
-	}
-	return ed_commands;
-}
-
-static int ftdi_elan_total_command_size(struct usb_ftdi *ftdi, int command_size)
-{
-	int total_size = 0;
-	int I = command_size;
-	int i = ftdi->command_head;
-	while (I-- > 0) {
-		struct u132_command *command = &ftdi->command[COMMAND_MASK &
-							      i++];
-		total_size += 5 + command->follows;
-	}
-	return total_size;
-}
-
-static int ftdi_elan_command_engine(struct usb_ftdi *ftdi)
-{
-	int retval;
-	char *buf;
-	int ed_commands;
-	int total_size;
-	struct urb *urb;
-	int command_size = ftdi->command_next - ftdi->command_head;
-	if (command_size == 0)
-		return 0;
-	total_size = ftdi_elan_total_command_size(ftdi, command_size);
-	urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!urb)
-		return -ENOMEM;
-	buf = usb_alloc_coherent(ftdi->udev, total_size, GFP_KERNEL,
-				 &urb->transfer_dma);
-	if (!buf) {
-		dev_err(&ftdi->udev->dev, "could not get a buffer to write %d commands totaling %d bytes to the Uxxx\n",
-			command_size, total_size);
-		usb_free_urb(urb);
-		return -ENOMEM;
-	}
-	ed_commands = fill_buffer_with_all_queued_commands(ftdi, buf,
-							   command_size, total_size);
-	usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
-							   ftdi->bulk_out_endpointAddr), buf, total_size,
-			  ftdi_elan_write_bulk_callback, ftdi);
-	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-	if (ed_commands) {
-		char diag[40 *3 + 4];
-		char *d = diag;
-		int m = total_size;
-		u8 *c = buf;
-		int s = (sizeof(diag) - 1) / 3;
-		diag[0] = 0;
-		while (s-- > 0 && m-- > 0) {
-			if (s > 0 || m == 0) {
-				d += sprintf(d, " %02X", *c++);
-			} else
-				d += sprintf(d, " ..");
-		}
-	}
-	retval = usb_submit_urb(urb, GFP_KERNEL);
-	if (retval) {
-		dev_err(&ftdi->udev->dev, "failed %d to submit urb %p to write %d commands totaling %d bytes to the Uxxx\n",
-			retval, urb, command_size, total_size);
-		usb_free_coherent(ftdi->udev, total_size, buf, urb->transfer_dma);
-		usb_free_urb(urb);
-		return retval;
-	}
-	usb_free_urb(urb);        /* release our reference to this urb,
-				     the USB core will eventually free it entirely */
-	ftdi->command_head += command_size;
-	ftdi_elan_kick_respond_queue(ftdi);
-	return 0;
-}
-
-static void ftdi_elan_do_callback(struct usb_ftdi *ftdi,
-				  struct u132_target *target, u8 *buffer, int length)
-{
-	struct urb *urb = target->urb;
-	int halted = target->halted;
-	int skipped = target->skipped;
-	int actual = target->actual;
-	int non_null = target->non_null;
-	int toggle_bits = target->toggle_bits;
-	int error_count = target->error_count;
-	int condition_code = target->condition_code;
-	int repeat_number = target->repeat_number;
-	void (*callback) (void *, struct urb *, u8 *, int, int, int, int, int,
-			  int, int, int, int) = target->callback;
-	target->active -= 1;
-	target->callback = NULL;
-	(*callback) (target->endp, urb, buffer, length, toggle_bits,
-		     error_count, condition_code, repeat_number, halted, skipped,
-		     actual, non_null);
-}
-
-static char *have_ed_set_response(struct usb_ftdi *ftdi,
-				  struct u132_target *target, u16 ed_length, int ed_number, int ed_type,
-				  char *b)
-{
-	int payload = (ed_length >> 0) & 0x07FF;
-	mutex_lock(&ftdi->u132_lock);
-	target->actual = 0;
-	target->non_null = (ed_length >> 15) & 0x0001;
-	target->repeat_number = (ed_length >> 11) & 0x000F;
-	if (ed_type == 0x02 || ed_type == 0x03) {
-		if (payload == 0 || target->abandoning > 0) {
-			target->abandoning = 0;
-			mutex_unlock(&ftdi->u132_lock);
-			ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
-					      payload);
-			ftdi->received = 0;
-			ftdi->expected = 4;
-			ftdi->ed_found = 0;
-			return ftdi->response;
-		} else {
-			ftdi->expected = 4 + payload;
-			ftdi->ed_found = 1;
-			mutex_unlock(&ftdi->u132_lock);
-			return b;
-		}
-	} else {
-		target->abandoning = 0;
-		mutex_unlock(&ftdi->u132_lock);
-		ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
-				      payload);
-		ftdi->received = 0;
-		ftdi->expected = 4;
-		ftdi->ed_found = 0;
-		return ftdi->response;
-	}
-}
-
-static char *have_ed_get_response(struct usb_ftdi *ftdi,
-				  struct u132_target *target, u16 ed_length, int ed_number, int ed_type,
-				  char *b)
-{
-	mutex_lock(&ftdi->u132_lock);
-	target->condition_code = TD_DEVNOTRESP;
-	target->actual = (ed_length >> 0) & 0x01FF;
-	target->non_null = (ed_length >> 15) & 0x0001;
-	target->repeat_number = (ed_length >> 11) & 0x000F;
-	mutex_unlock(&ftdi->u132_lock);
-	if (target->active)
-		ftdi_elan_do_callback(ftdi, target, NULL, 0);
-	target->abandoning = 0;
-	ftdi->received = 0;
-	ftdi->expected = 4;
-	ftdi->ed_found = 0;
-	return ftdi->response;
-}
-
-
-/*
- * The engine tries to empty the FTDI fifo
- *
- * all responses found in the fifo data are dispatched thus
- * the response buffer can only ever hold a maximum sized
- * response from the Uxxx.
- *
- */
-static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi)
-{
-	u8 *b = ftdi->response + ftdi->received;
-	int bytes_read = 0;
-	int retry_on_empty = 1;
-	int retry_on_timeout = 3;
-read:{
-		int packet_bytes = 0;
-		int retval = usb_bulk_msg(ftdi->udev,
-					  usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
-					  ftdi->bulk_in_buffer, ftdi->bulk_in_size,
-					  &packet_bytes, 500);
-		char diag[30 *3 + 4];
-		char *d = diag;
-		int m = packet_bytes;
-		u8 *c = ftdi->bulk_in_buffer;
-		int s = (sizeof(diag) - 1) / 3;
-		diag[0] = 0;
-		while (s-- > 0 && m-- > 0) {
-			if (s > 0 || m == 0) {
-				d += sprintf(d, " %02X", *c++);
-			} else
-				d += sprintf(d, " ..");
-		}
-		if (packet_bytes > 2) {
-			ftdi->bulk_in_left = packet_bytes - 2;
-			ftdi->bulk_in_last = 1;
-			goto have;
-		} else if (retval == -ETIMEDOUT) {
-			if (retry_on_timeout-- > 0) {
-				dev_err(&ftdi->udev->dev, "TIMED OUT with packet_bytes = %d with total %d bytes%s\n",
-					packet_bytes, bytes_read, diag);
-				goto more;
-			} else if (bytes_read > 0) {
-				dev_err(&ftdi->udev->dev, "ONLY %d bytes%s\n",
-					bytes_read, diag);
-				return -ENOMEM;
-			} else {
-				dev_err(&ftdi->udev->dev, "TIMED OUT with packet_bytes = %d with total %d bytes%s\n",
-					packet_bytes, bytes_read, diag);
-				return -ENOMEM;
-			}
-		} else if (retval == -EILSEQ) {
-			dev_err(&ftdi->udev->dev, "error = %d with packet_bytes = %d with total %d bytes%s\n",
-				retval, packet_bytes, bytes_read, diag);
-			return retval;
-		} else if (retval) {
-			dev_err(&ftdi->udev->dev, "error = %d with packet_bytes = %d with total %d bytes%s\n",
-				retval, packet_bytes, bytes_read, diag);
-			return retval;
-		} else {
-			if (retry_on_empty-- > 0) {
-				goto more;
-			} else
-				return 0;
-		}
-	}
-more:{
-		goto read;
-	}
-have:if (ftdi->bulk_in_left > 0) {
-		u8 c = ftdi->bulk_in_buffer[++ftdi->bulk_in_last];
-		bytes_read += 1;
-		ftdi->bulk_in_left -= 1;
-		if (ftdi->received == 0 && c == 0xFF) {
-			goto have;
-		} else
-			*b++ = c;
-		if (++ftdi->received < ftdi->expected) {
-			goto have;
-		} else if (ftdi->ed_found) {
-			int ed_number = (ftdi->response[0] >> 5) & 0x03;
-			u16 ed_length = (ftdi->response[2] << 8) |
-				ftdi->response[1];
-			struct u132_target *target = &ftdi->target[ed_number];
-			int payload = (ed_length >> 0) & 0x07FF;
-			char diag[30 *3 + 4];
-			char *d = diag;
-			int m = payload;
-			u8 *c = 4 + ftdi->response;
-			int s = (sizeof(diag) - 1) / 3;
-			diag[0] = 0;
-			while (s-- > 0 && m-- > 0) {
-				if (s > 0 || m == 0) {
-					d += sprintf(d, " %02X", *c++);
-				} else
-					d += sprintf(d, " ..");
-			}
-			ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
-					      payload);
-			ftdi->received = 0;
-			ftdi->expected = 4;
-			ftdi->ed_found = 0;
-			b = ftdi->response;
-			goto have;
-		} else if (ftdi->expected == 8) {
-			u8 buscmd;
-			int respond_head = ftdi->respond_head++;
-			struct u132_respond *respond = &ftdi->respond[
-				RESPOND_MASK & respond_head];
-			u32 data = ftdi->response[7];
-			data <<= 8;
-			data |= ftdi->response[6];
-			data <<= 8;
-			data |= ftdi->response[5];
-			data <<= 8;
-			data |= ftdi->response[4];
-			*respond->value = data;
-			*respond->result = 0;
-			complete(&respond->wait_completion);
-			ftdi->received = 0;
-			ftdi->expected = 4;
-			ftdi->ed_found = 0;
-			b = ftdi->response;
-			buscmd = (ftdi->response[0] >> 0) & 0x0F;
-			if (buscmd == 0x00) {
-			} else if (buscmd == 0x02) {
-			} else if (buscmd == 0x06) {
-			} else if (buscmd == 0x0A) {
-			} else
-				dev_err(&ftdi->udev->dev, "Uxxx unknown(%0X) value = %08X\n",
-					buscmd, data);
-			goto have;
-		} else {
-			if ((ftdi->response[0] & 0x80) == 0x00) {
-				ftdi->expected = 8;
-				goto have;
-			} else {
-				int ed_number = (ftdi->response[0] >> 5) & 0x03;
-				int ed_type = (ftdi->response[0] >> 0) & 0x03;
-				u16 ed_length = (ftdi->response[2] << 8) |
-					ftdi->response[1];
-				struct u132_target *target = &ftdi->target[
-					ed_number];
-				target->halted = (ftdi->response[0] >> 3) &
-					0x01;
-				target->skipped = (ftdi->response[0] >> 2) &
-					0x01;
-				target->toggle_bits = (ftdi->response[3] >> 6)
-					& 0x03;
-				target->error_count = (ftdi->response[3] >> 4)
-					& 0x03;
-				target->condition_code = (ftdi->response[
-								  3] >> 0) & 0x0F;
-				if ((ftdi->response[0] & 0x10) == 0x00) {
-					b = have_ed_set_response(ftdi, target,
-								 ed_length, ed_number, ed_type,
-								 b);
-					goto have;
-				} else {
-					b = have_ed_get_response(ftdi, target,
-								 ed_length, ed_number, ed_type,
-								 b);
-					goto have;
-				}
-			}
-		}
-	} else
-		goto more;
-}
-
-
-/*
- * create a urb, and a buffer for it, and copy the data to the urb
- *
- */
-static ssize_t ftdi_elan_write(struct file *file,
-			       const char __user *user_buffer, size_t count,
-			       loff_t *ppos)
-{
-	int retval = 0;
-	struct urb *urb;
-	char *buf;
-	struct usb_ftdi *ftdi = file->private_data;
-
-	if (ftdi->disconnected > 0) {
-		return -ENODEV;
-	}
-	if (count == 0) {
-		goto exit;
-	}
-	urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!urb) {
-		retval = -ENOMEM;
-		goto error_1;
-	}
-	buf = usb_alloc_coherent(ftdi->udev, count, GFP_KERNEL,
-				 &urb->transfer_dma);
-	if (!buf) {
-		retval = -ENOMEM;
-		goto error_2;
-	}
-	if (copy_from_user(buf, user_buffer, count)) {
-		retval = -EFAULT;
-		goto error_3;
-	}
-	usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
-							   ftdi->bulk_out_endpointAddr), buf, count,
-			  ftdi_elan_write_bulk_callback, ftdi);
-	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-	retval = usb_submit_urb(urb, GFP_KERNEL);
-	if (retval) {
-		dev_err(&ftdi->udev->dev,
-			"failed submitting write urb, error %d\n", retval);
-		goto error_3;
-	}
-	usb_free_urb(urb);
-
-exit:
-	return count;
-error_3:
-	usb_free_coherent(ftdi->udev, count, buf, urb->transfer_dma);
-error_2:
-	usb_free_urb(urb);
-error_1:
-	return retval;
-}
-
-static const struct file_operations ftdi_elan_fops = {
-	.owner = THIS_MODULE,
-	.llseek = no_llseek,
-	.read = ftdi_elan_read,
-	.write = ftdi_elan_write,
-	.open = ftdi_elan_open,
-	.release = ftdi_elan_release,
-};
-
-/*
- * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with the driver core
- */
-static struct usb_class_driver ftdi_elan_jtag_class = {
-	.name = "ftdi-%d-jtag",
-	.fops = &ftdi_elan_fops,
-	.minor_base = USB_FTDI_ELAN_MINOR_BASE,
-};
-
-/*
- * the following definitions are for the
- * ELAN FPGA state machgine processor that
- * lies on the other side of the FTDI chip
- */
-#define cPCIu132rd 0x0
-#define cPCIu132wr 0x1
-#define cPCIiord 0x2
-#define cPCIiowr 0x3
-#define cPCImemrd 0x6
-#define cPCImemwr 0x7
-#define cPCIcfgrd 0xA
-#define cPCIcfgwr 0xB
-#define cPCInull 0xF
-#define cU132cmd_status 0x0
-#define cU132flash 0x1
-#define cPIDsetup 0x0
-#define cPIDout 0x1
-#define cPIDin 0x2
-#define cPIDinonce 0x3
-#define cCCnoerror 0x0
-#define cCCcrc 0x1
-#define cCCbitstuff 0x2
-#define cCCtoggle 0x3
-#define cCCstall 0x4
-#define cCCnoresp 0x5
-#define cCCbadpid1 0x6
-#define cCCbadpid2 0x7
-#define cCCdataoverrun 0x8
-#define cCCdataunderrun 0x9
-#define cCCbuffoverrun 0xC
-#define cCCbuffunderrun 0xD
-#define cCCnotaccessed 0xF
-static int ftdi_elan_write_reg(struct usb_ftdi *ftdi, u32 data)
-{
-wait:if (ftdi->disconnected > 0) {
-		return -ENODEV;
-	} else {
-		int command_size;
-		mutex_lock(&ftdi->u132_lock);
-		command_size = ftdi->command_next - ftdi->command_head;
-		if (command_size < COMMAND_SIZE) {
-			struct u132_command *command = &ftdi->command[
-				COMMAND_MASK & ftdi->command_next];
-			command->header = 0x00 | cPCIu132wr;
-			command->length = 0x04;
-			command->address = 0x00;
-			command->width = 0x00;
-			command->follows = 4;
-			command->value = data;
-			command->buffer = &command->value;
-			ftdi->command_next += 1;
-			ftdi_elan_kick_command_queue(ftdi);
-			mutex_unlock(&ftdi->u132_lock);
-			return 0;
-		} else {
-			mutex_unlock(&ftdi->u132_lock);
-			msleep(100);
-			goto wait;
-		}
-	}
-}
-
-static int ftdi_elan_write_config(struct usb_ftdi *ftdi, int config_offset,
-				  u8 width, u32 data)
-{
-	u8 addressofs = config_offset / 4;
-wait:if (ftdi->disconnected > 0) {
-		return -ENODEV;
-	} else {
-		int command_size;
-		mutex_lock(&ftdi->u132_lock);
-		command_size = ftdi->command_next - ftdi->command_head;
-		if (command_size < COMMAND_SIZE) {
-			struct u132_command *command = &ftdi->command[
-				COMMAND_MASK & ftdi->command_next];
-			command->header = 0x00 | (cPCIcfgwr & 0x0F);
-			command->length = 0x04;
-			command->address = addressofs;
-			command->width = 0x00 | (width & 0x0F);
-			command->follows = 4;
-			command->value = data;
-			command->buffer = &command->value;
-			ftdi->command_next += 1;
-			ftdi_elan_kick_command_queue(ftdi);
-			mutex_unlock(&ftdi->u132_lock);
-			return 0;
-		} else {
-			mutex_unlock(&ftdi->u132_lock);
-			msleep(100);
-			goto wait;
-		}
-	}
-}
-
-static int ftdi_elan_write_pcimem(struct usb_ftdi *ftdi, int mem_offset,
-				  u8 width, u32 data)
-{
-	u8 addressofs = mem_offset / 4;
-wait:if (ftdi->disconnected > 0) {
-		return -ENODEV;
-	} else {
-		int command_size;
-		mutex_lock(&ftdi->u132_lock);
-		command_size = ftdi->command_next - ftdi->command_head;
-		if (command_size < COMMAND_SIZE) {
-			struct u132_command *command = &ftdi->command[
-				COMMAND_MASK & ftdi->command_next];
-			command->header = 0x00 | (cPCImemwr & 0x0F);
-			command->length = 0x04;
-			command->address = addressofs;
-			command->width = 0x00 | (width & 0x0F);
-			command->follows = 4;
-			command->value = data;
-			command->buffer = &command->value;
-			ftdi->command_next += 1;
-			ftdi_elan_kick_command_queue(ftdi);
-			mutex_unlock(&ftdi->u132_lock);
-			return 0;
-		} else {
-			mutex_unlock(&ftdi->u132_lock);
-			msleep(100);
-			goto wait;
-		}
-	}
-}
-
-int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, int mem_offset,
-			       u8 width, u32 data)
-{
-	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
-	return ftdi_elan_write_pcimem(ftdi, mem_offset, width, data);
-}
-
-
-EXPORT_SYMBOL_GPL(usb_ftdi_elan_write_pcimem);
-static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data)
-{
-wait:if (ftdi->disconnected > 0) {
-		return -ENODEV;
-	} else {
-		int command_size;
-		int respond_size;
-		mutex_lock(&ftdi->u132_lock);
-		command_size = ftdi->command_next - ftdi->command_head;
-		respond_size = ftdi->respond_next - ftdi->respond_head;
-		if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
-		{
-			struct u132_command *command = &ftdi->command[
-				COMMAND_MASK & ftdi->command_next];
-			struct u132_respond *respond = &ftdi->respond[
-				RESPOND_MASK & ftdi->respond_next];
-			int result = -ENODEV;
-			respond->result = &result;
-			respond->header = command->header = 0x00 | cPCIu132rd;
-			command->length = 0x04;
-			respond->address = command->address = cU132cmd_status;
-			command->width = 0x00;
-			command->follows = 0;
-			command->value = 0;
-			command->buffer = NULL;
-			respond->value = data;
-			init_completion(&respond->wait_completion);
-			ftdi->command_next += 1;
-			ftdi->respond_next += 1;
-			ftdi_elan_kick_command_queue(ftdi);
-			mutex_unlock(&ftdi->u132_lock);
-			wait_for_completion(&respond->wait_completion);
-			return result;
-		} else {
-			mutex_unlock(&ftdi->u132_lock);
-			msleep(100);
-			goto wait;
-		}
-	}
-}
-
-static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset,
-				 u8 width, u32 *data)
-{
-	u8 addressofs = config_offset / 4;
-wait:if (ftdi->disconnected > 0) {
-		return -ENODEV;
-	} else {
-		int command_size;
-		int respond_size;
-		mutex_lock(&ftdi->u132_lock);
-		command_size = ftdi->command_next - ftdi->command_head;
-		respond_size = ftdi->respond_next - ftdi->respond_head;
-		if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
-		{
-			struct u132_command *command = &ftdi->command[
-				COMMAND_MASK & ftdi->command_next];
-			struct u132_respond *respond = &ftdi->respond[
-				RESPOND_MASK & ftdi->respond_next];
-			int result = -ENODEV;
-			respond->result = &result;
-			respond->header = command->header = 0x00 | (cPCIcfgrd &
-								    0x0F);
-			command->length = 0x04;
-			respond->address = command->address = addressofs;
-			command->width = 0x00 | (width & 0x0F);
-			command->follows = 0;
-			command->value = 0;
-			command->buffer = NULL;
-			respond->value = data;
-			init_completion(&respond->wait_completion);
-			ftdi->command_next += 1;
-			ftdi->respond_next += 1;
-			ftdi_elan_kick_command_queue(ftdi);
-			mutex_unlock(&ftdi->u132_lock);
-			wait_for_completion(&respond->wait_completion);
-			return result;
-		} else {
-			mutex_unlock(&ftdi->u132_lock);
-			msleep(100);
-			goto wait;
-		}
-	}
-}
-
-static int ftdi_elan_read_pcimem(struct usb_ftdi *ftdi, int mem_offset,
-				 u8 width, u32 *data)
-{
-	u8 addressofs = mem_offset / 4;
-wait:if (ftdi->disconnected > 0) {
-		return -ENODEV;
-	} else {
-		int command_size;
-		int respond_size;
-		mutex_lock(&ftdi->u132_lock);
-		command_size = ftdi->command_next - ftdi->command_head;
-		respond_size = ftdi->respond_next - ftdi->respond_head;
-		if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
-		{
-			struct u132_command *command = &ftdi->command[
-				COMMAND_MASK & ftdi->command_next];
-			struct u132_respond *respond = &ftdi->respond[
-				RESPOND_MASK & ftdi->respond_next];
-			int result = -ENODEV;
-			respond->result = &result;
-			respond->header = command->header = 0x00 | (cPCImemrd &
-								    0x0F);
-			command->length = 0x04;
-			respond->address = command->address = addressofs;
-			command->width = 0x00 | (width & 0x0F);
-			command->follows = 0;
-			command->value = 0;
-			command->buffer = NULL;
-			respond->value = data;
-			init_completion(&respond->wait_completion);
-			ftdi->command_next += 1;
-			ftdi->respond_next += 1;
-			ftdi_elan_kick_command_queue(ftdi);
-			mutex_unlock(&ftdi->u132_lock);
-			wait_for_completion(&respond->wait_completion);
-			return result;
-		} else {
-			mutex_unlock(&ftdi->u132_lock);
-			msleep(100);
-			goto wait;
-		}
-	}
-}
-
-int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, int mem_offset,
-			      u8 width, u32 *data)
-{
-	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
-	if (ftdi->initialized == 0) {
-		return -ENODEV;
-	} else
-		return ftdi_elan_read_pcimem(ftdi, mem_offset, width, data);
-}
-
-
-EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_pcimem);
-static int ftdi_elan_edset_setup(struct usb_ftdi *ftdi, u8 ed_number,
-				 void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
-				 void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-						   int toggle_bits, int error_count, int condition_code, int repeat_number,
-						   int halted, int skipped, int actual, int non_null))
-{
-	u8 ed = ed_number - 1;
-wait:if (ftdi->disconnected > 0) {
-		return -ENODEV;
-	} else if (ftdi->initialized == 0) {
-		return -ENODEV;
-	} else {
-		int command_size;
-		mutex_lock(&ftdi->u132_lock);
-		command_size = ftdi->command_next - ftdi->command_head;
-		if (command_size < COMMAND_SIZE) {
-			struct u132_target *target = &ftdi->target[ed];
-			struct u132_command *command = &ftdi->command[
-				COMMAND_MASK & ftdi->command_next];
-			command->header = 0x80 | (ed << 5);
-			command->length = 0x8007;
-			command->address = (toggle_bits << 6) | (ep_number << 2)
-				| (address << 0);
-			command->width = usb_maxpacket(urb->dev, urb->pipe);
-			command->follows = 8;
-			command->value = 0;
-			command->buffer = urb->setup_packet;
-			target->callback = callback;
-			target->endp = endp;
-			target->urb = urb;
-			target->active = 1;
-			ftdi->command_next += 1;
-			ftdi_elan_kick_command_queue(ftdi);
-			mutex_unlock(&ftdi->u132_lock);
-			return 0;
-		} else {
-			mutex_unlock(&ftdi->u132_lock);
-			msleep(100);
-			goto wait;
-		}
-	}
-}
-
-int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number,
-			      void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
-			      void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-						int toggle_bits, int error_count, int condition_code, int repeat_number,
-						int halted, int skipped, int actual, int non_null))
-{
-	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
-	return ftdi_elan_edset_setup(ftdi, ed_number, endp, urb, address,
-				     ep_number, toggle_bits, callback);
-}
-
-
-EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_setup);
-static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number,
-				 void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
-				 void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-						   int toggle_bits, int error_count, int condition_code, int repeat_number,
-						   int halted, int skipped, int actual, int non_null))
-{
-	u8 ed = ed_number - 1;
-wait:if (ftdi->disconnected > 0) {
-		return -ENODEV;
-	} else if (ftdi->initialized == 0) {
-		return -ENODEV;
-	} else {
-		int command_size;
-		mutex_lock(&ftdi->u132_lock);
-		command_size = ftdi->command_next - ftdi->command_head;
-		if (command_size < COMMAND_SIZE) {
-			struct u132_target *target = &ftdi->target[ed];
-			struct u132_command *command = &ftdi->command[
-				COMMAND_MASK & ftdi->command_next];
-			u32 remaining_length = urb->transfer_buffer_length -
-				urb->actual_length;
-			command->header = 0x82 | (ed << 5);
-			if (remaining_length == 0) {
-				command->length = 0x0000;
-			} else if (remaining_length > 1024) {
-				command->length = 0x8000 | 1023;
-			} else
-				command->length = 0x8000 | (remaining_length -
-							    1);
-			command->address = (toggle_bits << 6) | (ep_number << 2)
-				| (address << 0);
-			command->width = usb_maxpacket(urb->dev, urb->pipe);
-			command->follows = 0;
-			command->value = 0;
-			command->buffer = NULL;
-			target->callback = callback;
-			target->endp = endp;
-			target->urb = urb;
-			target->active = 1;
-			ftdi->command_next += 1;
-			ftdi_elan_kick_command_queue(ftdi);
-			mutex_unlock(&ftdi->u132_lock);
-			return 0;
-		} else {
-			mutex_unlock(&ftdi->u132_lock);
-			msleep(100);
-			goto wait;
-		}
-	}
-}
-
-int usb_ftdi_elan_edset_input(struct platform_device *pdev, u8 ed_number,
-			      void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
-			      void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-						int toggle_bits, int error_count, int condition_code, int repeat_number,
-						int halted, int skipped, int actual, int non_null))
-{
-	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
-	return ftdi_elan_edset_input(ftdi, ed_number, endp, urb, address,
-				     ep_number, toggle_bits, callback);
-}
-
-
-EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_input);
-static int ftdi_elan_edset_empty(struct usb_ftdi *ftdi, u8 ed_number,
-				 void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
-				 void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-						   int toggle_bits, int error_count, int condition_code, int repeat_number,
-						   int halted, int skipped, int actual, int non_null))
-{
-	u8 ed = ed_number - 1;
-wait:if (ftdi->disconnected > 0) {
-		return -ENODEV;
-	} else if (ftdi->initialized == 0) {
-		return -ENODEV;
-	} else {
-		int command_size;
-		mutex_lock(&ftdi->u132_lock);
-		command_size = ftdi->command_next - ftdi->command_head;
-		if (command_size < COMMAND_SIZE) {
-			struct u132_target *target = &ftdi->target[ed];
-			struct u132_command *command = &ftdi->command[
-				COMMAND_MASK & ftdi->command_next];
-			command->header = 0x81 | (ed << 5);
-			command->length = 0x0000;
-			command->address = (toggle_bits << 6) | (ep_number << 2)
-				| (address << 0);
-			command->width = usb_maxpacket(urb->dev, urb->pipe);
-			command->follows = 0;
-			command->value = 0;
-			command->buffer = NULL;
-			target->callback = callback;
-			target->endp = endp;
-			target->urb = urb;
-			target->active = 1;
-			ftdi->command_next += 1;
-			ftdi_elan_kick_command_queue(ftdi);
-			mutex_unlock(&ftdi->u132_lock);
-			return 0;
-		} else {
-			mutex_unlock(&ftdi->u132_lock);
-			msleep(100);
-			goto wait;
-		}
-	}
-}
-
-int usb_ftdi_elan_edset_empty(struct platform_device *pdev, u8 ed_number,
-			      void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
-			      void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-						int toggle_bits, int error_count, int condition_code, int repeat_number,
-						int halted, int skipped, int actual, int non_null))
-{
-	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
-	return ftdi_elan_edset_empty(ftdi, ed_number, endp, urb, address,
-				     ep_number, toggle_bits, callback);
-}
-
-
-EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_empty);
-static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number,
-				  void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
-				  void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-						    int toggle_bits, int error_count, int condition_code, int repeat_number,
-						    int halted, int skipped, int actual, int non_null))
-{
-	u8 ed = ed_number - 1;
-wait:if (ftdi->disconnected > 0) {
-		return -ENODEV;
-	} else if (ftdi->initialized == 0) {
-		return -ENODEV;
-	} else {
-		int command_size;
-		mutex_lock(&ftdi->u132_lock);
-		command_size = ftdi->command_next - ftdi->command_head;
-		if (command_size < COMMAND_SIZE) {
-			u8 *b;
-			u16 urb_size;
-			int i = 0;
-			char data[30 *3 + 4];
-			char *d = data;
-			int m = (sizeof(data) - 1) / 3 - 1;
-			struct u132_target *target = &ftdi->target[ed];
-			struct u132_command *command = &ftdi->command[
-				COMMAND_MASK & ftdi->command_next];
-			command->header = 0x81 | (ed << 5);
-			command->address = (toggle_bits << 6) | (ep_number << 2)
-				| (address << 0);
-			command->width = usb_maxpacket(urb->dev, urb->pipe);
-			command->follows = min_t(u32, 1024,
-						 urb->transfer_buffer_length -
-						 urb->actual_length);
-			command->value = 0;
-			command->buffer = urb->transfer_buffer +
-				urb->actual_length;
-			command->length = 0x8000 | (command->follows - 1);
-			b = command->buffer;
-			urb_size = command->follows;
-			data[0] = 0;
-			while (urb_size-- > 0) {
-				if (i > m) {
-				} else if (i++ < m) {
-					int w = sprintf(d, " %02X", *b++);
-					d += w;
-				} else
-					d += sprintf(d, " ..");
-			}
-			target->callback = callback;
-			target->endp = endp;
-			target->urb = urb;
-			target->active = 1;
-			ftdi->command_next += 1;
-			ftdi_elan_kick_command_queue(ftdi);
-			mutex_unlock(&ftdi->u132_lock);
-			return 0;
-		} else {
-			mutex_unlock(&ftdi->u132_lock);
-			msleep(100);
-			goto wait;
-		}
-	}
-}
-
-int usb_ftdi_elan_edset_output(struct platform_device *pdev, u8 ed_number,
-			       void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
-			       void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-						 int toggle_bits, int error_count, int condition_code, int repeat_number,
-						 int halted, int skipped, int actual, int non_null))
-{
-	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
-	return ftdi_elan_edset_output(ftdi, ed_number, endp, urb, address,
-				      ep_number, toggle_bits, callback);
-}
-
-
-EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_output);
-static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number,
-				  void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
-				  void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-						    int toggle_bits, int error_count, int condition_code, int repeat_number,
-						    int halted, int skipped, int actual, int non_null))
-{
-	u8 ed = ed_number - 1;
-wait:if (ftdi->disconnected > 0) {
-		return -ENODEV;
-	} else if (ftdi->initialized == 0) {
-		return -ENODEV;
-	} else {
-		int command_size;
-		mutex_lock(&ftdi->u132_lock);
-		command_size = ftdi->command_next - ftdi->command_head;
-		if (command_size < COMMAND_SIZE) {
-			u32 remaining_length = urb->transfer_buffer_length -
-				urb->actual_length;
-			struct u132_target *target = &ftdi->target[ed];
-			struct u132_command *command = &ftdi->command[
-				COMMAND_MASK & ftdi->command_next];
-			command->header = 0x83 | (ed << 5);
-			if (remaining_length == 0) {
-				command->length = 0x0000;
-			} else if (remaining_length > 1024) {
-				command->length = 0x8000 | 1023;
-			} else
-				command->length = 0x8000 | (remaining_length -
-							    1);
-			command->address = (toggle_bits << 6) | (ep_number << 2)
-				| (address << 0);
-			command->width = usb_maxpacket(urb->dev, urb->pipe);
-			command->follows = 0;
-			command->value = 0;
-			command->buffer = NULL;
-			target->callback = callback;
-			target->endp = endp;
-			target->urb = urb;
-			target->active = 1;
-			ftdi->command_next += 1;
-			ftdi_elan_kick_command_queue(ftdi);
-			mutex_unlock(&ftdi->u132_lock);
-			return 0;
-		} else {
-			mutex_unlock(&ftdi->u132_lock);
-			msleep(100);
-			goto wait;
-		}
-	}
-}
-
-int usb_ftdi_elan_edset_single(struct platform_device *pdev, u8 ed_number,
-			       void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
-			       void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
-						 int toggle_bits, int error_count, int condition_code, int repeat_number,
-						 int halted, int skipped, int actual, int non_null))
-{
-	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
-	return ftdi_elan_edset_single(ftdi, ed_number, endp, urb, address,
-				      ep_number, toggle_bits, callback);
-}
-
-
-EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_single);
-static int ftdi_elan_edset_flush(struct usb_ftdi *ftdi, u8 ed_number,
-				 void *endp)
-{
-	u8 ed = ed_number - 1;
-	if (ftdi->disconnected > 0) {
-		return -ENODEV;
-	} else if (ftdi->initialized == 0) {
-		return -ENODEV;
-	} else {
-		struct u132_target *target = &ftdi->target[ed];
-		mutex_lock(&ftdi->u132_lock);
-		if (target->abandoning > 0) {
-			mutex_unlock(&ftdi->u132_lock);
-			return 0;
-		} else {
-			target->abandoning = 1;
-		wait_1:if (target->active == 1) {
-				int command_size = ftdi->command_next -
-					ftdi->command_head;
-				if (command_size < COMMAND_SIZE) {
-					struct u132_command *command =
-						&ftdi->command[COMMAND_MASK &
-							       ftdi->command_next];
-					command->header = 0x80 | (ed << 5) |
-						0x4;
-					command->length = 0x00;
-					command->address = 0x00;
-					command->width = 0x00;
-					command->follows = 0;
-					command->value = 0;
-					command->buffer = &command->value;
-					ftdi->command_next += 1;
-					ftdi_elan_kick_command_queue(ftdi);
-				} else {
-					mutex_unlock(&ftdi->u132_lock);
-					msleep(100);
-					mutex_lock(&ftdi->u132_lock);
-					goto wait_1;
-				}
-			}
-			mutex_unlock(&ftdi->u132_lock);
-			return 0;
-		}
-	}
-}
-
-int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number,
-			      void *endp)
-{
-	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
-	return ftdi_elan_edset_flush(ftdi, ed_number, endp);
-}
-
-
-EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_flush);
-static int ftdi_elan_flush_input_fifo(struct usb_ftdi *ftdi)
-{
-	int retry_on_empty = 10;
-	int retry_on_timeout = 5;
-	int retry_on_status = 20;
-more:{
-		int packet_bytes = 0;
-		int retval = usb_bulk_msg(ftdi->udev,
-					  usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
-					  ftdi->bulk_in_buffer, ftdi->bulk_in_size,
-					  &packet_bytes, 100);
-		if (packet_bytes > 2) {
-			char diag[30 *3 + 4];
-			char *d = diag;
-			int m = (sizeof(diag) - 1) / 3 - 1;
-			char *b = ftdi->bulk_in_buffer;
-			int bytes_read = 0;
-			diag[0] = 0;
-			while (packet_bytes-- > 0) {
-				char c = *b++;
-				if (bytes_read < m) {
-					d += sprintf(d, " %02X",
-						     0x000000FF & c);
-				} else if (bytes_read > m) {
-				} else
-					d += sprintf(d, " ..");
-				bytes_read += 1;
-				continue;
-			}
-			goto more;
-		} else if (packet_bytes > 1) {
-			char s1 = ftdi->bulk_in_buffer[0];
-			char s2 = ftdi->bulk_in_buffer[1];
-			if (s1 == 0x31 && s2 == 0x60) {
-				return 0;
-			} else if (retry_on_status-- > 0) {
-				goto more;
-			} else {
-				dev_err(&ftdi->udev->dev, "STATUS ERROR retry limit reached\n");
-				return -EFAULT;
-			}
-		} else if (packet_bytes > 0) {
-			char b1 = ftdi->bulk_in_buffer[0];
-			dev_err(&ftdi->udev->dev, "only one byte flushed from FTDI = %02X\n",
-				b1);
-			if (retry_on_status-- > 0) {
-				goto more;
-			} else {
-				dev_err(&ftdi->udev->dev, "STATUS ERROR retry limit reached\n");
-				return -EFAULT;
-			}
-		} else if (retval == -ETIMEDOUT) {
-			if (retry_on_timeout-- > 0) {
-				goto more;
-			} else {
-				dev_err(&ftdi->udev->dev, "TIMED OUT retry limit reached\n");
-				return -ENOMEM;
-			}
-		} else if (retval == 0) {
-			if (retry_on_empty-- > 0) {
-				goto more;
-			} else {
-				dev_err(&ftdi->udev->dev, "empty packet retry limit reached\n");
-				return -ENOMEM;
-			}
-		} else {
-			dev_err(&ftdi->udev->dev, "error = %d\n", retval);
-			return retval;
-		}
-	}
-	return -1;
-}
-
-
-/*
- * send the long flush sequence
- *
- */
-static int ftdi_elan_synchronize_flush(struct usb_ftdi *ftdi)
-{
-	int retval;
-	struct urb *urb;
-	char *buf;
-	int I = 257;
-	int i = 0;
-	urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!urb)
-		return -ENOMEM;
-	buf = usb_alloc_coherent(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma);
-	if (!buf) {
-		dev_err(&ftdi->udev->dev, "could not get a buffer for flush sequence\n");
-		usb_free_urb(urb);
-		return -ENOMEM;
-	}
-	while (I-- > 0)
-		buf[i++] = 0x55;
-	usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
-							   ftdi->bulk_out_endpointAddr), buf, i,
-			  ftdi_elan_write_bulk_callback, ftdi);
-	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-	retval = usb_submit_urb(urb, GFP_KERNEL);
-	if (retval) {
-		dev_err(&ftdi->udev->dev, "failed to submit urb containing the flush sequence\n");
-		usb_free_coherent(ftdi->udev, i, buf, urb->transfer_dma);
-		usb_free_urb(urb);
-		return -ENOMEM;
-	}
-	usb_free_urb(urb);
-	return 0;
-}
-
-
-/*
- * send the reset sequence
- *
- */
-static int ftdi_elan_synchronize_reset(struct usb_ftdi *ftdi)
-{
-	int retval;
-	struct urb *urb;
-	char *buf;
-	int I = 4;
-	int i = 0;
-	urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!urb)
-		return -ENOMEM;
-	buf = usb_alloc_coherent(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma);
-	if (!buf) {
-		dev_err(&ftdi->udev->dev, "could not get a buffer for the reset sequence\n");
-		usb_free_urb(urb);
-		return -ENOMEM;
-	}
-	buf[i++] = 0x55;
-	buf[i++] = 0xAA;
-	buf[i++] = 0x5A;
-	buf[i++] = 0xA5;
-	usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
-							   ftdi->bulk_out_endpointAddr), buf, i,
-			  ftdi_elan_write_bulk_callback, ftdi);
-	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-	retval = usb_submit_urb(urb, GFP_KERNEL);
-	if (retval) {
-		dev_err(&ftdi->udev->dev, "failed to submit urb containing the reset sequence\n");
-		usb_free_coherent(ftdi->udev, i, buf, urb->transfer_dma);
-		usb_free_urb(urb);
-		return -ENOMEM;
-	}
-	usb_free_urb(urb);
-	return 0;
-}
-
-static int ftdi_elan_synchronize(struct usb_ftdi *ftdi)
-{
-	int retval;
-	int long_stop = 10;
-	int retry_on_timeout = 5;
-	int retry_on_empty = 10;
-	retval = ftdi_elan_flush_input_fifo(ftdi);
-	if (retval)
-		return retval;
-	ftdi->bulk_in_left = 0;
-	ftdi->bulk_in_last = -1;
-	while (long_stop-- > 0) {
-		int read_stop;
-		int read_stuck;
-		retval = ftdi_elan_synchronize_flush(ftdi);
-		if (retval)
-			return retval;
-		retval = ftdi_elan_flush_input_fifo(ftdi);
-		if (retval)
-			return retval;
-	reset:retval = ftdi_elan_synchronize_reset(ftdi);
-		if (retval)
-			return retval;
-		read_stop = 100;
-		read_stuck = 10;
-	read:{
-			int packet_bytes = 0;
-			retval = usb_bulk_msg(ftdi->udev,
-					      usb_rcvbulkpipe(ftdi->udev,
-							      ftdi->bulk_in_endpointAddr),
-					      ftdi->bulk_in_buffer, ftdi->bulk_in_size,
-					      &packet_bytes, 500);
-			if (packet_bytes > 2) {
-				char diag[30 *3 + 4];
-				char *d = diag;
-				int m = (sizeof(diag) - 1) / 3 - 1;
-				char *b = ftdi->bulk_in_buffer;
-				int bytes_read = 0;
-				unsigned char c = 0;
-				diag[0] = 0;
-				while (packet_bytes-- > 0) {
-					c = *b++;
-					if (bytes_read < m) {
-						d += sprintf(d, " %02X", c);
-					} else if (bytes_read > m) {
-					} else
-						d += sprintf(d, " ..");
-					bytes_read += 1;
-					continue;
-				}
-				if (c == 0x7E) {
-					return 0;
-				} else {
-					if (c == 0x55) {
-						goto read;
-					} else if (read_stop-- > 0) {
-						goto read;
-					} else {
-						dev_err(&ftdi->udev->dev, "retry limit reached\n");
-						continue;
-					}
-				}
-			} else if (packet_bytes > 1) {
-				unsigned char s1 = ftdi->bulk_in_buffer[0];
-				unsigned char s2 = ftdi->bulk_in_buffer[1];
-				if (s1 == 0x31 && s2 == 0x00) {
-					if (read_stuck-- > 0) {
-						goto read;
-					} else
-						goto reset;
-				} else {
-					if (read_stop-- > 0) {
-						goto read;
-					} else {
-						dev_err(&ftdi->udev->dev, "retry limit reached\n");
-						continue;
-					}
-				}
-			} else if (packet_bytes > 0) {
-				if (read_stop-- > 0) {
-					goto read;
-				} else {
-					dev_err(&ftdi->udev->dev, "retry limit reached\n");
-					continue;
-				}
-			} else if (retval == -ETIMEDOUT) {
-				if (retry_on_timeout-- > 0) {
-					goto read;
-				} else {
-					dev_err(&ftdi->udev->dev, "TIMED OUT retry limit reached\n");
-					continue;
-				}
-			} else if (retval == 0) {
-				if (retry_on_empty-- > 0) {
-					goto read;
-				} else {
-					dev_err(&ftdi->udev->dev, "empty packet retry limit reached\n");
-					continue;
-				}
-			} else {
-				dev_err(&ftdi->udev->dev, "error = %d\n",
-					retval);
-				if (read_stop-- > 0) {
-					goto read;
-				} else {
-					dev_err(&ftdi->udev->dev, "retry limit reached\n");
-					continue;
-				}
-			}
-		}
-	}
-	dev_err(&ftdi->udev->dev, "failed to synchronize\n");
-	return -EFAULT;
-}
-
-static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi)
-{
-	int retry_on_empty = 10;
-	int retry_on_timeout = 5;
-	int retry_on_status = 50;
-more:{
-		int packet_bytes = 0;
-		int retval = usb_bulk_msg(ftdi->udev,
-					  usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
-					  ftdi->bulk_in_buffer, ftdi->bulk_in_size,
-					  &packet_bytes, 1000);
-		if (packet_bytes > 2) {
-			char diag[30 *3 + 4];
-			char *d = diag;
-			int m = (sizeof(diag) - 1) / 3 - 1;
-			char *b = ftdi->bulk_in_buffer;
-			int bytes_read = 0;
-			diag[0] = 0;
-			while (packet_bytes-- > 0) {
-				char c = *b++;
-				if (bytes_read < m) {
-					d += sprintf(d, " %02X",
-						     0x000000FF & c);
-				} else if (bytes_read > m) {
-				} else
-					d += sprintf(d, " ..");
-				bytes_read += 1;
-			}
-			goto more;
-		} else if (packet_bytes > 1) {
-			char s1 = ftdi->bulk_in_buffer[0];
-			char s2 = ftdi->bulk_in_buffer[1];
-			if (s1 == 0x31 && s2 == 0x60) {
-				return 0;
-			} else if (retry_on_status-- > 0) {
-				msleep(5);
-				goto more;
-			} else
-				return -EFAULT;
-		} else if (packet_bytes > 0) {
-			char b1 = ftdi->bulk_in_buffer[0];
-			dev_err(&ftdi->udev->dev, "only one byte flushed from FTDI = %02X\n", b1);
-			if (retry_on_status-- > 0) {
-				msleep(5);
-				goto more;
-			} else {
-				dev_err(&ftdi->udev->dev, "STATUS ERROR retry limit reached\n");
-				return -EFAULT;
-			}
-		} else if (retval == -ETIMEDOUT) {
-			if (retry_on_timeout-- > 0) {
-				goto more;
-			} else {
-				dev_err(&ftdi->udev->dev, "TIMED OUT retry limit reached\n");
-				return -ENOMEM;
-			}
-		} else if (retval == 0) {
-			if (retry_on_empty-- > 0) {
-				goto more;
-			} else {
-				dev_err(&ftdi->udev->dev, "empty packet retry limit reached\n");
-				return -ENOMEM;
-			}
-		} else {
-			dev_err(&ftdi->udev->dev, "error = %d\n", retval);
-			return -ENOMEM;
-		}
-	}
-	return -1;
-}
-
-static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi)
-{
-	int UxxxStatus = ftdi_elan_read_reg(ftdi, &ftdi->controlreg);
-	if (UxxxStatus)
-		return UxxxStatus;
-	if (ftdi->controlreg & 0x00400000) {
-		if (ftdi->card_ejected) {
-		} else {
-			ftdi->card_ejected = 1;
-			dev_err(&ftdi->udev->dev, "CARD EJECTED - controlreg = %08X\n",
-				ftdi->controlreg);
-		}
-		return -ENODEV;
-	} else {
-		u8 fn = ftdi->function - 1;
-		int activePCIfn = fn << 8;
-		u32 pcidata;
-		u32 pciVID;
-		u32 pciPID;
-		int reg = 0;
-		UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
-						   &pcidata);
-		if (UxxxStatus)
-			return UxxxStatus;
-		pciVID = pcidata & 0xFFFF;
-		pciPID = (pcidata >> 16) & 0xFFFF;
-		if (pciVID == ftdi->platform_data.vendor && pciPID ==
-		    ftdi->platform_data.device) {
-			return 0;
-		} else {
-			dev_err(&ftdi->udev->dev, "vendor=%04X pciVID=%04X device=%04X pciPID=%04X\n",
-				ftdi->platform_data.vendor, pciVID,
-				ftdi->platform_data.device, pciPID);
-			return -ENODEV;
-		}
-	}
-}
-
-
-#define ftdi_read_pcimem(ftdi, member, data) ftdi_elan_read_pcimem(ftdi, \
-								   offsetof(struct ohci_regs, member), 0, data);
-#define ftdi_write_pcimem(ftdi, member, data) ftdi_elan_write_pcimem(ftdi, \
-								     offsetof(struct ohci_regs, member), 0, data);
-
-#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
-#define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD |	\
-			OHCI_INTR_WDH)
-static int ftdi_elan_check_controller(struct usb_ftdi *ftdi, int quirk)
-{
-	int devices = 0;
-	int retval;
-	u32 hc_control;
-	int num_ports;
-	u32 control;
-	u32 rh_a = -1;
-	u32 status;
-	u32 fminterval;
-	u32 hc_fminterval;
-	u32 periodicstart;
-	u32 cmdstatus;
-	u32 roothub_a;
-	int mask = OHCI_INTR_INIT;
-	int sleep_time = 0;
-	int reset_timeout = 30;        /* ... allow extra time */
-	int temp;
-	retval = ftdi_write_pcimem(ftdi, intrdisable, OHCI_INTR_MIE);
-	if (retval)
-		return retval;
-	retval = ftdi_read_pcimem(ftdi, control, &control);
-	if (retval)
-		return retval;
-	retval = ftdi_read_pcimem(ftdi, roothub.a, &rh_a);
-	if (retval)
-		return retval;
-	num_ports = rh_a & RH_A_NDP;
-	retval = ftdi_read_pcimem(ftdi, fminterval, &hc_fminterval);
-	if (retval)
-		return retval;
-	hc_fminterval &= 0x3fff;
-	if (hc_fminterval != FI) {
-	}
-	hc_fminterval |= FSMP(hc_fminterval) << 16;
-	retval = ftdi_read_pcimem(ftdi, control, &hc_control);
-	if (retval)
-		return retval;
-	switch (hc_control & OHCI_CTRL_HCFS) {
-	case OHCI_USB_OPER:
-		sleep_time = 0;
-		break;
-	case OHCI_USB_SUSPEND:
-	case OHCI_USB_RESUME:
-		hc_control &= OHCI_CTRL_RWC;
-		hc_control |= OHCI_USB_RESUME;
-		sleep_time = 10;
-		break;
-	default:
-		hc_control &= OHCI_CTRL_RWC;
-		hc_control |= OHCI_USB_RESET;
-		sleep_time = 50;
-		break;
-	}
-	retval = ftdi_write_pcimem(ftdi, control, hc_control);
-	if (retval)
-		return retval;
-	retval = ftdi_read_pcimem(ftdi, control, &control);
-	if (retval)
-		return retval;
-	msleep(sleep_time);
-	retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a);
-	if (retval)
-		return retval;
-	if (!(roothub_a & RH_A_NPS)) {        /* power down each port */
-		for (temp = 0; temp < num_ports; temp++) {
-			retval = ftdi_write_pcimem(ftdi,
-						   roothub.portstatus[temp], RH_PS_LSDA);
-			if (retval)
-				return retval;
-		}
-	}
-	retval = ftdi_read_pcimem(ftdi, control, &control);
-	if (retval)
-		return retval;
-retry:retval = ftdi_read_pcimem(ftdi, cmdstatus, &status);
-	if (retval)
-		return retval;
-	retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_HCR);
-	if (retval)
-		return retval;
-extra:{
-		retval = ftdi_read_pcimem(ftdi, cmdstatus, &status);
-		if (retval)
-			return retval;
-		if (0 != (status & OHCI_HCR)) {
-			if (--reset_timeout == 0) {
-				dev_err(&ftdi->udev->dev, "USB HC reset timed out!\n");
-				return -ENODEV;
-			} else {
-				msleep(5);
-				goto extra;
-			}
-		}
-	}
-	if (quirk & OHCI_QUIRK_INITRESET) {
-		retval = ftdi_write_pcimem(ftdi, control, hc_control);
-		if (retval)
-			return retval;
-		retval = ftdi_read_pcimem(ftdi, control, &control);
-		if (retval)
-			return retval;
-	}
-	retval = ftdi_write_pcimem(ftdi, ed_controlhead, 0x00000000);
-	if (retval)
-		return retval;
-	retval = ftdi_write_pcimem(ftdi, ed_bulkhead, 0x11000000);
-	if (retval)
-		return retval;
-	retval = ftdi_write_pcimem(ftdi, hcca, 0x00000000);
-	if (retval)
-		return retval;
-	retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval);
-	if (retval)
-		return retval;
-	retval = ftdi_write_pcimem(ftdi, fminterval,
-				   ((fminterval & FIT) ^ FIT) | hc_fminterval);
-	if (retval)
-		return retval;
-	retval = ftdi_write_pcimem(ftdi, periodicstart,
-				   ((9 *hc_fminterval) / 10) & 0x3fff);
-	if (retval)
-		return retval;
-	retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval);
-	if (retval)
-		return retval;
-	retval = ftdi_read_pcimem(ftdi, periodicstart, &periodicstart);
-	if (retval)
-		return retval;
-	if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
-		if (!(quirk & OHCI_QUIRK_INITRESET)) {
-			quirk |= OHCI_QUIRK_INITRESET;
-			goto retry;
-		} else
-			dev_err(&ftdi->udev->dev, "init err(%08x %04x)\n",
-				fminterval, periodicstart);
-	}                        /* start controller operations */
-	hc_control &= OHCI_CTRL_RWC;
-	hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
-	retval = ftdi_write_pcimem(ftdi, control, hc_control);
-	if (retval)
-		return retval;
-	retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_BLF);
-	if (retval)
-		return retval;
-	retval = ftdi_read_pcimem(ftdi, cmdstatus, &cmdstatus);
-	if (retval)
-		return retval;
-	retval = ftdi_read_pcimem(ftdi, control, &control);
-	if (retval)
-		return retval;
-	retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_DRWE);
-	if (retval)
-		return retval;
-	retval = ftdi_write_pcimem(ftdi, intrstatus, mask);
-	if (retval)
-		return retval;
-	retval = ftdi_write_pcimem(ftdi, intrdisable,
-				   OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
-				   OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
-				   OHCI_INTR_SO);
-	if (retval)
-		return retval;        /* handle root hub init quirks ... */
-	retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a);
-	if (retval)
-		return retval;
-	roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
-	if (quirk & OHCI_QUIRK_SUPERIO) {
-		roothub_a |= RH_A_NOCP;
-		roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
-		retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a);
-		if (retval)
-			return retval;
-	} else if ((quirk & OHCI_QUIRK_AMD756) || distrust_firmware) {
-		roothub_a |= RH_A_NPS;
-		retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a);
-		if (retval)
-			return retval;
-	}
-	retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_LPSC);
-	if (retval)
-		return retval;
-	retval = ftdi_write_pcimem(ftdi, roothub.b,
-				   (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
-	if (retval)
-		return retval;
-	retval = ftdi_read_pcimem(ftdi, control, &control);
-	if (retval)
-		return retval;
-	mdelay((roothub_a >> 23) & 0x1fe);
-	for (temp = 0; temp < num_ports; temp++) {
-		u32 portstatus;
-		retval = ftdi_read_pcimem(ftdi, roothub.portstatus[temp],
-					  &portstatus);
-		if (retval)
-			return retval;
-		if (1 & portstatus)
-			devices += 1;
-	}
-	return devices;
-}
-
-static int ftdi_elan_setup_controller(struct usb_ftdi *ftdi, int fn)
-{
-	u32 latence_timer;
-	int UxxxStatus;
-	u32 pcidata;
-	int reg = 0;
-	int activePCIfn = fn << 8;
-	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800);
-	if (UxxxStatus)
-		return UxxxStatus;
-	reg = 16;
-	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
-					    0xFFFFFFFF);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
-					   &pcidata);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
-					    0xF0000000);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
-					   &pcidata);
-	if (UxxxStatus)
-		return UxxxStatus;
-	reg = 12;
-	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
-					   &latence_timer);
-	if (UxxxStatus)
-		return UxxxStatus;
-	latence_timer &= 0xFFFF00FF;
-	latence_timer |= 0x00001600;
-	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
-					    latence_timer);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
-					   &pcidata);
-	if (UxxxStatus)
-		return UxxxStatus;
-	reg = 4;
-	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
-					    0x06);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
-					   &pcidata);
-	if (UxxxStatus)
-		return UxxxStatus;
-	for (reg = 0; reg <= 0x54; reg += 4) {
-		UxxxStatus = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
-		if (UxxxStatus)
-			return UxxxStatus;
-	}
-	return 0;
-}
-
-static int ftdi_elan_close_controller(struct usb_ftdi *ftdi, int fn)
-{
-	u32 latence_timer;
-	int UxxxStatus;
-	u32 pcidata;
-	int reg = 0;
-	int activePCIfn = fn << 8;
-	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800);
-	if (UxxxStatus)
-		return UxxxStatus;
-	reg = 16;
-	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
-					    0xFFFFFFFF);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
-					   &pcidata);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
-					    0x00000000);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
-					   &pcidata);
-	if (UxxxStatus)
-		return UxxxStatus;
-	reg = 12;
-	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
-					   &latence_timer);
-	if (UxxxStatus)
-		return UxxxStatus;
-	latence_timer &= 0xFFFF00FF;
-	latence_timer |= 0x00001600;
-	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
-					    latence_timer);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
-					   &pcidata);
-	if (UxxxStatus)
-		return UxxxStatus;
-	reg = 4;
-	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
-					    0x00);
-	if (UxxxStatus)
-		return UxxxStatus;
-	return ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, &pcidata);
-}
-
-static int ftdi_elan_found_controller(struct usb_ftdi *ftdi, int fn, int quirk)
-{
-	int result;
-	int UxxxStatus;
-	UxxxStatus = ftdi_elan_setup_controller(ftdi, fn);
-	if (UxxxStatus)
-		return UxxxStatus;
-	result = ftdi_elan_check_controller(ftdi, quirk);
-	UxxxStatus = ftdi_elan_close_controller(ftdi, fn);
-	if (UxxxStatus)
-		return UxxxStatus;
-	return result;
-}
-
-static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
-{
-	u32 controlreg;
-	u8 sensebits;
-	int UxxxStatus;
-	UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L);
-	if (UxxxStatus)
-		return UxxxStatus;
-	msleep(750);
-	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000);
-	if (UxxxStatus)
-		return UxxxStatus;
-	msleep(250);
-	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
-	if (UxxxStatus)
-		return UxxxStatus;
-	UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
-	if (UxxxStatus)
-		return UxxxStatus;
-	msleep(1000);
-	sensebits = (controlreg >> 16) & 0x000F;
-	if (0x0D == sensebits)
-		return 0;
-	else
-		return - ENXIO;
-}
-
-static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi)
-{
-	int UxxxStatus;
-	u32 pcidata;
-	int reg = 0;
-	u8 fn;
-	int activePCIfn = 0;
-	int max_devices = 0;
-	int controllers = 0;
-	int unrecognized = 0;
-	ftdi->function = 0;
-	for (fn = 0; (fn < 4); fn++) {
-		u32 pciVID = 0;
-		u32 pciPID = 0;
-		int devices = 0;
-		activePCIfn = fn << 8;
-		UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
-						   &pcidata);
-		if (UxxxStatus)
-			return UxxxStatus;
-		pciVID = pcidata & 0xFFFF;
-		pciPID = (pcidata >> 16) & 0xFFFF;
-		if ((pciVID == PCI_VENDOR_ID_OPTI) && (pciPID == 0xc861)) {
-			devices = ftdi_elan_found_controller(ftdi, fn, 0);
-			controllers += 1;
-		} else if ((pciVID == PCI_VENDOR_ID_NEC) && (pciPID == 0x0035))
-		{
-			devices = ftdi_elan_found_controller(ftdi, fn, 0);
-			controllers += 1;
-		} else if ((pciVID == PCI_VENDOR_ID_AL) && (pciPID == 0x5237)) {
-			devices = ftdi_elan_found_controller(ftdi, fn, 0);
-			controllers += 1;
-		} else if ((pciVID == PCI_VENDOR_ID_ATT) && (pciPID == 0x5802))
-		{
-			devices = ftdi_elan_found_controller(ftdi, fn, 0);
-			controllers += 1;
-		} else if (pciVID == PCI_VENDOR_ID_AMD && pciPID == 0x740c) {
-			devices = ftdi_elan_found_controller(ftdi, fn,
-							     OHCI_QUIRK_AMD756);
-			controllers += 1;
-		} else if (pciVID == PCI_VENDOR_ID_COMPAQ && pciPID == 0xa0f8) {
-			devices = ftdi_elan_found_controller(ftdi, fn,
-							     OHCI_QUIRK_ZFMICRO);
-			controllers += 1;
-		} else if (0 == pcidata) {
-		} else
-			unrecognized += 1;
-		if (devices > max_devices) {
-			max_devices = devices;
-			ftdi->function = fn + 1;
-			ftdi->platform_data.vendor = pciVID;
-			ftdi->platform_data.device = pciPID;
-		}
-	}
-	if (ftdi->function > 0) {
-		return ftdi_elan_setup_controller(ftdi,	ftdi->function - 1);
-	} else if (controllers > 0) {
-		return -ENXIO;
-	} else if (unrecognized > 0) {
-		return -ENXIO;
-	} else {
-		ftdi->enumerated = 0;
-		return -ENXIO;
-	}
-}
-
-
-/*
- * we use only the first bulk-in and bulk-out endpoints
- */
-static int ftdi_elan_probe(struct usb_interface *interface,
-			   const struct usb_device_id *id)
-{
-	struct usb_host_interface *iface_desc;
-	struct usb_endpoint_descriptor *bulk_in, *bulk_out;
-	int retval;
-	struct usb_ftdi *ftdi;
-
-	ftdi = kzalloc(sizeof(struct usb_ftdi), GFP_KERNEL);
-	if (!ftdi)
-		return -ENOMEM;
-
-	mutex_lock(&ftdi_module_lock);
-	list_add_tail(&ftdi->ftdi_list, &ftdi_static_list);
-	ftdi->sequence_num = ++ftdi_instances;
-	mutex_unlock(&ftdi_module_lock);
-	ftdi_elan_init_kref(ftdi);
-	sema_init(&ftdi->sw_lock, 1);
-	ftdi->udev = usb_get_dev(interface_to_usbdev(interface));
-	ftdi->interface = interface;
-	mutex_init(&ftdi->u132_lock);
-	ftdi->expected = 4;
-
-	iface_desc = interface->cur_altsetting;
-	retval = usb_find_common_endpoints(iface_desc,
-			&bulk_in, &bulk_out, NULL, NULL);
-	if (retval) {
-		dev_err(&ftdi->udev->dev, "Could not find both bulk-in and bulk-out endpoints\n");
-		goto error;
-	}
-
-	ftdi->bulk_in_size = usb_endpoint_maxp(bulk_in);
-	ftdi->bulk_in_endpointAddr = bulk_in->bEndpointAddress;
-	ftdi->bulk_in_buffer = kmalloc(ftdi->bulk_in_size, GFP_KERNEL);
-	if (!ftdi->bulk_in_buffer) {
-		retval = -ENOMEM;
-		goto error;
-	}
-
-	ftdi->bulk_out_endpointAddr = bulk_out->bEndpointAddress;
-
-	dev_info(&ftdi->udev->dev, "interface %d has I=%02X O=%02X\n",
-		 iface_desc->desc.bInterfaceNumber, ftdi->bulk_in_endpointAddr,
-		 ftdi->bulk_out_endpointAddr);
-	usb_set_intfdata(interface, ftdi);
-	if (iface_desc->desc.bInterfaceNumber == 0 &&
-	    ftdi->bulk_in_endpointAddr == 0x81 &&
-	    ftdi->bulk_out_endpointAddr == 0x02) {
-		retval = usb_register_dev(interface, &ftdi_elan_jtag_class);
-		if (retval) {
-			dev_err(&ftdi->udev->dev, "Not able to get a minor for this device\n");
-			usb_set_intfdata(interface, NULL);
-			retval = -ENOMEM;
-			goto error;
-		} else {
-			ftdi->class = &ftdi_elan_jtag_class;
-			dev_info(&ftdi->udev->dev, "USB FDTI=%p JTAG interface %d now attached to ftdi%d\n",
-				 ftdi, iface_desc->desc.bInterfaceNumber,
-				 interface->minor);
-			return 0;
-		}
-	} else if (iface_desc->desc.bInterfaceNumber == 1 &&
-		   ftdi->bulk_in_endpointAddr == 0x83 &&
-		   ftdi->bulk_out_endpointAddr == 0x04) {
-		ftdi->class = NULL;
-		dev_info(&ftdi->udev->dev, "USB FDTI=%p ELAN interface %d now activated\n",
-			 ftdi, iface_desc->desc.bInterfaceNumber);
-		INIT_DELAYED_WORK(&ftdi->status_work, ftdi_elan_status_work);
-		INIT_DELAYED_WORK(&ftdi->command_work, ftdi_elan_command_work);
-		INIT_DELAYED_WORK(&ftdi->respond_work, ftdi_elan_respond_work);
-		ftdi_status_queue_work(ftdi, msecs_to_jiffies(3 *1000));
-		return 0;
-	} else {
-		dev_err(&ftdi->udev->dev,
-			"Could not find ELAN's U132 device\n");
-		retval = -ENODEV;
-		goto error;
-	}
-error:if (ftdi) {
-		ftdi_elan_put_kref(ftdi);
-	}
-	return retval;
-}
-
-static void ftdi_elan_disconnect(struct usb_interface *interface)
-{
-	struct usb_ftdi *ftdi = usb_get_intfdata(interface);
-	ftdi->disconnected += 1;
-	if (ftdi->class) {
-		int minor = interface->minor;
-		struct usb_class_driver *class = ftdi->class;
-		usb_set_intfdata(interface, NULL);
-		usb_deregister_dev(interface, class);
-		dev_info(&ftdi->udev->dev, "USB FTDI U132 jtag interface on minor %d now disconnected\n",
-			 minor);
-	} else {
-		ftdi_status_cancel_work(ftdi);
-		ftdi_command_cancel_work(ftdi);
-		ftdi_response_cancel_work(ftdi);
-		ftdi_elan_abandon_completions(ftdi);
-		ftdi_elan_abandon_targets(ftdi);
-		if (ftdi->registered) {
-			platform_device_unregister(&ftdi->platform_dev);
-			ftdi->synchronized = 0;
-			ftdi->enumerated = 0;
-			ftdi->initialized = 0;
-			ftdi->registered = 0;
-		}
-		ftdi->disconnected += 1;
-		usb_set_intfdata(interface, NULL);
-		dev_info(&ftdi->udev->dev, "USB FTDI U132 host controller interface now disconnected\n");
-	}
-	ftdi_elan_put_kref(ftdi);
-}
-
-static struct usb_driver ftdi_elan_driver = {
-	.name = "ftdi-elan",
-	.probe = ftdi_elan_probe,
-	.disconnect = ftdi_elan_disconnect,
-	.id_table = ftdi_elan_table,
-};
-static int __init ftdi_elan_init(void)
-{
-	int result;
-	pr_info("driver %s\n", ftdi_elan_driver.name);
-	mutex_init(&ftdi_module_lock);
-	INIT_LIST_HEAD(&ftdi_static_list);
-	result = usb_register(&ftdi_elan_driver);
-	if (result) {
-		pr_err("usb_register failed. Error number %d\n", result);
-	}
-	return result;
-
-}
-
-static void __exit ftdi_elan_exit(void)
-{
-	struct usb_ftdi *ftdi;
-	struct usb_ftdi *temp;
-	usb_deregister(&ftdi_elan_driver);
-	pr_info("ftdi_u132 driver deregistered\n");
-	list_for_each_entry_safe(ftdi, temp, &ftdi_static_list, ftdi_list) {
-		ftdi_status_cancel_work(ftdi);
-		ftdi_command_cancel_work(ftdi);
-		ftdi_response_cancel_work(ftdi);
-	}
-}
-
-
-module_init(ftdi_elan_init);
-module_exit(ftdi_elan_exit);
diff --git a/drivers/usb/misc/sisusbvga/sisusbvga.c b/drivers/usb/misc/sisusbvga/sisusbvga.c
index 654a79fd3231eae54c09ea186c195cce9485266b..febf34f9f04998582f06cffa92aa446232568214 100644
--- a/drivers/usb/misc/sisusbvga/sisusbvga.c
+++ b/drivers/usb/misc/sisusbvga/sisusbvga.c
@@ -2778,6 +2778,20 @@ static int sisusb_probe(struct usb_interface *intf,
 	struct usb_device *dev = interface_to_usbdev(intf);
 	struct sisusb_usb_data *sisusb;
 	int retval = 0, i;
+	static const u8 ep_addresses[] = {
+		SISUSB_EP_GFX_IN | USB_DIR_IN,
+		SISUSB_EP_GFX_OUT | USB_DIR_OUT,
+		SISUSB_EP_GFX_BULK_OUT | USB_DIR_OUT,
+		SISUSB_EP_GFX_LBULK_OUT | USB_DIR_OUT,
+		SISUSB_EP_BRIDGE_IN | USB_DIR_IN,
+		SISUSB_EP_BRIDGE_OUT | USB_DIR_OUT,
+		0};
+
+	/* Are the expected endpoints present? */
+	if (!usb_check_bulk_endpoints(intf, ep_addresses)) {
+		dev_err(&intf->dev, "Invalid USB2VGA device\n");
+		return -EINVAL;
+	}
 
 	dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
 			dev->devnum);
diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c
index e3abe67a155d0b93358225d703745a97db89c8f4..ce1da80d33656f93b84135aa0a08311d3d1e0b65 100644
--- a/drivers/usb/misc/usb251xb.c
+++ b/drivers/usb/misc/usb251xb.c
@@ -377,7 +377,6 @@ static int usb251xb_connect(struct usb251xb *hub)
 	return err;
 }
 
-#ifdef CONFIG_OF
 static void usb251xb_get_ports_field(struct usb251xb *hub,
 				    const char *prop_name, u8 port_cnt,
 				    bool ds_only, u8 *fld)
@@ -410,10 +409,7 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
 		return -ENODEV;
 	}
 
-	if (of_get_property(np, "skip-config", NULL))
-		hub->skip_config = 1;
-	else
-		hub->skip_config = 0;
+	hub->skip_config = of_property_read_bool(np, "skip-config");
 
 	hub->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
 	if (IS_ERR(hub->gpio_reset))
@@ -431,40 +427,40 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
 		hub->device_id = USB251XB_DEF_DEVICE_ID;
 
 	hub->conf_data1 = USB251XB_DEF_CONFIG_DATA_1;
-	if (of_get_property(np, "self-powered", NULL)) {
+	if (of_property_read_bool(np, "self-powered")) {
 		hub->conf_data1 |= BIT(7);
 
 		/* Configure Over-Current sens when self-powered */
 		hub->conf_data1 &= ~BIT(2);
-		if (of_get_property(np, "ganged-sensing", NULL))
+		if (of_property_read_bool(np, "ganged-sensing"))
 			hub->conf_data1 &= ~BIT(1);
-		else if (of_get_property(np, "individual-sensing", NULL))
+		else if (of_property_read_bool(np, "individual-sensing"))
 			hub->conf_data1 |= BIT(1);
-	} else if (of_get_property(np, "bus-powered", NULL)) {
+	} else if (of_property_read_bool(np, "bus-powered")) {
 		hub->conf_data1 &= ~BIT(7);
 
 		/* Disable Over-Current sense when bus-powered */
 		hub->conf_data1 |= BIT(2);
 	}
 
-	if (of_get_property(np, "disable-hi-speed", NULL))
+	if (of_property_read_bool(np, "disable-hi-speed"))
 		hub->conf_data1 |= BIT(5);
 
-	if (of_get_property(np, "multi-tt", NULL))
+	if (of_property_read_bool(np, "multi-tt"))
 		hub->conf_data1 |= BIT(4);
-	else if (of_get_property(np, "single-tt", NULL))
+	else if (of_property_read_bool(np, "single-tt"))
 		hub->conf_data1 &= ~BIT(4);
 
-	if (of_get_property(np, "disable-eop", NULL))
+	if (of_property_read_bool(np, "disable-eop"))
 		hub->conf_data1 |= BIT(3);
 
-	if (of_get_property(np, "individual-port-switching", NULL))
+	if (of_property_read_bool(np, "individual-port-switching"))
 		hub->conf_data1 |= BIT(0);
-	else if (of_get_property(np, "ganged-port-switching", NULL))
+	else if (of_property_read_bool(np, "ganged-port-switching"))
 		hub->conf_data1 &= ~BIT(0);
 
 	hub->conf_data2 = USB251XB_DEF_CONFIG_DATA_2;
-	if (of_get_property(np, "dynamic-power-switching", NULL))
+	if (of_property_read_bool(np, "dynamic-power-switching"))
 		hub->conf_data2 |= BIT(7);
 
 	if (!of_property_read_u32(np, "oc-delay-us", &property_u32)) {
@@ -487,17 +483,17 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
 		}
 	}
 
-	if (of_get_property(np, "compound-device", NULL))
+	if (of_property_read_bool(np, "compound-device"))
 		hub->conf_data2 |= BIT(3);
 
 	hub->conf_data3 = USB251XB_DEF_CONFIG_DATA_3;
-	if (of_get_property(np, "port-mapping-mode", NULL))
+	if (of_property_read_bool(np, "port-mapping-mode"))
 		hub->conf_data3 |= BIT(3);
 
 	if (data->led_support && of_get_property(np, "led-usb-mode", NULL))
 		hub->conf_data3 &= ~BIT(1);
 
-	if (of_get_property(np, "string-support", NULL))
+	if (of_property_read_bool(np, "string-support"))
 		hub->conf_data3 |= BIT(0);
 
 	hub->non_rem_dev = USB251XB_DEF_NON_REMOVABLE_DEVICES;
@@ -626,13 +622,6 @@ static const struct of_device_id usb251xb_of_match[] = {
 	}
 };
 MODULE_DEVICE_TABLE(of, usb251xb_of_match);
-#else /* CONFIG_OF */
-static int usb251xb_get_ofdata(struct usb251xb *hub,
-			       const struct usb251xb_data *data)
-{
-	return 0;
-}
-#endif /* CONFIG_OF */
 
 static void usb251xb_regulator_disable_action(void *data)
 {
@@ -754,7 +743,7 @@ MODULE_DEVICE_TABLE(i2c, usb251xb_id);
 static struct i2c_driver usb251xb_i2c_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
-		.of_match_table = of_match_ptr(usb251xb_of_match),
+		.of_match_table = usb251xb_of_match,
 		.pm = &usb251xb_pm_ops,
 	},
 	.probe_new = usb251xb_i2c_probe,
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index bd47c4437ca46b17c80cdaeaffb2f6cee2f9d93a..c6cfd1edaf762bed1c24d4501df4a90c631e9e74 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -46,34 +46,18 @@ struct usb3503 {
 	struct device		*dev;
 	struct clk		*clk;
 	u8	port_off_mask;
+	struct gpio_desc	*bypass;
 	struct gpio_desc	*intn;
 	struct gpio_desc 	*reset;
 	struct gpio_desc 	*connect;
 	bool	secondary_ref_clk;
 };
 
-static int usb3503_reset(struct usb3503 *hub, int state)
-{
-	if (!state && hub->connect)
-		gpiod_set_value_cansleep(hub->connect, 0);
-
-	if (hub->reset)
-		gpiod_set_value_cansleep(hub->reset, !state);
-
-	/* Wait T_HUBINIT == 4ms for hub logic to stabilize */
-	if (state)
-		usleep_range(4000, 10000);
-
-	return 0;
-}
-
 static int usb3503_connect(struct usb3503 *hub)
 {
 	struct device *dev = hub->dev;
 	int err;
 
-	usb3503_reset(hub, 1);
-
 	if (hub->regmap) {
 		/* SP_ILOCK: set connect_n, config_n for config */
 		err = regmap_write(hub->regmap, USB3503_SP_ILOCK,
@@ -126,25 +110,46 @@ static int usb3503_connect(struct usb3503 *hub)
 static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode)
 {
 	struct device *dev = hub->dev;
-	int err = 0;
+	int rst, bypass, conn;
 
 	switch (mode) {
 	case USB3503_MODE_HUB:
-		err = usb3503_connect(hub);
+		conn = 1;
+		rst = 0;
+		bypass = 0;
 		break;
-
 	case USB3503_MODE_STANDBY:
-		usb3503_reset(hub, 0);
+		conn = 0;
+		rst = 1;
+		bypass = 1;
 		dev_info(dev, "switched to STANDBY mode\n");
 		break;
-
+	case USB3503_MODE_BYPASS:
+		conn = 0;
+		rst = 0;
+		bypass = 1;
+		break;
 	default:
 		dev_err(dev, "unknown mode is requested\n");
-		err = -EINVAL;
-		break;
+		return -EINVAL;
 	}
 
-	return err;
+	if (!conn && hub->connect)
+		gpiod_set_value_cansleep(hub->connect, 0);
+
+	if (hub->reset)
+		gpiod_set_value_cansleep(hub->reset, rst);
+
+	if (hub->bypass)
+		gpiod_set_value_cansleep(hub->bypass, bypass);
+
+	if (conn) {
+		/* Wait T_HUBINIT == 4ms for hub logic to stabilize */
+		usleep_range(4000, 10000);
+		return usb3503_connect(hub);
+	}
+
+	return 0;
 }
 
 static const struct regmap_config usb3503_regmap_config = {
@@ -253,6 +258,14 @@ static int usb3503_probe(struct usb3503 *hub)
 	if (hub->connect)
 		gpiod_set_consumer_name(hub->connect, "usb3503 connect");
 
+	hub->bypass = devm_gpiod_get_optional(dev, "bypass", GPIOD_OUT_HIGH);
+	if (IS_ERR(hub->bypass)) {
+		err = PTR_ERR(hub->bypass);
+		goto err_clk;
+	}
+	if (hub->bypass)
+		gpiod_set_consumer_name(hub->bypass, "usb3503 bypass");
+
 	hub->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
 	if (IS_ERR(hub->reset)) {
 		err = PTR_ERR(hub->reset);
@@ -388,6 +401,7 @@ MODULE_DEVICE_TABLE(i2c, usb3503_id);
 static const struct of_device_id usb3503_of_match[] = {
 	{ .compatible = "smsc,usb3503", },
 	{ .compatible = "smsc,usb3503a", },
+	{ .compatible = "smsc,usb3803", },
 	{},
 };
 MODULE_DEVICE_TABLE(of, usb3503_of_match);
diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h
index 2d7b57e07eee227fa56b142b30389d5dff900d95..b4a7662dded585178689eec269d3917ac2fa37d8 100644
--- a/drivers/usb/mtu3/mtu3.h
+++ b/drivers/usb/mtu3/mtu3.h
@@ -90,7 +90,7 @@ struct mtu3_request;
  */
 #define EP0_RESPONSE_BUF  6
 
-#define BULK_CLKS_CNT	4
+#define BULK_CLKS_CNT	6
 
 /* device operated link and speed got from DEVICE_CONF register */
 enum mtu3_speed {
diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c
index 9b8aded3d95e902e044b2dc1bf0bd9639a1e32c4..8191b7ed3852107a4ddd55b39fc53987eb56fef6 100644
--- a/drivers/usb/mtu3/mtu3_dr.c
+++ b/drivers/usb/mtu3/mtu3_dr.c
@@ -294,6 +294,7 @@ static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx)
 	role_sx_desc.get = ssusb_role_sw_get;
 	role_sx_desc.fwnode = dev_fwnode(dev);
 	role_sx_desc.driver_data = ssusb;
+	role_sx_desc.allow_userspace_control = true;
 	otg_sx->role_sw = usb_role_switch_register(dev, &role_sx_desc);
 	if (IS_ERR(otg_sx->role_sw))
 		return PTR_ERR(otg_sx->role_sw);
diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c
index c0264d5426bfe6c289869dfc5292b1cb2ad8dfd2..ad0eeac4332d9f69d5237180a8a16cbc0eee35c2 100644
--- a/drivers/usb/mtu3/mtu3_gadget.c
+++ b/drivers/usb/mtu3/mtu3_gadget.c
@@ -23,7 +23,6 @@ __acquires(mep->mtu->lock)
 		req->status = status;
 
 	trace_mtu3_req_complete(mreq);
-	spin_unlock(&mtu->lock);
 
 	/* ep0 makes use of PIO, needn't unmap it */
 	if (mep->epnum)
@@ -32,6 +31,7 @@ __acquires(mep->mtu->lock)
 	dev_dbg(mtu->dev, "%s complete req: %p, sts %d, %d/%d\n",
 		mep->name, req, req->status, req->actual, req->length);
 
+	spin_unlock(&mtu->lock);
 	usb_gadget_giveback_request(&mep->ep, req);
 	spin_lock(&mtu->lock);
 }
diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c
index f3903367a6a07c2aaaf13578f2e7632d9745388f..177d2caf887c87f0d47d8f7fd28984d8b10c085d 100644
--- a/drivers/usb/mtu3/mtu3_host.c
+++ b/drivers/usb/mtu3/mtu3_host.c
@@ -11,7 +11,7 @@
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/mfd/syscon.h>
-#include <linux/of_device.h>
+#include <linux/of_platform.h>
 #include <linux/regmap.h>
 
 #include "mtu3.h"
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index d78ae52b4e2615eef0d90f3862598b933c1052d9..6f264b129243bb3e0413df716c4a71e827e49a36 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -234,6 +234,8 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
 	clks[1].id = "ref_ck";
 	clks[2].id = "mcu_ck";
 	clks[3].id = "dma_ck";
+	clks[4].id = "xhci_ck";
+	clks[5].id = "frmcnt_ck";
 	ret = devm_clk_bulk_get_optional(dev, BULK_CLKS_CNT, clks);
 	if (ret)
 		return ret;
diff --git a/drivers/usb/mtu3/mtu3_qmu.c b/drivers/usb/mtu3/mtu3_qmu.c
index a2fdab8b63b2824aaf0cc8264c2e1139fba79dec..3d77408e3133ce3e7969f0d28090477594cf9e88 100644
--- a/drivers/usb/mtu3/mtu3_qmu.c
+++ b/drivers/usb/mtu3/mtu3_qmu.c
@@ -210,6 +210,7 @@ static struct qmu_gpd *advance_enq_gpd(struct mtu3_gpd_ring *ring)
 	return ring->enqueue;
 }
 
+/* @dequeue may be NULL if ring is unallocated or freed */
 static struct qmu_gpd *advance_deq_gpd(struct mtu3_gpd_ring *ring)
 {
 	if (ring->dequeue < ring->end)
@@ -221,7 +222,7 @@ static struct qmu_gpd *advance_deq_gpd(struct mtu3_gpd_ring *ring)
 }
 
 /* check if a ring is emtpy */
-static int gpd_ring_empty(struct mtu3_gpd_ring *ring)
+static bool gpd_ring_empty(struct mtu3_gpd_ring *ring)
 {
 	struct qmu_gpd *enq = ring->enqueue;
 	struct qmu_gpd *next;
@@ -466,6 +467,37 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum)
 	mtu3_qmu_resume(mep);
 }
 
+/*
+ * when rx error happens (except zlperr), QMU will stop, and RQCPR saves
+ * the GPD encountered error, Done irq will arise after resuming QMU again.
+ */
+static void qmu_error_rx(struct mtu3 *mtu, u8 epnum)
+{
+	struct mtu3_ep *mep = mtu->out_eps + epnum;
+	struct mtu3_gpd_ring *ring = &mep->gpd_ring;
+	struct qmu_gpd *gpd_current = NULL;
+	struct mtu3_request *mreq;
+	dma_addr_t cur_gpd_dma;
+
+	cur_gpd_dma = read_rxq_cur_addr(mtu->mac_base, epnum);
+	gpd_current = gpd_dma_to_virt(ring, cur_gpd_dma);
+
+	mreq = next_request(mep);
+	if (!mreq || mreq->gpd != gpd_current) {
+		dev_err(mtu->dev, "no correct RX req is found\n");
+		return;
+	}
+
+	mreq->request.status = -EAGAIN;
+
+	/* by pass the current GDP */
+	gpd_current->dw0_info |= cpu_to_le32(GPD_FLAGS_BPS | GPD_FLAGS_HWO);
+	mtu3_qmu_resume(mep);
+
+	dev_dbg(mtu->dev, "%s EP%d, current=%p, req=%p\n",
+		__func__, epnum, gpd_current, mreq);
+}
+
 /*
  * NOTE: request list maybe is already empty as following case:
  * queue_tx --> qmu_interrupt(clear interrupt pending, schedule tasklet)-->
@@ -491,7 +523,7 @@ static void qmu_done_tx(struct mtu3 *mtu, u8 epnum)
 	dev_dbg(mtu->dev, "%s EP%d, last=%p, current=%p, enq=%p\n",
 		__func__, epnum, gpd, gpd_current, ring->enqueue);
 
-	while (gpd != gpd_current && !GET_GPD_HWO(gpd)) {
+	while (gpd && gpd != gpd_current && !GET_GPD_HWO(gpd)) {
 
 		mreq = next_request(mep);
 
@@ -530,7 +562,7 @@ static void qmu_done_rx(struct mtu3 *mtu, u8 epnum)
 	dev_dbg(mtu->dev, "%s EP%d, last=%p, current=%p, enq=%p\n",
 		__func__, epnum, gpd, gpd_current, ring->enqueue);
 
-	while (gpd != gpd_current && !GET_GPD_HWO(gpd)) {
+	while (gpd && gpd != gpd_current && !GET_GPD_HWO(gpd)) {
 
 		mreq = next_request(mep);
 
@@ -571,14 +603,18 @@ static void qmu_exception_isr(struct mtu3 *mtu, u32 qmu_status)
 
 	if ((qmu_status & RXQ_CSERR_INT) || (qmu_status & RXQ_LENERR_INT)) {
 		errval = mtu3_readl(mbase, U3D_RQERRIR0);
+		mtu3_writel(mbase, U3D_RQERRIR0, errval);
+
 		for (i = 1; i < mtu->num_eps; i++) {
 			if (errval & QMU_RX_CS_ERR(i))
 				dev_err(mtu->dev, "Rx %d CS error!\n", i);
 
 			if (errval & QMU_RX_LEN_ERR(i))
 				dev_err(mtu->dev, "RX %d Length error\n", i);
+
+			if (errval & (QMU_RX_CS_ERR(i) | QMU_RX_LEN_ERR(i)))
+				qmu_error_rx(mtu, i);
 		}
-		mtu3_writel(mbase, U3D_RQERRIR0, errval);
 	}
 
 	if (qmu_status & RXQ_ZLPERR_INT) {
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 3a1f4bcea80c0198dcca49c38b4b25b3669660ca..9a8cf3de061700d2c01e5e532ecac8a5f56ab38f 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -113,7 +113,7 @@ config USB_MUSB_MEDIATEK
 
 config USB_MUSB_POLARFIRE_SOC
 	tristate "Microchip PolarFire SoC platforms"
-	depends on SOC_MICROCHIP_POLARFIRE || COMPILE_TEST
+	depends on ARCH_MICROCHIP_POLARFIRE || COMPILE_TEST
 	depends on NOP_USB_XCEIV
 	select USB_MUSB_DUAL_ROLE
 	help
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index d47e5c94587b2234a1cb8f3550be90c040fbb4b1..912e32b78ac6e7460e3f20f762d5b4ddbbfff3ec 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -576,14 +576,12 @@ static int da8xx_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int da8xx_remove(struct platform_device *pdev)
+static void da8xx_remove(struct platform_device *pdev)
 {
 	struct da8xx_glue		*glue = platform_get_drvdata(pdev);
 
 	platform_device_unregister(glue->musb);
 	usb_phy_generic_unregister(glue->usb_phy);
-
-	return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -626,7 +624,7 @@ MODULE_DEVICE_TABLE(of, da8xx_id_table);
 
 static struct platform_driver da8xx_driver = {
 	.probe		= da8xx_probe,
-	.remove		= da8xx_remove,
+	.remove_new	= da8xx_remove,
 	.driver		= {
 		.name	= "musb-da8xx",
 		.pm = &da8xx_pm_ops,
diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c
index c7b1d2a394d9ad7cb62f7196368147466947b544..5aabdd7e2511d7d953e9143877de92e9a0138a01 100644
--- a/drivers/usb/musb/jz4740.c
+++ b/drivers/usb/musb/jz4740.c
@@ -308,14 +308,12 @@ static int jz4740_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int jz4740_remove(struct platform_device *pdev)
+static void jz4740_remove(struct platform_device *pdev)
 {
 	struct jz4740_glue *glue = platform_get_drvdata(pdev);
 
 	platform_device_unregister(glue->pdev);
 	clk_disable_unprepare(glue->clk);
-
-	return 0;
 }
 
 static const struct of_device_id jz4740_musb_of_match[] = {
@@ -327,7 +325,7 @@ MODULE_DEVICE_TABLE(of, jz4740_musb_of_match);
 
 static struct platform_driver jz4740_driver = {
 	.probe		= jz4740_probe,
-	.remove		= jz4740_remove,
+	.remove_new	= jz4740_remove,
 	.driver		= {
 		.name	= "musb-jz4740",
 		.of_match_table = jz4740_musb_of_match,
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c
index 27b9bd2583400ee38d68289e5628006e1403cbc8..598ee5c0bf3471db333943b329e6075a7913f23d 100644
--- a/drivers/usb/musb/mediatek.c
+++ b/drivers/usb/musb/mediatek.c
@@ -508,15 +508,13 @@ static int mtk_musb_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int mtk_musb_remove(struct platform_device *pdev)
+static void mtk_musb_remove(struct platform_device *pdev)
 {
 	struct mtk_glue *glue = platform_get_drvdata(pdev);
 	struct platform_device *usb_phy = glue->usb_phy;
 
 	platform_device_unregister(glue->musb_pdev);
 	usb_phy_generic_unregister(usb_phy);
-
-	return 0;
 }
 
 #ifdef CONFIG_OF
@@ -529,7 +527,7 @@ MODULE_DEVICE_TABLE(of, mtk_musb_match);
 
 static struct platform_driver mtk_musb_driver = {
 	.probe = mtk_musb_probe,
-	.remove = mtk_musb_remove,
+	.remove_new = mtk_musb_remove,
 	.driver = {
 		   .name = "musb-mtk",
 		   .of_match_table = of_match_ptr(mtk_musb_match),
diff --git a/drivers/usb/musb/mpfs.c b/drivers/usb/musb/mpfs.c
index cea2e8108867f322812f9f1882be91bbb2b7d47b..24b98716f7fce29a98c7ead73ca81600ece0be72 100644
--- a/drivers/usb/musb/mpfs.c
+++ b/drivers/usb/musb/mpfs.c
@@ -235,15 +235,13 @@ static int mpfs_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int mpfs_remove(struct platform_device *pdev)
+static void mpfs_remove(struct platform_device *pdev)
 {
 	struct mpfs_glue *glue = platform_get_drvdata(pdev);
 
 	clk_disable_unprepare(glue->clk);
 	platform_device_unregister(glue->musb);
 	usb_phy_generic_unregister(pdev);
-
-	return 0;
 }
 
 #ifdef CONFIG_OF
@@ -256,7 +254,7 @@ MODULE_DEVICE_TABLE(of, mpfs_id_table);
 
 static struct platform_driver mpfs_musb_driver = {
 	.probe = mpfs_probe,
-	.remove = mpfs_remove,
+	.remove_new = mpfs_remove,
 	.driver = {
 		.name = "mpfs-musb",
 		.of_match_table = of_match_ptr(mpfs_id_table)
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 648bb6021c5ef5e11269aaf04ba76bf545d6e7fa..d162afbbe19f70dcbfb888bdc6329827cd2b0d13 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2621,7 +2621,7 @@ static int musb_probe(struct platform_device *pdev)
 	return musb_init_controller(dev, irq, base);
 }
 
-static int musb_remove(struct platform_device *pdev)
+static void musb_remove(struct platform_device *pdev)
 {
 	struct device	*dev = &pdev->dev;
 	struct musb	*musb = dev_to_musb(dev);
@@ -2657,7 +2657,6 @@ static int musb_remove(struct platform_device *pdev)
 	usb_phy_shutdown(musb->xceiv);
 	musb_free(musb);
 	device_init_wakeup(dev, 0);
-	return 0;
 }
 
 #ifdef	CONFIG_PM
@@ -2955,7 +2954,7 @@ static struct platform_driver musb_driver = {
 		.dev_groups	= musb_groups,
 	},
 	.probe		= musb_probe,
-	.remove		= musb_remove,
+	.remove_new	= musb_remove,
 };
 
 module_platform_driver(musb_driver);
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index f75cde0f2b43d6d7ec02da55812bc3e5ef8a2747..9119b1d51370ff5fd718c950a98da27a02b01400 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -915,7 +915,7 @@ static int dsps_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int dsps_remove(struct platform_device *pdev)
+static void dsps_remove(struct platform_device *pdev)
 {
 	struct dsps_glue *glue = platform_get_drvdata(pdev);
 
@@ -923,8 +923,6 @@ static int dsps_remove(struct platform_device *pdev)
 
 	pm_runtime_disable(&pdev->dev);
 	iounmap(glue->usbss_base);
-
-	return 0;
 }
 
 static const struct dsps_musb_wrapper am33xx_driver_data = {
@@ -1036,7 +1034,7 @@ static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
 
 static struct platform_driver dsps_usbss_driver = {
 	.probe		= dsps_probe,
-	.remove         = dsps_remove,
+	.remove_new     = dsps_remove,
 	.driver         = {
 		.name   = "musb-dsps",
 		.pm	= &dsps_pm_ops,
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 44a21ec865fb219ec80eb34e66c46bc1ee7c6265..b4a4c1df4e0d961cfc75d105a84de8dd4c04a1f2 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -334,7 +334,7 @@ static int omap2430_probe(struct platform_device *pdev)
 	 * Legacy SoCs using omap_device get confused if node is moved
 	 * because of interconnect properties mixed into the node.
 	 */
-	if (of_get_property(np, "ti,hwmods", NULL)) {
+	if (of_property_present(np, "ti,hwmods")) {
 		dev_warn(&pdev->dev, "please update to probe with ti-sysc\n");
 		populate_irqs = true;
 	} else {
@@ -471,14 +471,12 @@ static int omap2430_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int omap2430_remove(struct platform_device *pdev)
+static void omap2430_remove(struct platform_device *pdev)
 {
 	struct omap2430_glue *glue = platform_get_drvdata(pdev);
 
 	platform_device_unregister(glue->musb);
 	pm_runtime_disable(glue->dev);
-
-	return 0;
 }
 
 #ifdef CONFIG_PM
@@ -610,7 +608,7 @@ MODULE_DEVICE_TABLE(of, omap2430_id_table);
 
 static struct platform_driver omap2430_driver = {
 	.probe		= omap2430_probe,
-	.remove		= omap2430_remove,
+	.remove_new	= omap2430_remove,
 	.driver		= {
 		.name	= "musb-omap2430",
 		.pm	= DEV_PM_OPS,
diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index 9b622cd9b2bd5dd00e174bd58d848b1332394232..c5c6c4e09300cf09981ecbac8d4624bb341aa237 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -805,15 +805,13 @@ static int sunxi_musb_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int sunxi_musb_remove(struct platform_device *pdev)
+static void sunxi_musb_remove(struct platform_device *pdev)
 {
 	struct sunxi_glue *glue = platform_get_drvdata(pdev);
 	struct platform_device *usb_phy = glue->usb_phy;
 
 	platform_device_unregister(glue->musb_pdev);
 	usb_phy_generic_unregister(usb_phy);
-
-	return 0;
 }
 
 static const struct sunxi_musb_cfg sun4i_a10_musb_cfg = {
@@ -862,7 +860,7 @@ MODULE_DEVICE_TABLE(of, sunxi_musb_match);
 
 static struct platform_driver sunxi_musb_driver = {
 	.probe = sunxi_musb_probe,
-	.remove = sunxi_musb_remove,
+	.remove_new = sunxi_musb_remove,
 	.driver = {
 		.name = "musb-sunxi",
 		.of_match_table = sunxi_musb_match,
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 5609b4e84d40a381decf5c567ee6415d1a52befe..a1f29dbc62e6e9502dca4f52e93b7ae4bb557154 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -1258,19 +1258,17 @@ static int tusb_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int tusb_remove(struct platform_device *pdev)
+static void tusb_remove(struct platform_device *pdev)
 {
 	struct tusb6010_glue		*glue = platform_get_drvdata(pdev);
 
 	platform_device_unregister(glue->musb);
 	usb_phy_generic_unregister(glue->phy);
-
-	return 0;
 }
 
 static struct platform_driver tusb_driver = {
 	.probe		= tusb_probe,
-	.remove		= tusb_remove,
+	.remove_new	= tusb_remove,
 	.driver		= {
 		.name	= "musb-tusb",
 	},
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index 8ea62c34432826ffb243f423c30b3a561f95e0e7..c8d9d2a1d2f0360da9b1ac4378e452dc549f4b59 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -303,14 +303,12 @@ static int ux500_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int ux500_remove(struct platform_device *pdev)
+static void ux500_remove(struct platform_device *pdev)
 {
 	struct ux500_glue	*glue = platform_get_drvdata(pdev);
 
 	platform_device_unregister(glue->musb);
 	clk_disable_unprepare(glue->clk);
-
-	return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -357,7 +355,7 @@ MODULE_DEVICE_TABLE(of, ux500_match);
 
 static struct platform_driver ux500_driver = {
 	.probe		= ux500_probe,
-	.remove		= ux500_remove,
+	.remove_new	= ux500_remove,
 	.driver		= {
 		.name	= "musb-ux500",
 		.pm	= &ux500_pm_ops,
diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index 4c52ba96f17e4392d6d394d7ffe5b7e85713f910..408f47e390259f37ecf00722f0137364cf78b63d 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -965,7 +965,7 @@ static int ab8500_usb_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int ab8500_usb_remove(struct platform_device *pdev)
+static void ab8500_usb_remove(struct platform_device *pdev)
 {
 	struct ab8500_usb *ab = platform_get_drvdata(pdev);
 
@@ -977,8 +977,6 @@ static int ab8500_usb_remove(struct platform_device *pdev)
 		ab8500_usb_host_phy_dis(ab);
 	else if (ab->mode == USB_PERIPHERAL)
 		ab8500_usb_peri_phy_dis(ab);
-
-	return 0;
 }
 
 static const struct platform_device_id ab8500_usb_devtype[] = {
@@ -989,7 +987,7 @@ MODULE_DEVICE_TABLE(platform, ab8500_usb_devtype);
 
 static struct platform_driver ab8500_usb_driver = {
 	.probe		= ab8500_usb_probe,
-	.remove		= ab8500_usb_remove,
+	.remove_new	= ab8500_usb_remove,
 	.id_table	= ab8500_usb_devtype,
 	.driver		= {
 		.name	= "abx5x0-usb",
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c
index 8524475d942d496e62aa757ce541955a84759f15..e39665cf4b4a983227e24adaca81aa3a927186f4 100644
--- a/drivers/usb/phy/phy-am335x.c
+++ b/drivers/usb/phy/phy-am335x.c
@@ -82,12 +82,11 @@ static int am335x_phy_probe(struct platform_device *pdev)
 	return usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
 }
 
-static int am335x_phy_remove(struct platform_device *pdev)
+static void am335x_phy_remove(struct platform_device *pdev)
 {
 	struct am335x_phy *am_phy = platform_get_drvdata(pdev);
 
 	usb_remove_phy(&am_phy->usb_phy_gen.phy);
-	return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -134,7 +133,7 @@ MODULE_DEVICE_TABLE(of, am335x_phy_ids);
 
 static struct platform_driver am335x_phy_driver = {
 	.probe          = am335x_phy_probe,
-	.remove         = am335x_phy_remove,
+	.remove_new     = am335x_phy_remove,
 	.driver         = {
 		.name   = "am335x-phy-driver",
 		.pm = &am335x_pm_ops,
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index 972704262b02be888f959ab6659f30e133c6fbef..79617bb0a70e860624b2ae726dab324d22cce778 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -983,7 +983,7 @@ static int fsl_otg_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int fsl_otg_remove(struct platform_device *pdev)
+static void fsl_otg_remove(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
@@ -998,13 +998,11 @@ static int fsl_otg_remove(struct platform_device *pdev)
 
 	if (pdata->exit)
 		pdata->exit(pdev);
-
-	return 0;
 }
 
 struct platform_driver fsl_otg_driver = {
 	.probe = fsl_otg_probe,
-	.remove = fsl_otg_remove,
+	.remove_new = fsl_otg_remove,
 	.driver = {
 		.name = driver_name,
 		.owner = THIS_MODULE,
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index c1309ea24a52e11be6e9ced6d9d187822d43f16c..770081b828a429326e8801981f9ec66a913b6890 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -330,13 +330,11 @@ static int usb_phy_generic_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int usb_phy_generic_remove(struct platform_device *pdev)
+static void usb_phy_generic_remove(struct platform_device *pdev)
 {
 	struct usb_phy_generic *nop = platform_get_drvdata(pdev);
 
 	usb_remove_phy(&nop->phy);
-
-	return 0;
 }
 
 static const struct of_device_id nop_xceiv_dt_ids[] = {
@@ -348,7 +346,7 @@ MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids);
 
 static struct platform_driver usb_phy_generic_driver = {
 	.probe		= usb_phy_generic_probe,
-	.remove		= usb_phy_generic_remove,
+	.remove_new	= usb_phy_generic_remove,
 	.driver		= {
 		.name	= "usb_phy_generic",
 		.of_match_table = nop_xceiv_dt_ids,
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index 12dfeff7de3d0b666e632ce3171f315bdcdfcb77..817c242a76ca06a964f14eeec2f9d0033ac250c7 100644
--- a/drivers/usb/phy/phy-gpio-vbus-usb.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -325,7 +325,7 @@ static int gpio_vbus_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int gpio_vbus_remove(struct platform_device *pdev)
+static void gpio_vbus_remove(struct platform_device *pdev)
 {
 	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
 
@@ -333,8 +333,6 @@ static int gpio_vbus_remove(struct platform_device *pdev)
 	cancel_delayed_work_sync(&gpio_vbus->work);
 
 	usb_remove_phy(&gpio_vbus->phy);
-
-	return 0;
 }
 
 #ifdef CONFIG_PM
@@ -386,7 +384,7 @@ static struct platform_driver gpio_vbus_driver = {
 		.of_match_table = gpio_vbus_of_match,
 	},
 	.probe		= gpio_vbus_probe,
-	.remove		= gpio_vbus_remove,
+	.remove_new	= gpio_vbus_remove,
 };
 
 module_platform_driver(gpio_vbus_driver);
diff --git a/drivers/usb/phy/phy-keystone.c b/drivers/usb/phy/phy-keystone.c
index f75912279b39955fa98b942330dba9e2aa99011b..bd9a98ad1b3093ea89de7be1833963d337f16172 100644
--- a/drivers/usb/phy/phy-keystone.c
+++ b/drivers/usb/phy/phy-keystone.c
@@ -88,13 +88,11 @@ static int keystone_usbphy_probe(struct platform_device *pdev)
 	return usb_add_phy_dev(&k_phy->usb_phy_gen.phy);
 }
 
-static int keystone_usbphy_remove(struct platform_device *pdev)
+static void keystone_usbphy_remove(struct platform_device *pdev)
 {
 	struct keystone_usbphy *k_phy = platform_get_drvdata(pdev);
 
 	usb_remove_phy(&k_phy->usb_phy_gen.phy);
-
-	return 0;
 }
 
 static const struct of_device_id keystone_usbphy_ids[] = {
@@ -105,7 +103,7 @@ MODULE_DEVICE_TABLE(of, keystone_usbphy_ids);
 
 static struct platform_driver keystone_usbphy_driver = {
 	.probe          = keystone_usbphy_probe,
-	.remove         = keystone_usbphy_remove,
+	.remove_new     = keystone_usbphy_remove,
 	.driver         = {
 		.name   = "keystone-usbphy",
 		.of_match_table = keystone_usbphy_ids,
diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c
index 86503b7d695c62aa55379dcf5bfbcb50f9c12832..df7c27474a75a6a3435ead94853299adae9ac577 100644
--- a/drivers/usb/phy/phy-mv-usb.c
+++ b/drivers/usb/phy/phy-mv-usb.c
@@ -644,7 +644,7 @@ static const struct attribute_group *mv_otg_groups[] = {
 	NULL,
 };
 
-static int mv_otg_remove(struct platform_device *pdev)
+static void mv_otg_remove(struct platform_device *pdev)
 {
 	struct mv_otg *mvotg = platform_get_drvdata(pdev);
 
@@ -654,8 +654,6 @@ static int mv_otg_remove(struct platform_device *pdev)
 	mv_otg_disable(mvotg);
 
 	usb_remove_phy(&mvotg->phy);
-
-	return 0;
 }
 
 static int mv_otg_probe(struct platform_device *pdev)
@@ -869,7 +867,7 @@ static int mv_otg_resume(struct platform_device *pdev)
 
 static struct platform_driver mv_otg_driver = {
 	.probe = mv_otg_probe,
-	.remove = mv_otg_remove,
+	.remove_new = mv_otg_remove,
 	.driver = {
 		   .name = driver_name,
 		   .dev_groups = mv_otg_groups,
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index d2836ef5d15c7609277f18ceaab5e1f91f148f8a..e1a2b2ea098b563af8b1bc35516c368a98b840ed 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -733,7 +733,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	/* Some SoCs don't have anatop registers */
-	if (of_get_property(np, "fsl,anatop", NULL)) {
+	if (of_property_present(np, "fsl,anatop")) {
 		mxs_phy->regmap_anatop = syscon_regmap_lookup_by_phandle
 			(np, "fsl,anatop");
 		if (IS_ERR(mxs_phy->regmap_anatop)) {
@@ -801,13 +801,11 @@ static int mxs_phy_probe(struct platform_device *pdev)
 	return usb_add_phy_dev(&mxs_phy->phy);
 }
 
-static int mxs_phy_remove(struct platform_device *pdev)
+static void mxs_phy_remove(struct platform_device *pdev)
 {
 	struct mxs_phy *mxs_phy = platform_get_drvdata(pdev);
 
 	usb_remove_phy(&mxs_phy->phy);
-
-	return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -853,7 +851,7 @@ static SIMPLE_DEV_PM_OPS(mxs_phy_pm, mxs_phy_system_suspend,
 
 static struct platform_driver mxs_phy_driver = {
 	.probe = mxs_phy_probe,
-	.remove = mxs_phy_remove,
+	.remove_new = mxs_phy_remove,
 	.driver = {
 		.name = DRIVER_NAME,
 		.of_match_table = mxs_phy_dt_ids,
diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c
index f2d2cc586c5b7b301ec912022f47d4ab9e2c6319..47562d49dfc1b8958f6f18db841e47d5f410a90a 100644
--- a/drivers/usb/phy/phy-tahvo.c
+++ b/drivers/usb/phy/phy-tahvo.c
@@ -412,7 +412,7 @@ static int tahvo_usb_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int tahvo_usb_remove(struct platform_device *pdev)
+static void tahvo_usb_remove(struct platform_device *pdev)
 {
 	struct tahvo_usb *tu = platform_get_drvdata(pdev);
 
@@ -420,13 +420,11 @@ static int tahvo_usb_remove(struct platform_device *pdev)
 	usb_remove_phy(&tu->phy);
 	if (!IS_ERR(tu->ick))
 		clk_disable(tu->ick);
-
-	return 0;
 }
 
 static struct platform_driver tahvo_usb_driver = {
 	.probe		= tahvo_usb_probe,
-	.remove		= tahvo_usb_remove,
+	.remove_new	= tahvo_usb_remove,
 	.driver		= {
 		.name	= "tahvo-usb",
 		.dev_groups = tahvo_groups,
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index f0240107edb15270d32ec67e19fe5dc200838665..8b2ff3a8882d624953b3dbfffab80608d52ed8ad 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -1375,7 +1375,7 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
 	tegra_phy->is_legacy_phy =
 		of_property_read_bool(np, "nvidia,has-legacy-mode");
 
-	if (of_find_property(np, "dr_mode", NULL))
+	if (of_property_present(np, "dr_mode"))
 		tegra_phy->mode = usb_get_dr_mode(&pdev->dev);
 	else
 		tegra_phy->mode = USB_DR_MODE_HOST;
@@ -1486,18 +1486,16 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
 	return usb_add_phy_dev(&tegra_phy->u_phy);
 }
 
-static int tegra_usb_phy_remove(struct platform_device *pdev)
+static void tegra_usb_phy_remove(struct platform_device *pdev)
 {
 	struct tegra_usb_phy *tegra_phy = platform_get_drvdata(pdev);
 
 	usb_remove_phy(&tegra_phy->u_phy);
-
-	return 0;
 }
 
 static struct platform_driver tegra_usb_phy_driver = {
 	.probe		= tegra_usb_phy_probe,
-	.remove		= tegra_usb_phy_remove,
+	.remove_new	= tegra_usb_phy_remove,
 	.driver		= {
 		.name	= "tegra-phy",
 		.of_match_table = tegra_usb_phy_id_table,
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
index ab3c38a7d8ac07eb5ca50df8d0266cdcdc2b551e..c3ce6b1054f1c354717dfd14a0139e6493f97508 100644
--- a/drivers/usb/phy/phy-twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -409,7 +409,7 @@ static int twl6030_usb_probe(struct platform_device *pdev)
 	return status;
 }
 
-static int twl6030_usb_remove(struct platform_device *pdev)
+static void twl6030_usb_remove(struct platform_device *pdev)
 {
 	struct twl6030_usb *twl = platform_get_drvdata(pdev);
 
@@ -422,8 +422,6 @@ static int twl6030_usb_remove(struct platform_device *pdev)
 	free_irq(twl->irq2, twl);
 	regulator_put(twl->usb3v3);
 	cancel_work_sync(&twl->set_vbus_work);
-
-	return 0;
 }
 
 static const struct of_device_id twl6030_usb_id_table[] = {
@@ -434,7 +432,7 @@ MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);
 
 static struct platform_driver twl6030_usb_driver = {
 	.probe		= twl6030_usb_probe,
-	.remove		= twl6030_usb_remove,
+	.remove_new	= twl6030_usb_remove,
 	.driver		= {
 		.name	= "twl6030_usb",
 		.of_match_table = of_match_ptr(twl6030_usb_id_table),
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index 96f3939a65e203e5516cf8c31493e316fcad66d4..fa34efabcccfe331b3c70ebc762a1551b71f9480 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -823,7 +823,7 @@ static struct platform_driver renesas_usbhs_driver = {
 	.driver		= {
 		.name	= "renesas_usbhs",
 		.pm	= &usbhsc_pm_ops,
-		.of_match_table = of_match_ptr(usbhs_of_match),
+		.of_match_table = usbhs_of_match,
 	},
 	.probe		= usbhs_probe,
 	.remove		= usbhs_remove,
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index f31cc3c763299d4dc7affd31e7aa94c025841029..644a55447fd7f2fe88c957d8003f2e482914edda 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -595,6 +595,11 @@ static void option_instat_callback(struct urb *urb);
 #define SIERRA_VENDOR_ID			0x1199
 #define SIERRA_PRODUCT_EM9191			0x90d3
 
+/* UNISOC (Spreadtrum) products */
+#define UNISOC_VENDOR_ID			0x1782
+/* TOZED LT70-C based on UNISOC SL8563 uses UNISOC's vendor ID */
+#define TOZED_PRODUCT_LT70C			0x4055
+
 /* Device flags */
 
 /* Highest interface number which can be used with NCTRL() and RSVD() */
@@ -2225,6 +2230,7 @@ static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) },
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
index 6fca40ace83a01fb341318f265c6e44d2cf8dc31..fee581409bf605a29f9dd70afc3929bb86c461e1 100644
--- a/drivers/usb/serial/quatech2.c
+++ b/drivers/usb/serial/quatech2.c
@@ -176,14 +176,6 @@ static inline int qt2_control_msg(struct usb_device *dev,
 			       NULL, 0, QT2_USB_TIMEOUT);
 }
 
-static inline int qt2_setdevice(struct usb_device *dev, u8 *data)
-{
-	u16 x = ((u16) (data[1] << 8) | (u16) (data[0]));
-
-	return qt2_control_msg(dev, QT_SET_GET_DEVICE, x, 0);
-}
-
-
 static inline int qt2_getregister(struct usb_device *dev,
 				  u8 uart,
 				  u8 reg,
diff --git a/drivers/usb/typec/hd3ss3220.c b/drivers/usb/typec/hd3ss3220.c
index 746ef3a75b76a23f6f69f4218597f70928a43c66..8bbeb9b1e439407132fbb8bada675b4cc878b4a3 100644
--- a/drivers/usb/typec/hd3ss3220.c
+++ b/drivers/usb/typec/hd3ss3220.c
@@ -290,7 +290,7 @@ MODULE_DEVICE_TABLE(of, dev_ids);
 static struct i2c_driver hd3ss3220_driver = {
 	.driver = {
 		.name = "hd3ss3220",
-		.of_match_table = of_match_ptr(dev_ids),
+		.of_match_table = dev_ids,
 	},
 	.probe_new = hd3ss3220_probe,
 	.remove =  hd3ss3220_remove,
diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index 1ffce00d94b46217c1d07d6b94cf4595e68d6590..62ba53357612453a39ad47302e29f07ed8f9a092 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -190,7 +190,7 @@ static void fusb302_log(struct fusb302_chip *chip, const char *fmt, ...)
 
 static int fusb302_debug_show(struct seq_file *s, void *v)
 {
-	struct fusb302_chip *chip = (struct fusb302_chip *)s->private;
+	struct fusb302_chip *chip = s->private;
 	int tail;
 
 	mutex_lock(&chip->logbuffer_lock);
@@ -1813,7 +1813,7 @@ static int fusb302_pm_resume(struct device *dev)
 	return 0;
 }
 
-static const struct of_device_id fusb302_dt_match[] = {
+static const struct of_device_id fusb302_dt_match[] __maybe_unused = {
 	{.compatible = "fcs,fusb302"},
 	{},
 };
diff --git a/drivers/usb/typec/tcpm/tcpci_mt6360.c b/drivers/usb/typec/tcpm/tcpci_mt6360.c
index 1b7c31278ebbef35055ad73b3625605f3649e924..6fa8fd5c8041a6e31d365c61dc6a6f23f82d3f3a 100644
--- a/drivers/usb/typec/tcpm/tcpci_mt6360.c
+++ b/drivers/usb/typec/tcpm/tcpci_mt6360.c
@@ -43,12 +43,6 @@ struct mt6360_tcpc_info {
 	int irq;
 };
 
-static inline int mt6360_tcpc_read16(struct regmap *regmap,
-				     unsigned int reg, u16 *val)
-{
-	return regmap_raw_read(regmap, reg, val, sizeof(u16));
-}
-
 static inline int mt6360_tcpc_write16(struct regmap *regmap,
 				      unsigned int reg, u16 val)
 {
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 1ee774c263f08c06ea87f28dcca1a83ef614e279..3c6b0c8e2d3ae2c7c896e300f162afe557037c95 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -737,7 +737,7 @@ static void tcpm_log_source_caps(struct tcpm_port *port)
 
 static int tcpm_debug_show(struct seq_file *s, void *v)
 {
-	struct tcpm_port *port = (struct tcpm_port *)s->private;
+	struct tcpm_port *port = s->private;
 	int tail;
 
 	mutex_lock(&port->logbuffer_lock);
@@ -1523,7 +1523,21 @@ static bool svdm_consume_svids(struct tcpm_port *port, const u32 *p, int cnt)
 		pmdata->svids[pmdata->nsvids++] = svid;
 		tcpm_log(port, "SVID %d: 0x%x", pmdata->nsvids, svid);
 	}
-	return true;
+
+	/*
+	 * PD3.0 Spec 6.4.4.3.2: The SVIDs are returned 2 per VDO (see Table
+	 * 6-43), and can be returned maximum 6 VDOs per response (see Figure
+	 * 6-19). If the Respondersupports 12 or more SVID then the Discover
+	 * SVIDs Command Shall be executed multiple times until a Discover
+	 * SVIDs VDO is returned ending either with a SVID value of 0x0000 in
+	 * the last part of the last VDO or with a VDO containing two SVIDs
+	 * with values of 0x0000.
+	 *
+	 * However, some odd dockers support SVIDs less than 12 but without
+	 * 0x0000 in the last VDO, so we need to break the Discover SVIDs
+	 * request and return false here.
+	 */
+	return cnt == 7;
 abort:
 	tcpm_log(port, "SVID_DISCOVERY_MAX(%d) too low!", SVID_DISCOVERY_MAX);
 	return false;
@@ -6577,6 +6591,8 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
 	port->port_type = port->typec_caps.type;
 
 	port->role_sw = usb_role_switch_get(port->dev);
+	if (!port->role_sw)
+		port->role_sw = fwnode_usb_role_switch_get(tcpc->fwnode);
 	if (IS_ERR(port->role_sw)) {
 		err = PTR_ERR(port->role_sw);
 		goto out_destroy_wq;
diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c
index 485b90c13078a9e9517f308838a53686924c08d1..8b075ca82ef6de80b4b6f31fa316b675141705c3 100644
--- a/drivers/usb/typec/tipd/core.c
+++ b/drivers/usb/typec/tipd/core.c
@@ -16,6 +16,7 @@
 #include <linux/usb/typec.h>
 #include <linux/usb/typec_altmode.h>
 #include <linux/usb/role.h>
+#include <linux/workqueue.h>
 
 #include "tps6598x.h"
 #include "trace.h"
@@ -97,6 +98,8 @@ struct tps6598x {
 
 	int wakeup;
 	u16 pwr_status;
+	struct delayed_work	wq_poll;
+	irq_handler_t irq_handler;
 };
 
 static enum power_supply_property tps6598x_psy_props[] = {
@@ -177,16 +180,6 @@ static inline int tps6598x_read64(struct tps6598x *tps, u8 reg, u64 *val)
 	return tps6598x_block_read(tps, reg, val, sizeof(u64));
 }
 
-static inline int tps6598x_write16(struct tps6598x *tps, u8 reg, u16 val)
-{
-	return tps6598x_block_write(tps, reg, &val, sizeof(u16));
-}
-
-static inline int tps6598x_write32(struct tps6598x *tps, u8 reg, u32 val)
-{
-	return tps6598x_block_write(tps, reg, &val, sizeof(u32));
-}
-
 static inline int tps6598x_write64(struct tps6598x *tps, u8 reg, u64 val)
 {
 	return tps6598x_block_write(tps, reg, &val, sizeof(u64));
@@ -568,6 +561,18 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
 	return IRQ_NONE;
 }
 
+/* Time interval for Polling */
+#define POLL_INTERVAL	500 /* msecs */
+static void tps6598x_poll_work(struct work_struct *work)
+{
+	struct tps6598x *tps = container_of(to_delayed_work(work),
+					    struct tps6598x, wq_poll);
+
+	tps->irq_handler(0, tps);
+	queue_delayed_work(system_power_efficient_wq,
+			   &tps->wq_poll, msecs_to_jiffies(POLL_INTERVAL));
+}
+
 static int tps6598x_check_mode(struct tps6598x *tps)
 {
 	char mode[5] = { };
@@ -746,6 +751,7 @@ static int tps6598x_probe(struct i2c_client *client)
 			TPS_REG_INT_PLUG_EVENT;
 	}
 
+	tps->irq_handler = irq_handler;
 	/* Make sure the controller has application firmware running */
 	ret = tps6598x_check_mode(tps);
 	if (ret)
@@ -837,10 +843,18 @@ static int tps6598x_probe(struct i2c_client *client)
 			dev_err(&client->dev, "failed to register partner\n");
 	}
 
-	ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
-					irq_handler,
-					IRQF_SHARED | IRQF_ONESHOT,
-					dev_name(&client->dev), tps);
+	if (client->irq) {
+		ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+						irq_handler,
+						IRQF_SHARED | IRQF_ONESHOT,
+						dev_name(&client->dev), tps);
+	} else {
+		dev_warn(tps->dev, "Unable to find the interrupt, switching to polling\n");
+		INIT_DELAYED_WORK(&tps->wq_poll, tps6598x_poll_work);
+		queue_delayed_work(system_power_efficient_wq, &tps->wq_poll,
+				   msecs_to_jiffies(POLL_INTERVAL));
+	}
+
 	if (ret)
 		goto err_disconnect;
 
@@ -848,7 +862,7 @@ static int tps6598x_probe(struct i2c_client *client)
 	fwnode_handle_put(fwnode);
 
 	tps->wakeup = device_property_read_bool(tps->dev, "wakeup-source");
-	if (tps->wakeup) {
+	if (tps->wakeup && client->irq) {
 		device_init_wakeup(&client->dev, true);
 		enable_irq_wake(client->irq);
 	}
@@ -887,6 +901,9 @@ static int __maybe_unused tps6598x_suspend(struct device *dev)
 		enable_irq_wake(client->irq);
 	}
 
+	if (!client->irq)
+		cancel_delayed_work_sync(&tps->wq_poll);
+
 	return 0;
 }
 
@@ -900,6 +917,10 @@ static int __maybe_unused tps6598x_resume(struct device *dev)
 		enable_irq(client->irq);
 	}
 
+	if (client->irq)
+		queue_delayed_work(system_power_efficient_wq, &tps->wq_poll,
+				   msecs_to_jiffies(POLL_INTERVAL));
+
 	return 0;
 }
 
diff --git a/drivers/usb/typec/ucsi/Kconfig b/drivers/usb/typec/ucsi/Kconfig
index 8f9c4b9f31f79cb81a4a4c20202432ab9ea3a866..b3bb0191987ed50496a90bd444da132d6e17e5a1 100644
--- a/drivers/usb/typec/ucsi/Kconfig
+++ b/drivers/usb/typec/ucsi/Kconfig
@@ -58,4 +58,14 @@ config UCSI_STM32G0
 	  To compile the driver as a module, choose M here: the module will be
 	  called ucsi_stm32g0.
 
+config UCSI_PMIC_GLINK
+	tristate "UCSI Qualcomm PMIC GLINK Interface Driver"
+	depends on QCOM_PMIC_GLINK
+	help
+	  This driver enables UCSI support on platforms that expose UCSI
+	  interface as PMIC GLINK device.
+
+	  To compile the driver as a module, choose M here: the module will be
+	  called ucsi_glink.
+
 endif
diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile
index 480d533d762feca2f09410a9e996201fb0b62d00..77f09e13695613b1fef5ad8148a3429cbd61ae0b 100644
--- a/drivers/usb/typec/ucsi/Makefile
+++ b/drivers/usb/typec/ucsi/Makefile
@@ -18,3 +18,4 @@ endif
 obj-$(CONFIG_UCSI_ACPI)			+= ucsi_acpi.o
 obj-$(CONFIG_UCSI_CCG)			+= ucsi_ccg.o
 obj-$(CONFIG_UCSI_STM32G0)		+= ucsi_stm32g0.o
+obj-$(CONFIG_UCSI_PMIC_GLINK)		+= ucsi_glink.o
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 8d1baf28df55c90e3f3bf2078ee6373134ddcfc6..2b472ec01dc42e84c7c355c6eae4073428b9a2ac 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -1444,11 +1444,13 @@ static void ucsi_init_work(struct work_struct *work)
 
 	ret = ucsi_init(ucsi);
 	if (ret)
-		dev_err(ucsi->dev, "PPM init failed (%d)\n", ret);
+		dev_err_probe(ucsi->dev, ret, "PPM init failed\n");
 
 	if (ret == -EPROBE_DEFER) {
-		if (ucsi->work_count++ > UCSI_ROLE_SWITCH_WAIT_COUNT)
+		if (ucsi->work_count++ > UCSI_ROLE_SWITCH_WAIT_COUNT) {
+			dev_err(ucsi->dev, "PPM init failed, stop trying\n");
 			return;
+		}
 
 		queue_delayed_work(system_long_wq, &ucsi->work,
 				   UCSI_ROLE_SWITCH_INTERVAL);
diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c
index 62206a6b8ea75019e1ec767146a1a1d35e5e5b90..217355f1f9b94a7de899b9b2e9d9cd2f30b1ac56 100644
--- a/drivers/usb/typec/ucsi/ucsi_acpi.c
+++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
@@ -9,6 +9,7 @@
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/acpi.h>
+#include <linux/dmi.h>
 
 #include "ucsi.h"
 
@@ -23,6 +24,7 @@ struct ucsi_acpi {
 	struct completion complete;
 	unsigned long flags;
 	guid_t guid;
+	u64 cmd;
 };
 
 static int ucsi_acpi_dsm(struct ucsi_acpi *ua, int func)
@@ -62,6 +64,7 @@ static int ucsi_acpi_async_write(struct ucsi *ucsi, unsigned int offset,
 	struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
 
 	memcpy(ua->base + offset, val, val_len);
+	ua->cmd = *(u64 *)val;
 
 	return ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_WRITE);
 }
@@ -93,13 +96,46 @@ static const struct ucsi_operations ucsi_acpi_ops = {
 	.async_write = ucsi_acpi_async_write
 };
 
+static int
+ucsi_zenbook_read(struct ucsi *ucsi, unsigned int offset, void *val, size_t val_len)
+{
+	struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
+	int ret;
+
+	if (offset == UCSI_VERSION || UCSI_COMMAND(ua->cmd) == UCSI_PPM_RESET) {
+		ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
+		if (ret)
+			return ret;
+	}
+
+	memcpy(val, ua->base + offset, val_len);
+
+	return 0;
+}
+
+static const struct ucsi_operations ucsi_zenbook_ops = {
+	.read = ucsi_zenbook_read,
+	.sync_write = ucsi_acpi_sync_write,
+	.async_write = ucsi_acpi_async_write
+};
+
+static const struct dmi_system_id zenbook_dmi_id[] = {
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"),
+		},
+	},
+	{ }
+};
+
 static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data)
 {
 	struct ucsi_acpi *ua = data;
 	u32 cci;
 	int ret;
 
-	ret = ucsi_acpi_read(ua->ucsi, UCSI_CCI, &cci, sizeof(cci));
+	ret = ua->ucsi->ops->read(ua->ucsi, UCSI_CCI, &cci, sizeof(cci));
 	if (ret)
 		return;
 
@@ -114,6 +150,7 @@ static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data)
 static int ucsi_acpi_probe(struct platform_device *pdev)
 {
 	struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
+	const struct ucsi_operations *ops = &ucsi_acpi_ops;
 	struct ucsi_acpi *ua;
 	struct resource *res;
 	acpi_status status;
@@ -143,7 +180,10 @@ static int ucsi_acpi_probe(struct platform_device *pdev)
 	init_completion(&ua->complete);
 	ua->dev = &pdev->dev;
 
-	ua->ucsi = ucsi_create(&pdev->dev, &ucsi_acpi_ops);
+	if (dmi_check_system(zenbook_dmi_id))
+		ops = &ucsi_zenbook_ops;
+
+	ua->ucsi = ucsi_create(&pdev->dev, ops);
 	if (IS_ERR(ua->ucsi))
 		return PTR_ERR(ua->ucsi);
 
diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c
new file mode 100644
index 0000000000000000000000000000000000000000..b454a5159896a908341b8a8b1fd648d4f25a54e0
--- /dev/null
+++ b/drivers/usb/typec/ucsi/ucsi_glink.c
@@ -0,0 +1,345 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Linaro Ltd
+ */
+#include <linux/auxiliary_bus.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/mutex.h>
+#include <linux/property.h>
+#include <linux/soc/qcom/pdr.h>
+#include <linux/soc/qcom/pmic_glink.h>
+#include "ucsi.h"
+
+#define UCSI_BUF_SIZE                   48
+
+#define MSG_TYPE_REQ_RESP               1
+#define UCSI_BUF_SIZE                   48
+
+#define UC_NOTIFY_RECEIVER_UCSI         0x0
+#define UC_UCSI_READ_BUF_REQ            0x11
+#define UC_UCSI_WRITE_BUF_REQ           0x12
+#define UC_UCSI_USBC_NOTIFY_IND         0x13
+
+struct ucsi_read_buf_req_msg {
+	struct pmic_glink_hdr   hdr;
+};
+
+struct ucsi_read_buf_resp_msg {
+	struct pmic_glink_hdr   hdr;
+	u8                      buf[UCSI_BUF_SIZE];
+	u32                     ret_code;
+};
+
+struct ucsi_write_buf_req_msg {
+	struct pmic_glink_hdr   hdr;
+	u8                      buf[UCSI_BUF_SIZE];
+	u32                     reserved;
+};
+
+struct ucsi_write_buf_resp_msg {
+	struct pmic_glink_hdr   hdr;
+	u32                     ret_code;
+};
+
+struct ucsi_notify_ind_msg {
+	struct pmic_glink_hdr   hdr;
+	u32                     notification;
+	u32                     receiver;
+	u32                     reserved;
+};
+
+struct pmic_glink_ucsi {
+	struct device *dev;
+
+	struct pmic_glink_client *client;
+
+	struct ucsi *ucsi;
+	struct completion read_ack;
+	struct completion write_ack;
+	struct completion sync_ack;
+	bool sync_pending;
+	struct mutex lock;	/* protects concurrent access to PMIC Glink interface */
+
+	int sync_val;
+
+	struct work_struct notify_work;
+	struct work_struct register_work;
+
+	u8 read_buf[UCSI_BUF_SIZE];
+};
+
+static int pmic_glink_ucsi_read(struct ucsi *__ucsi, unsigned int offset,
+				void *val, size_t val_len)
+{
+	struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(__ucsi);
+	struct ucsi_read_buf_req_msg req = {};
+	unsigned long left;
+	int ret;
+
+	req.hdr.owner = PMIC_GLINK_OWNER_USBC;
+	req.hdr.type = MSG_TYPE_REQ_RESP;
+	req.hdr.opcode = UC_UCSI_READ_BUF_REQ;
+
+	mutex_lock(&ucsi->lock);
+	memset(ucsi->read_buf, 0, sizeof(ucsi->read_buf));
+	reinit_completion(&ucsi->read_ack);
+
+	ret = pmic_glink_send(ucsi->client, &req, sizeof(req));
+	if (ret < 0) {
+		dev_err(ucsi->dev, "failed to send UCSI read request: %d\n", ret);
+		goto out_unlock;
+	}
+
+	left = wait_for_completion_timeout(&ucsi->read_ack, 5 * HZ);
+	if (!left) {
+		dev_err(ucsi->dev, "timeout waiting for UCSI read response\n");
+		ret = -ETIMEDOUT;
+		goto out_unlock;
+	}
+
+	memcpy(val, &ucsi->read_buf[offset], val_len);
+	ret = 0;
+
+out_unlock:
+	mutex_unlock(&ucsi->lock);
+
+	return ret;
+}
+
+static int pmic_glink_ucsi_locked_write(struct pmic_glink_ucsi *ucsi, unsigned int offset,
+					const void *val, size_t val_len)
+{
+	struct ucsi_write_buf_req_msg req = {};
+	unsigned long left;
+	int ret;
+
+	req.hdr.owner = PMIC_GLINK_OWNER_USBC;
+	req.hdr.type = MSG_TYPE_REQ_RESP;
+	req.hdr.opcode = UC_UCSI_WRITE_BUF_REQ;
+	memcpy(&req.buf[offset], val, val_len);
+
+	reinit_completion(&ucsi->write_ack);
+
+	ret = pmic_glink_send(ucsi->client, &req, sizeof(req));
+	if (ret < 0) {
+		dev_err(ucsi->dev, "failed to send UCSI write request: %d\n", ret);
+		return ret;
+	}
+
+	left = wait_for_completion_timeout(&ucsi->write_ack, 5 * HZ);
+	if (!left) {
+		dev_err(ucsi->dev, "timeout waiting for UCSI write response\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int pmic_glink_ucsi_async_write(struct ucsi *__ucsi, unsigned int offset,
+				       const void *val, size_t val_len)
+{
+	struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(__ucsi);
+	int ret;
+
+	mutex_lock(&ucsi->lock);
+	ret = pmic_glink_ucsi_locked_write(ucsi, offset, val, val_len);
+	mutex_unlock(&ucsi->lock);
+
+	return ret;
+}
+
+static int pmic_glink_ucsi_sync_write(struct ucsi *__ucsi, unsigned int offset,
+				      const void *val, size_t val_len)
+{
+	struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(__ucsi);
+	unsigned long left;
+	int ret;
+
+	/* TOFIX: Downstream forces recipient to CON when UCSI_GET_ALTERNATE_MODES command */
+
+	mutex_lock(&ucsi->lock);
+	ucsi->sync_val = 0;
+	reinit_completion(&ucsi->sync_ack);
+	ucsi->sync_pending = true;
+	ret = pmic_glink_ucsi_locked_write(ucsi, offset, val, val_len);
+	mutex_unlock(&ucsi->lock);
+
+	left = wait_for_completion_timeout(&ucsi->sync_ack, 5 * HZ);
+	if (!left) {
+		dev_err(ucsi->dev, "timeout waiting for UCSI sync write response\n");
+		ret = -ETIMEDOUT;
+	} else if (ucsi->sync_val) {
+		dev_err(ucsi->dev, "sync write returned: %d\n", ucsi->sync_val);
+	}
+
+	ucsi->sync_pending = false;
+
+	return ret;
+}
+
+static const struct ucsi_operations pmic_glink_ucsi_ops = {
+	.read = pmic_glink_ucsi_read,
+	.sync_write = pmic_glink_ucsi_sync_write,
+	.async_write = pmic_glink_ucsi_async_write
+};
+
+static void pmic_glink_ucsi_read_ack(struct pmic_glink_ucsi *ucsi, const void *data, int len)
+{
+	const struct ucsi_read_buf_resp_msg *resp = data;
+
+	if (resp->ret_code)
+		return;
+
+	memcpy(ucsi->read_buf, resp->buf, UCSI_BUF_SIZE);
+	complete(&ucsi->read_ack);
+}
+
+static void pmic_glink_ucsi_write_ack(struct pmic_glink_ucsi *ucsi, const void *data, int len)
+{
+	const struct ucsi_write_buf_resp_msg *resp = data;
+
+	if (resp->ret_code)
+		return;
+
+	ucsi->sync_val = resp->ret_code;
+	complete(&ucsi->write_ack);
+}
+
+static void pmic_glink_ucsi_notify(struct work_struct *work)
+{
+	struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, notify_work);
+	unsigned int con_num;
+	u32 cci;
+	int ret;
+
+	ret = pmic_glink_ucsi_read(ucsi->ucsi, UCSI_CCI, &cci, sizeof(cci));
+	if (ret) {
+		dev_err(ucsi->dev, "failed to read CCI on notification\n");
+		return;
+	}
+
+	con_num = UCSI_CCI_CONNECTOR(cci);
+	if (con_num)
+		ucsi_connector_change(ucsi->ucsi, con_num);
+
+	if (ucsi->sync_pending && cci & UCSI_CCI_BUSY) {
+		ucsi->sync_val = -EBUSY;
+		complete(&ucsi->sync_ack);
+	} else if (ucsi->sync_pending &&
+		   (cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE))) {
+		complete(&ucsi->sync_ack);
+	}
+}
+
+static void pmic_glink_ucsi_register(struct work_struct *work)
+{
+	struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, register_work);
+
+	ucsi_register(ucsi->ucsi);
+}
+
+static void pmic_glink_ucsi_callback(const void *data, size_t len, void *priv)
+{
+	struct pmic_glink_ucsi *ucsi = priv;
+	const struct pmic_glink_hdr *hdr = data;
+
+	switch (hdr->opcode) {
+	case UC_UCSI_READ_BUF_REQ:
+		pmic_glink_ucsi_read_ack(ucsi, data, len);
+		break;
+	case UC_UCSI_WRITE_BUF_REQ:
+		pmic_glink_ucsi_write_ack(ucsi, data, len);
+		break;
+	case UC_UCSI_USBC_NOTIFY_IND:
+		schedule_work(&ucsi->notify_work);
+		break;
+	};
+}
+
+static void pmic_glink_ucsi_pdr_notify(void *priv, int state)
+{
+	struct pmic_glink_ucsi *ucsi = priv;
+
+	if (state == SERVREG_SERVICE_STATE_UP)
+		schedule_work(&ucsi->register_work);
+	else if (state == SERVREG_SERVICE_STATE_DOWN)
+		ucsi_unregister(ucsi->ucsi);
+}
+
+static void pmic_glink_ucsi_destroy(void *data)
+{
+	struct pmic_glink_ucsi *ucsi = data;
+
+	/* Protect to make sure we're not in a middle of a transaction from a glink callback */
+	mutex_lock(&ucsi->lock);
+	ucsi_destroy(ucsi->ucsi);
+	mutex_unlock(&ucsi->lock);
+}
+
+static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
+				 const struct auxiliary_device_id *id)
+{
+	struct pmic_glink_ucsi *ucsi;
+	struct device *dev = &adev->dev;
+	int ret;
+
+	ucsi = devm_kzalloc(dev, sizeof(*ucsi), GFP_KERNEL);
+	if (!ucsi)
+		return -ENOMEM;
+
+	ucsi->dev = dev;
+	dev_set_drvdata(dev, ucsi);
+
+	INIT_WORK(&ucsi->notify_work, pmic_glink_ucsi_notify);
+	INIT_WORK(&ucsi->register_work, pmic_glink_ucsi_register);
+	init_completion(&ucsi->read_ack);
+	init_completion(&ucsi->write_ack);
+	init_completion(&ucsi->sync_ack);
+	mutex_init(&ucsi->lock);
+
+	ucsi->ucsi = ucsi_create(dev, &pmic_glink_ucsi_ops);
+	if (IS_ERR(ucsi->ucsi))
+		return PTR_ERR(ucsi->ucsi);
+
+	/* Make sure we destroy *after* pmic_glink unregister */
+	ret = devm_add_action_or_reset(dev, pmic_glink_ucsi_destroy, ucsi);
+	if (ret)
+		return ret;
+
+	ucsi_set_drvdata(ucsi->ucsi, ucsi);
+
+	ucsi->client = devm_pmic_glink_register_client(dev,
+						       PMIC_GLINK_OWNER_USBC,
+						       pmic_glink_ucsi_callback,
+						       pmic_glink_ucsi_pdr_notify,
+						       ucsi);
+	return PTR_ERR_OR_ZERO(ucsi->client);
+}
+
+static void pmic_glink_ucsi_remove(struct auxiliary_device *adev)
+{
+	struct pmic_glink_ucsi *ucsi = dev_get_drvdata(&adev->dev);
+
+	/* Unregister first to stop having read & writes */
+	ucsi_unregister(ucsi->ucsi);
+}
+
+static const struct auxiliary_device_id pmic_glink_ucsi_id_table[] = {
+	{ .name = "pmic_glink.ucsi", },
+	{},
+};
+MODULE_DEVICE_TABLE(auxiliary, pmic_glink_ucsi_id_table);
+
+static struct auxiliary_driver pmic_glink_ucsi_driver = {
+	.name = "pmic_glink_ucsi",
+	.probe = pmic_glink_ucsi_probe,
+	.remove = pmic_glink_ucsi_remove,
+	.id_table = pmic_glink_ucsi_id_table,
+};
+
+module_auxiliary_driver(pmic_glink_ucsi_driver);
+
+MODULE_DESCRIPTION("Qualcomm PMIC GLINK UCSI driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/platform_data/usb3503.h b/include/linux/platform_data/usb3503.h
index d01ef97ddf362f040f3e4041d8eb4d0425113db2..f3c942f396f822e04334ca49442aab9f6016df72 100644
--- a/include/linux/platform_data/usb3503.h
+++ b/include/linux/platform_data/usb3503.h
@@ -12,6 +12,7 @@ enum usb3503_mode {
 	USB3503_MODE_UNKNOWN,
 	USB3503_MODE_HUB,
 	USB3503_MODE_STANDBY,
+	USB3503_MODE_BYPASS,
 };
 
 struct usb3503_platform_data {
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 0a81e0f5beb4b173a4de0f3038de8e5b43502c82..25f8e62a30ecac5dcf9463102966e4b5d7938a6c 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -303,6 +303,11 @@ void usb_put_intf(struct usb_interface *intf);
 #define USB_MAXINTERFACES	32
 #define USB_MAXIADS		(USB_MAXINTERFACES/2)
 
+bool usb_check_bulk_endpoints(
+		const struct usb_interface *intf, const u8 *ep_addrs);
+bool usb_check_int_endpoints(
+		const struct usb_interface *intf, const u8 *ep_addrs);
+
 /*
  * USB Resume Timer: Every Host controller driver should drive the resume
  * signalling on the bus for the amount of time defined by this macro.
@@ -716,13 +721,12 @@ struct usb_device {
 
 	unsigned long active_duration;
 
-#ifdef CONFIG_PM
 	unsigned long connect_time;
 
 	unsigned do_remote_wakeup:1;
 	unsigned reset_resume:1;
 	unsigned port_is_suspended:1;
-#endif
+
 	struct wusb_dev *wusb_dev;
 	int slot_id;
 	struct usb2_lpm_parameters l1_params;
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 608dc962748bcb3c301ad603ad927d1f3fc93ff9..a2448e98854f6355b37573111b4b92faad965c3d 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -150,6 +150,9 @@ struct usb_os_desc_table {
  *	GetStatus() request when the recipient is Interface.
  * @func_suspend: callback to be called when
  *	SetFeature(FUNCTION_SUSPEND) is reseived
+ * @func_suspended: Indicates whether the function is in function suspend state.
+ * @func_wakeup_armed: Indicates whether the function is armed by the host for
+ *	wakeup signaling.
  *
  * A single USB function uses one or more interfaces, and should in most
  * cases support operation at both full and high speeds.  Each function is
@@ -220,6 +223,8 @@ struct usb_function {
 	int			(*get_status)(struct usb_function *);
 	int			(*func_suspend)(struct usb_function *,
 						u8 suspend_opt);
+	bool			func_suspended;
+	bool			func_wakeup_armed;
 	/* private: */
 	/* internals */
 	struct list_head		list;
@@ -241,6 +246,7 @@ int config_ep_by_speed_and_alt(struct usb_gadget *g, struct usb_function *f,
 
 int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f,
 			struct usb_ep *_ep);
+int usb_func_wakeup(struct usb_function *func);
 
 #define	MAX_CONFIG_INTERFACES		16	/* arbitrary; max 255 */
 
@@ -413,6 +419,8 @@ extern int composite_dev_prepare(struct usb_composite_driver *composite,
 extern int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
 					 struct usb_ep *ep0);
 void composite_dev_cleanup(struct usb_composite_dev *cdev);
+void check_remote_wakeup_config(struct usb_gadget *g,
+				struct usb_configuration *c);
 
 static inline struct usb_composite_driver *to_cdriver(
 		struct usb_gadget_driver *gdrv)
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 00750f7020f3bfe13373fe455bac4c1859643681..75bda0783395a0f48c21611196264feb9cab6222 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -310,6 +310,8 @@ struct usb_udc;
 struct usb_gadget_ops {
 	int	(*get_frame)(struct usb_gadget *);
 	int	(*wakeup)(struct usb_gadget *);
+	int	(*func_wakeup)(struct usb_gadget *gadget, int intf_id);
+	int	(*set_remote_wakeup)(struct usb_gadget *, int set);
 	int	(*set_selfpowered) (struct usb_gadget *, int is_selfpowered);
 	int	(*vbus_session) (struct usb_gadget *, int is_active);
 	int	(*vbus_draw) (struct usb_gadget *, unsigned mA);
@@ -384,6 +386,8 @@ struct usb_gadget_ops {
  * @connected: True if gadget is connected.
  * @lpm_capable: If the gadget max_speed is FULL or HIGH, this flag
  *	indicates that it supports LPM as per the LPM ECN & errata.
+ * @wakeup_capable: True if gadget is capable of sending remote wakeup.
+ * @wakeup_armed: True if gadget is armed by the host for remote wakeup.
  * @irq: the interrupt number for device controller.
  * @id_number: a unique ID number for ensuring that gadget names are distinct
  *
@@ -445,6 +449,8 @@ struct usb_gadget {
 	unsigned			deactivated:1;
 	unsigned			connected:1;
 	unsigned			lpm_capable:1;
+	unsigned			wakeup_capable:1;
+	unsigned			wakeup_armed:1;
 	int				irq;
 	int				id_number;
 };
@@ -601,6 +607,7 @@ static inline int gadget_is_otg(struct usb_gadget *g)
 #if IS_ENABLED(CONFIG_USB_GADGET)
 int usb_gadget_frame_number(struct usb_gadget *gadget);
 int usb_gadget_wakeup(struct usb_gadget *gadget);
+int usb_gadget_set_remote_wakeup(struct usb_gadget *gadget, int set);
 int usb_gadget_set_selfpowered(struct usb_gadget *gadget);
 int usb_gadget_clear_selfpowered(struct usb_gadget *gadget);
 int usb_gadget_vbus_connect(struct usb_gadget *gadget);
@@ -616,6 +623,8 @@ static inline int usb_gadget_frame_number(struct usb_gadget *gadget)
 { return 0; }
 static inline int usb_gadget_wakeup(struct usb_gadget *gadget)
 { return 0; }
+static inline int usb_gadget_set_remote_wakeup(struct usb_gadget *gadget, int set)
+{ return 0; }
 static inline int usb_gadget_set_selfpowered(struct usb_gadget *gadget)
 { return 0; }
 static inline int usb_gadget_clear_selfpowered(struct usb_gadget *gadget)
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index b51c07111729bba22fb773bcf38a6087d40836ed..094c77eaf455165c435baa1679e56860ca39413e 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -488,9 +488,7 @@ extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
 
 extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev);
 
-#ifdef CONFIG_PM
 extern const struct dev_pm_ops usb_hcd_pci_pm_ops;
-#endif
 #endif /* CONFIG_USB_PCI */
 
 /* pci-ish (pdev null is ok) buffer alloc/mapping support */