phy: rockchip-inno-usb2: delay suspending phy if plug out device
authorWilliam Wu <william.wu@rock-chips.com>
Thu, 20 Jul 2017 07:02:02 +0000 (15:02 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Fri, 21 Jul 2017 03:16:24 +0000 (11:16 +0800)
The otg_sm_work will suspend the usb2 phy immediately
if it detects disconnection from host. However, the usb2
controller(e.g. DWC2) may need to reinit registers and
reset usb core after usb disconnect, and it needs to
keep the usb2 phy stay in power on state to get utmi clk
for these usb controller operation. We don't have a good
synchronization mechanism to operate usb2 phy between
usb2 phy driver and usb2 controller driver, so we delay
4s to suspend phy if detect otg device disconnect from
host, this can make sure that usb2 controller completes
reinitialization before suspend usb2 phy.

Change-Id: I79288b8c7b141bb16e6d96d80cfee75f7558d2c0
Signed-off-by: William Wu <william.wu@rock-chips.com>
drivers/phy/phy-rockchip-inno-usb2.c

index 1fbcc518004703216192a28d63283b73ef597c0d..fbcf8f3b2081ec2e269107aaa71784cb311439cf 100644 (file)
@@ -886,19 +886,17 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
                } else {
                        rphy->chg_state = USB_CHG_STATE_UNDEFINED;
                        rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
+                       mutex_unlock(&rport->mutex);
+                       rockchip_usb2phy_power_off(rport->phy);
+                       mutex_lock(&rport->mutex);
                }
                break;
        case OTG_STATE_B_PERIPHERAL:
                if (!rport->vbus_attached) {
                        dev_dbg(&rport->phy->dev, "usb disconnect\n");
-                       rphy->chg_state = USB_CHG_STATE_UNDEFINED;
-                       rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
                        rport->state = OTG_STATE_B_IDLE;
                        rport->perip_connected = false;
-                       delay = 0;
-                       mutex_unlock(&rport->mutex);
-                       rockchip_usb2phy_power_off(rport->phy);
-                       mutex_lock(&rport->mutex);
+                       delay = OTG_SCHEDULE_DELAY * 2;
                        wake_unlock(&rport->wakelock);
                }
                sch_work = true;
@@ -1246,6 +1244,7 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
 
        mutex_unlock(&rport->mutex);
 
+       cancel_delayed_work_sync(&rport->otg_sm_work);
        rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
 
        return IRQ_HANDLED;
@@ -1324,6 +1323,7 @@ static int rockchip_otg_event(struct notifier_block *nb,
        struct rockchip_usb2phy_port *rport =
                container_of(nb, struct rockchip_usb2phy_port, event_nb);
 
+       cancel_delayed_work_sync(&rport->otg_sm_work);
        schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY);
 
        return NOTIFY_DONE;