diff options
author | Peter Chen <peter.chen@freescale.com> | 2014-03-31 13:54:46 +0800 |
---|---|---|
committer | Peter Chen <peter.chen@freescale.com> | 2014-04-01 09:34:37 +0800 |
commit | 8062f7e4af338f1520a6cd13133ff01fffd82a46 (patch) | |
tree | 68dda447f8788914eb73d37d9d6f5f73a7b2a347 /drivers | |
parent | 24c1d64737577fba4b4cc8d83170c9dfd6fd6dec (diff) |
ENGR00303543 usb: ehci-arc: do noop during resume if it is not in host mode
We find a bug that the usb will produce endless interrupt during the
resume after below steps:
- nothing connected at usb otg port, but enable usb gadget driver
- system enters suspend
- plug in usb cable
- system leaves suspend
The reasons of endless interrupt is: the host controller resume routine
leaves the phy low power mode, but device controller resume routine has
still not been called, so the software considers it is still at low power
mode. After this time, the vbus change interrupt comes, the wakeup routine
considers it is an wakeup interrupt, but in fact it is not. So, the endless
interrupt occurs.
The solution of this problem is do noop during host controller resume
routine if current usb mode is not host mode, and the device controller
reusme routine will handle it.
Signed-off-by: Peter Chen <peter.chen@freescale.com>
Diffstat (limited to 'drivers')
-rwxr-xr-x | drivers/usb/host/ehci-arc.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/usb/host/ehci-arc.c b/drivers/usb/host/ehci-arc.c index dde47dd76e5f..5e5d4e011d73 100755 --- a/drivers/usb/host/ehci-arc.c +++ b/drivers/usb/host/ehci-arc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 MontaVista Software - * Copyright (C) 2013 Freescale Semiconductor, Inc. + * Copyright (C) 2013-2014 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -802,6 +802,18 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev) if (!host_can_wakeup_system(pdev)) { /* Need open clock for register access */ fsl_usb_clk_gate(hcd->self.controller->platform_data, true); + u32 __iomem *reg_ptr; + + reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE); + tmp = ehci_readl(ehci, reg_ptr); + + /* quit, if not in host mode */ + if ((tmp & USBMODE_CM_HC) != USBMODE_CM_HC) { + usb_host_set_wakeup(hcd->self.controller, true); + fsl_usb_clk_gate(hcd->self.controller->platform_data, false); + enable_irq(hcd->irq); + return 0; + } fsl_usb_lowpower_mode(pdata, false); tmp = ehci_readl(ehci, &ehci->regs->port_status[0]); |