Some devices with A female host port and without use of usb_id pin
will need this for the otg controller works as device role
during firmware period and works as host role in rich os.

Signed-off-by: Kever Yang <kever.y...@rock-chips.com>
---
 drivers/usb/dwc2/core.c     |   13 +++++++++++++
 drivers/usb/dwc2/core.h     |    2 ++
 drivers/usb/dwc2/platform.c |    4 ++++
 3 files changed, 19 insertions(+)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 27d2c9b..6688951 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -118,6 +118,7 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg)
 {
        u32 greset;
        int count = 0;
+       u32 gusbcfg;
 
        dev_vdbg(hsotg->dev, "%s()\n", __func__);
 
@@ -148,6 +149,18 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg)
                }
        } while (greset & GRSTCTL_CSFTRST);
 
+       if (hsotg->dr_mode == USB_DR_MODE_HOST) {
+               gusbcfg = readl(hsotg->regs+GUSBCFG);
+               gusbcfg &= ~GUSBCFG_FORCEDEVMODE;
+               gusbcfg |= GUSBCFG_FORCEHOSTMODE;
+               writel(gusbcfg, hsotg->regs+GUSBCFG);
+       } else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) {
+               gusbcfg = readl(hsotg->regs+GUSBCFG);
+               gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
+               gusbcfg |= GUSBCFG_FORCEDEVMODE;
+               writel(gusbcfg, hsotg->regs+GUSBCFG);
+       }
+
        /*
         * NOTE: This long sleep is _very_ important, otherwise the core will
         * not stay in host mode after a connector ID change!
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 1efd10c..9fe960b 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -501,6 +501,7 @@ struct dwc2_hw_params {
  *                      a_peripheral and b_device=>b_host) this may not match
  *                      the core, but allows the software to determine
  *                      transitions
+ * @dr_mode:            requested mode of operation
  * @queuing_high_bandwidth: True if multiple packets of a high-bandwidth
  *                      transfer are in process of being queued
  * @srp_success:        Stores status of SRP request in the case of a FS PHY
@@ -592,6 +593,7 @@ struct dwc2_hsotg {
        /** Params to actually use */
        struct dwc2_core_params *core_params;
        enum usb_otg_state op_state;
+       enum usb_dr_mode        dr_mode;
 
        unsigned int queuing_high_bandwidth:1;
        unsigned int srp_success:1;
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index cc5983c..a2ac1ea 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -42,6 +42,8 @@
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 
+#include <linux/usb/of.h>
+
 #include "core.h"
 #include "hcd.h"
 
@@ -200,6 +202,8 @@ static int dwc2_driver_probe(struct platform_device *dev)
        dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n",
                (unsigned long)res->start, hsotg->regs);
 
+       hsotg->dr_mode = of_usb_get_dr_mode(dev->dev.of_node);
+
        retval = dwc2_hcd_init(hsotg, irq, params);
        if (retval)
                return retval;
-- 
1.7.9.5


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to