diff options
author | Ray Poudrier <rapoudrier@nvidia.com> | 2011-11-14 16:26:27 -0800 |
---|---|---|
committer | Varun Wadekar <vwadekar@nvidia.com> | 2011-12-21 15:31:17 +0530 |
commit | 964834f1203e375c13be8d3fb58b3fada083c579 (patch) | |
tree | 264984266456ec0ec7b5db47030c1c71fd6d5b85 /drivers/input/keyboard | |
parent | 7bf8839d96911891af925b031bb54f80fcdba1f0 (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: Ida938ada7d14085e11096b25cf41431fc2d46215
Reviewed-on: http://git-master/r/50218
Reviewed-on: http://git-master/r/64257
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>
Diffstat (limited to 'drivers/input/keyboard')
-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 134960a219ea..152cbf2af5f5 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -83,6 +83,7 @@ struct tegra_kbc { unsigned int num_pressed_keys; struct timer_list timer; struct clk *clk; + int is_open; unsigned long scan_timeout_count; unsigned long one_scan_time; }; @@ -480,6 +481,7 @@ static int tegra_kbc_start(struct tegra_kbc *kbc) u32 val = 0; clk_enable(kbc->clk); + kbc->is_open = 1; /* Reset the KBC controller to clear all previous status.*/ tegra_periph_reset_assert(kbc->clk); @@ -549,6 +551,7 @@ static void tegra_kbc_stop(struct tegra_kbc *kbc) del_timer_sync(&kbc->timer); clk_disable(kbc->clk); + kbc->is_open = 0; } static int tegra_kbc_open(struct input_dev *dev) @@ -666,6 +669,7 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) goto err_iounmap; } + kbc->is_open = 0; kbc->wake_enable_rows = 0; kbc->wake_enable_cols = 0; for (i = 0; i < pdata->wake_cnt; i++) { @@ -782,6 +786,10 @@ static int tegra_kbc_suspend(struct device *dev) unsigned long int_st; dev_dbg(&pdev->dev, "KBC: tegra_kbc_suspend\n"); + + if (!kbc->is_open) + return 0; + if (device_may_wakeup(&pdev->dev)) { timeout = DIV_ROUND_UP((kbc->scan_timeout_count + kbc->one_scan_time), 32); @@ -820,6 +828,9 @@ static int tegra_kbc_resume(struct device *dev) struct tegra_kbc *kbc = platform_get_drvdata(pdev); int err = 0; + if (!kbc->is_open) + return tegra_kbc_start(kbc); + if (device_may_wakeup(&pdev->dev)) { disable_irq_wake(kbc->irq); tegra_kbc_setup_wakekeys(kbc, false); |