diff options
author | Ray Poudrier <rapoudrier@nvidia.com> | 2011-08-31 19:03:10 -0700 |
---|---|---|
committer | Rohan Somvanshi <rsomvanshi@nvidia.com> | 2011-10-31 04:33:33 -0700 |
commit | 066682d454c2f00cefe9db60b6930106e3899a5d (patch) | |
tree | 1e34b60f8954667618b7dcc8f1336dd5067d598a | |
parent | 3e74aa621439db78500a8fb07d0fe4620ba3ad05 (diff) |
input: tegra-kbc: add is_open, don't suspend if no clock
Added is_open to know whether the clock has been disabled.
Occasionally _close is called before _suspend during LP0 cycles
resulting in a hang as the clock is disabled.
Bug 855753
Reviewed-on: http://git-master/r/50218
(cherry picked from commit c23a24625f5720adb5ede209b60793b5790ead80)
Change-Id: I7eec4b1352a7ea1180c14e4aa73e03fef12004ca
Reviewed-on: http://git-master/r/60842
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Tested-by: Laxman Dewangan <ldewangan@nvidia.com>
-rw-r--r-- | drivers/input/keyboard/tegra-kbc.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 469c53115af0..3bd1af17c424 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -61,6 +61,7 @@ struct tegra_kbc { struct work_struct key_repeat; struct workqueue_struct *kbc_work_queue; struct clk *clk; + int is_open; int row_seq[KBC_MAX_ROW]; int col_seq[KBC_MAX_COL]; int ncols; @@ -284,6 +285,7 @@ static void tegra_kbc_close(struct input_dev *dev) spin_unlock_irqrestore(&kbc->lock, flags); clk_disable(kbc->clk); + kbc->is_open = 0; } static void tegra_kbc_setup_wakekeys(struct tegra_kbc *kbc, bool filter) @@ -363,6 +365,7 @@ static int tegra_kbc_open(struct input_dev *dev) dev_dbg(kbc->dev, "KBC: tegra_kbc_open\n"); clk_enable(kbc->clk); + kbc->is_open = 1; /* Reset the KBC controller to clear all previous status.*/ tegra_periph_reset_assert(kbc->clk); @@ -519,6 +522,7 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, kbc); + kbc->is_open = 0; kbc->dev = &pdev->dev; kbc->idev->name = pdev->name; input_set_drvdata(kbc->idev, kbc); @@ -622,6 +626,7 @@ static int __devexit tegra_kbc_remove(struct platform_device *pdev) free_irq(kbc->irq, pdev); clk_disable(kbc->clk); + kbc->is_open = 0; clk_put(kbc->clk); input_unregister_device(kbc->idev); @@ -642,6 +647,9 @@ static int tegra_kbc_suspend(struct platform_device *pdev, pm_message_t state) int timeout = kbc->pdata->scan_timeout_cnt/32 + 200; unsigned long int_st; + if (!kbc->is_open) + return 0; + dev_dbg(&pdev->dev, "KBC: tegra_kbc_suspend\n"); if (device_may_wakeup(&pdev->dev) && (kbc->pdata->is_wake_on_any_key || kbc->pdata->wake_key_cnt)) { @@ -671,6 +679,9 @@ static int tegra_kbc_resume(struct platform_device *pdev) dev_dbg(&pdev->dev, "KBC: tegra_kbc_resume\n"); + if (!kbc->is_open) + return tegra_kbc_open(kbc->idev); + if (device_may_wakeup(&pdev->dev)) { disable_irq_wake(kbc->irq); tegra_kbc_setup_wakekeys(kbc, false); |