summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@freescale.com>2012-02-22 11:14:01 +0800
committerPeter Chen <peter.chen@freescale.com>2012-03-07 15:01:35 +0800
commit7f40896b71be935f53bf703c686c619062799c6f (patch)
tree5702647582e8a4ca03a7098968b91dc92d9139b5 /drivers
parent158ce9aa6bda83e44f2a608cb160040662710f62 (diff)
ENGR00176147-1: usb: fix some wakeup problems
- Do not call hcd core adjust wakeup flag code. It may change wakeup flag, and cause port change detect(PCD) enable setting change. - For ID wakeup, it should not call host's fsl_usb_recover_hcd at ID interrupt. The coming ID switch event will resume host. - Do not need enable wakeup interrupt for host at platform driver resume routine, it may introduce unnessary wakeup interrupt during bus resume. The wakeup will be enabled again when usb host goes to controller again due to autosuspend. - When there is no gadget enabled, the otg port is still at host mode with interrupt enabled, so when male Micro-B to female A-type cable with usb device plugs in, there will be PCD interrupt before hcd core leaves suspend mode. Signed-off-by: Peter Chen <peter.chen@freescale.com>
Diffstat (limited to 'drivers')
-rwxr-xr-xdrivers/usb/host/ehci-arc.c30
-rwxr-xr-xdrivers/usb/otg/fsl_otg.c10
2 files changed, 15 insertions, 25 deletions
diff --git a/drivers/usb/host/ehci-arc.c b/drivers/usb/host/ehci-arc.c
index 99ba497f5f5a..93ef469c39fb 100755
--- a/drivers/usb/host/ehci-arc.c
+++ b/drivers/usb/host/ehci-arc.c
@@ -28,7 +28,6 @@
#include "../core/usb.h"
#include "ehci-fsl.h"
#include <mach/fsl_usb.h>
-
extern void usb_host_set_wakeup(struct device *wkup_dev, bool para);
static void fsl_usb_lowpower_mode(struct fsl_usb2_platform_data *pdata, bool enable)
{
@@ -148,11 +147,11 @@ static irqreturn_t ehci_fsl_pre_irq(int irq, void *dev)
pdata = hcd->self.controller->platform_data;
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- if (pdata->irq_delay || !pdata->wakeup_event)
+ if (pdata->irq_delay || pdata->wakeup_event != WAKEUP_EVENT_DPDM)
return IRQ_NONE;
pr_debug("%s\n", __func__);
- pdata->wakeup_event = 0;
+ pdata->wakeup_event = WAKEUP_EVENT_INVALID;
fsl_usb_recover_hcd(pdev);
return IRQ_HANDLED;
} else {
@@ -674,17 +673,9 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev,
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
fsl_usb_clk_gate(hcd->self.controller->platform_data, true);
- ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd),
- device_may_wakeup(&(pdev->dev)));
- if (!host_can_wakeup_system(pdev)) {
- int mask;
-
- mask = ehci_readl(ehci, &ehci->regs->intr_enable);
- mask &= ~STS_PCD;
- ehci_writel(ehci, mask, &ehci->regs->intr_enable);
-
+ if (!host_can_wakeup_system(pdev))
usb_host_set_wakeup(hcd->self.controller, false);
- }
+
fsl_usb_clk_gate(hcd->self.controller->platform_data, false);
printk(KERN_DEBUG "host suspend ends\n");
return 0;
@@ -772,17 +763,6 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev)
if (pdata->pmflags == 0) {
printk(KERN_DEBUG "%s,pm event, wait for wakeup irq if needed\n", __func__);
wait_event_interruptible(wake_up_pdata->wq, !wake_up_pdata->usb_wakeup_is_pending);
- if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- fsl_usb_clk_gate(hcd->self.controller->platform_data, true);
- }
- if (!host_can_wakeup_system(pdev)) {
- usb_host_set_wakeup(hcd->self.controller, true);
-
- }
- ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
- if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- fsl_usb_clk_gate(hcd->self.controller->platform_data, false);
- }
return 0;
}
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
@@ -794,6 +774,7 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev)
spin_unlock_irqrestore(&ehci->lock, flags);
}
+ spin_lock_irqsave(&ehci->lock, flags);
/* set host mode */
fsl_platform_set_host_mode(hcd);
@@ -812,6 +793,7 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev)
tmp = ehci_readl(ehci, &ehci->regs->command);
tmp |= CMD_RUN;
ehci_writel(ehci, tmp, &ehci->regs->command);
+ spin_unlock_irqrestore(&ehci->lock, flags);
if ((hcd->state & HC_STATE_SUSPENDED)) {
printk(KERN_DEBUG "will resume roothub and its children\n");
diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c
index aa42f6b25f11..79b7e7bf2c25 100755
--- a/drivers/usb/otg/fsl_otg.c
+++ b/drivers/usb/otg/fsl_otg.c
@@ -729,6 +729,7 @@ static void fsl_otg_event(struct work_struct *work)
struct otg_fsm *fsm = &og->fsm;
struct otg_transceiver *otg = &og->otg;
struct fsl_usb2_platform_data *pdata;
+ int ret;
pdata = og->otg.dev->platform_data;
BUG_ON(!pdata);
@@ -758,7 +759,14 @@ static void fsl_otg_event(struct work_struct *work)
pdata->wake_up_enable(pdata, true);
fsl_otg_start_gadget(fsm, 1);
} else { /* switch to host */
- fsl_otg_start_gadget(fsm, 0);
+ ret = fsl_otg_start_gadget(fsm, 0);
+ if (ret == -ENODEV) {
+ /* Still at host mode, when vbus on, there will
+ * have PCD interrupt, but host core still at
+ * suspend.
+ */
+ writel(0x0, &usb_dr_regs->usbintr);
+ }
if (pdata->wake_up_enable)
pdata->wake_up_enable(pdata, false);
otg_drv_vbus(fsm, 1);