[08/11] ARM: OMAP2/3: GPIO: do not attempt to wake-enable
diff mbox

Message ID 7B4574D56E4ADF438756313E9A172A87397A91F5@dlee01.ent.ti.com
State Superseded
Delegated to: Kevin Hilman
Headers show

Commit Message

Hunter, Jon May 18, 2009, 7:50 p.m. UTC
Hi Kevin,

> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  arch/arm/plat-omap/gpio.c |   14 ++++----------
>  1 files changed, 4 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
> index d3fa41e..210a1c0 100644
> --- a/arch/arm/plat-omap/gpio.c
> +++ b/arch/arm/plat-omap/gpio.c
> @@ -921,13 +921,10 @@ static int _set_gpio_wakeup(struct gpio_bank *bank,
> int gpio, int enable)
>  	case METHOD_MPUIO:
>  	case METHOD_GPIO_1610:
>  		spin_lock_irqsave(&bank->lock, flags);
> -		if (enable) {
> +		if (enable)
>  			bank->suspend_wakeup |= (1 << gpio);
> -			enable_irq_wake(bank->irq);
> -		} else {
> -			disable_irq_wake(bank->irq);
> +		else
>  			bank->suspend_wakeup &= ~(1 << gpio);
> -		}
>  		spin_unlock_irqrestore(&bank->lock, flags);
>  		return 0;
>  #endif
> @@ -940,13 +937,10 @@ static int _set_gpio_wakeup(struct gpio_bank *bank,
> int gpio, int enable)
>  			return -EINVAL;
>  		}
>  		spin_lock_irqsave(&bank->lock, flags);
> -		if (enable) {
> +		if (enable)
>  			bank->suspend_wakeup |= (1 << gpio);
> -			enable_irq_wake(bank->irq);
> -		} else {
> -			disable_irq_wake(bank->irq);
> +		else
>  			bank->suspend_wakeup &= ~(1 << gpio);
> -		}
>  		spin_unlock_irqrestore(&bank->lock, flags);
>  		return 0;
>  #endif


I have been looking into an issue that appears to be related to this. I have the following questions with regard to this patch. 

1). Although, I agree with the above change was there any reason why we did not add some code to set/clear the appropriate bit in the WKUENA register in this function? If this function is called via a call to set_irq_wake it will not modify the WKUENA register. Therefore, we were thinking of something along the lines of:



2). We have found that a call to request_irq results in a call to the function "set_24xx_gpio_triggering()" (for OMAP3430). In addition to configuring the triggering for a given GPIO, this function is also programming the WKUENA register. Hence, the wake-up enable is enabled for GPIO without calling set_irq_wake(). 

I am not sure if this is the intended behaviour or if drivers should explicitly be calling set_irq_wake to enable/disable the wake-up. 

The other problem with this is that once request_irq is called for a gpio, then even if we call disable_irq the wake-up event is not cleared. So this means that a gpio event will still wake-up the device without the gpio being enabled and because the gpio is disabled the event will never be cleared and hence will prevent retention. 

So should the wake-up event only be enabled/disabled by a call to set_irq_wake() or should we make sure that calling disable_irq in turn calls gpio_mask_irq and make sure this clears the wake-up event? 

Cheers
Jon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Kevin Hilman May 21, 2009, 3:53 p.m. UTC | #1
"Hunter, Jon" <jon-hunter@ti.com> writes:

