summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin Xie <xxie@nvidia.com>2012-06-12 18:23:31 -0700
committerLokesh Pathak <lpathak@nvidia.com>2012-06-18 08:53:36 -0700
commite43dc6b9b19919885908c6f02b6cc5416da06456 (patch)
tree919f8a6f0183f785e6d821449bffa4aa61802a9d
parent97d9070b427f98596224fe876149027ed15e8eed (diff)
usb: tegra: otg: fix unbalanced suspend/resume
Becasue of a previous workaround, suspend/resume pair is implemented as suspend/complete pair in the driver's dev_pm_ops field. If any driver suspend routine (which is called before otg suspend) failed, then tegra_otg_resume() will be called even tegra_otg_suspend() is not called. This will cause disable the OTG clock, and OTG will not generate any more IRQ. Ideal fix would be use suspend/resume pair to implement the dev_pm_ops, but this might break previous workaround. This patch check suspend() routine is called or not in the resume routine; even we use suspend/ resume pair in the future, it will not cause bad behaviour. BUG 999759 Change-Id: I88f9c28bb76c5ff9e32917904017f291456cb933 Signed-off-by: Xin Xie <xxie@nvidia.com> Reviewed-on: http://git-master/r/108444 (cherry picked from commit c751aeea65f126d8e2df7f8a9ba02a631f958dc1) Reviewed-on: http://git-master/r/108945 Reviewed-by: Lokesh Pathak <lpathak@nvidia.com> Tested-by: Lokesh Pathak <lpathak@nvidia.com>
-rw-r--r--drivers/usb/otg/tegra-otg.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/usb/otg/tegra-otg.c b/drivers/usb/otg/tegra-otg.c
index 8442fcfc2796..081ad209e41c 100644
--- a/drivers/usb/otg/tegra-otg.c
+++ b/drivers/usb/otg/tegra-otg.c
@@ -67,6 +67,7 @@ struct tegra_otg_data {
void *charger_cb_data;
bool interrupt_mode;
bool builtin_host;
+ bool suspended
};
static struct tegra_otg_data *tegra_clone;
@@ -419,6 +420,7 @@ static int tegra_otg_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, tegra);
tegra_clone = tegra;
tegra->interrupt_mode = true;
+ tegra->suspended = false;
tegra->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(tegra->clk)) {
@@ -528,6 +530,8 @@ static int tegra_otg_suspend(struct device *dev)
if (otg->state == OTG_STATE_B_PERIPHERAL)
tegra_change_otg_state(tegra, OTG_STATE_A_SUSPEND);
+ tegra->suspended = true;
+
DBG("%s(%d) END\n", __func__, __LINE__);
return 0;
}
@@ -541,6 +545,9 @@ static void tegra_otg_resume(struct device *dev)
unsigned long flags;
DBG("%s(%d) BEGIN\n", __func__, __LINE__);
+ if (!tegra->suspended)
+ return;
+
/* Clear pending interrupts */
clk_enable(tegra->clk);
val = otg_readl(tegra, USB_PHY_WAKEUP);
@@ -564,6 +571,9 @@ static void tegra_otg_resume(struct device *dev)
irq_work(&tegra->work);
enable_interrupt(tegra, true);
+
+ tegra->suspended = false;
+
DBG("%s(%d) END\n", __func__, __LINE__);
}