aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArve Hjønnevåg <arve@android.com>2011-12-13 22:22:00 -0800
committerArve Hjønnevåg <arve@android.com>2011-12-14 17:58:53 -0800
commit5a44bf340a2f8967a30da5035dfee9ae452a585a (patch)
treeee49d914c45e7379ee4e5422bf5d6bdedb489ee3
parentaa7b27cb96dbadf29308f87d5e189e46d5ca39ce (diff)
downloadkernel_samsung_espresso10-5a44bf340a2f8967a30da5035dfee9ae452a585a.tar.gz
kernel_samsung_espresso10-5a44bf340a2f8967a30da5035dfee9ae452a585a.tar.bz2
kernel_samsung_espresso10-5a44bf340a2f8967a30da5035dfee9ae452a585a.zip
ARM: omap4: gpio: Use pad wakeupevent to detect pulses for edge triggered gpios
When the gpio controller is off we use the pad wakeup to wake up. The current code only detects edges if the state of the gpio when we wake up is different from the state we read before we turned the gpio controller off. This will miss short pulses. We now use the pad wakeupevent status to try to detect these pulses. If the interrupt is configured for dual edge triggering this will generate an interrupt for any pulse detected. If the interrupt is configured for single edge detect we only generate an interrupt if the old state matches the starting state for the enabled edge detect. This will still miss a pulse when the interrupt is configured for only the second edge in that pulse. We may also falsely generate an interrupt if an edge of the wrong polarity occured before reading the initial state (since the pad wakeup is enabled before then). Change-Id: Id9a68cd97b0281a7debb2f37d845979894b63bcc Signed-off-by: Arve Hjønnevåg <arve@android.com>
-rw-r--r--arch/arm/mach-omap2/mux.c10
-rw-r--r--arch/arm/mach-omap2/mux.h5
-rw-r--r--drivers/gpio/gpio-omap.c7
3 files changed, 22 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index a2ed524713e..c7d0b21c7f5 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -968,6 +968,16 @@ void omap_mux_set_gpio(u16 val, int gpio)
pr_err("%s: Could not set gpio%i\n", __func__, gpio);
}
+bool omap_mux_get_wakeupevent(struct omap_mux *m)
+{
+ u16 val;
+ if (IS_ERR_OR_NULL(m) || !cpu_is_omap44xx())
+ return false;
+
+ val = omap_mux_read(m->partition, m->reg_offset);
+ return val & OMAP_WAKEUP_EVENT;
+}
+
/* Has no locking, don't use on a pad that is remuxed (by hwmod or otherwise) */
bool omap_mux_get_wakeupenable(struct omap_mux *m)
{
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index 87bf022aa41..e631b5e82b9 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -286,6 +286,11 @@ int omap_mux_clear_wakeupenable(struct omap_mux *m);
*/
bool omap_mux_get_wakeupenable(struct omap_mux *m);
+/** omap_mux_get_wakeupevent() - get the wakeupevent bit from a mux struct
+ * @m: mux struct
+ */
+bool omap_mux_get_wakeupevent(struct omap_mux *m);
+
/**
* omap_mux_set_gpio() - set mux register value based on GPIO number
* @val: New mux register value
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 6a9bca627d9..561cb4f1f7e 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -1398,6 +1398,8 @@ static int omap_gpio_pm_runtime_resume(struct device *dev)
struct gpio_bank *bank = platform_get_drvdata(pdev);
u32 l = 0, gen, gen0, gen1;
int j;
+ unsigned long pad_wakeup;
+ int i;
for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
clk_enable(bank->dbck);
@@ -1421,6 +1423,11 @@ static int omap_gpio_pm_runtime_resume(struct device *dev)
l ^= bank->saved_datain;
l &= bank->enabled_non_wakeup_gpios;
+ pad_wakeup = bank->enabled_non_wakeup_gpios;
+ for_each_set_bit(i, &pad_wakeup, bank->width)
+ if (omap_mux_get_wakeupevent(bank->mux[i]))
+ l |= BIT(i);
+
/*
* No need to generate IRQs for the rising edge for gpio IRQs
* configured with falling edge only; and vice versa.