diff options
author | Joshua Primero <jprimero@nvidia.com> | 2011-10-03 17:34:55 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:50:01 -0800 |
commit | 7285d4751fa2048bbe5e4981ac1afda09770ec89 (patch) | |
tree | 06373d2acd753f229bb79f9f141de9ec5776e017 /arch/arm/mach-tegra/tegra3_throttle.c | |
parent | f5881ad6ca97f9c7a6a9a78cb90380dfce1a8ff3 (diff) |
arm: tegra: power: Add throttle as a cooling dev
Added cooling device hooks into the throttling module
to be used with the linux thermal sysfs infrastructure.
Reviewed-on: http://git-master/r/59470
(cherry picked from commit a7d0c2d23ae32cd074dc667f1ace6083273b1870)
Change-Id: I8ca4d94d838a00ea7c10423ab120329bf1b2343f
Reviewed-on: http://git-master/r/62573
Reviewed-by: Joshua Primero <jprimero@nvidia.com>
Tested-by: Joshua Primero <jprimero@nvidia.com>
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
Rebase-Id: R1bb4b36226f8a7c13166162feabeced9a1d469ee
Diffstat (limited to 'arch/arm/mach-tegra/tegra3_throttle.c')
-rw-r--r-- | arch/arm/mach-tegra/tegra3_throttle.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/tegra3_throttle.c b/arch/arm/mach-tegra/tegra3_throttle.c index 4be94a86450d..6f4a3bc1a28d 100644 --- a/arch/arm/mach-tegra/tegra3_throttle.c +++ b/arch/arm/mach-tegra/tegra3_throttle.c @@ -26,6 +26,7 @@ #include <linux/debugfs.h> #include <linux/seq_file.h> #include <linux/uaccess.h> +#include <linux/thermal.h> #include "clock.h" #include "cpu-tegra.h" @@ -53,6 +54,9 @@ static int throttle_index; static struct delayed_work throttle_work; static struct workqueue_struct *workqueue; static DEFINE_MUTEX(tegra_throttle_lock); +#ifdef CONFIG_TEGRA_THERMAL_SYSFS +static struct thermal_cooling_device *cdev; +#endif static unsigned int clip_to_table(unsigned int cpu_freq) { @@ -153,6 +157,69 @@ bool tegra_is_throttling(void) return is_throttling; } +#ifdef CONFIG_TEGRA_THERMAL_SYSFS + +static int +tegra_throttle_get_max_state(struct thermal_cooling_device *cdev, + unsigned long *max_state) +{ + *max_state = ARRAY_SIZE(throttle_table); + return 0; +} + +static int +tegra_throttle_get_cur_state(struct thermal_cooling_device *cdev, + unsigned long *cur_state) +{ + mutex_lock(cpu_throttle_lock); + *cur_state = is_throttling ? + (ARRAY_SIZE(throttle_table) - throttle_index) : + 0; + mutex_unlock(cpu_throttle_lock); + + return 0; +} + +static int +tegra_throttle_set_cur_state(struct thermal_cooling_device *cdev, + unsigned long cur_state) +{ + int core_level; + + mutex_lock(cpu_throttle_lock); + if (cur_state == 0) { + /* restore speed requested by governor */ + if (is_throttling) { + tegra_dvfs_core_cap_enable(false); + is_throttling = false; + } + + tegra_cpu_set_speed_cap(NULL); + } else { + if (!is_throttling) { + tegra_dvfs_core_cap_enable(true); + is_throttling = true; + } + + throttle_index = ARRAY_SIZE(throttle_table) - cur_state; + core_level = throttle_table[throttle_index].core_cap_level; + tegra_dvfs_core_cap_level_set(core_level); + + tegra_cpu_set_speed_cap(NULL); + } + + mutex_unlock(cpu_throttle_lock); + + return 0; +} + +struct thermal_cooling_device_ops tegra_throttle_cooling_ops = { + .get_max_state = tegra_throttle_get_max_state, + .get_cur_state = tegra_throttle_get_cur_state, + .set_cur_state = tegra_throttle_set_cur_state, +}; +#endif + int __init tegra_throttle_init(struct mutex *cpu_lock) { int i; @@ -182,11 +249,27 @@ int __init tegra_throttle_init(struct mutex *cpu_lock) throttle_table[i].cpu_freq = clip_to_table(cpu_freq); } +#ifdef CONFIG_TEGRA_THERMAL_SYSFS + cdev = thermal_cooling_device_register("Throttle", NULL, + &tegra_throttle_cooling_ops); + + if (IS_ERR(cdev)) { + cdev = NULL; + return -ENODEV; + } +#endif + return 0; } void tegra_throttle_exit(void) { +#ifdef CONFIG_TEGRA_THERMAL_SYSFS + if (cdev) { + thermal_cooling_device_unregister(cdev); + cdev = NULL; + } +#endif destroy_workqueue(workqueue); } |