summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Poudrier <rapoudrier@nvidia.com>2011-08-31 19:03:10 -0700
committerVarun Colbert <vcolbert@nvidia.com>2011-09-26 19:14:06 -0700
commitc23a24625f5720adb5ede209b60793b5790ead80 (patch)
tree701075bf8913fdf5b80b5d6d3c1ce9f996833a8c
parentf08b8cedaf5786d904e74767cda8fb43f600610e (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 Change-Id: I0b2dd890d275d5e41c2f4ab2450207950469d479 Reviewed-on: http://git-master/r/50218 Reviewed-by: Raymond Poudrier <rapoudrier@nvidia.com> Tested-by: Raymond Poudrier <rapoudrier@nvidia.com> Reviewed-by: Alok Chauhan <alokc@nvidia.com> Reviewed-by: Scott Williams <scwilliams@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@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);