usb: gadget: Enable/disable the gadget device on vbus_session calls
authorBenoit Goby <benoit@android.com>
Wed, 1 Sep 2010 00:09:39 +0000 (17:09 -0700)
committerColin Cross <ccross@android.com>
Wed, 6 Oct 2010 23:28:23 +0000 (16:28 -0700)
If we use an OTG driver, the driver will detect VBUS changes and notify
the gadget driver through vbus_session. Enable/disable the gadget driver
in vbus session so that there is no need to check the OTG state on every
interrupt.

Change-Id: I617ad5742be2632b2257b71314db8f330be463d5
Signed-off-by: Benoit Goby <benoit@android.com>
drivers/usb/gadget/fsl_udc_core.c

index eb93c69951badfcad3975ebac241dfe2a3b6eb7c..0a51f643c1cb597015e13aec575fe6def3130b9e 100644 (file)
@@ -83,6 +83,7 @@ fsl_ep0_desc = {
 };
 
 static void fsl_ep_fifo_flush(struct usb_ep *_ep);
+static int reset_queues(struct fsl_udc *udc);
 
 #ifdef CONFIG_PPC32
 #define fsl_readl(addr)                in_le32(addr)
@@ -316,6 +317,8 @@ static void dr_controller_run(struct fsl_udc *udc)
                fsl_writel(temp, &usb_sys_regs->vbus_wakeup);
        }
 #endif
+       /* Clear stopped bit */
+       udc->stopped = 0;
 
        /* Enable DR irq reg */
        temp = USB_INTR_INT_EN | USB_INTR_ERR_INT_EN
@@ -324,9 +327,6 @@ static void dr_controller_run(struct fsl_udc *udc)
 
        fsl_writel(temp, &dr_regs->usbintr);
 
-       /* Clear stopped bit */
-       udc->stopped = 0;
-
        /* Set the controller as device mode */
        temp = fsl_readl(&dr_regs->usbmode);
        temp |= USB_MODE_CTRL_MODE_DEVICE;
@@ -1151,7 +1151,37 @@ static int fsl_vbus_session(struct usb_gadget *gadget, int is_active)
 
        udc = container_of(gadget, struct fsl_udc, gadget);
        spin_lock_irqsave(&udc->lock, flags);
+
        VDBG("VBUS %s", is_active ? "on" : "off");
+
+       if (udc->transceiver) {
+               if (udc->vbus_active && !is_active) {
+                       /* reset all internal Queues and inform client driver */
+                       reset_queues(udc);
+                       /* stop the controller and turn off the clocks */
+                       dr_controller_stop(udc);
+                       dr_controller_reset(udc);
+                       fsl_udc_clk_suspend();
+                       udc->vbus_active = 0;
+                       udc->usb_state = USB_STATE_DEFAULT;
+               } else if (!udc->vbus_active && is_active) {
+                       fsl_udc_clk_resume();
+                       /* setup the controller in the device mode */
+                       dr_controller_setup(udc);
+                       /* setup EP0 for setup packet */
+                       ep0_setup(udc);
+                       /* start the controller */
+                       dr_controller_run(udc);
+                       /* initialize the USB and EP states */
+                       udc->usb_state = USB_STATE_ATTACHED;
+                       udc->ep0_state = WAIT_FOR_SETUP;
+                       udc->ep0_dir = 0;
+                       udc->vbus_active = 1;
+               }
+               spin_unlock_irqrestore(&udc->lock, flags);
+               return 0;
+       }
+
        udc->vbus_active = (is_active != 0);
        if (can_pullup(udc))
                fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
@@ -1795,45 +1825,6 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
 
        spin_lock_irqsave(&udc->lock, flags);
 
-#ifdef CONFIG_ARCH_TEGRA
-       if (udc->transceiver) {
-               if (udc->transceiver->state == OTG_STATE_B_PERIPHERAL) {
-                       if (!udc->vbus_active) {
-                               /* set vbus active  and enable the usb clocks */
-                               udc->vbus_active = 1;
-                               fsl_udc_clk_resume();
-                               /* setup the controller in the device mode */
-                               dr_controller_setup(udc);
-                               /* setup EP0 for setup packet */
-                               ep0_setup(udc);
-                               /* start the controller */
-                               dr_controller_run(udc);
-                               /* initialize the USB and EP states */
-                               udc->usb_state = USB_STATE_ATTACHED;
-                               udc->ep0_state = WAIT_FOR_SETUP;
-                               udc->ep0_dir = 0;
-                       }
-               } else if (udc->transceiver->state == OTG_STATE_A_SUSPEND) {
-                       if (udc->vbus_active) {
-                               /* Reset all internal Queues and inform client driver */
-                               reset_queues(udc);
-                               /* stop the controller and turn off the clocks */
-                               dr_controller_stop(udc);
-                               dr_controller_reset(udc);
-                               fsl_udc_clk_suspend();
-                               udc->vbus_active = 0;
-                               udc->usb_state = USB_STATE_DEFAULT;
-                       } else {
-                               spin_unlock_irqrestore(&udc->lock, flags);
-                               return IRQ_NONE;
-                       }
-               } else {
-                       spin_unlock_irqrestore(&udc->lock, flags);
-                       return IRQ_NONE;
-               }
-       }
-#endif
-
        /* Disable ISR for OTG host mode */
        if (udc->stopped) {
                spin_unlock_irqrestore(&udc->lock, flags);
@@ -1846,33 +1837,6 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
 
        /* VDBG("irq_src [0x%8x]", irq_src); */
 
-#ifdef CONFIG_ARCH_TEGRA
-       if (!udc->transceiver) {
-               /* VBUS A session detection interrupts. When the interrupt is received,
-                * the mark the vbus active shadow.
-                */
-               temp = fsl_readl(&usb_sys_regs->vbus_wakeup);
-               if (temp & USB_SYS_VBUS_WAKEUP_INT_STATUS) {
-                       if (temp & USB_SYS_VBUS_STATUS) {
-                               udc->vbus_active = 1;
-                       } else {
-                               reset_queues(udc);
-                               udc->vbus_active = 0;
-                               udc->usb_state = USB_STATE_DEFAULT;
-                       }
-                       /* write back the register to clear the interrupt */
-                       fsl_writel(temp, &usb_sys_regs->vbus_wakeup);
-
-                       if (udc->vbus_active)
-                               fsl_udc_clk_resume();
-                       else
-                               fsl_udc_clk_suspend();
-
-                       status = IRQ_HANDLED;
-               }
-       }
-#endif
-
        /* Need to resume? */
        if (udc->usb_state == USB_STATE_SUSPENDED)
                if ((fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_SUSPEND) == 0)