summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVarun Wadekar <vwadekar@nvidia.com>2011-05-12 14:19:03 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:42:40 -0800
commit2b2e4c000620fd74a4576e3918c34915863cb35a (patch)
tree797495164023cafbd07f8f45fac92dded855db5a
parent3a5fc7cb03ae52c52837953cf04f8c2b339b8990 (diff)
ARM: Tegra: Support to update edp zones
Tegra cpu-freq driver will now recognize edp zones and cap the max cpu freq for that zone. The temperature monitoring driver will be giving inputs to cpu-freq on the current temperature which would be interpreted by the cpu-freq driver appropriately. Original-Change-Id: I918eb31771aa7e1e1a5f25438edded727de6eb8c Signed-off-by: Varun Wadekar <vwadekar@nvidia.com> Reviewed-on: http://git-master/r/31339 Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com> Tested-by: Diwakar Tundlam <dtundlam@nvidia.com> Reviewed-by: Scott Williams <scwilliams@nvidia.com> Rebase-Id: R6d93bf69d0731ce4ae84f80d1e9013378483331c
-rw-r--r--arch/arm/mach-tegra/cpu-tegra.c45
-rw-r--r--arch/arm/mach-tegra/include/mach/edp.h40
-rw-r--r--arch/arm/mach-tegra/pm.h12
-rw-r--r--arch/arm/mach-tegra/tegra3_clocks.c1
4 files changed, 83 insertions, 15 deletions
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
index 4c15b3af35c5..a59af561f456 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -37,6 +37,7 @@
#include <asm/system.h>
#include <mach/clk.h>
+#include <mach/edp.h>
#include "clock.h"
#include "pm.h"
@@ -45,7 +46,6 @@
to be in ascending order */
static struct cpufreq_frequency_table *freq_table;
-
static struct clk *cpu_clk;
static struct clk *emc_clk;
@@ -226,6 +226,44 @@ static unsigned int edp_governor_speed(unsigned int requested_speed)
return edp_limit;
}
+int tegra_edp_update_thermal_zone(int temperature)
+{
+ int i;
+ int ret = 0;
+ int nlimits = cpu_edp_limits_size;
+ int index;
+
+ if (!cpu_edp_limits)
+ return -EINVAL;
+
+ index = nlimits - 1;
+
+ if (temperature < cpu_edp_limits[0].temperature) {
+ index = 0;
+ } else {
+ for (i = 0; i < (nlimits - 1); i++) {
+ if (temperature >= cpu_edp_limits[i].temperature &&
+ temperature < cpu_edp_limits[i + 1].temperature) {
+ index = i + 1;
+ break;
+ }
+ }
+ }
+
+ mutex_lock(&tegra_cpu_lock);
+
+ edp_thermal_index = index;
+ edp_update_limit();
+ ret = tegra_cpu_cap_highest_speed(NULL);
+ if (ret)
+ pr_err("%s: update cpu speed fail(%d)", __func__, ret);
+
+ mutex_unlock(&tegra_cpu_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tegra_edp_update_thermal_zone);
+
static int tegra_cpu_edp_notify(
struct notifier_block *nb, unsigned long event, void *hcpu)
{
@@ -247,6 +285,7 @@ static int tegra_cpu_edp_notify(
cpu_clear(cpu, edp_cpumask);
edp_update_limit();
}
+
printk(KERN_DEBUG "tegra CPU:%sforce EDP limit %u kHz"
"\n", ret ? " failed to " : " ", new_speed);
}
@@ -295,7 +334,7 @@ static void tegra_cpu_edp_exit(void)
void tegra_init_cpu_edp_limits(const struct tegra_edp_limits *limits, int size)
{
cpu_edp_limits = limits;
- cpu_edp_limits_size = cpu_edp_limits_size;
+ cpu_edp_limits_size = size;
}
#else /* CONFIG_TEGRA_EDP_LIMITS */
@@ -573,7 +612,7 @@ static void __exit tegra_cpufreq_exit(void)
#endif
tegra_cpu_edp_exit();
tegra_auto_hotplug_exit();
- cpufreq_unregister_driver(&tegra_cpufreq_driver);
+ cpufreq_unregister_driver(&tegra_cpufreq_driver);
}
diff --git a/arch/arm/mach-tegra/include/mach/edp.h b/arch/arm/mach-tegra/include/mach/edp.h
new file mode 100644
index 000000000000..8401e20d35b9
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/edp.h
@@ -0,0 +1,40 @@
+/*
+ * arch/arm/mach-tegra/include/mach/edp.h
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MACH_EDP_H
+#define __MACH_EDP_H
+
+struct tegra_edp_limits {
+ int temperature;
+ unsigned int freq_limits[CONFIG_NR_CPUS];
+};
+
+#ifdef CONFIG_TEGRA_EDP_LIMITS
+int tegra_edp_update_thermal_zone(int temperature);
+void tegra_init_cpu_edp_limits(const struct tegra_edp_limits *limits, int size);
+#else
+static inline void tegra_init_cpu_edp_limits(
+ const struct tegra_edp_limits *limits, int size)
+{ }
+static inline int tegra_edp_update_thermal_zone(int temperature)
+{ return -1; }
+#endif
+
+#endif /* __MACH_EDP_H */
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index 55c2cc044466..b079ab30b68f 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -87,18 +87,6 @@ unsigned long tegra_cpu_lowest_speed(void);
unsigned long tegra_cpu_highest_speed(void);
int tegra_cpu_cap_highest_speed(unsigned int *speed_cap);
-struct tegra_edp_limits {
- int temperature;
- unsigned int freq_limits[CONFIG_NR_CPUS];
-};
-#ifdef CONFIG_TEGRA_EDP_LIMITS
-void tegra_init_cpu_edp_limits(const struct tegra_edp_limits *limits, int size);
-#else
-static inline void tegra_init_cpu_edp_limits(
- const struct tegra_edp_limits *limits, int size)
-{ }
-#endif
-
#if defined(CONFIG_TEGRA_AUTO_HOTPLUG) && !defined(CONFIG_ARCH_TEGRA_2x_SOC)
int tegra_auto_hotplug_init(struct mutex *cpu_lock);
void tegra_auto_hotplug_exit(void);
diff --git a/arch/arm/mach-tegra/tegra3_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c
index 22bac57d5f6d..b9d391cf93d4 100644
--- a/arch/arm/mach-tegra/tegra3_clocks.c
+++ b/arch/arm/mach-tegra/tegra3_clocks.c
@@ -32,6 +32,7 @@
#include <asm/clkdev.h>
#include <mach/iomap.h>
+#include <mach/edp.h>
#include "clock.h"
#include "fuse.h"