summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2010-07-02 20:26:20 +0530
committerBharat Nihalani <bnihalani@nvidia.com>2010-07-05 04:30:03 -0700
commit3f82f1aaa86b5e216c365c89756bd2b72996ea09 (patch)
treebac84959c6b5f7ab33723598a0ca41ad12cf0cd2
parent0b00a8a4f98e056012450d619db989527f5b4785 (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.c22
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;