diff mbox series

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

Message ID 20181203012933.6647-2-tony@atomide.com (mailing list archive)
State New, archived
Headers show
Series [1/2] Input: omap-keypad: Fix keyboard debounce configuration | expand

Commit Message

Tony Lindgren Dec. 3, 2018, 1:29 a.m. UTC
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.

Note that we now must also disable OMAP4_DEF_IRQENABLE_LONGKEY as it
should not be used together with debounce according to the TRM.

Cc: Axel Haslam <axelhaslam@ti.com>
Cc: Illia Smyrnov <illia.smyrnov@ti.com>
Cc: Marcel Partap <mpartap@gmx.net>
Cc: Merlijn Wajer <merlijn@wizzup.org>
Cc: Michael Scott <hashcode0f@gmail.com>
Cc: NeKit <nekit1000@gmail.com>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: Sebastian Reichel <sre@kernel.org>
Reported-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/input/keyboard/omap4-keypad.c | 28 ++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

Comments

Dmitry Torokhov Dec. 3, 2018, 7:23 p.m. UTC | #1
On Sun, Dec 02, 2018 at 05:29:33PM -0800, Tony Lindgren wrote:
> 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.
> 
> Note that we now must also disable OMAP4_DEF_IRQENABLE_LONGKEY as it
> should not be used together with debounce according to the TRM.
> 
> Cc: Axel Haslam <axelhaslam@ti.com>
> Cc: Illia Smyrnov <illia.smyrnov@ti.com>
> Cc: Marcel Partap <mpartap@gmx.net>
> Cc: Merlijn Wajer <merlijn@wizzup.org>
> Cc: Michael Scott <hashcode0f@gmail.com>
> Cc: NeKit <nekit1000@gmail.com>
> Cc: Pavel Machek <pavel@ucw.cz>
> Cc: Sebastian Reichel <sre@kernel.org>
> Reported-by: Pavel Machek <pavel@ucw.cz>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  drivers/input/keyboard/omap4-keypad.c | 28 ++++++++++++++-------------
>  1 file changed, 15 insertions(+), 13 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
>  
> @@ -127,9 +128,11 @@ 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 */
> +		/* Disable interrupts and wake-up events */
>  		kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>  				 OMAP4_VAL_IRQDISABLE);

I wonder, do we need to turn off interrupts at keyboard controller
level, or we should simply use IRQF_ONESHOT?

> +		kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE, 0);

So we are saying that disabling wakeup for the time between hard
interrupt firing, and when interrupt thread runs, makes much difference?
It is surprising to me... How long does it take to schedule interrupt
thread?

Thanks.
Tony Lindgren Dec. 3, 2018, 11:12 p.m. UTC | #2
Hi,

* Dmitry Torokhov <dmitry.torokhov@gmail.com> [181203 19:24]:
> On Sun, Dec 02, 2018 at 05:29:33PM -0800, Tony Lindgren wrote:
...
> > Note that we now must also disable OMAP4_DEF_IRQENABLE_LONGKEY as it
> > should not be used together with debounce according to the TRM.

The above statement is no longer true, it's left over from an
earlier version of this fix, so will drop it.

> > --- a/drivers/input/keyboard/omap4-keypad.c
> > +++ b/drivers/input/keyboard/omap4-keypad.c
> > @@ -127,9 +128,11 @@ 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 */
> > +		/* Disable interrupts and wake-up events */
> >  		kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> >  				 OMAP4_VAL_IRQDISABLE);
> 
> I wonder, do we need to turn off interrupts at keyboard controller
> level, or we should simply use IRQF_ONESHOT?

Oh that's a good idea and seems to work nicely :)

> > +		kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE, 0);
> 
> So we are saying that disabling wakeup for the time between hard
> interrupt firing, and when interrupt thread runs, makes much difference?
> It is surprising to me... How long does it take to schedule interrupt
> thread?

Nope, you're right. Updated patch below.

Regards,

Tony

8< --------------------
From tony Mon Sep 17 00:00:00 2001
From: Tony Lindgren <tony@atomide.com>
Date: Mon, 3 Dec 2018 14:12:39 -0800
Subject: [PATCH] Input: omap-keypad: Fix idle configration 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. 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@gmail.com> so let's do that too.

Cc: Axel Haslam <axelhaslam@ti.com>
Cc: Illia Smyrnov <illia.smyrnov@ti.com>
Cc: Marcel Partap <mpartap@gmx.net>
Cc: Merlijn Wajer <merlijn@wizzup.org>
Cc: Michael Scott <hashcode0f@gmail.com>
Cc: NeKit <nekit1000@gmail.com>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: Sebastian Reichel <sre@kernel.org>
Reported-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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");
Dmitry Torokhov Dec. 4, 2018, 4 a.m. UTC | #3
Hi Tony,

