musb: highly experimental working support for LS/FS/HS(in FS) devices
authorPaul Fertser <fercerpav@gmail.com>
Wed, 3 Nov 2010 21:09:07 +0000 (00:09 +0300)
committerPaul Fertser <fercerpav@gmail.com>
Wed, 3 Nov 2010 21:09:07 +0000 (00:09 +0300)
With this patch i can use all kinds of devices this way:
hoston; booston;
Then i need to issue mconnect and LS device will be available immediately,
for a FS/HS device i need to issue mconnect twice with some delay
inbetween.

After boostoff; hostoff it usually helps to say lsusb once (and wait for
about 10 seconds until it returns) to restore to the default state.

drivers/usb/musb/musb_procfs.c
drivers/usb/musb/omap2430.c

index 5cac30a..c8d6eca 100644 (file)
@@ -601,6 +601,8 @@ done:
  * T start sending TEST_PACKET
  * D<num> set/query the debug level
  */
+int musb_platform_resume(struct musb *musb);
+
 static int musb_proc_write(struct file *file, const char __user *buffer,
                        unsigned long count, void *data)
 {
@@ -614,7 +616,70 @@ static int musb_proc_write(struct file *file, const char __user *buffer,
        if (unlikely(copy_from_user(&cmd, buffer, 1)))
                return -EFAULT;
 
+       musb_platform_resume(musb);
+
        switch (cmd) {
+       case 'V':
+               if (mbase) {
+                       musb_ulpi_writeb(mbase, ISP1704_USB_INTFALL, 0x1f);
+                       musb_ulpi_writeb(mbase, ISP1704_USB_INTRISE, 0x1f);
+               }
+               break;
+       case 'v':
+               if (mbase) {
+                       musb_ulpi_writeb(mbase, ISP1704_USB_INTFALL, 0);
+                       musb_ulpi_writeb(mbase, ISP1704_USB_INTRISE, 0);
+               }
+               break;
+       case 'S':
+               if (mbase) {
+                       reg = musb_readb(mbase, MUSB_DEVCTL)
+                                       | MUSB_DEVCTL_SESSION;
+                       musb_writeb(mbase, MUSB_DEVCTL, reg);
+               }
+               break;
+       case 's':
+               if (mbase) {
+                       reg = musb_readb(mbase, MUSB_DEVCTL)
+                                       & ~MUSB_DEVCTL_SESSION;
+                       musb_writeb(mbase, MUSB_DEVCTL, reg);
+               }
+               break;
+       case 'R':
+               if (mbase) {
+                       reg = musb_readb(mbase, MUSB_POWER)
+                                       | MUSB_POWER_RESET;
+                       musb_writeb(mbase, MUSB_POWER, reg);
+               }
+               break;
+       case 'r':
+               if (mbase) {
+                       reg = musb_readb(mbase, MUSB_POWER)
+                                       & ~MUSB_POWER_RESET;
+                       musb_writeb(mbase, MUSB_POWER, reg);
+               }
+               break;
+       case 'Q':
+               if (mbase) {
+                       reg = musb_readb(mbase, MUSB_TESTMODE)
+                                       | MUSB_TEST_FORCE_FS
+                                       | MUSB_TEST_FORCE_HOST;
+                       musb_writeb(mbase, MUSB_TESTMODE, reg);
+               }
+               break;
+       case 'A':
+               if (mbase) {
+                       musb_writeb(mbase, MUSB_TESTMODE, 0);
+               }
+               break;
+       case 'q':
+               if (mbase) {
+                       reg = musb_readb(mbase, MUSB_TESTMODE)
+                                       & ~MUSB_TEST_FORCE_FS;
+                       musb_writeb(mbase, MUSB_TESTMODE, reg);
+               }
+               break;
+
        case 'C':
                if (mbase) {
                        reg = musb_readb(mbase, MUSB_POWER)
@@ -648,10 +713,7 @@ static int musb_proc_write(struct file *file, const char __user *buffer,
                break;
 
        case 'F':
-               reg = musb_readb(mbase, MUSB_DEVCTL);
-               reg |= MUSB_DEVCTL_SESSION;
-               musb_writeb(mbase, MUSB_DEVCTL, reg);
-
+               {
                /* Pretend there's a session request */
                musb->ep0_stage = MUSB_EP0_START;
                musb->xceiv->state = OTG_STATE_A_IDLE;
@@ -659,7 +721,6 @@ static int musb_proc_write(struct file *file, const char __user *buffer,
                musb_set_vbus(musb, 1);
 
                /* Connect request */
-               {
                struct usb_hcd *hcd = musb_to_hcd(musb);
                u8 testmode;
 
@@ -684,22 +745,25 @@ static int musb_proc_write(struct file *file, const char __user *buffer,
                musb->port1_status |= USB_PORT_STAT_CONNECTION
                                        |(USB_PORT_STAT_C_CONNECTION << 16);
 
-               /* high vs full speed is just a guess until after reset */
-               testmode = musb_readb(mbase, MUSB_TESTMODE);
-               testmode &= ~(MUSB_TEST_FORCE_FS | MUSB_TEST_FORCE_HS);
                reg = musb_ulpi_readb(mbase, ISP1704_DEBUG);
-               switch (reg) {
-               case 1:         /* pullup indicates a full-speed device */
-                       testmode |= MUSB_TEST_FORCE_FS;
-                       break;
-               case 2:          /* low-speed device */
+               if (reg==1) {
+                       /* pullup indicates a full-speed device */
+                       musb_writeb(mbase, MUSB_TESTMODE, 0);
+                       reg = musb_readb(mbase, MUSB_DEVCTL)
+                                       | MUSB_DEVCTL_SESSION;
+                       musb_writeb(mbase, MUSB_DEVCTL, reg);
+                       musb_writeb(mbase, MUSB_TESTMODE,
+                                       MUSB_TEST_FORCE_FS
+                                       | MUSB_TEST_FORCE_HOST);
+               //      musb_ulpi_writeb(mbase, ISP1704_USB_INTFALL, 0x1f);
+               //      musb_ulpi_writeb(mbase, ISP1704_USB_INTRISE, 0x1f);
+               //      return count; /* FS device will generate an irq */
+               } else
                        musb->port1_status |= USB_PORT_STAT_LOW_SPEED;
-                       break;
-               default:
-                       DBG(1, "Error: no device attached during connect\n");
-               }
-               musb_writeb(mbase, MUSB_TESTMODE, testmode);
 
+               musb_ulpi_writeb(mbase, ISP1704_USB_INTFALL, 0x1f);
+               musb_ulpi_writeb(mbase, ISP1704_USB_INTRISE, 0x1f);
+               
                if (hcd->status_urb)
                        usb_hcd_poll_rh_status(hcd);
                else
index 709120a..547cea7 100644 (file)
@@ -211,7 +211,7 @@ static int omap_set_power(struct otg_transceiver *x, unsigned mA)
        return 0;
 }
 
-static int musb_platform_resume(struct musb *musb);
+int musb_platform_resume(struct musb *musb);
 
 int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
 {
@@ -233,6 +233,11 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
 
                        musb_platform_resume(musb);
 
+                       /* disable all irqs, will enable later on device connect */
+                       musb_ulpi_writeb(mbase, ISP1704_USB_INTFALL, 0);
+                       musb_ulpi_writeb(mbase, ISP1704_USB_INTRISE, 0);
+
+                       musb->xceiv->state = OTG_STATE_A_IDLE;
                        devctl |= MUSB_DEVCTL_SESSION;
                        musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 
@@ -252,6 +257,9 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
                        musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 
                        musb_writeb(musb->mregs, MUSB_TESTMODE, 0);
+                       /* reenable all irqs */
+                       musb_ulpi_writeb(musb->mregs, ISP1704_USB_INTFALL, 0x1f);
+                       musb_ulpi_writeb(musb->mregs, ISP1704_USB_INTRISE, 0x1f);
                }
 
                otg_set_peripheral(musb->xceiv, &musb->g);
@@ -346,7 +354,7 @@ int musb_platform_suspend(struct musb *musb)
        return 0;
 }
 
-static int musb_platform_resume(struct musb *musb)
+int musb_platform_resume(struct musb *musb)
 {
        u32 l;