diff options
| author | Varun Wadekar <vwadekar@nvidia.com> | 2012-07-31 16:27:34 +0530 |
|---|---|---|
| committer | Varun Colbert <vcolbert@nvidia.com> | 2012-08-01 19:10:44 -0700 |
| commit | 02569866aeb63d3404351f90d6ba2d88b3087282 (patch) | |
| tree | 8b040b9fe9c262df8e858e910fd53217db683a7a /drivers/gpio | |
| parent | b34dc18e7d9fb67f11980fe4737ba1abcc3a34be (diff) | |
ARM: tegra: support multiple wake sources with same irq
Partial port of commit 48651d264bdb2ff90624e965b8a68b011077ca7c
(http://git-master/r/103140).
Earlier implementation only allowed single wake source
for a particular irq in wake table. Changed implementation
to support multiple wake sources ==> single irq mapping.
Test: Cardhu boots up fine and can pass 100 suspend-resume
cycles.
Change-Id: I3345181d1e9a084e8b745234c4ffb11df5c68ff3
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-on: http://git-master/r/119641
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@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 8db4ce1215cf..546a510b6ce8 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -35,6 +35,7 @@ #include <mach/gpio-tegra.h> #include <mach/iomap.h> +#include <mach/legacy_irq.h> #include <mach/pinmux.h> #include "../../arch/arm/mach-tegra/pm-irq.h" @@ -79,6 +80,7 @@ struct tegra_gpio_bank { u32 oe[4]; u32 int_enb[4]; u32 int_lvl[4]; + u32 wake_enb[4]; #endif }; @@ -390,26 +392,65 @@ 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->hwirq; + + 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; int wake = tegra_gpio_to_wake(d->hwirq); - ret = tegra_pm_irq_set_wake(wake, 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); + ret = tegra_pm_irq_set_wake(wake, enable); if (ret) - tegra_pm_irq_set_wake(wake, !enable); + pr_err("Failed gpio lp0 %s for irq=%d, error=%d\n", + (enable ? "enable" : "disable"), d->irq, ret); +fail: return ret; } #else #define tegra_gpio_irq_set_wake NULL +#define tegra_update_lp1_gpio_wake NULL #define tegra_gpio_suspend NULL #define tegra_gpio_resume NULL #endif |
