2019-11-28 05:14:58

by John Stultz

[permalink] [raw]
Subject: [PATCH v6 0/8] HiKey960 USB support

Just another round here trying to push forward a patch series
submitted originally by Yu Chen to get HiKey960 dev-board's USB
functionality working.

The full patchset (including dts changes not submitted here) can
be found here:
https://git.linaro.org/people/john.stultz/android-dev.git/log/?id=950276ae1baab3a22836d1f89aeadbb08adf41e0


NOTE: I unfortunately don't have any deep knowledge of the
hardware other then the previously submitted code and what I
can intuit from testing. I tried to document the previously
undocumented bindings, fixed up a few minor checkpatch issues
and tried to address previous feedback as best I could.

I'd greatly appreciate any feedback or thoughts!

thanks
-john

New in v6:
* Felipe previously had disliked extending the dwc3 binding
to allow for more flexible clock and resest lists, so in
the last series I switched back to the dwc3-simple-of.c
approach, but Rob pushed back on the last series, and with
no reply from Felipe, I've switched back to this appraoch.
Clear guidance would be appreciated here!
* Fixed build issue Reported-by: kbuild test robot <[email protected]>


Cc: Greg Kroah-Hartman <[email protected]>
Cc: Rob Herring <[email protected]>
Cc: Mark Rutland <[email protected]>
CC: ShuFan Lee <[email protected]>
Cc: Heikki Krogerus <[email protected]>
Cc: Suzuki K Poulose <[email protected]>
Cc: Chunfeng Yun <[email protected]>
Cc: Yu Chen <[email protected]>
Cc: Felipe Balbi <[email protected]>
Cc: Hans de Goede <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: Jun Li <[email protected]>
Cc: Valentin Schneider <[email protected]>
Cc: Jack Pham <[email protected]>
Cc: [email protected]
Cc: [email protected]

John Stultz (5):
dt-bindings: usb: generic: Add role-switch-default-mode binding
usb: dwc3: Add support for role-switch-default-mode binding
dt-bindings: usb: dwc3: Allow clock list & resets to be more flexible
usb: dwc3: Rework clock initialization to be more flexible
usb: dwc3: Rework resets initialization to be more flexible

Yu Chen (3):
usb: dwc3: Registering a role switch in the DRD code.
dt-bindings: misc: Add bindings for HiSilicon usb hub and data role
switch functionality on HiKey960
misc: hisi_hikey_usb: Driver to support usb functionality of Hikey960

.../bindings/misc/hisilicon-hikey-usb.txt | 40 ++++
.../devicetree/bindings/usb/dwc3.txt | 5 +-
.../devicetree/bindings/usb/generic.txt | 6 +
drivers/misc/Kconfig | 6 +
drivers/misc/Makefile | 1 +
drivers/misc/hisi_hikey_usb.c | 178 ++++++++++++++++++
drivers/usb/dwc3/core.c | 22 +--
drivers/usb/dwc3/core.h | 6 +
drivers/usb/dwc3/drd.c | 96 +++++++++-
9 files changed, 341 insertions(+), 19 deletions(-)
create mode 100644 Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt
create mode 100644 drivers/misc/hisi_hikey_usb.c

--
2.17.1


2019-11-28 05:15:34

by John Stultz

[permalink] [raw]
Subject: [PATCH v6 1/8] usb: dwc3: Registering a role switch in the DRD code.

From: Yu Chen <[email protected]>

The Type-C drivers use USB role switch API to inform the
system about the negotiated data role, so registering a role
switch in the DRD code in order to support platforms with
USB Type-C connectors.

