phy: rockchip-inno-usb2: delay suspending phy if plug out device

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>
This commit is contained in:
William Wu
2017-07-20 15:02:02 +08:00
committed by Huang, Tao
parent 0d01d2234a
commit 4f519feed0

View 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;