usb: dwc_otg_310: pcd: hold wake lock until phy suspended and clk disabled

When begin connecting to PC in device mode, the driver will hold a
wake lock to prevent system from entering deep sleep. If it fails
to connect to PC or doesn't detect the vbus, the driver will suspend
usb phy and disable usb clk, and release the wake lock.

If unlock the wake lock first, system may enter deep sleep before
suspend usb phy and disable usb clk. Then wake up system by pull
out the usb cable, it may cause usb interrupt abnormal.

TEST=rk3126c connect the usb charger into the charging interface,
after the system entered deep sleep, pull out the usb cable with
the following log:

irq 42: nobody cared (try booting with the "irqpoll" option)
CPU: 0 PID: 146 Comm: charger Not tainted 3.10.104 #133
[<c0014088>] unwind_backtrace+0x0/0xe0
[<c00118cc>] show_stack+0x10/0x14
[<c00b0be0>] __report_bad_irq+0x28/0xb8
[<c00b0e68>] note_interrupt+0x138/0x1cc
[<c00aef88>] handle_irq_event_percpu+0x2c0/0x2f4
[<c00aeff8>] handle_irq_event+0x3c/0x5c
[<c00b1a20>] handle_fasteoi_irq+0xbc/0x124
[<c00ae764>] generic_handle_irq+0x20/0x30
[<c000e4cc>] handle_IRQ+0x64/0x8c
[<c000853c>] gic_handle_irq+0x38/0x5c
handlers:
[<c042b3ec>] dwc_otg_common_irq
[<c0438704>] dwc_otg_pcd_irq
[<c03fab48>] usb_hcd_irq
Disabling IRQ #42

Change-Id: Id36717ae68e02226255c1207aeded0bd6fb356cd
Signed-off-by: Feng Mingli <fml@rock-chips.com>
Signed-off-by: William Wu <william.wu@rock-chips.com>
This commit is contained in:
Feng Mingli
2017-08-09 20:34:17 +08:00
committed by William Wu
parent 5f173fa7d8
commit f4adf1bc37

View File

@@ -1664,11 +1664,6 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work)
printk("**************soft reconnect**************\n");
goto connect;
} else if (_pcd->conn_status == 2) {
/*
* Release pcd->wake_lock if fail to connect,
* and allow system to enter deep sleep.
*/
dwc_otg_msc_unlock(_pcd);
_pcd->conn_status++;
if (pldata->bc_detect_cb && iddig) {
@@ -1684,6 +1679,12 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work)
udelay(3);
pldata->clock_enable(pldata, 0);
}
/*
* Release pcd->wake_lock if fail to connect,
* and allow system to enter deep sleep.
*/
dwc_otg_msc_unlock(_pcd);
}
} else {
if (pldata->bc_detect_cb && iddig)
@@ -1697,15 +1698,15 @@ 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);
if (iddig || (usb_mode == USB_MODE_FORCE_DEVICE)) {
/* No vbus detect here , suspend usb phy */
pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
udelay(3);
pldata->clock_enable(pldata, 0);
}
/* Release wake lock */
dwc_otg_msc_unlock(_pcd);
}
/* Bypass usb phy to uart mode */