diff mbox

gpio/omap: fix off-mode bug: clear debounce clock enable mask on disable

Message ID 1351015771-6308-1-git-send-email-khilman@deeprootsystems.com (mailing list archive)
State New, archived
Headers show

Commit Message

Kevin Hilman Oct. 23, 2012, 6:09 p.m. UTC
From: Kevin Hilman <khilman@ti.com>

When debounce clocks are disabled, ensure that the banks
dbck_enable_mask is cleared also.  Otherwise, context restore on
subsequent off-mode transition will restore previous value from the
shadow copies (bank->context.debounce*) leading to mismatch state
between driver state and hardware state.

This was discovered when board code was doing

  gpio_request_one()
  gpio_set_debounce()
  gpio_free()

which was leaving the GPIO debounce settings in a confused state.
Then, enabling off mode causing bogus state to be restored, leaving
GPIO debounce enabled which then prevented the CORE powerdomain from
transitioning.

Reported-by: Paul Walmsley <paul@pwsan.com>
Cc: Igor Grinberg <grinberg@compulab.co.il>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
Applies on v3.7-rc2, targetted for v3.7.

 drivers/gpio/gpio-omap.c | 1 +
 1 file changed, 1 insertion(+)

Comments

Santosh Shilimkar Oct. 24, 2012, 7:33 a.m. UTC | #1
On Tuesday 23 October 2012 11:39 PM, Kevin Hilman wrote:
> From: Kevin Hilman <khilman@ti.com>
>
> When debounce clocks are disabled, ensure that the banks
> dbck_enable_mask is cleared also.  Otherwise, context restore on
> subsequent off-mode transition will restore previous value from the
> shadow copies (bank->context.debounce*) leading to mismatch state
> between driver state and hardware state.
>
> This was discovered when board code was doing
>
>    gpio_request_one()
>    gpio_set_debounce()
>    gpio_free()
>
> which was leaving the GPIO debounce settings in a confused state.
> Then, enabling off mode causing bogus state to be restored, leaving
> GPIO debounce enabled which then prevented the CORE powerdomain from
> transitioning.
>
> Reported-by: Paul Walmsley <paul@pwsan.com>
> Cc: Igor Grinberg <grinberg@compulab.co.il>
> Signed-off-by: Kevin Hilman <khilman@ti.com>
> ---
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Linus Walleij Oct. 24, 2012, 8:16 a.m. UTC | #2
On Tue, Oct 23, 2012 at 8:09 PM, Kevin Hilman
<khilman@deeprootsystems.com> wrote:

> From: Kevin Hilman <khilman@ti.com>
>
> When debounce clocks are disabled, ensure that the banks
> dbck_enable_mask is cleared also.  Otherwise, context restore on
> subsequent off-mode transition will restore previous value from the
> shadow copies (bank->context.debounce*) leading to mismatch state
> between driver state and hardware state.
>
> This was discovered when board code was doing
>
>   gpio_request_one()
>   gpio_set_debounce()
>   gpio_free()
>
> which was leaving the GPIO debounce settings in a confused state.
> Then, enabling off mode causing bogus state to be restored, leaving
> GPIO debounce enabled which then prevented the CORE powerdomain from
> transitioning.
>
> Reported-by: Paul Walmsley <paul@pwsan.com>
> Cc: Igor Grinberg <grinberg@compulab.co.il>
> Signed-off-by: Kevin Hilman <khilman@ti.com>

Thanks! Applied with Felipe's and Santosh's ACKs.

Yours,
Linus Walleij
Igor Grinberg Oct. 24, 2012, 8:56 a.m. UTC | #3
On 10/24/12 10:16, Linus Walleij wrote:
> On Tue, Oct 23, 2012 at 8:09 PM, Kevin Hilman
> <khilman@deeprootsystems.com> wrote:
> 
>> From: Kevin Hilman <khilman@ti.com>
>>
>> When debounce clocks are disabled, ensure that the banks
>> dbck_enable_mask is cleared also.  Otherwise, context restore on
>> subsequent off-mode transition will restore previous value from the
>> shadow copies (bank->context.debounce*) leading to mismatch state
>> between driver state and hardware state.
>>
>> This was discovered when board code was doing
>>
>>   gpio_request_one()
>>   gpio_set_debounce()
>>   gpio_free()
>>
>> which was leaving the GPIO debounce settings in a confused state.
>> Then, enabling off mode causing bogus state to be restored, leaving
>> GPIO debounce enabled which then prevented the CORE powerdomain from
>> transitioning.
>>
>> Reported-by: Paul Walmsley <paul@pwsan.com>
>> Cc: Igor Grinberg <grinberg@compulab.co.il>
>> Signed-off-by: Kevin Hilman <khilman@ti.com>
> 
> Thanks! Applied with Felipe's and Santosh's ACKs.

