usb: gadget: In OTG mode, power down the controller on probe
authorBenoit Goby <benoit@android.com>
Tue, 10 Aug 2010 03:49:09 +0000 (20:49 -0700)
committerColin Cross <ccross@android.com>
Wed, 6 Oct 2010 23:27:44 +0000 (16:27 -0700)
The OTG driver will power it up on ID pin detection. This avoids
race conditions when the device is powered on with the otg cable
attached.

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

index 7bbe2fb69d9d432144fc9fe0a6c803a44dd4d44c..00961da072facbd462d522a369bbc2cd372fd26c 100644 (file)
@@ -1951,14 +1951,14 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
                goto out;
        }
 
-       if (udc_controller->transceiver)
-               otg_set_peripheral(udc_controller->transceiver, &udc_controller->gadget);
-
        /* Enable DR IRQ reg and Set usbcmd reg  Run bit */
-       dr_controller_run(udc_controller);
-       udc_controller->usb_state = USB_STATE_ATTACHED;
-       udc_controller->ep0_state = WAIT_FOR_SETUP;
-       udc_controller->ep0_dir = 0;
+       if (!udc_controller->transceiver) {
+               dr_controller_run(udc_controller);
+               udc_controller->usb_state = USB_STATE_ATTACHED;
+               udc_controller->ep0_state = WAIT_FOR_SETUP;
+               udc_controller->ep0_dir = 0;
+       }
+
        printk(KERN_INFO "%s: bind to driver %s\n",
                        udc_controller->gadget.name, driver->driver.name);
 
@@ -1982,9 +1982,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
        if (!driver || driver != udc_controller->driver || !driver->unbind)
                return -EINVAL;
 
-       if (udc_controller->transceiver)
-               otg_set_peripheral(udc_controller->transceiver, NULL);
-
        /* stop DR, disable intr */
        dr_controller_stop(udc_controller);
 
@@ -2560,8 +2557,13 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 
 #ifdef CONFIG_USB_OTG_UTILS
        udc_controller->transceiver = otg_get_transceiver();
-       if (udc_controller->transceiver)
-               udc_controller->vbus_active = 1;
+       if (udc_controller->transceiver) {
+               dr_controller_stop(udc_controller);
+               fsl_udc_clk_suspend();
+               udc_controller->vbus_active = 0;
+               udc_controller->usb_state = USB_STATE_DEFAULT;
+               otg_set_peripheral(udc_controller->transceiver, &udc_controller->gadget);
+       }
 #else
 #ifdef CONFIG_ARCH_TEGRA
        /* Power down the phy if cable is not connected */
@@ -2601,6 +2603,9 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
                return -ENODEV;
        udc_controller->done = &done;
 
+       if (udc_controller->transceiver)
+               otg_set_peripheral(udc_controller->transceiver, NULL);
+
        fsl_udc_clk_release();
 
        /* DR has been stopped in usb_gadget_unregister_driver() */