diff options
author | Bitan Biswas <bbiswas@nvidia.com> | 2013-05-19 03:14:41 +0530 |
---|---|---|
committer | Riham Haidar <rhaidar@nvidia.com> | 2013-06-11 11:17:12 -0700 |
commit | b96d7c7db56bb49cd4f81190e25cf55b58794ab7 (patch) | |
tree | 27dc5680b51e542032e29bc2e877b9a19583cbc4 | |
parent | e08e02857171adc7579c958962a33a97de0ec6e8 (diff) |
ARM: tegra: allow 1-to-many irq to wake mapping
Problem:
Current Tegra wake table does not allow same USB irq to be used
for multiple wake sources.
Fix:
Changed tegra_irq_to_wake API to return multiple wake table indices
bug 1275273
Change-Id: I72e6d83cb71de76e23ea9623b6fcae34091171bb
Signed-off-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-on: http://git-master/r/231921
Reviewed-by: Riham Haidar <rhaidar@nvidia.com>
Tested-by: Riham Haidar <rhaidar@nvidia.com>
-rw-r--r-- | arch/arm/mach-tegra/irq.c | 62 | ||||
-rw-r--r-- | arch/arm/mach-tegra/pm-irq.h | 10 | ||||
-rw-r--r-- | arch/arm/mach-tegra/wakeups-t11x.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-tegra/wakeups-t2.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-tegra/wakeups-t3.c | 15 |
5 files changed, 79 insertions, 38 deletions
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c index 2c28a01f983f..47d2d004c946 100644 --- a/arch/arm/mach-tegra/irq.c +++ b/arch/arm/mach-tegra/irq.c @@ -4,17 +4,19 @@ * Author: * Colin Cross <ccross@android.com> * - * Copyright (C) 2010-2012, NVIDIA Corporation + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <linux/kernel.h> @@ -157,9 +159,24 @@ static int tegra_retrigger(struct irq_data *d) static int tegra_set_type(struct irq_data *d, unsigned int flow_type) { - int wake = tegra_irq_to_wake(d->irq); + int wake_size; + int wake_list[PMC_MAX_WAKE_COUNT]; + int i; + int err = 0; + int ret; + + tegra_irq_to_wake(d->irq, wake_list, &wake_size); - return tegra_pm_irq_set_wake_type(wake, flow_type); + for (i = 0; i < wake_size; i++) { + ret = tegra_pm_irq_set_wake_type(wake_list[i], flow_type); + if (ret < 0) { + pr_err("Set lp0 wake type=%d fail for irq=%d, wake%d ret=%d\n", + flow_type, d->irq, wake_list[i], ret); + if (!err) + err = ret; + } + } + return err; } @@ -170,14 +187,25 @@ static int tegra_set_type(struct irq_data *d, unsigned int flow_type) */ static int tegra_set_wake(struct irq_data *d, unsigned int enable) { - int wake = tegra_irq_to_wake(d->irq); int ret; - - /* pmc lp0 wake enable for non-gpio wake sources */ - ret = tegra_pm_irq_set_wake(wake, enable); - if (ret) - pr_err("Failed lp0 wake %s for irq=%d\n", - (enable ? "enable" : "disable"), d->irq); + int wake_size; + int wake_list[PMC_MAX_WAKE_COUNT]; + int i; + int err = 0; + + tegra_irq_to_wake(d->irq, wake_list, &wake_size); + + for (i = 0; i < wake_size; i++) { + /* pmc lp0 wake enable for non-gpio wake sources */ + ret = tegra_pm_irq_set_wake(wake_list[i], enable); + if (ret < 0) { + pr_err("Failed lp0 wake %s for irq=%d, wake%d ret=%d\n", + (enable ? "enable" : "disable"), d->irq, + wake_list[i], ret); + if (!err) + err = ret; + } + } /* lp1 wake enable for wake sources */ ret = tegra_update_lp1_irq_wake(d->irq, enable); diff --git a/arch/arm/mach-tegra/pm-irq.h b/arch/arm/mach-tegra/pm-irq.h index cbb7450ec2f2..61af6d7bfe26 100644 --- a/arch/arm/mach-tegra/pm-irq.h +++ b/arch/arm/mach-tegra/pm-irq.h @@ -22,13 +22,15 @@ #ifndef _MACH_TERA_PM_IRQ_H_ #define _MACH_TERA_PM_IRQ_H_ +#define PMC_MAX_WAKE_COUNT 64 + #ifdef CONFIG_PM_SLEEP u64 tegra_read_pmc_wake_status(void); int tegra_pm_irq_set_wake(int wake, int enable); int tegra_pm_irq_set_wake_type(int wake, int flow_type); bool tegra_pm_irq_lp0_allowed(void); int tegra_gpio_to_wake(int gpio); -int tegra_irq_to_wake(int irq); +void tegra_irq_to_wake(int irq, int *wak_list, int *wak_size); int tegra_wake_to_irq(int wake); int tegra_disable_wake_source(int wake); #else @@ -40,9 +42,11 @@ static inline int tegra_gpio_to_wake(int gpio) { return 0; } -static inline int tegra_irq_to_wake(int irq) +static inline +void tegra_irq_to_wake(int irq, int *wak_list, int *wak_size) { - return 0; + *wak_size = 0; + return; } static inline int tegra_disable_wake_source(int wake) { diff --git a/arch/arm/mach-tegra/wakeups-t11x.c b/arch/arm/mach-tegra/wakeups-t11x.c index 43a0bdf150ab..7a1834f63245 100644 --- a/arch/arm/mach-tegra/wakeups-t11x.c +++ b/arch/arm/mach-tegra/wakeups-t11x.c @@ -233,18 +233,20 @@ void tegra_set_usb_wake_source(void) } } -int tegra_irq_to_wake(int irq) +void tegra_irq_to_wake(int irq, int *wak_list, int *wak_size) { int i; - int ret = -EINVAL; + *wak_size = 0; for (i = 0; i < ARRAY_SIZE(tegra_wake_event_irq); i++) { if (tegra_wake_event_irq[i] == irq) { pr_info("Wake%d for irq=%d\n", i, irq); - ret = i; - goto out; + wak_list[*wak_size] = i; + *wak_size = *wak_size + 1; } } + if (*wak_size) + goto out; /* The gpio set_wake code bubbles the set_wake call up to the irq * set_wake code. This insures that the nested irq set_wake call @@ -259,11 +261,12 @@ int tegra_irq_to_wake(int irq) if (tegra_gpio_get_bank_int_nr(tegra_gpio_wakes[last_gpio]) == irq) { pr_info("gpio bank wake found: wake%d for irq=%d\n", i, irq); - ret = last_gpio; + wak_list[*wak_size] = last_gpio; + *wak_size = 1; } out: - return ret; + return; } int tegra_wake_to_irq(int wake) diff --git a/arch/arm/mach-tegra/wakeups-t2.c b/arch/arm/mach-tegra/wakeups-t2.c index df7f65cfef49..a068fc9d36b0 100644 --- a/arch/arm/mach-tegra/wakeups-t2.c +++ b/arch/arm/mach-tegra/wakeups-t2.c @@ -127,18 +127,20 @@ int tegra_gpio_to_wake(int gpio) return -EINVAL; } -int tegra_irq_to_wake(int irq) +void tegra_irq_to_wake(int irq, int *wak_list, int *wak_size) { int i; - int ret = -EINVAL; + *wak_size = 0; for (i = 0; i < ARRAY_SIZE(tegra_wake_event_irq); i++) { if (tegra_wake_event_irq[i] == irq) { pr_info("Wake %d for irq=%d\n", i, irq); - ret = i; - goto out; + wak_list[*wak_size] = i; + *wak_size = *wak_size + 1; } } + if (*wak_size) + goto out; /* The gpio set_wake code bubbles the set_wake call up to the irq * set_wake code. This insures that the nested irq set_wake call @@ -153,11 +155,12 @@ int tegra_irq_to_wake(int irq) if (tegra_gpio_get_bank_int_nr(tegra_gpio_wakes[last_gpio]) == irq) { pr_info("gpio bank wake found: wake %d for irq=%d\n", i, irq); - ret = last_gpio; + wak_list[*wak_size] = last_gpio; + *wak_size = 1; } out: - return ret; + return; } int tegra_wake_to_irq(int wake) diff --git a/arch/arm/mach-tegra/wakeups-t3.c b/arch/arm/mach-tegra/wakeups-t3.c index 3f3e0ae88e7e..2775a4eae145 100644 --- a/arch/arm/mach-tegra/wakeups-t3.c +++ b/arch/arm/mach-tegra/wakeups-t3.c @@ -146,18 +146,20 @@ int tegra_gpio_to_wake(int gpio) return -EINVAL; } -int tegra_irq_to_wake(int irq) +void tegra_irq_to_wake(int irq, int *wak_list, int *wak_size) { int i; - int ret = -EINVAL; + *wak_size = 0; for (i = 0; i < ARRAY_SIZE(tegra_wake_event_irq); i++) { if (tegra_wake_event_irq[i] == irq) { pr_info("Wake%d for irq=%d\n", i, irq); - ret = i; - goto out; + wak_list[*wak_size] = i; + *wak_size = *wak_size + 1; } } + if (*wak_size) + goto out; /* The gpio set_wake code bubbles the set_wake call up to the irq * set_wake code. This insures that the nested irq set_wake call @@ -172,11 +174,12 @@ int tegra_irq_to_wake(int irq) if (tegra_gpio_get_bank_int_nr(tegra_gpio_wakes[last_gpio]) == irq) { pr_info("gpio bank wake found: wake%d for irq=%d\n", i, irq); - ret = last_gpio; + wak_list[*wak_size] = last_gpio; + *wak_size = 1; } out: - return ret; + return; } int tegra_wake_to_irq(int wake) |