If not too late:
Acked-by: Igor Grinberg <grinberg@compulab.co.il>

Kevin, thanks for the patch and sorry I could not respond on time.
Grazvydas Ignotas Oct. 24, 2012, 12:02 p.m. UTC | #4
On Tue, Oct 23, 2012 at 9:09 PM, Kevin Hilman
<khilman@deeprootsystems.com> wrote:
> From: Kevin Hilman <khilman@ti.com>
>
> When debounce clocks are disabled, ensure that the banks
> dbck_enable_mask is cleared also.  Otherwise, context restore on
> subsequent off-mode transition will restore previous value from the
> shadow copies (bank->context.debounce*) leading to mismatch state
> between driver state and hardware state.

This doesn't look right to me, aren't you effectively disabling
debounce forever here? _gpio_dbck_disable is called from
omap_gpio_runtime_suspend() and nothing will ever restore
dbck_enable_mask back to what it was set by _set_gpio_debounce and
debounce functionality is lost.

>
> This was discovered when board code was doing
>
>   gpio_request_one()
>   gpio_set_debounce()
>   gpio_free()
>
> which was leaving the GPIO debounce settings in a confused state.
> Then, enabling off mode causing bogus state to be restored, leaving
> GPIO debounce enabled which then prevented the CORE powerdomain from
> transitioning.
>
> Reported-by: Paul Walmsley <paul@pwsan.com>
> Cc: Igor Grinberg <grinberg@compulab.co.il>
> Signed-off-by: Kevin Hilman <khilman@ti.com>
> ---
> Applies on v3.7-rc2, targetted for v3.7.
>
>  drivers/gpio/gpio-omap.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
> index 94cbc84..dee2856 100644
> --- a/drivers/gpio/gpio-omap.c
> +++ b/drivers/gpio/gpio-omap.c
> @@ -187,6 +187,7 @@ static inline void _gpio_dbck_disable(struct gpio_bank *bank)
>                  * to detect events and generate interrupts at least on OMAP3.
>                  */
>                 __raw_writel(0, bank->base + bank->regs->debounce_en);
> +               bank->dbck_enable_mask = 0;
>
>                 clk_disable(bank->dbck);
>                 bank->dbck_enabled = false;
> --
> 1.8.0
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Santosh Shilimkar Oct. 24, 2012, 12:49 p.m. UTC | #5
On Wednesday 24 October 2012 05:32 PM, Grazvydas Ignotas wrote:
> On Tue, Oct 23, 2012 at 9:09 PM, Kevin Hilman
> <khilman@deeprootsystems.com> wrote:
>> From: Kevin Hilman <khilman@ti.com>
>>
>> When debounce clocks are disabled, ensure that the banks
>> dbck_enable_mask is cleared also.  Otherwise, context restore on
>> subsequent off-mode transition will restore previous value from the
>> shadow copies (bank->context.debounce*) leading to mismatch state
>> between driver state and hardware state.
>
> This doesn't look right to me, aren't you effectively disabling
> debounce forever here? _gpio_dbck_disable is called from
> omap_gpio_runtime_suspend() and nothing will ever restore
> dbck_enable_mask back to what it was set by _set_gpio_debounce and
> debounce functionality is lost.
>
As per commit log, the issue seen with request->debounce->free()
sequence and hence on free, debounce state needs to be cleared.
Next gpio_set_debounce() should set the debounce mask right so
the patch seems to be right.

>>
>> This was discovered when board code was doing
>>
>>    gpio_request_one()
>>    gpio_set_debounce()
>>    gpio_free()
>>
>> which was leaving the GPIO debounce settings in a confused state.
>> Then, enabling off mode causing bogus state to be restored, leaving
>> GPIO debounce enabled which then prevented the CORE powerdomain from
>> transitioning.
>>

But there is one more case which might break because of this patch.
As part of idle, we might end up with below without gpio_free()
omap2_gpio_prepare_for_idle()
  ->pm_runtime_put_sync_suspend()
   -> omap_gpio_runtime_suspend()
    ->_gpio_dbck_disable()

And last call will clear the debounce mask state which will lost and
hence the debounce clock won't be enabled on resume.

I let Kevin comment whether this is the valid case or not.

