From 48651d264bdb2ff90624e965b8a68b011077ca7c Mon Sep 17 00:00:00 2001 From: Bitan Biswas Date: Tue, 29 May 2012 22:19:09 +0530 Subject: 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 Reviewed-on: http://git-master/r/103140 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Laxman Dewangan --- drivers/gpio/gpio-tegra.c | 51 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) (limited to 'drivers/gpio') 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 #include +#include #include #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 -- cgit v1.2.3