summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBitan Biswas <bbiswas@nvidia.com>2013-05-19 03:14:41 +0530
committerRiham Haidar <rhaidar@nvidia.com>2013-06-11 11:17:12 -0700
commitb96d7c7db56bb49cd4f81190e25cf55b58794ab7 (patch)
tree27dc5680b51e542032e29bc2e877b9a19583cbc4
parente08e02857171adc7579c958962a33a97de0ec6e8 (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.c62
-rw-r--r--arch/arm/mach-tegra/pm-irq.h10
-rw-r--r--arch/arm/mach-tegra/wakeups-t11x.c15
-rw-r--r--arch/arm/mach-tegra/wakeups-t2.c15
-rw-r--r--arch/arm/mach-tegra/wakeups-t3.c15
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)