aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-5.4/820-usb-0006-usb-dwc3-drd-add-usb-role-switch-class-support-for-d.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/layerscape/patches-5.4/820-usb-0006-usb-dwc3-drd-add-usb-role-switch-class-support-for-d.patch')
-rw-r--r--target/linux/layerscape/patches-5.4/820-usb-0006-usb-dwc3-drd-add-usb-role-switch-class-support-for-d.patch103
1 files changed, 103 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-5.4/820-usb-0006-usb-dwc3-drd-add-usb-role-switch-class-support-for-d.patch b/target/linux/layerscape/patches-5.4/820-usb-0006-usb-dwc3-drd-add-usb-role-switch-class-support-for-d.patch
new file mode 100644
index 0000000000..aece52c6a4
--- /dev/null
+++ b/target/linux/layerscape/patches-5.4/820-usb-0006-usb-dwc3-drd-add-usb-role-switch-class-support-for-d.patch
@@ -0,0 +1,103 @@
+From 8595748e58885439c7e18a11a94702378bff3b02 Mon Sep 17 00:00:00 2001
+From: Li Jun <jun.li@nxp.com>
+Date: Sun, 27 Jan 2019 19:40:03 +0800
+Subject: [PATCH] usb: dwc3: drd: add usb role switch class support for dual
+ role swap
+
+Register a usb_role_switch for dual role swap if the property
+"usb-role-switch" is present.
+
+Signed-off-by: Li Jun <jun.li@nxp.com>
+---
+ drivers/usb/dwc3/core.h | 2 ++
+ drivers/usb/dwc3/drd.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 48 insertions(+), 1 deletion(-)
+
+--- 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>
+@@ -1082,6 +1083,7 @@ struct dwc3 {
+ void __iomem *regs;
+ size_t regs_size;
+
++ struct usb_role_switch *role_switch;
+ enum usb_dr_mode dr_mode;
+ u32 current_dr_role;
+ u32 desired_dr_role;
+--- a/drivers/usb/dwc3/drd.c
++++ b/drivers/usb/dwc3/drd.c
+@@ -476,6 +476,43 @@ static struct extcon_dev *dwc3_get_extco
+ return edev;
+ }
+
++static int dwc3_usb_role_switch_set(struct device *dev, enum usb_role role)
++{
++ 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:
++ return 0;
++ };
++
++ dwc3_set_mode(dev_get_drvdata(dev), 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);
++ role = dwc->current_dr_role;
++ spin_unlock_irqrestore(&dwc->lock, flags);
++
++ return role;
++}
++
++static const struct usb_role_switch_desc dwc3_role_switch = {
++ .set = dwc3_usb_role_switch_set,
++ .get = dwc3_usb_role_switch_get,
++};
++
+ int dwc3_drd_init(struct dwc3 *dwc)
+ {
+ int ret, irq;
+@@ -484,7 +521,12 @@ int dwc3_drd_init(struct dwc3 *dwc)
+ if (IS_ERR(dwc->edev))
+ return PTR_ERR(dwc->edev);
+
+- if (dwc->edev) {
++ if (device_property_read_bool(dwc->dev, "usb-role-switch")) {
++ dwc->role_switch = usb_role_switch_register(dwc->dev,
++ &dwc3_role_switch);
++ if (IS_ERR(dwc->role_switch))
++ return PTR_ERR(dwc->role_switch);
++ } 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 +573,9 @@ void dwc3_drd_exit(struct dwc3 *dwc)
+ {
+ unsigned long flags;
+
++ if (dwc->role_switch)
++ usb_role_switch_unregister(dwc->role_switch);
++
+ if (dwc->edev)
+ extcon_unregister_notifier(dwc->edev, EXTCON_USB_HOST,
+ &dwc->edev_nb);