ARM: Tegra: Support to update edp zones
Varun Wadekar [Thu, 12 May 2011 08:49:03 +0000 (13:49 +0530)]
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

arch/arm/mach-tegra/cpu-tegra.c
arch/arm/mach-tegra/include/mach/edp.h [new file with mode: 0644]
arch/arm/mach-tegra/pm.h

index 8670140..2812a92 100644 (file)
@@ -34,6 +34,8 @@
 #include <linux/debugfs.h>
 #include <linux/cpu.h>
 
+#include <mach/edp.h>
+
 #include "clock.h"
 #include "pm.h"
 
@@ -41,7 +43,6 @@
    to be in ascending order */
 static struct cpufreq_frequency_table *freq_table;
 
-
 static struct clk *cpu_clk;
 static struct clk *emc_clk;
 
@@ -222,6 +223,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)
 {
@@ -243,6 +282,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);
                }
@@ -291,7 +331,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 */
@@ -568,7 +608,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 (file)
index 0000000..8401e20
--- /dev/null
@@ -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 */
index 8e898a5..dfa0bbb 100644 (file)
@@ -80,18 +80,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);