diff options
author | Bitan Biswas <bbiswas@nvidia.com> | 2012-05-29 22:19:09 +0530 |
---|---|---|
committer | Rohan Somvanshi <rsomvanshi@nvidia.com> | 2012-07-11 06:07:32 -0700 |
commit | 48651d264bdb2ff90624e965b8a68b011077ca7c (patch) | |
tree | 3b02c2fd3122e6a6b35d0c2049d4b290b37ae2d2 /drivers/gpio | |
parent | 25a4796d13bfd8ae0e7618e573ab0aad6f928a6d (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.c | 51 |
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 |