Cc: Greg Kroah-Hartman <[email protected]>
Cc: Rob Herring <[email protected]>
Cc: Mark Rutland <[email protected]>
CC: ShuFan Lee <[email protected]>
Cc: Heikki Krogerus <[email protected]>
Cc: Suzuki K Poulose <[email protected]>
Cc: Chunfeng Yun <[email protected]>
Cc: Yu Chen <[email protected]>
Cc: Felipe Balbi <[email protected]>
Cc: Hans de Goede <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: Jun Li <[email protected]>
Cc: Valentin Schneider <[email protected]>
Cc: Jack Pham <[email protected]>
Cc: [email protected]
Cc: [email protected]
Suggested-by: Heikki Krogerus <[email protected]>
Signed-off-by: Yu Chen <[email protected]>
Signed-off-by: John Stultz <[email protected]>
Change-Id: Ibd89b7eb3e59688895a2d317f3515e6d2705c6f3
---
v2: Fix role_sw and role_switch_default_mode descriptions as
reported by kbuild test robot <[email protected]>

v3: Split out the role-switch-default-host logic into its own
patch

v5: Drop selecting CONFIG_USB_ROLE_SWITCH & ifdef dependent code

v6: Fix build issue Reported-by: kbuild test robot <[email protected]>
---
drivers/usb/dwc3/core.h | 3 ++
drivers/usb/dwc3/drd.c | 77 ++++++++++++++++++++++++++++++++++++++++-
2 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 1c8b349379af..6f19e9891767 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -25,6 +25,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
+#include <linux/usb/role.h>
#include <linux/ulpi/interface.h>

