[PATCH] Input: omap-keypad: Fix idle configration to not block SoC idle states

From: Tony Lindgren
Date: Mon Dec 03 2018 - 17:12:39 EST


With PM enabled, I noticed that pressing a key on the droid4 keyboard will
block deeper idle states for the SoC. Looks like we can fix this by
managing the idle register to gether with the interrupt similar to what
we already do for the GPIO controller.

And there's no need to keep enabling and disabling interrupts and
wake-up events for normal use if we use IRQF_ONESHOT as suggested by
Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx> so let's do that too.

Cc: Axel Haslam <axelhaslam@xxxxxx>
Cc: Illia Smyrnov <illia.smyrnov@xxxxxx>
Cc: Marcel Partap <mpartap@xxxxxxx>
Cc: Merlijn Wajer <merlijn@xxxxxxxxxx>
Cc: Michael Scott <hashcode0f@xxxxxxxxx>
Cc: NeKit <nekit1000@xxxxxxxxx>
Cc: Pavel Machek <pavel@xxxxxx>
Cc: Sebastian Reichel <sre@xxxxxxxxxx>
Reported-by: Pavel Machek <pavel@xxxxxx>
Signed-off-by: Tony Lindgren <tony@xxxxxxxxxxx>
---
drivers/input/keyboard/omap4-keypad.c | 30 ++++++++++-----------------
1 file changed, 11 insertions(+), 19 deletions(-)

diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -53,11 +53,12 @@
/* OMAP4 bit definitions */
#define OMAP4_DEF_IRQENABLE_EVENTEN BIT(0)
#define OMAP4_DEF_IRQENABLE_LONGKEY BIT(1)
-#define OMAP4_DEF_WUP_EVENT_ENA BIT(0)
-#define OMAP4_DEF_WUP_LONG_KEY_ENA BIT(1)
#define OMAP4_DEF_CTRL_NOSOFTMODE BIT(1)
#define OMAP4_DEF_CTRL_PTV_SHIFT 2

+#define OMAP4_KBD_IRQ_MASK (OMAP4_DEF_IRQENABLE_LONGKEY | \
+ OMAP4_DEF_IRQENABLE_EVENTEN)
+
/* OMAP4 values */
#define OMAP4_VAL_IRQDISABLE 0x0

@@ -126,12 +127,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 +170,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;
}

@@ -197,11 +189,10 @@ static int omap4_keypad_open(struct input_dev *input)
/* clear pending interrupts */
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
- kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
- OMAP4_DEF_IRQENABLE_EVENTEN |
- OMAP4_DEF_IRQENABLE_LONGKEY);
- kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
- OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
+
+ /* enable interrupts and wake-up events */
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, OMAP4_KBD_IRQ_MASK);
+ kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE, OMAP4_KBD_IRQ_MASK);

enable_irq(keypad_data->irq);

@@ -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,
@@ -365,7 +357,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");
--
2.19.2