gpio: msm: do not re-enable the interrupt and clear the status
If a gpio interrupt is already enabled, do not re-enable it again and do not
clear the interrupt status.
Before this patch: if an edge interrupt is marked as wakeup, the gpio sys
suspend will enable it. On resume, the gpio sys resume would clear the
intr_status of the wakeup irq. Thus, if this particular wakeup irq triggered
and woke us up, we would lose its intr_status before calling the gpio summary
handler. Now, when the summary handler is finally called, the irq handler for
the wakeup interrupt is never called.
With this change: we are *not* re-enabling the gpio-irq again to make sure that
when the irq framework unmasks all irqs on resume, it does not clear the
intr_status.
Change-Id: Ia5a9c6b00173a56b1abbdd4d4821becb7311d7f6
Signed-off-by: Rohit Vaswani <rvaswani@codeaurora.org>
Signed-off-by: Ajay Dudani <adudani@codeaurora.org>
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/drivers/gpio/gpio-msm-common.c b/drivers/gpio/gpio-msm-common.c
index 46f6460..800c376 100644
--- a/drivers/gpio/gpio-msm-common.c
+++ b/drivers/gpio/gpio-msm-common.c
@@ -300,9 +300,11 @@
spin_lock_irqsave(&tlmm_lock, irq_flags);
__set_bit(gpio, msm_gpio.enabled_irqs);
- __msm_gpio_set_intr_status(gpio);
- __msm_gpio_set_intr_cfg_enable(gpio, 1);
- mb();
+ if (!__msm_gpio_get_intr_cfg_enable(gpio)) {
+ __msm_gpio_set_intr_status(gpio);
+ __msm_gpio_set_intr_cfg_enable(gpio, 1);
+ mb();
+ }
spin_unlock_irqrestore(&tlmm_lock, irq_flags);
if (msm_gpio_irq_extn.irq_mask)
diff --git a/drivers/gpio/gpio-msm-common.h b/drivers/gpio/gpio-msm-common.h
index c9ea3da..b1590ef 100644
--- a/drivers/gpio/gpio-msm-common.h
+++ b/drivers/gpio/gpio-msm-common.h
@@ -21,6 +21,7 @@
unsigned __msm_gpio_get_intr_status(unsigned gpio);
void __msm_gpio_set_intr_status(unsigned gpio);
unsigned __msm_gpio_get_intr_config(unsigned gpio);
+unsigned __msm_gpio_get_intr_cfg_enable(unsigned gpio);
void __msm_gpio_set_intr_cfg_enable(unsigned gpio, unsigned val);
void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type);
void __gpio_tlmm_config(unsigned config);
diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
index 943a4a2..592391e 100644
--- a/drivers/gpio/gpio-msm-v2.c
+++ b/drivers/gpio/gpio-msm-v2.c
@@ -155,6 +155,11 @@
}
}
+unsigned __msm_gpio_get_intr_cfg_enable(unsigned gpio)
+{
+ return __msm_gpio_get_intr_config(gpio) & INTR_ENABLE;
+}
+
void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type)
{
unsigned cfg;
diff --git a/drivers/gpio/gpio-msm-v3.c b/drivers/gpio/gpio-msm-v3.c
index 26716a0..1da276f 100644
--- a/drivers/gpio/gpio-msm-v3.c
+++ b/drivers/gpio/gpio-msm-v3.c
@@ -163,6 +163,11 @@
__raw_writel(cfg, GPIO_INTR_CFG(gpio));
}
+unsigned __msm_gpio_get_intr_cfg_enable(unsigned gpio)
+{
+ return __msm_gpio_get_intr_config(gpio) & INTR_ENABLE;
+}
+
void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type)
{
unsigned cfg;