forked from Minki/linux
Input: omap-keypad - fix idle configuration to not block SoC idle states
With PM enabled, I noticed that pressing a key on the droid4 keyboard will block deeper idle states for the SoC. Let's fix this by using IRQF_ONESHOT and stop constantly toggling the device OMAP4_KBD_IRQENABLE register as suggested by Dmitry Torokhov <dmitry.torokhov@gmail.com>. From the hardware point of view, looks like we need to manage the registers for OMAP4_KBD_IRQENABLE and OMAP4_KBD_WAKEUPENABLE together to avoid blocking deeper SoC idle states. And with toggling of OMAP4_KBD_IRQENABLE register now gone with IRQF_ONESHOT, also the SoC idle state problem is gone during runtime. We still also need to clear OMAP4_KBD_WAKEUPENABLE in omap4_keypad_close() though to pair it with omap4_keypad_open() to prevent blocking deeper SoC idle states after rmmod omap4-keypad. Reported-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
parent
6c3516fed7
commit
e2ca26ec4f
@ -126,12 +126,8 @@ static irqreturn_t omap4_keypad_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct omap4_keypad *keypad_data = dev_id;
|
||||
|
||||
if (kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)) {
|
||||
/* Disable interrupts */
|
||||
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
|
||||
OMAP4_VAL_IRQDISABLE);
|
||||
if (kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS))
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
return IRQ_NONE;
|
||||
}
|
||||
@ -173,11 +169,6 @@ static irqreturn_t omap4_keypad_irq_thread_fn(int irq, void *dev_id)
|
||||
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
|
||||
kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
|
||||
|
||||
/* enable interrupts */
|
||||
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
|
||||
OMAP4_DEF_IRQENABLE_EVENTEN |
|
||||
OMAP4_DEF_IRQENABLE_LONGKEY);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -214,9 +205,10 @@ static void omap4_keypad_close(struct input_dev *input)
|
||||
|
||||
disable_irq(keypad_data->irq);
|
||||
|
||||
/* Disable interrupts */
|
||||
/* Disable interrupts and wake-up events */
|
||||
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
|
||||
OMAP4_VAL_IRQDISABLE);
|
||||
kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE, 0);
|
||||
|
||||
/* clear pending interrupts */
|
||||
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
|
||||
@ -364,7 +356,7 @@ static int omap4_keypad_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
error = request_threaded_irq(keypad_data->irq, omap4_keypad_irq_handler,
|
||||
omap4_keypad_irq_thread_fn, 0,
|
||||
omap4_keypad_irq_thread_fn, IRQF_ONESHOT,
|
||||
"omap4-keypad", keypad_data);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to register interrupt\n");
|
||||
|
Loading…
Reference in New Issue
Block a user