On Mon, Dec 03, 2018 at 03:12:51PM -0800, Tony Lindgren wrote:
> 
> 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.

Can you show me where exactly we are doing this? I can't seem to find
the matching code.

Thanks!

> 
> 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@gmail.com> so let's do that too.
> 
> Cc: Axel Haslam <axelhaslam@ti.com>
> Cc: Illia Smyrnov <illia.smyrnov@ti.com>
> Cc: Marcel Partap <mpartap@gmx.net>
> Cc: Merlijn Wajer <merlijn@wizzup.org>
> Cc: Michael Scott <hashcode0f@gmail.com>
> Cc: NeKit <nekit1000@gmail.com>
> Cc: Pavel Machek <pavel@ucw.cz>
> Cc: Sebastian Reichel <sre@kernel.org>
> Reported-by: Pavel Machek <pavel@ucw.cz>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  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
Tony Lindgren Dec. 4, 2018, 7:09 p.m. UTC | #4
Hi,

* Dmitry Torokhov <dmitry.torokhov@gmail.com> [181204 04:00]:
> Hi Tony,
> 
> On Mon, Dec 03, 2018 at 03:12:51PM -0800, Tony Lindgren wrote:
> > 
> > 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.
> 
> Can you show me where exactly we are doing this? I can't seem to find
> the matching code.

With your change it now becomes the fix, and we're just missing the
clearing of the OMAP4_KBD_WAKEUPENABLE register in omap4_keypad_close.

Does the following minimal version with updated comments make
more sense now?

Regards,

Tony

8< --------------
From tony Mon Sep 17 00:00:00 2001
From: Tony Lindgren <tony@atomide.com>
Date: Tue, 4 Dec 2018 11:07:56 -0800
Subject: [PATCH] Input: omap-keypad: Fix idle configration 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.

Cc: Axel Haslam <axelhaslam@ti.com>
Cc: Illia Smyrnov <illia.smyrnov@ti.com>
Cc: Marcel Partap <mpartap@gmx.net>
Cc: Merlijn Wajer <merlijn@wizzup.org>
Cc: Michael Scott <hashcode0f@gmail.com>
Cc: NeKit <nekit1000@gmail.com>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: Sebastian Reichel <sre@kernel.org>
Reported-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/input/keyboard/omap4-keypad.c | 16 ++++------------
 1 file changed, 4 insertions(+), 12 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
@@ -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,
@@ -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");
Dmitry Torokhov Dec. 4, 2018, 7:15 p.m. UTC | #5
On December 4, 2018 11:09:32 AM PST, Tony Lindgren <tony@atomide.com> wrote:
>Hi,
>
>* Dmitry Torokhov <dmitry.torokhov@gmail.com> [181204 04:00]:
>> Hi Tony,
>> 
>> On Mon, Dec 03, 2018 at 03:12:51PM -0800, Tony Lindgren wrote:
>> > 
>> > 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.
>> 
>> Can you show me where exactly we are doing this? I can't seem to find
>> the matching code.
>
>With your change it now becomes the fix, and we're just missing the
>clearing of the OMAP4_KBD_WAKEUPENABLE register in omap4_keypad_close.
>
>Does the following minimal version with updated comments make
>more sense now?

Awesome, thank you Tony.

>
>Regards,
>
>Tony
>
>8< --------------
>From tony Mon Sep 17 00:00:00 2001
>From: Tony Lindgren <tony@atomide.com>
>Date: Tue, 4 Dec 2018 11:07:56 -0800
>Subject: [PATCH] Input: omap-keypad: Fix idle configration 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.
>
>Cc: Axel Haslam <axelhaslam@ti.com>
>Cc: Illia Smyrnov <illia.smyrnov@ti.com>
>Cc: Marcel Partap <mpartap@gmx.net>
>Cc: Merlijn Wajer <merlijn@wizzup.org>
>Cc: Michael Scott <hashcode0f@gmail.com>
>Cc: NeKit <nekit1000@gmail.com>
>Cc: Pavel Machek <pavel@ucw.cz>
>Cc: Sebastian Reichel <sre@kernel.org>
>Reported-by: Pavel Machek <pavel@ucw.cz>
>Signed-off-by: Tony Lindgren <tony@atomide.com>
>---
> drivers/input/keyboard/omap4-keypad.c | 16 ++++------------
> 1 file changed, 4 insertions(+), 12 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
>@@ -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,
>@@ -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");
diff mbox series

Patch

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
 
@@ -127,9 +128,11 @@  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 */
+		/* 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);
+
 		return IRQ_WAKE_THREAD;
 	}
 
@@ -173,10 +176,9 @@  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);
+	/* 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);
 
 	return IRQ_HANDLED;
 }
@@ -197,11 +199,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 +215,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,