summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Poudrier <rapoudrier@nvidia.com>2011-08-31 19:03:10 -0700
committerRohan Somvanshi <rsomvanshi@nvidia.com>2011-10-31 04:33:33 -0700
commit066682d454c2f00cefe9db60b6930106e3899a5d (patch)
tree1e34b60f8954667618b7dcc8f1336dd5067d598a
parent3e74aa621439db78500a8fb07d0fe4620ba3ad05 (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.c11
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);