USB: dwc_otg_310: modify usb mode change detect bug
authorFeng Mingli <fml@rock-chips.com>
Mon, 17 Aug 2015 01:24:49 +0000 (09:24 +0800)
committerlyz <lyz@rock-chips.com>
Tue, 18 Aug 2015 13:03:56 +0000 (21:03 +0800)
When dwc controller change mode form device to host, may check_vbus_work is running
on other cpu, but we don't have a good synchronization id_status_change and
check_vbus_work, as a result, phy and clk may in incorrect state. So modify it.

Signed-off-by: Feng Mingli <fml@rock-chips.com>
Signed-off-by: lyz <lyz@rock-chips.com>
Conflicts:
drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c

drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c

index e5f1c6d201d48a2f1680be3fc85d71eaed2bb126..e67384d733051ceb56d956311e2974bedfae87c7 100755 (executable)
@@ -1561,7 +1561,7 @@ static void id_status_change(dwc_otg_core_if_t *p, bool current_id)
                core_if->op_state = A_HOST;
                dwc_otg_set_force_mode(core_if, USB_MODE_FORCE_HOST);
 
-               cancel_delayed_work(&pcd->check_vbus_work);
+               cancel_delayed_work_sync(&pcd->check_vbus_work);
 
                /*
                 * Initialize the Core for Host mode.
@@ -1590,11 +1590,8 @@ static void check_id(struct work_struct *work)
                        pldata->phy_suspend(pldata, USB_PHY_ENABLED);
                }
 
-               if (!id) { /* Force Host */
-                       id_status_change(otg_dev->core_if, id);
-               } else { /* Force Device */
-                       id_status_change(otg_dev->core_if, id);
-               }
+               /* Force Device or Host by id */
+               id_status_change(otg_dev->core_if, id);
        }
        last_id = id;
        schedule_delayed_work(&_pcd->check_id_work, (HZ));
@@ -1662,10 +1659,12 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work)
                if (pldata->phy_status == USB_PHY_ENABLED) {
                        /* release wake lock */
                        dwc_otg_msc_unlock(_pcd);
-                       /* no vbus detect here , close usb phy  */
-                       pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
-                       udelay(3);
-                       pldata->clock_enable(pldata, 0);
+                       if (pldata->get_status(USB_STATUS_ID)) {
+                               /* no vbus detect here , close usb phy  */
+                               pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
+                               udelay(3);
+                               pldata->clock_enable(pldata, 0);
+                       }
                }
 
                /* usb phy bypass to uart mode  */
@@ -1673,7 +1672,8 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work)
                        pldata->dwc_otg_uart_mode(pldata, PHY_UART_MODE);
        }
 
-       schedule_delayed_work(&_pcd->check_vbus_work, HZ);
+       if (pldata->get_status(USB_STATUS_ID))
+               schedule_delayed_work(&_pcd->check_vbus_work, HZ);
        return;
 
 connect: