diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2010-07-02 20:26:20 +0530 |
---|---|---|
committer | Bharat Nihalani <bnihalani@nvidia.com> | 2010-07-05 04:30:03 -0700 |
commit | 3f82f1aaa86b5e216c365c89756bd2b72996ea09 (patch) | |
tree | bac84959c6b5f7ab33723598a0ca41ad12cf0cd2 | |
parent | 0b00a8a4f98e056012450d619db989527f5b4785 (diff) |
[arm/tegra] kbc: Configuring kbc controller for LP0.
KBC driver should set the DPD override register before entering in
to LP0. Also it should forcefully clear the interrupt status register
to clear any pending status.
Configuring the kbc rowmask register for allowing the key detection only
from wakeup enabled keysi before suspend.
Change-Id: I2b1b0e2cd7d0ffc10c2b2f6b2e88f79ab7fb687b
Reviewed-on: http://git-master/r/3495
Tested-by: Abhishek Aggarwal <aaggarwal@nvidia.com>
Reviewed-by: Narendra Damahe <ndamahe@nvidia.com>
Tested-by: Narendra Damahe <ndamahe@nvidia.com>
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
-rw-r--r-- | drivers/input/keyboard/tegra-kbc.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 1a91314319bd..b43f1cdda1d6 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -32,6 +32,8 @@ #include <linux/interrupt.h> #include <linux/clk.h> #include <mach/kbc.h> +#include <mach/pmc.h> +#include <mach/clk.h> #define KBC_CONTROL_0 0 #define KBC_INT_0 4 @@ -48,6 +50,8 @@ struct tegra_kbc { void __iomem *mmio; struct input_dev *idev; int irq; + unsigned int wake_enable_rows; + unsigned int wake_enable_cols; spinlock_t lock; unsigned int repoll_time; struct tegra_kbc_plat *pdata; @@ -77,6 +81,10 @@ static int tegra_kbc_suspend(struct platform_device *pdev, pm_message_t state) if (device_may_wakeup(&pdev->dev)) { tegra_kbc_setup_wakekeys(kbc, true); enable_irq_wake(kbc->irq); + tegra_configure_dpd_kbc(kbc->wake_enable_rows, kbc->wake_enable_cols); + /* Forcefully clear the interrupt status */ + writel(0x7, kbc->mmio + KBC_INT_0); + msleep(30); } else { tegra_kbc_close(kbc->idev); } @@ -91,6 +99,7 @@ static int tegra_kbc_resume(struct platform_device *pdev) if (device_may_wakeup(&pdev->dev)) { disable_irq_wake(kbc->irq); tegra_kbc_setup_wakekeys(kbc, false); + tegra_configure_dpd_kbc(0, 0); } else if (kbc->idev->users) return tegra_kbc_open(kbc->idev); @@ -258,6 +267,12 @@ static int tegra_kbc_open(struct input_dev *dev) clk_enable(kbc->clk); + /* Reset the KBC controller to clear all previous status.*/ + tegra_periph_reset_assert(kbc->clk); + udelay(100); + tegra_periph_reset_deassert(kbc->clk); + udelay(100); + tegra_kbc_config_pins(kbc); tegra_kbc_setup_wakekeys(kbc, false); @@ -430,6 +445,13 @@ static int __init tegra_kbc_probe(struct platform_device *pdev) cols[pdata->pin_cfg[i].num] = 1; } } + kbc->wake_enable_rows = 0; + kbc->wake_enable_cols = 0; + + for (i=0; i<pdata->wake_cnt; i++) { + kbc->wake_enable_rows |= (1 << kbc->pdata->wake_cfg[i].row); + kbc->wake_enable_cols |= (1 << kbc->pdata->wake_cfg[i].col); + } pdata->debounce_cnt = min_t(unsigned int, pdata->debounce_cnt, 0x3fful); kbc->repoll_time = 5 + (16+pdata->debounce_cnt)*nr + pdata->repeat_cnt; |