#include <linux/phy/phy.h>
@@ -951,6 +952,7 @@ struct dwc3_scratchpad_array {
* @hsphy_mode: UTMI phy mode, one of following:
* - USBPHY_INTERFACE_MODE_UTMI
* - USBPHY_INTERFACE_MODE_UTMIW
+ * @role_sw: usb_role_switch handle
* @usb2_phy: pointer to USB2 PHY
* @usb3_phy: pointer to USB3 PHY
* @usb2_generic_phy: pointer to USB2 PHY
@@ -1084,6 +1086,7 @@ struct dwc3 {
struct extcon_dev *edev;
struct notifier_block edev_nb;
enum usb_phy_interface hsphy_mode;
+ struct usb_role_switch *role_sw;

u32 fladj;
u32 irq_gadget;
diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c
index c946d64142ad..3b57d2ddda93 100644
--- a/drivers/usb/dwc3/drd.c
+++ b/drivers/usb/dwc3/drd.c
@@ -476,6 +476,73 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
return edev;
}

+#ifdef CONFIG_USB_ROLE_SWITCH
+#define ROLE_SWITCH 1
+static int dwc3_usb_role_switch_set(struct device *dev, enum usb_role role)
+{
+ struct dwc3 *dwc = dev_get_drvdata(dev);
+ u32 mode;
+
+ switch (role) {
+ case USB_ROLE_HOST:
+ mode = DWC3_GCTL_PRTCAP_HOST;
+ break;
+ case USB_ROLE_DEVICE:
+ mode = DWC3_GCTL_PRTCAP_DEVICE;
+ break;
+ default:
+ mode = DWC3_GCTL_PRTCAP_DEVICE;
+ break;
+ }
+
+ dwc3_set_mode(dwc, mode);
+ return 0;
+}
+
+static enum usb_role dwc3_usb_role_switch_get(struct device *dev)
+{
+ struct dwc3 *dwc = dev_get_drvdata(dev);
+ unsigned long flags;
+ enum usb_role role;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+ switch (dwc->current_dr_role) {
+ case DWC3_GCTL_PRTCAP_HOST:
+ role = USB_ROLE_HOST;
+ break;
+ case DWC3_GCTL_PRTCAP_DEVICE:
+ role = USB_ROLE_DEVICE;
+ break;
+ case DWC3_GCTL_PRTCAP_OTG:
+ role = dwc->current_otg_role;
+ break;
+ default:
+ role = USB_ROLE_DEVICE;
+ break;
+ }
+ spin_unlock_irqrestore(&dwc->lock, flags);
+ return role;
+}
+
+static int dwc3_setup_role_switch(struct dwc3 *dwc)
+{
+ struct usb_role_switch_desc dwc3_role_switch = {NULL};
+
+ dwc3_role_switch.fwnode = dev_fwnode(dwc->dev);
+ dwc3_role_switch.set = dwc3_usb_role_switch_set;
+ dwc3_role_switch.get = dwc3_usb_role_switch_get;
+ dwc->role_sw = usb_role_switch_register(dwc->dev, &dwc3_role_switch);
+ if (IS_ERR(dwc->role_sw))
+ return PTR_ERR(dwc->role_sw);
+
+ dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
+ return 0;
+}
+#else
+#define ROLE_SWITCH 0
+#define dwc3_setup_role_switch(x) 0
+#endif
+
int dwc3_drd_init(struct dwc3 *dwc)
{
int ret, irq;
@@ -484,7 +551,12 @@ int dwc3_drd_init(struct dwc3 *dwc)
if (IS_ERR(dwc->edev))
return PTR_ERR(dwc->edev);

- if (dwc->edev) {
+ if (ROLE_SWITCH &&
+ device_property_read_bool(dwc->dev, "usb-role-switch")) {
+ ret = dwc3_setup_role_switch(dwc);
+ if (ret < 0)
+ return ret;
+ } else if (dwc->edev) {
dwc->edev_nb.notifier_call = dwc3_drd_notifier;
ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,
&dwc->edev_nb);
@@ -531,6 +603,9 @@ void dwc3_drd_exit(struct dwc3 *dwc)
{
unsigned long flags;

+ if (dwc->role_sw)
+ usb_role_switch_unregister(dwc->role_sw);
+
if (dwc->edev)
extcon_unregister_notifier(dwc->edev, EXTCON_USB_HOST,
&dwc->edev_nb);
--
2.17.1

2019-12-02 10:35:19

by Bryan O'Donoghue

[permalink] [raw]
Subject: Re: [PATCH v6 1/8] usb: dwc3: Registering a role switch in the DRD code.

On 28/11/2019 05:09, John Stultz wrote:
> From: Yu Chen <[email protected]>
>
> The Type-C drivers use USB role switch API to inform the
> system about the negotiated data role, so registering a role
> switch in the DRD code in order to support platforms with
> USB Type-C connectors.
>
> Cc: Greg Kroah-Hartman <[email protected]>
> Cc: Rob Herring <[email protected]>
> Cc: Mark Rutland <[email protected]>
> CC: ShuFan Lee <[email protected]>
> Cc: Heikki Krogerus <[email protected]>
> Cc: Suzuki K Poulose <[email protected]>
> Cc: Chunfeng Yun <[email protected]>
> Cc: Yu Chen <[email protected]>
> Cc: Felipe Balbi <[email protected]>
> Cc: Hans de Goede <[email protected]>
> Cc: Andy Shevchenko <[email protected]>
> Cc: Jun Li <[email protected]>
> Cc: Valentin Schneider <[email protected]>
> Cc: Jack Pham <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Suggested-by: Heikki Krogerus <[email protected]>
> Signed-off-by: Yu Chen <[email protected]>
> Signed-off-by: John Stultz <[email protected]>
> Change-Id: Ibd89b7eb3e59688895a2d317f3515e6d2705c6f3
> ---
> v2: Fix role_sw and role_switch_default_mode descriptions as
> reported by kbuild test robot <[email protected]>
>
> v3: Split out the role-switch-default-host logic into its own
> patch
>
> v5: Drop selecting CONFIG_USB_ROLE_SWITCH & ifdef dependent code
>
> v6: Fix build issue Reported-by: kbuild test robot <[email protected]>
> ---
> drivers/usb/dwc3/core.h | 3 ++
> drivers/usb/dwc3/drd.c | 77 ++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 79 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 1c8b349379af..6f19e9891767 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -25,6 +25,7 @@
> #include <linux/usb/ch9.h>
> #include <linux/usb/gadget.h>
> #include <linux/usb/otg.h>
> +#include <linux/usb/role.h>
> #include <linux/ulpi/interface.h>
>
> #include <linux/phy/phy.h>
> @@ -951,6 +952,7 @@ struct dwc3_scratchpad_array {
> * @hsphy_mode: UTMI phy mode, one of following:
> * - USBPHY_INTERFACE_MODE_UTMI
> * - USBPHY_INTERFACE_MODE_UTMIW
> + * @role_sw: usb_role_switch handle
> * @usb2_phy: pointer to USB2 PHY
> * @usb3_phy: pointer to USB3 PHY
> * @usb2_generic_phy: pointer to USB2 PHY
> @@ -1084,6 +1086,7 @@ struct dwc3 {
> struct extcon_dev *edev;
> struct notifier_block edev_nb;
> enum usb_phy_interface hsphy_mode;
> + struct usb_role_switch *role_sw;
>
> u32 fladj;
> u32 irq_gadget;
> diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c
> index c946d64142ad..3b57d2ddda93 100644
> --- a/drivers/usb/dwc3/drd.c
> +++ b/drivers/usb/dwc3/drd.c
> @@ -476,6 +476,73 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
> return edev;
> }
>
> +#ifdef CONFIG_USB_ROLE_SWITCH
> +#define ROLE_SWITCH 1
> +static int dwc3_usb_role_switch_set(struct device *dev, enum usb_role role)
> +{
> + struct dwc3 *dwc = dev_get_drvdata(dev);
> + u32 mode;
> +
> + switch (role) {
> + case USB_ROLE_HOST:
> + mode = DWC3_GCTL_PRTCAP_HOST;
> + break;
> + case USB_ROLE_DEVICE:
> + mode = DWC3_GCTL_PRTCAP_DEVICE;
> + break;
> + default:
> + mode = DWC3_GCTL_PRTCAP_DEVICE;
> + break;
> + }
> +
> + dwc3_set_mode(dwc, mode);
> + return 0;
> +}
> +
> +static enum usb_role dwc3_usb_role_switch_get(struct device *dev)
> +{
> + struct dwc3 *dwc = dev_get_drvdata(dev);
> + unsigned long flags;
> + enum usb_role role;
> +
> + spin_lock_irqsave(&dwc->lock, flags);
> + switch (dwc->current_dr_role) {
> + case DWC3_GCTL_PRTCAP_HOST:
> + role = USB_ROLE_HOST;
> + break;
> + case DWC3_GCTL_PRTCAP_DEVICE:
> + role = USB_ROLE_DEVICE;
> + break;
> + case DWC3_GCTL_PRTCAP_OTG:
> + role = dwc->current_otg_role;
> + break;
> + default:
> + role = USB_ROLE_DEVICE;
> + break;
> + }
> + spin_unlock_irqrestore(&dwc->lock, flags);
> + return role;
> +}
> +
> +static int dwc3_setup_role_switch(struct dwc3 *dwc)
> +{
> + struct usb_role_switch_desc dwc3_role_switch = {NULL};
> +
> + dwc3_role_switch.fwnode = dev_fwnode(dwc->dev);
> + dwc3_role_switch.set = dwc3_usb_role_switch_set;
> + dwc3_role_switch.get = dwc3_usb_role_switch_get;
> + dwc->role_sw = usb_role_switch_register(dwc->dev, &dwc3_role_switch);
> + if (IS_ERR(dwc->role_sw))
> + return PTR_ERR(dwc->role_sw);
> +
> + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
> + return 0;
> +}
> +#else
> +#define ROLE_SWITCH 0
> +#define dwc3_setup_role_switch(x) 0
> +#endif
> +
> int dwc3_drd_init(struct dwc3 *dwc)
> {
> int ret, irq;
> @@ -484,7 +551,12 @@ int dwc3_drd_init(struct dwc3 *dwc)
> if (IS_ERR(dwc->edev))
> return PTR_ERR(dwc->edev);
>
> - if (dwc->edev) {
> + if (ROLE_SWITCH &&
> + device_property_read_bool(dwc->dev, "usb-role-switch")) {
> + ret = dwc3_setup_role_switch(dwc);
> + if (ret < 0)
> + return ret;
> + } else if (dwc->edev) {
> dwc->edev_nb.notifier_call = dwc3_drd_notifier;
> ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,
> &dwc->edev_nb);
> @@ -531,6 +603,9 @@ void dwc3_drd_exit(struct dwc3 *dwc)
> {
> unsigned long flags;
>
> + if (dwc->role_sw)
> + usb_role_switch_unregister(dwc->role_sw);
> +
> if (dwc->edev)
> extcon_unregister_notifier(dwc->edev, EXTCON_USB_HOST,
> &dwc->edev_nb);
>

Try again ;)

Tested-by: Bryan O'Donoghue <[email protected]>

2019-12-02 10:36:44

by Bryan O'Donoghue

[permalink] [raw]
Subject: Re: [PATCH v6 1/8] usb: dwc3: Registering a role switch in the DRD code.

On 28/11/2019 05:09, John Stultz wrote:
> From: Yu Chen <[email protected]>
>
> The Type-C drivers use USB role switch API to inform the
> system about the negotiated data role, so registering a role
> switch in the DRD code in order to support platforms with
> USB Type-C connectors.
>
> Cc: Greg Kroah-Hartman <[email protected]>
> Cc: Rob Herring <[email protected]>
> Cc: Mark Rutland <[email protected]>
> CC: ShuFan Lee <[email protected]>
> Cc: Heikki Krogerus <[email protected]>
> Cc: Suzuki K Poulose <[email protected]>
> Cc: Chunfeng Yun <[email protected]>
> Cc: Yu Chen <[email protected]>
> Cc: Felipe Balbi <[email protected]>
> Cc: Hans de Goede <[email protected]>
> Cc: Andy Shevchenko <[email protected]>
> Cc: Jun Li <[email protected]>
> Cc: Valentin Schneider <[email protected]>
> Cc: Jack Pham <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Suggested-by: Heikki Krogerus <[email protected]>
> Signed-off-by: Yu Chen <[email protected]>
> Signed-off-by: John Stultz <[email protected]>
> Change-Id: Ibd89b7eb3e59688895a2d317f3515e6d2705c6f3
> ---
> v2: Fix role_sw and role_switch_default_mode descriptions as
> reported by kbuild test robot <[email protected]>
>
> v3: Split out the role-switch-default-host logic into its own
> patch
>
> v5: Drop selecting CONFIG_USB_ROLE_SWITCH & ifdef dependent code
>
> v6: Fix build issue Reported-by: kbuild test robot <[email protected]>
> ---
> drivers/usb/dwc3/core.h | 3 ++
> drivers/usb/dwc3/drd.c | 77 ++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 79 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 1c8b349379af..6f19e9891767 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -25,6 +25,7 @@
> #include <linux/usb/ch9.h>
> #include <linux/usb/gadget.h>
> #include <linux/usb/otg.h>
> +#include <linux/usb/role.h>
> #include <linux/ulpi/interface.h>
>
> #include <linux/phy/phy.h>
> @@ -951,6 +952,7 @@ struct dwc3_scratchpad_array {
> * @hsphy_mode: UTMI phy mode, one of following:
> * - USBPHY_INTERFACE_MODE_UTMI
> * - USBPHY_INTERFACE_MODE_UTMIW
> + * @role_sw: usb_role_switch handle
> * @usb2_phy: pointer to USB2 PHY
> * @usb3_phy: pointer to USB3 PHY
> * @usb2_generic_phy: pointer to USB2 PHY
> @@ -1084,6 +1086,7 @@ struct dwc3 {
> struct extcon_dev *edev;
> struct notifier_block edev_nb;
> enum usb_phy_interface hsphy_mode;
> + struct usb_role_switch *role_sw;
>
> u32 fladj;
> u32 irq_gadget;
> diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c
> index c946d64142ad..3b57d2ddda93 100644
> --- a/drivers/usb/dwc3/drd.c
> +++ b/drivers/usb/dwc3/drd.c
> @@ -476,6 +476,73 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
> return edev;
> }
>
> +#ifdef CONFIG_USB_ROLE_SWITCH
> +#define ROLE_SWITCH 1
> +static int dwc3_usb_role_switch_set(struct device *dev, enum usb_role role)
> +{
> + struct dwc3 *dwc = dev_get_drvdata(dev);
> + u32 mode;
> +
> + switch (role) {
> + case USB_ROLE_HOST:
> + mode = DWC3_GCTL_PRTCAP_HOST;
> + break;
> + case USB_ROLE_DEVICE:
> + mode = DWC3_GCTL_PRTCAP_DEVICE;
> + break;
> + default:
> + mode = DWC3_GCTL_PRTCAP_DEVICE;
> + break;
> + }
> +
> + dwc3_set_mode(dwc, mode);
> + return 0;
> +}
> +
> +static enum usb_role dwc3_usb_role_switch_get(struct device *dev)
> +{
> + struct dwc3 *dwc = dev_get_drvdata(dev);
> + unsigned long flags;
> + enum usb_role role;
> +
> + spin_lock_irqsave(&dwc->lock, flags);
> + switch (dwc->current_dr_role) {
> + case DWC3_GCTL_PRTCAP_HOST:
> + role = USB_ROLE_HOST;
> + break;
> + case DWC3_GCTL_PRTCAP_DEVICE:
> + role = USB_ROLE_DEVICE;
> + break;
> + case DWC3_GCTL_PRTCAP_OTG:
> + role = dwc->current_otg_role;
> + break;
> + default:
> + role = USB_ROLE_DEVICE;
> + break;
> + }
> + spin_unlock_irqrestore(&dwc->lock, flags);
> + return role;
> +}
> +
> +static int dwc3_setup_role_switch(struct dwc3 *dwc)
> +{
> + struct usb_role_switch_desc dwc3_role_switch = {NULL};
> +
> + dwc3_role_switch.fwnode = dev_fwnode(dwc->dev);
> + dwc3_role_switch.set = dwc3_usb_role_switch_set;
> + dwc3_role_switch.get = dwc3_usb_role_switch_get;
> + dwc->role_sw = usb_role_switch_register(dwc->dev, &dwc3_role_switch);
> + if (IS_ERR(dwc->role_sw))
> + return PTR_ERR(dwc->role_sw);
> +
> + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
> + return 0;
> +}
> +#else
> +#define ROLE_SWITCH 0
> +#define dwc3_setup_role_switch(x) 0
> +#endif
> +
> int dwc3_drd_init(struct dwc3 *dwc)
> {
> int ret, irq;
> @@ -484,7 +551,12 @@ int dwc3_drd_init(struct dwc3 *dwc)
> if (IS_ERR(dwc->edev))
> return PTR_ERR(dwc->edev);
>
> - if (dwc->edev) {
> + if (ROLE_SWITCH &&
> + device_property_read_bool(dwc->dev, "usb-role-switch")) {
> + ret = dwc3_setup_role_switch(dwc);
> + if (ret < 0)
> + return ret;
> + } else if (dwc->edev) {
> dwc->edev_nb.notifier_call = dwc3_drd_notifier;
> ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,
> &dwc->edev_nb);
> @@ -531,6 +603,9 @@ void dwc3_drd_exit(struct dwc3 *dwc)
> {
> unsigned long flags;
>
> + if (dwc->role_sw)
> + usb_role_switch_unregister(dwc->role_sw);
> +
> if (dwc->edev)
> extcon_unregister_notifier(dwc->edev, EXTCON_USB_HOST,
> &dwc->edev_nb);
>

This again I've used on the qcs404 and it works nicely.

Tested-by: Bryan O'Donoghue <[email protected]>