summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2011-04-26 14:36:16 +0530
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:03:31 +0200
commit6fbbfcd700b57d212faf92fab1413a887da7aba7 (patch)
treede840259362db11ea1000e1c438671d1eac1bf86
parenta2db8d3ad080f5e8696c8510568546f5b412028f (diff)
db5500-keypad: handle suspend/resume
The onchip keyboard cannot wake up the system from sleep, so disable it in suspend and remove the device_init_wakeup call. Also introduce proper write allowed bit checks. ST-Ericsson Linux next: - ST-Ericsson ID: WP264487 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I01f065422ba86ef4990223682f351d49ec931434 Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/21575 Reviewed-by: Naveen Kumar GADDIPATI <naveen.gaddipati@stericsson.com> Reviewed-by: QATEST Reviewed-by: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
-rw-r--r--drivers/input/keyboard/db5500_keypad.c78
1 files changed, 56 insertions, 22 deletions
diff --git a/drivers/input/keyboard/db5500_keypad.c b/drivers/input/keyboard/db5500_keypad.c
index 398cf83a05f..8767b7f81ba 100644
--- a/drivers/input/keyboard/db5500_keypad.c
+++ b/drivers/input/keyboard/db5500_keypad.c
@@ -25,6 +25,7 @@
#define KEYPAD_NUM_ARRAY_REGS 5
#define KEYPAD_CTR_WRITE_IRQ_ENABLE (1 << 10)
+#define KEYPAD_CTR_WRITE_CONTROL (1 << 8)
#define KEYPAD_CTR_SCAN_ENABLE (1 << 7)
#define KEYPAD_ARRAY_CHANGEBIT (1 << 15)
@@ -160,12 +161,41 @@ again:
return IRQ_HANDLED;
}
-static int __devinit db5500_keypad_chip_init(struct db5500_keypad *keypad)
+static void db5500_keypad_writel(struct db5500_keypad *keypad, u32 val, u32 reg)
+{
+ int timeout = 4;
+ int allowedbit;
+
+ switch (reg) {
+ case KEYPAD_CTR:
+ allowedbit = KEYPAD_CTR_WRITE_CONTROL;
+ break;
+ case KEYPAD_INT_ENABLE:
+ allowedbit = KEYPAD_CTR_WRITE_IRQ_ENABLE;
+ break;
+ default:
+ BUG();
+ }
+
+ do {
+ u32 ctr = readl(keypad->base + KEYPAD_CTR);
+
+ if (ctr & allowedbit)
+ break;
+
+ udelay(50);
+ } while (--timeout);
+
+ /* Five 32k clk cycles (~150us) required, we waited 200us */
+ WARN_ON(!timeout);
+
+ writel(val, keypad->base + reg);
+}
+
+static int db5500_keypad_chip_init(struct db5500_keypad *keypad)
{
int debounce = keypad->board->debounce_ms;
int debounce_hits = 0;
- int timeout = 100;
- u32 val;
if (debounce < KEYPAD_DEBOUNCE_PERIOD_MIN)
debounce = KEYPAD_DEBOUNCE_PERIOD_MIN;
@@ -179,22 +209,27 @@ static int __devinit db5500_keypad_chip_init(struct db5500_keypad *keypad)
/* Convert the milliseconds to the bit mask */
debounce = DIV_ROUND_UP(debounce, KEYPAD_DEBOUNCE_PERIOD_MIN) - 1;
- writel(KEYPAD_CTR_SCAN_ENABLE
- | ((debounce_hits & 0x7) << 4)
- | debounce, keypad->base + KEYPAD_CTR);
-
- do {
- val = readl(keypad->base + KEYPAD_CTR);
- } while ((!(val & KEYPAD_CTR_WRITE_IRQ_ENABLE)) && --timeout);
+ clk_enable(keypad->clk);
- if (!timeout)
- return -EINVAL;
+ db5500_keypad_writel(keypad,
+ KEYPAD_CTR_SCAN_ENABLE
+ | ((debounce_hits & 0x7) << 4)
+ | debounce,
+ KEYPAD_CTR);
- writel(0x1, keypad->base + KEYPAD_INT_ENABLE);
+ db5500_keypad_writel(keypad, 0x1, KEYPAD_INT_ENABLE);
return 0;
}
+static void db5500_keypad_close(struct db5500_keypad *keypad)
+{
+ db5500_keypad_writel(keypad, 0, KEYPAD_CTR);
+ db5500_keypad_writel(keypad, 0, KEYPAD_INT_ENABLE);
+
+ clk_disable(keypad->clk);
+}
+
static int __devinit db5500_keypad_probe(struct platform_device *pdev)
{
const struct db5500_keypad_platform_data *plat;
@@ -292,9 +327,6 @@ static int __devinit db5500_keypad_probe(struct platform_device *pdev)
keypad->base = base;
keypad->clk = clk;
- /* allocations are sane, we begin HW initialization */
- clk_enable(keypad->clk);
-
ret = db5500_keypad_chip_init(keypad);
if (ret < 0) {
dev_err(&pdev->dev, "unable to init keypad hardware\n");
@@ -308,8 +340,6 @@ static int __devinit db5500_keypad_probe(struct platform_device *pdev)
goto out_unregisterinput;
}
- device_init_wakeup(&pdev->dev, true);
-
platform_set_drvdata(pdev, keypad);
return 0;
@@ -359,8 +389,10 @@ static int db5500_keypad_suspend(struct device *dev)
if (device_may_wakeup(dev))
enable_irq_wake(irq);
- else
- /* disable IRQ here */
+ else {
+ disable_irq(irq);
+ db5500_keypad_close(keypad);
+ }
return 0;
}
@@ -373,8 +405,10 @@ static int db5500_keypad_resume(struct device *dev)
if (device_may_wakeup(dev))
disable_irq_wake(irq);
- else
- /* enable IRQ here */
+ else {
+ db5500_keypad_chip_init(keypad);
+ enable_irq(irq);
+ }
return 0;
}