Skip to content

Commit ce9a53e

Browse files
Anson-Huangdtor
authored andcommitted
Input: imx_keypad - make sure keyboard can always wake up system
There are several scenarios that keyboard can NOT wake up system from suspend, e.g., if a keyboard is depressed between system device suspend phase and device noirq suspend phase, the keyboard ISR will be called and both keyboard depress and release interrupts will be disabled, then keyboard will no longer be able to wake up system. Another scenario would be, if a keyboard is kept depressed, and then system goes into suspend, the expected behavior would be when keyboard is released, system will be waked up, but current implementation can NOT achieve that, because both depress and release interrupts are disabled in ISR, and the event check is still in progress. To fix these issues, need to make sure keyboard's depress or release interrupt is enabled after noirq device suspend phase, this patch moves the suspend/resume callback to noirq suspend/resume phase, and enable the corresponding interrupt according to current keyboard status. Signed-off-by: Anson Huang <[email protected]> Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent a876697 commit ce9a53e

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

drivers/input/keyboard/imx_keypad.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -526,11 +526,12 @@ static int imx_keypad_probe(struct platform_device *pdev)
526526
return 0;
527527
}
528528

529-
static int __maybe_unused imx_kbd_suspend(struct device *dev)
529+
static int __maybe_unused imx_kbd_noirq_suspend(struct device *dev)
530530
{
531531
struct platform_device *pdev = to_platform_device(dev);
532532
struct imx_keypad *kbd = platform_get_drvdata(pdev);
533533
struct input_dev *input_dev = kbd->input_dev;
534+
unsigned short reg_val = readw(kbd->mmio_base + KPSR);
534535

535536
/* imx kbd can wake up system even clock is disabled */
536537
mutex_lock(&input_dev->mutex);
@@ -540,13 +541,20 @@ static int __maybe_unused imx_kbd_suspend(struct device *dev)
540541

541542
mutex_unlock(&input_dev->mutex);
542543

543-
if (device_may_wakeup(&pdev->dev))
544+
if (device_may_wakeup(&pdev->dev)) {
545+
if (reg_val & KBD_STAT_KPKD)
546+
reg_val |= KBD_STAT_KRIE;
547+
if (reg_val & KBD_STAT_KPKR)
548+
reg_val |= KBD_STAT_KDIE;
549+
writew(reg_val, kbd->mmio_base + KPSR);
550+
544551
enable_irq_wake(kbd->irq);
552+
}
545553

546554
return 0;
547555
}
548556

549-
static int __maybe_unused imx_kbd_resume(struct device *dev)
557+
static int __maybe_unused imx_kbd_noirq_resume(struct device *dev)
550558
{
551559
struct platform_device *pdev = to_platform_device(dev);
552560
struct imx_keypad *kbd = platform_get_drvdata(pdev);
@@ -570,7 +578,9 @@ static int __maybe_unused imx_kbd_resume(struct device *dev)
570578
return ret;
571579
}
572580

573-
static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume);
581+
static const struct dev_pm_ops imx_kbd_pm_ops = {
582+
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_kbd_noirq_suspend, imx_kbd_noirq_resume)
583+
};
574584

575585
static struct platform_driver imx_keypad_driver = {
576586
.driver = {

0 commit comments

Comments
 (0)