Skip to contentSkip to conversation

OMAP: GPIO: Avoid generating extra IRQs

PATCH In review [email protected] 2 participants 6 messages Jul 3, 2009 – Aug 10, 2009

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 OMAP: GPIO: Avoid generating extra IRQs

From: Eero Nurkkala <[email protected]>

It is possible for GPIO IRQ lines configured with falling edge triggering only to get IRQs at the rising edge upon the exit of offmode. And vice versa. Prevent such IRQs to arrive by generating the IRQ obeying the detection scheme.

---
 arch/arm/plat-omap/gpio.c |   27 +++++++++++++++++++++++----
 1 files changed, 23 insertions(+), 4 deletions(-)
arch/arm/plat-omap/gpio.c +23 -4
index 26b387c..7a270c0 100644
@@ -1804,7 +1804,7 @@ void omap2_gpio_resume_after_retention(void)
 		return;
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
-		u32 l;
+		u32 l, gen, gen0, gen1;
 
 		if (!(bank->enabled_non_wakeup_gpios))
 			continue;
@@ -1825,14 +1825,33 @@ void omap2_gpio_resume_after_retention(void)
 #endif
 		l ^= bank->saved_datain;
 		l &= bank->non_wakeup_gpios;
-		if (l) {
+
+		/*
+		 * No need to generate IRQs for the rising edge for gpio IRQs
+		 * configured with falling edge only; and vice versa.
+		 */
+		gen0 = l & bank->saved_fallingdetect;
+		gen0 &= bank->saved_datain;
+
+		gen1 = l & bank->saved_risingdetect;
+		gen1 &= ~(bank->saved_datain);
+
+		/* FIXME: Consider GPIO IRQs with level detections properly! */
+		gen = l & (~(bank->saved_fallingdetect) &
+				~(bank->saved_risingdetect));
+		/* Consider all GPIO IRQs needed to be updated */
+		gen |= gen0 | gen1;
+
+		if (gen) {
 			u32 old0, old1;
 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
 			defined(CONFIG_ARCH_OMAP4)
 			old0 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
 			old1 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
-			__raw_writel(old0 | l, bank->base + OMAP24XX_GPIO_LEVELDETECT0);
-			__raw_writel(old1 | l, bank->base + OMAP24XX_GPIO_LEVELDETECT1);
+			__raw_writel(old0 | gen, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT0);
+			__raw_writel(old1 | gen, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT1);
 			__raw_writel(old0, bank->base + OMAP24XX_GPIO_LEVELDETECT0);
 			__raw_writel(old1, bank->base + OMAP24XX_GPIO_LEVELDETECT1);
 #endif
Signature · 1 line
1.6.0.4
#1 lore raw

Hi,

Quoted 7 lines · * [email protected] <[email protected]> [090703 09:27]:

From: Eero Nurkkala <[email protected]>

It is possible for GPIO IRQ lines configured with
falling edge triggering only to get IRQs at the
rising edge upon the exit of offmode. And vice
versa. Prevent such IRQs to arrive by generating
the IRQ obeying the detection scheme.

Is the situation still the same if we temporarily change the level lines to edge for the duration of idle? This would allow waking up even if the line is level.

Also one question below.

Quoted 24 lines
---
 arch/arm/plat-omap/gpio.c |   27 +++++++++++++++++++++++----
 1 files changed, 23 insertions(+), 4 deletions(-)
arch/arm/plat-omap/gpio.c +2 -2
index 26b387c..7a270c0 100644
@@ -1804,7 +1804,7 @@ void omap2_gpio_resume_after_retention(void)
 		return;
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
-		u32 l;
+		u32 l, gen, gen0, gen1;
 
 		if (!(bank->enabled_non_wakeup_gpios))
 			continue;
@@ -1825,14 +1825,33 @@ void omap2_gpio_resume_after_retention(void)
 #endif
 		l ^= bank->saved_datain;
 		l &= bank->non_wakeup_gpios;
-		if (l) {
+

arch/arm/plat-omap/gpio.c void omap2_gpio_resume_after_retention(void) · line 1838

Quoted 10 lines
arch/arm/plat-omap/gpio.c +10 -0
+		/*
+		 * No need to generate IRQs for the rising edge for gpio IRQs
+		 * configured with falling edge only; and vice versa.
+		 */
+		gen0 = l & bank->saved_fallingdetect;
+		gen0 &= bank->saved_datain;
+
+		gen1 = l & bank->saved_risingdetect;
+		gen1 &= ~(bank->saved_datain);
+

Is the gen0 &= correct or should it also clear the bits?

Also, have you checked the code flow on omap1 when l, gen, gen0 & gen1 are not initialized? Just wondering ;)

Tony

Quoted 28 lines
arch/arm/plat-omap/gpio.c +11 -2
+		/* FIXME: Consider GPIO IRQs with level detections properly! */
+		gen = l & (~(bank->saved_fallingdetect) &
+				~(bank->saved_risingdetect));
+		/* Consider all GPIO IRQs needed to be updated */
+		gen |= gen0 | gen1;
+
+		if (gen) {
 			u32 old0, old1;
 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
 			defined(CONFIG_ARCH_OMAP4)
 			old0 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
 			old1 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
-			__raw_writel(old0 | l, bank->base + OMAP24XX_GPIO_LEVELDETECT0);
-			__raw_writel(old1 | l, bank->base + OMAP24XX_GPIO_LEVELDETECT1);
+			__raw_writel(old0 | gen, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT0);
+			__raw_writel(old1 | gen, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT1);
 			__raw_writel(old0, bank->base + OMAP24XX_GPIO_LEVELDETECT0);
 			__raw_writel(old1, bank->base + OMAP24XX_GPIO_LEVELDETECT1);
 #endif
Signature · 6 lines
1.6.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#2 lore raw
Quoted 17 lines
Quoted 5 lines
              l ^= bank->saved_datain;
              l &= bank->non_wakeup_gpios;
arch/arm/plat-omap/gpio.c +1 -1
-             if (l) {
+

arch/arm/plat-omap/gpio.c void omap2_gpio_resume_after_retention(void) · line 1838

Quoted 10 lines
arch/arm/plat-omap/gpio.c +10 -0
+             /*
+              * No need to generate IRQs for the rising edge for gpio IRQs
+              * configured with falling edge only; and vice versa.
+              */
+             gen0 = l & bank->saved_fallingdetect;
+             gen0 &= bank->saved_datain;
+
+             gen1 = l & bank->saved_risingdetect;
+             gen1 &= ~(bank->saved_datain);
+

Is the gen0 &= correct or should it also clear the bits?

What do you mean, eg, what bits should be cleared?

gen0 = (bit has changed) and is falling_edge
gen0 &= (the bit has changed) is falling edge and former state was "HIGH" (transition from HIGH to LOW has occurred)

for rising edge, needed is LOW to HIGH transition.

- Eero

#3 lore raw
Quoted 18 lines · * [email protected] <[email protected]> [090805 17:45]:
Quoted 17 lines
Quoted 5 lines
              l ^= bank->saved_datain;
              l &= bank->non_wakeup_gpios;
arch/arm/plat-omap/gpio.c +1 -1
-             if (l) {
+

arch/arm/plat-omap/gpio.c void omap2_gpio_resume_after_retention(void) · line 1838

Quoted 10 lines
arch/arm/plat-omap/gpio.c +10 -0
+             /*
+              * No need to generate IRQs for the rising edge for gpio IRQs
+              * configured with falling edge only; and vice versa.
+              */
+             gen0 = l & bank->saved_fallingdetect;
+             gen0 &= bank->saved_datain;
+
+             gen1 = l & bank->saved_risingdetect;
+             gen1 &= ~(bank->saved_datain);
+

Is the gen0 &= correct or should it also clear the bits?

Quoted 7 lines

What do you mean, eg, what bits should be cleared?

gen0 = (bit has changed) and is falling_edge
gen0 &= (the bit has changed) is falling edge and former state was "HIGH" (transition from HIGH to LOW has occurred)

for rising edge, needed is LOW to HIGH transition.

OK, my comment was just based on looking at the patch, sounds like you have verified that it's correct.

Tony

#4 lore raw
In reply to Tony Lindgren
Quoted 10 lines
Quoted 6 lines

It is possible for GPIO IRQ lines configured with falling edge triggering only to get IRQs at the rising edge upon the exit of offmode. And vice versa. Prevent such IRQs to arrive by generating the IRQ obeying the detection scheme.

Is the situation still the same if we temporarily change the level lines to edge for the duration of idle? This would allow waking up even if the line is level.

I admit that I haven't tested such a schenario. But I guess it's not different than what it used to be ... Is there a sample to try out?

However, if there's no edge detection (nor and or level detection) set at all, it will still generate soft IRQs, which possibly needs some rethinking (maybe WARN if no egde nor level detection on the GPIO IRQ). But it's been that way, so I figured no need to change that.

Quoted 4 lines

Also, have you checked the code flow on omap1 when l, gen, gen0 & gen1 are not initialized? Just wondering ;)

Tony

Right, possibly a compile warning.

- Eero

#5 lore raw

PATCH 1/1 OMAP: GPIO: Avoid generating extra IRQs

In reply to [email protected]

This patch has been applied to the linux-omap
by youw fwiendly patch wobot.

Branch in linux-omap: omap-upstream

Initial commit ID (Likely to change): ad23735d6744e7eeec4d2f012aa2ed2c1f8d64a9

PatchWorks
http://patchwork.kernel.org/patch/33855/

Git (Likely to change, and takes a while to get mirrored)
http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git;a=commit;h=ad23735d6744e7eeec4d2f012aa2ed2c1f8d64a9