Regards
Santosh
Grazvydas Ignotas Oct. 24, 2012, 1:40 p.m. UTC | #6
On Wed, Oct 24, 2012 at 3:49 PM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> On Wednesday 24 October 2012 05:32 PM, Grazvydas Ignotas wrote:
>>
>> On Tue, Oct 23, 2012 at 9:09 PM, Kevin Hilman
>> <khilman@deeprootsystems.com> wrote:
>>>
>>> From: Kevin Hilman <khilman@ti.com>
>>>
>>> When debounce clocks are disabled, ensure that the banks
>>> dbck_enable_mask is cleared also.  Otherwise, context restore on
>>> subsequent off-mode transition will restore previous value from the
>>> shadow copies (bank->context.debounce*) leading to mismatch state
>>> between driver state and hardware state.
>>
>>
>> This doesn't look right to me, aren't you effectively disabling
>> debounce forever here? _gpio_dbck_disable is called from
>> omap_gpio_runtime_suspend() and nothing will ever restore
>> dbck_enable_mask back to what it was set by _set_gpio_debounce and
>> debounce functionality is lost.
>>
> As per commit log, the issue seen with request->debounce->free()
> sequence and hence on free, debounce state needs to be cleared.
> Next gpio_set_debounce() should set the debounce mask right so
> the patch seems to be right.
>
>
>>>
>>> This was discovered when board code was doing
>>>
>>>    gpio_request_one()
>>>    gpio_set_debounce()
>>>    gpio_free()
>>>
>>> which was leaving the GPIO debounce settings in a confused state.
>>> Then, enabling off mode causing bogus state to be restored, leaving
>>> GPIO debounce enabled which then prevented the CORE powerdomain from
>>> transitioning.
>>>
>
> But there is one more case which might break because of this patch.
> As part of idle, we might end up with below without gpio_free()
> omap2_gpio_prepare_for_idle()
>  ->pm_runtime_put_sync_suspend()
>   -> omap_gpio_runtime_suspend()
>    ->_gpio_dbck_disable()
>
> And last call will clear the debounce mask state which will lost and
> hence the debounce clock won't be enabled on resume.
>
> I let Kevin comment whether this is the valid case or not.

That's exactly what I had in mind - we lose debounce functionality on
first runtime suspend.
Kevin Hilman Oct. 24, 2012, 2:19 p.m. UTC | #7
Grazvydas Ignotas <notasas@gmail.com> writes:

> On Tue, Oct 23, 2012 at 9:09 PM, Kevin Hilman
> <khilman@deeprootsystems.com> wrote:
>> From: Kevin Hilman <khilman@ti.com>
>>
>> When debounce clocks are disabled, ensure that the banks
>> dbck_enable_mask is cleared also.  Otherwise, context restore on
>> subsequent off-mode transition will restore previous value from the
>> shadow copies (bank->context.debounce*) leading to mismatch state
>> between driver state and hardware state.
>
> This doesn't look right to me, aren't you effectively disabling
> debounce forever here? _gpio_dbck_disable is called from
> omap_gpio_runtime_suspend() and nothing will ever restore
> dbck_enable_mask back to what it was set by _set_gpio_debounce and
> debounce functionality is lost.

Yes, you're right.   Good catch.

I need a fix that's more targetted to the free/reset path.

Linus, please revert if it's not too late, and I'll come up with a more
targetted fix.

Kevin
Santosh Shilimkar Oct. 24, 2012, 2:38 p.m. UTC | #8
On Wednesday 24 October 2012 07:49 PM, Kevin Hilman wrote:
> Grazvydas Ignotas <notasas@gmail.com> writes:
>
>> On Tue, Oct 23, 2012 at 9:09 PM, Kevin Hilman
>> <khilman@deeprootsystems.com> wrote:
>>> From: Kevin Hilman <khilman@ti.com>
>>>
>>> When debounce clocks are disabled, ensure that the banks
>>> dbck_enable_mask is cleared also.  Otherwise, context restore on
>>> subsequent off-mode transition will restore previous value from the
>>> shadow copies (bank->context.debounce*) leading to mismatch state
>>> between driver state and hardware state.
>>
>> This doesn't look right to me, aren't you effectively disabling
>> debounce forever here? _gpio_dbck_disable is called from
>> omap_gpio_runtime_suspend() and nothing will ever restore
>> dbck_enable_mask back to what it was set by _set_gpio_debounce and
>> debounce functionality is lost.
>
> Yes, you're right.   Good catch.
>
> I need a fix that's more targetted to the free/reset path.
>
Right. Just clearing the debounce mask in omap_gpio_free()
should do the trick.

Regards
Santosh
Linus Walleij Oct. 26, 2012, 7:21 a.m. UTC | #9
On Wed, Oct 24, 2012 at 4:19 PM, Kevin Hilman
<khilman@deeprootsystems.com> wrote:

> Linus, please revert if it's not too late, and I'll come up with a more
> targetted fix.

OK I ditched it, no big deal.

Yours,
Linus Walleij
diff mbox

Patch

diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 94cbc84..dee2856 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -187,6 +187,7 @@  static inline void _gpio_dbck_disable(struct gpio_bank *bank)
 		 * to detect events and generate interrupts at least on OMAP3.
 		 */
 		__raw_writel(0, bank->base + bank->regs->debounce_en);
+		bank->dbck_enable_mask = 0;
 
 		clk_disable(bank->dbck);
 		bank->dbck_enabled = false;