From dbfa483300a34035c9b5de68e67bdad269817144 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Thu, 12 May 2011 14:19:03 +0530 Subject: 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. Change-Id: I918eb31771aa7e1e1a5f25438edded727de6eb8c Signed-off-by: Varun Wadekar Reviewed-on: http://git-master/r/31339 Reviewed-by: Diwakar Tundlam Tested-by: Diwakar Tundlam Reviewed-by: Scott Williams --- arch/arm/mach-tegra/cpu-tegra.c | 45 +++++++++++++++++++++++++++++++--- arch/arm/mach-tegra/include/mach/edp.h | 40 ++++++++++++++++++++++++++++++ arch/arm/mach-tegra/power.h | 12 --------- arch/arm/mach-tegra/tegra3_clocks.c | 1 + 4 files changed, 83 insertions(+), 15 deletions(-) create mode 100644 arch/arm/mach-tegra/include/mach/edp.h diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c index b91a9e48188c..c501af7f897c 100644 --- a/arch/arm/mach-tegra/cpu-tegra.c +++ b/arch/arm/mach-tegra/cpu-tegra.c @@ -39,6 +39,7 @@ #include #include +#include #include "clock.h" #include "power.h" @@ -47,7 +48,6 @@ to be in ascending order */ static struct cpufreq_frequency_table *freq_table; - static struct clk *cpu_clk; static struct clk *emc_clk; @@ -228,6 +228,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) { @@ -249,6 +287,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); } @@ -297,7 +336,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/power.h b/arch/arm/mach-tegra/power.h index 580eb1913335..49b6c61723c7 100644 --- a/arch/arm/mach-tegra/power.h +++ b/arch/arm/mach-tegra/power.h @@ -153,18 +153,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 213381078e65..e45e28cd4a3c 100644 --- a/arch/arm/mach-tegra/tegra3_clocks.c +++ b/arch/arm/mach-tegra/tegra3_clocks.c @@ -33,6 +33,7 @@ #include #include +#include #include "clock.h" #include "fuse.h" -- cgit v1.2.3