summaryrefslogtreecommitdiff
path: root/drivers/gpio
diff options
context:
space:
mode:
authorBitan Biswas <bbiswas@nvidia.com>2012-05-29 22:19:09 +0530
committerRohan Somvanshi <rsomvanshi@nvidia.com>2012-07-11 06:07:32 -0700
commit48651d264bdb2ff90624e965b8a68b011077ca7c (patch)
tree3b02c2fd3122e6a6b35d0c2049d4b290b37ae2d2 /drivers/gpio
parent25a4796d13bfd8ae0e7618e573ab0aad6f928a6d (diff)
ARM: tegra: support multiple wake sources with same irq
Earlier implementation only allowed single wake source for a particular irq in wake table. Changed implementation to support multiple wake sources ==> single irq mapping. bug 980993 Change-Id: Iacb00487531129ef19c53128824aba802e80350e Signed-off-by: Bitan Biswas <bbiswas@nvidia.com> Reviewed-on: http://git-master/r/103140 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-tegra.c51
1 files changed, 46 insertions, 5 deletions
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 17e9c1cfdf4e..49abdf016b26 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -32,6 +32,7 @@
#include <asm/mach/irq.h>
#include <mach/iomap.h>
+#include <mach/legacy_irq.h>
#include <mach/pinmux.h>
#include "../../../arch/arm/mach-tegra/pm-irq.h"
@@ -90,6 +91,7 @@ struct tegra_gpio_bank {
u32 oe[4];
u32 int_enb[4];
u32 int_lvl[4];
+ u32 wake_enb[4];
#endif
};
@@ -395,21 +397,60 @@ static int tegra_gpio_suspend(void)
return 0;
}
+static int tegra_update_lp1_gpio_wake(struct irq_data *d, bool enable)
+{
+#ifdef CONFIG_PM_SLEEP
+ struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+ u8 mask;
+ u8 port_index;
+ u8 pin_index_in_bank;
+ u8 pin_in_port;
+ int gpio = d->irq - INT_GPIO_BASE;
+
+ if (gpio < 0)
+ return -EIO;
+ pin_index_in_bank = (gpio & 0x1F);
+ port_index = pin_index_in_bank >> 3;
+ pin_in_port = (pin_index_in_bank & 0x7);
+ mask = BIT(pin_in_port);
+ if (enable)
+ bank->wake_enb[port_index] |= mask;
+ else
+ bank->wake_enb[port_index] &= ~mask;
+#endif
+
+ return 0;
+}
+
static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable)
{
struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
int ret = 0;
- ret = tegra_pm_irq_set_wake(d->irq, enable);
+ /*
+ * update LP1 mask for gpio port/pin interrupt
+ * LP1 enable independent of LP0 wake support
+ */
+ ret = tegra_update_lp1_gpio_wake(d, enable);
+ if (ret) {
+ pr_err("Failed gpio lp1 %s for irq=%d, error=%d\n",
+ (enable ? "enable" : "disable"), d->irq, ret);
+ goto fail;
+ }
+ /* LP1 enable for bank interrupt */
+ ret = tegra_update_lp1_irq_wake(bank->irq, enable);
if (ret)
- return ret;
-
- ret = irq_set_irq_wake(bank->irq, enable);
+ pr_err("Failed gpio lp1 %s for irq=%d, error=%d\n",
+ (enable ? "enable" : "disable"), bank->irq, ret);
+ /* LP0 */
+ ret = tegra_pm_irq_set_wake(d->irq, enable);
if (ret)
- tegra_pm_irq_set_wake(d->irq, !enable);
+ pr_err("Failed gpio lp0 %s for irq=%d, error=%d\n",
+ (enable ? "enable" : "disable"), d->irq, ret);
+fail:
return ret;
}
#else