diff options
author | Ray Poudrier <rapoudrier@nvidia.com> | 2011-08-31 19:03:10 -0700 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-09-26 19:14:06 -0700 |
commit | c23a24625f5720adb5ede209b60793b5790ead80 (patch) | |
tree | 701075bf8913fdf5b80b5d6d3c1ce9f996833a8c /drivers | |
parent | f08b8cedaf5786d904e74767cda8fb43f600610e (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>
Diffstat (limited to 'drivers')
-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); |