diff options
author | Rabin Vincent <rabin.vincent@stericsson.com> | 2011-04-26 14:36:16 +0530 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-05-22 11:03:31 +0200 |
commit | 6fbbfcd700b57d212faf92fab1413a887da7aba7 (patch) | |
tree | de840259362db11ea1000e1c438671d1eac1bf86 /drivers/input/keyboard | |
parent | a2db8d3ad080f5e8696c8510568546f5b412028f (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>
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r-- | drivers/input/keyboard/db5500_keypad.c | 78 |
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; } |