[PATCH] usb: musb: Auto detect device mode for USB OTG

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>From Alex Kurkin <alexandr.kurkin@xxxxxxxxxxx>

Very often, we need the following logic USB OTG. At any moment, when we connect the gadget through the OTG cable to our device, USB port must be changed to the host mode to supply power to the device, and to work correctly with this device. After removing the device with or without OTG cable, USB port must again go into a wait state. At the moment, in the latest version of the kernel, this option does not work. I propose a patch that implements this logic. The patch was created and tested on development kit am3517 evm. But I think this logic should be for any phy controller.
In my patch I use following patch http://arago-project.org/git/projects/?p=linux-am33x.git;a=commitdiff;h=5b20494150d8c045f152f06bee57da2e64dc4964

Signed-off-by: Alex Kurkin <alexandr.kurkin@xxxxxxxxxxx>
---
ndex: drivers/usb/musb/musb_core.c
===================================================================
--- drivers/usb/musb/musb_core.c    (revision 1606)
+++ drivers/usb/musb/musb_core.c    (revision 1612)
@@ -809,6 +809,7 @@
         case OTG_STATE_A_SUSPEND:
             usb_hcd_resume_root_hub(musb_to_hcd(musb));
             musb_root_disconnect(musb);
+            musb->a_wait_bcon = 1;
             if (musb->a_wait_bcon != 0 && is_otg_enabled(musb))
                 musb_platform_try_idle(musb, jiffies
                     + msecs_to_jiffies(musb->a_wait_bcon));
@@ -982,7 +983,6 @@

     musb->is_active = 0;
     devctl = musb_readb(regs, MUSB_DEVCTL);
-    devctl &= ~MUSB_DEVCTL_SESSION;

     if (is_otg_enabled(musb)) {
         /* session started after:
Index: drivers/usb/musb/am35x.c
===================================================================
--- drivers/usb/musb/am35x.c    (revision 1606)
+++ drivers/usb/musb/am35x.c    (revision 1612)
@@ -344,17 +344,22 @@
     spin_lock_irqsave(&musb->lock, flags);
     switch (musb->xceiv->state) {
     case OTG_STATE_A_WAIT_BCON:
+
         devctl &= ~MUSB_DEVCTL_SESSION;
         musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);

         devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
-        if (devctl & MUSB_DEVCTL_BDEVICE) {
-            musb->xceiv->state = OTG_STATE_B_IDLE;
-            MUSB_DEV_MODE(musb);
-        } else {
+
+        if (devctl & MUSB_DEVCTL_HM) {
             musb->xceiv->state = OTG_STATE_A_IDLE;
             MUSB_HST_MODE(musb);
+        } else {
+            musb->xceiv->state = OTG_STATE_B_IDLE;
+            MUSB_DEV_MODE(musb);
         }
+
+        mod_timer(&otg_workaround,
+        jiffies + POLL_SECONDS * HZ);
         break;
     case OTG_STATE_A_WAIT_VFALL:
         musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
@@ -362,14 +367,35 @@
                 MUSB_INTR_VBUSERROR << AM35X_INTR_USB_SHIFT);
         break;
     case OTG_STATE_B_IDLE:
+
         if (!is_peripheral_enabled(musb))
             break;

         devctl = musb_readb(mregs, MUSB_DEVCTL);
-        if (devctl & MUSB_DEVCTL_BDEVICE)
+        if (devctl & MUSB_DEVCTL_HM) {
+            musb->xceiv->state = OTG_STATE_A_IDLE;
+        } else {
             mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
-        else
+            musb_writeb(musb->mregs, MUSB_DEVCTL, devctl |
+            MUSB_DEVCTL_SESSION);
+        }
+        break;
+    case OTG_STATE_A_WAIT_VRISE:
+        devctl &= ~MUSB_DEVCTL_SESSION;
+        musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+        devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+        if (devctl & MUSB_DEVCTL_HM) {
             musb->xceiv->state = OTG_STATE_A_IDLE;
+            MUSB_HST_MODE(musb);
+        } else {
+            musb->xceiv->state = OTG_STATE_B_IDLE;
+            MUSB_DEV_MODE(musb);
+        }
+
+        mod_timer(&otg_workaround,
+        jiffies + POLL_SECONDS * HZ);
         break;
     default:
         break;
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux