From 246d53d1570c4b2cf2e85783cdf14e23b0a293db Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 26 Apr 2011 14:36:16 +0530 Subject: 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 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/21575 Reviewed-by: Naveen Kumar GADDIPATI Reviewed-by: QATEST Reviewed-by: Srinidhi KASAGAR --- drivers/input/keyboard/db5500_keypad.c | 78 ++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 22 deletions(-) (limited to 'drivers/input') 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; } -- cgit v1.2.3