> Hi Kevin,
>
>> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
>> Signed-off-by: Tony Lindgren <tony@atomide.com>
>> ---
>>  arch/arm/plat-omap/gpio.c |   14 ++++----------
>>  1 files changed, 4 insertions(+), 10 deletions(-)
>> 
>> diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
>> index d3fa41e..210a1c0 100644
>> --- a/arch/arm/plat-omap/gpio.c
>> +++ b/arch/arm/plat-omap/gpio.c
>> @@ -921,13 +921,10 @@ static int _set_gpio_wakeup(struct gpio_bank *bank,
>> int gpio, int enable)
>>  	case METHOD_MPUIO:
>>  	case METHOD_GPIO_1610:
>>  		spin_lock_irqsave(&bank->lock, flags);
>> -		if (enable) {
>> +		if (enable)
>>  			bank->suspend_wakeup |= (1 << gpio);
>> -			enable_irq_wake(bank->irq);
>> -		} else {
>> -			disable_irq_wake(bank->irq);
>> +		else
>>  			bank->suspend_wakeup &= ~(1 << gpio);
>> -		}
>>  		spin_unlock_irqrestore(&bank->lock, flags);
>>  		return 0;
>>  #endif
>> @@ -940,13 +937,10 @@ static int _set_gpio_wakeup(struct gpio_bank *bank,
>> int gpio, int enable)
>>  			return -EINVAL;
>>  		}
>>  		spin_lock_irqsave(&bank->lock, flags);
>> -		if (enable) {
>> +		if (enable)
>>  			bank->suspend_wakeup |= (1 << gpio);
>> -			enable_irq_wake(bank->irq);
>> -		} else {
>> -			disable_irq_wake(bank->irq);
>> +		else
>>  			bank->suspend_wakeup &= ~(1 << gpio);
>> -		}
>>  		spin_unlock_irqrestore(&bank->lock, flags);
>>  		return 0;
>>  #endif
>
>
> I have been looking into an issue that appears to be related to this. I have the following questions with regard to this patch. 
>
> 1). Although, I agree with the above change was there any reason why we did not add some code to set/clear the appropriate bit in the WKUENA register in this function? If this function is called via a call to set_irq_wake it will not modify the WKUENA register. Therefore, we were thinking of something along the lines of:
>
> diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
> index 17d7afe..895c548 100644
> --- a/arch/arm/plat-omap/gpio.c
> +++ b/arch/arm/plat-omap/gpio.c
> @@ -941,10 +941,13 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
>                         return -EINVAL;
>                 }
>                 spin_lock_irqsave(&bank->lock, flags);
> -               if (enable)
> +               if (enable) {
>                         bank->suspend_wakeup |= (1 << gpio);
> -               else
> +                       __raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_SETWKUENA);
> +               } else {
> +                       __raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_CLEARWKUENA);
>                         bank->suspend_wakeup &= ~(1 << gpio);
> +               }
>                 spin_unlock_irqrestore(&bank->lock, flags);
>                 return 0;
>  #endif

You're right, ti doesn't enable the wakeup here, but it does
eventually get enabled in the suspend hook.  See the handling of the
bank->suspend_wakeup mask in the suspend hook.

This brings up an interesting point though that GPIO IRQs that are
configured as wakeups will cannot bring the system out of idle, but
can only bring the system out of suspend.

>
> 2). We have found that a call to request_irq results in a call to the function "set_24xx_gpio_triggering()" (for OMAP3430). In addition to configuring the triggering for a given GPIO, this function is also programming the WKUENA register. Hence, the wake-up enable is enabled for GPIO without calling set_irq_wake(). 
>
> I am not sure if this is the intended behaviour or if drivers should explicitly be calling set_irq_wake to enable/disable the wake-up. 

If a driver calls request_irq with one of the IRQF_TRIGGER* flags
(other than _NONE, see <linux/interrupt.h>), then the triggering code
should be called as internally, request_irq handles this.

If no IRQF_TRIGGER* flag is handed to request_irq() and the triggering
is still being enbabled, this is a bug.

> The other problem with this is that once request_irq is called for a
> gpio, then even if we call disable_irq the wake-up event is not
> cleared. So this means that a gpio event will still wake-up the
> device without the gpio being enabled and because the gpio is
> disabled the event will never be cleared and hence will prevent
> retention.
>
> So should the wake-up event only be enabled/disabled by a call to
> set_irq_wake() or should we make sure that calling disable_irq in
> turn calls gpio_mask_irq and make sure this clears the wake-up
> event?

IMHO, it should only be enabled/disabled by a call to *_irq_wake(), or
a request_irq with (flags & IRQF_TRIGGER_MASK) != 0

Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch
diff mbox

diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 17d7afe..895c548 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -941,10 +941,13 @@  static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
                        return -EINVAL;
                }
                spin_lock_irqsave(&bank->lock, flags);
-               if (enable)
+               if (enable) {
                        bank->suspend_wakeup |= (1 << gpio);
-               else
+                       __raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_SETWKUENA);
+               } else {
+                       __raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_CLEARWKUENA);
                        bank->suspend_wakeup &= ~(1 << gpio);
+               }
                spin_unlock_irqrestore(&bank->lock, flags);
                return 0;
 #endif